emacs-elpa-diffs
[Top][All Lists]
Advanced

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

[elpa] externals-release/org 7d223a8 6/9: Merge branch 'main' into bugfi


From: ELPA Syncer
Subject: [elpa] externals-release/org 7d223a8 6/9: Merge branch 'main' into bugfix
Date: Wed, 29 Sep 2021 08:58:02 -0400 (EDT)

branch: externals-release/org
commit 7d223a84644096d8e1d1c6bf54ec8a38eb4c4bb4
Merge: 0f6e0e8 0a86adc
Author: Bastien <bzg@gnu.org>
Commit: Bastien <bzg@gnu.org>

    Merge branch 'main' into bugfix
---
 .gitignore                                         |     6 +
 CONTRIBUTE                                         |    29 +-
 COPYING                                            |     8 +-
 README                                             |    44 +-
 README_ELPA                                        |     5 +-
 contrib/README                                     |   100 -
 contrib/lisp/ob-arduino.el                         |   105 -
 contrib/lisp/ob-clojure-literate.el                |   294 -
 contrib/lisp/ob-csharp.el                          |    83 -
 contrib/lisp/ob-eukleides.el                       |    98 -
 contrib/lisp/ob-fomus.el                           |    92 -
 contrib/lisp/ob-mathematica.el                     |    81 -
 contrib/lisp/ob-mathomatic.el                      |   145 -
 contrib/lisp/ob-oz.el                              |   294 -
 contrib/lisp/ob-php.el                             |    57 -
 contrib/lisp/ob-redis.el                           |    44 -
 contrib/lisp/ob-sclang.el                          |    92 -
 contrib/lisp/ob-smiles.el                          |    57 -
 contrib/lisp/ob-spice.el                           |   182 -
 contrib/lisp/ob-stata.el                           |   312 -
 contrib/lisp/ob-tcl.el                             |   128 -
 contrib/lisp/ob-vbnet.el                           |    84 -
 contrib/lisp/ol-bookmark.el                        |    90 -
 contrib/lisp/ol-elisp-symbol.el                    |   157 -
 contrib/lisp/ol-git-link.el                        |   231 -
 contrib/lisp/ol-man.el                             |    85 -
 contrib/lisp/ol-mew.el                             |   355 -
 contrib/lisp/ol-notmuch.el                         |   154 -
 contrib/lisp/ol-vm.el                              |   167 -
 contrib/lisp/ol-wl.el                              |   304 -
 contrib/lisp/org-annotate-file.el                  |   157 -
 contrib/lisp/org-attach-embedded-images.el         |   131 -
 contrib/lisp/org-bibtex-extras.el                  |   137 -
 contrib/lisp/org-checklist.el                      |   141 -
 contrib/lisp/org-choose.el                         |   496 -
 contrib/lisp/org-collector.el                      |   232 -
 contrib/lisp/org-contacts.el                       |  1151 --
 contrib/lisp/org-contribdir.el                     |    38 -
 contrib/lisp/org-depend.el                         |   431 -
 contrib/lisp/org-effectiveness.el                  |   369 -
 contrib/lisp/org-eldoc.el                          |   203 -
 contrib/lisp/org-eval-light.el                     |   199 -
 contrib/lisp/org-eval.el                           |   216 -
 contrib/lisp/org-expiry.el                         |   361 -
 contrib/lisp/org-interactive-query.el              |   311 -
 contrib/lisp/org-invoice.el                        |   403 -
 contrib/lisp/org-learn.el                          |   177 -
 contrib/lisp/org-license.el                        |   540 -
 contrib/lisp/org-link-edit.el                      |   392 -
 contrib/lisp/org-mac-iCal.el                       |   250 -
 contrib/lisp/org-mac-link.el                       |  1015 --
 contrib/lisp/org-mairix.el                         |   333 -
 contrib/lisp/org-notify.el                         |   406 -
 contrib/lisp/org-panel.el                          |   638 -
 contrib/lisp/org-passwords.el                      |   384 -
 contrib/lisp/org-registry.el                       |   272 -
 contrib/lisp/org-screen.el                         |   106 -
 contrib/lisp/org-screenshot.el                     |   529 -
 contrib/lisp/org-secretary.el                      |   230 -
 contrib/lisp/org-static-mathjax.el                 |   187 -
 contrib/lisp/org-sudoku.el                         |   288 -
 contrib/lisp/org-toc.el                            |   508 -
 contrib/lisp/org-track.el                          |   211 -
 contrib/lisp/org-velocity.el                       |   819 --
 contrib/lisp/org-wikinodes.el                      |   327 -
 contrib/lisp/orgtbl-sqlinsert.el                   |   118 -
 contrib/lisp/ox-bibtex.el                          |   430 -
 contrib/lisp/ox-confluence.el                      |   258 -
 contrib/lisp/ox-deck.el                            |   585 -
 contrib/lisp/ox-extra.el                           |   211 -
 contrib/lisp/ox-freemind.el                        |   527 -
 contrib/lisp/ox-groff.el                           |  1960 ----
 contrib/lisp/ox-rss.el                             |   419 -
 contrib/lisp/ox-s5.el                              |   433 -
 contrib/lisp/ox-taskjuggler.el                     |  1034 --
 contrib/scripts/.gitignore                         |     1 -
 contrib/scripts/StartOzServer.oz                   |   231 -
 contrib/scripts/dir2org.zsh                        |    56 -
 contrib/scripts/ditaa.jar                          |   Bin 186095 -> 0 bytes
 contrib/scripts/docco.css                          |   185 -
 contrib/scripts/org-docco.org                      |   206 -
 contrib/scripts/org2hpda                           |   106 -
 contrib/scripts/staticmathjax/.gitignore           |     1 -
 contrib/scripts/staticmathjax/README.org           |    79 -
 contrib/scripts/staticmathjax/application.ini      |    11 -
 .../scripts/staticmathjax/chrome/chrome.manifest   |     1 -
 .../scripts/staticmathjax/chrome/content/main.js   |   198 -
 .../scripts/staticmathjax/chrome/content/main.xul  |    11 -
 .../staticmathjax/defaults/preferences/prefs.js    |     1 -
 contrib/scripts/x11idle.c                          |    28 -
 doc/Makefile                                       |    15 +-
 doc/fdl.org                                        |     4 +-
 doc/htmlxref.cnf                                   |     4 +-
 doc/org-guide.org                                  |    11 +-
 doc/org-manual.org                                 |   867 +-
 doc/orgcard.tex                                    |     2 +-
 doc/pdflayout.sty                                  |     2 +-
 doc/texinfo.tex                                    |    12 +-
 etc/Makefile                                       |     2 +-
 etc/ORG-NEWS                                       |   622 +-
 etc/csl/chicago-author-date.csl                    |   644 +
 etc/csl/locales-en-US.xml                          |   348 +
 .../OpenDocument-schema-v1.3+libreoffice.rnc       |   892 ++
 ...ma-v1.2-os.rnc => OpenDocument-schema-v1.3.rnc} | 11694 ++++++++++---------
 etc/schema/schemas.xml                             |     7 +-
 lisp/ob-C.el                                       |    53 +-
 lisp/ob-J.el                                       |   189 -
 lisp/ob-R.el                                       |   124 +-
 lisp/ob-abc.el                                     |    90 -
 lisp/ob-asymptote.el                               |   137 -
 lisp/ob-awk.el                                     |    13 +-
 lisp/ob-calc.el                                    |     3 +-
 lisp/ob-clojure.el                                 |     3 +-
 lisp/ob-comint.el                                  |   180 +-
 lisp/ob-coq.el                                     |    80 -
 lisp/ob-core.el                                    |   179 +-
 lisp/ob-dot.el                                     |     3 +-
 lisp/ob-ebnf.el                                    |    81 -
 lisp/ob-eshell.el                                  |     3 +-
 lisp/ob-eval.el                                    |    87 +-
 lisp/ob-exp.el                                     |    16 +-
 lisp/ob-forth.el                                   |     4 +-
 lisp/ob-fortran.el                                 |    10 +-
 lisp/ob-gnuplot.el                                 |    24 +-
 lisp/ob-groovy.el                                  |     3 +-
 lisp/ob-haskell.el                                 |    11 +-
 lisp/ob-hledger.el                                 |    69 -
 lisp/ob-io.el                                      |   105 -
 lisp/ob-java.el                                    |   480 +-
 lisp/ob-js.el                                      |     4 +-
 {contrib/lisp => lisp}/ob-julia.el                 |   209 +-
 lisp/ob-latex.el                                   |    63 +-
 lisp/ob-ledger.el                                  |    68 -
 lisp/ob-lilypond.el                                |    28 +-
 lisp/ob-lisp.el                                    |     2 +-
 lisp/ob-lua.el                                     |     6 +-
 lisp/ob-makefile.el                                |     3 +-
 lisp/ob-mscgen.el                                  |    81 -
 lisp/ob-ocaml.el                                   |     4 +-
 lisp/ob-octave.el                                  |    18 +-
 lisp/ob-perl.el                                    |     1 +
 lisp/ob-picolisp.el                                |   185 -
 lisp/ob-plantuml.el                                |    15 +-
 lisp/ob-processing.el                              |     2 +-
 lisp/ob-python.el                                  |    69 +-
 lisp/ob-ruby.el                                    |     2 +-
 lisp/ob-sass.el                                    |     2 +-
 lisp/ob-scheme.el                                  |     2 +-
 lisp/ob-screen.el                                  |     3 +-
 lisp/ob-sed.el                                     |    12 +-
 lisp/ob-shen.el                                    |    79 -
 lisp/ob-sql.el                                     |    76 +-
 lisp/ob-sqlite.el                                  |    24 +-
 lisp/ob-stan.el                                    |    86 -
 lisp/ob-table.el                                   |     3 +-
 lisp/ob-tangle.el                                  |   180 +-
 lisp/ob-vala.el                                    |   116 -
 lisp/oc-basic.el                                   |   770 ++
 lisp/oc-biblatex.el                                |   319 +
 lisp/oc-csl.el                                     |   612 +
 lisp/oc-natbib.el                                  |   196 +
 lisp/oc.el                                         |  1608 +++
 lisp/ol-bbdb.el                                    |     6 +-
 lisp/ol-bibtex.el                                  |    35 +-
 lisp/ol-doi.el                                     |    70 +
 lisp/ol-eshell.el                                  |    10 +-
 lisp/ol-gnus.el                                    |     8 +-
 lisp/ol-info.el                                    |     4 +-
 lisp/ol-rmail.el                                   |     2 +-
 lisp/ol-w3m.el                                     |   111 +-
 lisp/ol.el                                         |    95 +-
 lisp/org-agenda.el                                 |  1108 +-
 lisp/org-archive.el                                |     2 +-
 lisp/org-attach-git.el                             |    33 +-
 lisp/org-attach.el                                 |    95 +-
 lisp/org-capture.el                                |   294 +-
 lisp/org-clock.el                                  |   187 +-
 lisp/org-colview.el                                |    75 +-
 lisp/org-compat.el                                 |   344 +-
 lisp/org-crypt.el                                  |    10 +-
 lisp/org-ctags.el                                  |    12 +-
 lisp/org-datetree.el                               |     6 +-
 lisp/org-element.el                                |   228 +-
 lisp/org-entities.el                               |     4 +-
 lisp/org-faces.el                                  |    74 +-
 lisp/org-feed.el                                   |     2 +-
 lisp/org-footnote.el                               |     5 +-
 lisp/org-goto.el                                   |    10 +-
 lisp/org-habit.el                                  |     2 +-
 lisp/org-id.el                                     |   174 +-
 lisp/org-indent.el                                 |    59 +-
 lisp/org-inlinetask.el                             |     8 +-
 lisp/org-keys.el                                   |    88 +-
 lisp/org-lint.el                                   |    94 +-
 lisp/org-list.el                                   |   332 +-
 lisp/org-macro.el                                  |   131 +-
 lisp/org-macs.el                                   |   118 +-
 lisp/org-mobile.el                                 |     2 +-
 lisp/org-mouse.el                                  |   214 +-
 lisp/org-num.el                                    |     7 +-
 lisp/org-pcomplete.el                              |    18 +-
 lisp/org-plot.el                                   |   624 +-
 lisp/org-protocol.el                               |    73 +-
 lisp/org-refile.el                                 |    23 +-
 lisp/org-src.el                                    |    60 +-
 lisp/org-table.el                                  |   265 +-
 lisp/org-tempo.el                                  |     2 +-
 lisp/org-timer.el                                  |    25 +-
 lisp/org.el                                        |  1069 +-
 lisp/ox-ascii.el                                   |    63 +-
 lisp/ox-beamer.el                                  |    73 +-
 lisp/ox-html.el                                    |   363 +-
 lisp/ox-icalendar.el                               |    10 +-
 {contrib/lisp => lisp}/ox-koma-letter.el           |    13 +-
 lisp/ox-latex.el                                   |   176 +-
 lisp/ox-man.el                                     |    34 +-
 lisp/ox-md.el                                      |    53 +-
 lisp/ox-odt.el                                     |    91 +-
 lisp/ox-org.el                                     |    19 +-
 lisp/ox-publish.el                                 |    60 +-
 lisp/ox-texinfo.el                                 |    31 +-
 lisp/ox.el                                         |   465 +-
 mk/default.mk                                      |     6 +-
 mk/guidesplit.pl                                   |     4 +-
 mk/mansplit.pl                                     |     4 +-
 mk/orgcard2txt.pl                                  |     2 +-
 mk/server.mk                                       |   134 -
 mk/targets.mk                                      |    24 +-
 testing/lisp/test-ob-C.el                          |     2 +-
 testing/lisp/test-ob-R.el                          |   151 +-
 testing/lisp/test-ob-awk.el                        |     2 +-
 testing/lisp/test-ob-clojure.el                    |     2 +-
 testing/lisp/test-ob-emacs-lisp.el                 |     2 +-
 testing/lisp/test-ob-eshell.el                     |     2 +-
 testing/lisp/test-ob-exp.el                        |     2 +-
 testing/lisp/test-ob-fortran.el                    |     2 +-
 testing/lisp/test-ob-header-arg-defaults.el        |     2 +-
 testing/lisp/test-ob-java.el                       |   616 +
 testing/lisp/test-ob-julia.el                      |   274 +
 testing/lisp/test-ob-lilypond.el                   |     2 +-
 testing/lisp/test-ob-lob.el                        |     2 +-
 testing/lisp/test-ob-lua.el                        |     2 +-
 testing/lisp/test-ob-maxima.el                     |     2 +-
 testing/lisp/test-ob-octave.el                     |     2 +-
 testing/lisp/test-ob-perl.el                       |     2 +-
 testing/lisp/test-ob-plantuml.el                   |     2 +-
 testing/lisp/test-ob-python.el                     |    63 +-
 testing/lisp/test-ob-ruby.el                       |     2 +-
 testing/lisp/test-ob-scheme.el                     |     2 +-
 testing/lisp/test-ob-sed.el                        |     2 +-
 testing/lisp/test-ob-shell.el                      |     2 +-
 testing/lisp/test-ob-sql.el                        |   380 +
 testing/lisp/test-ob-sqlite.el                     |     3 +-
 testing/lisp/test-ob-table.el                      |     2 +-
 testing/lisp/test-ob-tangle.el                     |     4 +-
 testing/lisp/test-ob-vala.el                       |   104 -
 testing/lisp/test-ob.el                            |    38 +-
 testing/lisp/test-oc.el                            |  1812 +++
 testing/lisp/test-ol-bbdb.el                       |     2 +-
 testing/lisp/test-org-agenda.el                    |    72 +-
 testing/lisp/test-org-archive.el                   |     2 +-
 testing/lisp/test-org-attach-git.el                |     2 +-
 testing/lisp/test-org-attach.el                    |     4 +-
 testing/lisp/test-org-capture.el                   |     2 +-
 testing/lisp/test-org-clock.el                     |     2 +-
 testing/lisp/test-org-colview.el                   |     2 +-
 testing/lisp/test-org-datetree.el                  |     2 +-
 testing/lisp/test-org-duration.el                  |     2 +-
 testing/lisp/test-org-element.el                   |   186 +-
 testing/lisp/test-org-feed.el                      |     2 +-
 testing/lisp/test-org-footnote.el                  |    10 +-
 testing/lisp/test-org-info.el                      |     2 +-
 testing/lisp/test-org-inlinetask.el                |     2 +-
 testing/lisp/test-org-lint.el                      |     8 +-
 testing/lisp/test-org-list.el                      |     2 +-
 testing/lisp/test-org-macro.el                     |     2 +-
 testing/lisp/test-org-macs.el                      |     2 +-
 testing/lisp/test-org-pcomplete.el                 |     2 +-
 testing/lisp/test-org-protocol.el                  |    42 +-
 testing/lisp/test-org-src.el                       |     4 +-
 testing/lisp/test-org-table.el                     |    14 +-
 testing/lisp/test-org-tempo.el                     |     2 +-
 testing/lisp/test-org-timer.el                     |     2 +-
 testing/lisp/test-org.el                           |   246 +-
 testing/lisp/test-ox-publish.el                    |    38 +-
 testing/lisp/test-ox.el                            |    13 +-
 testing/lisp/test-property-inheritance.el          |     2 +-
 testing/org-batch-test-init.el                     |     6 +-
 testing/org-test.el                                |    17 +-
 289 files changed, 22584 insertions(+), 34922 deletions(-)

diff --git a/.gitignore b/.gitignore
index 1a72cc2..4bb81c3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -49,6 +49,12 @@ local*.mk
 mk/x11idle
 ChangeLog
 
+# Files generated during `make packages/org` in a clone of `elpa.git`.
+
+/org-pkg.el
+/org-autoloads.el
+/lisp/org-autoloads.el
+
 # texi2pdf --tidy
 
 doc/*.t2d
diff --git a/CONTRIBUTE b/CONTRIBUTE
index fcbf3c0..94d471a 100644
--- a/CONTRIBUTE
+++ b/CONTRIBUTE
@@ -3,6 +3,10 @@
 The text below explains the rules for participating in Org mode
 development.
 
+* Org maintenance
+
+Org maintenance is detailed on Worg: see 
[[https://orgmode.org/worg/org-maintenance.html][org-maintenance]].
+
 * Main contribution rules
 
 1. The master git repository is hosted publicly on 
[[https://savannah.gnu.org][savannah.gnu.org]].
@@ -60,25 +64,8 @@ development.
 
 See [[https://orgmode.org/worg/org-contribute.html][worg/org-contribute]] for 
guidance on how to contribute effectively.
 
-* The contrib/ directory
-
-The git repository contains a =contrib/= directory.  This directory is
-the playing field for any developer, also people who have not (yet)
-signed the papers with the FSF.  You are free to add files to this
-directory, implementing extensions, new link types etc.
-
-Also non-Lisp extensions like scripts to process Org files in
-different ways are welcome in this directory.  You should provide
-documentation with your extensions, at least in the form of commentary
-in the file, better on worg.  Please discuss your extensions on
-[[mailto:emacs-orgmode@gnu.org][emacs-orgmode@gnu.org]].
-
-After files have been tested in =contrib/= and found to be generally
-useful, we may decide to clarify copyright questions and then move the
-file into the Org mode core.  This means they will be moved up to the
-root directory and will also eventually be added to GNU Emacs git
-repository.  The final decision about this rests with the maintainer.
-
-* Org maintenance
+* The =contrib/= directory
 
-Org maintenance is explained on Worg: see 
[[https://orgmode.org/worg/org-maintenance.html][org-maintenance]].
+The git repository used to contain a =contrib/= directory.  Files in
+this directory were moved to a new 
[[https://git.sr.ht/~bzg/org-contrib][org-contrib]] repository before Org
+9.5.  You can install the new =org-contrib= from 
[[https://elpa.nongnu.org/nongnu/][NonGNU ELPA]].
diff --git a/COPYING b/COPYING
index 94a9ed0..e600086 100644
--- a/COPYING
+++ b/COPYING
@@ -1,7 +1,7 @@
                     GNU GENERAL PUBLIC LICENSE
                        Version 3, 29 June 2007
 
- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
  Everyone is permitted to copy and distribute verbatim copies
  of this license document, but changing it is not allowed.
 
@@ -645,7 +645,7 @@ the "copyright" line and a pointer to where the full notice 
is found.
     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/>.
+    along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 Also add information on how to contact you by electronic and paper mail.
 
@@ -664,11 +664,11 @@ might be different; for a GUI interface, you would use an 
"about box".
   You should also get your employer (if you work as a programmer) or school,
 if any, to sign a "copyright disclaimer" for the program, if necessary.
 For more information on this, and how to apply and follow the GNU GPL, see
-<http://www.gnu.org/licenses/>.
+<https://www.gnu.org/licenses/>.
 
   The GNU General Public License does not permit incorporating your program
 into proprietary programs.  If your program is a subroutine library, you
 may consider it more useful to permit linking proprietary applications with
 the library.  If this is what you want to do, use the GNU Lesser General
 Public License instead of this License.  But first, please read
-<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+<https://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/README b/README
index 8644776..b0e39b9 100644
--- a/README
+++ b/README
@@ -11,8 +11,9 @@ Check the [[https://orgmode.org][homepage of Org]] and the 
[[https://orgmode.org
 
 - COPYING :: The GNU General Public License.
 
-- Makefile :: The makefile to compile and install Org.  For installation
-  instructions, see the manual or 
[[https://orgmode.org/worg/dev/org-build-system.html][the more detailed 
procedure on Worg]].
+- Makefile :: The makefile to compile and install Org.  For
+  installation instructions, see 
[[https://orgmode.org/org.html#Installation][the manual]] or 
[[https://orgmode.org/worg/dev/org-build-system.html][this more detailed
+  procedure on Worg]].
   
 - mk/ :: Files needed for building Org.
 
@@ -21,20 +22,45 @@ Check the [[https://orgmode.org][homepage of Org]] and the 
[[https://orgmode.org
 - doc/ :: The documentation files.  org.texi is the source of the
   documentation, org.html and org.pdf are formatted versions of it.
 
-- contrib/ :: A directory with third-party additions for Org.  Some
-  really cool stuff is in there.
-
 - etc/ :: Files needed for the ODT exporter.
 
 - testing/ :: Testing suite for Org.
 
 - request-assign-future.txt :: The form that contributors have to sign
   and get processed with the FSF before contributed changes can be
-  integrated into the Org core.  All files in this distribution except
-  the contrib/ directory have copyright assigned to the FSF.
+  integrated into the Org core.  All files in this distribution have
+  copyright assigned to the FSF.
+
+* Join the GNU Project
+
+Org is part of GNU Emacs and GNU Emacs is part of the GNU Operating
+System, developed by the GNU Project.
+
+If you are the author of an awesome program and want to join us in
+writing Free (libre) Software, please consider making it an official
+GNU program and become a GNU Maintainer.  Instructions on how to do
+this are here http://www.gnu.org/help/evaluation
+
+Don't have a program to contribute?  Look at all the other ways to
+help: https://www.gnu.org/help/help.html
+
+And to learn more about Free (libre) Software in general, please
+read and share this page: https://gnu.org/philosophy/free-sw.html
 
 * License
 
 Org-mode is published under [[https://www.gnu.org/licenses/gpl-3.0.html][the 
GNU GPLv3 license]] or any later
-version, the same as GNU Emacs.  See the COPYING file in this
-directory.
+version, the same as GNU Emacs.
+
+Org-mode 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 Org mode.  If not, see <https://www.gnu.org/licenses/>.
diff --git a/README_ELPA b/README_ELPA
index 7640a44..c1ff5e2 100644
--- a/README_ELPA
+++ b/README_ELPA
@@ -10,16 +10,13 @@ This distribution contains an ELPA packaged version of Org.
 "ELPA" stands for the "Emacs Lisp Package Archive".
 
 The GNU ELPA is at:
-  http://elpa.gnu.org
+  https://elpa.gnu.org
 
 It contains the org-*.tar package, containing only the org files
 that are also part of GNU Emacs.
 
 There are other ELPA online, offering more packages.
 
-Some contain the org-plus-contrib-*.tar ELPA package, which bundles
-the core Org files plus many additional contributed libraries.
-
 All ELPA packages of Org contain:
 
 README_ELPA
diff --git a/contrib/README b/contrib/README
deleted file mode 100644
index 73b4552..0000000
--- a/contrib/README
+++ /dev/null
@@ -1,100 +0,0 @@
-This directory contains add-ons to Org-mode.
-
-These contributions are not part of GNU Emacs or of the official
-Org-mode package.  But the git repository for Org-mode is glad to
-provide useful way to distribute and develop them as long as they
-are distributed under a free software license.
-
-Please put your contribution in one of these directories:
-
-LISP (Emacs Lisp)
-=================
-
-Org utils
-~~~~~~~~~
-org-annotate-file.el     --- Annotate a file with org syntax
-org-bibtex-extras.el     --- Extras for working with org-bibtex entries
-org-bookmark.el          --- Links to bookmarks
-org-checklist.el         --- org functions for checklist handling
-org-choose.el            --- Use TODO keywords to mark decision states
-org-collector.el         --- Collect properties into tables
-org-colview-xemacs.el   --- Column View in Org-mode, XEmacs-specific version
-org-contacts.el          --- Contacts management
-org-contribdir.el        --- Dummy file to mark the org contrib Lisp directory
-org-depend.el            --- TODO dependencies for Org-mode
-org-effectiveness.el     --- Measuring your personal effectiveness
-org-element.el           --- Parser and applications for Org syntax
-org-eldoc.el             --- Eldoc documentation for SRC blocks
-org-elisp-symbol.el      --- Org links to emacs-lisp symbols
-org-eval-light.el        --- Evaluate in-buffer code on demand
-org-eval.el              --- The <lisp> tag, adapted from Muse
-org-expiry.el            --- Expiry mechanism for Org entries
-org-export-generic.el    --- Export framework for configurable backends
-org-git-link.el          --- Provide org links to specific file version
-org-interactive-query.el --- Interactive modification of tags query
-org-invoice.el           --- Help manage client invoices in OrgMode
-org-learn.el             --- SuperMemo's incremental learning algorithm
-org-license.el          --- Insert free licenses to your org documents
-org-link-edit.el        --- Slurp and barf with Org links
-org-mac-iCal.el          --- Imports events from iCal.app to the Emacs diary
-org-mac-link.el          --- Grab links and URLs from various Mac applications
-org-mairix.el           --- Hook mairix search into Org for different MUAs
-org-man.el              --- Support for links to manpages in Org-mode
-org-mew.el              --- Support for links to Mew messages
-org-mime.el              --- org html export for text/html MIME emails
-org-mtags.el            --- Support for some Muse-like tags in Org-mode
-org-notify.el            --- Notifications for Org-mode
-org-notmuch.el           --- Support for links to notmuch messages
-org-panel.el            --- Simple routines for us with bad memory
-org-registry.el          --- A registry for Org links
-org-screen.el            --- Visit screen sessions through Org-mode links
-org-screenshot.el        --- Take and manage screenshots in Org-mode files
-org-secretary.el         --- Team management with org-mode
-org-static-mathjax.el    --- Muse-like tags in Org-mode
-org-sudoku.el            --- Create and solve SUDOKU puzzles in Org tables
-org-toc.el              --- Table of contents for Org-mode buffer
-org-track.el             --- Keep up with Org development
-org-velocity.el          --- something like Notational Velocity for Org
-org-vm.el               --- Support for links to VM messages
-org-w3m.el              --- Support link/copy/paste from w3m to Org-mode
-org-wikinodes.el         --- CamelCase wiki-like links for Org
-org-wl.el               --- Support for links to Wanderlust messages
-orgtbl-sqlinsert.el      --- Convert Org-mode tables to SQL insertions
-
-Org exporters
-~~~~~~~~~~~~~
-ox-confluence.el         --- Confluence Wiki exporter
-ox-deck.el               --- deck.js presentations exporter
-ox-groff.el              --- Groff exporter
-ox-koma-letter.el        --- KOMA Scrlttr2 exporter
-ox-rss.el               --- RSS 2.0 exporter
-ox-s5.el                 --- S5 presentations exporter
-ox-taskjuggler.el        --- TaskJuggler exporter
-
-Org Babel languages
-~~~~~~~~~~~~~~~~~~~
-ob-eukleides.el         --- Org-babel functions for eukleides evaluation
-ob-fomus.el             --- Org-babel functions for fomus evaluation
-ob-julia.el             --- Org-babel functions for julia evaluation
-ob-mathomatic.el        --- Org-babel functions for mathomatic evaluation
-ob-oz.el                --- Org-babel functions for Oz evaluation
-ob-stata.el              --- Org-babel functions for Stata evaluation
-ob-tcl.el               --- Org-babel functions for tcl evaluation
-
-External libraries
-~~~~~~~~~~~~~~~~~~
-htmlize.el               --- Convert buffer text and decorations to HTML
-
-
-SCRIPTS (shell, bash, etc.)
-===========================
-StartOzServer.oz        --- implements the Oz-side of the Org-babel Oz 
interface
-dir2org.zsh              --- Org compatible fs structure output
-ditaa.jar               --- ASCII to PNG converter by Stathis Sideris, GPL
-org-docco.org           --- docco side-by-side annotated code export to HTML
-org2hpda                --- Generate hipster pda style printouts from Org-mode
-staticmathjax           --- XULRunner application to process MathJax statically
-x11idle.c               --- get the idle time of your X session
-
-This directory also contains supporting files for the following
-packages: ob-oz.el, org-docco.org, and org-static-mathjax.el.
diff --git a/contrib/lisp/ob-arduino.el b/contrib/lisp/ob-arduino.el
deleted file mode 100644
index 57a15ff..0000000
--- a/contrib/lisp/ob-arduino.el
+++ /dev/null
@@ -1,105 +0,0 @@
-;;; ob-arduino.el --- Org-mode Babel support for Arduino.
-;;
-;; Authors: stardiviner <numbchild@gmail.com>
-;; Package-Requires: ((emacs "24.4") (org "24.1"))
-;; Package-Version: 1.0
-;; Keywords: arduino org babel
-;; homepage: https://github.com/stardiviner/arduino-mode
-;;
-;; 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:
-;; 
-;; Like the following src block, press =[C-c C-c]= to upload to Arduino board.
-;; 
-;; #+begin_src arduino
-;; // the setup function runs once when you press reset or power the board
-;; void setup() {
-;;   // initialize digital pin LED_BUILTIN as an output.
-;;   pinMode(LED_BUILTIN, OUTPUT);
-;; }
-;; 
-;; // the loop function runs over and over again forever
-;; void loop() {
-;;   digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the 
voltage level)
-;;   delay(100);                       // wait for 0.1 second
-;;   digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the 
voltage LOW
-;;   delay(100);                       // wait for 0.1 second
-;; }
-;; #+end_src
-;;
-;;; Code:
-
-(require 'org)
-(require 'ob)
-(require 'arduino-mode)
-
-(defgroup ob-arduino nil
-  "org-mode blocks for Arduino."
-  :group 'org)
-
-(defcustom ob-arduino:program "arduino"
-  "Default Arduino program name."
-  :group 'ob-arduino
-  :type 'string)
-
-(defcustom ob-arduino:port "/dev/ttyACM0"
-  "Default Arduino port."
-  :group 'ob-arduino
-  :type 'string)
-
-(defcustom ob-arduino:board "arduino:avr:uno"
-  "Default Arduino board."
-  :group 'ob-arduino
-  :type 'string)
-
-
-(defvar org-babel-default-header-args:sclang nil)
-
-;;;###autoload
-(defun org-babel-execute:arduino (body params)
-  "org-babel arduino hook."
-  (let* ((port (cdr (assoc :port params)))
-         (board (cdr (assoc :board params)))
-         (cmd (mapconcat 'identity (list
-                                    ob-arduino:program "--upload"
-                                    (if port (concat "--port " port))
-                                    (if board (concat "--board " board))
-                                    ) " "))
-         (code (org-babel-expand-body:generic body params))
-         (src-file (org-babel-temp-file "ob-arduino-" ".ino")))
-    ;; delete all `ob-arduino' temp files, otherwise arduino will compile all
-    ;; ob-arduino temp files, and report error.
-    (mapc
-     (lambda (f)
-       (unless (file-directory-p f)
-         (delete-file (expand-file-name f org-babel-temporary-directory))))
-     (directory-files
-      (file-name-directory (org-babel-temp-file "ob-arduino-" ".ino"))
-      nil ".ino"))
-    ;; specify file for arduino command.
-    (with-temp-file src-file
-      (insert code))
-    (org-babel-eval
-     (concat ob-arduino:program
-             " " "--upload"
-             " " (if port (concat "--port " port))
-             " " (if board (concat "--board " board))
-             " " src-file)
-     "" ; pass empty string "" as `BODY' to 
`org-babel--shell-command-on-region'
-     ;; to fix command `arduino' don't accept string issue.
-     )
-    ))
-
-
-;;;###autoload
-(eval-after-load 'org
-  '(add-to-list 'org-src-lang-modes '("arduino" . arduino)))
-
-
-
-
-(provide 'ob-arduino)
-
-;;; ob-arduino.el ends here
diff --git a/contrib/lisp/ob-clojure-literate.el 
b/contrib/lisp/ob-clojure-literate.el
deleted file mode 100644
index b1cc386..0000000
--- a/contrib/lisp/ob-clojure-literate.el
+++ /dev/null
@@ -1,294 +0,0 @@
-;;; ob-clojure-literate.el --- Clojure's Org-mode Literate Programming.
-
-;; Authors: stardiviner <numbchild@gmail.com>
-;; Package-Requires: ((emacs "24.4") (org "9") (cider "0.16.0") (dash 
"2.12.0"))
-;; Package-Version: 1.1
-;; Keywords: tools
-;; homepage: https://github.com/stardiviner/ob-clojure-literate
-
-;; 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:
-;;
-;; Auto setup ob-clojure-literate scaffold and jack-in Clojure project.
-;;
-;; Usage:
-;;
-;; [M-x ob-clojure-literate-mode] to toggle this minor mode.
-
-;;; Code:
-
-(require 'ob-clojure)
-(require 'cider)
-
-(defgroup ob-clojure-literate nil
-  "Clojure's Org-mode Literate Programming."
-  :prefix "ob-clojure-literate-"
-  :group 'ob-babel)
-
-;;;###autoload
-(defcustom ob-clojure-literate-auto-jackin-p nil
-  "Auto jack in ob-clojure project.
-Don't auto jack in by default for not rude."
-  :type 'boolean
-  :group 'ob-clojure-literate)
-
-(defcustom ob-clojure-literate-project-location nil
-  "The location for `ob-clojure-literate' scaffold project.
-If it is nil, then `cider-jack-in' will jack-in outside of Clojure project.
-If it is a directory, `ob-clojure-literate' will try to create Clojure project 
automatically."
-  :type 'string
-  :group 'ob-clojure-literate)
-
-(defvar ob-clojure-literate-session nil)
-(defvar ob-clojure-literate-original-ns nil)
-(defvar ob-clojure-literate-session-ns nil)
-(defvar ob-clojure-literate-cider-connections nil)
-
-(defcustom ob-clojure-literate-default-session "*cider-repl localhost*"
-  "The default session name for `ob-clojure-literate'."
-  :type 'string
-  :group 'ob-clojure-literate)
-
-(defun ob-clojure-literate-any-connection-p ()
-  "Return t if have any CIDER connection."
-  (and
-   ;; handle the case `cider-jack-in' is not finished creating connection, but 
`ob-clojure-literate-mode' is enabled.
-   (not (null (cider-connections)))
-   (not (null ob-clojure-literate-session)) ; before mode enabled, it is nil.
-   (not (string-empty-p ob-clojure-literate-session)) ; after disable, it is 
"".
-   ))
-
-(defun ob-clojure-literate-get-session-list ()
-  "Return a list of available started CIDER REPL sessions list."
-  (mapcar #'buffer-name
-         ;; for multiple connections case.
-         ;; get global value instead of buffer local.
-         (default-value 'cider-connections)))
-
-;;; Do not allow "ob-clojure" project session name.
-(defun ob-clojure-literate-set-session ()
-  "Set session name for buffer local."
-  ;; if default session is the only one in connections list.
-  (if (and (= (length (ob-clojure-literate-get-session-list)) 1)
-           (member ob-clojure-literate-default-session 
(ob-clojure-literate-get-session-list)))
-      (setq-local ob-clojure-literate-session 
ob-clojure-literate-default-session)
-    ;; if have any connections, choose one from them.
-    (if (ob-clojure-literate-any-connection-p)
-        (setq-local ob-clojure-literate-session
-                    (completing-read "Choose ob-clojure-literate :session : "
-                                     (ob-clojure-literate-get-session-list)))
-      ;; if none, set to default session name to fix `ob-clojure-literate-mode'
-      ;; is enabled before `cider-jack-in' generated connections.
-      (setq-local ob-clojure-literate-session
-                 ob-clojure-literate-default-session))))
-
-;;;###autoload
-(defun ob-clojure-literate-specify-session ()
-  "Specify ob-clojure header argument :session with value selected from a list 
of available sessions."
-  (interactive)
-  (let ((lang (nth 0 (org-babel-get-src-block-info))))
-    (if (and (string= lang "clojure") ; only in clojure src block.
-             (car (seq-filter ; only when :session is not specified yet.
-                   (lambda (header-argument)
-                     (if (eq (car header-argument) :session)
-                         (not (null (cdr header-argument)))))
-                   (nth 2 (org-babel-get-src-block-info)))))
-        (org-babel-insert-header-arg
-         "session"
-         (format "\"%s\""
-                 (completing-read
-                  "Choose :session for ob-clojure-literate: "
-                  (ob-clojure-literate-get-session-list))))
-      (message "This function only used in `clojure' src block.")))
-  )
-
-;;; Auto start CIDER REPL session in a complete Leiningen project environment 
for Org-mode Babel to jack-in.
-;;;###autoload
-(defun ob-clojure-literate-auto-jackin ()
-  "Auto setup ob-clojure-literate scaffold and jack-in Clojure project."
-  (interactive)
-  (cond
-   ;; jack-in outside of Clojure project.
-   ((null ob-clojure-literate-project-location)
-    (if (member (get-buffer "*cider-repl localhost*") cider-connections)
-       (message "CIDER default session already launched.")
-      (cider-jack-in nil)))
-   ((not (null ob-clojure-literate-project-location))
-    (unless (file-directory-p (expand-file-name 
ob-clojure-literate-project-location))
-      (make-directory ob-clojure-literate-project-location t)
-      (let ((default-directory ob-clojure-literate-project-location))
-       (shell-command "lein new ob-clojure")))
-    (unless (or
-             (and (cider-connected-p)
-                  (if (not (null ob-clojure-literate-session))
-                     (seq-contains cider-connections (get-buffer 
ob-clojure-literate-session))))
-             cider-connections
-            (ob-clojure-literate-any-connection-p))
-      ;; return back to original file.
-      (if (not (and (= (length (ob-clojure-literate-get-session-list)) 1)
-                    (member ob-clojure-literate-default-session 
(ob-clojure-literate-get-session-list))))
-          (save-window-excursion
-            (find-file (expand-file-name (concat 
ob-clojure-literate-project-location "ob-clojure/src/ob_clojure/core.clj")))
-            (with-current-buffer "core.clj"
-             (cider-jack-in))))))))
-
-(defun ob-clojure-literate-set-local-cider-connections (toggle?)
-  "Set buffer local `cider-connections' for `ob-clojure-literate-mode' 
`TOGGLE?'."
-  (if toggle?
-      (progn
-        (setq ob-clojure-literate-cider-connections cider-connections)
-        (unless (local-variable-if-set-p 'cider-connections)
-          (make-local-variable 'cider-connections))
-        (setq-local cider-connections ob-clojure-literate-cider-connections))
-    ;; store/restore emptied CIDER connections by `ob-clojure-literate-enable'.
-    (kill-local-variable 'cider-connections) ; kill local variable so that I 
can get the original global variable value.
-    ;; Empty all CIDER connections to avoid `cider-current-connection' return 
any connection.
-    ;; FIXME: when try to enable, `cider-connections' is local and nil.
-    ;; (if (and (= (length (ob-clojure-literate-get-session-list)) 1)
-    ;;          (member ob-clojure-literate-default-session 
(ob-clojure-literate-get-session-list))))
-    ;; (unless (local-variable-if-set-p 'cider-connections)
-    ;;   (make-local-variable 'cider-connections))
-    ;; (setq-local cider-connections '())
-    ))
-
-(defun ob-clojure-literate-set-ns (body params)
-  "Fix the issue that `cider-current-ns' try to invoke `clojure-find-ns' to 
extract ns from buffer."
-  ;; TODO: Is it possible to find ns in `body'?
-  (when (ob-clojure-literate-any-connection-p)
-    (setq ob-clojure-literate-original-ns (cider-current-ns))
-    (with-current-buffer ob-clojure-literate-session
-      (setq ob-clojure-literate-session-ns cider-buffer-ns))
-    (setq-local cider-buffer-ns (or (cdr (assq :ns params))
-                                   ob-clojure-literate-session-ns)))
-  (message (format "ob-clojure-literate: current CIDER ns is [%s]." 
cider-buffer-ns)))
-
-(defun ob-clojure-literate-set-local-session (toggle?)
-  "Set buffer local `org-babel-default-header-args:clojure' for 
`ob-clojure-literate-mode' `TOGGLE?'."
-  (if toggle?
-      (progn
-        ;; set local default session for ob-clojure.
-        (setq ob-clojure-literate-session (ob-clojure-literate-set-session))
-        (unless (local-variable-if-set-p 
'org-babel-default-header-args:clojure)
-          (make-local-variable 'org-babel-default-header-args:clojure))
-        (add-to-list 'org-babel-default-header-args:clojure
-                     `(:session . ,ob-clojure-literate-session))
-        )
-    ;; remove :session from buffer local default header arguments list.
-    (unless (local-variable-if-set-p 'org-babel-default-header-args:clojure)
-      (make-local-variable 'org-babel-default-header-args:clojure))
-    (setq org-babel-default-header-args:clojure
-          (delq t
-                (mapcar
-                 (lambda (cons) (if (eq (car cons) :session) t cons))
-                 org-babel-default-header-args:clojure)))))
-
-
-;;; Support header arguments  :results graphics :file "image.png" by inject 
Clojure code.
-(defun ob-clojure-literate-inject-code (args)
-  "Inject Clojure code into `BODY' in `ARGS'.
-It is used to change Clojure currently working directory in a FAKE way.
-And generate inline graphics image file link result.
-Use header argument like this:
-
-:results graphics :file \"incanter-plot.png\"
-
-Then you need to assign image variable to this :file value like:
-(def incanter-plot (histogram (sample-normal 1000)))
-
-*NOTE*: Currently only support Incanter's `save' function.
-"
-  (let* ((body (nth 0 args))
-         (params (nth 1 args))
-        (dir (cdr (assq :dir params)))
-        (default-directory (and (buffer-file-name) (file-name-directory 
(buffer-file-name))))
-         (directory (and dir (file-name-as-directory (expand-file-name dir))))
-        (result-type (cdr (assq :results params)))
-        (file (cdr (assq :file params)))
-        (file-name (and file (file-name-base file)))
-        ;; TODO: future support `:graphics-file' to avoid collision.
-        (graphics-result (member "graphics" (cdr (assq :result-params 
params))))
-        ;; (graphics-file (cdr (assq :graphics-file params)))
-        ;; (graphics-name (file-name-base graphics-file))
-         (prepend-to-body (lambda (code)
-                            (setq body (concat code "\n" body))))
-        (append-to-body (lambda (code)
-                          (setq body (concat body "\n" code "\n"))))
-         )
-    (when directory
-      (unless (file-directory-p (expand-file-name directory))
-       (warn (format "Target directory %s does not exist, please create it." 
dir))))
-    (when file
-      (funcall append-to-body
-              (format "(save %s \"%s\")" file-name (concat directory file)))
-      )
-    (list body params) ; return modified argument list
-    ))
-
-;;; support :results graphics :dir "data/image" :file "incanter-plot.png"
-(defun ob-clojure-literate-support-graphics-result (result)
-  "Support :results graphics :dir \"data/images\" :file \"incanter-plot.png\"
-reset `RESULT' to `nil'."
-  (let* ((params (nth 2 info))
-        (graphics-result (member "graphics" (cdr (assq :result-params 
params)))))
-    (if graphics-result
-       (setq result nil))
-    result))
-
-
-(defvar ob-clojure-literate-mode-map
-  (let ((map (make-sparse-keymap)))
-    map)
-  "Keymap for `ob-clojure-literate-mode'.")
-
-(define-key org-babel-map (kbd "M-s") 'ob-clojure-literate-specify-session)
-(define-key org-babel-map (kbd "M-j") 'ob-clojure-literate-auto-jackin)
-;; (define-key org-babel-map (kbd "M-e") 'cider-eval-last-sexp)
-;; (define-key org-babel-map (kbd "M-d") 'cider-doc)
-
-;;;###autoload
-(defun ob-clojure-literate-enable ()
-  "Enable Org-mode buffer locally for `ob-clojure-literate'."
-  (when (and (not (null cider-connections)) ; only enable 
`ob-clojure-literate-mode' when has CIDER connections.
-             (equal major-mode 'org-mode)) ; `ob-clojure-literate-mode' only 
works in `org-mode'.
-    (ob-clojure-literate-set-local-cider-connections ob-clojure-literate-mode)
-    (ob-clojure-literate-set-local-session ob-clojure-literate-mode)
-    (advice-add 'org-babel-execute:clojure :before 
#'ob-clojure-literate-set-ns)
-    (advice-add 'org-babel-expand-body:clojure :filter-args 
#'ob-clojure-literate-inject-code)
-    (advice-add 'org-babel-execute:clojure :filter-return 
#'ob-clojure-literate-support-graphics-result)
-    (message "ob-clojure-literate minor mode enabled.")))
-
-;;;###autoload
-(defun ob-clojure-literate-disable ()
-  "Disable Org-mode buffer locally for `ob-clojure-literate'."
-  (advice-remove 'org-babel-execute:clojure #'ob-clojure-literate-set-ns)
-  (advice-remove 'org-babel-expand-body:clojure 
#'ob-clojure-literate-inject-code)
-  (advice-remove 'org-babel-execute:clojure 
#'ob-clojure-literate-support-graphics-result)
-  (setq-local cider-buffer-ns ob-clojure-literate-original-ns)
-  (ob-clojure-literate-set-local-cider-connections ob-clojure-literate-mode)
-  (ob-clojure-literate-set-local-session ob-clojure-literate-mode)
-  (message "ob-clojure-literate minor mode disabled."))
-
-;;;###autoload
-(if ob-clojure-literate-auto-jackin-p (ob-clojure-literate-auto-jackin))
-
-;;;###autoload
-(define-minor-mode ob-clojure-literate-mode
-  "A minor mode to toggle `ob-clojure-literate'."
-  :require 'ob-clojure-literate
-  :init-value nil
-  :lighter " clj-lp"
-  :group 'ob-clojure-literate
-  :keymap ob-clojure-literate-mode-map
-  :global nil
-  (if ob-clojure-literate-mode
-      (ob-clojure-literate-enable)
-    (ob-clojure-literate-disable))
-  )
-
-
-
-(provide 'ob-clojure-literate)
-
-;;; ob-clojure-literate.el ends here
diff --git a/contrib/lisp/ob-csharp.el b/contrib/lisp/ob-csharp.el
deleted file mode 100644
index a6a253c..0000000
--- a/contrib/lisp/ob-csharp.el
+++ /dev/null
@@ -1,83 +0,0 @@
-;;; ob-csharp.el --- org-babel functions for csharp evaluation
-
-;; Copyright (C) 2011-2021 Free Software Foundation, Inc.
-
-;; Author: thomas "at" friendlyvillagers.com based on ob-java.el by Eric 
Schulte
-;; Keywords: literate programming, reproducible research
-;; Homepage: https://orgmode.org
-
-;; This file is not 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 this only supports the external compilation and execution
-;; of csharp code blocks (i.e., no session support).
-
-;;; Code:
-(require 'ob)
-
-(defvar org-babel-tangle-lang-exts)
-(add-to-list 'org-babel-tangle-lang-exts '("csharp" . "cs"))
-
-(defcustom org-babel-csharp-command "mono"
-  "Name of the csharp command.
-May be either a command in the path, like mono
-or an absolute path name, like /usr/local/bin/mono
-parameters may be used, like mono -verbose"
-  :group 'org-babel
-  :version "24.3"
-  :type 'string)
-
-(defcustom org-babel-csharp-compiler "mcs"
-  "Name of the csharp compiler.
-May be either a command in the path, like mcs
-or an absolute path name, like /usr/local/bin/mcs
-parameters may be used, like mcs -warnaserror+"
-  :group 'org-babel
-  :version "24.3"
-  :type 'string)
-
-(defun org-babel-execute:csharp (body params)
-  (let* ((full-body (org-babel-expand-body:generic body params))
-        (cmpflag (or (cdr (assq :cmpflag params)) ""))
-        (cmdline (or (cdr (assq :cmdline params)) ""))
-        (src-file (org-babel-temp-file "csharp-src-" ".cs"))
-        (exe-file (concat (file-name-sans-extension src-file)  ".exe"))
-        (compile
-         (progn (with-temp-file  src-file (insert full-body))
-                (org-babel-eval
-                 (concat org-babel-csharp-compiler " " cmpflag " "  src-file) 
""))))
-    (let ((results (org-babel-eval (concat org-babel-csharp-command " " 
cmdline " " exe-file) "")))
-      (org-babel-reassemble-table
-       (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 (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:csharp (session params)
-  "Return an error because csharp does not support sessions."
-  (error "Sessions are not supported for CSharp"))
-
-(provide 'ob-csharp)
-
-
-
-;;; ob-csharp.el ends here
diff --git a/contrib/lisp/ob-eukleides.el b/contrib/lisp/ob-eukleides.el
deleted file mode 100644
index fc5e7d4..0000000
--- a/contrib/lisp/ob-eukleides.el
+++ /dev/null
@@ -1,98 +0,0 @@
-;;; ob-eukleides.el --- Org-babel functions for eukleides evaluation
-
-;; Copyright (C) 2010-2021  Free Software Foundation, Inc.
-
-;; Author: Luis Anaya
-;; Keywords: literate programming, reproducible research
-;; Homepage: https://orgmode.org
-
-;; This file is not 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:
-
-;; Org-Babel support for evaluating eukleides script.
-;;
-;; Inspired by Ian Yang's org-export-blocks-format-eukleides
-;; http://www.emacswiki.org/emacs/org-export-blocks-format-eukleides.el
-
-;;; Requirements:
-
-;; eukleides     | http://eukleides.org
-;; eukleides     | `org-eukleides-path' should point to the eukleides 
executablexs
-
-;;; Code:
-(require 'ob)
-(require 'ob-eval)
-
-(defvar org-babel-default-header-args:eukleides
-  '((:results . "file") (:exports . "results"))
-  "Default arguments for evaluating a eukleides source block.")
-
-(defcustom org-eukleides-path nil
-  "Path to the eukleides executable file."
-  :group 'org-babel
-  :type 'string)
-
-(defcustom org-eukleides-eps-to-raster nil
-  "Command used to convert EPS to raster. Nil for no conversion."
-  :group 'org-babel
-  :type '(choice
-         (repeat :tag "Shell Command Sequence" (string :tag "Shell Command"))
-         (const :tag "sam2p" "a=%s;b=%s;sam2p ${a} ${b}" )
-         (const :tag "NetPNM"  "a=%s;b=%s;pstopnm -stdout ${a} | pnmtopng  > 
${b}" )
-         (const :tag "None" nil)))
-
-(defun org-babel-execute:eukleides (body params)
-  "Execute a block of eukleides code with org-babel.
-This function is called by `org-babel-execute-src-block'."
-  (let* ((result-params (split-string (or (cdr (assq :results params)) "")))
-        (out-file (or (cdr (assq :file params))
-                      (error "Eukleides requires a \":file\" header 
argument")))
-        (cmdline (cdr (assq :cmdline params)))
-        (in-file (org-babel-temp-file "eukleides-"))
-        (java (or (cdr (assq :java params)) ""))
-        (cmd (if (not org-eukleides-path)
-                 (error "`org-eukleides-path' is not set")
-               (concat (expand-file-name org-eukleides-path)
-                " -b --output="
-                (org-babel-process-file-name
-                 (concat
-                  (file-name-sans-extension out-file) ".eps"))
-                " "
-                (org-babel-process-file-name in-file)))))
-    (unless (file-exists-p org-eukleides-path)
-      (error "Could not find eukleides at %s" org-eukleides-path))
-
-    (if (string= (file-name-extension out-file) "png")
-        (if org-eukleides-eps-to-raster
-            (shell-command (format org-eukleides-eps-to-raster
-                                    (concat (file-name-sans-extension 
out-file) ".eps")
-                                    (concat (file-name-sans-extension 
out-file) ".png")))
-          (error "Conversion to PNG not supported.  Use a file with an EPS 
name")))
-
-    (with-temp-file in-file (insert body))
-    (message "%s" cmd) (org-babel-eval cmd "")
-    nil)) ;; signal that output has already been written to file
-
-(defun org-babel-prep-session:eukleides (session params)
-  "Return an error because eukleides does not support sessions."
-  (error "Eukleides does not support sessions"))
-
-(provide 'ob-eukleides)
-
-
-
-;;; ob-eukleides.el ends here
diff --git a/contrib/lisp/ob-fomus.el b/contrib/lisp/ob-fomus.el
deleted file mode 100644
index 6ff27b6..0000000
--- a/contrib/lisp/ob-fomus.el
+++ /dev/null
@@ -1,92 +0,0 @@
-;;; ob-fomus.el --- Org-babel functions for fomus evaluation
-
-;; Copyright (C) 2011-2014 Torsten Anders
-
-;; Author: Torsten Anders
-;; Keywords: literate programming, reproducible research
-;; Homepage: https://orgmode.org
-
-;; This file is not 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, 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 evaluating Fomus source code.
-;; For information on Fomus see http://fomus.sourceforge.net/
-;;
-;; This differs from most standard languages in that
-;;
-;; 1) there is no such thing as a "session" in fomus
-;;
-;; 2) we are generally only going to return results of type "file"
-;;
-;; 3) we are adding the "file" and "cmdline" header arguments
-;;
-;; 4) there are no variables (at least for now)
-
-;;; Code:
-(require 'ob)
-(require 'ob-eval)
-
-(defvar org-babel-default-header-args:fomus
-  '((:results . "file") (:exports . "results"))
-  "Default arguments to use when evaluating a fomus source block.")
-
-(defun org-babel-expand-body:fomus (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:fomus (body params)
-  "Execute a block of Fomus code with org-babel.
-This function is called by `org-babel-execute-src-block'."
-  (let* ((result-params (cdr (assq :result-params params)))
-        (out-file (cdr (assq :file params)))
-        (cmdline (cdr (assq :cmdline params)))
-        (cmd (or (cdr (assq :cmd params)) "fomus"))
-        (in-file (org-babel-temp-file "fomus-" ".fms")))
-    (with-temp-file in-file
-      (insert (org-babel-expand-body:fomus body params)))
-    ;; TMP: testing
-    ;; (message (concat cmd
-    ;;              " " (org-babel-process-file-name in-file)
-    ;;              " " cmdline
-    ;;              " -o " (org-babel-process-file-name out-file)))
-    (org-babel-eval
-     (concat cmd
-            " " (org-babel-process-file-name in-file)
-            " " cmdline
-            " -o " (org-babel-process-file-name out-file)) "")
-    nil)) ;; signal that output has already been written to file
-
-(defun org-babel-prep-session:fomus (session params)
-  "Return an error because Fomus does not support sessions."
-  (error "Fomus does not support sessions"))
-
-(provide 'ob-fomus)
-
-;;; ob-fomus.el ends here
diff --git a/contrib/lisp/ob-mathematica.el b/contrib/lisp/ob-mathematica.el
deleted file mode 100644
index cb35dec..0000000
--- a/contrib/lisp/ob-mathematica.el
+++ /dev/null
@@ -1,81 +0,0 @@
-;;; ob-mathematica.el --- org-babel functions for Mathematica evaluation
-
-;; Copyright (C) 2014 Yi Wang
-
-;; Authors: Yi Wang
-;; Keywords: literate programming, reproducible research
-;; Homepage: https://github.com/tririver/wy-els/blob/master/ob-mathematica.el
-;; Distributed under the GNU GPL v2 or later
-
-;; Org-Babel support for evaluating Mathematica source code.
-
-;;; Code:
-(require 'ob)
-(require 'ob-ref)
-(require 'ob-comint)
-(require 'ob-eval)
-
-(declare-function org-trim "org" (s &optional keep-lead))
-
-;; Optionally require mma.el for font lock, etc
-(require 'mma nil 'noerror)
-(add-to-list 'org-src-lang-modes '("mathematica" . "mma"))
-
-(defvar org-babel-tangle-lang-exts)
-(add-to-list 'org-babel-tangle-lang-exts '("mathematica" . "m"))
-
-(defvar org-babel-default-header-args:mathematica '())
-
-(defvar org-babel-mathematica-command "MathematicaScript -script"
-  "Name of the command for executing Mathematica code.")
-
-(defvar org-babel-mathematica-command-alt "math -noprompt"
-  "Name of the command for executing Mathematica code.")
-
-(defun org-babel-expand-body:mathematica (body params)
-  "Expand BODY according to PARAMS, return the expanded body."
-  (let ((vars (org-babel--get-vars params)))
-    (concat
-     (mapconcat ;; define any variables
-      (lambda (pair)
-       (format "%s=%s;"
-               (car pair)
-               (org-babel-mathematica-var-to-mathematica (cdr pair))))
-      vars "\n") "\nPrint[\n" body "\n]\n")))
-
-(defun org-babel-execute:mathematica (body params)
-  "Execute a block of Mathematica code with org-babel.  This function is
-called by `org-babel-execute-src-block'"
-  (let* ((result-params (cdr (assq :result-params params)))
-        (full-body (org-babel-expand-body:mathematica body params))
-        (tmp-script-file (org-babel-temp-file "mathematica-"))
-        (cmd org-babel-mathematica-command))
-    ;; actually execute the source-code block
-    (with-temp-file tmp-script-file (insert full-body))
-    ;; (with-temp-file "/tmp/dbg" (insert full-body))
-    ((lambda (raw)
-       (if (or (member "code" result-params)
-              (member "pp" result-params)
-              (and (member "output" result-params)
-                   (not (member "table" result-params))))
-          raw
-        (org-babel-script-escape (org-trim raw))))
-    (org-babel-eval (concat cmd " " tmp-script-file) ""))))
-
-(defun org-babel-prep-session:mathematica (session params)
-  "This function does nothing so far"
-  (error "Currently no support for sessions"))
-
-(defun org-babel-prep-session:mathematica (session body params)
-  "This function does nothing so far"
-  (error "Currently no support for sessions"))
-
-(defun org-babel-mathematica-var-to-mathematica (var)
-  "Convert an elisp value to a Mathematica variable.
-Convert an elisp value, VAR, into a string of Mathematica source code
-specifying a variable of the same value."
-  (if (listp var)
-      (concat "{" (mapconcat #'org-babel-mathematica-var-to-mathematica var ", 
") "}")
-    (format "%S" var)))
-
-(provide 'ob-mathematica)
diff --git a/contrib/lisp/ob-mathomatic.el b/contrib/lisp/ob-mathomatic.el
deleted file mode 100644
index a798312..0000000
--- a/contrib/lisp/ob-mathomatic.el
+++ /dev/null
@@ -1,145 +0,0 @@
-;;; ob-mathomatic.el --- Org-babel functions for mathomatic evaluation
-
-;; Copyright (C) 2009-2021  Free Software Foundation, Inc.
-
-;; Author: Eric S Fraga
-;;     Eric Schulte
-;;  Luis Anaya (Mathomatic)
-
-;; Keywords: literate programming, reproducible research, mathomatic
-;; Homepage: https://orgmode.org
-
-;; This file is not 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:
-
-;; Org-Babel support for evaluating mathomatic entries.
-;;
-;; This differs from most standard languages in that
-;;
-;; 1) there is no such thing as a "session" in mathomatic
-;;
-;; 2) we are adding the "cmdline" header argument
-
-;;; Code:
-(require 'ob)
-
-(defvar org-babel-tangle-lang-exts)
-(add-to-list 'org-babel-tangle-lang-exts '("mathomatic" . "math"))
-
-(defvar org-babel-default-header-args:mathomatic '())
-
-(defcustom org-babel-mathomatic-command
-  (if (boundp 'mathomatic-command) mathomatic-command "mathomatic")
-  "Command used to call mathomatic on the shell."
-  :group 'org-babel)
-
-(defun org-babel-mathomatic-expand (body params)
-  "Expand a block of Mathomatic code according to its header arguments."
-  (let ((vars (org-babel--get-vars params)))
-    (mapconcat 'identity
-              (list
-               ;; graphic output
-               (let ((graphic-file (org-babel-mathomatic-graphical-output-file 
params)))
-                 (if graphic-file
-                     (cond
-                      ((string-match ".\.eps$" graphic-file)
-                       (format ;; Need to add command to send to file.
-                        "set plot set terminal postscript eps\\;set output %S "
-                        graphic-file))
-                      ((string-match ".\.ps$" graphic-file)
-                       (format ;; Need to add command to send to file.
-                        "set plot set terminal postscript\\;set output %S "
-                        graphic-file))
-
-                      ((string-match ".\.pic$" graphic-file)
-                       (format ;; Need to add command to send to file.
-                        "set plot set terminal gpic\\;set output %S "
-                        graphic-file))
-                      (t
-                       (format ;; Need to add command to send to file.
-                        "set plot set terminal png\\;set output %S "
-                        graphic-file)))
-                   ""))
-               ;; variables
-               (mapconcat 'org-babel-mathomatic-var-to-mathomatic vars "\n")
-               ;; body
-               body
-               "")
-              "\n")))
-
-(defun org-babel-execute:mathomatic (body params)
-  "Execute a block of Mathomatic entries with org-babel.  This function is
-called by `org-babel-execute-src-block'."
-  (message "executing Mathomatic source code block")
-  (let ((result-params (split-string (or (cdr (assq :results params)) "")))
-       (result
-        (let* ((cmdline (or (cdr (assq :cmdline params)) ""))
-               (in-file (org-babel-temp-file "mathomatic-" ".math"))
-               (cmd (format "%s -t -c -q  %s %s"
-                            org-babel-mathomatic-command in-file cmdline)))
-          (with-temp-file in-file (insert (org-babel-mathomatic-expand body 
params)))
-          (message cmd)
-          ((lambda (raw) ;; " | grep -v batch | grep -v 'replaced' | sed 
'/^$/d' "
-             (mapconcat
-              #'identity
-              (delq nil
-                    (mapcar (lambda (line)
-                              (unless (or (string-match "batch" line)
-                                          (string-match "^rat: replaced .*$" 
line)
-                                          (= 0 (length line)))
-                                line))
-                            (split-string raw "[\r\n]"))) "\n"))
-           (org-babel-eval cmd "")))))
-    (if (org-babel-mathomatic-graphical-output-file params)
-       nil
-      (if (or (member "scalar" result-params)
-             (member "verbatim" result-params)
-             (member "output" result-params))
-         result
-       (let ((tmp-file (org-babel-temp-file "mathomatic-res-")))
-         (with-temp-file tmp-file (insert result))
-         (org-babel-import-elisp-from-file tmp-file))))))
-
-(defun org-babel-prep-session:mathomatic (session params)
-  (error "Mathomatic does not support sessions"))
-
-(defun org-babel-mathomatic-var-to-mathomatic (pair)
-  "Convert an elisp val into a string of mathomatic code specifying a var
-of the same value."
-  (let ((var (car pair))
-        (val (cdr pair)))
-    (when (symbolp val)
-      (setq val (symbol-name val))
-      (when (= (length val) 1)
-        (setq val (string-to-char val))))
-      (format "%s=%s" var
-             (org-babel-mathomatic-elisp-to-mathomatic val))))
-
-(defun org-babel-mathomatic-graphical-output-file (params)
-  "Name of file to which mathomatic should send graphical output."
-  (and (member "graphics" (cdr (assq :result-params params)))
-       (cdr (assq :file params))))
-
-(defun org-babel-mathomatic-elisp-to-mathomatic (val)
-  "Return a string of mathomatic code which evaluates to VAL."
-  (if (listp val)
-      (mapconcat #'org-babel-mathomatic-elisp-to-mathomatic val " ")
-    (format "%s" val)))
-
-(provide 'ob-mathomatic)
-
-;;; ob-mathomatic.el ends here
diff --git a/contrib/lisp/ob-oz.el b/contrib/lisp/ob-oz.el
deleted file mode 100644
index 46bf536..0000000
--- a/contrib/lisp/ob-oz.el
+++ /dev/null
@@ -1,294 +0,0 @@
-;;; ob-oz.el --- Org-babel functions for Oz evaluation
-
-;; Copyright (C) 2009-2014 Torsten Anders and Eric Schulte
-
-;; Author: Torsten Anders and Eric Schulte
-;; Keywords: literate programming, reproducible research
-;; Homepage: https://orgmode.org
-;; Version: 0.02
-
-;; This file is not 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, 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 evaluating Oz source code.
-;;
-;; Oz code is always send to the Oz Programming Environment (OPI), the
-;; Emacs mode and compiler interface for Oz programs. Therefore, only
-;; session mode is supported. In practice, non-session code blocks are
-;; handled equally well by the session mode. However, only a single
-;; session is supported. Consequently, the :session header argument is
-;; ignored.
-;;
-;; The Org-babel header argument :results is interpreted as
-;; follows. :results output requires the respective code block to be
-;; an Oz statement and :results value requires an Oz
-;; expression. Currently, results are only supported for expressions
-;; (i.e. the result of :results output is always nil).
-;;
-;; Expression evaluation happens synchronously. Therefore there is an
-;; additional header argument :wait-time <number>, which specifies the
-;; maximum time to wait for the result of a given expression. nil
-;; means to wait as long as it takes to get a result (potentially wait
-;; forever).
-;;
-;; NOTE: Currently the copyright of this file may not be in a state to
-;;       permit inclusion as core software into Emacs or Org-mode.
-
-;;; Requirements:
-
-;; - Mozart Programming System, the implementation of the Oz
-;;   programming language (http://www.mozart-oz.org/), which includes
-;;   the major mode mozart for editing Oz programs.
-;;
-;; - StartOzServer.oz which is located in the contrib/scripts
-;;   directory of the Org-mode repository
-
-;;; TODO:
-
-;; - Decide: set communication to \\switch -threadedqueries?
-;;
-;; - Only start Oz compiler when required, e.g., load Org-babel only when 
needed?
-;;
-;; - Avoid synchronous evaluation to avoid blocking Emacs (complex
-;;   Strasheela programs can take long to find a result..). In order
-;;   to cleanly map code blocks to their associated results (which can
-;;   arrive then in any order) I could use IDs
-;;   (e.g. integers). However, how do I do concurrency in Emacs Lisp,
-;;   and how can I define org-babel-execute:oz concurrently.
-;;
-;; - Expressions are rarely used in Oz at the top-level, and using
-;;   them in documentation and Literate Programs will cause
-;;   confusion. Idea: hide expression from reader and instead show
-;;   them statement (e.g., MIDI output statement) and then include
-;;   result in Org file. Implementation: for expressions (:results
-;;   value) support an additional header argument that takes arbitrary
-;;   Oz code. This code is not seen by the reader, but will be used
-;;   for the actual expression at the end.  Alternative: feed all
-;;   relevant code as statement (:results output), then add expression
-;;   as extra code block which outputs, e.g., file name (so the file
-;;   name must be accessible by global var), but the code of this
-;;   extra codeblock is not seen.  Hm, in that case it might be even
-;;   more easy to manually add this link to the Org file.
-;;
-
-
-(require 'ob)
-;;; major mode for editing Oz programs
-(require 'mozart nil t)
-
-;;
-;; Interface to communicate with Oz.
-;; (1) For statements without any results: oz-send-string
-;; (2) For expressions with a single result: oz-send-string-expression
-;;     (defined in org-babel-oz-ResultsValue.el)
-;;
-
-;; oz-send-string-expression implements an additional very direct
-;; communication between Org-babel and the Oz compiler. Communication
-;; with the Oz server works already without this code via the function
-;; oz-send-string from mozart.el.in, but this function does not get
-;; back any results from Oz to Emacs. The following code creates a
-;; socket for sending code to the OPI compiler and results are
-;; returned by the same socket. On the Oz side, a socket is opened and
-;; connected to the compiler of the OPI (via oz-send-string). On the
-;; Emacs side, a connection to this socket is created for feeding code
-;; and receiving results. This additional communication channel to the
-;; OPI compiler ensures that results are returned cleanly (e.g., only
-;; the result of the sent code is returned, no parsing or any
-;; processing of *Oz Emulator* is required).
-;;
-;; There is no buffer, nor sentinel involved. Oz code is send
-;; directly, and results from Oz are send back, but Emacs Lisp
-;; requires a filter function for processing results.
-
-(defvar org-babel-oz-server-dir
-  (file-name-as-directory
-   (expand-file-name
-    "contrib/scripts"
-    (file-name-as-directory
-     (expand-file-name
-      "../../.."
-      (file-name-directory (or load-file-name buffer-file-name))))))
-  "Path to the contrib/scripts directory in which
-StartOzServer.oz is located.")
-
-(defvar org-babel-oz-port 6001
-  "Port for communicating with Oz compiler.")
-(defvar org-babel-oz-OPI-socket nil
-  "Socket for communicating with OPI.")
-
-(defvar org-babel-oz-collected-result nil
-  "Aux var to hand result from org-babel-oz-filter to 
oz-send-string-expression.")
-(defun org-babel-oz-filter (proc string)
-  "Processes output from socket org-babel-oz-OPI-socket."
-;;   (setq org-babel-oz-collected-results (cons string 
org-babel-oz-collected-results))
-  (setq org-babel-oz-collected-result string)
-  )
-
-
-(defun org-babel-oz-create-socket ()
-  (message "Create OPI socket for evaluating expressions")
-  ;; Start Oz directly
-  (run-oz)
-  ;; Create socket on Oz side (after Oz was started).
-  (oz-send-string (concat "\\insert '" org-babel-oz-server-dir 
"StartOzServer.oz'"))
-  ;; Wait until socket is created before connecting to it.
-  ;; Quick hack: wait 3 sec
-  ;;
-  ;; extending time to 30 secs does not help when starting Emacs for
-  ;; the first time (and computer does nothing else)
-  (sit-for 3)
-  ;; connect to OPI socket
-  (setq org-babel-oz-OPI-socket
-       ;; Creates a socket. I/O interface of Emacs sockets as for processes.
-       (open-network-stream "*Org-babel-OPI-socket*" nil "localhost" 
org-babel-oz-port))
-  ;; install filter
-  (set-process-filter org-babel-oz-OPI-socket #'org-babel-oz-filter)
-)
-
-;; communication with org-babel-oz-OPI-socket is asynchronous, but
-;; oz-send-string-expression turns is into synchronous...
-(defun oz-send-string-expression (string &optional wait-time)
-  "Similar to oz-send-string, oz-send-string-expression sends a string to the 
OPI compiler. However, string must be expression and this function returns the 
result of the expression (as string). oz-send-string-expression is synchronous, 
wait-time allows to specify a maximum wait time. After wait-time is over with 
no result, the function returns nil."
-  (if (not org-babel-oz-OPI-socket)
-      (org-babel-oz-create-socket))
-  (let ((polling-delay 0.1)
-       result)
-    (process-send-string org-babel-oz-OPI-socket string)
-    ;; wait for result
-    (if wait-time
-       (let ((waited 0))
-         (unwind-protect
-             (progn
-               (while
-                   ;; stop loop if org-babel-oz-collected-result \= nil or 
waiting time is over
-                   (not (or (not (equal org-babel-oz-collected-result nil))
-                            (> waited wait-time)))
-                 (progn
-                   (sit-for polling-delay)
-;;                 (message "org-babel-oz: next polling iteration")
-                   (setq waited (+ waited polling-delay))))
-;;             (message "org-babel-oz: waiting over, got result or waiting 
timed out")
-;;             (message (format "wait-time: %s, waited: %s" wait-time waited))
-               (setq result org-babel-oz-collected-result)
-               (setq org-babel-oz-collected-result nil))))
-      (unwind-protect
-         (progn
-           (while (equal org-babel-oz-collected-result nil)
-             (sit-for polling-delay))
-           (setq result org-babel-oz-collected-result)
-           (setq org-babel-oz-collected-result nil))))
-    result))
-
-(defun org-babel-expand-body:oz (body params)
-  (let ((vars (org-babel--get-vars params)))
-    (if vars
-       ;; prepend code to define all arguments passed to the code block
-       (let ((var-string (mapcar (lambda (pair)
-                                   (format "%s=%s"
-                                           (car pair)
-                                           (org-babel-oz-var-to-oz (cdr 
pair))))
-                                 vars)))
-         ;; only add var declarations if any variables are there
-         (mapconcat #'identity
-                    (append (list "local") var-string (list "in" body "end"))
-                    "\n"))
-      body)))
-
-(defun org-babel-execute:oz (body params)
-  "Execute a block of Oz code with org-babel.  This function is
-called by `org-babel-execute-src-block' via multiple-value-bind."
-  (let* ((result-params (cdr (assq :result-params params)))
-        (full-body (org-babel-expand-body:oz body params))
-        (wait-time (plist-get params :wait-time)))
-    ;; actually execute the source-code block
-    (org-babel-reassemble-table
-     (cond
-      ((member "output" result-params)
-       (message "Org-babel: executing Oz statement")
-       (oz-send-string full-body))
-      ((member "value" result-params)
-       (message "Org-babel: executing Oz expression")
-       (oz-send-string-expression full-body (or wait-time 1)))
-      (t (error "either 'output' or 'results' must be members of :results")))
-     (org-babel-pick-name (cdr (assq :colname-names params))
-                         (cdr (assq :colnames params)))
-     (org-babel-pick-name (cdr (assq :roname-names params))
-                         (cdr (assq :rownames params))))))
-
-;; This function should be used to assign any variables in params in
-;; the context of the session environment.
-(defun org-babel-prep-session:oz (session params)
-  "Prepare SESSION according to the header arguments specified in PARAMS."
-  (error "org-babel-prep-session:oz unimplemented"))
-;; TODO: testing... (copied from org-babel-haskell.el)
-;; (defun org-babel-prep-session:oz (session params)
-;;   "Prepare SESSION according to the header arguments specified in PARAMS."
-;;   (save-window-excursion
-;;     (org-babel-oz-initiate-session session)
-;;     (let* ((vars (org-babel-ref-variables params))
-;;            (var-lines (mapconcat ;; define any variables
-;;                        (lambda (pair)
-;;                          (format "%s=%s"
-;;                                  (car pair)
-;;                                  (org-babel-ruby-var-to-ruby (cdr pair))))
-;;                        vars "\n"))
-;;            (vars-file (concat (make-temp-file "org-babel-oz-vars") ".oz")))
-;;       (when vars
-;;         (with-temp-buffer
-;;           (insert var-lines) (write-file vars-file)
-;;           (oz-mode)
-;; ;;    (inferior-oz-load-file) ; ??
-;;       ))
-;;       (current-buffer))))
-;;
-
-
-;; TODO: testing... (simplified version of def in org-babel-prep-session:ocaml)
-;;
-;; BUG: does not work yet. Error: ad-Orig-error: buffer none doesn't exist or 
has no process
-;; UNUSED DEF
-(defun org-babel-oz-initiate-session (&optional session params)
-  "If there is not a current inferior-process-buffer in SESSION
-then create.  Return the initialized session."
-  (unless (string= session "none")
-    ;; TODO: make it possible to have multiple sessions
-    (save-window-excursion
-      ;; (run-oz)
-      (get-buffer oz-compiler-buffer))))
-
-(defun org-babel-oz-var-to-oz (var)
-  "Convert an elisp var into a string of Oz source code
-specifying a var of the same value."
-  (if (listp var)
-;;       (concat "[" (mapconcat #'org-babel-oz-var-to-oz var ", ") "]")
-      (eval var)
-    (format "%s" var) ; don't preserve string quotes.
-;;     (format "%s" var)
-    ))
-
-;; TODO:
-(defun org-babel-oz-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."
-  (error "org-babel-oz-table-or-string unimplemented"))
-
-
-(provide 'ob-oz)
-;;; org-babel-oz.el ends here
diff --git a/contrib/lisp/ob-php.el b/contrib/lisp/ob-php.el
deleted file mode 100644
index 99b084c..0000000
--- a/contrib/lisp/ob-php.el
+++ /dev/null
@@ -1,57 +0,0 @@
-;;; ob-php.el --- Execute PHP within org-mode blocks.
-;; Copyright 2016 stardiviner
-
-;; Author: stardiviner <numbchild@gmail.com>
-;; Maintainer: stardiviner <numbchild@gmail.com>
-;; Keywords: org babel php
-;; URL: https://github.com/stardiviner/ob-php
-;; Created: 04th May 2016
-;; Version: 0.0.1
-;; Package-Requires: ((org "8"))
-
-;;; Commentary:
-;;
-;; Execute PHP within org-mode blocks.
-
-;;; Code:
-(require 'org)
-(require 'ob)
-
-(defgroup ob-php nil
-  "org-mode blocks for PHP."
-  :group 'org)
-
-(defcustom org-babel-php-command "php"
-  "The command to execute babel body code."
-  :group 'ob-php
-  :type 'string)
-
-(defcustom org-babel-php-command-options nil
-  "The php command options to use when execute code."
-  :group 'ob-php
-  :type 'string)
-
-(defcustom ob-php:inf-php-buffer "*php*"
-  "Default PHP inferior buffer."
-  :group 'ob-php
-  :type 'string)
-
-;;;###autoload
-(defun org-babel-execute:php (body params)
-  "Orgmode Babel PHP evaluate function for `BODY' with `PARAMS'."
-  (let* ((cmd (concat org-babel-php-command " " org-babel-php-command-options))
-         (body (concat "<?php\n" body "\n?>")))
-    (org-babel-eval cmd body)))
-
-;;;###autoload
-(eval-after-load 'org
-  '(add-to-list 'org-src-lang-modes '("php" . php)))
-
-(defvar org-babel-default-header-args:php '())
-
-(add-to-list 'org-babel-default-header-args:php
-             '(:results . "output"))
-
-(provide 'ob-php)
-
-;;; ob-php.el ends here
diff --git a/contrib/lisp/ob-redis.el b/contrib/lisp/ob-redis.el
deleted file mode 100644
index 086b4cd..0000000
--- a/contrib/lisp/ob-redis.el
+++ /dev/null
@@ -1,44 +0,0 @@
-;;; ob-redis.el --- Execute Redis queries within org-mode blocks.
-;; Copyright 2016 stardiviner
-
-;; Author: stardiviner <numbchild@gmail.com>
-;; Maintainer: stardiviner <numbchild@gmail.com>
-;; Keywords: org babel redis
-;; URL: https://github.com/stardiviner/ob-redis
-;; Created: 28th Feb 2016
-;; Version: 0.0.1
-;; Package-Requires: ((org "8"))
-
-;;; Commentary:
-;;
-;; Execute Redis queries within org-mode blocks.
-
-;;; Code:
-(require 'org)
-(require 'ob)
-
-(defgroup ob-redis nil
-  "org-mode blocks for Redis."
-  :group 'org)
-
-(defcustom ob-redis:default-db "127.0.0.1:6379"
-  "Default Redis database."
-  :group 'ob-redis
-  :type 'string)
-
-;;;###autoload
-(defun org-babel-execute:redis (body params)
-  "org-babel redis hook."
-  (let* ((db (or (cdr (assoc :db params))
-                 ob-redis:default-db))
-         (cmd (mapconcat 'identity (list "redis-cli") " ")))
-    (org-babel-eval cmd body)
-    ))
-
-;;;###autoload
-(eval-after-load 'org
-  '(add-to-list 'org-src-lang-modes '("redis" . redis)))
-
-(provide 'ob-redis)
-
-;;; ob-redis.el ends here
diff --git a/contrib/lisp/ob-sclang.el b/contrib/lisp/ob-sclang.el
deleted file mode 100644
index 5ab2686..0000000
--- a/contrib/lisp/ob-sclang.el
+++ /dev/null
@@ -1,92 +0,0 @@
-;;; ob-sclang.el --- SCLang support for Org-mode Babel
-;;; -*- coding: utf-8 -*-
-
-;; Copyright (C) 2017-2021 Free Software Foundation, Inc.
-
-;; Authors: stardiviner <numbchild@gmail.com>
-;; Package-Version: 0.1
-;; Keywords: babel sclang
-
-;; This file is not 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:
-
-;; `ob-sclang' requires `sclang' from SuperCollider.
-;; Usually SuperCollider dependencies for Emacs are at 
/usr/share/emacs/site-lisp/SuperCollider/
-;; You can install SuperCollider following this article:
-;; https://github.com/supercollider/supercollider#building-the-source-code
-
-;; Usage:
-
-;; Support to evaluate sclang Org-mode src block with function 
`sclang-eval-string'.
-
-;; For example:
-
-;; #+BEGIN_SRC sclang :results none
-;; "Hello World".postln;
-;; #+END_SRC
-;;
-;; *NOTE* Temporary output to org-babel result output is not supported.
-;; Because `sclang-eval-string' will send output to Sclang Post Buffer.
-;; And command line `sclang' execute will not automatically stop after 
finished execution.
-;;
-;; #+BEGIN_SRC sclang :results none
-;; // modulate a sine frequency and a noise amplitude with another sine
-;; // whose frequency depends on the horizontal mouse pointer position
-;; {
-;; var x = SinOsc.ar(MouseX.kr(1, 100));
-;; SinOsc.ar(300 * x + 800, 0, 0.1)
-;; +
-;; PinkNoise.ar(0.1 * x + 0.1)
-;; }.play;
-;; #+END_SRC
-
-
-;;; Code:
-;;; 
----------------------------------------------------------------------------
-(require 'org)
-(require 'ob)
-
-(require 'sclang)
-
-(defgroup ob-sclang nil
-  "org-mode blocks for SuperCollider SCLang."
-  :group 'org)
-
-;;;###autoload
-(defun org-babel-execute:sclang (body params)
-  "Org-mode Babel sclang hook for evaluate `BODY' with `PARAMS'."
-  (unless (or (equal (buffer-name) sclang-post-buffer)
-              (sclang-get-process))
-    (sclang-start))
-  (sclang-eval-string body t))
-
-(defvar org-babel-default-header-args:sclang nil)
-
-(setq org-babel-default-header-args:sclang
-      '((:session . "*SCLang:Workspace*")
-       ;; TODO: temporary can't find way to let sclang output to stdout for 
org-babel.
-        (:output . "none")))
-
-(eval-after-load 'org
-  '(progn
-     (add-to-list 'org-src-lang-modes '("sclang" . sclang))))
-
-;;; 
----------------------------------------------------------------------------
-
-(provide 'ob-sclang)
-
-;;; ob-sclang.el ends here
diff --git a/contrib/lisp/ob-smiles.el b/contrib/lisp/ob-smiles.el
deleted file mode 100644
index 5a0fbf6..0000000
--- a/contrib/lisp/ob-smiles.el
+++ /dev/null
@@ -1,57 +0,0 @@
-;;; ob-smiles.el --- Org-mode Babel support for SMILES.
-;;; -*- coding: utf-8 -*-
-
-;; Keywords: org babel SMILES
-;; Version: 0.0.1
-;; Package-Requires: ((smiles-mode "0.0.1") (org "8"))
-
-;;; Commentary:
-
-;;; I copy code from:
-;;; 
http://kitchingroup.cheme.cmu.edu/blog/2016/03/26/A-molecule-link-for-org-mode
-
-;; Author: John Kitchin [jkitchin@andrew.cmu.edu]
-;; Maintainer: stardiviner [numbchild@gmail.com]
-
-;;; Code:
-
-(require 'ob)
-(require 'org-element)
-
-;; Org-mode Babel
-(defun org-babel-execute:smiles (body params)
-  "Execute SMILES babel `BODY' with `PARAMS'."
-  (shell-command-to-string
-   (format "obabel -:\"%s\" -osvg 2> /dev/null" body)))
-
-;; Org-mode link
-(defun molecule-jump (name)
-  "Jump to molecule `NAME' definition."
-  (org-mark-ring-push)
-  (org-link-open-from-string (format "[[%s]]" name)))
-
-(defun molecule-export (path desc backend)
-  "Export molecule to HTML format on `PATH' with `DESC' and `BACKEND'."
-  (let ((name (save-window-excursion
-                (molecule-jump path)
-                (org-element-property :name (org-element-context)))))
-    (cond
-     ((eq 'html backend)
-      (format "<a href=\"#%s\">%s</a>" name name)))))
-
-(org-link-set-parameters
- "molecule"
- :follow 'molecule-jump
- :export 'molecule-export)
-
-;; org-mode element
-(org-element-map (org-element-parse-buffer)
-    'src-block
-  (lambda (src)
-    (when (string= "smiles" (org-element-property :language src))
-      (org-element-property :name src))))
-
-
-(provide 'ob-smiles)
-
-;;; ob-smiles.el ends here
diff --git a/contrib/lisp/ob-spice.el b/contrib/lisp/ob-spice.el
deleted file mode 100644
index c452c99..0000000
--- a/contrib/lisp/ob-spice.el
+++ /dev/null
@@ -1,182 +0,0 @@
-;;; ob-spice.el --- org-babel functions for spice evaluation
-;;; -*- coding: utf-8 -*-
-
-;; Author: Tiago Oliveira Weber
-;; Maintainer: stardiviner (numbchild@gmail.com)
-;; Version: 0.4
-;; Package-Requires: ((spice-mode "0.0.1") (org "8"))
-;; Homepage: http://tiagoweber.github.io
-
-;; License: GPL v3, or any later version
-;;
-;; This file 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 file 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:
-
-;; Org-Babel support for evaluating spice script.
-;; Inspired by Ian Yang's org-export-blocks-format-plantuml 
(http://www.emacswiki.org/emacs/org-export-blocks-format-plantuml.el)
-
-;;; Requirements:
-;;
-;; - ngspice
-
-;;; Code:
-(require 'ob)
-
-(add-to-list 'org-babel-tangle-lang-exts '("spice" . "cir"))
-
-(defun ob-spice-concat (wordlist)
-  "Concatenate elements of a `WORDLIST' into a string separated by spaces."
-  ;; example of usage
-  ;; (ob-spice-concat '("This" "is" "a" "long" "journey"))
-  (setq newtext (car wordlist)) ; first word is without space before
-  (setq wordlist (rest wordlist)) ; exclude the first word from the list
-  (dolist (word wordlist newtext) ; loop through the list and concatenate the 
values
-    (setq newtext (concat newtext " " word))))
-
-(defun org-babel-expand-body:spice (body params)
-  "Expand BODY according to PARAMS, return the expanded body."
-  (let* ((vars (mapcar #'cdr (org-babel-get-header params :var))))
-    (setq newbody "");
-    (setq bodylinelist (split-string body "\n"))
-    (dolist (line bodylinelist newbody)
-      (progn  ;loop through list of lines
-        (setq wordlist (split-string line " "))
-        (setq firstword 1)
-        (dolist (word wordlist)
-          (progn  ;loop through the words
-            (if (string-match "\\$\\(.*\\)\\[\\(.*\\)\\]" word)
-                (progn 
-                  ;; if matches a vector variable format
-                  (setq varname (match-string 1 word))
-                  (setq varindex (match-string 2 word))
-                  ;; search varname in vars and use the value of varindex to 
word
-                  (setq newword
-                        (nth (string-to-number varindex)
-                             (car (assoc-default varname vars
-                                                 (lambda (key candidate)
-                                                   (string= key candidate))))))
-                  (if (not (eq newword nil))
-                      (if (not (stringp newword))
-                          (setq word (number-to-string newword))
-                        (setq word newword)))
-                  )
-              ) ; end of (if (string-match "\\$\\(.*\\)\\[\\(.*\\)\\]" word))
-            (if (string-match "\\$\\(.*\\)\\." word) ; if variable has a dot 
in the end
-                (progn
-                  ;; if matches a non-vector variable format
-                  (setq varname (match-string 1 word))
-                  (setq newword
-                        (assoc-default varname vars
-                                       (lambda (key candidate)
-                                         (string= key candidate))))
-                  (if (not (eq newword nil))
-                      (progn 
-                        (if (not (stringp newword))
-                            (setq newword (number-to-string newword)))
-                        (setq word (replace-match (concat newword ".")  nil 
nil word))
-                                        ;(setq word word)
-                        )
-                    ))
-              );; end of (if (string-match "\\$\\(.*\\)\\." word)
-            (if (string-match "\\$\\(.*\\)" word)
-                (progn
-                  ;; if matches a non-vector variable format
-                  (setq varname (match-string 1 word))
-                  (setq newword
-                        (assoc-default varname vars
-                                       (lambda (key candidate)
-                                         (string= key candidate))))
-                  (if (not (eq newword nil))
-                      (if (not (stringp newword))
-                          (setq word (number-to-string newword))
-                        (setq word newword)
-                        ))
-                  )
-              ) ; end of (if (string-match "\\$\\(.*\\)" word)
-
-            
-            (setq newbody (concat newbody
-                                  (if (not (eq firstword 1)) " ")
-                                  word))
-            (setq firstword 0)
-            ) ; end of (progn
-          ) ; end of (dolist (word wordlist))
-        
-        (setq newbody (concat newbody "\n"))
-        ) ; end of (progn ;; loop through list of lines ... )
-      ) ; end of (dolist (line bodylinelist)  ...function ...)
-    ))
-
-;;;###autoload
-(defun org-babel-execute:spice (body params)
-  "Execute a block of Spice code `BODY' with org-babel and `PARAMS'."
-  (let ((body (org-babel-expand-body:spice body params))
-        (vars (mapcar #'cdr (org-babel-get-header params :var))))
-
-    ;;******************************
-    ;; clean temporary files
-    (mapc (lambda (pair)
-            (when (string= (car pair) "file")
-              (setq textfile (concat (cdr pair) ".txt"))
-              (setq imagefile (concat (cdr pair) ".png"))            
-              )
-            )
-          vars)
-    ;;    (if (file-readable-p textfile)    (delete-file textfile))
-    ;;    (if (file-readable-p imagefile)    (delete-file imagefile))
-    ;;*******************************
-
-    (org-babel-eval "ngspice -b " body)
-
-    ;; loop through all pairs (elements) of the list vars and set text and 
image file if finds "file" var
-    (mapc (lambda (pair)
-            (when (string= (car pair) "file")
-              (setq textfile (concat (cdr pair) ".txt"))
-              (setq imagefile (concat (cdr pair) ".png"))))
-          vars)
-    ;; produce results        
-    ;; THE FOLLOWING WAS COMMENTED TEMPORARILY
-    ;; (concat
-    ;;  (if (file-readable-p textfile)
-    ;;          (get-string-from-file textfile))
-    ;;  (if (file-readable-p imagefile)
-    ;;          (concat '"#+ATTR_HTML: :width 600px \n [[file:./" imagefile 
"]]")
-    ;;    )
-    ;;  )
-
-    ;; ;; Get measurement values from text-file by splitting comma separated 
values   
-    (if (file-readable-p textfile)
-        (progn   
-          (setq rawtext (get-string-from-file textfile))
-          ;;(setq rawtext (replace-regexp-in-string "\n" "" rawtext))
-          (setq rawtext (replace-regexp-in-string "\n" "" rawtext))
-          (setq result (split-string rawtext ","))))    
-    (if (file-readable-p imagefile)
-        (progn
-          ;; test if result exist already
-          ;;(if (boundp 'result)
-          (add-to-list 'result (concat '"[[file:./" imagefile "]]") t)    ;; 
add imagefile to last entry
-          ;;(concat '"[[file:./" imagefile "]]")
-          ;;)  
-          ))
-    result
-    ;; Produce output like     '(test test2)
-    ;;'(test test2)
-    
-    )
-  )
-
-(provide 'ob-spice)
-;;; ob-spice.el ends here
diff --git a/contrib/lisp/ob-stata.el b/contrib/lisp/ob-stata.el
deleted file mode 100644
index d8cf52a..0000000
--- a/contrib/lisp/ob-stata.el
+++ /dev/null
@@ -1,312 +0,0 @@
-;;; ob-stata.el --- org-babel functions for stata code evaluation
-
-;; Copyright (C) 2014 Ista Zahn
-;; Author: Ista Zahn istazahn@gmail.com
-;;      G. Jay Kerns
-;;      Eric Schulte
-;;      Dan Davison
-
-
-;; This file is not 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, 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:
-
-;; The file provides Org-Babel support for evaluating stata code.
-;; It is basically result of find-and-replace "stata" for "julia"
-;; in ob-julia.el by G. Jay Kerns. Only ":results output" works: the
-;; header args must include ":results output" (this is the default).
-;; Note that I'm not sure ':results value' makes sense or is useful
-;; but I have left all the value-processing stuff inherited from
-;; ob-julia and ob-R. ':results graphics' would be nice, but I have
-;; not tried to implement it.
-;; --Ista, 07/30/2014
-
-;;; Requirements:
-;; Stata: http://stata.com
-;; ESS: http://ess.r-project.org
-
-;;; Code:
-(require 'ob)
-(require 'cl-lib)
-
-(declare-function orgtbl-to-csv "org-table" (table params))
-(declare-function stata "ext:ess-stata" (&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))
-
-(defconst org-babel-header-args:stata
-  '((width              . :any)
-    (horizontal                 . :any)
-    (results             . ((file list vector table scalar verbatim)
-                           (raw org html latex code pp wrap)
-                           (replace silent append prepend)
-                            ;; NOTE: not sure 'value' makes sense in stata
-                            ;; we may want to remove it from the list
-                           (output value graphics))))
-  "stata-specific header arguments.")
-
-(add-to-list 'org-babel-tangle-lang-exts '("stata" . "do"))
-
-;; only ':results output' currently works, so make that the default
-(defvar org-babel-default-header-args:stata '((:results . "output")))
-
-(defcustom org-babel-stata-command inferior-STA-program-name
-  "Name of command to use for executing stata code."
-  :group 'org-babel
-  :version "24.4"
-  :package-version '(Org . "8.3")
-  :type 'string)
-
-(defvar ess-local-process-name) ; dynamically scoped
-(defun org-babel-edit-prep:stata (info)
-  (let ((session (cdr (assq :session (nth 2 info)))))
-    (when (and session (string-match "^\\*\\(.+?\\)\\*$" session))
-      (save-match-data (org-babel-stata-initiate-session session nil)))))
-
-(defun org-babel-expand-body:stata (body params &optional graphics-file)
-  "Expand BODY according to PARAMS, return the expanded body."
-  (let ((graphics-file
-        (or graphics-file (org-babel-stata-graphical-output-file params))))
-    (mapconcat
-     #'identity
-     ((lambda (inside)
-       (if graphics-file
-            inside
-         inside))
-      (append (org-babel-variable-assignments:stata params)
-             (list body))) "\n")))
-
-(defun org-babel-execute:stata (body params)
-  "Execute a block of stata code.
-This function is called by `org-babel-execute-src-block'."
-  (save-excursion
-    (let* ((result-params (cdr (assq :result-params params)))
-          (result-type (cdr (assq :result-type params)))
-           (session (org-babel-stata-initiate-session
-                    (cdr (assq :session params)) params))
-          (colnames-p (cdr (assq :colnames params)))
-          (rownames-p (cdr (assq :rownames params)))
-          (graphics-file (org-babel-stata-graphical-output-file params))
-          (full-body (org-babel-expand-body:stata body params graphics-file))
-          (result
-           (org-babel-stata-evaluate
-            session full-body result-type result-params
-            (or (equal "yes" colnames-p)
-                (org-babel-pick-name
-                 (cdr (assq :colname-names params)) colnames-p))
-            (or (equal "yes" rownames-p)
-                (org-babel-pick-name
-                 (cdr (assq :rowname-names params)) rownames-p)))))
-      (if graphics-file nil result))))
-
-(defun org-babel-prep-session:stata (session params)
-  "Prepare SESSION according to the header arguments specified in PARAMS."
-  (let* ((session (org-babel-stata-initiate-session session params))
-        (var-lines (org-babel-variable-assignments:stata params)))
-    (org-babel-comint-in-buffer session
-      (mapc (lambda (var)
-              (end-of-line 1) (insert var) (comint-send-input nil t)
-              (org-babel-comint-wait-for-output session)) var-lines))
-    session))
-
-(defun org-babel-load-session:stata (session body params)
-  "Load BODY into SESSION."
-  (save-window-excursion
-    (let ((buffer (org-babel-prep-session:stata 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:stata (params)
-  "Return list of stata statements assigning the block's variables."
-  (let ((vars (org-babel--get-vars params)))
-    (mapcar
-     (lambda (pair)
-       (org-babel-stata-assign-elisp
-       (car pair) (cdr pair)
-       (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 (assq :colname-names params))))
-              (cdr (nth i (cdr (assq :rowname-names params)))))))
-      (org-number-sequence 0 (1- (length vars)))))))
-
-(defun org-babel-stata-quote-csv-field (s)
-  "Quote field S for export to stata."
-  (if (stringp s)
-      (concat "\"" (mapconcat 'identity (split-string s "\"") "\"\"") "\"")
-    (format "%S" s)))
-
-(defun org-babel-stata-assign-elisp (name value colnames-p rownames-p)
-  "Construct stata code assigning the elisp VALUE to a variable named NAME."
-  (if (listp value)
-      (let ((max (apply #'max (mapcar #'length (cl-remove-if-not
-                                               #'sequencep value))))
-           (min (apply #'min (mapcar #'length (cl-remove-if-not
-                                               #'sequencep value))))
-           (transition-file (org-babel-temp-file "stata-import-")))
-        ;; 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-csv value '(:fmt org-babel-stata-quote-csv-field))
-          "\n"))
-       (let ((file (org-babel-process-file-name transition-file 'noquote))
-             (header (if (or (eq (nth 1 value) 'hline) colnames-p)
-                         "TRUE" "FALSE"))
-             (row-names (if rownames-p "1" "NULL")))
-         (if (= max min)
-             (format "%s = insheet using \"%s\"" name file)
-           (format "%s = insheet using \"%s\""
-                   name file))))
-    (format "%s = %s" name (org-babel-stata-quote-csv-field value))))
-
-(defvar ess-ask-for-ess-directory) ; dynamically scoped
-
-(defun org-babel-stata-initiate-session (session params)
-  "If there is not a current stata process then create one."
-  (unless (string= session "none")
-    (let ((session (or session "*stata*"))
-         (ess-ask-for-ess-directory
-          (and (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
-         (require 'ess) (stata)
-         (rename-buffer
-          (if (bufferp session)
-              (buffer-name session)
-            (if (stringp session)
-                session
-              (buffer-name))))
-         (current-buffer))))))
-
-(defun org-babel-stata-associate-session (session)
-  "Associate stata code buffer with a stata session.
-Make SESSION be the inferior ESS process associated with the
-current code buffer."
-  (setq ess-local-process-name
-       (process-name (get-buffer-process session)))
-  (ess-make-buffer-current))
-
-(defun org-babel-stata-graphical-output-file (params)
-  "Name of file to which stata should send graphical output."
-  (and (member "graphics" (cdr (assq :result-params params)))
-       (cdr (assq :file params))))
-
-(defvar org-babel-stata-eoe-indicator "display \"org_babel_stata_eoe\"")
-(defvar org-babel-stata-eoe-output "org_babel_stata_eoe")
-
-(defvar org-babel-stata-write-object-command "outsheet using \"%s\"")
-
-(defun org-babel-stata-evaluate
-  (session body result-type result-params column-names-p row-names-p)
-  "Evaluate stata code in BODY."
-  (if session
-      (org-babel-stata-evaluate-session
-       session body result-type result-params column-names-p row-names-p)
-    (org-babel-stata-evaluate-external-process
-     body result-type result-params column-names-p row-names-p)))
-
-(defun org-babel-stata-evaluate-external-process
-  (body result-type result-params column-names-p row-names-p)
-  "Evaluate BODY in external stata 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."
-  (cl-case result-type
-    (value
-     (let ((tmp-file (org-babel-temp-file "stata-")))
-       (org-babel-eval org-babel-stata-command
-                      (format org-babel-stata-write-object-command
-                              (org-babel-process-file-name tmp-file 'noquote)
-                              (format "begin\n%s\nend" body)))
-       (org-babel-stata-process-value-result
-       (org-babel-result-cond result-params
-         (with-temp-buffer
-           (insert-file-contents tmp-file)
-           (buffer-string))
-         (org-babel-import-elisp-from-file tmp-file '(4)))
-       column-names-p)))
-    (output (org-babel-eval org-babel-stata-command body))))
-
-(defun org-babel-stata-evaluate-session
-  (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
-last statement in BODY, as elisp."
-  (cl-case result-type
-    (value
-     (with-temp-buffer
-       (insert (org-babel-chomp body))
-       (let ((ess-local-process-name
-             (process-name (get-buffer-process session)))
-            (ess-eval-visibly-p nil))
-        (ess-eval-buffer nil)))
-     (let ((tmp-file (org-babel-temp-file "stata-")))
-       (org-babel-comint-eval-invisibly-and-wait-for-file
-       session tmp-file
-       (format org-babel-stata-write-object-command
-               (org-babel-process-file-name tmp-file 'noquote) "ans"))
-       (org-babel-stata-process-value-result
-       (org-babel-result-cond result-params
-         (with-temp-buffer
-           (insert-file-contents tmp-file)
-           (buffer-string))
-         (org-babel-import-elisp-from-file tmp-file '(4)))
-       column-names-p)))
-    (output
-     (mapconcat
-      #'org-babel-chomp
-      (butlast
-       (delq nil
-            (mapcar
-             (lambda (line) (when (> (length line) 0) line))
-             (mapcar
-              (lambda (line) ;; cleanup extra prompts left in output
-                (if (string-match
-                     "^\\([ ]*[>+\\.][ ]?\\)+\\([[0-9]+\\|[ ]\\)" line)
-                    (substring line (match-end 1))
-                  line))
-              (org-babel-comint-with-output (session 
org-babel-stata-eoe-output)
-                (insert (mapconcat #'org-babel-chomp
-                                   (list body org-babel-stata-eoe-indicator)
-                                   "\n"))
-                (inferior-ess-send-input)))))) "\n"))))
-
-(defun org-babel-stata-process-value-result (result column-names-p)
-  "stata-specific processing of return value.
-Insert hline if column names in output have been requested."
-  (if column-names-p
-      (cons (car result) (cons 'hline (cdr result)))
-    result))
-
-(provide 'ob-stata)
-
-;;; ob-stata.el ends here
diff --git a/contrib/lisp/ob-tcl.el b/contrib/lisp/ob-tcl.el
deleted file mode 100644
index 2d8b0e4..0000000
--- a/contrib/lisp/ob-tcl.el
+++ /dev/null
@@ -1,128 +0,0 @@
-;;; ob-tcl.el --- Org-babel functions for tcl evaluation
-
-;; Copyright (C) 2009-2021  Free Software Foundation, Inc.
-
-;; Authors: Dan Davison
-;;      Eric Schulte
-;;   Luis Anaya (tcl)
-;;
-;; Keywords: literate programming, reproducible research
-;; Homepage: https://orgmode.org
-
-;; This file is not 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:
-
-;; Org-Babel support for evaluating tcl source code.
-
-;;; Code:
-(require 'ob)
-(require 'ob-eval)
-(eval-when-compile (require 'cl))
-
-(defvar org-babel-tangle-lang-exts)
-(add-to-list 'org-babel-tangle-lang-exts '("tcl" . "tcl"))
-
-(defvar org-babel-default-header-args:tcl nil)
-
-(defcustom org-babel-tcl-command "tclsh"
-"Name of command to use for executing Tcl code."
-  :group 'org-babel
-  :type 'string)
-
-
-(defun org-babel-execute:tcl (body params)
-  "Execute a block of Tcl code with Babel.
-This function is called by `org-babel-execute-src-block'."
-  (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:tcl params)))
-       (session (org-babel-tcl-initiate-session session)))
-    (org-babel-reassemble-table
-     (org-babel-tcl-evaluate session full-body result-type)
-     (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:tcl (session params)
-  "Prepare SESSION according to the header arguments in PARAMS."
-  (error "Sessions are not supported for Tcl"))
-
-(defun org-babel-variable-assignments:tcl (params)
-  "Return list of tcl statements assigning the block's variables."
-  (mapcar
-   (lambda (pair)
-     (format "set %s %s"
-            (car pair)
-            (org-babel-tcl-var-to-tcl (cdr pair))))
-   (org-babel--get-vars params)))
-
-;; helper functions
-
-(defun org-babel-tcl-var-to-tcl (var)
-  "Convert an elisp value to a tcl variable.
-The elisp value, VAR, is converted to a string of tcl source code
-specifying a var of the same value."
-  (if (listp var)
-      (concat "{" (mapconcat #'org-babel-tcl-var-to-tcl var "  ") "}")
-    (format "%s" var)))
-
-(defvar org-babel-tcl-buffers '(:default . nil))
-
-(defun org-babel-tcl-initiate-session (&optional session params)
-  "Return nil because sessions are not supported by tcl."
-nil)
-
-(defvar org-babel-tcl-wrapper-method
-  "
-proc main {} {
-   %s
-}
-
-set r [eval main]
-set o [open \"%s\" \"w\"];
-puts $o $r
-flush $o
-close $o
-
-")
-
-(defvar org-babel-tcl-pp-wrapper-method
-  nil)
-
-(defun org-babel-tcl-evaluate (session body &optional result-type)
-  "Pass BODY to the Tcl 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
-return the value of the last statement in BODY, as elisp."
-  (when session (error "Sessions are not supported for Tcl"))
-  (case result-type
-    (output (org-babel-eval org-babel-tcl-command body))
-    (value (let ((tmp-file (org-babel-temp-file "tcl-")))
-             (org-babel-eval
-              org-babel-tcl-command
-              (format org-babel-tcl-wrapper-method body
-                      (org-babel-process-file-name tmp-file 'noquote)))
-             (org-babel-eval-read-file tmp-file)))))
-
-(provide 'ob-tcl)
-
-
-
-;;; ob-tcl.el ends here
diff --git a/contrib/lisp/ob-vbnet.el b/contrib/lisp/ob-vbnet.el
deleted file mode 100644
index 3c6e9fe..0000000
--- a/contrib/lisp/ob-vbnet.el
+++ /dev/null
@@ -1,84 +0,0 @@
-;;; ob-vbnet.el --- org-babel functions for VB.Net evaluation
-
-;; Copyright (C) 2011-2021 Free Software Foundation, Inc.
-
-;; Author: thomas "at" friendlyvillagers.com based on ob-java.el by Eric 
Schulte
-;; Keywords: literate programming, reproducible research
-;; Homepage: https://orgmode.org
-
-;; This file is not 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 this only supports the external compilation and execution
-;; of VB.Net code blocks (i.e., no session support).
-
-;;; Code:
-(require 'ob)
-
-(defvar org-babel-tangle-lang-exts)
-(add-to-list 'org-babel-tangle-lang-exts '("vbnet" . "vb"))
-
-(defcustom org-babel-vbnet-command "mono"
-  "Name of the mono command.
-May be either a command in the path, like mono
-or an absolute path name, like /usr/local/bin/mono
-parameters may be used, like mono -verbose"
-  :group 'org-babel
-  :version "24.3"
-  :type 'string)
-
-(defcustom org-babel-vbnet-compiler "vbnc"
-  "Name of the VB.Net compiler.
-May be either a command in the path, like vbnc
-or an absolute path name, like /usr/local/bin/vbnc
-parameters may be used, like vbnc /warnaserror+"
-  :group 'org-babel
-  :version "24.3"
-  :type 'string)
-
-(defun org-babel-execute:vbnet (body params)
-  (let* ((full-body (org-babel-expand-body:generic body params))
-        (cmpflag (or (cdr (assq :cmpflag params)) ""))
-        (cmdline (or (cdr (assq :cmdline params)) ""))
-        (src-file (org-babel-temp-file "vbnet-src-" ".vb"))
-        (exe-file (concat (file-name-sans-extension src-file)  ".exe"))
-        (compile
-         (progn (with-temp-file  src-file (insert full-body))
-                (org-babel-eval
-                 (concat org-babel-vbnet-compiler " " cmpflag " " src-file)
-                 ""))))
-    (let ((results (org-babel-eval (concat org-babel-vbnet-command " " cmdline 
" " exe-file) "")))
-      (org-babel-reassemble-table
-       (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 (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:vbnet (session params)
-  "Return an error because vbnet does not support sessions."
-  (error "Sessions are not supported for VB.Net"))
-
-(provide 'ob-vbnet)
-
-
-
-;;; ob-vbnet.el ends here
diff --git a/contrib/lisp/ol-bookmark.el b/contrib/lisp/ol-bookmark.el
deleted file mode 100644
index 08932e9..0000000
--- a/contrib/lisp/ol-bookmark.el
+++ /dev/null
@@ -1,90 +0,0 @@
-;;; ol-bookmark.el - Links to bookmarks
-;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
-;;
-;; Author: Tokuya Kameshima <kames AT fa2.so-net.ne.jp>
-;; Version: 1.0
-;; Keywords: outlines, hypermedia, calendar, wp
-;;
-;; This file is not part of GNU Emacs.
-;;
-;; 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, 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.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(require 'org)
-(require 'bookmark)
-(require 'ol)
-
-(defgroup org-bookmark nil
-  "Options concerning the bookmark link."
-  :tag "Org Startup"
-  :group 'org-link)
-
-(defcustom org-bookmark-in-dired nil
-  "Use org-bookmark in dired."
-  :group 'org-bookmark
-  :type 'boolean)
-
-(defcustom org-bookmark-when-visiting-a-file nil
-  "Use org-bookmark in any buffer visiting a file."
-  :group 'org-bookmark
-  :type 'boolean)
-
-(defcustom org-bookmark-use-first-bookmark nil
-  "If several bookmarks links to the buffer, take the first one.
-Otherwise prompt the user for the right bookmark to use."
-  :group 'org-bookmark
-  :type 'boolean)
-
-(org-link-set-parameters "bookmark"
-                        :follow #'org-bookmark-open
-                        :store #'org-bookmark-store-link)
-
-(defun org-bookmark-open (bookmark _)
-  "Visit the bookmark BOOKMARK."
-  (bookmark-jump bookmark))
-
-(defun org-bookmark-store-link ()
-  "Store a link to the current line's bookmark in bookmark list."
-  (let (file bookmark bmks)
-    (cond ((and org-bookmark-in-dired
-               (eq major-mode 'dired-mode))
-          (setq file (abbreviate-file-name (dired-get-filename))))
-         ((and org-bookmark-when-visiting-a-file
-               (buffer-file-name (buffer-base-buffer)))
-          (setq file (abbreviate-file-name
-                      (buffer-file-name (buffer-base-buffer))))))
-    (if (not file)
-       (when (eq major-mode 'bookmark-bmenu-mode)
-         (setq bookmark (bookmark-bmenu-bookmark)))
-      (when (and (setq bmks
-                      (mapcar (lambda (name)
-                                (if (equal file
-                                           (abbreviate-file-name
-                                            (bookmark-location name)))
-                                    name))
-                              (bookmark-all-names)))
-                (setq bmks (delete nil bmks)))
-       (setq bookmark
-             (if (or (eq 1 (length bmks)) org-bookmark-use-first-bookmark)
-                 (car bmks)
-               (completing-read "Bookmark: " bmks nil t nil nil (car bmks))))))
-    (if bookmark
-       (org-store-link-props :link (concat "bookmark:" bookmark)
-                             :description bookmark))))
-
-(provide 'ol-bookmark)
-
-;;; ol-bookmark.el ends here
diff --git a/contrib/lisp/ol-elisp-symbol.el b/contrib/lisp/ol-elisp-symbol.el
deleted file mode 100644
index 3b416ff..0000000
--- a/contrib/lisp/ol-elisp-symbol.el
+++ /dev/null
@@ -1,157 +0,0 @@
-;;; ol-elisp-symbol.el --- Links to Emacs-lisp symbols
-;;
-;; Copyright 2007-2021 Free Software Foundation, Inc.
-;;
-;; Author: Bastien Guerry
-;; Version: 0.2
-;; Keywords: org, remember, lisp
-;; URL: http://www.cognition.ens.fr/~guerry/u/org-elisp-symbol.el
-;;
-;; This file is not 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, 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:
-;;
-;; Org-mode already lets you store/insert links to emacs-lisp files,
-;; just like any other file.  This package lets you precisely link to
-;; any emacs-lisp symbol and access useful information about the symbol.
-;;
-;; Here is the list of available properties when linking from a elisp-symbol:
-;;
-;; :name        The symbol's name.
-;; :stype       The symbol's type (commandp, function, etc.)
-;; :def         The function used to set the symbol's value (defun, etc.)
-;; :keys        The keys associated with the command.
-;; :args        The arguments of the function.
-;; :docstring   The docstring of the symbol.
-;; :doc         The first line of the dostring.
-;; :comment     A comment line just above the sexp, if any.
-;; :fixme       A FIXME comment line just above the sexp, if any.
-;;
-;; Let's say we have a defun like this one:
-;;
-;; ;; FIXME update docstring
-;; (defun org-export-latex-lists ()
-;;   "Convert lists to LaTeX."
-;;   (goto-char (point-min))
-;;   (while (re-search-forward org-export-latex-list-beginning-re nil t)
-;;     (beginning-of-line)
-;;     (insert (org-list-to-latex (org-list-parse-list t)) "\n")))
-;;
-;; And a remember template like:
-;;
-;; (setq org-remember-templates
-;;   '((?s "* DEBUG `%:name' (%:args)\n\n%?\n\nFixme: %:fixme\n  \
-;;          Doc: \"%:doc\"\n\n%a")))
-;;
-;; Then M-x `org-remember' on this sexp will produce this buffer:
-;;
-;; =====================================================================
-;; * DEBUG `org-export-latex-lists' ()
-;;
-;; <== point
-;;
-;; Fixme: update the docstring
-;; Doc: "Convert lists to LaTeX."
-;;
-;; [[file:~/path/file.el::defun%20my-func][Function: my-func]]
-;; =====================================================================
-;;
-;; Put this file into your load-path and the following into your ~/.emacs:
-;;   (require 'org-elisp-symbol)
-
-;;; Code:
-
-(provide 'ol-elisp-symbol)
-(require 'ol)
-(require 'org)
-
-(org-link-set-parameters "elisp-symbol"
-                        :follow #'org-elisp-symbol-open
-                        :store #'org-elisp-symbol-store-link)
-
-(defun org-elisp-symbol-open (symbol arg)
-  (org-link-open-as-file symbol arg))
-
-(defun org-elisp-symbol-store-link ()
-  "Store a link to an emacs-lisp elisp-symbol."
-  (when (eq major-mode 'emacs-lisp-mode)
-    (save-excursion
-      (or (looking-at "^(") (beginning-of-defun))
-      (looking-at "^(\\([a-z]+\\) \\([^)\n ]+\\) ?\n?[ 
\t]*\\(?:(\\(.*\\))\\)?")
-      (let* ((end (save-excursion
-                   (save-match-data
-                     (end-of-defun) (point))))
-            (def (match-string 1))
-            (name (match-string 2))
-            (sym-name (intern-soft name))
-            (stype (cond ((commandp sym-name) "Command")
-                         ((functionp sym-name) "Function")
-                         ((user-variable-p sym-name) "User variable")
-                         ((string= def "defvar") "Variable")
-                         ((string= def "defmacro") "Macro")
-                         ((string= def "defun") "Function or command")
-                         (t "Symbol")))
-            (args (if (match-string 3)
-                      (mapconcat (lambda (a) (unless (string-match "^&" a) a))
-                                 (split-string (match-string 3)) " ")
-                    "no arg"))
-            (docstring (cond ((functionp sym-name)
-                              (or (documentation sym-name)
-                                  "[no documentation]"))
-                             ((string-match "[Vv]ariable" stype)
-                              (documentation-property sym-name
-                                                      'variable-documentation))
-                             (t "no documentation")))
-            (doc (and (string-match "^\\([^\n]+\\)$" docstring)
-                      (match-string 1 docstring)))
-            (fixme (save-excursion
-                     (beginning-of-defun) (end-of-defun)
-                     (if (re-search-forward "^;+ ?FIXME[ :]*\\(.*\\)$" end t)
-                         (match-string 1) "nothing to fix")))
-            (comment (save-excursion
-                       (beginning-of-defun) (end-of-defun)
-                       (if (re-search-forward "^;;+ ?\\(.*\\)$" end t)
-                           (match-string 1) "no comment")))
-            keys keys-desc link description)
-       (if (equal stype "Command")
-           (setq keys (where-is-internal sym-name)
-                 keys-desc
-                 (if keys (mapconcat 'key-description keys " ") "none")))
-       (setq link (concat "file:" (abbreviate-file-name buffer-file-name)
-                          "::" def " " name))
-       (setq description (concat stype ": " name))
-       (org-store-link-props
-        :type "elisp-symbol"
-        :link link
-        :description description
-        :def def
-        :name name
-        :stype stype
-        :args args
-        :keys keys-desc
-        :docstring docstring
-        :doc doc
-        :fixme fixme
-        :comment comment)))))
-
-(provide 'org-elisp-symbol)
-
-
-;;;;##########################################################################
-;;;;  User Options, Variables
-;;;;##########################################################################
-
-;;; ol-elisp-symbol.el ends here
diff --git a/contrib/lisp/ol-git-link.el b/contrib/lisp/ol-git-link.el
deleted file mode 100644
index 4076e24..0000000
--- a/contrib/lisp/ol-git-link.el
+++ /dev/null
@@ -1,231 +0,0 @@
-;;; ol-git-link.el --- Links to specific file version
-
-;; Copyright (C) 2009-2014  Reimar Finken
-
-;; Author: Reimar Finken <reimar.finken@gmx.de>
-;; Keywords: files, calendar, hypermedia
-
-;; This file is not 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 distaributed 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:
-
-;; `org-git-link.el' defines two new link types. The `git' link
-;; type is meant to be used in the typical scenario and mimics the
-;; `file' link syntax as closely as possible. The `gitbare' link
-;; type exists mostly for debugging reasons, but also allows e.g.
-;; linking to files in a bare git repository for the experts.
-
-;; * User friendy form
-;;   [[git:/path/to/file::searchstring]]
-
-;;   This form is the familiar from normal org file links
-;;   including search options. However, its use is
-;;   restricted to files in a working directory and does not
-;;   handle bare repositories on purpose (see the bare form for
-;;   that).
-
-;;   The search string references a commit (a tree-ish in Git
-;;   terminology). The two most useful types of search strings are
-
-;;   - A symbolic ref name, usually a branch or tag name (e.g.
-;;     master or nobelprize).
-;;   - A ref followed by the suffix @ with a date specification
-;;     enclosed in a brace pair (e.g. {yesterday}, {1 month 2
-;;     weeks 3 days 1 hour 1 second ago} or {1979-02-26 18:30:00})
-;;     to specify the value of the ref at a prior point in time
-;;
-;; * Bare git form
-;;   [[gitbare:$GIT_DIR::$OBJECT]]
-;;
-;;    This is the more bare metal version, which gives the user most
-;;    control. It directly translates to the git command
-;;    git --no-pager --git-dir=$GIT_DIR show $OBJECT
-;;    Using this version one can also view files from a bare git
-;;    repository. For detailed information on how to specify an
-;;    object, see the man page of `git-rev-parse' (section
-;;    SPECIFYING REVISIONS). A specific blob (file) can be
-;;    specified by a suffix clolon (:) followed by a path.
-
-;;; Code:
-
-(require 'org)
-(require 'ol)
-
-(defcustom org-git-program "git"
-  "Name of the git executable used to follow git links."
-  :type '(string)
-  :group 'org)
-
-;; org link functions
-;; bare git link
-(org-link-set-parameters "gitbare" :follow #'org-gitbare-open)
-
-(defun org-gitbare-open (str _)
-  (let* ((strlist (org-git-split-string str))
-         (gitdir (nth 0 strlist))
-         (object (nth 1 strlist)))
-    (org-git-open-file-internal gitdir object)))
-
-
-(defun org-git-open-file-internal (gitdir object)
-  (let* ((sha (org-git-blob-sha gitdir object))
-         (tmpdir (concat temporary-file-directory "org-git-" sha))
-         (filename (org-git-link-filename object))
-         (tmpfile (expand-file-name filename tmpdir)))
-    (unless (file-readable-p tmpfile)
-      (make-directory tmpdir)
-      (with-temp-file tmpfile
-        (org-git-show gitdir object (current-buffer))))
-    (org-open-file tmpfile)
-    (set-buffer (get-file-buffer tmpfile))
-    (setq buffer-read-only t)))
-
-;; user friendly link
-(org-link-set-parameters "git" :follow #'org-git-open :store 
#'org-git-store-link)
-
-(defun org-git-open (str _)
-  (let* ((strlist (org-git-split-string str))
-         (filepath (nth 0 strlist))
-         (commit (nth 1 strlist))
-         (line (nth 2 strlist))
-         (dirlist (org-git-find-gitdir (file-truename filepath)))
-         (gitdir (nth 0 dirlist))
-         (relpath (nth 1 dirlist)))
-    (org-git-open-file-internal gitdir (concat commit ":" relpath))
-    (when line
-      (save-restriction
-       (widen)
-       (goto-char (point-min))
-       (forward-line (1- (string-to-number line)))))))
-
-
-;; Utility functions (file names etc)
-
-(defun org-git-split-dirpath (dirpath)
-  "Given a directory name, return '(dirname basname)"
-  (let ((dirname (file-name-directory (directory-file-name dirpath)))
-        (basename (file-name-nondirectory (directory-file-name dirpath))))
-    (list dirname basename)))
-
-;; finding the git directory
-(defun org-git-find-gitdir (path)
-  "Given a file (not necessarily existing) file path, return the
-  a pair (gitdir relpath), where gitdir is the path to the first
-  .git subdirectory found updstream and relpath is the rest of
-  the path. Example: (org-git-find-gitdir
-  \"~/gitrepos/foo/bar.txt\") returns
-  '(\"/home/user/gitrepos/.git\" \"foo/bar.txt\"). When not in a git 
repository, return nil."
-  (let ((dir (expand-file-name (file-name-directory path)))
-        (relpath (file-name-nondirectory path)))
-    (catch 'toplevel
-      (while (not (file-exists-p (expand-file-name ".git" dir)))
-        (let ((dirlist (org-git-split-dirpath dir)))
-          (when (string= (nth 1 dirlist) "") ; at top level
-            (throw 'toplevel nil))
-          (setq dir (nth 0 dirlist)
-                relpath (concat (file-name-as-directory (nth 1 dirlist)) 
relpath))))
-      (list (expand-file-name ".git" dir) relpath))))
-
-
-(eval-and-compile
-  (defalias 'org-git-gitrepos-p 'org-git-find-gitdir
-    "Return non-nil if path is in git repository"))
-
-;; splitting the link string
-
-;; Both link open functions are called with a string of
-;; consisting of three parts separated by a double colon (::).
-(defun org-git-split-string (str)
-  "Given a string of the form \"str1::str2::str3\", return a list of
-  three substrings \'(\"str1\" \"str2\" \"str3\"). If there are less
-than two double colons, str2 and/or str3 may be set the empty string."
-  (let ((strlist (split-string str "::")))
-    (cond ((= 1 (length strlist))
-           (list (car strlist) "" ""))
-          ((= 2 (length strlist))
-           (append strlist (list "")))
-          ((= 3 (length strlist))
-           strlist)
-          (t (error "org-git-split-string: only one or two :: allowed: %s" 
str)))))
-
-;; finding the file name part of a commit
-(defun org-git-link-filename (str)
-  "Given an object description (see the man page of
-  git-rev-parse), return the nondirectory part of the referenced
-  filename, if it can be extracted. Otherwise, return a valid
-  filename."
-  (let* ((match (and (string-match "[^:]+$" str)
-                     (match-string 0 str)))
-         (filename (and match (file-name-nondirectory match)))) ;extract the 
final part without slash
-    filename))
-
-;; creating a link
-(defun org-git-create-searchstring (branch timestring)
-  (concat branch "@{" timestring "}"))
-
-
-(defun org-git-create-git-link (file &optional line)
-  "Create git link part to file at specific time"
-  (interactive "FFile: ")
-  (let* ((gitdir (nth 0 (org-git-find-gitdir (file-truename file))))
-         (branchname (org-git-get-current-branch gitdir))
-         (timestring (format-time-string "%Y-%m-%d" (current-time))))
-    (concat "git:" file "::" (org-git-create-searchstring branchname 
timestring)
-           (if line (format "::%s" line) ""))))
-
-(defun org-git-store-link ()
-  "Store git link to current file."
-  (when (buffer-file-name)
-    (let ((file (abbreviate-file-name (buffer-file-name)))
-         (line (line-number-at-pos)))
-      (when (org-git-gitrepos-p file)
-       (org-store-link-props
-        :type "git"
-        :link (org-git-create-git-link file line))))))
-
-(defun org-git-insert-link-interactively (file searchstring &optional 
description)
-  (interactive "FFile: \nsSearch string: \nsDescription: ")
-  (insert (org-make-link-string (concat "git:" file "::" searchstring) 
description)))
-
-;; Calling git
-(defun org-git-show (gitdir object buffer)
-  "Show the output of git --git-dir=gitdir show object in buffer."
-  (unless
-      (zerop (call-process org-git-program nil buffer nil
-                           "--no-pager" (concat "--git-dir=" gitdir) "show" 
object))
-    (error "git error: %s " (with-current-buffer buffer (buffer-string)))))
-
-(defun org-git-blob-sha (gitdir object)
-  "Return sha of the referenced object"
-    (with-temp-buffer
-      (if (zerop (call-process org-git-program nil t nil
-                               "--no-pager" (concat "--git-dir=" gitdir) 
"rev-parse" object))
-          (buffer-substring (point-min) (1- (point-max))) ; to strip off final 
newline
-        (error "git error: %s " (buffer-string)))))
-
-(defun org-git-get-current-branch (gitdir)
-  "Return the name of the current branch."
-  (with-temp-buffer
-    (if (not (zerop (call-process org-git-program nil t nil
-                                  "--no-pager" (concat "--git-dir=" gitdir) 
"symbolic-ref" "-q" "HEAD")))
-        (error "git error: %s " (buffer-string))
-      (goto-char (point-min))
-      (if (looking-at "^refs/heads/")   ; 11 characters
-          (buffer-substring 12 (1- (point-max))))))) ; to strip off final 
newline
-
-(provide 'ol-git-link)
-
-;;; ol-git-link.el ends here
diff --git a/contrib/lisp/ol-man.el b/contrib/lisp/ol-man.el
deleted file mode 100644
index b21ed9e..0000000
--- a/contrib/lisp/ol-man.el
+++ /dev/null
@@ -1,85 +0,0 @@
-;;; ol-man.el - Links to man pages
-;;
-;; Author: Carsten Dominik <carsten at orgmode dot org>
-;; Keywords: outlines, hypermedia, calendar, wp
-;; Homepage: https://orgmode.org
-;; Version: 1.0
-;;
-;; This file is not yet 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, 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:
-
-(require 'ol)
-
-(org-link-set-parameters "man"
-                        :follow #'org-man-open
-                        :export #'org-man-export
-                        :store #'org-man-store-link)
-
-(defcustom org-man-command 'man
-  "The Emacs command to be used to display a man page."
-  :group 'org-link
-  :type '(choice (const man) (const woman)))
-
-(defun org-man-open (path _)
-  "Visit the manpage on PATH.
-PATH should be a topic that can be thrown at the man command.
-If PATH contains extra ::STRING which will use `occur' to search
-matched strings in man buffer."
-  (string-match "\\(.*?\\)\\(?:::\\(.*\\)\\)?$" path)
-  (let* ((command (match-string 1 path))
-        (search (match-string 2 path)))
-    (funcall org-man-command command)
-    (when search
-      (with-current-buffer (concat "*Man " command "*")
-       (goto-char (point-min))
-       (search-forward search)))))
-
-(defun org-man-store-link ()
-  "Store a link to a README file."
-  (when (memq major-mode '(Man-mode woman-mode))
-    ;; This is a man page, we do make this link
-    (let* ((page (org-man-get-page-name))
-           (link (concat "man:" page))
-           (description (format "Manpage for %s" page)))
-      (org-link-store-props
-       :type "man"
-       :link link
-       :description description))))
-
-(defun org-man-get-page-name ()
-  "Extract the page name from the buffer name."
-  ;; This works for both `Man-mode' and `woman-mode'.
-  (if (string-match " \\(\\S-+\\)\\*" (buffer-name))
-      (match-string 1 (buffer-name))
-    (error "Cannot create link to this man page")))
-
-(defun org-man-export (link description format)
-  "Export a man page link from Org files."
-  (let ((path (format "http://man.he.net/?topic=%s&section=all"; link))
-       (desc (or description link)))
-    (cond
-     ((eq format 'html) (format "<a target=\"_blank\" href=\"%s\">%s</a>" path 
desc))
-     ((eq format 'latex) (format "\\href{%s}{%s}" path desc))
-     ((eq format 'texinfo) (format "@uref{%s,%s}" path desc))
-     ((eq format 'ascii) (format "%s (%s)" desc path))
-     ((eq format 'md) (format "[%s](%s)" desc path))
-     (t path))))
-
-(provide 'ol-man)
-
-;;; ol-man.el ends here
diff --git a/contrib/lisp/ol-mew.el b/contrib/lisp/ol-mew.el
deleted file mode 100644
index c3d78f6..0000000
--- a/contrib/lisp/ol-mew.el
+++ /dev/null
@@ -1,355 +0,0 @@
-;;; ol-mew.el --- Links to Mew messages
-
-;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
-
-;; Author: Tokuya Kameshima <kames at fa2 dot so-net dot ne dot jp>
-;; Keywords: outlines, hypermedia, calendar, wp
-;; Homepage: https://orgmode.org
-
-;; This file is not 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:
-
-;; This file implements links to Mew messages from within Org-mode.
-;; Org-mode loads this module by default - if this is not what you want,
-;; configure the variable `org-modules'.
-;;
-;; Here is an example of workflow:
-
-;; In your ~/.mew.el configuration file:
-;;
-;; (define-key mew-summary-mode-map "'" 'org-mew-search)
-;; (eval-after-load "mew-summary"
-;;   '(define-key mew-summary-mode-map "\C-o" 'org-mew-capture))
-
-;; 1. In the Mew's inbox folder, take a glance at new messages to find
-;;    a message that requires any action.
-
-;; 2. If the message is a reply from somebody and associated with the
-;;    existing orgmode entry, type M-x `org-mew-search' RET (or press
-;;    the ' key simply) to find the entry.  If you can find the entry
-;;    successfully and think you should start the task right now,
-;;    start the task by M-x `org-agenda-clock-in' RET.
-
-;; 3. If the message is a new message, type M-x `org-mew-capture' RET,
-;;    enter the refile folder, and the buffer to capture the message
-;;    is shown up (without selecting the template by hand).  Then you
-;;    can fill the template and type C-c C-c to complete the capture.
-;;    Note that you can configure `org-capture-templates' so that the
-;;    captured entry has a link to the message.
-
-;;; Code:
-
-(require 'org)
-(require 'ol)
-
-(defgroup org-mew nil
-  "Options concerning the Mew link."
-  :tag "Org Startup"
-  :group 'org-link)
-
-(defcustom org-mew-link-to-refile-destination t
-  "Create a link to the refile destination if the message is marked as refile."
-  :group 'org-mew
-  :type 'boolean)
-
-(defcustom org-mew-inbox-folder nil
-  "The folder where new messages are incorporated.
-If `org-mew-inbox-folder' is non-nil, `org-mew-open' locates the message
-in this inbox folder as well as the folder specified by the link."
-  :group 'org-mew
-  :type 'string)
-
-(defcustom org-mew-use-id-db t
-  "Use ID database to locate the message if id.db is created."
-  :group 'org-mew
-  :type 'boolean)
-
-(defcustom org-mew-subject-alist
-  (list (cons (concat "^\\(?:\\(?:re\\|fwd?\\): *\\)*"
-                     "\\(?:[[(][a-z0-9._-]+[:,]? [0-9]+[])]\\)? *"
-                     "\\(?:\\(?:re\\|fwd?\\): *\\)*"
-                     "\\(.*\\)[ \t]*")
-             1))
-  "Alist of subject regular expression and matched group number for search."
-  :group 'org-mew
-  :type '(repeat (cons (regexp) (integer))))
-
-(defcustom org-mew-capture-inbox-folders nil
-  "List of inbox folders whose messages need refile marked before capture.
-`org-mew-capture' will ask you to put the refile mark on the
-message if the message's folder is any of these folders and the
-message is not marked.  Nil means `org-mew-capture' never ask you
-destination folders before capture."
-  :group 'org-mew
-  :type '(repeat string))
-
-(defcustom org-mew-capture-guess-alist nil
-  "Alist of the regular expression of the folder name and the capture
-template selection keys.
-
-For example,
-    '((\"^%emacs-orgmode$\" . \"o\")
-      (\"\" . \"t\"))
-the messages in \"%emacs-orgmode\" folder will be captured with
-the capture template associated with \"o\" key, and any other
-messages will be captured with the capture template associated
-with \"t\" key."
-  :group 'org-mew
-  :type '(repeat (cons regexp string)))
-
-;; Declare external functions and variables
-(declare-function mew-cache-hit "ext:mew-cache" (fld msg &optional must-hit))
-(declare-function mew-case-folder "ext:mew-func" (case folder))
-(declare-function mew-folder-path-to-folder
-                 "ext:mew-func" (path &optional has-proto))
-(declare-function mew-idstr-to-id-list "ext:mew-header" (idstr &optional rev))
-(declare-function mew-folder-remotep "ext:mew-func" (folder))
-(declare-function mew-folder-virtualp "ext:mew-func" (folder))
-(declare-function mew-header-get-value "ext:mew-header"
-                 (field &optional as-list))
-(declare-function mew-init "ext:mew" ())
-(declare-function mew-refile-get "ext:mew-refile" (msg))
-(declare-function mew-sinfo-get-case "ext:mew-summary" ())
-(declare-function mew-summary-diag-global "ext:mew-thread" (id opt who))
-(declare-function mew-summary-display "ext:mew-summary2" (&optional redisplay))
-(declare-function mew-summary-folder-name "ext:mew-syntax" (&optional ext))
-(declare-function mew-summary-get-mark "ext:mew-mark" ())
-(declare-function mew-summary-message-number2 "ext:mew-syntax" ())
-(declare-function mew-summary-pick-with-mewl "ext:mew-pick"
-                 (pattern folder src-msgs))
-(declare-function mew-summary-refile "ext:mew-refile" (&optional report))
-(declare-function mew-summary-search-msg "ext:mew-const" (msg))
-(declare-function mew-summary-set-message-buffer "ext:mew-summary3" (fld msg))
-(declare-function mew-summary-visit-folder "ext:mew-summary4"
-                 (folder &optional goend no-ls))
-(declare-function mew-window-push "ext:mew" ())
-(declare-function mew-expand-folder "ext:mew-func" (folder))
-(declare-function mew-case:folder-folder "ext:mew-func" (case:folder))
-(declare-function mew "ext:mew" (&optional arg))
-(declare-function mew-message-goto-summary "ext:mew-message" ())
-(declare-function mew-summary-mode "ext:mew-summary" ())
-
-(defvar mew-init-p)
-(defvar mew-mark-afterstep-spec)
-(defvar mew-summary-goto-line-then-display)
-
-;; Install the link type
-(org-link-set-parameters "mew" :follow #'org-mew-open :store 
#'org-mew-store-link)
-
-;; Implementation
-(defun org-mew-store-link ()
-  "Store a link to a Mew folder or message."
-  (save-window-excursion
-    (if (eq major-mode 'mew-message-mode)
-       (mew-message-goto-summary))
-    (when (memq major-mode '(mew-summary-mode mew-virtual-mode))
-      (let ((msgnum (mew-summary-message-number2))
-           (folder-name (org-mew-folder-name)))
-       (if (fboundp 'mew-summary-set-message-buffer)
-           (mew-summary-set-message-buffer folder-name msgnum)
-         (set-buffer (mew-cache-hit folder-name msgnum t)))
-       (let* ((message-id (mew-header-get-value "Message-Id:"))
-              (from (mew-header-get-value "From:"))
-              (to (mew-header-get-value "To:"))
-              (date (mew-header-get-value "Date:"))
-              (subject (mew-header-get-value "Subject:"))
-              desc link)
-         (org-store-link-props :type "mew" :from from :to to :date date
-                               :subject subject :message-id message-id)
-         (setq message-id (org-unbracket-string "<" ">" message-id))
-         (setq desc (org-email-link-description))
-         (setq link (concat "mew:" folder-name "#" message-id))
-         (org-add-link-props :link link :description desc)
-         link)))))
-
-(defun org-mew-folder-name ()
-  "Return the folder name of the current message."
-  (save-window-excursion
-    (if (eq major-mode 'mew-message-mode)
-       (mew-message-goto-summary))
-    (let* ((msgnum (mew-summary-message-number2))
-          (mark-info (mew-summary-get-mark)))
-      (if (and org-mew-link-to-refile-destination
-              (eq mark-info ?o))       ; marked as refile
-         (mew-case-folder (mew-sinfo-get-case)
-                          (nth 1 (mew-refile-get msgnum)))
-       (let ((folder-or-path (mew-summary-folder-name)))
-         (mew-folder-path-to-folder folder-or-path t))))))
-
-(defun org-mew-open (path _)
-  "Follow the Mew message link specified by PATH."
-  (let (folder message-id)
-    (cond ((string-match "\\`\\(+.*\\)+\\+\\([0-9]+\\)\\'" path) ; for 
Bastien's
-          (setq folder (match-string 1 path))
-          (setq message-id (match-string 2 path)))
-         ((string-match "\\`\\(\\(%#\\)?[^#]+\\)\\(#\\(.*\\)\\)?" path)
-          (setq folder (match-string 1 path))
-          (setq message-id (match-string 4 path)))
-         ((and org-mew-use-id-db (string-match "\\`#\\(.+\\)" path))
-          (setq folder nil)
-          (setq message-id (match-string 1 path)))
-         (t (error "Error in Mew link")))
-    (require 'mew)
-    (mew-window-push)
-    (unless mew-init-p (mew-init))
-    (if (null folder)
-       (progn
-         (mew t)
-         (org-mew-open-by-message-id message-id))
-      (or (org-mew-follow-link folder message-id)
-         (and org-mew-inbox-folder (not (string= org-mew-inbox-folder folder))
-              (org-mew-follow-link org-mew-inbox-folder message-id))
-         (and org-mew-use-id-db
-              (org-mew-open-by-message-id message-id))
-         (error "Message not found")))))
-
-(defun org-mew-follow-link (folder message-id)
-  (unless (org-mew-folder-exists-p folder)
-    (error "No such folder or wrong folder %s" folder))
-  (mew-summary-visit-folder folder)
-  (when message-id
-    (let ((msgnum (org-mew-get-msgnum folder message-id)))
-      (when (mew-summary-search-msg msgnum)
-       (if mew-summary-goto-line-then-display
-           (mew-summary-display))
-       t))))
-
-(defun org-mew-folder-exists-p (folder)
-  (let ((dir (mew-expand-folder folder)))
-    (cond
-     ((mew-folder-virtualp folder) (get-buffer folder))
-     ((null dir) nil)
-     ((mew-folder-remotep (mew-case:folder-folder folder)) t)
-     (t (file-directory-p dir)))))
-
-(defun org-mew-get-msgnum (folder message-id)
-  (if (string-match "\\`[0-9]+\\'" message-id)
-      message-id
-    (let* ((pattern (concat "message-id=" message-id))
-          (msgs (mew-summary-pick-with-mewl pattern folder nil)))
-      (car msgs))))
-
-(defun org-mew-open-by-message-id (message-id)
-  "Open message using ID database."
-  (let ((result (mew-summary-diag-global (format "<%s>" message-id)
-                                        "-p" "Message")))
-    (unless (eq result t)
-      (error "Message not found"))))
-
-;; In ~/.mew.el, add the following line:
-;;   (define-key mew-summary-mode-map "'" 'org-mew-search)
-(defun org-mew-search (&optional arg)
-  "Show all entries related to the message using `org-search-view'.
-
-It shows entries which contains the message ID, the reference
-IDs, or the subject of the message.
-
-With C-u prefix, search for the entries that contains the message
-ID or any of the reference IDs.  With C-u C-u prefix, search for
-the message ID or the last reference ID.
-
-The search phase for the subject is extracted with
-`org-mew-subject-alist', which defines the regular expression of
-the subject and the group number to extract.  You can get rid of
-\"Re:\" and some other prefix from the subject text."
-  (interactive "P")
-  (when (memq major-mode '(mew-summary-mode mew-virtual-mode))
-    (let ((last-reference-only (equal arg '(16)))
-         (by-subject (null arg))
-         (msgnum (mew-summary-message-number2))
-         (folder-name (mew-summary-folder-name))
-         subject message-id references id-list)
-      (save-window-excursion
-       (if (fboundp 'mew-summary-set-message-buffer)
-           (mew-summary-set-message-buffer folder-name msgnum)
-         (set-buffer (mew-cache-hit folder-name msgnum t)))
-       (setq subject (mew-header-get-value "Subject:"))
-       (setq message-id (mew-header-get-value "Message-Id:"))
-       (setq references (mew-header-get-value "References:")))
-      (setq id-list (mapcar (lambda (id) (org-unbracket-string "<" ">" id))
-                           (mew-idstr-to-id-list references)))
-      (if last-reference-only
-         (setq id-list (last id-list))
-       (if message-id
-           (setq id-list (cons (org-unbracket-string "<" ">" message-id)
-                               id-list))))
-      (when (and by-subject (stringp subject))
-       (catch 'matched
-         (mapc (lambda (elem)
-                 (let ((regexp (car elem))
-                       (num (cdr elem)))
-                   (when (string-match regexp subject)
-                     (setq subject (match-string num subject))
-                     (throw 'matched t))))
-               org-mew-subject-alist))
-       (setq id-list (cons subject id-list)))
-      (cond ((null id-list)
-            (error "No message ID to search"))
-           ((equal (length id-list) 1)
-            (org-search-view nil (car id-list)))
-           (t
-            (org-search-view nil (format "{\\(%s\\)}"
-                                         (mapconcat 'regexp-quote
-                                                    id-list "\\|"))))))
-    (delete-other-windows)))
-
-(defun org-mew-capture (arg)
-  "Guess the capture template from the folder name and invoke `org-capture'.
-
-This selects a capture template in `org-capture-templates' by
-searching for capture template selection keys defined in
-`org-mew-capture-guess-alist' which are associated with the
-regular expression that matches the message's folder name, and
-then invokes `org-capture'.
-
-If the message's folder is a inbox folder, you are prompted to
-put the refile mark on the message and the capture template is
-guessed from the refile destination folder.  You can customize
-the inbox folders by `org-mew-capture-inbox-folders'.
-
-If ARG is non-nil, this does not guess the capture template but
-asks you to select the capture template."
-  (interactive "P")
-  (or (not (member (org-mew-folder-name)
-                  org-mew-capture-inbox-folders))
-      (eq (mew-summary-get-mark) ?o)
-      (save-window-excursion
-       (if (eq major-mode 'mew-message-mode)
-           (mew-message-goto-summary))
-       (let ((mew-mark-afterstep-spec '((?o 0 0 0 0 0 0 0))))
-         (mew-summary-refile)))
-      (error "No refile folder selected"))
-  (let* ((org-mew-link-to-refile-destination t)
-        (folder-name (org-mew-folder-name))
-        (keys (if arg
-                  nil
-                (org-mew-capture-guess-selection-keys folder-name))))
-    (org-capture nil keys)))
-
-(defun org-mew-capture-guess-selection-keys (folder-name)
-  (catch 'found
-    (let ((alist org-mew-capture-guess-alist))
-      (while alist
-       (let ((elem (car alist)))
-         (if (string-match (car elem) folder-name)
-             (throw 'found (cdr elem))))
-       (setq alist (cdr alist))))))
-
-(provide 'ol-mew)
-
-;;; ol-mew.el ends here
diff --git a/contrib/lisp/ol-notmuch.el b/contrib/lisp/ol-notmuch.el
deleted file mode 100644
index 0fa0c5a..0000000
--- a/contrib/lisp/ol-notmuch.el
+++ /dev/null
@@ -1,154 +0,0 @@
-;;; ol-notmuch.el --- Links to notmuch messages
-
-;; Copyright (C) 2010-2014  Matthieu Lemerre
-
-;; Author: Matthieu Lemerre <racin@free.fr>
-;; Keywords: outlines, hypermedia, calendar, wp
-;; Homepage: https://orgmode.org
-
-;; This file is not part of GNU Emacs.
-
-;; This file 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 2, or (at your option)
-;; any later version.
-
-;; This file 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:
-
-;; This file implements links to notmuch messages and "searches". A
-;; search is a query to be performed by notmuch; it is the equivalent
-;; to folders in other mail clients. Similarly, mails are referred to
-;; by a query, so both a link can refer to several mails.
-
-;; Links have one the following form
-;; notmuch:<search terms>
-;; notmuch-search:<search terms>.
-
-;; The first form open the queries in notmuch-show mode, whereas the
-;; second link open it in notmuch-search mode. Note that queries are
-;; performed at the time the link is opened, and the result may be
-;; different from when the link was stored.
-
-;;; Code:
-
-(require 'ol)
-
-;; customisable notmuch open functions
-(defcustom org-notmuch-open-function
-  'org-notmuch-follow-link
-  "Function used to follow notmuch links.
-
-Should accept a notmuch search string as the sole argument."
-  :group 'org-notmuch
-  :version "24.4"
-  :package-version '(Org . "8.0")
-  :type 'function)
-
-(defcustom org-notmuch-search-open-function
-  'org-notmuch-search-follow-link
-  "Function used to follow notmuch-search links.
-Should accept a notmuch search string as the sole argument."
-  :group 'org-notmuch
-  :version "24.4"
-  :package-version '(Org . "8.0")
-  :type 'function)
-
-(make-obsolete-variable 'org-notmuch-search-open-function nil "9.3")
-
-
-
-;; Install the link type
-(org-link-set-parameters "notmuch"
-                        :follow #'org-notmuch-open
-                        :store #'org-notmuch-store-link)
-
-(defun org-notmuch-store-link ()
-  "Store a link to a notmuch search or message."
-  (when (memq major-mode '(notmuch-show-mode notmuch-tree-mode))
-    (let* ((message-id (notmuch-show-get-message-id t))
-          (subject (notmuch-show-get-subject))
-          (to (notmuch-show-get-to))
-          (from (notmuch-show-get-from))
-          (date (org-trim (notmuch-show-get-date)))
-          desc link)
-      (org-link-store-props :type "notmuch" :from from :to to :date date
-                                   :subject subject :message-id message-id)
-      (setq desc (org-link-email-description))
-      (setq link (concat "notmuch:id:" message-id))
-      (org-link-add-props :link link :description desc)
-      link)))
-
-(defun org-notmuch-open (path _)
-  "Follow a notmuch message link specified by PATH."
-  (funcall org-notmuch-open-function path))
-
-(defun org-notmuch-follow-link (search)
-  "Follow a notmuch link to SEARCH.
-
-Can link to more than one message, if so all matching messages are shown."
-  (require 'notmuch)
-  (notmuch-show search))
-
-
-
-(org-link-set-parameters "notmuch-search"
-                        :follow #'org-notmuch-search-open
-                        :store #'org-notmuch-search-store-link)
-
-(defun org-notmuch-search-store-link ()
-  "Store a link to a notmuch search or message."
-  (when (eq major-mode 'notmuch-search-mode)
-    (let ((link (concat "notmuch-search:" notmuch-search-query-string))
-         (desc (concat "Notmuch search: " notmuch-search-query-string)))
-      (org-link-store-props :type "notmuch-search"
-                           :link link
-                           :description desc)
-      link)))
-
-(defun org-notmuch-search-open (path _)
-  "Follow a notmuch message link specified by PATH."
-  (message "%s" path)
-  (org-notmuch-search-follow-link path))
-
-(defun org-notmuch-search-follow-link (search)
-  "Follow a notmuch link by displaying SEARCH in notmuch-search mode."
-  (require 'notmuch)
-  (notmuch-search search))
-
-
-
-(org-link-set-parameters "notmuch-tree"
-                        :follow #'org-notmuch-tree-open
-                        :store #'org-notmuch-tree-store-link)
-
-(defun org-notmuch-tree-store-link ()
-  "Store a link to a notmuch search or message."
-  (when (eq major-mode 'notmuch-tree-mode)
-    (let ((link (concat "notmuch-tree:" (notmuch-tree-get-query)))
-         (desc (concat "Notmuch tree: " (notmuch-tree-get-query))))
-      (org-link-store-props :type "notmuch-tree"
-                           :link link
-                           :description desc)
-      link)))
-
-(defun org-notmuch-tree-open (path _)
-  "Follow a notmuch message link specified by PATH."
-  (message "%s" path)
-  (org-notmuch-tree-follow-link path))
-
-(defun org-notmuch-tree-follow-link (search)
-  "Follow a notmuch link by displaying SEARCH in notmuch-tree mode."
-  (require 'notmuch)
-  (notmuch-tree search))
-
-(provide 'ol-notmuch)
-
-;;; ol-notmuch.el ends here
diff --git a/contrib/lisp/ol-vm.el b/contrib/lisp/ol-vm.el
deleted file mode 100644
index 1ec0531..0000000
--- a/contrib/lisp/ol-vm.el
+++ /dev/null
@@ -1,167 +0,0 @@
-;;; ol-vm.el --- Links to VM messages
-
-;; Copyright (C) 2004-2021 Free Software Foundation, Inc.
-
-;; Author: Carsten Dominik <carsten at orgmode dot org>
-;; Keywords: outlines, hypermedia, calendar, wp
-;; Homepage: https://orgmode.org
-;;
-;; Support for IMAP folders added
-;; by Konrad Hinsen <konrad dot hinsen at fastmail dot net>
-;; Requires VM 8.2.0a or later.
-;;
-;; This file is not 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:
-;; This file implements links to VM messages and folders from within Org-mode.
-;; Org-mode loads this module by default - if this is not what you want,
-;; configure the variable `org-modules'.
-
-;;; Code:
-
-(require 'ol)
-(require 'org)
-
-;; Declare external functions and variables
-(declare-function vm-preview-current-message "ext:vm-page" ())
-(declare-function vm-follow-summary-cursor "ext:vm-motion" ())
-(declare-function vm-get-header-contents "ext:vm-summary"
-                 (message header-name-regexp &optional clump-sep))
-(declare-function vm-isearch-narrow "ext:vm-search" ())
-(declare-function vm-isearch-update "ext:vm-search" ())
-(declare-function vm-select-folder-buffer "ext:vm-macro" ())
-(declare-function vm-su-message-id "ext:vm-summary" (m))
-(declare-function vm-su-subject "ext:vm-summary" (m))
-(declare-function vm-summarize "ext:vm-summary" (&optional display raise))
-(declare-function vm-imap-folder-p "ext:vm-save" ())
-(declare-function vm-imap-find-spec-for-buffer "ext:vm-imap" (buffer))
-(declare-function vm-imap-folder-for-spec "ext:vm-imap" (spec))
-(declare-function vm-imap-parse-spec-to-list "ext:vm-imap" (spec))
-(declare-function vm-imap-spec-for-account "ext:vm-imap" (account))
-(defvar vm-message-pointer)
-(defvar vm-folder-directory)
-
-;; Install the link type
-(org-link-set-parameters "vm" :follow #'org-vm-open :store #'org-vm-store-link)
-(org-link-set-parameters "vm-imap" :follow #'org-vm-imap-open)
-
-;; Implementation
-(defun org-vm-store-link ()
-  "Store a link to a VM folder or message."
-  (when (and (or (eq major-mode 'vm-summary-mode)
-                (eq major-mode 'vm-presentation-mode))
-            (save-window-excursion
-              (vm-select-folder-buffer) buffer-file-name))
-    (and (eq major-mode 'vm-presentation-mode) (vm-summarize))
-    (vm-follow-summary-cursor)
-    (save-excursion
-      (vm-select-folder-buffer)
-      (let* ((message (car vm-message-pointer))
-            (subject (vm-su-subject message))
-            (to (vm-get-header-contents message "To"))
-            (from (vm-get-header-contents message "From"))
-             (message-id (vm-su-message-id message))
-             (link-type (if (vm-imap-folder-p) "vm-imap" "vm"))
-            (date (vm-get-header-contents message "Date"))
-            folder desc link)
-        (if (vm-imap-folder-p)
-           (let ((spec (vm-imap-find-spec-for-buffer (current-buffer))))
-             (setq folder (vm-imap-folder-for-spec spec)))
-          (progn
-            (setq folder (abbreviate-file-name buffer-file-name))
-            (if (and vm-folder-directory
-                     (string-match (concat "^" (regexp-quote 
vm-folder-directory))
-                                   folder))
-                (setq folder (replace-match "" t t folder)))))
-        (setq message-id (org-unbracket-string "<" ">" message-id))
-       (org-store-link-props :type link-type :from from :to to :subject subject
-                             :message-id message-id :date date)
-       (setq desc (org-email-link-description))
-       (setq link (concat (concat link-type ":") folder "#" message-id))
-       (org-add-link-props :link link :description desc)
-       link))))
-
-(defun org-vm-open (path _)
-  "Follow a VM message link specified by PATH."
-  (let (folder article)
-    (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path))
-       (error "Error in VM link"))
-    (setq folder (match-string 1 path)
-         article (match-string 3 path))
-    ;; The prefix argument will be interpreted as read-only
-    (org-vm-follow-link folder article current-prefix-arg)))
-
-(defun org-vm-follow-link (&optional folder article readonly)
-  "Follow a VM link to FOLDER and ARTICLE."
-  (require 'vm)
-  (setq article (org-link-add-angle-brackets article))
-  (if (string-match "^//\\([a-zA-Z]+@\\)?\\([^:]+\\):\\(.*\\)" folder)
-      ;; ange-ftp or efs or tramp access
-      (let ((user (or (match-string 1 folder) (user-login-name)))
-           (host (match-string 2 folder))
-           (file (match-string 3 folder)))
-       (cond
-        ((featurep 'tramp)
-         ;; use tramp to access the file
-         (setq folder (format "/%s@%s:%s" user host file)))
-        (t
-         ;; use ange-ftp or efs
-         (require 'ange-ftp)
-         (setq folder (format "/%s@%s:%s" user host file))))))
-  (when folder
-    (funcall (cdr (assq 'vm org-link-frame-setup)) folder readonly)
-    (when article
-      (org-vm-select-message (org-link-add-angle-brackets article)))))
-
-(defun org-vm-imap-open (path _)
-  "Follow a VM link to an IMAP folder."
-  (require 'vm-imap)
-  (when (string-match "\\([^:]+\\):\\([^#]+\\)#?\\(.+\\)?" path)
-    (let* ((account-name (match-string 1 path))
-           (mailbox-name (match-string 2 path))
-           (message-id  (match-string 3 path))
-           (account-spec (vm-imap-parse-spec-to-list
-                          (vm-imap-spec-for-account account-name)))
-           (mailbox-spec (mapconcat 'identity
-                                    (append (butlast account-spec 4)
-                                            (cons mailbox-name
-                                                  (last account-spec 3)))
-                                    ":")))
-      (funcall (cdr (assq 'vm-imap org-link-frame-setup))
-               mailbox-spec)
-      (when message-id
-        (org-vm-select-message (org-link-add-angle-brackets message-id))))))
-
-(defun org-vm-select-message (message-id)
-  "Go to the message with message-id in the current folder."
-  (require 'vm-search)
-  (sit-for 0.1)
-  (vm-select-folder-buffer)
-  (widen)
-  (let ((case-fold-search t))
-    (goto-char (point-min))
-    (if (not (re-search-forward
-              (concat "^" "message-id: *" (regexp-quote message-id))))
-        (error "Could not find the specified message in this folder"))
-    (vm-isearch-update)
-    (vm-isearch-narrow)
-    (vm-preview-current-message)
-    (vm-summarize)))
-
-(provide 'ol-vm)
-
-;;; ol-vm.el ends here
diff --git a/contrib/lisp/ol-wl.el b/contrib/lisp/ol-wl.el
deleted file mode 100644
index 5ceba35..0000000
--- a/contrib/lisp/ol-wl.el
+++ /dev/null
@@ -1,304 +0,0 @@
-;;; ol-wl.el --- Links to Wanderlust messages
-
-;; Copyright (C) 2004-2021 Free Software Foundation, Inc.
-
-;; Author: Tokuya Kameshima <kames at fa2 dot so-net dot ne dot jp>
-;;         David Maus <dmaus at ictsoc dot de>
-;; Keywords: outlines, hypermedia, calendar, wp
-;; Homepage: https://orgmode.org
-;;
-;; This file is not 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:
-
-;; This file implements links to Wanderlust 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:
-
-(require 'ol)
-(require 'org)
-
-(defgroup org-wl nil
-  "Options concerning the Wanderlust link."
-  :tag "Org Startup"
-  :group 'org-link)
-
-(defcustom org-wl-link-to-refile-destination t
-  "Create a link to the refile destination if the message is marked as refile."
-  :group 'org-wl
-  :type 'boolean)
-
-(defcustom org-wl-link-remove-filter nil
-  "Remove filter condition if message is filter folder."
-  :group 'org-wl
-  :type 'boolean)
-
-(defcustom org-wl-shimbun-prefer-web-links nil
-  "If non-nil create web links for shimbun messages."
-  :group 'org-wl
-  :type 'boolean)
-
-(defcustom org-wl-nntp-prefer-web-links nil
-  "If non-nil create web links for nntp messages.
-When folder name contains string \"gmane\" link to gmane,
-googlegroups otherwise."
-  :type 'boolean
-  :group 'org-wl)
-
-(defcustom org-wl-disable-folder-check t
-  "Disable check for new messages when open a link."
-  :type 'boolean
-  :group 'org-wl)
-
-(defcustom org-wl-namazu-default-index nil
-  "Default namazu search index."
-  :type '(choice (const nil) (directory))
-  :group 'org-wl)
-
-;; Declare external functions and variables
-(declare-function elmo-folder-exists-p "ext:elmo" (folder) t)
-(declare-function elmo-message-entity-field "ext:elmo-msgdb"
-                 (entity field &optional type))
-(declare-function elmo-message-field "ext:elmo"
-                 (folder number field &optional type) t)
-(declare-function elmo-msgdb-overview-get-entity "ext:elmo" (id msgdb) t)
-;; Backward compatibility to old version of wl
-(declare-function wl "ext:wl" () t)
-(declare-function wl-summary-buffer-msgdb "ext:wl-folder" () t)
-(declare-function wl-summary-jump-to-msg-by-message-id "ext:wl-summary"
-                 (&optional id))
-(declare-function wl-summary-jump-to-msg "ext:wl-summary"
-                 (&optional number beg end))
-(declare-function wl-summary-line-from "ext:wl-summary" ())
-(declare-function wl-summary-line-subject "ext:wl-summary" ())
-(declare-function wl-summary-message-number "ext:wl-summary" ())
-(declare-function wl-summary-redisplay "ext:wl-summary" (&optional arg))
-(declare-function wl-summary-registered-temp-mark "ext:wl-action" (number))
-(declare-function wl-folder-goto-folder-subr "ext:wl-folder"
-                 (&optional folder sticky))
-(declare-function wl-folder-get-petname "ext:wl-folder" (name))
-(declare-function wl-folder-get-entity-from-buffer "ext:wl-folder"
-                 (&optional getid))
-(declare-function wl-folder-buffer-group-p "ext:wl-folder")
-(defvar wl-init)
-(defvar wl-summary-buffer-elmo-folder)
-(defvar wl-summary-buffer-folder-name)
-(defvar wl-folder-group-regexp)
-(defvar wl-auto-check-folder-name)
-(defvar elmo-nntp-default-server)
-
-(defconst org-wl-folder-types
-  '(("%" . imap) ("-" . nntp) ("+" . mh) ("." . maildir)
-    ("=" . spool) ("$" . archive) ("&" . pop) ("@" . shimbun)
-    ("rss" . rss) ("[" . search) ("*" . multi) ("/" . filter)
-    ("|" . pipe) ("'" . internal) )
-  "List of folder indicators.  See Wanderlust manual, section 3.")
-
-;; Install the link type
-(org-link-set-parameters "wl" :follow #'org-wl-open :store #'org-wl-store-link)
-
-;; Implementation
-
-(defun org-wl-folder-type (folder)
-  "Return symbol that indicates the type of FOLDER.
-FOLDER is the wanderlust folder name.  The first character of the
-folder name determines the folder type."
-  (let* ((indicator (substring folder 0 1))
-        (type (cdr (assoc indicator org-wl-folder-types))))
-    ;; maybe access or file folder
-    (when (not type)
-      (setq type
-           (cond
-            ((and (>= (length folder) 5)
-                  (string= (substring folder 0 5) "file:"))
-             'file)
-            ((and (>= (length folder) 7)
-                  (string= (substring folder 0 7) "access:"))
-             'access)
-            (t
-             nil))))
-    type))
-
-(defun org-wl-message-field (field entity)
-  "Return content of FIELD in ENTITY.
-FIELD is a symbol of a rfc822 message header field.
-ENTITY is a message entity."
-  (let ((content (elmo-message-entity-field entity field 'string)))
-    (if (listp content) (car content) content)))
-
-(defun org-wl-store-link ()
-  "Store a link to a WL message or folder."
-  (unless (eobp)
-    (cond
-     ((memq major-mode '(wl-summary-mode mime-view-mode))
-      (org-wl-store-link-message))
-     ((eq major-mode 'wl-folder-mode)
-      (org-wl-store-link-folder))
-     (t
-      nil))))
-
-(defun org-wl-store-link-folder ()
-  "Store a link to a WL folder."
-  (let* ((folder (wl-folder-get-entity-from-buffer))
-        (petname (wl-folder-get-petname folder))
-        (link (concat "wl:" folder)))
-    (save-excursion
-      (beginning-of-line)
-      (unless (and (wl-folder-buffer-group-p)
-                  (looking-at wl-folder-group-regexp))
-       (org-store-link-props :type "wl" :description petname
-                             :link link)
-       link))))
-
-(defun org-wl-store-link-message ()
-  "Store a link to a WL message."
-  (save-excursion
-    (let ((buf (if (eq major-mode 'wl-summary-mode)
-                  (current-buffer)
-                (and (boundp 'wl-message-buffer-cur-summary-buffer)
-                     wl-message-buffer-cur-summary-buffer))))
-      (when buf
-       (with-current-buffer buf
-         (let* ((msgnum (wl-summary-message-number))
-                (mark-info (wl-summary-registered-temp-mark msgnum))
-                (folder-name
-                 (if (and org-wl-link-to-refile-destination
-                          mark-info
-                          (equal (nth 1 mark-info) "o")) ; marked as refile
-                     (nth 2 mark-info)
-                   wl-summary-buffer-folder-name))
-                (folder-type (org-wl-folder-type folder-name))
-                (wl-message-entity
-                 (if (fboundp 'elmo-message-entity)
-                     (elmo-message-entity
-                      wl-summary-buffer-elmo-folder msgnum)
-                   (elmo-msgdb-overview-get-entity
-                    msgnum (wl-summary-buffer-msgdb))))
-                (message-id
-                 (org-wl-message-field 'message-id wl-message-entity))
-                (message-id-no-brackets
-                 (org-unbracket-string "<" ">" message-id))
-                (from (org-wl-message-field 'from wl-message-entity))
-                (to (org-wl-message-field 'to wl-message-entity))
-                (xref (org-wl-message-field 'xref wl-message-entity))
-                (subject (org-wl-message-field 'subject wl-message-entity))
-                (date (org-wl-message-field 'date wl-message-entity))
-                desc link)
-
-           ;; remove text properties of subject string to avoid possible bug
-           ;; when formatting the subject
-           ;; (Emacs bug #5306, fixed)
-           (set-text-properties 0 (length subject) nil subject)
-
-           ;; maybe remove filter condition
-           (when (and (eq folder-type 'filter) org-wl-link-remove-filter)
-             (while (eq (org-wl-folder-type folder-name) 'filter)
-               (setq folder-name
-                     (replace-regexp-in-string "^/[^/]+/" "" folder-name))))
-
-           ;; maybe create http link
-           (cond
-            ((and (eq folder-type 'shimbun)
-                  org-wl-shimbun-prefer-web-links xref)
-             (org-store-link-props :type "http" :link xref :description subject
-                                   :from from :to to :message-id message-id
-                                   :message-id-no-brackets 
message-id-no-brackets
-                                   :subject subject))
-            ((and (eq folder-type 'nntp) org-wl-nntp-prefer-web-links)
-             (setq link
-                   (format
-                    (if (string-match-p "gmane\\." folder-name)
-                        "http://mid.gmane.org/%s";
-                      "http://groups.google.com/groups/search?as_umsgid=%s";)
-                    (url-encode-url message-id)))
-             (org-store-link-props :type "http" :link link :description subject
-                                   :from from :to to :message-id message-id
-                                   :message-id-no-brackets 
message-id-no-brackets
-                                   :subject subject))
-            (t
-             (org-store-link-props :type "wl" :from from :to to
-                                   :subject subject :message-id message-id
-                                   :message-id-no-brackets 
message-id-no-brackets)
-             (setq desc (org-email-link-description))
-             (setq link (concat "wl:" folder-name "#" message-id-no-brackets))
-             (org-add-link-props :link link :description desc)))
-           (org-add-link-props :date date)
-           (or link xref)))))))
-
-(defun org-wl-open-nntp (path)
-  "Follow the nntp: link specified by PATH."
-  (let* ((spec (split-string path "/"))
-        (server (split-string (nth 2 spec) "@"))
-        (group (nth 3 spec))
-        (article (nth 4 spec)))
-    (org-wl-open
-     (concat "-" group ":" (if (cdr server)
-                              (car (split-string (car server) ":"))
-                            "")
-            (if (string= elmo-nntp-default-server (nth 2 spec))
-                ""
-              (concat "@" (or (cdr server) (car server))))
-            (if article (concat "#" article) "")))))
-
-(defun org-wl-open (path &rest _)
-  "Follow the WL message link specified by PATH.
-When called with one prefix, open message in namazu search folder
-with `org-wl-namazu-default-index' as search index.  When called
-with two prefixes or `org-wl-namazu-default-index' is nil, ask
-for namazu index."
-  (require 'wl)
-  (let ((wl-auto-check-folder-name
-        (if org-wl-disable-folder-check
-            'none
-          wl-auto-check-folder-name)))
-    (unless wl-init (wl))
-    ;; XXX: The imap-uw's MH folder names start with "%#".
-    (if (not (string-match "\\`\\(\\(?:%#\\)?[^#]+\\)\\(#\\(.*\\)\\)?" path))
-       (error "Error in Wanderlust link"))
-    (let ((folder (match-string 1 path))
-         (article (match-string 3 path)))
-      ;; maybe open message in namazu search folder
-      (when current-prefix-arg
-       (setq folder (concat "[" article "]"
-                            (if (and (equal current-prefix-arg '(4))
-                                     org-wl-namazu-default-index)
-                                org-wl-namazu-default-index
-                              (read-directory-name "Namazu index: ")))))
-      (if (not (elmo-folder-exists-p (with-no-warnings
-                                      (wl-folder-get-elmo-folder folder))))
-         (error "No such folder: %s" folder))
-      (let ((old-buf (current-buffer))
-           (old-point (point-marker)))
-       (wl-folder-goto-folder-subr folder)
-       (with-current-buffer old-buf
-         ;; XXX: `wl-folder-goto-folder-subr' moves point to the
-         ;; beginning of the current line.  So, restore the point
-         ;; in the old buffer.
-         (goto-char old-point))
-       (when article
-         (if (string-match-p "@" article)
-             (wl-summary-jump-to-msg-by-message-id (org-link-add-angle-brackets
-                                                    article))
-           (or (wl-summary-jump-to-msg (string-to-number article))
-               (error "No such message: %s" article)))
-         (wl-summary-redisplay))))))
-
-(provide 'ol-wl)
-
-;;; ol-wl.el ends here
diff --git a/contrib/lisp/org-annotate-file.el 
b/contrib/lisp/org-annotate-file.el
deleted file mode 100644
index e1f1f13..0000000
--- a/contrib/lisp/org-annotate-file.el
+++ /dev/null
@@ -1,157 +0,0 @@
-;;; org-annotate-file.el --- Annotate a file with org syntax
-
-;; Copyright (C) 2008-2014 Philip Jackson
-
-;; Author: Philip Jackson <phil@shellarchive.co.uk>
-;; Version: 0.2
-
-;; This file is not currently 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 2, 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 ; see the file COPYING.  If not, write to
-;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This is yet another implementation to allow the annotation of a
-;; file without modification of the file itself.  The annotation is in
-;; org syntax so you can use all of the org features you are used to.
-
-;; To use you might put the following in your .emacs:
-;;
-;; (require 'org-annotate-file)
-;; (global-set-key (kbd "C-c C-l") 'org-annotate-file) ; for example
-;;
-;; To change the location of the annotation file:
-;;
-;; (setq org-annotate-file-storage-file "~/annotated.org")
-;;
-;; Then when you visit any file and hit C-c C-l you will find yourself
-;; in an org buffer on a headline which links to the file you were
-;; visiting, e.g:
-
-;; * ~/org-annotate-file.el
-
-;; Under here you can put anything you like, save the file
-;; and next time you hit C-c C-l you will hit those notes again.
-;;
-;; To put a subheading with a text search for the current line set
-;; `org-annotate-file-add-search` to non-nil value.  Then when you hit
-;; C-c C-l (on the above line for example) you will get:
-
-;; * ~/org-annotate-file.el
-;; ** `org-annotate-file-add-search` to non-nil value.  Then when...
-
-;; Note that both of the above will be links.
-
-;;; Code:
-
-(require 'org)
-
-(defgroup org-annotate-file nil
-  "Org Annotate"
-  :group 'org)
-
-(defcustom org-annotate-file-storage-file "~/.org-annotate-file.org"
-  "File in which to keep annotations."
-  :group 'org-annotate-file
-  :type 'file)
-
-(defcustom org-annotate-file-add-search nil
-  "If non-nil, add a link as a second level to the actual file location."
-  :group 'org-annotate-file
-  :type 'boolean)
-
-(defcustom org-annotate-file-always-open t
-  "If non-nil, always expand the full tree when visiting the annotation file."
-  :group 'org-annotate-file
-  :type 'boolean)
-
-(defun org-annotate-file-ellipsify-desc (string &optional after)
-  "Return shortened STRING with appended ellipsis.
-Trim whitespace at beginning and end of STRING and replace any
-  characters that appear after the occurrence of AFTER with '...'"
-  (let* ((after (number-to-string (or after 30)))
-         (replace-map (list (cons "^[ \t]*" "")
-                            (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))
-
-;;;###autoload
-(defun org-annotate-file ()
-  "Visit `org-annotate-file-storage-file` and add a new annotation section.
-The annotation is opened at the new section which will be referencing
-the point in the current file."
-  (interactive)
-  (unless (buffer-file-name)
-    (error "This buffer has no associated file!"))
-  (switch-to-buffer
-   (org-annotate-file-show-section org-annotate-file-storage-file)))
-
-;;;###autoload
-(defun org-annotate-file-show-section (storage-file &optional annotated-buffer)
-  "Add or show annotation entry in STORAGE-FILE and return the buffer.
-The annotation will link to ANNOTATED-BUFFER if specified,
-  otherwise the current buffer is used."
-  (let ((filename (abbreviate-file-name (or annotated-buffer
-                                           (buffer-file-name))))
-        (line (buffer-substring-no-properties (point-at-bol) (point-at-eol)))
-        (annotation-buffer (find-file-noselect storage-file)))
-    (with-current-buffer annotation-buffer
-      (org-annotate-file-annotate filename line))
-    annotation-buffer))
-
-(defun org-annotate-file-annotate (filename line)
-  "Add annotation for FILENAME at LINE using current buffer."
-  (let* ((link (org-make-link-string (concat "file:" filename) filename))
-         (search-link (org-make-link-string
-                       (concat "file:" filename "::" line)
-                      (org-annotate-file-ellipsify-desc line))))
-    (unless (eq major-mode 'org-mode)
-      (org-mode))
-    (goto-char (point-min))
-    (widen)
-    (when org-annotate-file-always-open
-      (show-all))
-    (unless (search-forward-regexp
-            (concat "^* " (regexp-quote link)) nil t)
-      (org-annotate-file-add-upper-level link))
-    (beginning-of-line)
-    (org-narrow-to-subtree)
-    ;; deal with a '::' search if need be
-    (when org-annotate-file-add-search
-      (unless (search-forward-regexp
-              (concat "^** " (regexp-quote search-link)) nil t)
-       (org-annotate-file-add-second-level search-link)))))
-
-(defun org-annotate-file-add-upper-level (link)
-  "Add and link heading to LINK."
-  (goto-char (point-min))
-  (call-interactively 'org-insert-heading)
-  (insert link))
-
-(defun org-annotate-file-add-second-level (link)
-  "Add and link subheading to LINK."
-  (goto-char (point-at-eol))
-  (call-interactively 'org-insert-subheading)
-  (insert link))
-
-(provide 'org-annotate-file)
-
-;;; org-annotate-file.el ends here
diff --git a/contrib/lisp/org-attach-embedded-images.el 
b/contrib/lisp/org-attach-embedded-images.el
deleted file mode 100644
index adbbfba..0000000
--- a/contrib/lisp/org-attach-embedded-images.el
+++ /dev/null
@@ -1,131 +0,0 @@
-;;; org-attach-embedded-images.el --- Transmute images to attachments
-;;
-;; Copyright 2018-2021 Free Software Foundation, Inc.
-;;
-;; Author: Marco Wahl
-;; Version: 0.1
-;; Keywords: org, media
-;;
-;; This file is not 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, 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:
-;;
-;; There are occasions when images are displayed in a subtree which
-;; are not org attachments.  For example if you copy and paste a part
-;; of a web page (containing images) from eww to an org subtree.
-
-;; This module provides command `org-attach-embedded-images-in-subtree'
-;; to save such images as attachments and insert org links to them.
-
-;; Install:
-
-;; To use this module insert it to `org-modules'.  The insert can be
-;; performed via {M-x customize-variable RET org-modules RET} followed
-;; by insertion of `org-attach-embedded-images' to the external
-;; modules section.
-
-;; Alternatively you can add the line
-
-;; (require 'org-attach-embedded-images)
-
-;; to your emacs configuration.
-
-;; Use
-
-;;     M-x org-attach-embedded-images-in-subtree
-
-;; in a subtree with embedded images.  The images get attached and can
-;; later be reviewed.
-
-;; Note: Possibly
-
-;;     M-x org-toggle-inline-images
-
-;; is needed to see the images in the Org mode window.
-
-
-;; Code:
-
-(require 'org)
-(require 'org-attach)
-
-
-;; Auxiliary functions
-
-(defun org-attach-embedded-images--next-property-display-data (position limit)
-  "Return position of the next property-display location with image data.
-Return nil if there is no next display property.
-POSITION and LIMIT as in `next-single-property-change'."
-  (let ((pos (next-single-property-change position 'display nil limit)))
-    (while (and (< pos limit)
-               (let ((display-prop
-                      (plist-get (text-properties-at pos) 'display)))
-                 (or (not display-prop)
-                     (not (plist-get (cdr display-prop) :data)))))
-      (setq pos (next-single-property-change pos 'display nil limit)))
-    pos))
-
-(defun org-attach-embedded-images--attach-with-sha1-name (data)
-  "Save the image given as DATA as org attachment with its sha1 as name.
-Return the filename."
-  (let* ((extension (symbol-name (image-type-from-data data)))
-         (basename (concat (sha1 data) "." extension))
-        (dir (org-attach-dir t))
-         (filename (concat dir "/" basename)))
-    (unless (file-exists-p filename)
-      (with-temp-file filename
-        (setq buffer-file-coding-system 'binary)
-        (set-buffer-multibyte nil)
-        (insert data)))
-    (org-attach-sync)
-    basename))
-
-
-;; Command
-
-;;;###autoload
-(defun org-attach-embedded-images-in-subtree ()
-  "Save the displayed images as attachments and insert links to them."
-  (interactive)
-  (when (org-before-first-heading-p)
-    (user-error "Before first heading.  Nothing has been attached."))
-  (save-excursion
-    (org-attach-dir t)
-    (let ((beg (progn (org-back-to-heading) (point)))
-          (end (progn (org-end-of-subtree) (point)))
-         names)
-      ;; pass 1
-      (goto-char beg)
-      (while (< (goto-char 
(org-attach-embedded-images--next-property-display-data (point) end)) end)
-       (let ((data (plist-get (cdr (plist-get (text-properties-at (point)) 
'display)) :data)))
-         (assert data)
-         (push (org-attach-embedded-images--attach-with-sha1-name data)
-               names)))
-      ;; pass 2
-      (setq names (nreverse names))
-      (goto-char beg)
-      (while names
-       (goto-char (org-attach-embedded-images--next-property-display-data 
(point) end))
-        (while (get-text-property (point) 'display)
-         (goto-char (next-property-change (point) nil end)))
-        (skip-chars-forward "]")
-        (insert (concat "\n[[attachment:" (pop names) "]]"))))))
-
-
-(provide 'org-attach-embedded-images)
-
-
-;;; org-attach-embedded-images.el ends here
diff --git a/contrib/lisp/org-bibtex-extras.el 
b/contrib/lisp/org-bibtex-extras.el
deleted file mode 100644
index 8c62ef7..0000000
--- a/contrib/lisp/org-bibtex-extras.el
+++ /dev/null
@@ -1,137 +0,0 @@
-;;; org-bibtex-extras --- extras for working with org-bibtex entries
-
-;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
-
-;; Author: Eric Schulte <eric dot schulte at gmx dot com>
-;; Keywords: outlines, hypermedia, bibtex, d3
-;; Homepage: https://orgmode.org
-;; Version: 0.01
-
-;; This file is not yet 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, 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:
-
-;; Warning: This should certainly be considered EXPERIMENTAL and still
-;;          in development, feedback is welcome, but don't expect it
-;;          to work.
-
-;; This file add some extra functionality to your bibtex entries which
-;; are stored as Org-mode headlines using org-bibtex.el.  Most
-;; features expect that you keep all of your reading notes in a single
-;; file, set the `obe-bibtex-file' variable to the path to this file.
-;;
-;; - d3 view :: d3 is a Javascript library which supports interactive
-;;              display of graphs.  To view your citations as a d3
-;;              graph, execute the following which will create a .json
-;;              export of your references file, then grab a copy of
-;;              d3, edit examples/force/force.js to replace
-;;
-;;                var source`"miserables.json";
-;;
-;;              with
-;;
-;;                var source`"your-references.json";
-;;
-;;              then view examples/force/force.html in your browser.
-;;
-;; - HTML export :: Customize the `obe-html-link-base' variable so
-;;                  that it points to an html export of your
-;;                  references, then add the following to your html
-;;                  export hook, and citations will be resolved during
-;;                  html export.
-;;
-;;      (add-hook 'org-export-first-hook
-;;               (lambda ()
-;;                 (when (equal org-export-current-backend 'html)
-;;                   (obe-html-export-citations))))
-
-;;; Code:
-(require 'ol-bibtex)
-
-(declare-function org-trim "org" (s &optional keep-lead))
-
-(defcustom obe-bibtex-file nil "File holding bibtex entries.")
-
-(defcustom obe-html-link-base nil
-  "Base of citation links.
-For example, to point to your `obe-bibtex-file' use the following.
-
-  (setq obe-html-link-base (format \"file:%s\" obe-bibtex-file))
-")
-
-(defvar obe-citations nil)
-(defun obe-citations ()
-  "Return all citations from `obe-bibtex-file'."
-  (or obe-citations
-      (save-window-excursion
-       (find-file (or obe-bibtex-file
-                      (error "`obe-bibtex-file' has not been configured")))
-       (goto-char (point-min))
-       (while (re-search-forward "  :CUSTOM_ID: \\(.+\\)$" nil t)
-         (push (org-no-properties (match-string 1))
-               obe-citations))
-       obe-citations)))
-
-(defun obe-html-export-citations ()
-  "Convert all \\cite{...} citations in the current file into HTML links."
-  (save-excursion
-    (goto-char (point-min))
-    (while (re-search-forward "\\\\cite{\\([^\000}]+\\)}" nil t)
-      (replace-match
-       (save-match-data
-        (mapconcat (lambda (c) (format "[[%s#%s][%s]]" obe-html-link-base c c))
-                   (mapcar #'org-trim
-                           (split-string (match-string 1) ",")) ", "))))))
-
-(defun obe-meta-to-json (meta &optional fields)
-  "Turn a list of META data from citations into a string of json."
-  (let ((counter 1) nodes links)
-    (flet ((id (it) (position it nodes :test #'string= :key #'car))
-          (col (k) (mapcar (lambda (r) (cdr (assoc k r))) meta))
-          (add (lst)
-               (dolist (el lst) (push (cons el counter) nodes))
-               (incf counter)))
-      ;; build the nodes of the graph
-      (add (col :title))
-      (add (remove-if (lambda (author) (string-match "others" author))
-                     (remove-duplicates (apply #'append (col :authors))
-                                        :test #'string=)))
-      (dolist (field fields)
-       (add (remove-duplicates (col field) :test #'string=)))
-      ;; build the links in the graph
-      (dolist (citation meta)
-        (let ((dest (id (cdr (assq :title citation)))))
-          (dolist (author (mapcar #'id (cdr (assq :authors citation))))
-            (when author (push (cons author dest) links)))
-          (let ((jid (id (cdr (assq :journal citation)))))
-            (when jid (push (cons jid dest) links)))
-          (let ((cid (id (cdr (assq :category citation)))))
-            (when cid (push (cons cid dest) links)))))
-      ;; build the json string
-      (format "{\"nodes\":[%s],\"links\":[%s]}"
-             (mapconcat
-              (lambda (pair)
-                (format "{\"name\":%S,\"group\":%d}"
-                        (car pair) (cdr pair)))
-              nodes ",")
-             (mapconcat
-              (lambda (link)
-                (format "{\"source\":%d,\"target\":%d,\"value\":1}"
-                        (car link) (cdr link)))
-              (meta-to-links meta nodes) ",")))))
-
-(provide 'org-bibtex-extras)
-;;; org-bibtex-extras ends here
diff --git a/contrib/lisp/org-checklist.el b/contrib/lisp/org-checklist.el
deleted file mode 100644
index 2bc00c0..0000000
--- a/contrib/lisp/org-checklist.el
+++ /dev/null
@@ -1,141 +0,0 @@
-;;; org-checklist.el --- org functions for checklist handling
-
-;; Copyright (C) 2008-2014 James TD Smith
-
-;; Author: James TD Smith (@ ahktenzero (. mohorovi cc))
-;; Version: 1.0
-;; Keywords: org, checklists
-;;
-;; This file is not 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, 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:
-
-;; This file provides some functions for handing repeated tasks which involve
-;; checking off a list of items. By setting the RESET_CHECK_BOXES property in 
an
-;; item, when the TODO state is set to done all checkboxes under that item are
-;; cleared. If the LIST_EXPORT_BASENAME property is set, a file will be created
-;; using the value of that property plus a timestamp, containing all the items
-;; in the list which are not checked. Additionally the user will be prompted to
-;; print the list.
-;;
-;; I use this for to keep track of stores of various things (food stores,
-;; components etc) which I check periodically and use the exported list of 
items
-;; which are not present as a shopping list.
-;;
-;;; Usage:
-;; (require 'org-checklist)
-;;
-;; Set the RESET_CHECK_BOXES and LIST_EXPORT_BASENAME properties in items as
-;; needed.
-;;
-;;; Code:
-(require 'org)
-(load "a2ps-print" 'no-error)
-
-(setq org-default-properties (cons "RESET_CHECK_BOXES" (cons 
"LIST_EXPORT_BASENAME" org-default-properties)))
-
-(defgroup org-checklist nil
-  "Extended checklist handling for org"
-  :tag "Org-checklist"
-  :group 'org)
-
-(defcustom org-checklist-export-time-format "%Y%m%d%H%M"
-  "The format of timestamp appended to LIST_EXPORT_BASENAME to
-  make the name of the export file."
-  :link '(function-link format-time-string)
-  :group 'org-checklist
-  :type 'string)
-
-(defcustom org-checklist-export-function 'org-export-as-ascii
-  "function used to prepare the export file for printing"
-  :group 'org-checklist
-  :type '(radio (function-item :tag "ascii text" org-export-as-ascii)
-               (function-item :tag "HTML"  org-export-as-html)
-               (function-item :tag "LaTeX" :value org-export-as-latex)
-               (function-item :tag "XOXO" :value org-export-as-xoxo)))
-
-(defcustom org-checklist-export-params nil
-  "options for the export function file for printing"
-  :group 'org-checklist
-  :type '(repeat string))
-
-(defcustom org-checklist-a2ps-params nil
-  "options for a2ps for printing"
-  :group 'org-checklist
-  :type '(repeat string))
-
-(defun org-reset-checkbox-state-maybe ()
-  "Reset all checkboxes in an entry if the `RESET_CHECK_BOXES' property is set"
-  (interactive "*")
-  (if (org-entry-get (point) "RESET_CHECK_BOXES")
-      (org-reset-checkbox-state-subtree)))
-
-
-(defun org-make-checklist-export ()
-  "Produce a checklist containing all unchecked items from a list
-of checkbox items"
-  (interactive "*")
-  (if (org-entry-get (point) "LIST_EXPORT_BASENAME")
-      (let* ((export-file (concat (org-entry-get (point) 
"LIST_EXPORT_BASENAME" nil)
-                                 "-" (format-time-string
-                                      org-checklist-export-time-format)
-                                 ".org"))
-            (print (case (org-entry-get (point) "PRINT_EXPORT" nil)
-                     (("" "nil" nil) nil)
-                     (t t)
-                     (nil (y-or-n-p "Print list? "))))
-            exported-lines
-            (title "Checklist export"))
-       (save-restriction
-         (save-excursion
-           (org-narrow-to-subtree)
-           (org-update-checkbox-count-maybe)
-           (org-show-subtree)
-           (goto-char (point-min))
-           (when (looking-at org-complex-heading-regexp)
-             (setq title (match-string 4)))
-           (goto-char (point-min))
-           (let ((end (point-max)))
-             (while (< (point) end)
-               (when (and (org-at-item-checkbox-p)
-                          (or (string= (match-string 0) "[ ]")
-                              (string= (match-string 0) "[-]")))
-                 (add-to-list 'exported-lines (thing-at-point 'line) t))
-               (beginning-of-line 2)))
-           (set-buffer (get-buffer-create export-file))
-           (org-insert-heading)
-           (insert (or title export-file) "\n")
-           (dolist (entry exported-lines) (insert entry))
-           (org-update-checkbox-count-maybe)
-           (write-file export-file)
-           (if (print)
-               (progn (funcall org-checklist-export-function
-                               org-checklist-export-params)
-                      (let* ((current-a2ps-switches a2ps-switches)
-                             (a2ps-switches (append current-a2ps-switches
-                                                    
org-checklist-a2ps-params)))
-                        (a2ps-buffer)))))))))
-
-(defun org-checklist ()
-  (when (member org-state org-done-keywords) ;; org-state dynamically bound in 
org.el/org-todo
-    (org-make-checklist-export)
-    (org-reset-checkbox-state-maybe)))
-
-(add-hook 'org-after-todo-state-change-hook 'org-checklist)
-
-(provide 'org-checklist)
-
-;;; org-checklist.el ends here
diff --git a/contrib/lisp/org-choose.el b/contrib/lisp/org-choose.el
deleted file mode 100644
index c791a86..0000000
--- a/contrib/lisp/org-choose.el
+++ /dev/null
@@ -1,496 +0,0 @@
-;;; org-choose.el --- decision management for org-mode
-
-;; Copyright (C) 2009-2014 Tom Breton (Tehom)
-
-;; This file is not part of GNU Emacs.
-
-;; Author: Tom Breton (Tehom)
-;; Keywords: outlines, convenience
-
-;; This file 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 2, or (at your option)
-;; any later version.
-
-;; This file 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., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This is code to support decision management.  It lets you treat a
-;; group of sibling items in org-mode as alternatives in a decision.
-
-;; There are no user commands in this file.  You use it by:
-;;   * Loading it (manually or by M-x customize-apropos org-modules)
-
-;;   * Setting up at least one set of TODO keywords with the
-;;     interpretation "choose" by either:
-
-;;     * Using the file directive #+CHOOSE_TODO:
-
-;;       * For instance, "#+CHOOSE_TODO: NO(,-) MAYBE(,0) YES"
-
-;;     * Or by M-x customize-apropos org-todo-keywords
-
-;;   * Operating on single items with the TODO commands.
-
-;;     * Use C-S-right to change the keyword set.  Use this to change to
-;;       the "choose" keyword set that you just defined.
-
-;;     * Use S-right to advance the TODO mark to the next setting.
-
-;;       For "choose", that means you like this alternative more than
-;;       before.  Other alternatives will be automatically demoted to
-;;       keep your settings consistent.
-
-;;     * Use S-left to demote TODO to the previous setting.
-
-;;       For "choose", that means you don't like this alternative as much
-;;       as before.  Other alternatives will be automatically promoted,
-;;       if this item was all that was keeping them down.
-
-;;     * All the other TODO commands are available and behave essentially
-;;       the normal way.
-
-;;; Requires
-
-(require 'org)
-                                       ;(eval-when-compile
-                                       ;   (require 'cl))
-(require 'cl)
-
-;;; Body
-;;; The variables
-
-(defstruct (org-choose-mark-data. (:type list))
-  "The format of an entry in org-choose-mark-data.
-Indexes are 0-based or `nil'.
-"
-  keyword
-  bot-lower-range
-  top-upper-range
-  range-length
-  static-default
-  all-keywords)
-
-(defvar org-choose-mark-data
-  ()
-  "Alist of information for choose marks.
-
-Each entry is an `org-choose-mark-data.'" )
-(make-variable-buffer-local 'org-choose-mark-data)
-;;;_ , For setup
-;;;_  . org-choose-filter-one
-
-(defun org-choose-filter-one (i)
-  "Return a list of
- * a canonized version of the string
- * optionally one symbol"
-
-  (if
-      (not
-       (string-match "(.*)" i))
-      (list i i)
-    (let*
-       (
-        (end-text (match-beginning 0))
-        (vanilla-text (substring i 0 end-text))
-        ;;Get the parenthesized part.
-        (match (match-string 0 i))
-        ;;Remove the parentheses.
-        (args (substring match 1 -1))
-        ;;Split it
-        (arglist
-         (let
-             ((arglist-x (org-split-string args ",")))
-           ;;When string starts with "," `split-string' doesn't
-           ;;make a first arg, so in that case make one
-           ;;manually.
-           (if
-               (string-match "^," args)
-               (cons nil arglist-x)
-             arglist-x)))
-        (decision-arg (second arglist))
-        (type
-         (cond
-          ((string= decision-arg "0")
-           'default-mark)
-          ((string= decision-arg "+")
-           'top-upper-range)
-          ((string= decision-arg "-")
-           'bot-lower-range)
-          (t nil)))
-        (vanilla-arg (first arglist))
-        (vanilla-mark
-         (if vanilla-arg
-             (concat vanilla-text "("vanilla-arg")")
-           vanilla-text)))
-      (if type
-         (list vanilla-text vanilla-mark type)
-       (list vanilla-text vanilla-mark)))))
-
-;;;_  . org-choose-setup-vars
-(defun org-choose-setup-vars (bot-lower-range top-upper-range
-                                             static-default num-items 
all-mark-texts)
-  "Add to org-choose-mark-data according to arguments"
-  (let*
-      ((tail
-       ;;If there's no bot-lower-range or no default, we don't
-       ;;have ranges.
-       (cdr
-        (if (and static-default bot-lower-range)
-            (let*
-                ;;If there's no top-upper-range, use the last
-                ;;item.
-                ((top-upper-range
-                  (or top-upper-range (1- num-items)))
-                 (lower-range-length
-                  (1+ (- static-default bot-lower-range)))
-                 (upper-range-length
-                  (- top-upper-range static-default))
-                 (range-length
-                  (min upper-range-length lower-range-length)))
-              (make-org-choose-mark-data.
-               :keyword nil
-               :bot-lower-range bot-lower-range
-               :top-upper-range top-upper-range
-               :range-length    range-length
-               :static-default static-default
-               :all-keywords all-mark-texts))
-          (make-org-choose-mark-data.
-           :keyword nil
-           :bot-lower-range nil
-           :top-upper-range nil
-           :range-length    nil
-           :static-default (or static-default 0)
-           :all-keywords all-mark-texts)))))
-    (dolist (text all-mark-texts)
-      (pushnew (cons text tail)
-              org-choose-mark-data
-              :test
-              #'(lambda (a b)
-                  (equal (car a) (car b)))))))
-
-;;; org-choose-filter-tail
-(defun org-choose-filter-tail (raw)
-  "Return a translation of RAW to vanilla and set appropriate
-buffer-local variables.
-
-RAW is a list of strings representing the input text of a choose
-interpretation."
-  (let
-      ((vanilla-list nil)
-       (all-mark-texts nil)
-       (index 0)
-       bot-lower-range top-upper-range range-length static-default)
-    (dolist (i raw)
-      (destructuring-bind
-         (vanilla-text vanilla-mark &optional type)
-         (org-choose-filter-one i)
-       (cond
-        ((eq type 'bot-lower-range)
-         (setq bot-lower-range index))
-        ((eq type 'top-upper-range)
-         (setq top-upper-range index))
-        ((eq type 'default-mark)
-         (setq static-default index)))
-       (incf index)
-       (push vanilla-text all-mark-texts)
-       (push vanilla-mark vanilla-list)))
-
-    (org-choose-setup-vars bot-lower-range top-upper-range
-                          static-default index (reverse all-mark-texts))
-    (nreverse vanilla-list)))
-
-;;; org-choose-setup-filter
-
-(defun org-choose-setup-filter (raw)
-  "A setup filter for choose interpretations."
-  (when (eq (car raw) 'choose)
-    (cons
-     'choose
-     (org-choose-filter-tail (cdr raw)))))
-
-;;; org-choose-conform-after-promotion
-(defun org-choose-conform-after-promotion (entry-pos keywords highest-ok-ix)
-  "Conform the current item after another item was promoted"
-  (unless
-      ;;Skip the entry that triggered this by skipping any entry with
-      ;;the same starting position.  plist uses the start of the
-      ;;header line as the position, but map no longer does, so we
-      ;;have to go back to the heading.
-      (=
-       (save-excursion
-        (org-back-to-heading)
-        (point))
-       entry-pos)
-    (let
-       ((ix
-         (org-choose-get-entry-index keywords)))
-      ;;If the index of the entry exceeds the highest allowable
-      ;;index, change it to that.
-      (when (and ix
-                (> ix highest-ok-ix))
-       (org-todo
-        (nth highest-ok-ix keywords))))))
-;;;_  . org-choose-conform-after-demotion
-(defun org-choose-conform-after-demotion (entry-pos keywords
-                                                   raise-to-ix
-                                                   old-highest-ok-ix)
-  "Conform the current item after another item was demoted."
-  (unless
-      ;;Skip the entry that triggered this.
-      (=
-       (save-excursion
-        (org-back-to-heading)
-        (point))
-       entry-pos)
-    (let
-       ((ix
-         (org-choose-get-entry-index keywords)))
-      ;;If the index of the entry was at or above the old allowable
-      ;;position, change it to the new mirror position if there is
-      ;;one.
-      (when (and
-            ix
-            raise-to-ix
-            (>= ix old-highest-ok-ix))
-       (org-todo
-        (nth raise-to-ix keywords))))))
-
-;;; org-choose-keep-sensible (the org-trigger-hook function)
-(defun org-choose-keep-sensible (change-plist)
-  "Bring the other items back into a sensible state after an item's
-setting was changed."
-  (let*
-      (  (from (plist-get change-plist :from))
-        (to (plist-get change-plist :to))
-        (entry-pos
-         (set-marker
-          (make-marker)
-          (plist-get change-plist :position)))
-        (kwd-data
-         (assoc to org-todo-kwd-alist)))
-    (when
-       (eq (nth 1 kwd-data) 'choose)
-      (let*
-         (
-          (data
-           (assoc to org-choose-mark-data))
-          (keywords
-           (org-choose-mark-data.-all-keywords data))
-          (old-index
-           (org-choose-get-index-in-keywords
-            from
-            keywords))
-          (new-index
-           (org-choose-get-index-in-keywords
-            to
-            keywords))
-          (highest-ok-ix
-           (org-choose-highest-other-ok
-            new-index
-            data))
-          (funcdata
-           (cond
-            ;;The entry doesn't participate in conformance,
-            ;;so give `nil' which does nothing.
-            ((not highest-ok-ix) nil)
-            ;;The entry was created or promoted
-            ((or
-              (not old-index)
-              (> new-index old-index))
-             (list
-              #'org-choose-conform-after-promotion
-              entry-pos keywords
-              highest-ok-ix))
-            (t ;;Otherwise the entry was demoted.
-             (let
-                 (
-                  (raise-to-ix
-                   (min
-                    highest-ok-ix
-                    (org-choose-mark-data.-static-default
-                     data)))
-                  (old-highest-ok-ix
-                   (org-choose-highest-other-ok
-                    old-index
-                    data)))
-               (list
-                #'org-choose-conform-after-demotion
-                entry-pos
-                keywords
-                raise-to-ix
-                old-highest-ok-ix))))))
-       (if funcdata
-           ;;The funny-looking names are to make variable capture
-           ;;unlikely.  (Poor-man's lexical bindings).
-           (destructuring-bind (func-d473 . args-46k) funcdata
-             (let
-                 ((map-over-entries
-                   (org-choose-get-fn-map-group))
-                  ;;We may call `org-todo', so let various hooks
-                  ;;`nil' so we don't cause loops.
-                  org-after-todo-state-change-hook
-                  org-trigger-hook
-                  org-blocker-hook
-                  org-todo-get-default-hook
-                  ;;Also let this alist `nil' so we don't log
-                  ;;secondary transitions.
-                  org-todo-log-states)
-               ;;Map over group
-               (funcall map-over-entries
-                        #'(lambda ()
-                            (apply func-d473 args-46k))))))))
-    ;;Remove the marker
-    (set-marker entry-pos nil)))
-
-;;; Getting the default mark
-;;; org-choose-get-index-in-keywords
-(defun org-choose-get-index-in-keywords (ix all-keywords)
-  "Return the index of the current entry."
-  (if ix
-      (position ix all-keywords
-               :test #'equal)))
-
-;;; org-choose-get-entry-index
-(defun org-choose-get-entry-index (all-keywords)
-  "Return index of current entry."
-  (let*
-      ((state (org-entry-get (point) "TODO")))
-    (org-choose-get-index-in-keywords state all-keywords)))
-
-;;; org-choose-get-fn-map-group
-
-(defun org-choose-get-fn-map-group ()
-  "Return a function to map over the group"
-  #'(lambda (fn)
-      (require 'org-agenda) ;; `org-map-entries' seems to need it.
-      (save-excursion
-       (unless (org-up-heading-safe)
-         (error "Choosing is only supported between siblings in a tree, not on 
top level"))
-       (let
-           ((level (org-reduced-level (org-outline-level))))
-         (save-restriction
-           (org-map-entries
-            fn
-            (format "LEVEL=%d" level)
-            'tree))))))
-
-;;; org-choose-get-highest-mark-index
-
-(defun org-choose-get-highest-mark-index (keywords)
-  "Get the index of the highest current mark in the group.
-If there is none, return 0"
-  (let*
-      ;;Func maps over applicable entries.
-      ((map-over-entries
-       (org-choose-get-fn-map-group))
-       (indexes-list
-       (remove nil
-               (funcall map-over-entries
-                        #'(lambda ()
-                            (org-choose-get-entry-index keywords))))))
-    (if
-       indexes-list
-       (apply #'max indexes-list)
-      0)))
-
-;;; org-choose-highest-ok
-
-(defun org-choose-highest-other-ok (ix data)
-  "Return the highest index that any choose mark can sensibly have,
-given that another mark has index IX.
-DATA must be a `org-choose-mark-data.'."
-  (let
-      ((bot-lower-range
-       (org-choose-mark-data.-bot-lower-range data))
-       (top-upper-range
-       (org-choose-mark-data.-top-upper-range data))
-       (range-length
-       (org-choose-mark-data.-range-length data)))
-    (when (and ix bot-lower-range)
-      (let*
-         ((delta
-           (- top-upper-range ix)))
-       (unless
-           (< range-length delta)
-         (+ bot-lower-range delta))))))
-
-;;; org-choose-get-default-mark-index
-
-(defun org-choose-get-default-mark-index (data)
-  "Return the index of the default mark in a choose interpretation.
-
-DATA must be a `org-choose-mark-data.'."
-  (or
-   (let
-       ((highest-mark-index
-        (org-choose-get-highest-mark-index
-         (org-choose-mark-data.-all-keywords data))))
-     (org-choose-highest-other-ok
-      highest-mark-index data))
-   (org-choose-mark-data.-static-default data)))
-
-;;; org-choose-get-mark-N
-(defun org-choose-get-mark-N (n data)
-  "Get the text of the nth mark in a choose interpretation."
-
-  (let*
-      ((l (org-choose-mark-data.-all-keywords data)))
-    (nth n l)))
-
-;;; org-choose-get-default-mark
-
-(defun org-choose-get-default-mark (new-mark old-mark)
-  "Get the default mark IFF in a choose interpretation.
-NEW-MARK and OLD-MARK are the text of the new and old marks."
-  (let*
-      ((old-kwd-data
-       (assoc old-mark org-todo-kwd-alist))
-       (new-kwd-data
-       (assoc new-mark org-todo-kwd-alist))
-       (becomes-choose
-       (and
-        (or
-         (not old-kwd-data)
-         (not
-          (eq (nth 1 old-kwd-data) 'choose)))
-        (eq (nth 1 new-kwd-data) 'choose))))
-    (when
-       becomes-choose
-      (let
-         ((new-mark-data
-           (assoc new-mark org-choose-mark-data)))
-       (if
-           new-mark
-           (org-choose-get-mark-N
-            (org-choose-get-default-mark-index
-             new-mark-data)
-            new-mark-data)
-         (error "Somehow got an unrecognizable mark"))))))
-
-;;; Setting it all up
-
-(eval-after-load 'org
-  '(progn
-     (add-to-list 'org-todo-setup-filter-hook
-                 #'org-choose-setup-filter)
-     (add-to-list 'org-todo-get-default-hook
-                 #'org-choose-get-default-mark)
-     (add-to-list 'org-trigger-hook
-                 #'org-choose-keep-sensible)
-     (add-to-list 'org-todo-interpretation-widgets
-                 '(:tag "Choose   (to record decisions)" choose)
-                 'append)))
-
-(provide 'org-choose)
-
-;;; org-choose.el ends here
diff --git a/contrib/lisp/org-collector.el b/contrib/lisp/org-collector.el
deleted file mode 100644
index ace6313..0000000
--- a/contrib/lisp/org-collector.el
+++ /dev/null
@@ -1,232 +0,0 @@
-;;; org-collector --- collect properties into tables
-
-;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
-
-;; Author: Eric Schulte <schulte dot eric at gmail dot com>
-;; Keywords: outlines, hypermedia, calendar, wp, experimentation,
-;;           organization, properties
-;; Homepage: https://orgmode.org
-;; Version: 0.01
-
-;; This file is not yet 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, 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:
-
-;; Pass in an alist of columns, each column can be either a single
-;; property or a function which takes column names as arguments.
-;;
-;; For example the following propview block would collect the value of
-;; the 'amount' property from each header in the current buffer
-;;
-;; #+BEGIN: propview :cols (ITEM amount)
-;; | "ITEM"              | "amount" |
-;; |---------------------+----------|
-;; | "December Spending" |        0 |
-;; | "Grocery Store"     |    56.77 |
-;; | "Athletic club"     |     75.0 |
-;; | "Restaurant"        |    30.67 |
-;; | "January Spending"  |        0 |
-;; | "Athletic club"     |     75.0 |
-;; | "Restaurant"        |    50.00 |
-;; |---------------------+----------|
-;; |                     |          |
-;; #+END:
-;;
-;; This slightly more selective propview block will limit those
-;; headers included to those in the subtree with the id 'december'
-;; in which the spendtype property is equal to "food"
-;;
-;; #+BEGIN: propview :id "december" :conds ((string= spendtype "food")) :cols 
(ITEM amount)
-;; | "ITEM"          | "amount" |
-;; |-----------------+----------|
-;; | "Grocery Store" |    56.77 |
-;; | "Restaurant"    |    30.67 |
-;; |-----------------+----------|
-;; |                 |          |
-;; #+END:
-;;
-;; Org Collector allows arbitrary processing of the property values
-;; through elisp in the cols: property.  This allows for both simple
-;; computations as in the following example
-;;
-;; #+BEGIN: propview :id "results" :cols (ITEM f d list (apply '+ list) (+ f 
d))
-;; | "ITEM" | "f" | "d" | "list"                  | "(apply (quote +) list)" | 
"(+ f d)" |
-;; 
|--------+-----+-----+-------------------------+--------------------------+-----------|
-;; | "run1" |   2 |  33 | (quote (9 2 3 4 5 6 7)) | 36                       | 
       35 |
-;; | "run2" |   2 |  34 | :na                     | :na                      | 
       36 |
-;; | "run3" |   2 |  35 | :na                     | :na                      | 
       37 |
-;; | "run4" |   2 |  36 | :na                     | :na                      | 
       38 |
-;; |        |     |     |                         |                          | 
          |
-;; #+END:
-;;
-;; or more complex computations as in the following example taken from
-;; an org file where each header in "results" subtree contained a
-;; property "sorted_hits" which was passed through the
-;; "average-precision" elisp function
-;;
-;; #+BEGIN: propview :id "results" :cols (ITEM (average-precision sorted_hits))
-;; | "ITEM"    | "(average-precision sorted_hits)" |
-;; |-----------+-----------------------------------|
-;; | run (80)  |                          0.105092 |
-;; | run (70)  |                          0.108142 |
-;; | run (10)  |                          0.111348 |
-;; | run (60)  |                          0.113593 |
-;; | run (50)  |                          0.116446 |
-;; | run (100) |                          0.118863 |
-;; #+END:
-;;
-
-;;; Code:
-(require 'org)
-(require 'org-table)
-
-(defvar org-propview-default-value 0
-  "Default value to insert into the propview table when the no
-value is calculated either through lack of required variables for
-a column, or through the generation of an error.")
-
-(defun and-rest (list)
-  (if (listp list)
-      (if (> (length list) 1)
-         (and (car list) (and-rest (cdr list)))
-       (car list))
-    list))
-
-(put 'org-collector-error
-     'error-conditions
-     '(error column-prop-error org-collector-error))
-
-(defun org-dblock-write:propview (params)
-  "collect the column specification from the #+cols line
-preceding the dblock, then update the contents of the dblock."
-  (interactive)
-  (condition-case er
-      (let ((cols (plist-get params :cols))
-           (inherit (plist-get params :inherit))
-           (conds (plist-get params :conds))
-           (match (plist-get params :match))
-           (scope (plist-get params :scope))
-           (noquote (plist-get params :noquote))
-           (colnames (plist-get params :colnames))
-           (defaultval (plist-get params :defaultval))
-           (content-lines (org-split-string (plist-get params :content) "\n"))
-           id table line pos)
-       (save-excursion
-         (when (setq id (plist-get params :id))
-           (cond ((not id) nil)
-                 ((eq id 'global) (goto-char (point-min)))
-                 ((eq id 'local)  nil)
-                 ((setq idpos (org-find-entry-with-id id))
-                  (goto-char idpos))
-                 (t (error "Cannot find entry with :ID: %s" id))))
-         (unless (eq id 'global) (org-narrow-to-subtree))
-         (setq stringformat (if noquote "%s" "%S"))
-         (let ((org-propview-default-value (if defaultval defaultval 
org-propview-default-value)))
-           (setq table (org-propview-to-table
-                        (org-propview-collect cols stringformat conds match 
scope inherit
-                                              (if colnames colnames cols)) 
stringformat)))
-         (widen))
-       (setq pos (point))
-       (when content-lines
-         (while (string-match "^#" (car content-lines))
-           (insert (pop content-lines) "\n")))
-       (insert table) (insert "\n|--") (org-cycle) (move-end-of-line 1)
-       (message (format "point-%d" pos))
-       (while (setq line (pop content-lines))
-         (when (string-match "^#" line)
-           (insert "\n" line)))
-       (goto-char pos)
-       (org-table-recalculate 'all))
-    (org-collector-error (widen) (error "%s" er))
-    (error (widen) (error "%s" er))))
-
-(defun org-propview-eval-w-props (props body)
-  "evaluate the BODY-FORMS binding the variables using the
-variables and values specified in props"
-  (condition-case nil ;; catch any errors
-      (eval `(let ,(mapcar
-                   (lambda (pair) (list (intern (car pair)) (cdr pair)))
-                   props)
-              ,body))
-    (error nil)))
-
-(defun org-propview-get-with-inherited (&optional inherit)
-  (append
-   (org-entry-properties)
-   (delq nil
-        (mapcar (lambda (i)
-                  (let* ((n (symbol-name i))
-                         (p (org-entry-get (point) n 'do-inherit)))
-                    (when p (cons n p))))
-                inherit))))
-
-(defun org-propview-collect (cols stringformat &optional conds match scope 
inherit colnames)
-  (interactive)
-  ;; collect the properties from every header
-  (let* ((header-props
-         (let ((org-trust-scanner-tags t) alst)
-           (org-map-entries
-            (quote (cons (cons "ITEM" (org-get-heading t))
-                         (org-propview-get-with-inherited inherit)))
-            match scope)))
-        ;; read property values
-        (header-props
-         (mapcar (lambda (props)
-                   (mapcar (lambda (pair)
-                             (let ((inhibit-lisp-eval (string= (car pair) 
"ITEM")))
-                               (cons (car pair) (org-babel-read (cdr pair) 
inhibit-lisp-eval))))
-                           props))
-                 header-props))
-        ;; collect all property names
-        (prop-names
-         (mapcar 'intern (delete-dups
-                          (apply 'append (mapcar (lambda (header)
-                                                   (mapcar 'car header))
-                                                 header-props))))))
-    (append
-     (list
-      (if colnames colnames (mapcar (lambda (el) (format stringformat el)) 
cols))
-       'hline) ;; ------------------------------------------------
-     (mapcar ;; calculate the value of the column for each header
-      (lambda (props) (mapcar (lambda (col)
-                          (let ((result (org-propview-eval-w-props props col)))
-                            (if result result org-propview-default-value)))
-                        cols))
-      (if conds
-         ;; eliminate the headers which don't satisfy the property
-         (delq nil
-               (mapcar
-                (lambda (props)
-                  (if (and-rest (mapcar
-                                 (lambda (col)
-                                   (org-propview-eval-w-props props col))
-                                 conds))
-                      props))
-                header-props))
-         header-props)))))
-
-(defun org-propview-to-table (results stringformat)
-  ;; (message (format "cols:%S" cols))
-  (orgtbl-to-orgtbl
-   (mapcar
-    (lambda (row)
-      (if (equal row 'hline)
-         'hline
-       (mapcar (lambda (el) (format stringformat el)) row)))
-    (delq nil results)) '()))
-
-(provide 'org-collector)
-;;; org-collector ends here
diff --git a/contrib/lisp/org-contacts.el b/contrib/lisp/org-contacts.el
deleted file mode 100644
index 4b3693a..0000000
--- a/contrib/lisp/org-contacts.el
+++ /dev/null
@@ -1,1151 +0,0 @@
-;;; org-contacts.el --- Contacts management
-
-;; Copyright (C) 2010-2014 Julien Danjou <julien@danjou.info>
-
-;; Author: Julien Danjou <julien@danjou.info>
-;; Keywords: outlines, hypermedia, calendar
-;;
-;; This file is NOT 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:
-
-;; This file contains the code for managing your contacts into Org-mode.
-
-;; To enter new contacts, you can use `org-capture' and a minimal template 
just like
-;; this:
-
-;;         ("c" "Contacts" entry (file "~/Org/contacts.org")
-;;          "* %(org-contacts-template-name)
-;; :PROPERTIES:
-;; :EMAIL: %(org-contacts-template-email)
-;; :END:")))
-;;
-;; You can also use a complex template, for example:
-;;
-;;         ("c" "Contacts" entry (file "~/Org/contacts.org")
-;;          "* %(org-contacts-template-name)
-;; :PROPERTIES:
-;; :EMAIL: %(org-contacts-template-email)
-;; :PHONE:
-;; :ALIAS:
-;; :NICKNAME:
-;; :IGNORE:
-;; :ICON:
-;; :NOTE:
-;; :ADDRESS:
-;; :BIRTHDAY:
-;; :END:")))
-;;
-;;; Code:
-
-(require 'cl-lib)
-(require 'org)
-(require 'gnus-util)
-(require 'gnus-art)
-(require 'mail-utils)
-(require 'org-agenda)
-(require 'org-capture)
-(require 'ol)
-
-(defgroup org-contacts nil
-  "Options about contacts management."
-  :group 'org)
-
-(defcustom org-contacts-files nil
-  "List of Org files to use as contacts source.
-When set to nil, all your Org files will be used."
-  :type '(repeat file)
-  :group 'org-contacts)
-
-(defcustom org-contacts-email-property "EMAIL"
-  "Name of the property for contact email address."
-  :type 'string
-  :group 'org-contacts)
-
-(defcustom org-contacts-tel-property "PHONE"
-  "Name of the property for contact phone number."
-  :type 'string
-  :group 'org-contacts)
-
-(defcustom org-contacts-address-property "ADDRESS"
-  "Name of the property for contact address."
-  :type 'string
-  :group 'org-contacts)
-
-(defcustom org-contacts-birthday-property "BIRTHDAY"
-  "Name of the property for contact birthday date."
-  :type 'string
-  :group 'org-contacts)
-
-(defcustom org-contacts-note-property "NOTE"
-  "Name of the property for contact note."
-  :type 'string
-  :group 'org-contacts)
-
-(defcustom org-contacts-alias-property "ALIAS"
-  "Name of the property for contact name alias."
-  :type 'string
-  :group 'org-contacts)
-
-(defcustom org-contacts-ignore-property "IGNORE"
-  "Name of the property, which values will be ignored when
-completing or exporting to vcard."
-  :type 'string
-  :group 'org-contacts)
-
-
-(defcustom org-contacts-birthday-format "Birthday: %l (%Y)"
-  "Format of the anniversary agenda entry.
-The following replacements are available:
-
-  %h - Heading name
-  %l - Link to the heading
-  %y - Number of year
-  %Y - Number of year (ordinal)"
-  :type 'string
-  :group 'org-contacts)
-
-(defcustom org-contacts-last-read-mail-property "LAST_READ_MAIL"
-  "Name of the property for contact last read email link storage."
-  :type 'string
-  :group 'org-contacts)
-
-(defcustom org-contacts-icon-property "ICON"
-  "Name of the property for contact icon."
-  :type 'string
-  :group 'org-contacts)
-
-(defcustom org-contacts-nickname-property "NICKNAME"
-  "Name of the property for IRC nickname match."
-  :type 'string
-  :group 'org-contacts)
-
-(defcustom org-contacts-icon-size 32
-  "Size of the contacts icons."
-  :type 'string
-  :group 'org-contacts)
-
-(defcustom org-contacts-icon-use-gravatar (fboundp 'gravatar-retrieve)
-  "Whether use Gravatar to fetch contact icons."
-  :type 'boolean
-  :group 'org-contacts)
-
-(defcustom org-contacts-completion-ignore-case t
-  "Ignore case when completing contacts."
-  :type 'boolean
-  :group 'org-contacts)
-
-(defcustom org-contacts-group-prefix "+"
-  "Group prefix."
-  :type 'string
-  :group 'org-contacts)
-
-(defcustom org-contacts-tags-props-prefix "#"
-  "Tags and properties prefix."
-  :type 'string
-  :group 'org-contacts)
-
-(defcustom org-contacts-matcher
-  (mapconcat #'identity
-            (mapcar (lambda (x) (concat x "<>\"\""))
-                    (list org-contacts-email-property
-                          org-contacts-alias-property
-                          org-contacts-tel-property
-                          org-contacts-address-property
-                          org-contacts-birthday-property))
-            "|")
-  "Matching rule for finding heading that are contacts.
-This can be a tag name, or a property check."
-  :type 'string
-  :group 'org-contacts)
-
-(defcustom org-contacts-email-link-description-format "%s (%d)"
-  "Format used to store links to email.
-This overrides `org-email-link-description-format' if set."
-  :group 'org-contacts
-  :type 'string)
-
-(defcustom org-contacts-vcard-file "contacts.vcf"
-  "Default file for vcard export."
-  :group 'org-contacts
-  :type 'file)
-
-(defcustom org-contacts-enable-completion t
-  "Enable or not the completion in `message-mode' with `org-contacts'."
-  :group 'org-contacts
-  :type 'boolean)
-
-(defcustom org-contacts-complete-functions
-  '(org-contacts-complete-group org-contacts-complete-tags-props 
org-contacts-complete-name)
-  "List of functions used to complete contacts in `message-mode'."
-  :group 'org-contacts
-  :type 'hook)
-
-;; Decalre external functions and variables
-(declare-function org-reverse-string "org")
-(declare-function diary-ordinal-suffix "ext:diary-lib")
-(declare-function wl-summary-message-number "ext:wl-summary")
-(declare-function wl-address-header-extract-address "ext:wl-address")
-(declare-function wl-address-header-extract-realname "ext:wl-address")
-(declare-function erc-buffer-list "ext:erc")
-(declare-function erc-get-channel-user-list "ext:erc")
-(declare-function google-maps-static-show "ext:google-maps-static")
-(declare-function elmo-message-field "ext:elmo-pipe")
-(declare-function std11-narrow-to-header "ext:std11")
-(declare-function std11-fetch-field "ext:std11")
-
-(defconst org-contacts-property-values-separators "[,; \f\t\n\r\v]+"
-  "The default value of separators for `org-contacts-split-property'.
-
-A regexp matching strings of whitespace, `,' and `;'.")
-
-(defvar org-contacts-keymap
-  (let ((map (make-sparse-keymap)))
-    (define-key map "M" 'org-contacts-view-send-email)
-    (define-key map "i" 'org-contacts-view-switch-to-irc-buffer)
-    map)
-  "The keymap used in `org-contacts' result list.")
-
-(defvar org-contacts-db nil
-  "Org Contacts database.")
-
-(defvar org-contacts-last-update nil
-  "Last time the Org Contacts database has been updated.")
-
-(defun org-contacts-files ()
-  "Return list of Org files to use for contact management."
-  (or org-contacts-files (org-agenda-files t 'ifmode)))
-
-(defun org-contacts-db-need-update-p ()
-  "Determine whether `org-contacts-db' needs to be refreshed."
-  (or (null org-contacts-last-update)
-      (cl-find-if (lambda (file)
-                    (or (time-less-p org-contacts-last-update
-                                     (elt (file-attributes file) 5))))
-                  (org-contacts-files))
-      (org-contacts-db-has-dead-markers-p org-contacts-db)))
-
-(defun org-contacts-db-has-dead-markers-p (org-contacts-db)
-  "Returns t if at least one dead marker is found in
-ORG-CONTACTS-DB. A dead marker in this case is a marker pointing
-to dead or no buffer."
-    ;; Scan contacts list looking for dead markers, and return t at first 
found.
-    (catch 'dead-marker-found
-      (while org-contacts-db
-        (unless (marker-buffer (nth 1 (car org-contacts-db)))
-          (throw 'dead-marker-found t))
-        (setq org-contacts-db (cdr org-contacts-db)))
-      nil))
-
-(defun org-contacts-db ()
-  "Return the latest Org Contacts Database."
-  (let* ((org--matcher-tags-todo-only nil)
-        (contacts-matcher (cdr (org-make-tags-matcher org-contacts-matcher)))
-        result)
-    (when (org-contacts-db-need-update-p)
-      (let ((progress-reporter
-            (make-progress-reporter "Updating Org Contacts Database..." 0 
(length org-contacts-files)))
-           (i 0))
-       (dolist (file (org-contacts-files))
-         (if (catch 'nextfile
-                ;; if file doesn't exist and the user agrees to removing it
-                ;; from org-agendas-list, 'nextfile is thrown.  Catch it here
-                ;; and skip processing the file.
-                ;;
-                ;; TODO: suppose that the user has set an org-contacts-files
-                ;; list that contains an element that doesn't exist in the
-                ;; file system: in that case, the org-agenda-files list could
-                ;; be updated (and saved to the customizations of the user) if
-                ;; it contained the same file even though the org-agenda-files
-                ;; list wasn't actually used.  I don't think it is normal that
-                ;; org-contacts updates org-agenda-files in this case, but
-                ;; short of duplicating org-check-agenda-files and
-                ;; org-remove-files, I don't know how to avoid it.
-                ;;
-                ;; A side effect of the TODO is that the faulty
-                ;; org-contacts-files list never gets updated and thus the
-                ;; user is always queried about the missing files when
-                ;; org-contacts-db-need-update-p returns true.
-                (org-check-agenda-file file))
-              (message "Skipped %s removed from org-agenda-files list."
-                       (abbreviate-file-name file))
-           (with-current-buffer (org-get-agenda-file-buffer file)
-             (unless (eq major-mode 'org-mode)
-               (error "File %s is not in `org-mode'" file))
-             (setf result
-                   (append result
-                           (org-scan-tags 'org-contacts-at-point
-                                          contacts-matcher
-                                          org--matcher-tags-todo-only)))))
-         (progress-reporter-update progress-reporter (setq i (1+ i))))
-       (setf org-contacts-db result
-             org-contacts-last-update (current-time))
-       (progress-reporter-done progress-reporter)))
-    org-contacts-db))
-
-(defun org-contacts-at-point (&optional pom)
-  "Return the contacts at point-or-marker POM or current position
-if nil."
-  (setq pom (or pom (point)))
-  (org-with-point-at pom
-    (list (org-get-heading t) (set-marker (make-marker) pom) 
(org-entry-properties pom 'all))))
-
-(defun org-contacts-filter (&optional name-match tags-match prop-match)
-  "Search for a contact matching any of NAME-MATCH, TAGS-MATCH, PROP-MATCH.
-If all match values are nil, return all contacts.
-
-The optional PROP-MATCH argument is a single (PROP . VALUE) cons
-cell corresponding to the contact properties.
-"
-  (if (and (null name-match)
-          (null prop-match)
-          (null tags-match))
-      (org-contacts-db)
-    (cl-loop for contact in (org-contacts-db)
-            if (or
-                (and name-match
-                     (string-match-p name-match
-                                         (first contact)))
-                (and prop-match
-                     (cl-find-if (lambda (prop)
-                                    (and (string= (car prop-match) (car prop))
-                                         (string-match-p (cdr prop-match) (cdr 
prop))))
-                                  (caddr contact)))
-                (and tags-match
-                     (cl-find-if (lambda (tag)
-                                    (string-match-p tags-match tag))
-                                  (org-split-string
-                                   (or (cdr (assoc-string "ALLTAGS" (caddr 
contact))) "") ":"))))
-            collect contact)))
-
-(when (not (fboundp 'completion-table-case-fold))
-  ;; That function is new in Emacs 24...
-  (defun completion-table-case-fold (table &optional dont-fold)
-    (lambda (string pred action)
-      (let ((completion-ignore-case (not dont-fold)))
-       (complete-with-action action table string pred)))))
-
-(defun org-contacts-try-completion-prefix (to-match collection &optional 
predicate)
-  "Custom implementation of `try-completion'.
-This version works only with list and alist and it looks at all
-prefixes rather than just the beginning of the string."
-  (cl-loop with regexp = (concat "\\b" (regexp-quote to-match))
-          with ret = nil
-          with ret-start = nil
-          with ret-end = nil
-
-          for el in collection
-          for string = (if (listp el) (car el) el)
-
-          for start = (when (or (null predicate) (funcall predicate string))
-                        (string-match regexp string))
-
-          if start
-          do (let ((end (match-end 0))
-                   (len (length string)))
-               (if (= end len)
-                   (cl-return t)
-                 (cl-destructuring-bind (string start end)
-                     (if (null ret)
-                         (values string start end)
-                       (org-contacts-common-substring
-                        ret ret-start ret-end
-                        string start end))
-                   (setf ret string
-                         ret-start start
-                         ret-end end))))
-
-          finally (cl-return
-                   (replace-regexp-in-string "\\`[ \t\n]*" "" ret))))
-
-(defun org-contacts-compare-strings (s1 start1 end1 s2 start2 end2 &optional 
ignore-case)
-  "Compare the contents of two strings, using `compare-strings'.
-
-This function works like `compare-strings' excepted that it
-returns a cons.
-- The CAR is the number of characters that match at the beginning.
-- The CDR is T is the two strings are the same and NIL otherwise."
-  (let ((ret (compare-strings s1 start1 end1 s2 start2 end2 ignore-case)))
-    (if (eq ret t)
-       (cons (or end1 (length s1)) t)
-      (cons (1- (abs ret)) nil))))
-
-(defun org-contacts-common-substring (s1 start1 end1 s2 start2 end2)
-  "Extract the common substring between S1 and S2.
-
-This function extracts the common substring between S1 and S2 and
-adjust the part that remains common.
-
-START1 and END1 delimit the part in S1 that we know is common
-between the two strings. This applies to START2 and END2 for S2.
-
-This function returns a list whose contains:
-- The common substring found.
-- The new value of the start of the known inner substring.
-- The new value of the end of the known inner substring."
-  ;; Given two strings:
-  ;; s1: "foo bar baz"
-  ;; s2: "fooo bar baz"
-  ;; and the inner substring is "bar"
-  ;; then: start1 = 4, end1 = 6, start2 = 5, end2 = 7
-  ;;
-  ;; To find the common substring we will compare two substrings:
-  ;; " oof" and " ooof" to find the beginning of the common substring.
-  ;; " baz" and " baz" to find the end of the common substring.
-  (let* ((len1 (length s1))
-        (start1 (or start1 0))
-        (end1 (or end1 len1))
-
-        (len2 (length s2))
-        (start2 (or start2 0))
-        (end2 (or end2 len2))
-
-        (new-start (car (org-contacts-compare-strings
-                         (substring (org-reverse-string s1) (- len1 start1)) 
nil nil
-                         (substring (org-reverse-string s2) (- len2 start2)) 
nil nil)))
-
-        (new-end (+ end1 (car (org-contacts-compare-strings
-                               (substring s1 end1) nil nil
-                               (substring s2 end2) nil nil)))))
-    (list (substring s1 (- start1 new-start) new-end)
-         new-start
-         (+ new-start (- end1 start1)))))
-
-(defun org-contacts-all-completions-prefix (to-match collection &optional 
predicate)
-  "Custom version of `all-completions'.
-This version works only with list and alist and it looks at all
-prefixes rather than just the beginning of the string."
-  (cl-loop with regexp = (concat "\\b" (regexp-quote to-match))
-          for el in collection
-          for string = (if (listp el) (car el) el)
-          for match? = (when (and (or (null predicate) (funcall predicate 
string)))
-                         (string-match regexp string))
-          if match?
-          collect (progn
-                    (let ((end (match-end 0)))
-                      (org-no-properties string)
-                      (when (< end (length string))
-                        ;; Here we add a text property that will be used
-                        ;; later to highlight the character right after
-                        ;; the common part between each addresses.
-                        ;; See `org-contacts-display-sort-function'.
-                        (put-text-property end (1+ end) 'org-contacts-prefix 
't string)))
-                    string)))
-
-(defun org-contacts-make-collection-prefix (collection)
-  "Make a collection function from COLLECTION which will match on prefixes."
-  (lexical-let ((collection collection))
-    (lambda (string predicate flag)
-      (cond ((eq flag nil)
-            (org-contacts-try-completion-prefix string collection predicate))
-           ((eq flag t)
-            ;; `org-contacts-all-completions-prefix' has already been
-            ;; used to compute `all-completions'.
-            collection)
-           ((eq flag 'lambda)
-            (org-contacts-test-completion-prefix string collection predicate))
-           ((and (listp flag) (eq (car flag) 'boundaries))
-            (cl-destructuring-bind (to-ignore &rest suffix)
-                flag
-              (org-contacts-boundaries-prefix string collection predicate 
suffix)))
-           ((eq flag 'metadata)
-            (org-contacts-metadata-prefix string collection predicate))
-           (t nil                      ; operation unsupported
-              )))))
-
-(defun org-contacts-display-sort-function (completions)
-  "Sort function for contacts display."
-  (mapcar (lambda (string)
-           (cl-loop with len = (1- (length string))
-                    for i upfrom 0 to len
-                    if (memq 'org-contacts-prefix
-                             (text-properties-at i string))
-                    do (set-text-properties
-                        i (1+ i)
-                        (list 'font-lock-face
-                              (if (char-equal (aref string i)
-                                              (string-to-char " "))
-                                  ;; Spaces can't be bold.
-                                  'underline
-                                'bold)) string)
-                    else
-                    do (set-text-properties i (1+ i) nil string)
-                    finally (cl-return string)))
-         completions))
-
-(defun org-contacts-test-completion-prefix (string collection predicate)
-  (cl-find-if (lambda (el)
-               (and (or (null predicate) (funcall predicate el))
-                    (string= string el)))
-             collection))
-
-(defun org-contacts-boundaries-prefix (string collection predicate suffix)
-  (list* 'boundaries (completion-boundaries string collection predicate 
suffix)))
-
-(defun org-contacts-metadata-prefix (string collection predicate)
-  '(metadata .
-            ((cycle-sort-function . org-contacts-display-sort-function)
-             (display-sort-function . org-contacts-display-sort-function))))
-
-(defun org-contacts-complete-group (start end string)
-  "Complete text at START from a group.
-
-A group FOO is composed of contacts with the tag FOO."
-  (let* ((completion-ignore-case org-contacts-completion-ignore-case)
-        (group-completion-p (string-match-p
-                             (concat "^" org-contacts-group-prefix) string)))
-    (when group-completion-p
-      (let ((completion-list
-            (all-completions
-             string
-             (mapcar (lambda (group)
-                       (propertize (concat org-contacts-group-prefix group)
-                                   'org-contacts-group group))
-                     (org-uniquify
-                      (cl-loop for contact in (org-contacts-filter)
-                               nconc (org-split-string
-                                      (or (cdr (assoc-string "ALLTAGS" (caddr 
contact))) "") ":")))))))
-       (list start end
-             (if (= (length completion-list) 1)
-                 ;; We've found the correct group, returns the address
-                 (lexical-let ((tag (get-text-property 0 'org-contacts-group
-                                                       (car completion-list))))
-                   (lambda (string pred &optional to-ignore)
-                     (mapconcat 'identity
-                                (cl-loop for contact in (org-contacts-filter
-                                                         nil
-                                                         tag)
-                                         ;; The contact name is always the car 
of the assoc-list
-                                         ;; returned by `org-contacts-filter'.
-                                         for contact-name = (car contact)
-                                         ;; Grab the first email of the contact
-                                         for email = (org-contacts-strip-link
-                                                      (or (car 
(org-contacts-split-property
-                                                                (or
-                                                                 (cdr 
(assoc-string org-contacts-email-property
-                                                                               
     (cl-caddr contact)))
-                                                                 ""))) ""))
-                                         ;; If the user has an email address, 
append USER <EMAIL>.
-                                         if email collect 
(org-contacts-format-email contact-name email))
-                                ", ")))
-               ;; We haven't found the correct group
-               (completion-table-case-fold completion-list
-                                           (not 
org-contacts-completion-ignore-case))))))))
-
-(defun org-contacts-complete-tags-props (start end string)
-  "Insert emails that match the tags expression.
-
-For example: FOO-BAR will match entries tagged with FOO but not
-with BAR.
-
-See (org) Matching tags and properties for a complete
-description."
-  (let* ((completion-ignore-case org-contacts-completion-ignore-case)
-        (completion-p (string-match-p
-                       (concat "^" org-contacts-tags-props-prefix) string)))
-    (when completion-p
-      (let ((result
-            (mapconcat
-             'identity
-             (cl-loop for contact in (org-contacts-db)
-                      for contact-name = (car contact)
-                      for email = (org-contacts-strip-link (or (car 
(org-contacts-split-property
-                                                                     (or
-                                                                      (cdr 
(assoc-string org-contacts-email-property
-                                                                               
          (cl-caddr contact)))
-                                                                      ""))) 
""))
-                      for tags = (cdr (assoc "TAGS" (nth 2 contact)))
-                      for tags-list = (if tags
-                                          (split-string (substring (cdr (assoc 
"TAGS" (nth 2 contact))) 1 -1) ":")
-                                        '())
-                      for marker = (nth 1 contact)
-                      if (with-current-buffer (marker-buffer marker)
-                           (save-excursion
-                             (goto-char marker)
-                             (let (todo-only)
-                               (eval (cdr (org-make-tags-matcher (cl-subseq 
string 1)))))))
-                      collect (org-contacts-format-email contact-name email))
-             ",")))
-       (when (not (string= "" result))
-         ;; return (start end function)
-         (lexical-let* ((to-return result))
-           (list start end
-                 (lambda (string pred &optional to-ignore) to-return))))))))
-
-(defun org-contacts-remove-ignored-property-values (ignore-list list)
-  "Remove all ignore-list's elements from list and you can use
-   regular expressions in the ignore list."
-  (cl-remove-if (lambda (el)
-                 (cl-find-if (lambda (x)
-                                (string-match-p x el))
-                              ignore-list))
-               list))
-
-(defun org-contacts-complete-name (start end string)
-  "Complete text at START with a user name and email."
-  (let* ((completion-ignore-case org-contacts-completion-ignore-case)
-         (completion-list
-         (cl-loop for contact in (org-contacts-filter)
-                  ;; The contact name is always the car of the assoc-list
-                  ;; returned by `org-contacts-filter'.
-                  for contact-name = (car contact)
-
-                  ;; Build the list of the email addresses which has
-                  ;; been expired
-                  for ignore-list = (org-contacts-split-property
-                                     (or (cdr (assoc-string 
org-contacts-ignore-property
-                                                            (nth 2 contact))) 
""))
-                  ;; Build the list of the user email addresses.
-                  for email-list = (org-contacts-remove-ignored-property-values
-                                    ignore-list
-                                    (org-contacts-split-property
-                                     (or (cdr (assoc-string 
org-contacts-email-property
-                                                            (nth 2 contact))) 
"")))
-                  ;; If the user has email addressesโ€ฆ
-                  if email-list
-                  ;; โ€ฆ append a list of USER <EMAIL>.
-                  nconc (cl-loop for email in email-list
-                                 collect (org-contacts-format-email 
contact-name (org-contacts-strip-link email)))))
-        (completion-list (org-contacts-all-completions-prefix
-                          string
-                          (org-uniquify completion-list))))
-    (when completion-list
-      (list start end
-           (org-contacts-make-collection-prefix completion-list)))))
-
-(defun org-contacts-message-complete-function (&optional start)
-  "Function used in `completion-at-point-functions' in `message-mode'."
-  ;; Avoid to complete in `post-command-hook'.
-  (when completion-in-region-mode
-    (remove-hook 'post-command-hook #'completion-in-region--postch))
-  (let ((mail-abbrev-mode-regexp
-         
"^\\(Resent-To\\|To\\|B?Cc\\|Reply-To\\|From\\|Mail-Followup-To\\|Mail-Copies-To\\|Disposition-Notification-To\\|Return-Receipt-To\\):"))
-    (when (mail-abbrev-in-expansion-header-p)
-      (lexical-let*
-         ((end (point))
-          (start (or start
-                     (save-excursion
-                       (re-search-backward "\\(\\`\\|[\n:,]\\)[ \t]*")
-                       (goto-char (match-end 0))
-                       (point))))
-          (string (buffer-substring start end)))
-       (run-hook-with-args-until-success
-        'org-contacts-complete-functions start end string)))))
-
-(defun org-contacts-gnus-get-name-email ()
-  "Get name and email address from Gnus message."
-  (if (gnus-alive-p)
-      (gnus-with-article-headers
-        (mail-extract-address-components
-         (or (mail-fetch-field "From") "")))))
-
-(defun org-contacts-gnus-article-from-get-marker ()
-  "Return a marker for a contact based on From."
-  (let* ((address (org-contacts-gnus-get-name-email))
-         (name (car address))
-         (email (cadr address)))
-    (cl-cadar (or (org-contacts-filter
-                  nil
-                  nil
-                  (cons org-contacts-email-property (concat "\\b" 
(regexp-quote email) "\\b")))
-                 (when name
-                   (org-contacts-filter
-                    (concat "^" name "$")))))))
-
-(defun org-contacts-gnus-article-from-goto ()
-  "Go to contact in the From address of current Gnus message."
-  (interactive)
-  (let ((marker (org-contacts-gnus-article-from-get-marker)))
-    (when marker
-      (switch-to-buffer-other-window (marker-buffer marker))
-      (goto-char marker)
-      (when (eq major-mode 'org-mode) (org-show-context 'agenda)))))
-
-(with-no-warnings (defvar date)) ;; unprefixed, from calendar.el
-(defun org-contacts-anniversaries (&optional field format)
-  "Compute FIELD anniversary for each contact, returning FORMAT.
-Default FIELD value is \"BIRTHDAY\".
-
-Format is a string matching the following format specification:
-
-  %h - Heading name
-  %l - Link to the heading
-  %y - Number of year
-  %Y - Number of year (ordinal)"
-  (let ((calendar-date-style 'american)
-        (entry ""))
-    (unless format (setq format org-contacts-birthday-format))
-    (cl-loop for contact in (org-contacts-filter)
-            for anniv = (let ((anniv (cdr (assoc-string
-                                           (or field 
org-contacts-birthday-property)
-                                           (nth 2 contact)))))
-                          (when anniv
-                            (calendar-gregorian-from-absolute
-                             (org-time-string-to-absolute anniv))))
-            ;; Use `diary-anniversary' to compute anniversary.
-            if (and anniv (apply 'diary-anniversary anniv))
-            collect (format-spec format
-                                 `((?l . ,(org-with-point-at (cadr contact) 
(org-store-link nil)))
-                                   (?h . ,(car contact))
-                                   (?y . ,(- (calendar-extract-year date)
-                                             (calendar-extract-year anniv)))
-                                   (?Y . ,(let ((years (- 
(calendar-extract-year date)
-                                                          
(calendar-extract-year anniv))))
-                                            (format "%d%s" years 
(diary-ordinal-suffix years)))))))))
-
-(defun org-completing-read-date (prompt collection
-                                        &optional predicate require-match 
initial-input
-                                        hist def inherit-input-method)
-  "Like `completing-read' but reads a date.
-Only PROMPT and DEF are really used."
-  (org-read-date nil nil nil prompt nil def))
-
-(add-to-list 'org-property-set-functions-alist
-             `(,org-contacts-birthday-property . org-completing-read-date))
-
-(defun org-contacts-template-name (&optional return-value)
-  "Try to return the contact name for a template.
-If not found return RETURN-VALUE or something that would ask the user."
-  (or (car (org-contacts-gnus-get-name-email))
-      return-value
-      "%^{Name}"))
-
-(defun org-contacts-template-email (&optional return-value)
-  "Try to return the contact email for a template.
-If not found return RETURN-VALUE or something that would ask the user."
-  (or (cadr (org-contacts-gnus-get-name-email))
-      return-value
-      (concat "%^{" org-contacts-email-property "}p")))
-
-(defun org-contacts-gnus-store-last-mail ()
-  "Store a link between mails and contacts.
-
-This function should be called from `gnus-article-prepare-hook'."
-  (let ((marker (org-contacts-gnus-article-from-get-marker)))
-    (when marker
-      (with-current-buffer (marker-buffer marker)
-        (save-excursion
-          (goto-char marker)
-          (let* ((org-email-link-description-format (or 
org-contacts-email-link-description-format
-                                                        
org-email-link-description-format))
-                 (link (gnus-with-article-buffer (org-store-link nil))))
-            (org-set-property org-contacts-last-read-mail-property link)))))))
-
-(defun org-contacts-icon-as-string ()
-  "Return the contact icon as a string."
-  (let ((image (org-contacts-get-icon)))
-    (concat
-     (propertize "-" 'display
-                 (append
-                  (if image
-                      image
-                    `'(space :width (,org-contacts-icon-size)))
-                  '(:ascent center)))
-     " ")))
-
-;;;###autoload
-(defun org-contacts (name)
-  "Create agenda view for contacts matching NAME."
-  (interactive (list (read-string "Name: ")))
-  (let ((org-agenda-files (org-contacts-files))
-        (org-agenda-skip-function
-         (lambda () (org-agenda-skip-if nil `(notregexp ,name))))
-        (org-agenda-prefix-format (propertize
-                                  "%(org-contacts-icon-as-string)% 
s%(org-contacts-irc-number-of-unread-messages) "
-                                  'keymap org-contacts-keymap))
-        (org-agenda-overriding-header
-         (or org-agenda-overriding-header
-             (concat "List of contacts matching `" name "':"))))
-    (setq org-agenda-skip-regexp name)
-    (org-tags-view nil org-contacts-matcher)
-    (with-current-buffer org-agenda-buffer-name
-      (setq org-agenda-redo-command
-            (list 'org-contacts name)))))
-
-(defun org-contacts-completing-read (prompt
-                                     &optional predicate
-                                     initial-input hist def 
inherit-input-method)
-  "Call `completing-read' with contacts name as collection."
-  (org-completing-read
-   prompt (org-contacts-filter) predicate t initial-input hist def 
inherit-input-method))
-
-(defun org-contacts-format-name (name)
-  "Trim any local formatting to get a bare NAME."
-  ;; Remove radio targets characters
-  (replace-regexp-in-string org-radio-target-regexp "\\1" name))
-
-(defun org-contacts-format-email (name email)
-  "Format an EMAIL address corresponding to NAME."
-  (unless email
-    (error "`email' cannot be nul"))
-  (if name
-      (concat (org-contacts-format-name name) " <" email ">")
-    email))
-
-(defun org-contacts-check-mail-address (mail)
-  "Add MAIL address to contact at point if it does not have it."
-  (let ((mails (org-entry-get (point) org-contacts-email-property)))
-    (unless (member mail (split-string mails))
-      (when (yes-or-no-p
-             (format "Do you want to add this address to %s?" (org-get-heading 
t)))
-        (org-set-property org-contacts-email-property (concat mails " " 
mail))))))
-
-(defun org-contacts-gnus-check-mail-address ()
-  "Check that contact has the current address recorded.
-This function should be called from `gnus-article-prepare-hook'."
-  (let ((marker (org-contacts-gnus-article-from-get-marker)))
-    (when marker
-      (org-with-point-at marker
-        (org-contacts-check-mail-address (cadr 
(org-contacts-gnus-get-name-email)))))))
-
-(defun org-contacts-gnus-insinuate ()
-  "Add some hooks for Gnus user.
-This adds `org-contacts-gnus-check-mail-address' and
-`org-contacts-gnus-store-last-mail' to
-`gnus-article-prepare-hook'.  It also adds a binding on `;' in
-`gnus-summary-mode-map' to `org-contacts-gnus-article-from-goto'"
-  (require 'gnus)
-  (require 'gnus-art)
-  (define-key gnus-summary-mode-map ";" 'org-contacts-gnus-article-from-goto)
-  (add-hook 'gnus-article-prepare-hook 'org-contacts-gnus-check-mail-address)
-  (add-hook 'gnus-article-prepare-hook 'org-contacts-gnus-store-last-mail))
-
-(defun org-contacts-setup-completion-at-point ()
-  "Add `org-contacts-message-complete-function' as a new function
-to complete the thing at point."
-  (add-to-list 'completion-at-point-functions
-              'org-contacts-message-complete-function))
-
-(defun org-contacts-unload-hook ()
-  (remove-hook 'message-mode-hook 'org-contacts-setup-completion-at-point))
-
-(when (and org-contacts-enable-completion
-          (boundp 'completion-at-point-functions))
-  (add-hook 'message-mode-hook 'org-contacts-setup-completion-at-point))
-
-(defun org-contacts-wl-get-from-header-content ()
-  "Retrieve the content of the `From' header of an email.
-Works from wl-summary-mode and mime-view-mode - that is while viewing email.
-Depends on Wanderlust been loaded."
-  (with-current-buffer (org-capture-get :original-buffer)
-    (cond
-     ((eq major-mode 'wl-summary-mode) (when (and (boundp 
'wl-summary-buffer-elmo-folder)
-                                                 wl-summary-buffer-elmo-folder)
-                                         (elmo-message-field
-                                          wl-summary-buffer-elmo-folder
-                                          (wl-summary-message-number)
-                                          'from)))
-     ((eq major-mode 'mime-view-mode) (std11-narrow-to-header)
-      (prog1
-         (std11-fetch-field "From")
-       (widen))))))
-
-(defun org-contacts-wl-get-name-email ()
-  "Get name and email address from Wanderlust email.
-See `org-contacts-wl-get-from-header-content' for limitations."
-  (let ((from (org-contacts-wl-get-from-header-content)))
-    (when from
-      (list (wl-address-header-extract-realname from)
-           (wl-address-header-extract-address from)))))
-
-(defun org-contacts-template-wl-name (&optional return-value)
-  "Try to return the contact name for a template from wl.
-If not found, return RETURN-VALUE or something that would ask the
-user."
-  (or (car (org-contacts-wl-get-name-email))
-      return-value
-      "%^{Name}"))
-
-(defun org-contacts-template-wl-email (&optional return-value)
-  "Try to return the contact email for a template from Wanderlust.
-If not found return RETURN-VALUE or something that would ask the user."
-  (or (cadr (org-contacts-wl-get-name-email))
-      return-value
-      (concat "%^{" org-contacts-email-property "}p")))
-
-(defun org-contacts-view-send-email (&optional ask)
-  "Send email to the contact at point.
-If ASK is set, ask for the email address even if there's only one
-address."
-  (interactive "P")
-  (let ((marker (org-get-at-bol 'org-hd-marker)))
-    (org-with-point-at marker
-      (let ((emails (org-entry-get (point) org-contacts-email-property)))
-        (if emails
-            (let ((email-list (org-contacts-split-property emails)))
-              (if (and (= (length email-list) 1) (not ask))
-                  (compose-mail (org-contacts-format-email
-                                 (org-get-heading t) emails))
-                (let ((email (completing-read "Send mail to which address: " 
email-list)))
-                 (setq email (org-contacts-strip-link email))
-                  (org-contacts-check-mail-address email)
-                  (compose-mail (org-contacts-format-email (org-get-heading t) 
email)))))
-          (error (format "This contact has no mail address set (no %s 
property)"
-                         org-contacts-email-property)))))))
-
-(defun org-contacts-get-icon (&optional pom)
-  "Get icon for contact at POM."
-  (setq pom (or pom (point)))
-  (catch 'icon
-    ;; Use `org-contacts-icon-property'
-    (let ((image-data (org-entry-get pom org-contacts-icon-property)))
-      (when image-data
-        (throw 'icon
-               (if (fboundp 'gnus-rescale-image)
-                   (gnus-rescale-image (create-image image-data)
-                                       (cons org-contacts-icon-size 
org-contacts-icon-size))
-                 (create-image image-data)))))
-    ;; Next, try Gravatar
-    (when org-contacts-icon-use-gravatar
-      (let* ((gravatar-size org-contacts-icon-size)
-             (email-list (org-entry-get pom org-contacts-email-property))
-             (gravatar
-              (when email-list
-                (loop for email in (org-contacts-split-property email-list)
-                      for gravatar = (gravatar-retrieve-synchronously 
(org-contacts-strip-link email))
-                      if (and gravatar
-                              (not (eq gravatar 'error)))
-                      return gravatar))))
-        (when gravatar (throw 'icon gravatar))))))
-
-(defun org-contacts-irc-buffer (&optional pom)
-  "Get the IRC buffer associated with the entry at POM."
-  (setq pom (or pom (point)))
-  (let ((nick (org-entry-get pom org-contacts-nickname-property)))
-    (when nick
-      (let ((buffer (get-buffer nick)))
-        (when buffer
-          (with-current-buffer buffer
-            (when (eq major-mode 'erc-mode)
-              buffer)))))))
-
-(defun org-contacts-irc-number-of-unread-messages (&optional pom)
-  "Return the number of unread messages for contact at POM."
-  (when (boundp 'erc-modified-channels-alist)
-    (let ((number (cadr (assoc (org-contacts-irc-buffer pom) 
erc-modified-channels-alist))))
-      (if number
-          (format (concat "%3d unread message" (if (> number 1) "s" " ") " ") 
number)
-        (make-string 21 ? )))))
-
-(defun org-contacts-view-switch-to-irc-buffer ()
-  "Switch to the IRC buffer of the current contact if it has one."
-  (interactive)
-  (let ((marker (org-get-at-bol 'org-hd-marker)))
-    (org-with-point-at marker
-      (switch-to-buffer-other-window (org-contacts-irc-buffer)))))
-
-(defun org-contacts-completing-read-nickname (prompt collection
-                                                     &optional predicate 
require-match initial-input
-                                                     hist def 
inherit-input-method)
-  "Like `completing-read' but reads a nickname."
-  (org-completing-read prompt (append collection (erc-nicknames-list)) 
predicate require-match
-                       initial-input hist def inherit-input-method))
-
-(defun erc-nicknames-list ()
-  "Return all nicknames of all ERC buffers."
-  (loop for buffer in (erc-buffer-list)
-       nconc (with-current-buffer buffer
-               (loop for user-entry in (mapcar 'car 
(erc-get-channel-user-list))
-                     collect (elt user-entry 1)))))
-
-(add-to-list 'org-property-set-functions-alist
-             `(,org-contacts-nickname-property . 
org-contacts-completing-read-nickname))
-
-(defun org-contacts-vcard-escape (str)
-  "Escape ; , and \n in STR for the VCard format."
-  ;; Thanks to this library for the regexp:
-  ;; http://www.emacswiki.org/cgi-bin/wiki/bbdb-vcard-export.el
-  (when str
-    (replace-regexp-in-string
-     "\n" "\\\\n"
-     (replace-regexp-in-string "\\(;\\|,\\|\\\\\\)" "\\\\\\1" str))))
-
-(defun org-contacts-vcard-encode-name (name)
-  "Try to encode NAME as VCard's N property.
-The N property expects
-
-  FamilyName;GivenName;AdditionalNames;Prefix;Postfix.
-
-Org-contacts does not specify how to encode the name.  So we try
-to do our best."
-  (concat (replace-regexp-in-string "\\(\\w+\\) \\(.*\\)" "\\2;\\1" name) 
";;;"))
-
-(defun org-contacts-vcard-format (contact)
-  "Formats CONTACT in VCard 3.0 format."
-  (let* ((properties (nth 2 contact))
-        (name (org-contacts-vcard-escape (car contact)))
-        (n (org-contacts-vcard-encode-name name))
-        (email (cdr (assoc-string org-contacts-email-property properties)))
-        (tel (cdr (assoc-string org-contacts-tel-property properties)))
-        (ignore-list (cdr (assoc-string org-contacts-ignore-property 
properties)))
-        (ignore-list (when ignore-list
-                       (org-contacts-split-property ignore-list)))
-        (note (cdr (assoc-string org-contacts-note-property properties)))
-        (bday (org-contacts-vcard-escape (cdr (assoc-string 
org-contacts-birthday-property properties))))
-        (addr (cdr (assoc-string org-contacts-address-property properties)))
-        (nick (org-contacts-vcard-escape (cdr (assoc-string 
org-contacts-nickname-property properties))))
-        (head (format "BEGIN:VCARD\nVERSION:3.0\nN:%s\nFN:%s\n" n name))
-        emails-list result phones-list)
-    (concat head
-           (when email (progn
-                         (setq emails-list 
(org-contacts-remove-ignored-property-values ignore-list 
(org-contacts-split-property email)))
-                         (setq result "")
-                         (while emails-list
-                           (setq result (concat result  "EMAIL:" 
(org-contacts-strip-link (car emails-list)) "\n"))
-                           (setq emails-list (cdr emails-list)))
-                         result))
-           (when addr
-             (format "ADR:;;%s\n" (replace-regexp-in-string "\\, ?" ";" addr)))
-           (when tel (progn
-                       (setq phones-list 
(org-contacts-remove-ignored-property-values ignore-list 
(org-contacts-split-property tel)))
-                       (setq result "")
-                       (while phones-list
-                         (setq result (concat result  "TEL:" 
(org-contacts-strip-link (org-link-unescape (car phones-list))) "\n"))
-                         (setq phones-list (cdr phones-list)))
-                       result))
-           (when bday
-             (let ((cal-bday (calendar-gregorian-from-absolute 
(org-time-string-to-absolute bday))))
-               (format "BDAY:%04d-%02d-%02d\n"
-                       (calendar-extract-year cal-bday)
-                       (calendar-extract-month cal-bday)
-                       (calendar-extract-day cal-bday))))
-           (when nick (format "NICKNAME:%s\n" nick))
-           (when note (format "NOTE:%s\n" note))
-           "END:VCARD\n\n")))
-
-(defun org-contacts-export-as-vcard (&optional name file to-buffer)
-  "Export org contacts to V-Card 3.0.
-
-By default, all contacts are exported to `org-contacts-vcard-file'.
-
-When NAME is \\[universal-argument], prompts for a contact name.
-
-When NAME is \\[universal-argument] \\[universal-argument],
-prompts for a contact name and a file name where to export.
-
-When NAME is \\[universal-argument] \\[universal-argument]
-\\[universal-argument], prompts for a contact name and a buffer where to 
export.
-
-If the function is not called interactively, all parameters are
-passed to `org-contacts-export-as-vcard-internal'."
-  (interactive "P")
-  (when (called-interactively-p 'any)
-    (cl-psetf name
-             (when name
-               (read-string "Contact name: "
-                            (nth 0 (org-contacts-at-point))))
-             file
-             (when (equal name '(16))
-               (read-file-name "File: " nil org-contacts-vcard-file))
-             to-buffer
-             (when (equal name '(64))
-               (read-buffer "Buffer: "))))
-  (org-contacts-export-as-vcard-internal name file to-buffer))
-
-(defun org-contacts-export-as-vcard-internal (&optional name file to-buffer)
-  "Export all contacts matching NAME as VCard 3.0.
-If TO-BUFFER is nil, the content is written to FILE or
-`org-contacts-vcard-file'.  If TO-BUFFER is non-nil, the buffer
-is created and the VCard is written into that buffer."
-  (let* ((filename (or file org-contacts-vcard-file))
-        (buffer (if to-buffer
-                    (get-buffer-create to-buffer)
-                  (find-file-noselect filename))))
-    (message "Exporting...")
-    (set-buffer buffer)
-    (let ((inhibit-read-only t)) (erase-buffer))
-    (fundamental-mode)
-    (when (fboundp 'set-buffer-file-coding-system)
-      (set-buffer-file-coding-system coding-system-for-write))
-    (loop for contact in (org-contacts-filter name)
-         do (insert (org-contacts-vcard-format contact)))
-    (if to-buffer
-       (current-buffer)
-      (progn (save-buffer) (kill-buffer)))))
-
-(defun org-contacts-show-map (&optional name)
-  "Show contacts on a map.
-Requires google-maps-el."
-  (interactive)
-  (unless (fboundp 'google-maps-static-show)
-    (error "`org-contacts-show-map' requires `google-maps-el'"))
-  (google-maps-static-show
-   :markers
-   (cl-loop
-    for contact in (org-contacts-filter name)
-    for addr = (cdr (assoc-string org-contacts-address-property (nth 2 
contact)))
-    if addr
-    collect (cons (list addr) (list :label (string-to-char (car contact)))))))
-
-(defun org-contacts-strip-link (link)
-  "Remove brackets, description, link type and colon from an org
-link string and return the pure link target."
-   (let (startpos colonpos endpos)
-     (setq startpos (string-match (regexp-opt '("[[tel:" "[[mailto:";)) link))
-     (if startpos
-         (progn
-            (setq colonpos (string-match ":" link))
-            (setq endpos (string-match "\\]" link))
-            (if endpos (substring link (1+ colonpos) endpos) link))
-         (progn
-            (setq startpos (string-match "mailto:"; link))
-            (setq colonpos (string-match ":" link))
-            (if startpos (substring link (1+ colonpos)) link)))))
-
-;; Add the link type supported by org-contacts-strip-link
-;; so everything is in order for its use in Org files
-(org-link-set-parameters "tel")
-
-(defun org-contacts-split-property (string &optional separators omit-nulls)
-  "Custom version of `split-string'.
-Split a property STRING into sub-strings bounded by matches
-for SEPARATORS but keep Org links intact.
-
-The beginning and end of STRING, and each match for SEPARATORS, are
-splitting points.  The substrings matching SEPARATORS are removed, and
-the substrings between the splitting points are collected as a list,
-which is returned.
-
-If SEPARATORS is non-nil, it should be a regular expression
-matching text which separates, but is not part of, the
-substrings.  If nil it defaults to `org-contacts-property-values-separators',
-normally \"[,; \f\t\n\r\v]+\", and OMIT-NULLS is forced to t.
-
-If OMIT-NULLS is t, zero-length substrings are omitted from the list \(so
-that for the default value of SEPARATORS leading and trailing whitespace
-are effectively trimmed).  If nil, all zero-length substrings are retained."
-  (let* ((omit-nulls (if separators omit-nulls t))
-        (rexp (or separators org-contacts-property-values-separators))
-        (inputlist (split-string string rexp omit-nulls))
-        (linkstring "")
-        (bufferstring "")
-        (proplist (list "")))
-    (while inputlist
-      (setq bufferstring (pop inputlist))
-      (if (string-match "\\[\\[" bufferstring)
-          (progn
-            (setq linkstring (concat bufferstring " "))
-            (while (not (string-match "\\]\\]" bufferstring))
-              (setq bufferstring (pop inputlist))
-              (setq linkstring (concat  linkstring bufferstring " ")))
-            (setq proplist (cons (org-trim linkstring) proplist)))
-        (setq proplist (cons bufferstring proplist))))
-    (cdr (reverse proplist))))
-
-(provide 'org-contacts)
-
-;;; org-contacts.el ends here
diff --git a/contrib/lisp/org-contribdir.el b/contrib/lisp/org-contribdir.el
deleted file mode 100644
index 0a26513..0000000
--- a/contrib/lisp/org-contribdir.el
+++ /dev/null
@@ -1,38 +0,0 @@
-;;; org-contribdir.el --- Mark the location of the contrib directory
-;; Copyright (C) 2009-2021 Free Software Foundation, Inc.
-;;
-;; Author: Carsten Dominik <carsten at orgmode dot org>
-;; Keywords: outlines, hypermedia, calendar, wp
-;; Homepage: https://orgmode.org
-;; Version: 0.01
-;;
-;; This file is not yet 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, 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:
-;;
-
-;; The sole purpose of this file is to be located in the same place
-;; as where the contributed Org files are located, typically in the
-;; contrib/lisp directory of the Org-mode distribution.  This is to
-;; make sure that the command `org-reload' can reliably locate
-;; contributed org files.
-
-(provide 'org-contribdir)
-
-;;; org-contribdir.el ends here
diff --git a/contrib/lisp/org-depend.el b/contrib/lisp/org-depend.el
deleted file mode 100644
index 8cbf000..0000000
--- a/contrib/lisp/org-depend.el
+++ /dev/null
@@ -1,431 +0,0 @@
-;;; org-depend.el --- TODO dependencies for Org-mode
-;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
-;;
-;; Author: Carsten Dominik <carsten at orgmode dot org>
-;; Keywords: outlines, hypermedia, calendar, wp
-;; Homepage: https://orgmode.org
-;; Version: 0.08
-;;
-;; This file is not part of GNU Emacs.
-;;
-;; This file 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:
-;;
-;; WARNING: This file is just a PROOF OF CONCEPT, not a supported part
-;;          of Org-mode.
-;;
-;; This is an example implementation of TODO dependencies in Org-mode.
-;; It uses the new hooks in version 5.13 of Org-mode,
-;; `org-trigger-hook' and `org-blocker-hook'.
-;;
-;; It implements the following:
-;;
-;; Triggering
-;; ----------
-;;
-;; 1) If an entry contains a TRIGGER property that contains the string
-;;    "chain-siblings(KEYWORD)", then switching that entry to DONE does
-;;    do the following:
-;;    - The sibling following this entry switched to todo-state KEYWORD.
-;;    - The sibling also gets a TRIGGER property "chain-sibling(KEYWORD)",
-;;      property, to make sure that, when *it* is DONE, the chain will
-;;      continue.
-;;
-;; 2) If an entry contains a TRIGGER property that contains the string
-;;    "chain-siblings-scheduled", then switching that entry to DONE does
-;;    the following actions, similarly to "chain-siblings(KEYWORD)":
-;;    - The sibling receives the same scheduled time as the entry
-;;      marked as DONE (or, in the case, in which there is no scheduled
-;;      time, the sibling does not get any either).
-;;    - The sibling also gets the same TRIGGER property
-;;      "chain-siblings-scheduled", so the chain can continue.
-;;
-;; 3) If the TRIGGER property contains the string
-;;    "chain-find-next(KEYWORD[,OPTIONS])", then switching that entry
-;;    to DONE do the following:
-;;    - All siblings are of the entry are collected into a temporary
-;;      list and then filtered and sorted according to OPTIONS
-;;    - The first sibling on the list is changed into KEYWORD state
-;;    - The sibling also gets the same TRIGGER property
-;;      "chain-find-next", so the chain can continue.
-;;
-;;    OPTIONS should be a comma separated string without spaces, and
-;;    can contain following options:
-;;
-;;    - from-top      the candidate list is all of the siblings in
-;;                    the current subtree
-;;
-;;    - from-bottom   candidate list are all siblings from bottom up
-;;
-;;    - from-current  candidate list are all siblings from current item
-;;                    until end of subtree, then wrapped around from
-;;                    first sibling
-;;
-;;    - no-wrap       candidate list are siblings from current one down
-;;
-;;    - todo-only     Only consider siblings that have a todo keyword
-;;    -
-;;    - todo-and-done-only
-;;                    Same as above but also include done items.
-;;
-;;    - priority-up   sort by highest priority
-;;    - priority-down sort by lowest priority
-;;    - effort-up     sort by highest effort
-;;    - effort-down   sort by lowest effort
-;;
-;;    Default OPTIONS are from-top
-;;
-;;
-;; 4) If the TRIGGER property contains any other words like
-;;    XYZ(KEYWORD), these are treated as entry id's with keywords.  That
-;;    means Org-mode will search for an entry with the ID property XYZ
-;;    and switch that entry to KEYWORD as well.
-;;
-;; Blocking
-;; --------
-;;
-;; 1) If an entry contains a BLOCKER property that contains the word
-;;    "previous-sibling", the sibling above the current entry is
-;;    checked when you try to mark it DONE.  If it is still in a TODO
-;;    state, the current state change is blocked.
-;;
-;; 2) If the BLOCKER property contains any other words, these are
-;;    treated as entry id's.  That means Org-mode will search for an
-;;    entry with the ID property exactly equal to this word.  If any
-;;    of these entries is not yet marked DONE, the current state change
-;;    will be blocked.
-;;
-;; 3) Whenever a state change is blocked, an org-mark is pushed, so that
-;;    you can find the offending entry with `C-c &'.
-;;
-;;; Example:
-;;
-;; When trying this example, make sure that the settings for TODO keywords
-;; have been activated, i.e. include the following line and press C-c C-c
-;; on the line before working with the example:
-;;
-;; #+TYP_TODO: TODO NEXT | DONE
-;;
-;; * TODO Win a million in Las Vegas
-;;   The "third" TODO (see above) cannot become a TODO without this money.
-;;
-;;   :PROPERTIES:
-;;     :ID: I-cannot-do-it-without-money
-;;   :END:
-;;
-;; * Do this by doing a chain of TODO's
-;; ** NEXT This is the first in this chain
-;;    :PROPERTIES:
-;;      :TRIGGER: chain-siblings(NEXT)
-;;    :END:
-;;
-;; ** This is the second in this chain
-;;
-;; ** This is the third in this chain
-;;    :PROPERTIES:
-;;      :BLOCKER: I-cannot-do-it-without-money
-;;    :END:
-;;
-;; ** This is the forth in this chain
-;;    When this is DONE, we will also trigger entry XYZ-is-my-id
-;;   :PROPERTIES:
-;;     :TRIGGER: XYZ-is-my-id(TODO)
-;;   :END:
-;;
-;; ** This is the fifth in this chain
-;;
-;; * Start writing report
-;;   :PROPERTIES:
-;;     :ID: XYZ-is-my-id
-;;   :END:
-;;
-;;
-
-(require 'org)
-(eval-when-compile
-  (require 'cl))
-
-(defcustom org-depend-tag-blocked t
-  "Whether to indicate blocked TODO items by a special tag."
-  :group 'org
-  :type 'boolean)
-
-(defcustom org-depend-find-next-options
-  "from-current,todo-only,priority-up"
-  "Default options for chain-find-next trigger"
-  :group 'org
-  :type 'string)
-
-(defmacro org-depend-act-on-sibling (trigger-val &rest rest)
-  "Perform a set of actions on the next sibling, if it exists,
-copying the sibling spec TRIGGER-VAL to the next sibling."
-  `(catch 'exit
-     (save-excursion
-       (goto-char pos)
-       ;; find the sibling, exit if no more siblings
-       (condition-case nil
-           (outline-forward-same-level 1)
-         (error (throw 'exit t)))
-       ;; mark the sibling TODO
-       ,@rest
-       ;; make sure the sibling will continue the chain
-       (org-entry-add-to-multivalued-property
-        nil "TRIGGER" ,trigger-val))))
-
-(defvar org-depend-doing-chain-find-next nil)
-
-(defun org-depend-trigger-todo (change-plist)
-  "Trigger new TODO entries after the current is switched to DONE.
-This does two different kinds of triggers:
-
-- If the current entry contains a TRIGGER property that contains
-  \"chain-siblings(KEYWORD)\", it goes to the next sibling, marks it
-  KEYWORD and also installs the \"chain-sibling\" trigger to continue
-  the chain.
-- If the current entry contains a TRIGGER property that contains
-  \"chain-siblings-scheduled\", we go to the next sibling and copy
-  the scheduled time from the current task, also installing the property
-  in the sibling.
-- Any other word (space-separated) like XYZ(KEYWORD) in the TRIGGER
-  property is seen as an entry id.  Org-mode finds the entry with the
-  corresponding ID property and switches it to the state TODO as well."
-
-  ;; Refresh the effort text properties
-  (org-refresh-properties org-effort-property 'org-effort)
-  ;; Get information from the plist
-  (let* ((type (plist-get change-plist :type))
-        (pos (plist-get change-plist :position))
-        (from (plist-get change-plist :from))
-        (to (plist-get change-plist :to))
-        (org-log-done nil) ; IMPORTANT!: no logging during automatic trigger!
-        trigger triggers tr p1 p2 kwd id)
-    (catch 'return
-      (unless (eq type 'todo-state-change)
-       ;; We are only handling todo-state-change....
-       (throw 'return t))
-      (unless (and (member from org-not-done-keywords)
-                  (member to org-done-keywords))
-       ;; This is not a change from TODO to DONE, ignore it
-       (throw 'return t))
-
-      ;; OK, we just switched from a TODO state to a DONE state
-      ;; Lets see if this entry has a TRIGGER property.
-      ;; If yes, split it up on whitespace.
-      (setq trigger (org-entry-get pos "TRIGGER")
-           triggers (and trigger (split-string trigger)))
-
-      ;; Go through all the triggers
-      (while (setq tr (pop triggers))
-       (cond
-        ((and (not org-depend-doing-chain-find-next)
-              (string-match "\\`chain-find-next(\\b\\(.+?\\)\\b\\(.*\\))\\'" 
tr))
-         ;; smarter sibling selection
-         (let* ((org-depend-doing-chain-find-next t)
-                (kwd (match-string 1 tr))
-                (options (match-string 2 tr))
-                (options (if (or (null options)
-                                 (equal options ""))
-                             org-depend-find-next-options
-                           options))
-                (todo-only (string-match "todo-only" options))
-                (todo-and-done-only (string-match "todo-and-done-only"
-                                                  options))
-                (from-top (string-match "from-top" options))
-                (from-bottom (string-match "from-bottom" options))
-                (from-current (string-match "from-current" options))
-                (no-wrap (string-match "no-wrap" options))
-                (priority-up (string-match "priority-up" options))
-                (priority-down (string-match "priority-down" options))
-                (effort-up (string-match "effort-up" options))
-                (effort-down (string-match "effort-down" options)))
-           (save-excursion
-             (org-back-to-heading t)
-             (let ((this-item (point)))
-               ;; go up to the parent headline, then advance to next child
-               (org-up-heading-safe)
-               (let ((end (save-excursion (org-end-of-subtree t)
-                                          (point)))
-                     (done nil)
-                     (items '()))
-                 (outline-next-heading)
-                 (while (not done)
-                   (if (not (looking-at org-complex-heading-regexp))
-                       (setq done t)
-                     (let ((todo-kwd (match-string 2))
-                           (tags (match-string 5))
-                           (priority (org-get-priority (or (match-string 3) 
"")))
-                           (effort (when (or effort-up effort-down)
-                                     (let ((effort (get-text-property (point) 
'org-effort)))
-                                       (when effort
-                                         (org-duration-to-minutes effort))))))
-                       (push (list (point) todo-kwd priority tags effort)
-                             items))
-                     (unless (org-goto-sibling)
-                       (setq done t))))
-                 ;; massage the list according to options
-                 (setq items
-                       (cond (from-top (nreverse items))
-                             (from-bottom items)
-                             ((or from-current no-wrap)
-                              (let* ((items (nreverse items))
-                                     (pos (position this-item items :key 
#'first))
-                                     (items-before (subseq items 0 pos))
-                                     (items-after (subseq items pos)))
-                                (if no-wrap items-after
-                                  (append items-after items-before))))
-                             (t (nreverse items))))
-                 (setq items (remove-if
-                              (lambda (item)
-                                (or (equal (first item) this-item)
-                                    (and (not todo-and-done-only)
-                                         (member (second item) 
org-done-keywords))
-                                    (and (or todo-only
-                                             todo-and-done-only)
-                                         (null (second item)))))
-                              items))
-                 (setq items
-                       (sort
-                        items
-                        (lambda (item1 item2)
-                          (let* ((p1 (third item1))
-                                 (p2 (third item2))
-                                 (e1 (fifth item1))
-                                 (e2 (fifth item2))
-                                 (p1-lt (< p1 p2))
-                                 (p1-gt (> p1 p2))
-                                 (e1-lt (and e1 (or (not e2) (< e1 e2))))
-                                 (e2-gt (and e2 (or (not e1) (> e1 e2)))))
-                            (cond (priority-up
-                                   (or p1-gt
-                                       (and (equal p1 p2)
-                                            (or (and effort-up e1-lt)
-                                                (and effort-down e2-gt)))))
-                                  (priority-down
-                                   (or p1-lt
-                                       (and (equal p1 p2)
-                                            (or (and effort-up e1-lt)
-                                                (and effort-down e2-gt)))))
-                                  (effort-up
-                                   (or e2-gt (and (equal e1 e2) p1-gt)))
-                                  (effort-down
-                                   (or e1-lt (and (equal e1 e2) p1-gt))))))))
-                 (when items
-                   (goto-char (first (first items)))
-                   (org-entry-add-to-multivalued-property nil "TRIGGER" tr)
-                   (org-todo kwd)))))))
-        ((string-match "\\`chain-siblings(\\(.*?\\))\\'" tr)
-         ;; This is a TODO chain of siblings
-         (setq kwd (match-string 1 tr))
-          (org-depend-act-on-sibling (format "chain-siblings(%s)" kwd)
-                                     (org-todo kwd)))
-        ((string-match "\\`\\(\\S-+\\)(\\(.*?\\))\\'" tr)
-         ;; This seems to be ENTRY_ID(KEYWORD)
-         (setq id (match-string 1 tr)
-               kwd (match-string 2 tr)
-               p1 (org-find-entry-with-id id))
-         ;; First check current buffer, then all files.
-         (if p1
-             ;; There is an entry with this ID, mark it TODO.
-             (save-excursion
-               (goto-char p1)
-               (org-todo kwd))
-           (when (setq p2 (org-id-find id))
-             (save-excursion
-               (with-current-buffer (find-file-noselect (car p2))
-                 (goto-char (cdr p2))
-                 (org-todo kwd))))))
-         ((string-match "\\`chain-siblings-scheduled\\'" tr)
-          (let ((time (org-get-scheduled-time pos)))
-            (when time
-              (org-depend-act-on-sibling
-               "chain-siblings-scheduled"
-               (org-schedule nil time))))))))))
-
-(defun org-depend-block-todo (change-plist)
-  "Block turning an entry into a TODO.
-This checks for a BLOCKER property in an entry and checks
-all the entries listed there.  If any of them is not done,
-block changing the current entry into a TODO entry.  If the property contains
-the word \"previous-sibling\", the sibling above the current entry is checked.
-Any other words are treated as entry id's. If an entry exists with the
-this ID property, that entry is also checked."
-  ;; Get information from the plist
-  (let* ((type (plist-get change-plist :type))
-        (pos (plist-get change-plist :position))
-        (from (plist-get change-plist :from))
-        (to (plist-get change-plist :to))
-        (org-log-done nil) ; IMPORTANT!: no logging during automatic trigger
-        blocker blockers bl p1 p2
-        (proceed-p
-         (catch 'return
-            ;; If this is not a todo state change, or if this entry is
-            ;; DONE, do not block
-            (when (or (not (eq type 'todo-state-change))
-                      (member from (cons 'done org-done-keywords))
-                      (member to (cons 'todo org-not-done-keywords))
-                      (not to))
-              (throw 'return t))
-
-           ;; OK, the plan is to switch from nothing to TODO
-           ;; Lets see if we will allow it.  Find the BLOCKER property
-           ;; and split it on whitespace.
-           (setq blocker (org-entry-get pos "BLOCKER")
-                 blockers (and blocker (split-string blocker)))
-
-           ;; go through all the blockers
-           (while (setq bl (pop blockers))
-             (cond
-              ((equal bl "previous-sibling")
-               ;; the sibling is required to be DONE.
-               (catch 'ignore
-                 (save-excursion
-                   (goto-char pos)
-                   ;; find the older sibling, exit if no more siblings
-                   (unless (org-get-last-sibling)
-                     (throw 'ignore t))
-                   ;; Check if this entry is not yet done and block
-                   (unless (org-entry-is-done-p)
-                     ;; return nil, to indicate that we block the change!
-                     (org-mark-ring-push)
-                     (throw 'return nil)))))
-              ((setq p1 (org-find-entry-with-id bl))
-               ;; there is an entry with this ID, check it out
-               (save-excursion
-                 (goto-char p1)
-                 (unless (org-entry-is-done-p)
-                   ;; return nil, to indicate that we block the change!
-                   (org-mark-ring-push)
-                   (throw 'return nil))))
-              ((setq p2 (org-id-find bl))
-               (save-excursion
-                 (with-current-buffer (find-file-noselect (car p2))
-                   (goto-char (cdr p2))
-                   (unless (org-entry-is-done-p)
-                     (org-mark-ring-push)
-                     (throw 'return nil)))))))
-           ;; Return t to indicate that we are not blocking.
-           t)))
-    (when org-depend-tag-blocked
-      (org-toggle-tag "blocked" (if proceed-p 'off 'on)))
-
-    proceed-p))
-
-(add-hook 'org-trigger-hook 'org-depend-trigger-todo)
-(add-hook 'org-blocker-hook 'org-depend-block-todo)
-
-(provide 'org-depend)
-
-;;; org-depend.el ends here
diff --git a/contrib/lisp/org-effectiveness.el 
b/contrib/lisp/org-effectiveness.el
deleted file mode 100644
index 28793b8..0000000
--- a/contrib/lisp/org-effectiveness.el
+++ /dev/null
@@ -1,369 +0,0 @@
-;;; org-effectiveness.el --- Measuring the personal effectiveness
-
-;; Copyright (C) 2013-2021 Free Software Foundation, Inc.
-
-;; Author: David Arroyo Menรฉndez <davidam@es.gnu.org>
-;; Keywords: effectiveness, plot
-;; Homepage: https://orgmode.org
-;;
-;; This file is not part of GNU Emacs, yet.
-;;
-;; 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:
-
-;; This file implements functions to measure the effectiveness in org.
-;; Org-mode doesn't load this module by default - if this is not what
-;; you want, configure the variable `org-modules'. Thanks to #emacs-es
-;; irc channel for your support.
-
-;;; Code:
-
-(require 'org)
-
-(defcustom org-effectiveness-max-todo 50
-  "This variable is useful to advice to the user about
-many TODO pending"
-  :type 'integer
-  :group 'org-effectiveness)
-
-(defun org-effectiveness-advice()
-  "Advicing about a possible excess of TODOS"
-  (interactive)
-  (save-excursion
-    (goto-char (point-min))
-    (if (< org-effectiveness-max-todo (count-matches "* TODO"))
-       (message "An excess of TODOS!"))))
-
-;; Check advice starting an org file
-(add-hook 'org-mode-hook 'org-effectiveness-advice)
-
-(defun org-effectiveness-count-keyword(keyword)
-  "Print a message with the number of keyword outline in the current buffer"
-  (interactive "sKeyword: ")
-  (save-excursion
-    (goto-char (point-min))
-    (message "Number of %s: %d" keyword (count-matches (concat "* " 
keyword)))))
-
-(defun org-effectiveness-count-todo()
-  "Print a message with the number of todo tasks in the current buffer"
-  (interactive)
-  (save-excursion
-    (goto-char (point-min))
-    (message "Number of TODO: %d" (count-matches "* TODO"))))
-
-(defun org-effectiveness-count-done()
-  "Print a message with the number of done tasks in the current buffer"
-  (interactive)
-  (save-excursion
-    (goto-char (point-min))
-    (message "Number of DONE: %d" (count-matches "* DONE"))))
-
-(defun org-effectiveness-count-canceled()
-  "Print a message with the number of canceled tasks in the current buffer"
-  (interactive)
-  (save-excursion
-    (goto-char (point-min))
-    (message "Number of Canceled: %d" (count-matches "* CANCEL+ED"))))
-
-(defun org-effectiveness-count-task()
-  "Print a message with the number of tasks and subtasks in the current buffer"
-  (interactive)
-  (save-excursion
-    (goto-char (point-min))
-    (message "Number of tasks: %d" (count-matches "^*"))))
-
-(defun org-effectiveness()
-  "Returns the effectiveness in the current org buffer"
-  (interactive)
-  (save-excursion
-    (goto-char (point-min))
-    (let ((done (float (count-matches "* DONE.*\n.*")))
-         (canc (float (count-matches "* CANCEL+ED.*\n.*"))))
-      (if (and (= done canc) (zerop done))
-         (setq effectiveness 0)
-       (setq effectiveness (* 100 (/ done (+ done canc)))))
-      (message "Effectiveness: %f" effectiveness))))
-
-
-(defun org-effectiveness-keywords-in-date(keyword date)
-  (interactive "sKeyword: \nsDate: " keyword date)
-  (setq count (count-matches (concat keyword ".*\n.*" date)))
-  (message (concat "%sS: %d" keyword count)))
-
-(defun org-effectiveness-dones-in-date(date &optional notmessage)
-  (interactive "sGive me a date: " date)
-  (save-excursion
-    (goto-char (point-min))
-    (let ((count (count-matches (concat "DONE.*\n.*" date))))
-      (if (eq notmessage 1)
-         (message "%d" count)
-       (message "DONES: %d " count)))))
-
-(defun org-effectiveness-todos-in-date(date)
-  (interactive "sGive me a date: " date)
-  (save-excursion
-    (goto-char (point-min))
-    (setq count (count-matches (concat "TODO.*\n.*" date)))
-    (message "TODOS: %d" count)))
-
-(defun org-effectiveness-canceled-in-date(date)
-  (interactive "sGive me a date: " date)
-  (save-excursion
-    (goto-char (point-min))
-    (setq count (count-matches (concat "CANCEL+ED.*\n.*" date)))
-    (message "CANCELEDS: %d" count)))
-
-(defun org-effectiveness-ntasks-in-date(date &optional notmessage)
-  (interactive "sGive me a date: " date)
-  (save-excursion
-    (goto-char (point-min))
-    (let ((tasks (float (count-matches (concat "^*.*\n.*" date)))))
-      (message "%d" tasks))))
-
-(defun org-effectiveness-in-date(date &optional notmessage)
-  (interactive "sGive me a date: " date)
-  (save-excursion
-    (goto-char (point-min))
-    (let ((done (float (count-matches (concat "* DONE.*\n.*" date))))
-         (canc (float (count-matches (concat "* CANCEL+ED.*\n.*" date)))))
-      (if (and (= done canc) (zerop done))
-         (setq effectiveness 0)
-       (setq effectiveness (* 100 (/ done (+ done canc)))))
-      (if (eq notmessage 1)
-         (message "%d" effectiveness)
-       (message "Effectiveness: %d " effectiveness)))))
-
-(defun org-effectiveness-month-to-string (m)
-  (if (< m 10)
-      (concat "0" (number-to-string m))
-    (number-to-string m)))
-
-(defun org-effectiveness-plot(startdate enddate &optional save)
-  (interactive "sGive me the start date: \nsGive me the end date: " startdate 
enddate)
-  (setq dates (org-effectiveness-check-dates startdate enddate))
-  (setq syear (cadr (assq 'startyear dates)))
-  (setq smonth (cadr (assq 'startmonth dates)))
-  (setq eyear (cadr (assq 'endyear dates)))
-  (setq emonth (assq 'endmonth dates))
-;; Checking the format of the dates
-  (if (not (string-match "[0-9][0-9][0-9][0-9]-[0-9][0-9]" startdate))
-      (message "The start date must have the next format YYYY-MM"))
-  (if (not (string-match "[0-9][0-9][0-9][0-9]-[0-9][0-9]" enddate))
-      (message "The end date must have the next format YYYY-MM"))
-;; Checking if startdate < enddate
-  (if (string-match "^[0-9][0-9][0-9][0-9]" startdate)
-      (setq startyear (string-to-number (match-string 0 startdate))))
-  (if (string-match "[0-9][0-9]$" startdate)
-      (setq startmonth (string-to-number (match-string 0 startdate))))
-  (if (string-match "^[0-9][0-9][0-9][0-9]" enddate)
-      (setq endyear (string-to-number (match-string 0 enddate))))
-  (if (string-match "[0-9][0-9]$" enddate)
-      (setq endmonth (string-to-number (match-string 0 enddate))))
-  (if (> startyear endyear)
-       (message "The start date must be before that end date"))
-  (if (and (= startyear endyear) (> startmonth endmonth))
-      (message "The start date must be before that end date"))
-;; Create a file
-  (let ((month startmonth)
-       (year startyear)
-       (str ""))
-    (while (or (> endyear year) (and (= endyear year) (>= endmonth month)))
-      (setq str (concat str (number-to-string year) "-" 
(org-effectiveness-month-to-string month) " " (org-effectiveness-in-date 
(concat (number-to-string year) "-" (org-effectiveness-month-to-string month)) 
1) "\n"))
-      (if (= month 12)
-         (progn
-           (setq year (+ 1 year))
-           (setq month 1))
-       (setq month (+ 1 month))))
-      (write-region str nil "/tmp/org-effectiveness"))
-;; Create the bar graph
-  (if (eq save t)
-      (setq strplot "/usr/bin/gnuplot -e 'set term png; set output 
\"/tmp/org-effectiveness.png\"; plot \"/tmp/org-effectiveness\" using 
2:xticlabels(1) with histograms' -p")
-    (setq strplot "/usr/bin/gnuplot -e 'plot \"/tmp/org-effectiveness\" using 
2:xticlabels(1) with histograms' -p"))
-  (if (file-exists-p "/usr/bin/gnuplot")
-      (call-process "/bin/bash" nil t nil "-c" strplot)
-    (message "gnuplot is not installed")))
-
-(defun org-effectiveness-plot-save(startdate enddate &optional save)
-  (interactive "sGive me the start date: \nsGive me the end date: " startdate 
enddate)
-  (org-effectiveness-plot startdate enddate t))
-
-;; (defun org-effectiveness-plot(startdate enddate)
-
-
-(defun org-effectiveness-ascii-bar(n &optional label)
-  "Print a bar with the percentage from 0 to 100 printed in ascii"
-  (interactive "nPercentage: \nsLabel: ")
-  (if (or (< n 0) (> n 100))
-      (message "The percentage must be between 0 to 100")
-    (let ((x 0)
-         (y 0)
-         (z 0))
-      (insert (format "\n### %s ###" label))
-      (insert "\n-")
-      (while (< x n)
-       (insert "-")
-       (setq x (+ x 1)))
-      (insert "+\n")
-      (insert (format "%d" n))
-      (if (> n 10)
-         (setq y (+ y 1)))
-      (while (< y n)
-       (insert " ")
-       (setq y (+ y 1)))
-      (insert "|\n")
-      (insert "-")
-      (while (< z n)
-       (insert "-")
-       (setq z (+ z 1)))
-      (insert "+"))))
-
-(defun org-effectiveness-html-bar(n &optional label)
-  "Print a bar with the percentage from 0 to 100 printed in html"
-  (interactive "nPercentage: \nsLabel: ")
-  (if (or (< n 0) (> n 100))
-      (message "The percentage must be between 0 to 100")
-    (let ((x 0)
-         (y 0)
-         (z 0))
-      (insert (format "\n<div class='percentage-%d'>%d</div>" n n))
-)))
-
-
-(defun org-effectiveness-check-dates (startdate enddate)
-  "Generate a list with ((startyear startmonth) (endyear endmonth))"
-  (setq str nil)
-  (if (not (string-match "[0-9][0-9][0-9][0-9]-[0-9][0-9]" startdate))
-      (setq str "The start date must have the next format YYYY-MM"))
-  (if (not (string-match "[0-9][0-9][0-9][0-9]-[0-9][0-9]" enddate))
-      (setq str "The end date must have the next format YYYY-MM"))
-;; Checking if startdate < enddate
-  (if (string-match "^[0-9][0-9][0-9][0-9]" startdate)
-      (setq startyear (string-to-number (match-string 0 startdate))))
-  (if (string-match "[0-9][0-9]$" startdate)
-      (setq startmonth (string-to-number (match-string 0 startdate))))
-  (if (string-match "^[0-9][0-9][0-9][0-9]" enddate)
-      (setq endyear (string-to-number (match-string 0 enddate))))
-  (if (string-match "[0-9][0-9]$" enddate)
-      (setq endmonth (string-to-number (match-string 0 enddate))))
-  (if (> startyear endyear)
-      (setq str "The start date must be before that end date"))
-  (if (and (= startyear endyear) (> startmonth endmonth))
-      (setq str "The start date must be before that end date"))
-  (if str
-      (message str)
-;;    (list (list startyear startmonth) (list endyear endmonth))))
-    (list (list 'startyear startyear) (list 'startmonth startmonth) (list 
'endyear endyear) (list 'endmonth endmonth))))
-
-(defun org-effectiveness-plot-ascii (startdate enddate)
-  (interactive "sGive me the start date: \nsGive me the end date: " startdate 
enddate)
-  (setq dates (org-effectiveness-check-dates startdate enddate))
-  (let ((syear (cadr (assq 'startyear dates)))
-       (smonth (cadr (assq 'startmonth dates)))
-       (year (cadr (assq 'startyear dates)))
-       (month (cadr (assq 'startmonth dates)))
-       (emonth (cadr (assq 'endmonth dates)))
-       (eyear (cadr (assq 'endyear dates)))
-       (buffer (current-buffer))
-       (str ""))
-    (while (or (> eyear year) (and (= eyear year) (>= emonth month)))
-      (setq str (org-effectiveness-in-date (concat (number-to-string year) "-" 
(org-effectiveness-month-to-string month)) 1))
-      (switch-to-buffer "*org-effectiveness*")
-      (org-effectiveness-ascii-bar (string-to-number str) (format "%s-%s" year 
month))
-      (switch-to-buffer buffer)
-      (if (eq month 12)
-         (progn
-           (setq year (+ 1 year))
-           (setq month 1))
-       (setq month (+ 1 month)))))
-  (switch-to-buffer "*org-effectiveness*"))
-
-
-(defun org-effectiveness-plot-ascii-ntasks (startdate enddate)
-  (interactive "sGive me the start date: \nsGive me the end date: " startdate 
enddate)
-  (setq dates (org-effectiveness-check-dates startdate enddate))
-  (let ((syear (cadr (assq 'startyear dates)))
-       (smonth (cadr (assq 'startmonth dates)))
-       (year (cadr (assq 'startyear dates)))
-       (month (cadr (assq 'startmonth dates)))
-       (emonth (cadr (assq 'endmonth dates)))
-       (eyear (cadr (assq 'endyear dates)))
-       (buffer (current-buffer))
-       (str ""))
-    (while (or (> eyear year) (and (= eyear year) (>= emonth month)))
-      (setq str (org-effectiveness-ntasks-in-date (concat (number-to-string 
year) "-" (org-effectiveness-month-to-string month)) 1))
-      (switch-to-buffer "*org-effectiveness*")
-      (org-effectiveness-ascii-bar (string-to-number str) (format "%s-%s" year 
month))
-      (switch-to-buffer buffer)
-      (if (eq month 12)
-         (progn
-           (setq year (+ 1 year))
-           (setq month 1))
-       (setq month (+ 1 month)))))
-  (switch-to-buffer "*org-effectiveness*"))
-
-(defun org-effectiveness-plot-ascii-dones (startdate enddate)
-  (interactive "sGive me the start date: \nsGive me the end date: " startdate 
enddate)
-  (setq dates (org-effectiveness-check-dates startdate enddate))
-  (let ((syear (cadr (assq 'startyear dates)))
-       (smonth (cadr (assq 'startmonth dates)))
-       (year (cadr (assq 'startyear dates)))
-       (month (cadr (assq 'startmonth dates)))
-       (emonth (cadr (assq 'endmonth dates)))
-       (eyear (cadr (assq 'endyear dates)))
-       (buffer (current-buffer))
-       (str ""))
-    (while (or (> eyear year) (and (= eyear year) (>= emonth month)))
-      (setq str (org-effectiveness-dones-in-date (concat (number-to-string 
year) "-" (org-effectiveness-month-to-string month)) 1))
-      (switch-to-buffer "*org-effectiveness*")
-      (org-effectiveness-ascii-bar (string-to-number str) (format "%s-%s" year 
month))
-      (switch-to-buffer buffer)
-      (if (eq month 12)
-         (progn
-           (setq year (+ 1 year))
-           (setq month 1))
-       (setq month (+ 1 month)))))
-  (switch-to-buffer "*org-effectiveness*"))
-
-
-(defun org-effectiveness-plot-html (startdate enddate)
-  "Print html bars about the effectiveness in a buffer"
-  (interactive "sGive me the start date: \nsGive me the end date: " startdate 
enddate)
-  (setq dates (org-effectiveness-check-dates startdate enddate))
-  (let ((syear (cadr (assq 'startyear dates)))
-       (smonth (cadr (assq 'startmonth dates)))
-       (year (cadr (assq 'startyear dates)))
-       (month (cadr (assq 'startmonth dates)))
-       (emonth (cadr (assq 'endmonth dates)))
-       (eyear (cadr (assq 'endyear dates)))
-       (buffer (current-buffer))
-       (str ""))
-    (switch-to-buffer "*org-effectiveness-html*")
-    (insert "<html><head><title>Graphbar</title><meta 
http-equiv='Content-type' content='text/html; charset=utf-8'><link 
rel='stylesheet' type='text/css' href='graphbar.css' 
title='graphbar'></head><body>")
-    (while (or (> eyear year) (and (= eyear year) (>= emonth month)))
-      (setq str (org-effectiveness-in-date (concat (number-to-string year) "-" 
(org-effectiveness-month-to-string month)) 1))
-      (switch-to-buffer "*org-effectiveness-html*")
-      (org-effectiveness-html-bar (string-to-number str) (format "%s-%s" year 
month))
-      (switch-to-buffer buffer)
-      (format "%s-%s" year month)
-      (if (eq month 12)
-         (progn
-           (setq year (+ 1 year))
-           (setq month 1))
-       (setq month (+ 1 month))))
-    (switch-to-buffer "*org-effectiveness-html*")
-    (insert "</body></html>")))
-
-(provide 'org-effectiveness)
diff --git a/contrib/lisp/org-eldoc.el b/contrib/lisp/org-eldoc.el
deleted file mode 100644
index b9b4460..0000000
--- a/contrib/lisp/org-eldoc.el
+++ /dev/null
@@ -1,203 +0,0 @@
-;;; org-eldoc.el --- display org header and src block info using eldoc -*- 
lexical-binding: t; -*-
-
-;; Copyright (c) 2014-2021 Free Software Foundation, Inc.
-
-;; Author: ลukasz Gruner <lukasz@gruner.lu>
-;; Maintainer: ลukasz Gruner <lukasz@gruner.lu>
-;; Version: 6
-;; Package-Requires: ((org "8"))
-;; URL: https://bitbucket.org/ukaszg/org-eldoc
-;; Created: 25/05/2014
-;; Keywords: eldoc, outline, breadcrumb, org, babel, minibuffer
-
-;; This file is not part of 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:
-
-;;; Changelog:
-
-;; As of 01/11/14 switching license to GPL3 to allow submission to org-mode.
-;; 08/11/14 switch code to automatically define eldoc-documentation-function, 
but don't autostart eldoc-mode.
-
-;;; Code:
-
-(require 'org)
-(require 'ob-core)
-(require 'eldoc)
-
-(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))
-
-(defgroup org-eldoc nil "" :group 'org)
-
-(defcustom org-eldoc-breadcrumb-separator "/"
-  "Breadcrumb separator."
-  :group 'org-eldoc
-  :type 'string)
-
-(defcustom org-eldoc-test-buffer-name " *Org-eldoc test buffer*"
-  "Name of the buffer used while testing for mode-local variable values."
-  :group 'org-eldoc
-  :type 'string)
-
-(defun org-eldoc-get-breadcrumb ()
-  "Return breadcrumb if on a headline or nil."
-  (let ((case-fold-search t) cur)
-    (save-excursion
-      (beginning-of-line)
-      (save-match-data
-        (when (looking-at org-complex-heading-regexp)
-          (setq cur (match-string 4))
-          (org-format-outline-path
-           (append (org-get-outline-path) (list cur))
-           (frame-width) "" org-eldoc-breadcrumb-separator))))))
-
-(defun org-eldoc-get-src-header ()
-  "Returns lang and list of header properties if on src definition line and 
nil otherwise."
-  (let ((case-fold-search t) info lang hdr-args)
-    (save-excursion
-      (beginning-of-line)
-      (save-match-data
-        (when (looking-at "^[ \t]*#\\+\\(begin\\|end\\)_src")
-          (setq info (org-babel-get-src-block-info 'light)
-                lang (propertize (or (nth 0 info) "no lang") 'face 
'font-lock-string-face)
-                hdr-args (nth 2 info))
-          (concat
-           lang
-           ": "
-           (mapconcat
-            (lambda (elem)
-              (when (and (cdr elem) (not (string= "" (cdr elem))))
-                (concat
-                 (propertize (symbol-name (car elem)) 'face 'org-list-dt)
-                 " "
-                 (propertize (cdr elem) 'face 'org-verbatim)
-                 " ")))
-            hdr-args " ")))))))
-
-(defun org-eldoc-get-src-lang ()
-  "Return value of lang for the current block if in block body and nil 
otherwise."
-  (let ((element (save-match-data (org-element-at-point))))
-    (and (eq (org-element-type element) 'src-block)
-        (>= (line-beginning-position)
-            (org-element-property :post-affiliated element))
-        (<=
-         (line-end-position)
-         (org-with-wide-buffer
-          (goto-char (org-element-property :end element))
-          (skip-chars-backward " \t\n")
-          (line-end-position)))
-        (org-element-property :language element))))
-
-(defvar org-eldoc-local-functions-cache (make-hash-table :size 40 :test 'equal)
-  "Cache of major-mode's eldoc-documentation-functions,
- used by \\[org-eldoc-get-mode-local-documentation-function].")
-
-(defun org-eldoc-get-mode-local-documentation-function (lang)
-  "Check if LANG-mode sets eldoc-documentation-function and return its value."
-  (let ((cached-func (gethash lang org-eldoc-local-functions-cache 'empty))
-        (mode-func (org-src-get-lang-mode lang))
-        doc-func)
-    (if (eq 'empty cached-func)
-        (when (fboundp mode-func)
-         (with-temp-buffer
-           (funcall mode-func)
-           (setq doc-func (if (boundp 'eldoc-documentation-functions)
-                              (let ((doc-funs eldoc-documentation-functions))
-                                (lambda (callback)
-                                  (let ((eldoc-documentation-functions 
doc-funs))
-                                    (run-hook-with-args-until-success
-                                     'eldoc-documentation-functions
-                                     callback))))
-                            (and eldoc-documentation-function
-                                 (symbol-value 
'eldoc-documentation-function))))
-           (puthash lang doc-func org-eldoc-local-functions-cache))
-          doc-func)
-      cached-func)))
-
-(declare-function c-eldoc-print-current-symbol-info "c-eldoc" ())
-(declare-function css-eldoc-function "css-eldoc" ())
-(declare-function php-eldoc-function "php-eldoc" ())
-(declare-function go-eldoc--documentation-function "go-eldoc" ())
-
-(defun org-eldoc-documentation-function (&rest args)
-  "Return breadcrumbs when on a headline, args for src block header-line,
-  calls other documentation functions depending on lang when inside src body."
-  (or
-   (org-eldoc-get-breadcrumb)
-   (org-eldoc-get-src-header)
-   (let ((lang (org-eldoc-get-src-lang)))
-     (cond ((or
-             (string= lang "emacs-lisp")
-             (string= lang "elisp"))
-           (cond ((and (boundp 'eldoc-documentation-functions) ; Emacs>=28
-                       (fboundp 'elisp-eldoc-var-docstring)
-                       (fboundp 'elisp-eldoc-funcall))
-                  (let ((eldoc-documentation-functions
-                         '(elisp-eldoc-var-docstring elisp-eldoc-funcall)))
-                    (eldoc-print-current-symbol-info)))
-                 ((fboundp 'elisp-eldoc-documentation-function)
-                  (elisp-eldoc-documentation-function))
-                 (t                    ; Emacs<25
-                  (let (eldoc-documentation-function)
-                    (eldoc-print-current-symbol-info)))))
-           ((or
-             (string= lang "c") ;; http://github.com/nflath/c-eldoc
-             (string= lang "C")) (when (require 'c-eldoc nil t)
-                                   (c-eldoc-print-current-symbol-info)))
-           ;; https://github.com/zenozeng/css-eldoc
-           ((string= lang "css") (when (require 'css-eldoc nil t)
-                                   (css-eldoc-function)))
-           ;; https://github.com/zenozeng/php-eldoc
-           ((string= lang "php") (when (require 'php-eldoc nil t)
-                                   (php-eldoc-function)))
-           ((or
-             (string= lang "go")
-             (string= lang "golang")) (when (require 'go-eldoc nil t)
-                                        (go-eldoc--documentation-function)))
-           (t (let ((doc-fun (org-eldoc-get-mode-local-documentation-function 
lang))
-                   (callback (car args)))
-                (when (functionp doc-fun)
-                 (if (functionp callback)
-                     (funcall doc-fun callback)
-                   (funcall doc-fun)))))))))
-
-;;;###autoload
-(defun org-eldoc-load ()
-  "Set up org-eldoc documentation function."
-  (interactive)
-  ;; This approach is taken from python.el.
-  (with-no-warnings
-    (cond
-     ((null eldoc-documentation-function) ; Emacs<25
-      (setq-local eldoc-documentation-function
-                 #'org-eldoc-documentation-function))
-     ((boundp 'eldoc-documentation-functions) ; Emacs>=28
-      (add-hook 'eldoc-documentation-functions
-               #'org-eldoc-documentation-function nil t))
-     (t
-      (add-function :before-until (local 'eldoc-documentation-function)
-                   #'org-eldoc-documentation-function)))))
-
-;;;###autoload
-(add-hook 'org-mode-hook #'org-eldoc-load)
-
-(provide 'org-eldoc)
-
-;; -*- coding: utf-8-emacs; -*-
-
-;;; org-eldoc.el ends here
diff --git a/contrib/lisp/org-eval-light.el b/contrib/lisp/org-eval-light.el
deleted file mode 100644
index 6af4736..0000000
--- a/contrib/lisp/org-eval-light.el
+++ /dev/null
@@ -1,199 +0,0 @@
-;;; org-eval-light.el --- Display result of evaluating code in various 
languages (light)
-
-;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
-
-;; Author: Carsten Dominik <carsten at orgmode dot org>,
-;;         Eric Schulte <schulte dot eric at gmail dot com>
-;; Keywords: outlines, hypermedia, calendar, wp, literate programming,
-;;           reproducible research
-;; Homepage: https://orgmode.org
-;; Version: 0.04
-
-;; This file is not yet 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, 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:
-
-;; This file is based off of org-eval, with the following changes.
-;;
-;; 1) forms are only executed manually, (allowing for the execution of
-;;    an entire subtree of forms)
-;; 2) use the org-mode style src blocks, rather than the muse style
-;;    <code></code> blocks
-;; 3) forms are not replaced by their outputs, but rather the output
-;;    is placed in the buffer immediately following the src block
-;;    commented by `org-eval-light-make-region-example' (when
-;;    evaluated with a prefix argument no output is placed in the
-;;    buffer)
-;; 4) add defadvice to org-ctrl-c-ctrl-c so that when called inside of
-;;    a source block it will call `org-eval-light-current-snippet'
-
-;;; Code:
-(require 'org)
-
-(defgroup org-eval-light nil
-  "Options concerning including output from commands into the Org-mode buffer."
-  :tag "Org Eval"
-  :group 'org)
-
-(defvar org-eval-light-example-size-cutoff 10
-  "The number of lines under which an example is considered
-'small', and is exported with the '^:' syntax instead of in a
-large example block")
-
-(defvar org-eval-light-regexp nil)
-
-(defun org-eval-light-set-interpreters (var value)
-  (set-default var value)
-  (setq org-eval-light-regexp
-       (concat "#\\+begin_src \\("
-               (mapconcat 'regexp-quote value "\\|")
-               "\\)\\([^\000]+?\\)#\\+end_src")))
-
-(defcustom org-eval-light-interpreters '("lisp" "emacs-lisp" "ruby" "shell")
-  "Interpreters allows for evaluation tags.
-This is a list of program names (as strings) that can evaluate code and
-insert the output into an Org-mode buffer.  Valid choices are
-
-lisp    Interpret Emacs Lisp code and display the result
-shell   Pass command to the shell and display the result
-perl    The perl interpreter
-python  Thy python interpreter
-ruby    The ruby interpreter"
-  :group 'org-eval-light
-  :set 'org-eval-light-set-interpreters
-  :type '(set :greedy t
-             (const "lisp")
-             (const "emacs-lisp")
-             (const "perl")
-             (const "python")
-             (const "ruby")
-             (const "shell")))
-
-;;; functions
-(defun org-eval-light-inside-snippet ()
-  (interactive)
-  (save-excursion
-    (let ((case-fold-search t)
-         (start-re "^#\\+begin_src\\( \\([^ \t\n]+\\)\\)?.*\n")
-         (end-re "\n#\\+end_src")
-         (pos (point))
-         beg end)
-      (if (and (setq beg (re-search-backward start-re nil t))
-              (setq end (re-search-forward end-re nil t))
-              (<= beg pos) (>= end pos))
-         t))))
-
-(defun org-eval-light-make-region-example (beg end)
-  "Comment out region using either the '^:' or the BEGIN_EXAMPLE
-syntax based on the size of the region as compared to
-`org-eval-light-example-size-cutoff'."
-  (interactive "*r")
-  (let ((size (abs (- (line-number-at-pos end)
-                     (line-number-at-pos beg)))))
-    (if (= size 0)
-       (let ((result (buffer-substring beg end)))
-         (delete-region beg end)
-         (insert (concat ": " result)))
-      (if (<= size org-eval-light-example-size-cutoff)
-         (save-excursion
-           (goto-char beg)
-           (dotimes (n size)
-             (move-beginning-of-line 1) (insert ": ") (forward-line 1)))
-       (let ((result (buffer-substring beg end)))
-         (delete-region beg end)
-         (insert (concat "#+BEGIN_EXAMPLE\n" result "#+END_EXAMPLE\n")))))))
-
-(defun org-eval-light-current-snippet (&optional arg)
-  "Execute the current #+begin_src #+end_src block, and dump the
-results into the buffer immediately following the src block,
-commented by `org-eval-light-make-region-example'."
-  (interactive "P")
-  (let ((line (org-current-line))
-       (case-fold-search t)
-       (info (org-edit-src-find-region-and-lang))
-       beg end lang result)
-    (setq beg (nth 0 info)
-           end (nth 1 info)
-           lang (nth 2 info))
-    (unless (member lang org-eval-light-interpreters)
-      (error "Language is not in `org-eval-light-interpreters': %s" lang))
-    (goto-line line)
-    (setq result (org-eval-light-code lang (buffer-substring beg end)))
-    (unless arg
-      (save-excursion
-      (re-search-forward "^#\\+end_src" nil t) (open-line 1) (forward-char 2)
-      (let ((beg (point))
-           (end (progn (insert result)
-                       (point))))
-       (message (format "from %S %S" beg end))
-       (org-eval-light-make-region-example beg end))))))
-
-(defun org-eval-light-eval-subtree (&optional arg)
-  "Replace EVAL snippets in the entire subtree."
-  (interactive "P")
-  (save-excursion
-    (org-narrow-to-subtree)
-    (goto-char (point-min))
-    (while (re-search-forward org-eval-light-regexp nil t)
-      (org-eval-light-current-snippet arg))
-    (widen)))
-
-(defun org-eval-light-code (interpreter code)
-  (cond
-   ((member interpreter '("lisp" "emacs-lisp"))
-    (org-eval-light-lisp (concat "(progn\n" code "\n)")))
-   ((equal interpreter "shell")
-    (shell-command-to-string code))
-   ((member interpreter '("perl" "python" "ruby"))
-    (org-eval-light-run (executable-find interpreter) code))
-   (t (error "Cannot evaluate code type %s" interpreter))))
-
-(defun org-eval-light-lisp (form)
-  "Evaluate the given form and return the result as a string."
-  (require 'pp)
-  (save-match-data
-    (condition-case err
-        (let ((object (eval (read form))))
-          (cond
-           ((stringp object) object)
-           ((and (listp object)
-                 (not (eq object nil)))
-            (let ((string (pp-to-string object)))
-              (substring string 0 (1- (length string)))))
-           ((numberp object)
-            (number-to-string object))
-           ((eq object nil) "")
-           (t
-            (pp-to-string object))))
-      (error
-       (org-display-warning (format "%s: Error evaluating %s: %s"
-                                     "???" form err))
-       "; INVALID LISP CODE"))))
-
-(defun org-eval-light-run (cmd code)
-  (with-temp-buffer
-    (insert code)
-    (shell-command-on-region (point-min) (point-max) cmd nil 'replace)
-    (buffer-string)))
-
-(defadvice org-ctrl-c-ctrl-c (around org-cc-eval-source activate)
-  (if (org-eval-light-inside-snippet)
-      (call-interactively 'org-eval-light-current-snippet)
-    ad-do-it))
-
-(provide 'org-eval-light)
-
-;;; org-eval-light.el ends here
diff --git a/contrib/lisp/org-eval.el b/contrib/lisp/org-eval.el
deleted file mode 100644
index fc878a9..0000000
--- a/contrib/lisp/org-eval.el
+++ /dev/null
@@ -1,216 +0,0 @@
-;;; org-eval.el --- Display result of evaluating code in various languages
-;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
-;;
-;; Author: Carsten Dominik <carsten at orgmode dot org>
-;; Keywords: outlines, hypermedia, calendar, wp
-;; Homepage: https://orgmode.org
-;; Version: 0.04
-;;
-;; This file is not yet 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, 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:
-;;
-;; This modules allows to include output from various commands into an
-;; Org-mode buffer, both for live display, and for export.
-;; This technique has been copied from emacs-wiki and Emacs Muse, and
-;; we try to make it work here in a way as similar as possible to
-;; Muse, so that people who move between both worlds don't need to learn
-;; new syntax.
-;;
-;; Basically it works like this:
-;;
-;;    <lisp>(concat "aaa" "bbb")</lisp>
-;;
-;; will display "aaabbb" in the buffer and export like that as well.
-;; The leading lisp tag will also accept the attributes "markup" and
-;; "lang", to specify how the text should be formatted during export.
-;; For example,
-;;
-;;    <lisp markup="src" lang="emacs-lisp"> .... </lisp>
-;;
-;; will format the result of the lisp form as if it was lisp source
-;; code.  Internally, it will wrap the text into a
-;;
-;;    #+begin_src emacs-lisp
-;;    #+end_src
-;;
-;; structure so that the right things happen when the exporter is running.
-;;
-;; By default, only the <lisp> tag is turned on, but you can configure
-;; the variable `org-eval-interpreters' to add more interpreters like
-;; `perl', `python', or the `shell'.
-;;
-;; You can edit the code snippets with "C-c '" (org-edit-src-code).
-;;
-;; Please note that this mechanism is potentially dangerous, because it
-;; executes code that you don't even see.  This gives you great power,
-;; but also enough rope to hang yourself.  And, it gives your friends
-;; who send you Org files plenty of opportunity for good and bad jokes.
-;; This is also why this module is not turned on by default, but only
-;; available as a contributed package.
-;;
-;;
-;;
-(require 'org)
-
-;;; Customization
-
-(defgroup org-eval nil
-  "Options concerning including output from commands into the Org-mode buffer."
-  :tag "Org Eval"
-  :group 'org)
-
-(defface org-eval
-  (org-compatible-face nil
-    '((((class color grayscale) (min-colors 88) (background light))
-       (:foreground "grey40"))
-      (((class color grayscale) (min-colors 88) (background dark))
-       (:foreground "grey60"))
-      (((class color) (min-colors 8) (background light))
-       (:foreground "green"))
-      (((class color) (min-colors 8) (background dark))
-       (:foreground "yellow"))))
-  "Face for command output that is included into an Org-mode buffer."
-  :group 'org-eval
-  :group 'org-faces)
-
-(defvar org-eval-regexp nil)
-
-(defun org-eval-set-interpreters (var value)
-  (set-default var value)
-  (setq org-eval-regexp
-       (concat "<\\("
-               (mapconcat 'regexp-quote value "\\|")
-               "\\)"
-               "\\([^>]\\{0,50\\}?\\)>"
-               "\\([^\000]+?\\)</\\1>")))
-
-(defcustom org-eval-interpreters '("lisp")
-  "Interpreters allows for evaluation tags.
-This is a list of program names (as strings) that can evaluate code and
-insert the output into an Org-mode buffer.  Valid choices are
-
-lisp    Interpret Emacs Lisp code and display the result
-shell   Pass command to the shell and display the result
-perl    The perl interpreter
-python  Thy python interpreter
-ruby    The ruby interpreter"
-  :group 'org-eval
-  :set 'org-eval-set-interpreters
-  :type '(set :greedy t
-             (const "lisp")
-             (const "perl")
-             (const "python")
-             (const "ruby")
-             (const "shell")))
-
-(defun org-eval-handle-snippets (limit &optional replace)
-  "Evaluate code snippets and display the results as display property.
-When REPLACE is non-nil, replace the code region with the result (used
-for export)."
-  (let (a)
-    (while (setq a (text-property-any (point) (or limit (point-max))
-                                     'org-eval t))
-      (remove-text-properties
-       a (next-single-property-change a 'org-eval nil limit)
-       '(display t intangible t org-eval t))))
-  (while (re-search-forward org-eval-regexp limit t)
-    (let* ((beg (match-beginning 0))
-          (end (match-end 0))
-          (kind (match-string 1))
-          (attr (match-string 2))
-          (code (match-string 3))
-          (value (org-eval-code kind code))
-          markup lang)
-      (if replace
-         (progn
-           (setq attr (save-match-data (org-eval-get-attributes attr))
-                 markup (cdr (assoc "markup" attr))
-                 lang  (cdr (assoc "lang" attr)))
-           (replace-match
-            (concat (if markup (format "#+BEGIN_%s" (upcase markup)))
-                    (if (and markup (equal (downcase markup) "src"))
-                        (concat " " (or lang "fundamental")))
-                    "\n"
-                    value
-                    (if markup (format "\n#+END_%s\n" (upcase markup))))
-            t t))
-       (add-text-properties
-        beg end
-        (list 'display value 'intangible t 'font-lock-multiline t
-              'face 'org-eval
-              'org-eval t))))))
-
-(defun org-eval-replace-snippts ()
-  "Replace EVAL snippets in the entire buffer.
-This should go into the `org-export-preprocess-hook'."
-  (goto-char (point-min))
-  (org-eval-handle-snippets nil 'replace))
-
-(add-hook 'org-export-preprocess-hook 'org-eval-replace-snippts)
-(add-hook 'org-font-lock-hook 'org-eval-handle-snippets)
-
-(defun org-eval-get-attributes (str)
-  (let ((start 0) key value rtn)
-    (while (string-match "\\<\\([a-zA-Z]+\\)\\>=\"\\([^\"]+\\)\"" str start)
-      (setq key (match-string 1 str)
-           value (match-string 2 str)
-           start (match-end 0))
-      (push (cons key value) rtn))
-    rtn))
-
-(defun org-eval-code (interpreter code)
-  (cond
-   ((equal interpreter "lisp")
-    (org-eval-lisp (concat "(progn\n" code "\n)")))
-   ((equal interpreter "shell")
-    (shell-command-to-string code))
-   ((member interpreter '("perl" "python" "ruby"))
-    (org-eval-run (executable-find interpreter) code))
-   (t (error "Cannot evaluate code type %s" interpreter))))
-
-(defun org-eval-lisp (form)
-  "Evaluate the given form and return the result as a string."
-  (require 'pp)
-  (save-match-data
-    (condition-case err
-        (let ((object (eval (read form))))
-          (cond
-           ((stringp object) object)
-           ((and (listp object)
-                 (not (eq object nil)))
-            (let ((string (pp-to-string object)))
-              (substring string 0 (1- (length string)))))
-           ((numberp object)
-            (number-to-string object))
-           ((eq object nil) "")
-           (t
-            (pp-to-string object))))
-      (error
-       (org-display-warning (format "%s: Error evaluating %s: %s"
-                                     "???" form err))
-       "; INVALID LISP CODE"))))
-
-(defun org-eval-run (cmd code)
-  (with-temp-buffer
-    (insert code)
-    (shell-command-on-region (point-min) (point-max) cmd nil 'replace)
-    (buffer-string)))
-
-(provide 'org-eval)
-
-;;; org-eval.el ends here
diff --git a/contrib/lisp/org-expiry.el b/contrib/lisp/org-expiry.el
deleted file mode 100644
index 559458c..0000000
--- a/contrib/lisp/org-expiry.el
+++ /dev/null
@@ -1,361 +0,0 @@
-;;; org-expiry.el --- expiry mechanism for Org entries
-;;
-;; Copyright 2007-2021 Free Software Foundation, Inc.
-;;
-;; Author: Bastien Guerry
-;; Version: 0.2
-;; Keywords: org expiry
-
-;; This file is not 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, 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:
-;;
-;; This gives you a chance to get rid of old entries in your Org files
-;; by expiring them.
-;;
-;; By default, entries that have no EXPIRY property are considered to be
-;; new (i.e. 0 day old) and only entries older than one year go to the
-;; expiry process, which consist in adding the ARCHIVE tag.  None of
-;; your tasks will be deleted with the default settings.
-;;
-;; When does an entry expires?
-;;
-;; Consider this entry:
-;;
-;; * Stop watching TV
-;;   :PROPERTIES:
-;;   :CREATED:  <2008-01-07 lun 08:01>
-;;   :EXPIRY:   <2008-01-09 08:01>
-;;   :END:
-;;
-;; This entry will expire on the 9th, january 2008.
-
-;; * Stop watching TV
-;;   :PROPERTIES:
-;;   :CREATED:  <2008-01-07 lun 08:01>
-;;   :EXPIRY:   +1w
-;;   :END:
-;;
-;; This entry will expire on the 14th, january 2008, one week after its
-;; creation date.
-;;
-;; What happen when an entry is expired?  Nothing until you explicitly
-;; M-x org-expiry-process-entries When doing this, org-expiry will check
-;; for expired entries and request permission to process them.
-;;
-;; Processing an expired entries means calling the function associated
-;; with `org-expiry-handler-function'; the default is to add the tag
-;; :ARCHIVE:, but you can also add a EXPIRED keyword or even archive
-;; the subtree.
-;;
-;; Is this useful?  Well, when you're in a brainstorming session, it
-;; might be useful to know about the creation date of an entry, and be
-;; able to archive those entries that are more than xxx days/weeks old.
-;;
-;; When you're in such a session, you can insinuate org-expiry like
-;; this: M-x org-expiry-insinuate
-;;
-;; Then, each time you're pressing M-RET to insert an item, the CREATION
-;; property will be automatically added.  Same when you're scheduling or
-;; deadlining items.  You can deinsinuate: M-x org-expiry-deinsinuate
-
-;;; Code:
-
-;;; User variables:
-
-(defgroup org-expiry nil
-  "Org expiry process."
-  :tag "Org Expiry"
-  :group 'org)
-
-(defcustom org-expiry-inactive-timestamps nil
-  "Insert inactive timestamps for created/expired properties."
-  :type 'boolean
-  :group 'org-expiry)
-
-(defcustom org-expiry-created-property-name "CREATED"
-  "The name of the property for setting the creation date."
-  :type 'string
-  :group 'org-expiry)
-
-(defcustom org-expiry-expiry-property-name "EXPIRY"
-  "The name of the property for setting the expiry date/delay."
-  :type 'string
-  :group 'org-expiry)
-
-(defcustom org-expiry-keyword "EXPIRED"
-  "The default keyword for `org-expiry-add-keyword'."
-  :type 'string
-  :group 'org-expiry)
-
-(defcustom org-expiry-wait "+1y"
-  "Time span between the creation date and the expiry.
-The default value for this variable (\"+1y\") means that entries
-will expire if there are at least one year old.
-
-If the expiry delay cannot be retrieved from the entry or the
-subtree above, the expiry process compares the expiry delay with
-`org-expiry-wait'.  This can be either an ISO date or a relative
-time specification.  See `org-read-date' for details."
-  :type 'string
-  :group 'org-expiry)
-
-(defcustom org-expiry-created-date "+0d"
-  "The default creation date.
-The default value of this variable (\"+0d\") means that entries
-without a creation date will be handled as if they were created
-today.
-
-If the creation date cannot be retrieved from the entry or the
-subtree above, the expiry process will compare the expiry delay
-with this date.  This can be either an ISO date or a relative
-time specification.  See `org-read-date' for details on relative
-time specifications."
-  :type 'string
-  :group 'org-expiry)
-
-(defcustom org-expiry-handler-function 'org-toggle-archive-tag
-  "Function to process expired entries.
-Possible candidates for this function are:
-
-`org-toggle-archive-tag'
-`org-expiry-add-keyword'
-`org-expiry-archive-subtree'"
-  :type 'function
-  :group 'org-expiry)
-
-(defcustom org-expiry-confirm-flag t
-  "Non-nil means confirm expiration process."
-  :type '(choice
-         (const :tag "Always require confirmation" t)
-         (const :tag "Do not require confirmation" nil)
-         (const :tag "Require confirmation in interactive expiry process"
-                interactive))
-  :group 'org-expiry)
-
-(defcustom org-expiry-advised-functions
-  '(org-scheduled org-deadline org-time-stamp)
-  "A list of advised functions.
-`org-expiry-insinuate' will activate the expiry advice for these
-functions.  `org-expiry-deinsinuate' will deactivate them."
-  :type 'boolean
-  :group 'list)
-
-;;; Advices and insinuation:
-
-(defadvice org-schedule (after org-schedule-update-created)
-  "Update the creation-date property when calling `org-schedule'."
-  (org-expiry-insert-created))
-
-(defadvice org-deadline (after org-deadline-update-created)
-  "Update the creation-date property when calling `org-deadline'."
-  (org-expiry-insert-created))
-
-(defadvice org-time-stamp (after org-time-stamp-update-created)
-  "Update the creation-date property when calling `org-time-stamp'."
-  (org-expiry-insert-created))
-
-(defun org-expiry-insinuate (&optional arg)
-  "Add hooks and activate advices for org-expiry.
-If ARG, also add a hook to `before-save-hook' in `org-mode' and
-restart `org-mode' if necessary."
-  (interactive "P")
-  (ad-activate 'org-schedule)
-  (ad-activate 'org-time-stamp)
-  (ad-activate 'org-deadline)
-  (add-hook 'org-insert-heading-hook 'org-expiry-insert-created)
-  (add-hook 'org-after-todo-state-change-hook 'org-expiry-insert-created)
-  (add-hook 'org-after-tags-change-hook 'org-expiry-insert-created)
-  (when arg
-    (add-hook 'org-mode-hook
-             (lambda() (add-hook 'before-save-hook
-                                 'org-expiry-process-entries t t)))
-    ;; need this to refresh org-mode hooks
-    (when (eq major-mode 'org-mode)
-      (org-mode)
-      (if (called-interactively-p 'any)
-         (message "Org-expiry insinuated, `org-mode' restarted.")))))
-
-(defun org-expiry-deinsinuate (&optional arg)
-  "Remove hooks and deactivate advices for org-expiry.
-If ARG, also remove org-expiry hook in Org's `before-save-hook'
-and restart `org-mode' if necessary."
-  (interactive "P")
-  (ad-deactivate 'org-schedule)
-  (ad-deactivate 'org-time-stamp)
-  (ad-deactivate 'org-deadline)
-  (remove-hook 'org-insert-heading-hook 'org-expiry-insert-created)
-  (remove-hook 'org-after-todo-state-change-hook 'org-expiry-insert-created)
-  (remove-hook 'org-after-tags-change-hook 'org-expiry-insert-created)
-  (remove-hook 'org-mode-hook
-              (lambda() (add-hook 'before-save-hook
-                                  'org-expiry-process-entries t t)))
-  (when arg
-    ;; need this to refresh org-mode hooks
-    (when (eq major-mode 'org-mode)
-      (org-mode)
-      (if (called-interactively-p 'any)
-         (message "Org-expiry de-insinuated, `org-mode' restarted.")))))
-
-;;; org-expiry-expired-p:
-
-(defun org-expiry-expired-p ()
-  "Check if the entry at point is expired.
-Return nil if the entry is not expired.  Otherwise return the
-amount of time between today and the expiry date.
-
-If there is no creation date, use `org-expiry-created-date'.
-If there is no expiry date, use `org-expiry-wait'."
-  (let* ((ex-prop org-expiry-expiry-property-name)
-        (cr-prop org-expiry-created-property-name)
-        (ct (current-time))
-        (cr (org-read-date nil t (or (org-entry-get (point) cr-prop t)
-                                     org-expiry-created-date)))
-        (ex-field (or (org-entry-get (point) ex-prop t) org-expiry-wait))
-        (ex (if (string-match "^[ \t]?[+-]" ex-field)
-                (time-add cr (time-subtract (org-read-date nil t ex-field) ct))
-              (org-read-date nil t ex-field))))
-    (if (time-less-p ex ct)
-       (time-subtract ct ex))))
-
-;;; Expire an entry or a region/buffer:
-
-(defun org-expiry-process-entry (&optional force)
-  "Call `org-expiry-handler-function' on entry.
-If FORCE is non-nil, don't require confirmation from the user.
-Otherwise rely on `org-expiry-confirm-flag' to decide."
-  (interactive "P")
-  (save-excursion
-    (when (called-interactively-p) (org-reveal))
-    (when (org-expiry-expired-p)
-      (org-back-to-heading)
-      (looking-at org-complex-heading-regexp)
-      (let* ((ov (make-overlay (point) (match-end 0)))
-            (e (org-expiry-expired-p))
-            (d (time-to-number-of-days e)))
-       (overlay-put ov 'face 'secondary-selection)
-       (if (or force
-               (null org-expiry-confirm-flag)
-               (and (eq org-expiry-confirm-flag 'interactive)
-                    (not (interactive)))
-               (and org-expiry-confirm-flag
-                    (y-or-n-p (format "Entry expired by %d days.  Process? " 
d))))
-         (funcall org-expiry-handler-function))
-       (delete-overlay ov)))))
-
-(defun org-expiry-process-entries (beg end)
-  "Process all expired entries between BEG and END.
-The expiry process will run the function defined by
-`org-expiry-handler-functions'."
-  (interactive "r")
-  (save-excursion
-    (let ((beg (if (org-region-active-p)
-                  (region-beginning) (point-min)))
-         (end (if (org-region-active-p)
-                  (region-end) (point-max))))
-      (goto-char beg)
-      (let ((expired 0) (processed 0))
-       (while (and (outline-next-heading) (< (point) end))
-         (when (org-expiry-expired-p)
-           (setq expired (1+ expired))
-           (if (if (called-interactively-p 'any)
-                   (call-interactively 'org-expiry-process-entry)
-                 (org-expiry-process-entry))
-               (setq processed (1+ processed)))))
-       (if (equal expired 0)
-           (message "No expired entry")
-         (message "Processed %d on %d expired entries"
-                  processed expired))))))
-
-;;; Insert created/expiry property:
-
-(defun org-expiry-insert-created (&optional arg)
-  "Insert or update a property with the creation date.
-If ARG, always update it.  With one `C-u' prefix, silently update
-to today's date.  With two `C-u' prefixes, prompt the user for to
-update the date."
-  (interactive "P")
-  (let* ((d (org-entry-get (point) org-expiry-created-property-name))
-        d-time d-hour timestr)
-    (when (or (null d) arg)
-      ;; update if no date or non-nil prefix argument
-      ;; FIXME Use `org-time-string-to-time'
-      (setq d-time (if d (org-time-string-to-time d)
-                    (current-time)))
-      (setq d-hour (format-time-string "%H:%M" d-time))
-      (setq timestr
-           ;; two C-u prefixes will call org-read-date
-           (if (equal arg '(16))
-               (concat "<" (org-read-date
-                            nil nil nil nil d-time d-hour) ">")
-             (format-time-string (cdr org-time-stamp-formats))))
-      ;; maybe transform to inactive timestamp
-      (if org-expiry-inactive-timestamps
-         (setq timestr (concat "[" (substring timestr 1 -1) "]")))
-      (save-excursion
-       (org-entry-put
-        (point) org-expiry-created-property-name timestr)))))
-
-(defun org-expiry-insert-expiry (&optional today)
-  "Insert a property with the expiry date.
-With one `C-u' prefix, don't prompt interactively for the date
-and insert today's date."
-  (interactive "P")
-  (let* ((d (org-entry-get (point) org-expiry-expiry-property-name))
-        d-time d-hour)
-    (setq d-time (if d (org-time-string-to-time d)
-                  (current-time)))
-    (setq d-hour (format-time-string "%H:%M" d-time))
-    (setq timestr (if today
-                     (format-time-string (cdr org-time-stamp-formats))
-                   (concat "<" (org-read-date
-                                nil nil nil nil d-time d-hour) ">")))
-    ;; maybe transform to inactive timestamp
-    (if org-expiry-inactive-timestamps
-       (setq timestr (concat "[" (substring timestr 1 -1) "]")))
-
-    (save-excursion
-      (org-entry-put
-       (point) org-expiry-expiry-property-name timestr))))
-
-;;; Functions to process expired entries:
-
-(defun org-expiry-archive-subtree ()
-  "Archive the entry at point if it is expired."
-  (interactive)
-  (save-excursion
-    (if (org-expiry-expired-p)
-       (org-archive-subtree)
-      (if (called-interactively-p 'any)
-         (message "Entry at point is not expired.")))))
-
-(defun org-expiry-add-keyword (&optional keyword)
-  "Add KEYWORD to the entry at point if it is expired."
-  (interactive "sKeyword: ")
-  (if (or (member keyword org-todo-keywords-1)
-         (setq keyword org-expiry-keyword))
-      (save-excursion
-       (if (org-expiry-expired-p)
-           (org-todo keyword)
-         (if (called-interactively-p 'any)
-             (message "Entry at point is not expired."))))
-    (error "\"%s\" is not a to-do keyword in this buffer" keyword)))
-
-;; FIXME what about using org-refile ?
-
-(provide 'org-expiry)
-
-;;; org-expiry.el ends here
diff --git a/contrib/lisp/org-interactive-query.el 
b/contrib/lisp/org-interactive-query.el
deleted file mode 100644
index 56b9a6d..0000000
--- a/contrib/lisp/org-interactive-query.el
+++ /dev/null
@@ -1,311 +0,0 @@
-;;; org-interactive-query.el --- Interactive modification of agenda query
-;;
-;; Copyright 2007-2021 Free Software Foundation, Inc.
-;;
-;; Author: Christopher League <league at contrapunctus dot net>
-;; Version: 1.0
-;; Keywords: org, wp
-;;
-;; This file is not 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, 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:
-;;
-
-;; This library implements interactive modification of a tags/todo query
-;; in the org-agenda.  It adds 4 keys to the agenda
-;;
-;; /   add a keyword as a positive selection criterion
-;; \   add a keyword as a newgative selection criterion
-;; =   clear a keyword from the selection string
-;; ;
-
-(require 'org)
-
-(org-defkey org-agenda-mode-map "=" 'org-agenda-query-clear-cmd)
-(org-defkey org-agenda-mode-map "/" 'org-agenda-query-and-cmd)
-(org-defkey org-agenda-mode-map ";" 'org-agenda-query-or-cmd)
-(org-defkey org-agenda-mode-map "\\" 'org-agenda-query-not-cmd)
-
-;;; Agenda interactive query manipulation
-
-(defcustom org-agenda-query-selection-single-key t
-  "Non-nil means query manipulation exits after first change.
-When nil, you have to press RET to exit it.
-During query selection, you can toggle this flag with `C-c'.
-This variable can also have the value `expert'.  In this case, the window
-displaying the tags menu is not even shown, until you press C-c again."
-  :group 'org-agenda
-  :type '(choice
-         (const :tag "No" nil)
-         (const :tag "Yes" t)
-         (const :tag "Expert" expert)))
-
-(defun org-agenda-query-selection (current op table &optional todo-table)
-  "Fast query manipulation with single keys.
-CURRENT is the current query string, OP is the initial
-operator (one of \"+|-=\"), TABLE is an alist of tags and
-corresponding keys, possibly with grouping information.
-TODO-TABLE is a similar table with TODO keywords, should these
-have keys assigned to them.  If the keys are nil, a-z are
-automatically assigned.  Returns the new query string, or nil to
-not change the current one."
-  (let* ((fulltable (append table todo-table))
-        (maxlen (apply 'max (mapcar
-                             (lambda (x)
-                               (if (stringp (car x)) (string-width (car x)) 0))
-                             fulltable)))
-        (fwidth (+ maxlen 3 1 3))
-        (ncol (/ (- (window-width) 4) fwidth))
-        (expert (eq org-agenda-query-selection-single-key 'expert))
-        (exit-after-next org-agenda-query-selection-single-key)
-        (done-keywords org-done-keywords)
-         tbl char cnt e groups ingroup
-        tg c2 c c1 ntable rtn)
-    (save-window-excursion
-      (if expert
-         (set-buffer (get-buffer-create " *Org tags*"))
-       (delete-other-windows)
-       (split-window-vertically)
-       (org-switch-to-buffer-other-window (get-buffer-create " *Org tags*")))
-      (erase-buffer)
-      (setq-local org-done-keywords done-keywords)
-      (insert "Query:    " current "\n")
-      (org-agenda-query-op-line op)
-      (insert "\n\n")
-      (org-fast-tag-show-exit exit-after-next)
-      (setq tbl fulltable char ?a cnt 0)
-      (while (setq e (pop tbl))
-       (cond
-        ((equal e '(:startgroup))
-         (push '() groups) (setq ingroup t)
-         (when (not (= cnt 0))
-           (setq cnt 0)
-           (insert "\n"))
-         (insert "{ "))
-        ((equal e '(:endgroup))
-         (setq ingroup nil cnt 0)
-         (insert "}\n"))
-        (t
-         (setq tg (car e) c2 nil)
-         (if (cdr e)
-             (setq c (cdr e))
-           ;; automatically assign a character.
-           (setq c1 (string-to-char
-                     (downcase (substring
-                                tg (if (= (string-to-char tg) ?@) 1 0)))))
-           (if (or (rassoc c1 ntable) (rassoc c1 table))
-               (while (or (rassoc char ntable) (rassoc char table))
-                 (setq char (1+ char)))
-             (setq c2 c1))
-           (setq c (or c2 char)))
-         (if ingroup (push tg (car groups)))
-         (setq tg (org-add-props tg nil 'face
-                                 (cond
-                                  ((not (assoc tg table))
-                                   (org-get-todo-face tg))
-                                  (t nil))))
-         (if (and (= cnt 0) (not ingroup)) (insert "  "))
-         (insert "[" c "] " tg (make-string
-                                (- fwidth 4 (length tg)) ?\ ))
-         (push (cons tg c) ntable)
-         (when (= (setq cnt (1+ cnt)) ncol)
-           (insert "\n")
-           (if ingroup (insert "  "))
-           (setq cnt 0)))))
-      (setq ntable (nreverse ntable))
-      (insert "\n")
-      (goto-char (point-min))
-      (if (and (not expert) (fboundp 'fit-window-to-buffer))
-         (fit-window-to-buffer))
-      (setq rtn
-           (catch 'exit
-             (while t
-               (message "[a-z..]:Toggle [SPC]:clear [RET]:accept 
[TAB]:free%s%s"
-                        (if groups " [!] no groups" " [!]groups")
-                        (if expert " [C-c]:window" (if exit-after-next " 
[C-c]:single" " [C-c]:multi")))
-               (setq c (let ((inhibit-quit t)) (read-char-exclusive)))
-               (cond
-                ((= c ?\r) (throw 'exit t))
-                ((= c ?!)
-                 (setq groups (not groups))
-                 (goto-char (point-min))
-                 (while (re-search-forward "[{}]" nil t) (replace-match " ")))
-                ((= c ?\C-c)
-                 (if (not expert)
-                     (org-fast-tag-show-exit
-                      (setq exit-after-next (not exit-after-next)))
-                   (setq expert nil)
-                   (delete-other-windows)
-                   (split-window-vertically)
-                   (org-switch-to-buffer-other-window " *Org tags*")
-                   (and (fboundp 'fit-window-to-buffer)
-                        (fit-window-to-buffer))))
-                ((or (= c ?\C-g)
-                     (and (= c ?q) (not (rassoc c ntable))))
-                 (setq quit-flag t))
-                ((= c ?\ )
-                 (setq current "")
-                 (if exit-after-next (setq exit-after-next 'now)))
-                ((= c ?\[)             ; clear left
-                  (org-agenda-query-decompose current)
-                  (setq current (concat "/" (match-string 2 current)))
-                 (if exit-after-next (setq exit-after-next 'now)))
-                ((= c ?\])             ; clear right
-                  (org-agenda-query-decompose current)
-                  (setq current (match-string 1 current))
-                 (if exit-after-next (setq exit-after-next 'now)))
-                ((= c ?\t)
-                 (condition-case nil
-                     (setq current (read-string "Query: " current))
-                   (quit))
-                 (if exit-after-next (setq exit-after-next 'now)))
-                 ;; operators
-                 ((or (= c ?/) (= c ?+)) (setq op "+"))
-                 ((or (= c ?\;) (= c ?|)) (setq op "|"))
-                 ((or (= c ?\\) (= c ?-)) (setq op "-"))
-                 ((= c ?=) (setq op "="))
-                 ;; todos
-                 ((setq e (rassoc c todo-table) tg (car e))
-                  (setq current (org-agenda-query-manip
-                                 current op groups 'todo tg))
-                  (if exit-after-next (setq exit-after-next 'now)))
-                 ;; tags
-                 ((setq e (rassoc c ntable) tg (car e))
-                  (setq current (org-agenda-query-manip
-                                 current op groups 'tag tg))
-                  (if exit-after-next (setq exit-after-next 'now))))
-               (if (eq exit-after-next 'now) (throw 'exit t))
-               (goto-char (point-min))
-               (beginning-of-line 1)
-               (delete-region (point) (point-at-eol))
-                (insert "Query:    " current)
-                (beginning-of-line 2)
-                (delete-region (point) (point-at-eol))
-                (org-agenda-query-op-line op)
-               (goto-char (point-min)))))
-      (if rtn current nil))))
-
-(defun org-agenda-query-op-line (op)
-  (insert "Operator: "
-          (org-agenda-query-op-entry (equal op "+") "/+" "and")
-          (org-agenda-query-op-entry (equal op "|") ";|" "or")
-          (org-agenda-query-op-entry (equal op "-") "\\-" "not")
-          (org-agenda-query-op-entry (equal op "=") "=" "clear")))
-
-(defun org-agenda-query-op-entry (matchp chars str)
-  (if matchp
-      (org-add-props (format "[%s %s]  " chars (upcase str))
-          nil 'face 'org-todo)
-    (format "[%s]%s   " chars str)))
-
-(defun org-agenda-query-decompose (current)
-  (string-match "\\([^/]*\\)/?\\(.*\\)" current))
-
-(defun org-agenda-query-clear (current prefix tag)
-  (if (string-match (concat prefix "\\b" (regexp-quote tag) "\\b") current)
-      (replace-match "" t t current)
-    current))
-
-(defun org-agenda-query-manip (current op groups kind tag)
-  "Apply an operator to a query string and a tag.
-CURRENT is the current query string, OP is the operator, GROUPS is a
-list of lists of tags that are mutually exclusive.  KIND is 'tag for a
-regular tag, or 'todo for a TODO keyword, and TAG is the tag or
-keyword string."
-  ;; If this tag is already in query string, remove it.
-  (setq current (org-agenda-query-clear current "[-\\+&|]?" tag))
-  (if (equal op "=") current
-    ;; When using AND, also remove mutually exclusive tags.
-    (if (equal op "+")
-        (loop for g in groups do
-              (if (member tag g)
-                  (mapc (lambda (x)
-                          (setq current
-                                (org-agenda-query-clear current "\\+" x)))
-                        g))))
-    ;; Decompose current query into q1 (tags) and q2 (TODOs).
-    (org-agenda-query-decompose current)
-    (let* ((q1 (match-string 1 current))
-           (q2 (match-string 2 current)))
-      (cond
-       ((eq kind 'tag)
-        (concat q1 op tag "/" q2))
-       ;; It's a TODO; when using AND, drop all other TODOs.
-       ((equal op "+")
-        (concat q1 "/+" tag))
-       (t
-        (concat q1 "/" q2 op tag))))))
-
-(defun org-agenda-query-global-todo-keys (&optional files)
-  "Return alist of all TODO keywords and their fast keys, in all FILES."
-  (let (alist)
-    (unless (and files (car files))
-      (setq files (org-agenda-files)))
-    (save-excursion
-      (loop for f in files do
-            (set-buffer (find-file-noselect f))
-            (loop for k in org-todo-key-alist do
-                  (setq alist (org-agenda-query-merge-todo-key
-                               alist k)))))
-    alist))
-
-(defun org-agenda-query-merge-todo-key (alist entry)
-  (let (e)
-    (cond
-     ;; if this is not a keyword (:startgroup, etc), ignore it
-     ((not (stringp (car entry))))
-     ;; if keyword already exists, replace char if it's null
-     ((setq e (assoc (car entry) alist))
-      (when (null (cdr e)) (setcdr e (cdr entry))))
-     ;; if char already exists, prepend keyword but drop char
-     ((rassoc (cdr entry) alist)
-      (message "TRACE POSITION 2")
-      (setq alist (cons (cons (car entry) nil) alist)))
-     ;; else, prepend COPY of entry
-     (t
-      (setq alist (cons (cons (car entry) (cdr entry)) alist)))))
-  alist)
-
-(defun org-agenda-query-generic-cmd (op)
-  "Activate query manipulation with OP as initial operator."
-  (let ((q (org-agenda-query-selection org-agenda-query-string op
-                                       org-tag-alist
-                                       (org-agenda-query-global-todo-keys))))
-    (when q
-      (setq org-agenda-query-string q)
-      (org-agenda-redo))))
-
-(defun org-agenda-query-clear-cmd ()
-  "Activate query manipulation, to clear a tag from the string."
-  (interactive)
-  (org-agenda-query-generic-cmd "="))
-
-(defun org-agenda-query-and-cmd ()
-  "Activate query manipulation, initially using the AND (+) operator."
-  (interactive)
-  (org-agenda-query-generic-cmd "+"))
-
-(defun org-agenda-query-or-cmd ()
-  "Activate query manipulation, initially using the OR (|) operator."
-  (interactive)
-  (org-agenda-query-generic-cmd "|"))
-
-(defun org-agenda-query-not-cmd ()
-  "Activate query manipulation, initially using the NOT (-) operator."
-  (interactive)
-  (org-agenda-query-generic-cmd "-"))
-
-(provide 'org-interactive-query)
diff --git a/contrib/lisp/org-invoice.el b/contrib/lisp/org-invoice.el
deleted file mode 100644
index 6868894..0000000
--- a/contrib/lisp/org-invoice.el
+++ /dev/null
@@ -1,403 +0,0 @@
-;;; org-invoice.el --- Help manage client invoices in OrgMode
-;;
-;; Copyright (C) 2008-2014 pmade inc. (Peter Jones pjones@pmade.com)
-;;
-;; This file is not part of GNU Emacs.
-;;
-;; Permission is hereby granted, free of charge, to any person obtaining
-;; a copy of this software and associated documentation files (the
-;; "Software"), to deal in the Software without restriction, including
-;; without limitation the rights to use, copy, modify, merge, publish,
-;; distribute, sublicense, and/or sell copies of the Software, and to
-;; permit persons to whom the Software is furnished to do so, subject to
-;; the following conditions:
-;;
-;; The above copyright notice and this permission notice shall be
-;; included in all copies or substantial portions of the Software.
-;;
-;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-;; LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-;; OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-;; WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-;;
-;;; Commentary:
-;;
-;; Building on top of the terrific OrgMode, org-invoice tries to
-;; provide functionality for managing invoices.  Currently, it does
-;; this by implementing an OrgMode dynamic block where invoice
-;; information is aggregated so that it can be exported.
-;;
-;; It also provides a library of functions that can be used to collect
-;; this invoice information and use it in other ways, such as
-;; submitting it to on-line invoicing tools.
-;;
-;; I'm already working on an elisp package to submit this invoice data
-;; to the FreshBooks on-line accounting tool.
-;;
-;; Usage:
-;;
-;; In your ~/.emacs:
-;; (autoload 'org-invoice-report "org-invoice")
-;; (autoload 'org-dblock-write:invoice "org-invoice")
-;;
-;; See the documentation in the following functions:
-;;
-;; `org-invoice-report'
-;; `org-dblock-write:invoice'
-;;
-;; Latest version:
-;;
-;; git clone git://pmade.com/elisp
-(eval-when-compile
-  (require 'cl)
-  (require 'org))
-
-(declare-function org-duration-from-minutes "org-duration" (minutes &optional 
fmt fractional))
-
-(defgroup org-invoice nil
-  "OrgMode Invoice Helper"
-  :tag "Org-Invoice" :group 'org)
-
-(defcustom org-invoice-long-date-format "%A, %B %d, %Y"
-  "The format string for long dates."
-  :type 'string :group 'org-invoice)
-
-(defcustom org-invoice-strip-ts t
-  "Remove org timestamps that appear in headings."
-  :type 'boolean :group 'org-invoice)
-
-(defcustom org-invoice-default-level 2
-  "The heading level at which a new invoice starts.  This value
-is used if you don't specify a scope option to the invoice block,
-and when other invoice helpers are trying to find the heading
-that starts an invoice.
-
-The default is 2, assuming that you structure your invoices so
-that they fall under a single heading like below:
-
-* Invoices
-** This is invoice number 1...
-** This is invoice number 2...
-
-If you don't structure your invoices using those conventions,
-change this setting to the number that corresponds to the heading
-at which an invoice begins."
-  :type 'integer :group 'org-invoice)
-
-(defcustom org-invoice-start-hook nil
-  "Hook called when org-invoice is about to collect data from an
-invoice heading.  When this hook is called, point will be on the
-heading where the invoice begins.
-
-When called, `org-invoice-current-invoice' will be set to the
-alist that represents the info for this invoice."
-  :type 'hook :group 'org-invoice)
-
-  (defcustom org-invoice-heading-hook nil
-  "Hook called when org-invoice is collecting data from a
-heading. You can use this hook to add additional information to
-the alist that represents the heading.
-
-When this hook is called, point will be on the current heading
-being processed, and `org-invoice-current-item' will contain the
-alist for the current heading.
-
-This hook is called repeatedly for each invoice item processed."
-  :type 'hook :group 'org-invoice)
-
-(defvar org-invoice-current-invoice nil
-  "Information about the current invoice.")
-
-(defvar org-invoice-current-item nil
-  "Information about the current invoice item.")
-
-(defvar org-invoice-table-params nil
-  "The table parameters currently being used.")
-
-(defvar org-invoice-total-time nil
-  "The total invoice time for the summary line.")
-
-(defvar org-invoice-total-price nil
-  "The total invoice price for the summary line.")
-
-(defconst org-invoice-version "1.0.0"
-  "The org-invoice version number.")
-
-(defun org-invoice-goto-tree (&optional tree)
-  "Move point to the heading that represents the head of the
-current invoice.  The heading level will be taken from
-`org-invoice-default-level' unless tree is set to a string that
-looks like tree2, where the level is 2."
-  (let ((level org-invoice-default-level))
-    (save-match-data
-      (when (and tree (string-match "^tree\\([0-9]+\\)$" tree))
-        (setq level (string-to-number (match-string 1 tree)))))
-    (org-back-to-heading)
-    (while (and (> (org-reduced-level (org-outline-level)) level)
-                (org-up-heading-safe)))))
-
-(defun org-invoice-heading-info ()
-  "Return invoice information from the current heading."
-  (let ((title   (org-no-properties (org-get-heading t)))
-        (date    (org-entry-get nil "TIMESTAMP" 'selective))
-        (work    (org-entry-get nil "WORK" nil))
-        (rate    (or (org-entry-get nil "RATE" t) "0"))
-        (level   (org-outline-level))
-        raw-date long-date)
-    (unless date (setq date (org-entry-get nil "TIMESTAMP_IA" 'selective)))
-    (unless date (setq date (org-entry-get nil "TIMESTAMP" t)))
-    (unless date (setq date (org-entry-get nil "TIMESTAMP_IA" t)))
-    (unless work (setq work (org-entry-get nil "CLOCKSUM" nil)))
-    (unless work (setq work "00:00"))
-    (when date
-      (setq raw-date (apply 'encode-time (org-parse-time-string date)))
-      (setq long-date (format-time-string org-invoice-long-date-format 
raw-date)))
-    (when (and org-invoice-strip-ts (string-match org-ts-regexp-both title))
-      (setq title (replace-match "" nil nil title)))
-    (when (string-match "^[ \t]+" title)
-      (setq title (replace-match "" nil nil title)))
-    (when (string-match "[ \t]+$" title)
-      (setq title (replace-match "" nil nil title)))
-    (setq work (org-duration-to-minutes work))
-    (setq rate (string-to-number rate))
-    (setq org-invoice-current-item (list (cons 'title title)
-          (cons 'date date)
-          (cons 'raw-date raw-date)
-          (cons 'long-date long-date)
-          (cons 'work work)
-          (cons 'rate rate)
-          (cons 'level level)
-          (cons 'price (* rate (/ work 60.0)))))
-    (run-hook-with-args 'org-invoice-heading-hook)
-    org-invoice-current-item))
-
-(defun org-invoice-level-min-max (ls)
-  "Return a list where the car is the min level, and the cdr the max."
-  (let ((max 0) min level)
-    (dolist (info ls)
-      (when (cdr (assq 'date info))
-        (setq level (cdr (assq 'level info)))
-        (when (or (not min) (< level min)) (setq min level))
-        (when (> level max) (setq max level))))
-    (cons (or min 0) max)))
-
-(defun org-invoice-collapse-list (ls)
-  "Reorganize the given list by dates."
-  (let ((min-max (org-invoice-level-min-max ls)) new)
-    (dolist (info ls)
-      (let* ((date (cdr (assq 'date info)))
-             (work (cdr (assq 'work info)))
-             (price (cdr (assq 'price info)))
-             (long-date (cdr (assq 'long-date info)))
-             (level (cdr (assq 'level info)))
-             (bucket (cdr (assoc date new))))
-        (if (and (/= (car min-max) (cdr min-max))
-                   (=  (car min-max) level)
-                   (=  work 0) (not bucket) date)
-            (progn
-              (setq info (assq-delete-all 'work info))
-              (push (cons 'total-work 0) info)
-              (push (cons date (list info)) new)
-              (setq bucket (cdr (assoc date new))))
-          (when (and date (not bucket))
-            (setq bucket (list (list (cons 'date date)
-                                     (cons 'title long-date)
-                                     (cons 'total-work 0)
-                                     (cons 'price 0))))
-            (push (cons date bucket) new)
-            (setq bucket (cdr (assoc date new))))
-          (when (and date bucket)
-            (setcdr (assq 'total-work (car bucket))
-                    (+ work (cdr (assq 'total-work (car bucket)))))
-            (setcdr (assq 'price (car bucket))
-                    (+ price (cdr (assq 'price (car bucket)))))
-            (nconc bucket (list info))))))
-    (nreverse new)))
-
-(defun org-invoice-info-to-table (info)
-  "Create a single org table row from the given info alist."
-  (let ((title (cdr (assq 'title info)))
-        (total (cdr (assq 'total-work info)))
-        (work  (cdr (assq 'work info)))
-        (price (cdr (assq 'price info)))
-        (with-price (plist-get org-invoice-table-params :price)))
-    (unless total
-      (setq
-       org-invoice-total-time (+ org-invoice-total-time work)
-       org-invoice-total-price (+ org-invoice-total-price price)))
-    (setq total (and total (org-duration-from-minutes total)))
-    (setq work  (and work  (org-duration-from-minutes work)))
-    (insert-before-markers
-     (concat "|" title
-             (cond
-              (total (concat "|" total))
-              (work  (concat "|" work)))
-             (and with-price price (concat "|" (format "%.2f" price)))
-             "|" "\n"))))
-
-(defun org-invoice-list-to-table (ls)
-  "Convert a list of heading info to an org table"
-  (let ((with-price (plist-get org-invoice-table-params :price))
-        (with-summary (plist-get org-invoice-table-params :summary))
-        (with-header (plist-get org-invoice-table-params :headers))
-        (org-invoice-total-time 0)
-        (org-invoice-total-price 0))
-    (insert-before-markers
-     (concat "| Task / Date | Time" (and with-price "| Price") "|\n"))
-    (dolist (info ls)
-      (insert-before-markers "|-\n")
-      (mapc 'org-invoice-info-to-table (if with-header (cdr info) (cdr (cdr 
info)))))
-    (when with-summary
-      (insert-before-markers
-       (concat "|-\n|Total:|"
-               (org-duration-from-minutes org-invoice-total-time)
-               (and with-price (concat "|" (format "%.2f" 
org-invoice-total-price)))
-               "|\n")))))
-
-(defun org-invoice-collect-invoice-data ()
-  "Collect all the invoice data from the current OrgMode tree and
-return it.  Before you call this function, move point to the
-heading that begins the invoice data, usually using the
-`org-invoice-goto-tree' function."
-  (let ((org-invoice-current-invoice
-         (list (cons 'point (point)) (cons 'buffer (current-buffer))))
-        (org-invoice-current-item nil))
-    (save-restriction
-      (org-narrow-to-subtree)
-      (org-clock-sum)
-      (run-hook-with-args 'org-invoice-start-hook)
-      (cons org-invoice-current-invoice
-            (org-invoice-collapse-list
-             (org-map-entries 'org-invoice-heading-info t 'tree 'archive))))))
-
-(defun org-dblock-write:invoice (params)
-  "Function called by OrgMode to write the invoice dblock.  To
-create an invoice dblock you can use the `org-invoice-report'
-function.
-
-The following parameters can be given to the invoice block (for
-information about dblock parameters, please see the Org manual):
-
-:scope Allows you to override the `org-invoice-default-level'
-       variable.  The only supported values right now are ones
-       that look like :tree1, :tree2, etc.
-
-:prices Set to nil to turn off the price column.
-
-:headers Set to nil to turn off the group headers.
-
-:summary Set to nil to turn off the final summary line."
-  (let ((scope (plist-get params :scope))
-        (org-invoice-table-params params)
-        (zone (point-marker))
-        table)
-    (unless scope (setq scope 'default))
-    (unless (plist-member params :price) (plist-put params :price t))
-    (unless (plist-member params :summary) (plist-put params :summary t))
-    (unless (plist-member params :headers) (plist-put params :headers t))
-    (save-excursion
-      (cond
-       ((eq scope 'tree) (org-invoice-goto-tree "tree1"))
-       ((eq scope 'default) (org-invoice-goto-tree))
-       ((symbolp scope) (org-invoice-goto-tree (symbol-name scope))))
-      (setq table (org-invoice-collect-invoice-data))
-      (goto-char zone)
-      (org-invoice-list-to-table (cdr table))
-      (goto-char zone)
-      (org-table-align)
-      (move-marker zone nil))))
-
-(defun org-invoice-in-report-p ()
-  "Check to see if point is inside an invoice report."
-  (let ((pos (point)) start)
-    (save-excursion
-      (end-of-line 1)
-      (and (re-search-backward "^#\\+BEGIN:[ \t]+invoice" nil t)
-          (setq start (match-beginning 0))
-          (re-search-forward "^#\\+END:.*" nil t)
-          (>= (match-end 0) pos)
-          start))))
-
-(defun org-invoice-report (&optional jump)
-  "Create or update an invoice dblock report.  If point is inside
-an existing invoice report, the report is updated.  If point
-isn't inside an invoice report, a new report is created.
-
-When called with a prefix argument, move to the first invoice
-report after point and update it.
-
-For information about various settings for the invoice report,
-see the `org-dblock-write:invoice' function documentation.
-
-An invoice report is created by reading a heading tree and
-collecting information from various properties.  It is assumed
-that all invoices start at a second level heading, but this can
-be configured using the `org-invoice-default-level' variable.
-
-Here is an example, where all invoices fall under the first-level
-heading Invoices:
-
-* Invoices
-** Client Foo (Jan 01 - Jan 15)
-*** [2008-01-01 Tue] Built New Server for Production
-*** [2008-01-02 Wed] Meeting with Team to Design New System
-** Client Bar (Jan 01 - Jan 15)
-*** [2008-01-01 Tue] Searched for Widgets on Google
-*** [2008-01-02 Wed] Billed You for Taking a Nap
-
-In this layout, invoices begin at level two, and invoice
-items (tasks) are at level three.  You'll notice that each level
-three heading starts with an inactive timestamp.  The timestamp
-can actually go anywhere you want, either in the heading, or in
-the text under the heading.  But you must have a timestamp
-somewhere so that the invoice report can group your items by
-date.
-
-Properties are used to collect various bits of information for
-the invoice.  All properties can be set on the invoice item
-headings, or anywhere in the tree.  The invoice report will scan
-up the tree looking for each of the properties.
-
-Properties used:
-
-CLOCKSUM: You can use the Org clock-in and clock-out commands to
-          create a CLOCKSUM property.  Also see WORK.
-
-WORK: An alternative to the CLOCKSUM property.  This property
-      should contain the amount of work that went into this
-      invoice item formatted as HH:MM (e.g. 01:30).
-
-RATE: Used to calculate the total price for an invoice item.
-      Should be the price per hour that you charge (e.g. 45.00).
-      It might make more sense to place this property higher in
-      the hierarchy than on the invoice item headings.
-
-Using this information, a report is generated that details the
-items grouped by days.  For each day you will be able to see the
-total number of hours worked, the total price, and the items
-worked on.
-
-You can place the invoice report anywhere in the tree you want.
-I place mine under a third-level heading like so:
-
-* Invoices
-** An Invoice Header
-*** [2008-11-25 Tue] An Invoice Item
-*** Invoice Report
-#+BEGIN: invoice
-#+END:"
-  (interactive "P")
-  (let ((report (org-invoice-in-report-p)))
-    (when (and (not report) jump)
-      (when (re-search-forward "^#\\+BEGIN:[ \t]+invoice" nil t)
-        (org-show-entry)
-        (beginning-of-line)
-        (setq report (point))))
-    (if report (goto-char report)
-      (org-create-dblock (list :name "invoice")))
-    (org-update-dblock)))
-
-(provide 'org-invoice)
diff --git a/contrib/lisp/org-learn.el b/contrib/lisp/org-learn.el
deleted file mode 100644
index 5e39b15..0000000
--- a/contrib/lisp/org-learn.el
+++ /dev/null
@@ -1,177 +0,0 @@
-;;; org-learn.el --- Implements SuperMemo's incremental learning algorithm
-
-;; Copyright (C) 2009-2021 Free Software Foundation, Inc.
-
-;; Author: John Wiegley <johnw at gnu dot org>
-;; Keywords: outlines, hypermedia, calendar, wp
-;; Homepage: https://orgmode.org
-;; Version: 6.32trans
-;;
-;; This file is not 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:
-
-;; The file implements the learning algorithm described at
-;; http://supermemo.com/english/ol/sm5.htm, which is a system for reading
-;; material according to "spaced repetition".  See
-;; http://en.wikipedia.org/wiki/Spaced_repetition for more details.
-;;
-;; To use, turn on state logging and schedule some piece of information you
-;; want to read.  Then in the agenda buffer type
-
-(require 'org)
-(eval-when-compile
-  (require 'cl))
-
-(defgroup org-learn nil
-  "Options concerning the learning code in Org-mode."
-  :tag "Org Learn"
-  :group 'org-progress)
-
-(defcustom org-learn-always-reschedule nil
-  "If non-nil, always reschedule items, even if retention was \"perfect\"."
-  :type 'boolean
-  :group 'org-learn)
-
-(defcustom org-learn-fraction 0.5
-  "Controls the rate at which EF is increased or decreased.
-Must be a number between 0 and 1 (the greater it is the faster
-the changes of the OF matrix)."
-  :type 'float
-  :group 'org-learn)
-
-(defun initial-optimal-factor (n ef)
-  (if (= 1 n)
-      4
-    ef))
-
-(defun get-optimal-factor (n ef of-matrix)
-  (let ((factors (assoc n of-matrix)))
-    (or (and factors
-            (let ((ef-of (assoc ef (cdr factors))))
-              (and ef-of (cdr ef-of))))
-       (initial-optimal-factor n ef))))
-
-(defun set-optimal-factor (n ef of-matrix of)
-  (let ((factors (assoc n of-matrix)))
-    (if factors
-       (let ((ef-of (assoc ef (cdr factors))))
-         (if ef-of
-             (setcdr ef-of of)
-           (push (cons ef of) (cdr factors))))
-      (push (cons n (list (cons ef of))) of-matrix)))
-  of-matrix)
-
-(defun inter-repetition-interval (n ef &optional of-matrix)
-  (let ((of (get-optimal-factor n ef of-matrix)))
-    (if (= 1 n)
-       of
-      (* of (inter-repetition-interval (1- n) ef of-matrix)))))
-
-(defun modify-e-factor (ef quality)
-  (if (< ef 1.3)
-      1.3
-    (+ ef (- 0.1 (* (- 5 quality) (+ 0.08 (* (- 5 quality) 0.02)))))))
-
-(defun modify-of (of q fraction)
-  (let ((temp (* of (+ 0.72 (* q 0.07)))))
-    (+ (* (- 1 fraction) of) (* fraction temp))))
-
-(defun calculate-new-optimal-factor (interval-used quality used-of
-                                                  old-of fraction)
-  "This implements the SM-5 learning algorithm in Lisp.
-INTERVAL-USED is the last interval used for the item in question.
-QUALITY is the quality of the repetition response.
-USED-OF is the optimal factor used in calculation of the last
-interval used for the item in question.
-OLD-OF is the previous value of the OF entry corresponding to the
-relevant repetition number and the E-Factor of the item.
-FRACTION is a number belonging to the range (0,1) determining the
-rate of modifications (the greater it is the faster the changes
-of the OF matrix).
-
-Returns the newly calculated value of the considered entry of the
-OF matrix."
-  (let (;; the value proposed for the modifier in case of q=5
-       (mod5 (/ (1+ interval-used) interval-used))
-       ;; the value proposed for the modifier in case of q=2
-       (mod2 (/ (1- interval-used) interval-used))
-       ;; the number determining how many times the OF value will
-       ;; increase or decrease
-       modifier)
-    (if (< mod5 1.05)
-       (setq mod5 1.05))
-    (if (< mod2 0.75)
-       (setq mod5 0.75))
-    (if (> quality 4)
-       (setq modifier (1+ (* (- mod5 1) (- quality 4))))
-      (setq modifier (- 1 (* (/ (- 1 mod2) 2) (- 4 quality)))))
-    (if (< modifier 0.05)
-       (setq modifier 0.05))
-    (setq new-of (* used-of modifier))
-    (if (> quality 4)
-       (if (< new-of old-of)
-           (setq new-of old-of)))
-    (if (< quality 4)
-       (if (> new-of old-of)
-           (setq new-of old-of)))
-    (setq new-of (+ (* new-of fraction) (* old-of (- 1 fraction))))
-    (if (< new-of 1.2)
-       (setq new-of 1.2)
-      new-of)))
-
-(defvar initial-repetition-state '(-1 1 2.5 nil))
-
-(defun determine-next-interval (n ef quality of-matrix)
-  (assert (> n 0))
-  (assert (and (>= quality 0) (<= quality 5)))
-  (if (< quality 3)
-      (list (inter-repetition-interval n ef) (1+ n) ef nil)
-    (let ((next-ef (modify-e-factor ef quality)))
-      (setq of-matrix
-           (set-optimal-factor n next-ef of-matrix
-                               (modify-of (get-optimal-factor n ef of-matrix)
-                                          quality org-learn-fraction))
-           ef next-ef)
-      ;; For a zero-based quality of 4 or 5, don't repeat
-      (if (and (>= quality 4)
-              (not org-learn-always-reschedule))
-         (list 0 (1+ n) ef of-matrix)
-       (list (inter-repetition-interval n ef of-matrix) (1+ n)
-             ef of-matrix)))))
-
-(defun org-smart-reschedule (quality)
-  (interactive "nHow well did you remember the information (on a scale of 
0-5)? ")
-  (let* ((learn-str (org-entry-get (point) "LEARN_DATA"))
-        (learn-data (or (and learn-str
-                             (read learn-str))
-                        (copy-list initial-repetition-state)))
-        closed-dates)
-    (setq learn-data
-         (determine-next-interval (nth 1 learn-data)
-                                  (nth 2 learn-data)
-                                  quality
-                                  (nth 3 learn-data)))
-    (org-entry-put (point) "LEARN_DATA" (prin1-to-string learn-data))
-    (if (= 0 (nth 0 learn-data))
-       (org-schedule t)
-      (org-schedule nil (time-add (current-time)
-                                 (days-to-time (nth 0 learn-data)))))))
-
-(provide 'org-learn)
-
-;;; org-learn.el ends here
diff --git a/contrib/lisp/org-license.el b/contrib/lisp/org-license.el
deleted file mode 100644
index 0f95ea5..0000000
--- a/contrib/lisp/org-license.el
+++ /dev/null
@@ -1,540 +0,0 @@
-;;; org-license.el --- Add a license to your org files
-
-;; Copyright (C) 2013-2021 Free Software Foundation, Inc.
-
-;; Author: David Arroyo Menรฉndez <davidam@es.gnu.org>
-;; Keywords: licenses, creative commons
-;; Homepage: https://orgmode.org
-;;
-;; This file is not part of GNU Emacs, yet.
-;;
-;; 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:
-
-;; This file implements functions to add a license fast in org files.
-;; Org-mode doesn't load this module by default - if this is not what
-;; you want, configure the variable `org-modules'. Thanks to #emacs-es
-;; irc channel for your support.
-
-;;; Code:
-
-;; 
-;;
-;; You can download the images from http://www.davidam/img/licenses.tar.gz
-;;
-;;; CHANGELOG:
-;; v 0.2 - add public domain functions
-;; v 0.1 - Initial release
-
-
-(defvar org-license-images-directory "")
-
-(defun org-license-cc-by (language)
-  (interactive "MLanguage ( br | ca | de | en | es | eo | eu | fi | fr | gl | 
it | jp | nl | pt ): " language)
-  (cond ((equal language "br")
-        (setq org-license-cc-url 
"https://creativecommons.org/licenses/by/3.0/br/deed.pt_BR";)
-        (insert (concat "* Licenรงa
-Este texto รฉ disponibilizado nos termos da licenรงa [[" org-license-cc-url 
"][Atribuiรงรฃo 3.0 Brasil]]\n")))
-       ((equal language "ca")
-        (setq org-license-cc-url 
"https://creativecommons.org/licenses/by/3.0/es/deed.ca";)
-        (insert (concat "* Licรจncia
-El text estร  disponible sota la [[" org-license-cc-url "][Reconeixement 3.0 
Espanya]]\n")))
-       ((equal language "de")
-        (setq org-license-cc-url 
"https://creativecommons.org/licenses/by/3.0/de/deed.de";)
-        (insert (concat "* Lizenz
-Dieses Werk bzw. Inhalt steht unter einer [[" org-license-cc-url "][Lizenz 
Creative Commons Namensnennung 3.0 Deutschland]]\n")))
-       ((equal language "eo")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by/3.0/eo/deed.eo";)
-        (insert (concat "* Licenco
-ฤˆi tiu verko estas disponebla laลญ la permesilo [[" org-license-cc-url "][Krea 
Komunaฤตo Atribuite 3.0 Neadaptita]]\n")))
-        ((equal language "es")
-         (setq org-license-cc-url 
"http://creativecommons.org/licenses/by/3.0/es/deed.es";)
-         (insert (concat "* Licencia
-Este documento estรก bajo una [[" org-license-cc-url "][Licencia Creative 
Commons Atribuciรณn 3.0 Espaรฑa]]\n")))
-        ((equal language "eu")
-         (setq org-license-cc-url 
"http://creativecommons.org/licenses/by/3.0/es/deed.eu";)
-         (insert (concat "* Licenzua
-Testua [[" org-license-cc-url "][Aitortu 3.0 Espainia]] lizentziari jarraituz 
erabil daiteke\n")))
-        ((equal language "fi")
-         (setq org-license-cc-url 
"http://creativecommons.org/licenses/by/1.0/fi/deed.fi";)
-         (insert (concat "* Lisenssi
-Teksti on saatavilla [[" org-license-cc-url "][Nimeรค 1.0 Suomi]] 
lisenssillรค\n")))
-        ((equal language "fr")
-         (setq org-license-cc-url 
"http://creativecommons.org/licenses/by/3.0/fr/deed.fr";)
-         (insert (concat "* Licence
-Ce(tte) ล“uvre est mise ร  disposition selon les termes de la [[" 
org-license-cc-url "][Licence Creative Commons Attribution 3.0 France]]\n")))
-        ((equal language "gl")
-         (setq org-license-cc-url 
"http://creativecommons.org/licenses/by/3.0/es/deed.gl";)
-         (insert (concat "* Licenza
-Todo o texto estรก dispoรฑible baixo a [[" org-license-cc-url "][licenza 
Creative Commons recoรฑecemento compartir igual 3.0]].\n")))
-        ((equal language "it")
-         (setq org-license-cc-url 
"http://creativecommons.org/licenses/by/3.0/it/deed.it";)
-         (insert (concat "* Licenza
-Quest'opera e distribuita con Licenza [[" org-license-cc-url "][Licenza 
Creative Commons Attribuzione 3.0 Italia]]\n")))
-        ((equal language "jp")
-         (setq org-license-cc-url 
"http://creativecommons.org/licenses/by/2.1/jp/deed.en";)
-         (insert (concat "* ใƒฉใ‚คใ‚ปใƒณใ‚น
-ใ“ใฎๆ–‡ๆ›ธใฏ [[" org-license-cc-url "][Creative Commons Attribution 2.1 ]] 
ใƒฉใ‚คใ‚ปใƒณใ‚นใฎไธ‹ใงใ‚ใ‚‹\n")))
-        ((equal language "nl")
-         (setq org-license-cc-url 
"http://creativecommons.org/licenses/by/3.0/nl/deed.nl";)
-         (insert (concat "* Licentie
-Dit werk is valt onder een [[" org-license-cc-url "][Creative Commons 
Naamsvermelding 3.0 Nederland]]\n")))
-        ((equal language "pt")
-         (setq org-license-cc-url 
"http://creativecommons.org/licenses/by/3.0/pt/deed.pt";)
-         (insert (concat "* Licenรงa
-Este texto รฉ disponibilizado nos termos da licenรงa [[" org-license-cc-url 
"][Atribuiรงรฃo 3.0 Portugal]]\n")))
-        (t
-         (setq org-license-cc-url 
"http://creativecommons.org/licenses/by/4.0/deed";) 
-         (concat (insert "* License
-This document is under a [[" org-license-cc-url "][Creative Commons 
Attribution 4.0 International]]\n"))))
-  (if (string= "" org-license-images-directory)
-      (insert (concat "\n[[" org-license-cc-url 
"][file:http://i.creativecommons.org/l/by/3.0/80x15.png]]\n";))
-    (insert (concat "\n[[" org-license-cc-url "][file:" 
org-license-images-directory "/by/3.0/80x15.png]]\n"))))
-
-(defun org-license-cc-by-sa (language)
-  (interactive "MLanguage ( br | ca | de | en | es | eu | fi | fr | it | jp | 
nl | pt ): " language)
-  (cond ((equal language "br")
-        (setq org-license-cc-url 
"https://creativecommons.org/licenses/by-sa/3.0/br/deed.pt_BR";)
-        (concat (insert "* Licenรงa
-Este texto รฉ disponibilizado nos termos da licenรงa [[" org-license-cc-url 
"][Atribuiรงรฃo Compartil ha Igual 3.0 Brasil]]\n")))
-       ((equal language "ca")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-sa/3.0/es/deed.ca";)
-        (insert (concat "* Licรจncia
-El text estร  disponible sota la [[" org-license-cc-url 
"][Reconeixement-CompartirIgual 3.0 Espanya]]\n")))
-       ((equal language "de")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-sa/3.0/de/deed.de";)
-        (insert (concat "* Lizenz
-Dieses Werk bzw. Inhalt steht unter einer [[" org-license-cc-url 
"][Namensnennung - Weitergabe unter gleichen Bedingungen 3.0 Deutschland]]\n")))
-       ((equal language "es") 
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-sa/3.0/es/deed.es";) 
-        (concat (insert "* Licencia
-Este documento estรก bajo una [[" org-license-cc-url "][Licencia Creative 
Commons Atribuciรณn Compartir por Igual 3.0 Espaรฑa]]\n")))
-       ((equal language "eu")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-sa/3.0/es/deed.eu";)
-        (concat (insert "* Licenzua
-Testua [[" org-license-cc-url "][Aitortu-PartekatuBerdin 3.0 Espainia]] 
lizentziari jarraituz erabil daiteke\n")))
-       ((equal language "fi")
-         (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-sa/1.0/fi/deed.fi";)
-         (insert (concat "* Lisenssi
-Teksti on saatavilla [[" org-license-cc-url "][Nimeรค-JaaSamoin 1.0 Suomi]] 
lisenssillรค\n")))
-       ((equal language "fr")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-sa/3.0/fr/deed.fr";)
-        (concat (insert "* Licence
-Ce(tte) ล“uvre est mise ร  disposition selon les termes de la [[" 
org-license-cc-url "][Licence Creative Commons Attribution - Partage dans les 
Mรชmes Conditions 3.0 France]]\n")))
-       ((equal language "gl")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-sa/3.0/es/deed.gl";)
-        (insert (concat "* Licenza
-Todo o texto estรก dispoรฑible baixo a [[" org-license-cc-url "][licenza 
Creative Commons recoรฑecemento compartir igual 3.0]].\n")))
-       ((equal language "it")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-sa/3.0/it/deed.it";)
-        (insert (concat "* Licenza
-Quest'opera e distribuita con Licenza [[" org-license-cc-url "][Licenza 
Creative Commons Attribuzione - Condividi allo stesso modo 3.0 Italia]]\n")))
-       ((equal language "jp")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-sa/2.1/jp/deed.en";)
-        (insert (concat "* ใƒฉใ‚คใ‚ปใƒณใ‚น
-ใ“ใฎๆ–‡ๆ›ธใฏใ€[[" org-license-cc-url "][Creative Commons Attribution 2.1 ]] 
ใƒฉใ‚คใ‚ปใƒณใ‚นใฎไธ‹ใงใ‚ใ‚‹\n")))
-       ((equal language "nl")
-         (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-sa/3.0/nl/deed.nl";)
-         (insert (concat "* Licentie
-Dit werk is valt onder een [[" org-license-cc-url "][Creative Commons 
Naamsvermelding Gelijk Delen 3.0 Nederland]]\n")))
-       ((equal language "pt")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-sa/3.0/pt/deed.pt";)
-        (insert (concat "* Licenรงa
-Este texto รฉ disponibilizado nos termos da licenรงa [[" org-license-cc-url 
"][Atribuiรงรฃo-CompartilhaIgual 3.0 Portugal]]\n")))
-       (t
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-sa/4.0/deed";)
-        (insert (concat "* License
-This document is under a [[" org-license-cc-url "][Creative Commons 
Attribution-ShareAlike 4.0 International]]\n"))))
-  (if (string= "" org-license-images-directory)
-      (insert (concat "\n[[" org-license-cc-url 
"][file:http://i.creativecommons.org/l/by-sa/3.0/80x15.png]]\n";))
-    (insert (concat "\n[[" org-license-cc-url "][file:" 
org-license-images-directory "/by-sa/3.0/80x15.png]]\n"))))
-
-(defun org-license-cc-by-nd (language)
-  (interactive "MLanguage ( br | ca | de | en | es | eu | fi | fr | it | pt ): 
" language)
-  (cond ((equal language "br")
-        (setq org-license-cc-url 
"https://creativecommons.org/licenses/by-nd/3.0/br/deed.pt_BR";)
-        (insert (concat "* Licenรงa
-Este texto รฉ disponibilizado nos termos da licenรงa [[" org-license-cc-url 
"][Atribuiรงรฃo Compartil ha Igual 3.0 Brasil]]\n")))
-       ((equal language "ca")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nd/3.0/es/deed.ca";)
-        (insert (concat "* Licรจncia
-El text estร  disponible sota la [[" org-license-cc-url 
"][Reconeixement-SenseObraDerivada 3.0 Espanya]]\n")))
-       ((equal language "de")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nd/3.0/de/deed.de";)
-        (insert (concat "* Lizenz
-Dieses Werk bzw. Inhalt steht unter einer [[" org-license-cc-url 
"][Namensnennung-Keine Bearbeitung 3.0 Deutschland]]\n")))
-       ((equal language "es")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nd/3.0/es/deed.es";) 
-        (insert (concat "* Licencia
-Este documento estรก bajo una [[" org-license-cc-url "][Licencia Creative 
Commons Atribuciรณn-SinDerivadas 3.0]]\n")))
-       ((equal language "eu")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nd/3.0/es/deed.eu";)
-        (insert (concat "* Licenzua
-Testua [[" org-license-cc-url "][Aitortu-LanEratorririkGabe 3.0 Espainia]] 
lizentziari jarraituz erabil daiteke\n")))
-       ((equal language "fi")
-         (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nd/1.0/fi/deed.fi";)
-         (insert (concat "* Lisenssi
-Teksti on saatavilla [[" org-license-cc-url "][Nimeรค-JaaSamoin 1.0 Suomi]] 
lisenssillรค\n")))
-       ((equal language "fr")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nd/3.0/fr/deed.fr";)
-        (insert (concat "* Licence
-Ce(tte) ล“uvre est mise ร  disposition selon les termes de la [[" 
org-license-cc-url "][Licence Creative Commons Attribution - Pas de 
Modification 3.0 France]]\n")))
-       ((equal language "gl")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nd/3.0/es/deed.gl";)
-        (insert (concat "* Licenza
-Todo o texto estรก dispoรฑible baixo a [[" org-license-cc-url "][licenza 
Creative Commons recoรฑecemento compartir igual 3.0]].\n")))
-       ((equal language "it")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nd/3.0/it/deed.it";)
-        (insert (concat "* Licenza
-Quest'opera e distribuita con Licenza [[" org-license-cc-url "][Licenza 
Creative Commons Attribuzione - Non opere derivate 3.0 Italia]]\n")))
-       ((equal language "jp")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nd/2.1/jp/deed.en";)
-        (insert (concat "* ใƒฉใ‚คใ‚ปใƒณใ‚น
-ใ“ใฎๆ–‡ๆ›ธใฏใ€[[" org-license-cc-url "][Creative Commons No Derivatives 2.1]] 
ใƒฉใ‚คใ‚ปใƒณใ‚นใฎไธ‹ใงใ‚ใ‚‹\n")))
-       ((equal language "nl")
-         (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nd/3.0/nl/deed.nl";)
-         (insert (concat "* Licentie
-Dit werk is valt onder een [[" org-license-cc-url "][Creative Commons 
Naamsvermelding GeenAfgeleideWerken 3.0 Nederland]]\n")))
-       ((equal language "pt")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nd/3.0/pt/deed.pt";)
-        (insert (concat "* Licenรงa
-Este texto รฉ disponibilizado nos termos da licenรงa [[" org-license-cc-url 
"][Atribuiรงรฃo Sem Derivados 3.0 Portugal]]\n")))
-       (t
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nd/4.0/deed";)
-        (insert (concat "* License
-This document is under a [[" org-license-cc-url "][Creative Commons No 
Derivatives 4.0 International]]\n"))))
-  (if (string= "" org-license-images-directory)
-      (insert (concat "\n[[" org-license-cc-url 
"][file:http://i.creativecommons.org/l/by-nd/3.0/80x15.png]]\n";))
-    (insert (concat "\n[[" org-license-cc-url "][file:" 
org-license-images-directory "/by-nd/3.0/80x15.png]]\n"))))
-
-
-(defun org-license-cc-by-nc (language)
-  (interactive "MLanguage ( br | ca | de | en | es | eu | fi | fr | it | jp | 
nl | pt ): " language)
-  (cond ((equal language "br")
-        (setq org-license-cc-url 
"https://creativecommons.org/licenses/by-nc/3.0/br/deed.pt_BR";)
-        (insert (concat "* Licenรงa
-Este texto รฉ disponibilizado nos termos da licenรงa [[" org-license-cc-url 
"][Atribuiรงรฃo Nรฃo Comercial 3.0 Brasil]]\n")))
-       ((equal language "ca")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nc/3.0/es/deed.ca";)
-        (insert (concat "* Licรจncia
-El text estร  disponible sota la [[" org-license-cc-url 
"][Reconeixement-NoComercial 3.0 Espanya]]\n")))
-       ((equal language "de")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nc/3.0/de/deed.de";)
-        (insert (concat "* Lizenz
-Dieses Werk bzw. Inhalt steht unter einer [[" org-license-cc-url 
"][Namensnennung-Nicht-kommerziell 3.0 Deutschland]]\n")))
-       ((equal language "es")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nc/3.0/es/deed.es";)
-        (insert (concat "* Licencia
-Este documento estรก bajo una [[" org-license-cc-url "][Licencia Creative 
Commons Reconocimiento-NoComercial 3.0]]\n")))
-       ((equal language "eu")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nc/3.0/es/deed.eu";)
-        (insert "* Licenzua
-Testua [[" org-license-cc-url "][Aitortu-EzKomertziala 3.0 Espainia]] 
lizentziari jarraituz erabil daiteke\n"))
-       ((equal language "fi")
-         (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nc/1.0/fi/deed.fi";)
-         (insert (concat "* Lisenssi
-Teksti on saatavilla [[" org-license-cc-url "][Nimeรค-Epรคkaupallinen 1.0 
Suomi]] lisenssillรค\n")))
-       ((equal language "fr")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nc/3.0/fr/deed.fr";)
-        (insert (concat "* Licence
-Ce(tte) ล“uvre est mise ร  disposition selon les termes de la [[" 
org-license-cc-url "][Licence Creative Commons Attribution - Pas d'Utilisation 
Commerciale 3.0 France]]\n")))
-       ((equal language "gl")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nc/3.0/es/deed.gl";)
-        (insert (concat "* Licenza
-Todo o texto estรก dispoรฑible baixo a [[" org-license-cc-url "][licenza 
Creative Commons recoรฑecemento compartir igual 3.0]].\n")))
-       ((equal language "it")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nc/3.0/it/deed.it";)
-        (insert (concat "* Licenza
-Quest'opera e distribuita con Licenza [[" org-license-cc-url "][Licenza 
Creative Commons Attribuzione - Non commerciale 3.0 Italia]]\n")))
-       ((equal language "jp")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nc/2.1/jp/deed.en";)
-        (insert (concat "* ใƒฉใ‚คใ‚ปใƒณใ‚น
-ใ“ใฎๆ–‡ๆ›ธใฏใ€[[" org-license-cc-url "][Creative Commons Attribution-NonCommercial 2.1 
]] ใƒฉใ‚คใ‚ปใƒณใ‚นใฎไธ‹ใงใ‚ใ‚‹\n")))
-       ((equal language "nl")
-         (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nc/3.0/nl/deed.nl";)
-         (insert (concat "* Licentie
-Dit werk is valt onder een [[" org-license-cc-url "][Creative Commons 
Naamsvermelding NietCommercieel 3.0 Nederland 3.0 Nederland]]\n")))
-       ((equal language "pt")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nc/3.0/pt/deed.pt";)
-        (insert (concat "* Licenรงa
-Este texto รฉ disponibilizado nos termos da licenรงa [[" org-license-cc-url 
"][Atribuiรงรฃo Nรฃo Comercial 3.0 Portugal]]\n")))
-       (t 
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nc/4.0/deed";)
-        (insert (concat "* License 
-This document is under a [[" org-license-cc-url "][Creative Commons 
Attribution-NonCommercial 4.0 International]]\n"))))
-  (if (string= "" org-license-images-directory)
-      (insert (concat "\n[[" org-license-cc-url 
"][file:http://i.creativecommons.org/l/by-nc/3.0/80x15.png]]\n";))
-    (insert (concat "\n[[" org-license-cc-url "][file:" 
org-license-images-directory "/by-nc/3.0/80x15.png]]\n"))))
-
-(defun org-license-cc-by-nc-sa (language)
-  (interactive "MLanguage ( br | ca | de | en | es | eu | fi | fr | gl | it | 
jp | nl | pt ): " language)
-  (cond ((equal language "br")
-        (setq org-license-cc-url 
"https://creativecommons.org/licenses/by-nc-sa/3.0/br/deed.pt_BR";)
-        (insert (concat "* Licenรงa
-Este texto รฉ disponibilizado nos termos da licenรงa [[" org-license-cc-url 
"][Atribuiรงรฃo Nรฃo Comercial - Compartil ha Igual 3.0 Brasil]]\n")))
-       ((equal language "ca")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nc-sa/3.0/es/deed.ca";)
-        (insert (concat "* Licรจncia
-El text estร  disponible sota la [[" org-license-cc-url 
"][Reconeixement-NoComercial 3.0 Espanya]]\n")))
-       ((equal language "de")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nc-sa/3.0/de/deed.de";)
-        (insert (concat "* Lizenz
-Dieses Werk bzw. Inhalt steht unter einer [[" org-license-cc-url 
"][Namensnennung - Weitergabe unter gleichen Bedingungen 3.0 Deutschland]]\n")))
-       ((equal language "es")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nc-sa/3.0/es/deed.es";) 
-        (insert (concat "* Licencia
-Este documento estรก bajo una [[" org-license-cc-url "][Licencia Creative 
Commons Reconocimiento-NoComercial 3.0]]\n")))
-       ((equal language "eu")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nc-sa/3.0/es/deed.eu";)
-        (insert "* Licenzua
-Testua [[" org-license-cc-url "][Aitortu-EzKomertziala-PartekatuBerdin 3.0 
Espainia]] lizentziari jarraituz erabil daiteke\n"))
-       ((equal language "fi")
-         (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nc-sa/1.0/fi/deed.fi";)
-         (insert (concat "* Lisenssi
-Teksti on saatavilla [[" org-license-cc-url "][Nimeรค-Epรคkaupallinen-JaaSamoin 
1.0 Suomi]] lisenssillรค\n")))
-       ((equal language "fr")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nc-sa/3.0/fr/deed.fr";)
-        (insert (concat "* Licence
-Ce(tte) ล“uvre est mise ร  disposition selon les termes de la [[" 
org-license-cc-url "][Licence Creative Commons Attribution - Pas dโ€™Utilisation 
Commerciale - Partage dans les Mรชmes Conditions 3.0 France]]\n")))
-       ((equal language "gl")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nc-sa/3.0/es/deed.gl";)
-        (insert (concat "* Licenza
-Todo o texto estรก dispoรฑible baixo a [[" org-license-cc-url "][licenza 
Creative Commons recoรฑecemento compartir igual 3.0]].\n")))
-       ((equal language "it")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nc-sa/3.0/it/deed.it";)
-        (insert (concat "* Licenza
-Quest'opera e distribuita con Licenza [[" org-license-cc-url "][Licenza 
Creative Commons Attribuzione - Non opere derivate 3.0 Italia]]\n")))
-       ((equal language "jp")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nc-sa/2.1/jp/deed.en";)
-        (insert (concat "* ใƒฉใ‚คใ‚ปใƒณใ‚น
-ใ“ใฎๆ–‡ๆ›ธใฏใ€[[" org-license-cc-url "][License Creative Commons Attribution Non 
Commercial Share Alike 2.1 ]] ใƒฉใ‚คใ‚ปใƒณใ‚นใฎไธ‹ใงใ‚ใ‚‹\n")))
-       ((equal language "nl")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nc-sa/3.0/nl/deed.nl";)
-        (insert (concat "* Licentie
-Dit werk is valt onder een [[" org-license-cc-url "][Creative Commons 
Naamsvermelding NietCommercieel GelijkDelen 3.0 Nederland]]\n")))
-       ((equal language "pt")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nc/3.0/pt/deed.pt";)
-        (insert (concat "* Licenรงa
-Este texto รฉ disponibilizado nos termos da licenรงa [[" org-license-cc-url 
"][Atribuiรงรฃo NรฃoComercial Compartil ha Igual 3.0 Portugal]]\n")))
-       (t 
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nc-sa/4.0/deed";)
-        (insert (concat "* License
-This document is under a [[" org-license-cc-url "][License Creative Commons 
Attribution Non Commercial Share Alike 4.0 International]]\n"))))
-  (if (string= "" org-license-images-directory)
-      (insert (concat "\n[[" org-license-cc-url  
"][file:http://i.creativecommons.org/l/by-nc-sa/3.0/80x15.png]]\n";))
-    (insert (concat "\n[[" org-license-cc-url "][file:" 
org-license-images-directory "/by-nc-sa/3.0/80x15.png]]\n"))))
-
-(defun org-license-cc-by-nc-nd (language)
-  (interactive "MLanguage ( br | ca | de | en | es | eu | fi | fr | gl | it | 
pt ): " language)
-  (cond ((equal language "br")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nc-nd/3.0/pt/deed.pt";)
-        (insert (concat "* Licenรงa
-Este texto รฉ disponibilizado nos termos da licenรงa [[" org-license-cc-url 
"][Atribuiรงรฃo Nรฃo Comercial Sem Derivados 3.0 Brasil]]\n")))
-       ((equal language "ca")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nc-nd/3.0/es/deed.ca";)
-        (insert (concat "* Licรจncia
-El text estร  disponible sota la [[" org-license-cc-url 
"][Reconeixement-NoComercial-SenseObraDerivada 3.0 Espanya]]\n")))
-       ((equal language "de")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nc-nd/3.0/de/deed.de";)
-        (insert (concat "* Lizenz
-Dieses Werk bzw. Inhalt steht unter einer [[" org-license-cc-url 
"][Namensnennung-NichtKommerziell-KeineBearbeitung 3.0 Deutschland]]\n")))
-       ((equal language "es")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nc-nd/3.0/es/deed.es";)
-        (insert (concat "* Licencia 
-Este documento estรก bajo una [[" org-license-cc-url "][Licencia Creative 
Commons Reconocimiento-NoComercial-SinObraDerivada 3.0]]\n")))
-       ((equal language "eu")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nc-nd/3.0/es/deed.eu";)
-        (insert (concat "* Licenzua
-Testua [[" org-license-cc-url "][Aitortu-LanEratorririkGabe 3.0 Espainia]] 
lizentziari jarraituz erabil daiteke\n")))
-       ((equal language "fi")
-         (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nc-nd/1.0/fi/deed.fi";)
-         (insert (concat "* Lisenssi
-Teksti on saatavilla [[" org-license-cc-url "][Nimeรค-Ei 
muutoksia-Epรคkaupallinen 1.0 Suomi]] lisenssillรค\n")))
-       ((equal language "fr")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nc-nd/3.0/fr/deed.fr";)
-        (insert (concat "* Licence
-Ce(tte) ล“uvre est mise ร  disposition selon les termes de la [[" 
org-license-cc-url "][Licence Creative Commons Attribution - Pas de 
Modification 3.0 France]]\n")))
-       ((equal language "gl")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nc-nd/3.0/es/deed.gl";)
-        (insert (concat "* Licenza
-Todo o texto estรก dispoรฑible baixo a [[" org-license-cc-url "][licenza 
Creative Commons recoรฑecemento compartir igual 3.0]].\n")))
-       ((equal language "it")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nc-nd/3.0/it/deed.it";)
-        (insert (concat "* Licenza
-Quest'opera e distribuita con Licenza [[" org-license-cc-url "][Licenza 
Creative Commons Attribuzione - Non opere derivate 3.0 Italia]]\n")))
-       ((equal language "jp")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nc-nd/2.1/jp/deed.en";)
-        (insert (concat "* ใƒฉใ‚คใ‚ปใƒณใ‚น
-ใ“ใฎๆ–‡ๆ›ธใฏ [[" org-license-cc-url "][License Creative Commons Attribution Non 
Commercial - No Derivs 2.1]] ใƒฉใ‚คใ‚ปใƒณใ‚นใฎไธ‹ใงใ‚ใ‚‹\n")))
-       ((equal language "nl")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nc-nd/3.0/nl/deed.nl";)
-        (insert (concat "* Licentie
-Dit werk is valt onder een [[" org-license-cc-url "][Creative Commons 
Naamsvermelding NietCommercieel GeenAfgeleideWerken 3.0 Nederland]]\n")))
-       ((equal language "pt")
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nc-nd/3.0/pt/deed.pt";)
-        (insert (concat "* Licenรงa
-Este texto รฉ disponibilizado nos termos da licenรงa [[" org-license-cc-url 
"][Atribuiรงรฃo Nรฃo Comercial Sem Derivados 3.0 Portugal]]\n")))
-       (t 
-        (setq org-license-cc-url 
"http://creativecommons.org/licenses/by-nc-nd/4.0/deed";)
-        (insert (concat "* License
-This document is under a [[" org-license-cc-url "][License Creative Commons 
Attribution-NonCommercial-NoDerivatives 4.0 International]]\n"))))
-  (if (string= "" org-license-images-directory)
-      (insert (concat "\n[[" org-license-cc-url 
"][file:http://i.creativecommons.org/l/by-nc-nd/3.0/80x15.png]]\n";))
-    (insert (concat "\n[[" org-license-cc-url "][file:" 
org-license-images-directory "/by-nc-nd/3.0/80x15.png]]\n"))))
-
-(defun org-license-gfdl (language)
-  (interactive "MLanguage (es | en): " language)
-  (cond ((equal language "es")
-        (insert "* Licencia
-Copyright (C) " (format-time-string "%Y") "  " user-full-name
-"\n    Se permite copiar, distribuir y/o modificar este documento
-    bajo los tรฉrminos de la GNU Free Documentation License, Version 1.3
-    o cualquier versiรณn publicada por la Free Software Foundation;
-    sin Secciones Invariantes y sin Textos de Portada o Contraportada.
-    Una copia de la licencia estรก incluida en 
[[https://www.gnu.org/copyleft/fdl.html][GNU Free Documentation License]].\n"))
-       (t (insert (concat "* License
-Copyright (C) " (format-time-string "%Y") " " user-full-name
-"\n    Permission is granted to copy, distribute and/or modify this document
-    under the terms of the GNU Free Documentation License, Version 1.3
-    or any later version published by the Free Software Foundation;
-    with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
-    A copy of the license is included in 
[[https://www.gnu.org/copyleft/fdl.html][GNU Free Documentation 
License]].\n"))))
-  (if (string= "" org-license-images-directory)
-      (insert 
"\n[[https://www.gnu.org/copyleft/fdl.html][file:https://upload.wikimedia.org/wikipedia/commons/thumb/4/42/GFDL_Logo.svg/200px-GFDL_Logo.svg.png]]\n";)
-    (insert (concat "\n[[https://www.gnu.org/copyleft/fdl.html][file:"; 
org-license-images-directory "/gfdl/gfdl.png]]\n"))))
-
-(defun org-license-publicdomain-zero (language)
-  (interactive "MLanguage ( en | es ): " language)
-  (setq org-license-pd-url "http://creativecommons.org/publicdomain/zero/1.0/";)
-  (setq org-license-pd-file "zero/1.0/80x15.png")
-  (if (equal language "es")
-         (insert (concat "* Licencia
-Este documento estรก bajo una licencia [[" org-license-pd-url "][Public Domain 
Zero]]\n"))
-    (insert (concat "* License
-This documento is under a [[" org-license-pd-url "][Public Domain Zero]] 
license\n")))
-  (if (string= "" org-license-images-directory)
-      (insert (concat "\n[[" org-license-pd-url 
"][file:http://i.creativecommons.org/p/zero/1.0/80x15.png]]\n";))
-    (insert (concat "\n[[" org-license-pd-url "][file:" 
org-license-images-directory org-license-pd-file "]]\n"))))
-
-(defun org-license-publicdomain-mark (language)
-  (interactive "MLanguage ( en | es ): " language)
-  (setq org-license-pd-url "http://creativecommons.org/publicdomain/mark/1.0/";)
-  (setq org-license-pd-file "mark/1.0/80x15.png")
-  (if (equal language "es")
-         (insert (concat "* Licencia
-Este documento estรก bajo una licencia [[" org-license-pd-url "][Etiqueta de 
Dominio Pรบblico 1.0]]\n"))
-    (insert (concat "* License
-This documento is under a [[" org-license-pd-url "][Public Domain Mark]] 
license\n")))
-  (if (string= "" org-license-images-directory)
-      (insert (concat "\n[[" org-license-pd-url 
"][file:http://i.creativecommons.org/p/mark/1.0/80x15.png]]\n";))
-    (insert (concat "\n[[" org-license-pd-url "][file:" 
org-license-images-directory org-license-pd-file "]]\n"))))
-
-(defun org-license-print-all ()
-"Print all combinations of licenses and languages, it's useful to find bugs"
-  (interactive)
-  (org-license-gfdl "es")
-  (org-license-gfdl "en")
-  (org-license-publicdomain-mark "es")
-  (org-license-publicdomain-mark "en")
-  (org-license-publicdomain-zero "es")
-  (org-license-publicdomain-zero "en")
-  (org-license-cc-by "br")
-  (org-license-cc-by "ca")
-  (org-license-cc-by "de")
-  (org-license-cc-by "es")
-  (org-license-cc-by "en")
-  (org-license-cc-by "eo")
-  (org-license-cc-by "eu")
-  (org-license-cc-by "fi")
-  (org-license-cc-by "fr")
-  (org-license-cc-by "gl")
-  (org-license-cc-by "it")
-  (org-license-cc-by "jp")
-  (org-license-cc-by "nl")
-  (org-license-cc-by "pt")
-  (org-license-cc-by-sa "br")
-  (org-license-cc-by-sa "ca")
-  (org-license-cc-by-sa "de")
-  (org-license-cc-by-sa "es")
-  (org-license-cc-by-sa "en")
-;;  (org-license-cc-by-sa "eo")
-  (org-license-cc-by-sa "eu")
-  (org-license-cc-by-sa "fi")
-  (org-license-cc-by-sa "fr")
-  (org-license-cc-by-sa "gl")
-  (org-license-cc-by-sa "it")
-  (org-license-cc-by-sa "jp")
-  (org-license-cc-by-sa "nl")
-  (org-license-cc-by-sa "pt")
-  (org-license-cc-by-nd "br")
-  (org-license-cc-by-nd "ca")
-  (org-license-cc-by-nd "de")
-  (org-license-cc-by-nd "es")
-  (org-license-cc-by-nd "en")
-;;  (org-license-cc-by-nd "eo")
-  (org-license-cc-by-nd "eu")
-  (org-license-cc-by-nd "fi")
-  (org-license-cc-by-nd "fr")
-  (org-license-cc-by-nd "gl")
-  (org-license-cc-by-nd "it")
-  (org-license-cc-by-nd "jp")
-  (org-license-cc-by-nd "nl")
-  (org-license-cc-by-nd "pt")
-  (org-license-cc-by-nc "br")
-  (org-license-cc-by-nc "ca")
-  (org-license-cc-by-nc "de")
-  (org-license-cc-by-nc "es")
-  (org-license-cc-by-nc "en")
-;;  (org-license-cc-by-nc "eo")
-  (org-license-cc-by-nc "eu")
-  (org-license-cc-by-nc "fi")
-  (org-license-cc-by-nc "fr")
-  (org-license-cc-by-nc "gl")
-  (org-license-cc-by-nc "it")
-  (org-license-cc-by-nc "jp")
-  (org-license-cc-by-nc "nl")
-  (org-license-cc-by-nc "pt")
-  (org-license-cc-by-nc-sa "br")
-  (org-license-cc-by-nc-sa "ca")
-  (org-license-cc-by-nc-sa "de")
-  (org-license-cc-by-nc-sa "es")
-  (org-license-cc-by-nc-sa "en")
-;;  (org-license-cc-by-nc-sa "eo")
-  (org-license-cc-by-nc-sa "eu")
-  (org-license-cc-by-nc-sa "fi")
-  (org-license-cc-by-nc-sa "fr")
-  (org-license-cc-by-nc-sa "gl")
-  (org-license-cc-by-nc-sa "it")
-  (org-license-cc-by-nc-sa "jp")
-  (org-license-cc-by-nc-sa "nl")
-  (org-license-cc-by-nc-sa "pt")
-  (org-license-cc-by-nc-nd "br")
-  (org-license-cc-by-nc-nd "ca")
-  (org-license-cc-by-nc-nd "de")
-  (org-license-cc-by-nc-nd "es")
-  (org-license-cc-by-nc-nd "en")
-;;  (org-license-cc-by-nc-nd "eo")
-  (org-license-cc-by-nc-nd "eu")
-  (org-license-cc-by-nc-nd "fi")
-  (org-license-cc-by-nc-nd "fr")
-  (org-license-cc-by-nc-nd "gl")
-  (org-license-cc-by-nc-nd "it")
-  (org-license-cc-by-nc-nd "jp")
-  (org-license-cc-by-nc-nd "nl")
-  (org-license-cc-by-nc-nd "pt")
-)
-
-
diff --git a/contrib/lisp/org-link-edit.el b/contrib/lisp/org-link-edit.el
deleted file mode 100644
index a27a13d..0000000
--- a/contrib/lisp/org-link-edit.el
+++ /dev/null
@@ -1,392 +0,0 @@
-;;; org-link-edit.el --- Slurp and barf with Org links  -*- lexical-binding: 
t; -*-
-
-;; Copyright (C) 2015-2020 Kyle Meyer <kyle@kyleam.com>
-
-;; Author:  Kyle Meyer <kyle@kyleam.com>
-;; URL: https://git.kyleam.com/org-link-edit/about
-;; Keywords: convenience
-;; Version: 1.2.1
-;; Package-Requires: ((cl-lib "0.5") (org "9.3"))
-
-;; 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 <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; Org Link Edit provides Paredit-inspired slurping and barfing
-;; commands for Org link descriptions.
-;;
-;; There are four slurp and barf commands, all which operate when
-;; point is on an Org link.
-;;
-;; - org-link-edit-forward-slurp
-;; - org-link-edit-backward-slurp
-;; - org-link-edit-forward-barf
-;; - org-link-edit-backward-barf
-;;
-;; Org Link Edit doesn't bind these commands to any keys.  Finding
-;; good keys for these commands is difficult because, while it's
-;; convenient to be able to quickly repeat these commands, they won't
-;; be used frequently enough to be worthy of a short, repeat-friendly
-;; binding.  Using Hydra [1] provides a nice solution to this.  After
-;; an initial key sequence, any of the commands will be repeatable
-;; with a single key.  (Plus, you get a nice interface that displays
-;; the key for each command.)  Below is one example of how you could
-;; configure this.
-;;
-;;     (define-key org-mode-map YOUR-KEY
-;;       (defhydra hydra-org-link-edit ()
-;;         "Org Link Edit"
-;;         ("j" org-link-edit-forward-slurp "forward slurp")
-;;         ("k" org-link-edit-forward-barf "forward barf")
-;;         ("u" org-link-edit-backward-slurp "backward slurp")
-;;         ("i" org-link-edit-backward-barf "backward barf")
-;;         ("q" nil "cancel")))
-;;
-;; In addition to the slurp and barf commands, the command
-;; `org-link-edit-transport-next-link' searches for the next (or
-;; previous) link and moves it to point, using the word at point or
-;; the selected region as the link's description.
-;;
-;; [1] https://github.com/abo-abo/hydra
-
-;;; Code:
-
-(require 'org)
-(require 'org-element)
-(require 'cl-lib)
-
-(defun org-link-edit--on-link-p (&optional element)
-  (org-element-lineage (or element (org-element-context)) '(link) t))
-
-(defun org-link-edit--link-data ()
-  "Return list with information about the link at point.
-The list includes
-- the position at the start of the link
-- the position at the end of the link
-- the link text
-- the link description (nil when on a plain link)"
-  (let ((el (org-element-context)))
-    (unless (org-link-edit--on-link-p el)
-      (user-error "Point is not on a link"))
-    (save-excursion
-      (goto-char (org-element-property :begin el))
-      (cond
-       ;; Use match-{beginning,end} because match-end is consistently
-       ;; positioned after ]], while the :end property is positioned
-       ;; at the next word on the line, if one is present.
-       ((looking-at org-link-bracket-re)
-        (list (match-beginning 0)
-              (match-end 0)
-              (save-match-data
-                (org-link-unescape (match-string-no-properties 1)))
-              (or (match-string-no-properties 2) "")))
-       ((looking-at org-link-plain-re)
-        (list (match-beginning 0)
-              (match-end 0)
-              (match-string-no-properties 0)
-              nil))
-       (t
-        (error "What am I looking at?"))))))
-
-(defun org-link-edit--forward-blob (n &optional no-punctuation)
-  "Move forward N blobs (backward if N is negative).
-
-A block of non-whitespace characters is a blob.  If
-NO-PUNCTUATION is non-nil, trailing punctuation characters are
-not considered part of the blob when going in the forward
-direction.
-
-If the edge of the buffer is reached before completing the
-movement, return nil.  Otherwise, return t."
-  (let* ((forward-p (> n 0))
-         (nblobs (abs n))
-         (skip-func (if forward-p 'skip-syntax-forward 'skip-syntax-backward))
-         skip-func-retval)
-    (while (/= nblobs 0)
-      (funcall skip-func " ")
-      (setq skip-func-retval (funcall skip-func "^ "))
-      (setq nblobs (1- nblobs)))
-    (when (and forward-p no-punctuation)
-      (let ((punc-tail-offset (save-excursion (skip-syntax-backward "."))))
-        ;; Don't consider trailing punctuation as part of the blob
-        ;; unless the whole blob consists of punctuation.
-        (unless (= skip-func-retval (- punc-tail-offset))
-          (goto-char (+ (point) punc-tail-offset)))))
-    (/= skip-func-retval 0)))
-
-;;;###autoload
-(defun org-link-edit-forward-slurp (&optional n)
-  "Slurp N trailing blobs into link's description.
-
-  The \[\[https://orgmode.org/\]\[Org mode\]\] site
-
-                        |
-                        v
-
-  The \[\[https://orgmode.org/\]\[Org mode site\]\]
-
-A blob is a block of non-whitespace characters.  When slurping
-forward, trailing punctuation characters are not considered part
-of a blob.
-
-After slurping, return the slurped text and move point to the
-beginning of the link.
-
-If N is negative, slurp leading blobs instead of trailing blobs."
-  (interactive "p")
-  (setq n (or n 1))
-  (cond
-   ((= n 0))
-   ((< n 0)
-    (org-link-edit-backward-slurp (- n)))
-   (t
-    (cl-multiple-value-bind (beg end link desc) (org-link-edit--link-data)
-      (goto-char (save-excursion
-                   (goto-char end)
-                   (or (org-link-edit--forward-blob n 'no-punctuation)
-                       (user-error "Not enough blobs after the link"))
-                   (point)))
-      (let ((slurped (buffer-substring-no-properties end (point))))
-        (setq slurped (replace-regexp-in-string "\n+" " " slurped))
-        (when (and (= (length desc) 0)
-                   (string-match "^\\s-+\\(.*\\)" slurped))
-          (setq slurped (match-string 1 slurped)))
-        (setq desc (concat desc slurped)
-              end (+ end (length slurped)))
-        (delete-region beg (point))
-        (insert (org-link-make-string link desc))
-        (goto-char beg)
-        slurped)))))
-
-;;;###autoload
-(defun org-link-edit-backward-slurp (&optional n)
-  "Slurp N leading blobs into link's description.
-
-  The \[\[https://orgmode.org/\]\[Org mode\]\] site
-
-                        |
-                        v
-
-  \[\[https://orgmode.org/\]\[The Org mode\]\] site
-
-A blob is a block of non-whitespace characters.
-
-After slurping, return the slurped text and move point to the
-beginning of the link.
-
-If N is negative, slurp trailing blobs instead of leading blobs."
-  (interactive "p")
-  (setq n (or n 1))
-  (cond
-   ((= n 0))
-   ((< n 0)
-    (org-link-edit-forward-slurp (- n)))
-   (t
-    (cl-multiple-value-bind (beg end link desc) (org-link-edit--link-data)
-      (goto-char (save-excursion
-                   (goto-char beg)
-                   (or (org-link-edit--forward-blob (- n))
-                       (user-error "Not enough blobs before the link"))
-                   (point)))
-      (let ((slurped (buffer-substring-no-properties (point) beg)))
-        (when (and (= (length desc) 0)
-                   (string-match "\\(.*\\)\\s-+$" slurped))
-          (setq slurped (match-string 1 slurped)))
-        (setq slurped (replace-regexp-in-string "\n+" " " slurped))
-        (setq desc (concat slurped desc)
-              beg (- beg (length slurped)))
-        (delete-region (point) end)
-        (insert (org-link-make-string link desc))
-        (goto-char beg)
-        slurped)))))
-
-(defun org-link-edit--split-first-blobs (string n)
-  "Split STRING into (N first blobs . other) cons cell.
-'N first blobs' contains all text from the start of STRING up to
-the start of the N+1 blob.  'other' includes the remaining text
-of STRING.  If the number of blobs in STRING is fewer than N,
-'other' is nil."
-  (when (< n 0) (user-error "N cannot be negative"))
-  (with-temp-buffer
-    (insert string)
-    (goto-char (point-min))
-    (with-syntax-table org-mode-syntax-table
-      (let ((within-bound (org-link-edit--forward-blob n)))
-        (skip-syntax-forward " ")
-        (cons (buffer-substring 1 (point))
-              (and within-bound
-                   (buffer-substring (point) (point-max))))))))
-
-(defun org-link-edit--split-last-blobs (string n)
-  "Split STRING into (other . N last blobs) cons cell.
-'N last blobs' contains all text from the end of STRING back to
-the end of the N+1 last blob.  'other' includes the remaining
-text of STRING.  If the number of blobs in STRING is fewer than
-N, 'other' is nil."
-  (when (< n 0) (user-error "N cannot be negative"))
-  (with-temp-buffer
-    (insert string)
-    (goto-char (point-max))
-    (with-syntax-table org-mode-syntax-table
-      (let ((within-bound (org-link-edit--forward-blob (- n))))
-        (skip-syntax-backward " ")
-        (cons (and within-bound
-                   (buffer-substring 1 (point)))
-              (buffer-substring (point) (point-max)))))))
-
-;;;###autoload
-(defun org-link-edit-forward-barf (&optional n)
-  "Barf N trailing blobs from link's description.
-
-  The \[\[https://orgmode.org/\]\[Org mode\]\] site
-
-                        |
-                        v
-
-  The \[\[https://orgmode.org/\]\[Org\]\] mode site
-
-A blob is a block of non-whitespace characters.
-
-After barfing, return the barfed text and move point to the
-beginning of the link.
-
-If N is negative, barf leading blobs instead of trailing blobs."
-  (interactive "p")
-  (setq n (or n 1))
-  (cond
-   ((= n 0))
-   ((< n 0)
-    (org-link-edit-backward-barf (- n)))
-   (t
-    (cl-multiple-value-bind (beg end link desc) (org-link-edit--link-data)
-      (when (= (length desc) 0)
-        (user-error "Link has no description"))
-      (pcase-let ((`(,new-desc . ,barfed) (org-link-edit--split-last-blobs
-                                           desc n)))
-        (unless new-desc (user-error "Not enough blobs in description"))
-        (goto-char beg)
-        (delete-region beg end)
-        (insert (org-link-make-string link new-desc))
-        (when (string= new-desc "")
-          (setq barfed (concat " " barfed)))
-        (insert barfed)
-        (goto-char beg)
-        barfed)))))
-
-;;;###autoload
-(defun org-link-edit-backward-barf (&optional n)
-  "Barf N leading blobs from link's description.
-
-  The \[\[https://orgmode.org/\]\[Org mode\]\] site
-
-                        |
-                        v
-
-  The Org \[\[https://orgmode.org/\]\[mode\]\] site
-
-A blob is a block of non-whitespace characters.
-
-After barfing, return the barfed text and move point to the
-beginning of the link.
-
-If N is negative, barf trailing blobs instead of leading blobs."
-  (interactive "p")
-  (setq n (or n 1))
-  (cond
-   ((= n 0))
-   ((< n 0)
-    (org-link-edit-forward-barf (- n)))
-   (t
-    (cl-multiple-value-bind (beg end link desc) (org-link-edit--link-data)
-      (when (= (length desc) 0)
-        (user-error "Link has no description"))
-      (pcase-let ((`(,barfed . ,new-desc) (org-link-edit--split-first-blobs
-                                           desc n)))
-        (unless new-desc (user-error "Not enough blobs in description"))
-        (goto-char beg)
-        (delete-region beg end)
-        (insert (org-link-make-string link new-desc))
-        (when (string= new-desc "")
-          (setq barfed (concat barfed " ")))
-        (goto-char beg)
-        (insert barfed)
-        barfed)))))
-
-(defun org-link-edit--next-link-data (&optional previous)
-  (save-excursion
-    (if (funcall (if previous #'re-search-backward #'re-search-forward)
-                 org-link-any-re nil t)
-        (org-link-edit--link-data)
-      (user-error "No %s link found" (if previous "previous" "next")))))
-
-;;;###autoload
-(defun org-link-edit-transport-next-link (&optional previous beg end overwrite)
-  "Move the next link to point.
-
-If the region is active, use the selected text as the link's
-description.  Otherwise, use the word at point.
-
-With prefix argument PREVIOUS, move the previous link instead of
-the next link.
-
-Non-interactively, use the text between BEG and END as the
-description, moving the next (or previous) link relative to BEG
-and END.  By default, refuse to overwrite an existing
-description.  If OVERWRITE is `ask', prompt for confirmation
-before overwriting; for any other non-nil value, overwrite
-without asking."
-  (interactive `(,current-prefix-arg
-                 ,@(if (use-region-p)
-                       (list (region-beginning) (region-end))
-                     (list nil nil))
-                 ask))
-  (let ((pt (point))
-        (desc-bounds (cond
-                      ((and beg end)
-                       (cons (progn (goto-char beg)
-                                    (point-marker))
-                             (progn (goto-char end)
-                                    (point-marker))))
-                      ((not (looking-at-p "\\s-"))
-                       (progn (skip-syntax-backward "w")
-                              (let ((beg (point-marker)))
-                                (skip-syntax-forward "w")
-                                (cons beg (point-marker))))))))
-    (when (or (and desc-bounds
-                   (or (progn (goto-char (car desc-bounds))
-                              (org-link-edit--on-link-p))
-                       (progn (goto-char (cdr desc-bounds))
-                              (org-link-edit--on-link-p))))
-              (progn (goto-char pt)
-                     (org-link-edit--on-link-p)))
-      (user-error "Cannot transport next link with point on a link"))
-    (goto-char (or (car desc-bounds) pt))
-    (cl-multiple-value-bind (link-beg link-end link orig-desc)
-        (org-link-edit--next-link-data previous)
-      (unless (or (not desc-bounds)
-                  (= (length orig-desc) 0)
-                  (if (eq overwrite 'ask)
-                      (y-or-n-p "Overwrite existing description?")
-                    overwrite))
-        (user-error "Link already has a description"))
-      (delete-region link-beg link-end)
-      (insert (org-link-make-string
-               link
-               (if desc-bounds
-                   (delete-and-extract-region (car desc-bounds)
-                                              (cdr desc-bounds))
-                 orig-desc))))))
-
-(provide 'org-link-edit)
-;;; org-link-edit.el ends here
diff --git a/contrib/lisp/org-mac-iCal.el b/contrib/lisp/org-mac-iCal.el
deleted file mode 100644
index 937b6dd..0000000
--- a/contrib/lisp/org-mac-iCal.el
+++ /dev/null
@@ -1,250 +0,0 @@
-;;; org-mac-iCal.el --- Imports events from iCal.app to the Emacs diary
-
-;; Copyright (C) 2009-2014 Christopher Suckling
-
-;; Author: Christopher Suckling <suckling at gmail dot com>
-;; Version: 0.1057.104
-;; Keywords: outlines, calendar
-
-;; This file is not 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, 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:
-;;
-;; This file provides the import of events from Mac OS X 10.5 iCal.app
-;; into the Emacs diary (it is not compatible with OS X < 10.5). The
-;; function org-mac-iCal will import events in all checked iCal.app
-;; calendars for the date range org-mac-iCal-range months, centered
-;; around the current date.
-;;
-;; CAVEAT: This function is destructive; it will overwrite the current
-;; contents of the Emacs diary.
-;;
-;; Installation: add (require 'org-mac-iCal) to your .emacs.
-;;
-;; If you view Emacs diary entries in org-agenda, the following hook
-;; will ensure that all-day events are not orphaned below TODO items
-;; and that any supplementary fields to events (e.g. Location) are
-;; grouped with their parent event
-;;
-;; (add-hook 'org-agenda-cleanup-fancy-diary-hook
-;;       (lambda ()
-;;         (goto-char (point-min))
-;;         (save-excursion
-;;           (while (re-search-forward "^[a-z]" nil t)
-;;             (goto-char (match-beginning 0))
-;;             (insert "0:00-24:00 ")))
-;;         (while (re-search-forward "^ [a-z]" nil t)
-;;           (goto-char (match-beginning 0))
-;;           (save-excursion
-;;             (re-search-backward "^[0-9]+:[0-9]+-[0-9]+:[0-9]+ " nil t))
-;;           (insert (match-string 0)))))
-
-;;; Code:
-
-(defcustom org-mac-iCal-range 2
-  "The range in months to import iCal.app entries into the Emacs
-diary. The import is centered around today's date; thus a value
-of 2 imports entries for one month before and one month after
-today's date"
-  :group 'org-time
-  :type 'integer)
-
-(defun org-mac-iCal ()
-  "Selects checked calendars in iCal.app and imports them into
-the the Emacs diary"
-  (interactive)
-
-  ;; kill diary buffers then empty diary files to avoid duplicates
-  (setq currentBuffer (buffer-name))
-  (setq openBuffers (mapcar (function buffer-name) (buffer-list)))
-  (omi-kill-diary-buffer openBuffers)
-  (with-temp-buffer
-    (insert-file-contents diary-file)
-    (delete-region (point-min) (point-max))
-    (write-region (point-min) (point-max) diary-file))
-
-  ;; determine available calendars
-  (setq caldav-folders (directory-files "~/Library/Calendars" 1 ".*caldav$"))
-  (setq caldav-calendars nil)
-  (mapc
-     (lambda (x)
-       (setq caldav-calendars (nconc caldav-calendars (directory-files x 1 
".*calendar$"))))
-     caldav-folders)
-
-  (setq local-calendars nil)
-  (setq local-calendars (directory-files "~/Library/Calendars" 1 
".*calendar$"))
-
-  (setq all-calendars (append caldav-calendars local-calendars))
-
-  ;; parse each calendar's Info.plist to see if calendar is checked in iCal
-  (setq all-calendars (delq 'nil (mapcar
-                                   (lambda (x)
-                                     (omi-checked x))
-                                   all-calendars)))
-
-  ;; for each calendar, concatenate individual events into a single ics file
-  (with-temp-buffer
-    (shell-command "sw_vers" (current-buffer))
-    (when (re-search-backward "10\\.[5678]" nil t)
-      (omi-concat-leopard-ics all-calendars)))
-
-  ;; move all caldav ics files to the same place as local ics files
-  (mapc
-   (lambda (x)
-     (mapc
-      (lambda (y)
-        (rename-file (concat x "/" y);
-                     (concat "~/Library/Calendars/" y)))
-      (directory-files x nil ".*ics$")))
-   caldav-folders)
-
-  ;; check calendar has contents and import
-  (setq import-calendars (directory-files "~/Library/Calendars" 1 ".*ics$"))
-  (mapc
-   (lambda (x)
-     (when (/= (nth 7 (file-attributes x 'string)) 0)
-       (omi-import-ics x)))
-   import-calendars)
-
-  ;; tidy up intermediate files and buffers
-  (setq usedCalendarsBuffers (mapcar (function buffer-name) (buffer-list)))
-  (omi-kill-ics-buffer usedCalendarsBuffers)
-  (setq usedCalendarsFiles (directory-files "~/Library/Calendars" 1 ".*ics$"))
-  (omi-delete-ics-file usedCalendarsFiles)
-
-  (org-pop-to-buffer-same-window currentBuffer))
-
-(defun omi-concat-leopard-ics (list)
-  "Leopard stores each iCal.app event in a separate ics file.
-Whilst useful for Spotlight indexing, this is less helpful for
-icalendar-import-file. omi-concat-leopard-ics concatenates these
-individual event files into a single ics file"
-  (mapc
-   (lambda (x)
-     (setq omi-leopard-events (directory-files (concat x "/Events") 1 
".*ics$"))
-     (with-temp-buffer
-       (mapc
-       (lambda (y)
-         (insert-file-contents (expand-file-name y)))
-       omi-leopard-events)
-       (write-region (point-min) (point-max) (concat (expand-file-name x) 
".ics"))))
-   list))
-
-(defun omi-import-ics (string)
-  "Imports an ics file into the Emacs diary. First tidies up the
-ics file so that it is suitable for import and selects a sensible
-date range so that Emacs calendar view doesn't grind to a halt"
-  (with-temp-buffer
-    (insert-file-contents string)
-    (goto-char (point-min))
-    (while
-       (re-search-forward "^BEGIN:VCALENDAR$" nil t)
-      (setq startEntry (match-beginning 0))
-      (re-search-forward "^END:VCALENDAR$" nil t)
-      (setq endEntry (match-end 0))
-      (save-restriction
-       (narrow-to-region startEntry endEntry)
-       (goto-char (point-min))
-       (re-search-forward 
"\\(^DTSTART;.*:\\)\\([0-9][0-9][0-9][0-9]\\)\\([0-9][0-9]\\)" nil t)
-       (if (or (eq (match-string 2) nil) (eq (match-string 3) nil))
-           (progn
-             (setq yearEntry 1)
-             (setq monthEntry 1))
-         (setq yearEntry (string-to-number (match-string 2)))
-         (setq monthEntry (string-to-number (match-string 3))))
-       (setq year (string-to-number (format-time-string "%Y")))
-       (setq month (string-to-number (format-time-string "%m")))
-        (setq now (list month 1 year))
-        (setq entryDate (list monthEntry 1 yearEntry))
-        ;; Check to see if this is a repeating event
-        (goto-char (point-min))
-        (setq isRepeating (re-search-forward "^RRULE:" nil t))
-       ;; Delete if outside range and not repeating
-        (when (and
-               (not isRepeating)
-               (> (abs (- (calendar-absolute-from-gregorian now)
-                          (calendar-absolute-from-gregorian entryDate)))
-                  (* (/ org-mac-iCal-range 2) 30))
-         (delete-region startEntry endEntry)))
-          (goto-char (point-max))))
-    (while
-       (re-search-forward "^END:VEVENT$" nil t)
-      (delete-blank-lines))
-    (goto-line 1)
-    (insert "BEGIN:VCALENDAR\n\n")
-    (goto-line 2)
-    (while
-       (re-search-forward "^BEGIN:VCALENDAR$" nil t)
-      (replace-match "\n"))
-    (goto-line 2)
-    (while
-       (re-search-forward "^END:VCALENDAR$" nil t)
-      (replace-match "\n"))
-    (insert "END:VCALENDAR")
-    (goto-line 1)
-    (delete-blank-lines)
-    (while
-       (re-search-forward "^END:VEVENT$" nil t)
-      (delete-blank-lines))
-    (goto-line 1)
-    (while
-       (re-search-forward "^ORG.*" nil t)
-      (replace-match "\n"))
-    (goto-line 1)
-    (write-region (point-min) (point-max) string))
-
-  (icalendar-import-file string diary-file))
-
-(defun omi-kill-diary-buffer (list)
-  (mapc
-   (lambda (x)
-     (if (string-match "^diary" x)
-        (kill-buffer x)))
-   list))
-
-(defun omi-kill-ics-buffer (list)
-  (mapc
-   (lambda (x)
-     (if (string-match "ics$" x)
-        (kill-buffer x)))
-   list))
-
-(defun omi-delete-ics-file (list)
-  (mapc
-   (lambda (x)
-     (delete-file x))
-   list))
-
-(defun omi-checked (directory)
-  "Parse Info.plist in iCal.app calendar folder and determine
-whether Checked key is 1. If Checked key is not 1, remove
-calendar from list of calendars for import"
-  (let* ((root (xml-parse-file (car (directory-files directory 1 
"Info.plist"))))
-        (plist (car root))
-        (dict (car (xml-get-children plist 'dict)))
-        (keys (cdr (xml-node-children dict)))
-        (keys (mapcar
-               (lambda (x)
-                 (cond ((listp x)
-                        x)))
-               keys))
-        (keys (delq 'nil keys)))
-    (when (equal "1" (car (cddr (lax-plist-get keys '(key nil "Checked")))))
-      directory)))
-
-(provide 'org-mac-iCal)
-
-;;; org-mac-iCal.el ends here
diff --git a/contrib/lisp/org-mac-link.el b/contrib/lisp/org-mac-link.el
deleted file mode 100644
index e56354c..0000000
--- a/contrib/lisp/org-mac-link.el
+++ /dev/null
@@ -1,1015 +0,0 @@
-;;; org-mac-link.el --- Insert org-mode links to items selected in various Mac 
apps
-;;
-;; Copyright (c) 2010-2021 Free Software Foundation, Inc.
-;;
-;; Author: Anthony Lander <anthony.lander@gmail.com>
-;;      John Wiegley <johnw@gnu.org>
-;;      Christopher Suckling <suckling at gmail dot com>
-;;      Daniil Frumin <difrumin@gmail.com>
-;;      Alan Schmitt <alan.schmitt@polytechnique.org>
-;;      Mike McLean <mike.mclean@pobox.com>
-;;
-;;
-;; Version: 1.1
-;; Keywords: org, mac, hyperlink
-;;
-;; Version: 1.2
-;; Keywords: outlook
-;; Author: Mike McLean <mike.mclean@pobox.com>
-;; Add support for Microsoft Outlook for Mac as Org mode links
-;;
-;; Version: 1.3
-;; Author: Alan Schmitt <alan.schmitt@polytechnique.org>
-;; Consistently use `org-mac-paste-applescript-links'
-;;
-;; Version 1.4
-;; Author: Mike McLean <mike.mclean@pobox.com>
-;; Make the path to Microsoft Outlook a `defcustom'
-;;
-;; Version 1.5
-;; Author: Mike McLean <mike.mclean@pobox.com>
-;; Add Support for Evernote
-;;
-;; This file is not 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, 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:
-;;
-;; This code allows you to grab either the current selected items, or
-;; the frontmost url in various mac appliations, and insert them as
-;; hyperlinks into the current org-mode document at point.
-;;
-;; This code is heavily based on, and indeed incorporates,
-;; org-mac-message.el written by John Wiegley and Christopher
-;; Suckling.
-;;
-;; Detailed comments for each application interface are inlined with
-;; the code.  Here is a brief overview of how the code interacts with
-;; each application:
-;;
-;; Finder.app - grab links to the selected files in the frontmost window
-;; Mail.app - grab links to the selected messages in the message list
-;; AddressBook.app - Grab links to the selected addressbook Cards
-;; Firefox.app - Grab the url of the frontmost tab in the frontmost window
-;; Vimperator/Firefox.app - Grab the url of the frontmost tab in the frontmost 
window
-;; Safari.app - Grab the url of the frontmost tab in the frontmost window
-;; Google Chrome.app - Grab the url of the frontmost tab in the frontmost 
window
-;; Brave.app - Grab the url of the frontmost tab in the frontmost window
-;; Together.app - Grab links to the selected items in the library list
-;; Skim.app - Grab a link to the selected page in the topmost pdf document
-;; Microsoft Outlook.app - Grab a link to the selected message in the message 
list
-;; DEVONthink Pro Office.app - Grab a link to the selected DEVONthink item(s); 
open DEVONthink item by reference
-;; Evernote.app - Grab a link to the selected Evernote item(s); open Evernote 
item by ID
-;;
-;;
-;; Installation:
-;;
-;; add (require 'org-mac-link) to your .emacs, and optionally bind a
-;; key to activate the link grabber menu, like this:
-;;
-;; (add-hook 'org-mode-hook (lambda ()
-;;   (define-key org-mode-map (kbd "C-c g") 'org-mac-grab-link)))
-;;
-;; Usage:
-;;
-;; Type C-c g (or whatever key you defined, as above), or type M-x
-;; org-mac-grab-link RET to activate the link grabber.  This will present
-;; you with a menu to choose an application from which to grab a link
-;; to insert at point.  You may also type C-g to abort.
-;;
-;; Customizing:
-;;
-;; You may customize which applications appear in the grab menu by
-;; customizing the group `org-mac-link'.  Changes take effect
-;; immediately.
-;;
-;;
-;;; Code:
-
-(require 'org)
-
-(defgroup org-mac-link nil
-  "Options for grabbing links from Mac applications."
-  :tag "Org Mac link"
-  :group 'org-link)
-
-(defcustom org-mac-grab-Finder-app-p t
-  "Add menu option [F]inder to grab links from the Finder."
-  :tag "Grab Finder.app links"
-  :group 'org-mac-link
-  :type 'boolean)
-
-(defcustom org-mac-grab-Mail-app-p t
-  "Add menu option [m]ail to grab links from Mail.app."
-  :tag "Grab Mail.app links"
-  :group 'org-mac-link
-  :type 'boolean)
-
-(defcustom org-mac-grab-Outlook-app-p t
-  "Add menu option [o]utlook to grab links from Microsoft Outlook.app."
-  :tag "Grab Microsoft Outlook.app links"
-  :group 'org-mac-link
-  :type 'boolean)
-
-(defcustom org-mac-outlook-path "/Applications/Microsoft Outlook.app"
-  "The path to the installed copy of Microsoft Outlook.app. Do not escape 
spaces as the AppleScript call will quote this string."
-  :tag "Path to Microsoft Outlook"
-  :group 'org-mac-link
-  :type 'string)
-
-(defcustom org-mac-grab-devonthink-app-p t
-  "Add menu option [d]EVONthink to grab links from DEVONthink Pro Office.app."
-  :tag "Grab DEVONthink Pro Office.app links"
-  :group 'org-mac-link
-  :type 'boolean)
-
-(defcustom org-mac-grab-Addressbook-app-p t
-  "Add menu option [a]ddressbook to grab links from AddressBook.app."
-  :tag "Grab AddressBook.app links"
-  :group 'org-mac-link
-  :type 'boolean)
-
-(defcustom org-mac-grab-Safari-app-p t
-  "Add menu option [s]afari to grab links from Safari.app."
-  :tag "Grab Safari.app links"
-  :group 'org-mac-link
-  :type 'boolean)
-
-(defcustom org-mac-grab-Firefox-app-p t
-  "Add menu option [f]irefox to grab links from Firefox.app."
-  :tag "Grab Firefox.app links"
-  :group 'org-mac-link
-  :type 'boolean)
-
-(defcustom org-mac-grab-Firefox+Vimperator-p nil
-  "Add menu option [v]imperator to grab links from Firefox.app running the 
Vimperator plugin."
-  :tag "Grab Vimperator/Firefox.app links"
-  :group 'org-mac-link
-  :type 'boolean)
-
-(defcustom org-mac-grab-Chrome-app-p t
-  "Add menu option [c]hrome to grab links from Google Chrome.app."
-  :tag "Grab Google Chrome.app links"
-  :group 'org-mac-link
-  :type 'boolean)
-
-(defcustom org-mac-grab-Brave-app-p t
-  "Add menu option [b]rave to grab links from Brave.app."
-  :tag "Grab Brave.app links"
-  :group 'org-mac-link
-  :type 'boolean)
-
-(defcustom org-mac-grab-Together-app-p nil
-  "Add menu option [t]ogether to grab links from Together.app."
-  :tag "Grab Together.app links"
-  :group 'org-mac-link
-  :type 'boolean)
-
-(defcustom org-mac-grab-Skim-app-p
-  (< 0 (length (shell-command-to-string
-                "mdfind kMDItemCFBundleIdentifier == 
'net.sourceforge.skim-app.skim'")))
-  "Add menu option [S]kim to grab page links from Skim.app."
-  :tag "Grab Skim.app page links"
-  :group 'org-mac-link
-  :type 'boolean)
-
-(defcustom org-mac-Skim-highlight-selection-p nil
-  "Highlight the active selection when grabbing a link from Skim.app."
-  :tag "Highlight selection in Skim.app"
-  :group 'org-mac-link
-  :type 'boolean)
-
-(defcustom org-mac-grab-Acrobat-app-p t
-  "Add menu option [A]crobat to grab page links from Acrobat.app."
-  :tag "Grab Acrobat.app page links"
-  :group 'org-mac-link
-  :type 'boolean)
-
-(defgroup org-mac-flagged-mail nil
-  "Options foring linking to flagged Mail.app messages."
-  :tag "Org Mail.app"
-  :group 'org-link)
-
-(defcustom org-mac-mail-account nil
-  "The Mail.app account in which to search for flagged messages."
-  :group 'org-mac-flagged-mail
-  :type 'string)
-
-(defcustom org-mac-grab-Evernote-app-p
-  (< 0 (length (shell-command-to-string
-                "mdfind kMDItemCFBundleIdentifier == 
'com.evernote.Evernote'")))
-  "Add menu option [e]vernote to grab note links from Evernote.app."
-  :tag "Grab Evernote.app note links"
-  :group 'org-mac-link
-  :type 'boolean)
-
-(defcustom org-mac-evernote-path (replace-regexp-in-string (rx (* (any " 
\t\n")) eos)
-                                                           ""
-                                                           
(shell-command-to-string
-                                                            "mdfind 
kMDItemCFBundleIdentifier == 'com.evernote.Evernote'"))
-  "The path to the installed copy of Evernote.app. Do not escape spaces as the 
AppleScript call will quote this string."
-  :tag "Path to Evernote"
-  :group 'org-mac-link
-  :type 'string)
-
-
-;; In mac.c, removed in Emacs 23.
-(declare-function do-applescript "org-mac-message" (script))
-(unless (fboundp 'do-applescript)
-  ;; Need to fake this using shell-command-to-string
-  (defun do-applescript (script)
-    (let (start cmd return)
-      (while (string-match "\n" script)
-        (setq script (replace-match "\r" t t script)))
-      (while (string-match "'" script start)
-        (setq start (+ 2 (match-beginning 0))
-              script (replace-match "\\'" t t script)))
-      (setq cmd (concat "osascript -e '" script "'"))
-      (setq return (shell-command-to-string cmd))
-      (concat "\"" (org-trim return) "\""))))
-
-;;;###autoload
-(defun org-mac-grab-link ()
-  "Prompt for an application to grab a link from.
-When done, go grab the link, and insert it at point."
-  (interactive)
-  (let* ((descriptors
-         `(("F" "inder" org-mac-finder-insert-selected 
,org-mac-grab-Finder-app-p)
-           ("m" "ail" org-mac-message-insert-selected ,org-mac-grab-Mail-app-p)
-           ("d" "EVONthink Pro Office" org-mac-devonthink-item-insert-selected
-            ,org-mac-grab-devonthink-app-p)
-           ("o" "utlook" org-mac-outlook-message-insert-selected 
,org-mac-grab-Outlook-app-p)
-           ("a" "ddressbook" org-mac-addressbook-insert-selected 
,org-mac-grab-Addressbook-app-p)
-           ("s" "afari" org-mac-safari-insert-frontmost-url 
,org-mac-grab-Safari-app-p)
-           ("f" "irefox" org-mac-firefox-insert-frontmost-url 
,org-mac-grab-Firefox-app-p)
-           ("v" "imperator" org-mac-vimperator-insert-frontmost-url 
,org-mac-grab-Firefox+Vimperator-p)
-           ("c" "hrome" org-mac-chrome-insert-frontmost-url 
,org-mac-grab-Chrome-app-p)
-           ("b" "rave" org-mac-brave-insert-frontmost-url 
,org-mac-grab-Brave-app-p)
-            ("e" "evernote" org-mac-evernote-note-insert-selected 
,org-mac-grab-Evernote-app-p)
-           ("t" "ogether" org-mac-together-insert-selected 
,org-mac-grab-Together-app-p)
-           ("S" "kim" org-mac-skim-insert-page ,org-mac-grab-Skim-app-p)
-           ("A" "crobat" org-mac-acrobat-insert-page 
,org-mac-grab-Acrobat-app-p)))
-         (menu-string (make-string 0 ?x))
-         input)
-
-    ;; Create the menu string for the keymap
-    (mapc (lambda (descriptor)
-            (when (elt descriptor 3)
-              (setf menu-string (concat menu-string
-                                       "[" (elt descriptor 0) "]"
-                                       (elt descriptor 1) " "))))
-          descriptors)
-    (setf (elt menu-string (- (length menu-string) 1)) ?:)
-
-    ;; Prompt the user, and grab the link
-    (message menu-string)
-    (setq input (read-char-exclusive))
-    (mapc (lambda (descriptor)
-            (let ((key (elt (elt descriptor 0) 0))
-                  (active (elt descriptor 3))
-                  (grab-function (elt descriptor 2)))
-              (when (and active (eq input key))
-                (call-interactively grab-function))))
-          descriptors)))
-
-(defun org-mac-paste-applescript-links (as-link-list)
-  "Paste in a list of links from an applescript handler.
-The links are of the form <link>::split::<name>."
-  (let* ((noquote-as-link-list 
-         (if (string-prefix-p "\"" as-link-list) 
-             (substring as-link-list 1 -1) 
-           as-link-list))
-        (link-list
-          (mapcar (lambda (x) (if (string-match "\\`\"\\(.*\\)\"\\'" x)
-                                 (setq x (match-string 1 x)))
-                   x)
-                 (split-string noquote-as-link-list "[\r\n]+")))
-         split-link URL description orglink orglink-insert rtn orglink-list)
-    (while link-list
-      (setq split-link (split-string (pop link-list) "::split::"))
-      (setq URL (car split-link))
-      (setq description (cadr split-link))
-      (when (not (string= URL ""))
-        (setq orglink (org-make-link-string URL description))
-        (push orglink orglink-list)))
-    (setq rtn (mapconcat 'identity orglink-list "\n"))
-    (kill-new rtn)
-    rtn))
-
-
-;; Handle links from Firefox.app
-;;
-;; This code allows you to grab the current active url from the main
-;; Firefox.app window, and insert it as a link into an org-mode
-;; document. Unfortunately, firefox does not expose an applescript
-;; dictionary, so this is necessarily introduces some limitations.
-;;
-;; The applescript to grab the url from Firefox.app uses the System
-;; Events application to give focus to the firefox application, select
-;; the contents of the url bar, and copy it. It then uses the title of
-;; the window as the text of the link. There is no way to grab links
-;; from other open tabs, and further, if there is more than one window
-;; open, it is not clear which one will be used (though emperically it
-;; seems that it is always the last active window).
-
-(defun org-as-mac-firefox-get-frontmost-url ()
-  (let ((result
-        (do-applescript
-         (concat
-          "set oldClipboard to the clipboard\n"
-          "set frontmostApplication to path to frontmost application\n"
-          "tell application \"Firefox\"\n"
-          "    activate\n"
-          "    delay 0.15\n"
-          "    tell application \"System Events\"\n"
-          "            keystroke \"l\" using {command down}\n"
-          "            keystroke \"a\" using {command down}\n"
-          "            keystroke \"c\" using {command down}\n"
-          "    end tell\n"
-          "    delay 0.15\n"
-          "    set theUrl to the clipboard\n"
-          "    set the clipboard to oldClipboard\n"
-          "    set theResult to (get theUrl) & \"::split::\" & (get name of 
window 1)\n"
-          "end tell\n"
-          "activate application (frontmostApplication as text)\n"
-          "set links to {}\n"
-          "copy theResult to the end of links\n"
-          "return links as string\n"))))
-    (car (split-string result "[\r\n]+" t))))
-
-;;;###autoload
-(defun org-mac-firefox-get-frontmost-url ()
-  (interactive)
-  (message "Applescript: Getting Firefox url...")
-  (org-mac-paste-applescript-links (org-as-mac-firefox-get-frontmost-url)))
-
-;;;###autoload
-(defun org-mac-firefox-insert-frontmost-url ()
-  (interactive)
-  (insert (org-mac-firefox-get-frontmost-url)))
-
-
-;; Handle links from Google Firefox.app running the Vimperator extension
-;; Grab the frontmost url from Firefox+Vimperator. Same limitations are
-;; Firefox
-
-(defun org-as-mac-vimperator-get-frontmost-url ()
-  (let ((result
-        (do-applescript
-         (concat
-          "set oldClipboard to the clipboard\n"
-          "set frontmostApplication to path to frontmost application\n"
-          "tell application \"Firefox\"\n"
-          "    activate\n"
-          "    delay 0.15\n"
-          "    tell application \"System Events\"\n"
-          "            keystroke \"y\"\n"
-          "    end tell\n"
-          "    delay 0.15\n"
-          "    set theUrl to the clipboard\n"
-          "    set the clipboard to oldClipboard\n"
-          "    set theResult to (get theUrl) & \"::split::\" & (get name of 
window 1)\n"
-          "end tell\n"
-          "activate application (frontmostApplication as text)\n"
-          "set links to {}\n"
-          "copy theResult to the end of links\n"
-          "return links as string\n"))))
-    (replace-regexp-in-string
-     "\s+-\s+Vimperator" "" (car (split-string result "[\r\n]+" t)))))
-
-;;;###autoload
-(defun org-mac-vimperator-get-frontmost-url ()
-  (interactive)
-  (message "Applescript: Getting Vimperator url...")
-  (org-mac-paste-applescript-links (org-as-mac-vimperator-get-frontmost-url)))
-
-;;;###autoload
-(defun org-mac-vimperator-insert-frontmost-url ()
-  (interactive)
-  (insert (org-mac-vimperator-get-frontmost-url)))
-
-
-;; Handle links from Google Chrome.app
-;; Grab the frontmost url from Google Chrome. Same limitations as
-;; Firefox because Chrome doesn't publish an Applescript dictionary
-
-(defun org-as-mac-chrome-get-frontmost-url ()
-  (let ((result
-        (do-applescript
-         (concat
-          "set frontmostApplication to path to frontmost application\n"
-          "tell application \"Google Chrome\"\n"
-          "    set theUrl to get URL of active tab of first window\n"
-          "    set theResult to (get theUrl) & \"::split::\" & (get name of 
window 1)\n"
-          "end tell\n"
-          "activate application (frontmostApplication as text)\n"
-          "set links to {}\n"
-          "copy theResult to the end of links\n"
-          "return links as string\n"))))
-    (replace-regexp-in-string
-     "^\"\\|\"$" "" (car (split-string result "[\r\n]+" t)))))
-
-;;;###autoload
-(defun org-mac-chrome-get-frontmost-url ()
-  (interactive)
-  (message "Applescript: Getting Chrome url...")
-  (org-mac-paste-applescript-links (org-as-mac-chrome-get-frontmost-url)))
-
-;;;###autoload
-(defun org-mac-chrome-insert-frontmost-url ()
-  (interactive)
-  (insert (org-mac-chrome-get-frontmost-url)))
-
-
-;; Handle links from Brave.app
-;; Grab the frontmost url from Brave. Same limitations as
-;; Firefox/Chrome because Brave doesn't publish an Applescript
-;; dictionary
-
-(defun org-as-mac-brave-get-frontmost-url ()
-  (let ((result
-        (do-applescript
-         (concat
-          "set frontmostApplication to path to frontmost application\n"
-          "tell application \"Brave\"\n"
-          "    set theUrl to get URL of active tab of first window\n"
-          "    set theResult to (get theUrl) & \"::split::\" & (get name of 
window 1)\n"
-          "end tell\n"
-          "activate application (frontmostApplication as text)\n"
-          "set links to {}\n"
-          "copy theResult to the end of links\n"
-          "return links as string\n"))))
-    (replace-regexp-in-string
-     "^\"\\|\"$" "" (car (split-string result "[\r\n]+" t)))))
-
-;;;###autoload
-(defun org-mac-brave-get-frontmost-url ()
-  (interactive)
-  (message "Applescript: Getting Brave url...")
-  (org-mac-paste-applescript-links (org-as-mac-brave-get-frontmost-url)))
-
-;;;###autoload
-(defun org-mac-brave-insert-frontmost-url ()
-  (interactive)
-  (insert (org-mac-brave-get-frontmost-url)))
-
-
-;; Handle links from Safari.app
-;; Grab the frontmost url from Safari.
-
-(defun org-as-mac-safari-get-frontmost-url ()
-  (do-applescript
-   (concat
-    "tell application \"Safari\"\n"
-    "  set theUrl to URL of document 1\n"
-    "  set theName to the name of the document 1\n"
-    "  return theUrl & \"::split::\" & theName & \"\n\"\n"
-    "end tell\n")))
-
-;;;###autoload
-(defun org-mac-safari-get-frontmost-url ()
-  (interactive)
-  (message "Applescript: Getting Safari url...")
-  (org-mac-paste-applescript-links 
-   (org-as-mac-safari-get-frontmost-url)))
-
-;;;###autoload
-(defun org-mac-safari-insert-frontmost-url ()
-  (interactive)
-  (insert (org-mac-safari-get-frontmost-url)))
-
-
-;; Handle links from together.app
-(org-link-set-parameters "x-together-item" :follow 
#'org-mac-together-item-open)
-
-(defun org-mac-together-item-open (uid _)
-  "Open UID, which is a reference to an item in Together."
-  (shell-command (concat "open -a Together \"x-together-item:" uid "\"")))
-
-(defun as-get-selected-together-items ()
-  (do-applescript
-   (concat
-    "tell application \"Together\"\n"
-    "  set theLinkList to {}\n"
-    "  set theSelection to selected items\n"
-    "  repeat with theItem in theSelection\n"
-    "          set theLink to (get item link of theItem) & \"::split::\" & 
(get name of theItem) & \"\n\"\n"
-    "          copy theLink to end of theLinkList\n"
-    "  end repeat\n"
-    "  return theLinkList as string\n"
-    "end tell")))
-
-;;;###autoload
-(defun org-mac-together-get-selected ()
-  (interactive)
-  (message "Applescript: Getting Together items...")
-  (org-mac-paste-applescript-links (as-get-selected-together-items)))
-
-;;;###autoload
-(defun org-mac-together-insert-selected ()
-  (interactive)
-  (insert (org-mac-together-get-selected)))
-
-
-;; Handle links from Finder.app
-
-(defun as-get-selected-finder-items ()
-  (do-applescript
-   (concat
-    "tell application \"Finder\"\n"
-    " set theSelection to the selection\n"
-    " set links to {}\n"
-    " repeat with theItem in theSelection\n"
-    " set theLink to \"file://\" & (POSIX path of (theItem as string)) & 
\"::split::\" & (get the name of theItem) & \"\n\"\n"
-    " copy theLink to the end of links\n"
-    " end repeat\n"
-    " return links as string\n"
-    "end tell\n")))
-
-;;;###autoload
-(defun org-mac-finder-item-get-selected ()
-  (interactive)
-  (message "Applescript: Getting Finder items...")
-  (org-mac-paste-applescript-links (as-get-selected-finder-items)))
-
-;;;###autoload
-(defun org-mac-finder-insert-selected ()
-  (interactive)
-  (insert (org-mac-finder-item-get-selected)))
-
-
-;; Handle links from AddressBook.app
-(org-link-set-parameters "addressbook" :follow #'org-mac-addressbook-item-open)
-
-(defun org-mac-addressbook-item-open (uid _)
-  "Open UID, which is a reference to an item in the addressbook."
-  (shell-command (concat "open \"addressbook:" uid "\"")))
-
-(defun as-get-selected-addressbook-items ()
-  (do-applescript
-   (concat
-    "tell application \"Address Book\"\n"
-    "  set theSelection to the selection\n"
-    "  set links to {}\n"
-    "  repeat with theItem in theSelection\n"
-    "          set theLink to \"addressbook://\" & (the id of theItem) & 
\"::split::\" & (the name of theItem) & \"\n\"\n"
-    "          copy theLink to the end of links\n"
-    "  end repeat\n"
-    "  return links as string\n"
-    "end tell\n")))
-
-;;;###autoload
-(defun org-mac-addressbook-item-get-selected ()
-  (interactive)
-  (message "Applescript: Getting Address Book items...")
-  (org-mac-paste-applescript-links (as-get-selected-addressbook-items)))
-
-;;;###autoload
-(defun org-mac-addressbook-insert-selected ()
-  (interactive)
-  (insert (org-mac-addressbook-item-get-selected)))
-
-
-;; Handle links from Skim.app
-;;
-;; Original code & idea by Christopher Suckling (org-mac-protocol)
-
-(org-link-set-parameters "skim" :follow #'org-mac-skim-open)
-
-(defun org-mac-skim-open (uri _)
-  "Visit page of pdf in Skim"
-  (let* ((page (when (string-match "::\\(.+\\)\\'" uri)
-                 (match-string 1 uri)))
-         (document (substring uri 0 (match-beginning 0))))
-    (do-applescript
-     (concat
-      "tell application \"Skim\"\n"
-      "activate\n"
-      "set theDoc to \"" document "\"\n"
-      "set thePage to " page "\n"
-      "open theDoc\n"
-      "go document 1 to page thePage of document 1\n"
-      "end tell"))))
-
-(defun as-get-skim-page-link ()
-  (do-applescript
-   (concat
-    "tell application \"Skim\"\n"
-    "set theDoc to front document\n"
-    "set theTitle to (name of theDoc)\n"
-    "set thePath to (path of theDoc)\n"
-    "set thePage to (get index for current page of theDoc)\n"
-    "set theSelection to selection of theDoc\n"
-    "set theContent to contents of (get text for theSelection)\n"
-    "if theContent is missing value then\n"
-    "    set theContent to theTitle & \", p. \" & thePage\n"
-    (when org-mac-Skim-highlight-selection-p
-      (concat
-       "else\n"
-       "    tell theDoc\n"
-       "        set theNote to make note with properties {type:highlight note, 
selection:theSelection}\n"
-       "         set text of theNote to (get text for theSelection)\n"
-       "    end tell\n"))
-    "end if\n"
-    "set theLink to \"skim://\" & thePath & \"::\" & thePage & "
-    "\"::split::\" & theContent\n"
-    "end tell\n"
-    "return theLink as string\n")))
-
-;;;###autoload
-(defun org-mac-skim-get-page ()
-  (interactive)
-  (message "Applescript: Getting Skim page link...")
-  (org-mac-paste-applescript-links (as-get-skim-page-link)))
-
-;;;###autoload
-(defun org-mac-skim-insert-page ()
-  (interactive)
-  (insert (org-mac-skim-get-page)))
-
-;; Handle links from Adobe Acrobat Pro.app
-;;
-;; Original code & idea by Christopher Suckling (org-mac-protocol)
-;;
-;; The URI format is path_to_pdf_file::page_number
-
-(org-link-set-parameters "acrobat" :follow #'org-mac-acrobat-open)
-
-(defun org-mac-acrobat-open (uri _)
-  "Visit page of pdf in Acrobat"
-  (let* ((page (when (string-match "::\\(.+\\)\\'" uri)
-                 (match-string 1 uri)))
-         (document (substring uri 0 (match-beginning 0))))
-    (do-applescript
-     (concat
-      "tell application \"Adobe Acrobat Pro\"\n"
-      "  activate\n"
-      "  set theDoc to \"" document "\"\n"
-      "  set thePage to " page "\n"
-      "  open theDoc\n"
-      "  tell PDF Window 1\n"
-      "    goto page thePage\n"
-      "  end tell\n"
-      "end tell"))))
-
-;; The applescript returns link in the format
-;; "adobe:path_to_pdf_file::page_number::split::document_title, p.page_label"
-
-(defun org-mac-as-get-acrobat-page-link ()
-  (do-applescript
-   (concat
-    "tell application \"Adobe Acrobat Pro\"\n"
-    "  set theDoc to active doc\n"
-    "  set theWindow to (PDF Window 1 of theDoc)\n"
-    "  set thePath to (file alias of theDoc)\n"
-    "  set theTitle to (name of theWindow)\n"
-    "  set thePage to (page number of theWindow)\n"
-    "  set theLabel to (label text of (page thePage of theWindow))\n"
-    "end tell\n"
-    "set theResult to \"acrobat:\" & thePath & \"::\" & thePage & 
\"::split::\" & theTitle & \", p.\" & theLabel\n"
-    "return theResult as string\n")))
-
-;;;###autoload
-(defun org-mac-acrobat-get-page ()
-  (interactive)
-  (message "Applescript: Getting Acrobat page link...")
-  (org-mac-paste-applescript-links (org-mac-as-get-acrobat-page-link)))
-
-;;;###autoload
-(defun org-mac-acrobat-insert-page ()
-  (interactive)
-  (insert (org-mac-acrobat-get-page)))
-
-
-;; Handle links from Microsoft Outlook.app
-
-(org-link-set-parameters "mac-outlook" :follow #'org-mac-outlook-message-open)
-
-(defun org-mac-outlook-message-open (msgid _)
-  "Open a message in Outlook"
-  (do-applescript
-   (concat
-    "tell application \"" org-mac-outlook-path "\"\n"
-    (format "open message id %s\n" (substring-no-properties msgid))
-    "activate\n"
-    "end tell")))
-
-(defun org-as-get-selected-outlook-mail ()
-  "AppleScript to create links to selected messages in Microsoft Outlook.app."
-  (do-applescript
-   (concat
-    "tell application \"" org-mac-outlook-path "\"\n"
-    "set msgCount to count current messages\n"
-    "if (msgCount < 1) then\n"
-    "return\n"
-    "end if\n"
-    "set theLinkList to {}\n"
-    "set theSelection to (get current messages)\n"
-    "repeat with theMessage in theSelection\n"
-    "set theID to id of theMessage as string\n"
-    "set theURL to \"mac-outlook:\" & theID\n"
-    "set theSubject to subject of theMessage\n"
-    "set theLink to theURL & \"::split::\" & theSubject & \"\n\"\n"
-    "copy theLink to end of theLinkList\n"
-    "end repeat\n"
-    "return theLinkList as string\n"
-    "end tell")))
-
-(defun org-sh-get-flagged-outlook-mail ()
-  "Shell commands to create links to flagged messages in Microsoft 
Outlook.app."
-  (mapconcat
-   (lambda (x) ""
-     (concat
-      "mac-outlook:"
-      (mapconcat
-       (lambda (y) "" y)
-       (split-string
-       (shell-command-to-string
-        (format "mdls -raw -name com_microsoft_outlook_recordID -name 
kMDItemDisplayName \"%s\"" x))
-       "\000")
-       "::split::")
-      "\n"))
-   (with-temp-buffer
-     (let ((coding-system-for-read (or file-name-coding-system 'utf-8))
-          (coding-system-for-write 'utf-8))
-       (shell-command
-       "mdfind com_microsoft_outlook_flagged==1"
-       (current-buffer)))
-     (split-string
-      (buffer-string) "\n" t))
-   ""))
-
-;;;###autoload
-(defun org-mac-outlook-message-get-links (&optional select-or-flag)
-  "Create links to the messages currently selected or flagged in Microsoft 
Outlook.app.
-This will use AppleScript to get the message-id and the subject of the
-messages in Microsoft Outlook.app and make a link out of it.
-When SELECT-OR-FLAG is \"s\", get the selected messages (this is also
-the default).  When SELECT-OR-FLAG is \"f\", get the flagged messages.
-The Org-syntax text will be pushed to the kill ring, and also returned."
-  (interactive "sLink to (s)elected or (f)lagged messages: ")
-  (setq select-or-flag (or select-or-flag "s"))
-  (message "Org Mac Outlook: searching mailboxes...")
-  (org-mac-paste-applescript-links
-   (if (string= select-or-flag "s")
-       (org-as-get-selected-outlook-mail)
-      (if (string= select-or-flag "f")
-         (org-sh-get-flagged-outlook-mail)
-       (error "Please select \"s\" or \"f\"")))))
-
-;;;###autoload
-(defun org-mac-outlook-message-insert-selected ()
-  "Insert a link to the messages currently selected in Microsoft Outlook.app.
-This will use AppleScript to get the message-id and the subject
-of the active mail in Microsoft Outlook.app and make a link out
-of it."
-  (interactive)
-  (insert (org-mac-outlook-message-get-links "s")))
-
-;;;###autoload
-(defun org-mac-outlook-message-insert-flagged (org-buffer org-heading)
-  "Asks for an org buffer and a heading within it, and replace message links.
-If heading exists, delete all mac-outlook:// links within
-heading's first level.  If heading doesn't exist, create it at
-point-max.  Insert list of mac-outlook:// links to flagged mail
-after heading."
-  (interactive "bBuffer in which to insert links: \nsHeading after which to 
insert links: ")
-  (with-current-buffer org-buffer
-    (goto-char (point-min))
-    (let ((isearch-forward t)
-          (message-re 
"\\[\\[\\(mac-outlook:\\)\\([^]]+\\)\\]\\(\\[\\([^]]+\\)\\]\\)?\\]"))
-      (if (org-goto-local-search-headings org-heading nil t)
-          (if (not (eobp))
-              (progn
-                (save-excursion
-                  (while (re-search-forward
-                          message-re (save-excursion (outline-next-heading)) t)
-                    (delete-region (match-beginning 0) (match-end 0)))
-                  (insert "\n" (org-mac-outlook-message-get-links "f")))
-                (flush-lines "^$" (point) (outline-next-heading)))
-           (insert "\n" (org-mac-outlook-message-get-links "f")))
-       (goto-char (point-max))
-       (insert "\n")
-       (org-insert-heading nil t)
-       (insert org-heading "\n" (org-mac-outlook-message-get-links "f"))))))
-
-;; Handle links from Evernote.app
-
-(org-link-set-parameters "mac-evernote" :follow #'org-mac-evernote-note-open)
-
-(defun org-mac-evernote-note-open (noteid _)
-  "Open a note in Evernote"
-  (do-applescript
-   (concat
-    "tell application \"" org-mac-evernote-path "\"\n"
-    "    set theNotes to get every note of every notebook where its local id 
is \"" (substring-no-properties noteid) "\"\n"
-    "    repeat with _note in theNotes\n"
-    "        if length of _note is not 0 then\n"
-    "            set _selectedNote to _note\n"
-    "        end if\n"
-    "    end repeat\n"
-    "    open note window with item 1 of _selectedNote\n"
-    "    activate\n"
-    "end tell")))
-
-(defun org-as-get-selected-evernote-notes ()
-  "AppleScript to create links to selected notes in Evernote.app."
-  (do-applescript
-   (concat
-    "tell application \"" org-mac-evernote-path "\"\n"
-     "    set noteCount to count selection\n"
-     "    if (noteCount < 1) then\n"
-     "        return\n"
-     "    end if\n"
-     "    set theLinkList to {}\n"
-     "    set theSelection to selection\n"
-     "    repeat with theNote in theSelection\n"
-     "        set theTitle to title of theNote\n"
-     "        set theID to local id of theNote\n"
-     "        set theURL to \"mac-evernote:\" & theID\n"
-     "        set theLink to theURL & \"::split::\" & theTitle & \"\n\"\n"
-     "        copy theLink to end of theLinkList\n"
-     "    end repeat\n"
-     "    return theLinkList as string\n"
-     "end tell\n")))
-
-;;;###autoload
-(defun org-mac-evernote-note-insert-selected ()
-  "Insert a link to the notes currently selected in Evernote.app.
-This will use AppleScript to get the note id and the title of the
-note(s) in Evernote.app and make a link out of it/them."
-  (interactive)
-  (message "Org Mac Evernote: searching notes...")
-(insert (org-mac-paste-applescript-links
-        (org-as-get-selected-evernote-notes))))
-
-
-;; Handle links from DEVONthink Pro Office.app
-
-(org-link-set-parameters "x-devonthink-item" :follow 
#'org-devonthink-item-open)
-
-(defun org-devonthink-item-open (uid _)
-  "Open UID, which is a reference to an item in DEVONthink Pro Office."
-  (shell-command (concat "open \"x-devonthink-item:" uid "\"")))
-
-(defun org-as-get-selected-devonthink-item ()
-  "AppleScript to create links to selected items in DEVONthink Pro Office.app."
-  (do-applescript
-   (concat
-    "set theLinkList to {}\n"
-    "tell application \"DEVONthink Pro\"\n"
-    "set selectedRecords to selection\n"
-    "set selectionCount to count of selectedRecords\n"
-    "if (selectionCount < 1) then\n"
-    "return\n"
-    "end if\n"
-    "repeat with theRecord in selectedRecords\n"
-    "set theID to uuid of theRecord\n"
-    "set theURL to \"x-devonthink-item:\" & theID\n"
-    "set theSubject to name of theRecord\n"
-    "set theLink to theURL & \"::split::\" & theSubject & \"\n\"\n"
-    "copy theLink to end of theLinkList\n"
-    "end repeat\n"
-    "end tell\n"
-    "return theLinkList as string"
-    )))
-
-(defun org-mac-devonthink-get-links ()
-  "Create links to the item(s) currently selected in DEVONthink Pro Office.
-This will use AppleScript to get the `uuid' and the `name' of the
-selected items in DEVONthink Pro Office.app and make links out of
-it/them. This function will push the Org-syntax text to the kill
-ring, and also return it."
-  (message "Org Mac DEVONthink: looking for selected items...")
-  (org-mac-paste-applescript-links (org-as-get-selected-devonthink-item)))
-
-;;;###autoload
-(defun org-mac-devonthink-item-insert-selected ()
-  "Insert a link to the item(s) currently selected in DEVONthink Pro Office.
-This will use AppleScript to get the `uuid'(s) and the name(s) of the
-selected items in DEVONthink Pro Office and make link(s) out of it/them."
-  (interactive)
-  (insert (org-mac-devonthink-get-links)))
-
-
-;; Handle links from Mail.app
-
-(org-link-set-parameters "message" :follow #'org-mac-message-open)
-
-(defun org-mac-message-open (message-id _)
-  "Visit the message with MESSAGE-ID.
-This will use the command `open' with the message URL."
-  (start-process (concat "open message:" message-id) nil
-                 "open" (concat "message://%3C" (substring message-id 2) 
"%3E")))
-
-(defun org-as-get-selected-mail ()
-  "AppleScript to create links to selected messages in Mail.app."
-  (do-applescript
-   (concat
-    "tell application \"Mail\"\n"
-    "set theLinkList to {}\n"
-    "set theSelection to selection\n"
-    "repeat with theMessage in theSelection\n"
-    "set theID to message id of theMessage\n"
-    "set theSubject to subject of theMessage\n"
-    "set theLink to \"message://\" & theID & \"::split::\" & theSubject\n"
-    "if (theLinkList is not equal to {}) then\n"
-    "set theLink to \"\n\" & theLink\n"
-    "end if\n"
-    "copy theLink to end of theLinkList\n"
-    "end repeat\n"
-    "return theLinkList as string\n"
-    "end tell")))
-
-(defun org-as-get-flagged-mail ()
-  "AppleScript to create links to flagged messages in Mail.app."
-  (unless org-mac-mail-account
-    (error "You must set org-mac-mail-account"))
-  (do-applescript
-   (concat
-    ;; Get links
-    "tell application \"Mail\"\n"
-    "set theMailboxes to every mailbox of account \"" org-mac-mail-account 
"\"\n"
-    "set theLinkList to {}\n"
-    "repeat with aMailbox in theMailboxes\n"
-    "set theSelection to (every message in aMailbox whose flagged status = 
true)\n"
-    "repeat with theMessage in theSelection\n"
-    "set theID to message id of theMessage\n"
-    "set theSubject to subject of theMessage\n"
-    "set theLink to \"message://\" & theID & \"::split::\" & theSubject & 
\"\n\"\n"
-    "copy theLink to end of theLinkList\n"
-    "end repeat\n"
-    "end repeat\n"
-    "return theLinkList as string\n"
-    "end tell")))
-
-;;;###autoload
-(defun org-mac-message-get-links (&optional select-or-flag)
-  "Create links to the messages currently selected or flagged in Mail.app.
-This will use AppleScript to get the message-id and the subject of the
-messages in Mail.app and make a link out of it.
-When SELECT-OR-FLAG is \"s\", get the selected messages (this is also
-the default).  When SELECT-OR-FLAG is \"f\", get the flagged messages.
-The Org-syntax text will be pushed to the kill ring, and also returned."
-  (interactive "sLink to (s)elected or (f)lagged messages: ")
-  (setq select-or-flag (or select-or-flag "s"))
-  (message "AppleScript: searching mailboxes...")
-  (org-mac-paste-applescript-links
-   (cond
-    ((string= select-or-flag "s") (org-as-get-selected-mail))
-    ((string= select-or-flag "f") (org-as-get-flagged-mail))
-    (t (error "Please select \"s\" or \"f\"")))))
-
-;;;###autoload
-(defun org-mac-message-insert-selected ()
-  "Insert a link to the messages currently selected in Mail.app.
-This will use AppleScript to get the message-id and the subject of the
-active mail in Mail.app and make a link out of it."
-  (interactive)
-  (insert (org-mac-message-get-links "s")))
-
-;; The following line is for backward compatibility
-(defalias 'org-mac-message-insert-link 'org-mac-message-insert-selected)
-
-;;;###autoload
-(defun org-mac-message-insert-flagged (org-buffer org-heading)
-  "Asks for an org buffer and a heading within it, and replace message links.
-If heading exists, delete all message:// links within heading's first
-level.  If heading doesn't exist, create it at point-max.  Insert
-list of message:// links to flagged mail after heading."
-  (interactive "bBuffer in which to insert links: \nsHeading after which to 
insert links: ")
-  (with-current-buffer org-buffer
-    (goto-char (point-min))
-    (let ((isearch-forward t)
-          (message-re 
"\\[\\[\\(message:\\)\\([^]]+\\)\\]\\(\\[\\([^]]+\\)\\]\\)?\\]"))
-      (if (org-goto-local-search-headings org-heading nil t)
-          (if (not (eobp))
-              (progn
-                (save-excursion
-                  (while (re-search-forward
-                          message-re (save-excursion (outline-next-heading)) t)
-                    (delete-region (match-beginning 0) (match-end 0)))
-                  (insert "\n" (org-mac-message-get-links "f")))
-                (flush-lines "^$" (point) (outline-next-heading)))
-           (insert "\n" (org-mac-message-get-links "f")))
-       (goto-char (point-max))
-       (insert "\n")
-       (org-insert-heading nil t)
-       (insert org-heading "\n" (org-mac-message-get-links "f"))))))
-
-
-(provide 'org-mac-link)
-
-;;; org-mac-link.el ends here
diff --git a/contrib/lisp/org-mairix.el b/contrib/lisp/org-mairix.el
deleted file mode 100644
index 1037328..0000000
--- a/contrib/lisp/org-mairix.el
+++ /dev/null
@@ -1,333 +0,0 @@
-;;; org-mairix.el - Support for hooking mairix search into Org for different 
MUAs
-;;
-;; Copyright (C) 2007-2014 Georg C. F. Greve
-;; mutt support by Adam Spiers <orgmode at adamspiers dot org>
-;;
-;; This file is not part of GNU Emacs.
-;;
-;; Author: Georg C. F. Greve <greve at fsfeurope dot org>
-;; Keywords: outlines, hypermedia, calendar, wp, email, mairix
-;; Purpose: Integrate mairix email searching into Org mode
-;; See https://orgmode.org and http://www.rpcurnow.force9.co.uk/mairix/
-;; Version: 0.5
-;;
-;; This file 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.
-
-;; It 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/>.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; USAGE NOTE
-;;
-;; You will need to configure mairix first, which involves setting up your
-;; .mairixrc in your home directory. Once it is working, you should set up
-;; your way to display results in your favorite way -- usually a MUA.
-;; Currently gnus and mutt are supported.
-;;
-;; After both steps are done, all you should need to hook mairix, org
-;; and your MUA together is to do (require 'org-mairix) in your
-;; startup file. Everything can then be configured normally through
-;; Emacs customisation.
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(require 'org)
-
-;;; The custom variables
-
-(defgroup org-mairix nil
-  "Mairix support/integration in org."
-  :tag "Org Mairix"
-  :group 'org)
-
-(defcustom org-mairix-threaded-links t
-  "Should new links be created as threaded links?
-If t, links will be stored as threaded searches.
-If nil, links will be stored as non-threaded searches."
-  :group 'org-mairix
-  :type 'boolean)
-
-(defcustom org-mairix-augmented-links nil
-  "Should new links be created as augmenting searches?
-If t, links will be stored as augmenting searches.
-If nil, links will be stored as normal searches.
-
-Attention: When activating this option, you will need
-to remove old articles from your mairix results group
-in some other way, mairix will not do it for you."
-  :group 'org-mairix
-  :type 'boolean)
-
-(defcustom org-mairix-display-hook 'org-mairix-gnus-display-results
-  "Hook to call to display the results of a successful mairix search.
-Defaults to Gnus, feel free to add your own MUAs or methods."
-  :group 'org-mairix
-  :type 'hook)
-
-(defcustom org-mairix-open-command "mairix %args% '%search%'"
-  "The mairix command-line to use. If your paths are set up
-correctly, you should not need to change this.
-
-'%search%' will get substituted with the search expression, and
-'%args%' with any additional arguments."
-  :group 'org-mairix
-  :type 'string)
-
-;;; The hooks to integrate mairix into org
-
-(org-link-set-parameters "mairix"
-                        :follow #'org-mairix-open
-                        :store #'org-mairix-store-gnus-link)
-
-;;; Generic org-mairix functions
-
-(defun org-mairix-construct-link (message-id)
-  "Construct a mairix: hyperlink based on message-id."
-  (concat "mairix:"
-          (if org-mairix-threaded-links "t:")
-          (if org-mairix-augmented-links "a:")
-          "@@"
-          (org-unbracket-string "<" ">" message-id)))
-
-(defun org-store-mairix-link-props (&rest plist)
-  "Take a property list describing a mail, and add mairix link
-and description properties so that org can build a mairix link to
-it."
-  ;; We have to call `org-store-link-props' twice:
-  ;;
-  ;;   - It extracts 'fromname'/'fromaddress' from 'from' property,
-  ;;     and stores the updated plist to `org-store-link-plist'.
-  ;;
-  ;;   - `org-email-link-description' uses these new properties to
-  ;;     build a description from the previously stored plist.  I
-  ;;     wrote a tiny patch to `org-email-link-description' so it
-  ;;     could take a non-stored plist as an optional 2nd argument,
-  ;;     but the plist provided still needs 'fromname'/'fromaddress'.
-  ;;
-  ;;   - Ideally we would decouple the storing bit of
-  ;;     `org-store-link-props' from the extraction bit, but lots of
-  ;;     stuff in `org-store-link' which calls it would need to be
-  ;;     changed.  Maybe just factor out the extraction so it can be
-  ;;     reused separately?
-  (let ((mid (plist-get plist :message-id)))
-    (apply 'org-store-link-props
-           (append plist
-                   (list :type "mairix"
-                         :link (org-mairix-construct-link mid))))
-    (apply 'org-store-link-props
-           (append org-store-link-plist
-                   (list :description (org-email-link-description))))))
-
-(defun org-mairix-message-send-and-exit-with-link ()
-  "Function that can be assigned as an alternative sending function,
-it sends the message and then stores a mairix link to it before burying
-the buffer just like 'message-send-and-exit' does."
-  (interactive)
-  (message-send)
-  (let* ((message-id (message-fetch-field "Message-Id"))
-         (subject (message-fetch-field "Subject"))
-         (link (org-mairix-construct-link message-id))
-         (desc (concat "Email: '" subject "'")))
-    (setq org-stored-links
-          (cons (list link desc) org-stored-links)))
-  (message-bury (current-buffer)))
-
-(defun org-mairix-open (search _)
-  "Function to open mairix link.
-
-We first need to split it into its individual parts, and then
-extract the message-id to be passed on to the display function
-before call mairix, evaluate the number of matches returned, and
-make sure to only call display of mairix succeeded in matching."
-  (let* ((args ""))
-    (if (equal (substring search 0 2) "t:" )
-        (progn (setq search (substring search 2 nil))
-               (setq args (concat args " --threads"))))
-    (if (equal (substring search 0 2) "a:")
-        (progn (setq search (substring search 2 nil))
-               (setq args (concat args " --augment"))))
-    (let ((cmdline (org-mairix-command-substitution
-                    org-mairix-open-command search args)))
-      (print cmdline)
-      (setq retval (shell-command-to-string cmdline))
-      (string-match "\[0-9\]+" retval)
-      (setq matches (string-to-number (match-string 0 retval)))
-      (if (eq matches 0) (message "Link failed: no matches, sorry")
-        (message "Link returned %d matches" matches)
-        (run-hook-with-args 'org-mairix-display-hook search args)))))
-
-(defun org-mairix-command-substitution (cmd search args)
-  "Substitute '%search%' and '%args% in mairix search command."
-  (while (string-match "%search%" cmd)
-    (setq cmd (replace-match search 'fixedcase 'literal cmd)))
-  (while (string-match "%args%" cmd)
-    (setq cmd (replace-match args 'fixedcase 'literal cmd)))
-  cmd)
-
-;;; Functions necessary for integration of external MUAs.
-
-;; Of course we cannot call `org-store-link' from within an external
-;; MUA, so we need some other way of storing a link for later
-;; retrieval by org-mode and/or remember-mode.  To do this we use a
-;; temporary file as a kind of dedicated clipboard.
-
-(defcustom org-mairix-link-clipboard "~/.org-mairix-link"
-  "Pseudo-clipboard file where mairix URLs get copied to by external
-applications in order to mimic `org-store-link'.  Used by
-`org-mairix-insert-link'."
-  :group 'org-mairix
-  :type 'string)
-
-;; When we resolve some of the issues with `org-store-link' detailed
-;; at 
<https://orgmode.org/list/20071105181739.GB13544@atlantic.linksys.moosehall
-;; we might not need org-mairix-insert-link.
-
-(defun org-mairix-insert-link ()
-  "Insert link from file defined by `org-mairix-link-clipboard'."
-  (interactive)
-  (let ((bytes (cadr (insert-file-contents
-                      (expand-file-name org-mairix-link-clipboard)))))
-    (forward-char bytes)
-    (save-excursion
-      (forward-char -1)
-      (if (looking-at "\n")
-          (delete-char 1)))))
-
-;;; Functions necessary for mutt integration
-
-(defgroup org-mairix-mutt nil
-  "Use mutt for mairix support in org."
-  :tag "Org Mairix Mutt"
-  :group 'org-mairix)
-
-(defcustom org-mairix-mutt-display-command
-  "xterm -title 'mairix search: %search%' -e 'unset COLUMNS; mutt -f
-~/mail/mairix -e \"push <display-message>\"' &"
-  "Command to execute to display mairix search results via mutt within
-an xterm.
-
-'%search%' will get substituted with the search expression, and
-'%args%' with any additional arguments used in the search."
-  :group 'org-mairix-mutt
-  :type 'string)
-
-(defun org-mairix-mutt-display-results (search args)
-  "Display results of mairix search in mutt, using the command line
-defined in `org-mairix-mutt-display-command'."
-  ;; By default, async `shell-command' invocations display the temp
-  ;; buffer, which is annoying here.  We choose a deterministic
-  ;; buffer name so we can hide it again immediately.
-  ;; Note: `call-process' is synchronous so not useful here.
-  (let ((cmd (org-mairix-command-substitution
-              org-mairix-mutt-display-command search args))
-        (tmpbufname (generate-new-buffer-name " *mairix-view*")))
-    (shell-command cmd tmpbufname)
-    (delete-windows-on (get-buffer tmpbufname))))
-
-;;; Functions necessary for gnus integration
-
-(defgroup org-mairix-gnus nil
-  "Use gnus for mairix support in org."
-  :tag "Org Mairix Gnus"
-  :group 'org-mairix)
-
-(defcustom org-mairix-gnus-results-group "nnmaildir:mairix"
-  "The group that is configured to hold the mairix search results,
-which needs to be setup independently of the org-mairix integration,
-along with general mairix configuration."
-  :group 'org-mairix-gnus
-  :type 'string)
-
-(defcustom org-mairix-gnus-select-display-group-function
-'org-mairix-gnus-select-display-group-function-gg
-  "Hook to call to select the group that contains the matching articles.
-We should not need this, it is owed to a problem of gnus that people were
-not yet able to figure out, see
- http://article.gmane.org/gmane.emacs.gnus.general/65248
- http://article.gmane.org/gmane.emacs.gnus.general/65265
- http://article.gmane.org/gmane.emacs.gnus.user/9596
-for reference.
-
-It seems gnus needs a 'forget/ignore everything you think you
-know about that group' function. Volunteers?"
-  :group 'org-mairix-gnus
-  :type 'hook)
-
-(defun org-mairix-store-gnus-link ()
-  "Store a link to the current gnus message as a Mairix search for its
-Message ID."
-
-  ;; gnus integration
-  (when (memq major-mode '(gnus-summary-mode gnus-article-mode))
-    (and (eq major-mode 'gnus-article-mode) (gnus-article-show-summary))
-    (let* ((article (gnus-summary-article-number))
-           (header (gnus-summary-article-header article))
-           (from (mail-header-from header))
-           (message-id (mail-header-id header))
-           (subject (gnus-summary-subject-string)))
-      (org-store-mairix-link-props :from from
-                                   :subject subject
-                                   :message-id message-id))))
-
-(defun org-mairix-gnus-display-results (search args)
-  "Display results of mairix search in Gnus.
-
-Note: This does not work as cleanly as I would like it to. The
-problem being that Gnus should simply reread the group cleanly,
-without remembering anything. At the moment it seems to be unable
-to do that -- so you're likely to see zombies floating around.
-
-If you can improve this, please do!"
-  (if (not (equal (substring search 0 2) "m:" ))
-      (error "org-mairix-gnus-display-results: display of search other than
-message-id not implemented yet"))
-  (setq message-id (substring search 2 nil))
-  (require 'gnus)
-  (require 'gnus-sum)
-  ;; FIXME: (bzg/gg) We might need to make sure gnus is running here,
-  ;;        and to start it in case it isn't running already. Does
-  ;;        anyone know a function to do that? It seems main org mode
-  ;;        does not do this, either.
-  (funcall (cdr (assq 'gnus org-link-frame-setup)))
-  (if gnus-other-frame-object (select-frame gnus-other-frame-object))
-
-  ;; FIXME: This is horribly broken. Please see
-  ;;  http://article.gmane.org/gmane.emacs.gnus.general/65248
-  ;;  http://article.gmane.org/gmane.emacs.gnus.general/65265
-  ;;  http://article.gmane.org/gmane.emacs.gnus.user/9596
-  ;; for reference.
-  ;;
-  ;; It seems gnus needs a "forget/ignore everything you think you
-  ;; know about that group" function. Volunteers?
-  ;;
-  ;; For now different methods seem to work differently well for
-  ;; different people. So we're playing hook-selection here to make
-  ;; it easy to play around until we found a proper solution.
-  (run-hook-with-args 'org-mairix-gnus-select-display-group-function)
-  (gnus-summary-select-article
-   nil t t (car (gnus-find-matching-articles "message-id" message-id))))
-
-(defun org-mairix-gnus-select-display-group-function-gg ()
-  "Georg's hack to select a group that gnus (falsely) believes to be
-empty to then call rebuilding of the summary. It leaves zombies of
-old searches around, though."
-  (gnus-group-quick-select-group 0 org-mairix-gnus-results-group)
-  (gnus-group-clear-data)
-  (gnus-summary-reselect-current-group t t))
-
-(defun org-mairix-gnus-select-display-group-function-bzg ()
-  "This is the classic way the org mode is using, and it seems to be
-using better for Bastien, so it may work for you."
-  (gnus-group-clear-data org-mairix-gnus-results-group)
-  (gnus-group-read-group t nil org-mairix-gnus-results-group))
-
-(provide 'org-mairix)
-
-;;; org-mairix.el ends here
diff --git a/contrib/lisp/org-notify.el b/contrib/lisp/org-notify.el
deleted file mode 100644
index 4796f3e..0000000
--- a/contrib/lisp/org-notify.el
+++ /dev/null
@@ -1,406 +0,0 @@
-;;; org-notify.el --- Notifications for Org-mode
-
-;; Copyright (C) 2012-2021  Free Software Foundation, Inc.
-
-;; Author: Peter Mรผnster <pmrb@free.fr>
-;; Keywords: notification, todo-list, alarm, reminder, pop-up
-
-;; This file is not 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 this program.  If not, see <http://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; Get notifications, when there is something to do.
-;; Sometimes, you need a reminder a few days before a deadline, e.g. to buy a
-;; present for a birthday, and then another notification one hour before to
-;; have enough time to choose the right clothes.
-;; For other events, e.g. rolling the dustbin to the roadside once per week,
-;; you probably need another kind of notification strategy.
-;; This package tries to satisfy the various needs.
-
-;; In order to activate this package, you must add the following code
-;; into your .emacs:
-;;
-;;   (require 'org-notify)
-;;   (org-notify-start)
-
-;; Example setup:
-;;
-;; (org-notify-add 'appt
-;;                 '(:time "-1s" :period "20s" :duration 10
-;;                   :actions (-message -ding))
-;;                 '(:time "15m" :period "2m" :duration 100
-;;                   :actions -notify)
-;;                 '(:time "2h" :period "5m" :actions -message)
-;;                 '(:time "3d" :actions -email))
-;;
-;; This means for todo-items with `notify' property set to `appt': 3 days
-;; before deadline, send a reminder-email, 2 hours before deadline, start to
-;; send messages every 5 minutes, then 15 minutes before deadline, start to
-;; pop up notification windows every 2 minutes.  The timeout of the window is
-;; set to 100 seconds.  Finally, when deadline is overdue, send messages and
-;; make noise."
-
-;; Take also a look at the function `org-notify-add'.
-
-;;; Code:
-
-(eval-when-compile (require 'cl-lib))
-(require 'org-element)
-
-(declare-function appt-delete-window    "appt"          ())
-(declare-function notifications-notify  "notifications" (&rest prms))
-(declare-function article-lapsed-string "gnus-art"      (t &optional ms))
-
-(defgroup org-notify nil
-  "Options for Org-mode notifications."
-  :tag "Org Notify"
-  :group 'org)
-
-(defcustom org-notify-audible t
-  "Non-nil means beep to indicate notification."
-  :type 'boolean
-  :group 'org-notify)
-
-(defcustom org-notify-max-notifications-per-run 3
-  "Maximum number of notifications per run of `org-notify-process'."
-  :type 'integer
-  :group 'org-notify)
-
-(defconst org-notify-actions
-  '("show" "show" "done" "done" "hour" "one hour later" "day" "one day later"
-    "week" "one week later")
-  "Possible actions for call-back functions.")
-
-(defconst org-notify-window-buffer-name "*org-notify-%s*"
-  "Buffer-name for the `org-notify-action-window' function.")
-
-(defvar org-notify-map nil
-  "Mapping between names and parameter lists.")
-
-(defvar org-notify-timer nil
-  "Timer of the notification daemon.")
-
-(defvar org-notify-parse-file nil
-  "Index of current file, that `org-element-parse-buffer' is parsing.")
-
-(defvar org-notify-on-action-map nil
-  "Mapping between on-action identifiers and parameter lists.")
-
-(defun org-notify-string->seconds (str)
-  "Convert time string STR to number of seconds."
-  (when str
-    (let* ((conv `(("s" . 1) ("m" . 60) ("h" . ,(* 60 60))
-                   ("d" . ,(* 24 60 60)) ("w" . ,(* 7 24 60 60))
-                   ("M" . ,(* 30 24 60 60))))
-           (letters (concat
-                     (mapcar (lambda (x) (string-to-char (car x))) conv)))
-           (case-fold-search nil))
-      (string-match (concat "\\(-?\\)\\([0-9]+\\)\\([" letters "]\\)") str)
-      (* (string-to-number (match-string 2 str))
-         (cdr (assoc (match-string 3 str) conv))
-         (if (= (length (match-string 1 str)) 1) -1 1)))))
-
-(defun org-notify-convert-deadline (orig)
-  "Convert original deadline from `org-element-parse-buffer' to
-simple timestamp string."
-  (if orig
-      (replace-regexp-in-string "^<\\|>$" ""
-                               (plist-get (plist-get orig 'timestamp)
-                                          :raw-value))))
-
-(defun org-notify-make-todo (heading &rest ignored)
-  "Create one todo item."
-  (cl-macrolet ((get (k) `(plist-get list ,k))
-             (pr (k v) `(setq result (plist-put result ,k ,v))))
-    (let* ((list (nth 1 heading))      (notify (or (get :NOTIFY) "default"))
-           (deadline (org-notify-convert-deadline (get :deadline)))
-          (heading (get :raw-value))
-           result)
-      (when (and (eq (get :todo-type) 'todo) heading deadline)
-        (pr :heading heading)     (pr :notify (intern notify))
-        (pr :begin (get :begin))
-        (pr :file (nth org-notify-parse-file (org-agenda-files 'unrestricted)))
-        (pr :timestamp deadline)  (pr :uid (md5 (concat heading deadline)))
-        (pr :deadline (- (org-time-string-to-seconds deadline)
-                         (float-time))))
-      result)))
-
-(defun org-notify-todo-list ()
-  "Create the todo-list for one org-agenda file."
-  (let* ((files (org-agenda-files 'unrestricted))
-         (max (1- (length files))))
-    (when files
-      (setq org-notify-parse-file
-           (if (or (not org-notify-parse-file) (>= org-notify-parse-file max))
-               0
-             (1+ org-notify-parse-file)))
-      (save-excursion
-       (with-current-buffer (find-file-noselect
-                             (nth org-notify-parse-file files))
-         (org-element-map (org-element-parse-buffer 'headline)
-             'headline 'org-notify-make-todo))))))
-
-(defun org-notify-maybe-too-late (diff period heading)
-  "Print warning message, when notified significantly later than defined by
-PERIOD."
-  (if (> (/ diff period) 1.5)
-      (message "Warning: notification for \"%s\" behind schedule!" heading))
-  t)
-
-(cl-defun org-notify-process ()
-  "Process the todo-list, and possibly notify user about upcoming or
-forgotten tasks."
-  (let ((notification-cnt 0))
-    (cl-macrolet ((prm (k) `(plist-get prms ,k))  (td (k) `(plist-get todo 
,k)))
-      (dolist (todo (org-notify-todo-list))
-       (let* ((deadline (td :deadline))  (heading (td :heading))
-               (uid (td :uid))            (last-run-sym
-                                           (intern (concat ":last-run-" uid))))
-          (cl-dolist (prms (plist-get org-notify-map (td :notify)))
-            (when (< deadline (org-notify-string->seconds (prm :time)))
-              (let ((period (org-notify-string->seconds (prm :period)))
-                    (last-run (prm last-run-sym))  (now (float-time))
-                    (actions (prm :actions))       diff  plist)
-               (when (or (not last-run)
-                          (and period (< period (setq diff (- now last-run)))
-                               (org-notify-maybe-too-late diff period 
heading)))
-                  (setq prms (plist-put prms last-run-sym now)
-                       plist (append todo prms))
-                  (if (if (plist-member prms :audible)
-                          (prm :audible)
-                       org-notify-audible)
-                      (ding))
-                  (unless (listp actions)
-                    (setq actions (list actions)))
-                 (cl-incf notification-cnt)
-                  (dolist (action actions)
-                    (funcall (if (fboundp action) action
-                               (intern (concat "org-notify-action"
-                                               (symbol-name action))))
-                            plist))
-                 (when (>= notification-cnt 
org-notify-max-notifications-per-run)
-                   (cl-return-from org-notify-process)))
-               (cl-return)))))))))
-
-(defun org-notify-add (name &rest params)
-  "Add a new notification type.
-The NAME can be used in Org-mode property `notify'.  If NAME is
-`default', the notification type applies for todo items without
-the `notify' property.  This file predefines such a default
-notification type.
-
-Each element of PARAMS is a list with parameters for a given time
-distance to the deadline.  This distance must increase from one
-element to the next.
-
-List of possible parameters:
-
-  :time      Time distance to deadline, when this type of notification shall
-             start.  It's a string: an integral value (positive or negative)
-             followed by a unit (s, m, h, d, w, M).
-  :actions   A function or a list of functions to be called to notify the
-             user.  Instead of a function name, you can also supply a suffix
-             of one of the various predefined `org-notify-action-xxx'
-             functions.
-  :period    Optional: can be used to repeat the actions periodically.
-             Same format as :time.
-  :duration  Some actions use this parameter to specify the duration of the
-             notification.  It's an integral number in seconds.
-  :audible   Overwrite the value of `org-notify-audible' for this action.
-
-For the actions, you can use your own functions or some of the predefined
-ones, whose names are prefixed with `org-notify-action-'."
-  (setq org-notify-map (plist-put org-notify-map name params)))
-
-(defun org-notify-start (&optional secs)
-  "Start the notification daemon.
-If SECS is positive, it's the period in seconds for processing
-the notifications of one org-agenda file, and if negative,
-notifications will be checked only when emacs is idle for -SECS
-seconds.  The default value for SECS is 20."
-  (interactive)
-  (if org-notify-timer
-      (org-notify-stop))
-  (setq secs (or secs 20)
-        org-notify-timer (if (< secs 0)
-                             (run-with-idle-timer (* -1 secs) t
-                                                  'org-notify-process)
-                           (run-with-timer secs secs 'org-notify-process))))
-
-(defun org-notify-stop ()
-  "Stop the notification daemon."
-  (when org-notify-timer
-    (cancel-timer org-notify-timer)
-    (setq org-notify-timer nil)))
-
-(defun org-notify-on-action (plist key)
-  "User wants to see action."
-  (let ((file (plist-get plist :file))
-        (begin (plist-get plist :begin)))
-    (if (string-equal key "show")
-        (progn
-          (switch-to-buffer (find-file-noselect file))
-          (org-with-wide-buffer
-           (goto-char begin)
-           (outline-show-entry))
-          (goto-char begin)
-          (search-forward "DEADLINE: <")
-          (search-forward ":")
-          (if (display-graphic-p)
-              (x-focus-frame nil)))
-      (save-excursion
-        (with-current-buffer (find-file-noselect file)
-          (org-with-wide-buffer
-           (goto-char begin)
-           (search-forward "DEADLINE: <")
-           (cond
-            ((string-equal key "done")  (org-todo))
-            ((string-equal key "hour")  (org-timestamp-change 60 'minute))
-            ((string-equal key "day")   (org-timestamp-up-day))
-            ((string-equal key "week")  (org-timestamp-change 7 'day)))))))))
-
-(defun org-notify-on-action-notify (id key)
-  "User wants to see action after mouse-click in notify window."
-  (org-notify-on-action (plist-get org-notify-on-action-map id) key)
-  (org-notify-on-close id nil))
-
-(defun org-notify-on-action-button (button)
-  "User wants to see action after button activation."
-  (cl-macrolet ((get (k) `(button-get button ,k)))
-    (org-notify-on-action (get 'plist) (get 'key))
-    (org-notify-delete-window (get 'buffer))
-    (cancel-timer (get 'timer))))
-
-(defun org-notify-delete-window (buffer)
-  "Delete the notification window."
-  (require 'appt)
-  (let ((appt-buffer-name buffer)
-        (appt-audible nil))
-    (appt-delete-window)))
-
-(defun org-notify-on-close (id reason)
-  "Notification window has been closed."
-  (setq org-notify-on-action-map (plist-put org-notify-on-action-map id nil)))
-
-(defun org-notify-action-message (plist)
-  "Print a message."
-  (message "TODO: \"%s\" at %s!" (plist-get plist :heading)
-           (plist-get plist :timestamp)))
-
-(defun org-notify-action-ding (plist)
-  "Make noise."
-  (let ((timer (run-with-timer 0 1 'ding)))
-    (run-with-timer (or (plist-get plist :duration) 3) nil
-                    'cancel-timer timer)))
-
-(defun org-notify-body-text (plist)
-  "Make human readable string for remaining time to deadline."
-  (require 'gnus-art)
-  (format "%s\n(%s)"
-          (replace-regexp-in-string
-           " in the future" ""
-           (article-lapsed-string
-            (time-add (current-time)
-                      (seconds-to-time (plist-get plist :deadline))) 2))
-          (plist-get plist :timestamp)))
-
-(defun org-notify-action-email (plist)
-  "Send email to user."
-  (compose-mail user-mail-address (concat "TODO: " (plist-get plist :heading)))
-  (insert (org-notify-body-text plist))
-  (funcall send-mail-function)
-  (cl-letf (((symbol-function 'yes-or-no-p) (lambda (x) t)))
-    (kill-buffer)))
-
-(defun org-notify-select-highest-window ()
-  "Select the highest window on the frame, that is not is not an
-org-notify window.  Mostly copied from `appt-select-lowest-window'."
-  (let ((highest-window (selected-window))
-        (bottom-edge (nth 3 (window-edges)))
-        next-bottom-edge)
-    (walk-windows (lambda (w)
-                    (when (and
-                           (not (string-match "^\\*org-notify-.*\\*$"
-                                              (buffer-name
-                                               (window-buffer w))))
-                           (> bottom-edge (setq next-bottom-edge
-                                                (nth 3 (window-edges w)))))
-                      (setq bottom-edge next-bottom-edge
-                            highest-window w))) 'nomini)
-    (select-window highest-window)))
-
-(defun org-notify-action-window (plist)
-  "Pop up a window, mostly copied from `appt-disp-window'."
-  (save-excursion
-    (cl-macrolet ((get (k) `(plist-get plist ,k)))
-      (let ((this-window (selected-window))
-            (buf (get-buffer-create
-                  (format org-notify-window-buffer-name (get :uid)))))
-        (when (minibufferp)
-          (other-window 1)
-          (and (minibufferp) (display-multi-frame-p) (other-frame 1)))
-        (if (cdr (assq 'unsplittable (frame-parameters)))
-            (progn (set-buffer buf) (display-buffer buf))
-          (unless (or (special-display-p (buffer-name buf))
-                      (same-window-p (buffer-name buf)))
-            (org-notify-select-highest-window)
-            (when (>= (window-height) (* 2 window-min-height))
-              (select-window (split-window nil nil 'above))))
-          (switch-to-buffer buf))
-        (setq buffer-read-only nil  buffer-undo-list t)
-        (erase-buffer)
-        (insert (format "TODO: %s, %s.\n" (get :heading)
-                        (org-notify-body-text plist)))
-        (let ((timer (run-with-timer (or (get :duration) 10) nil
-                                     'org-notify-delete-window buf)))
-          (dotimes (i (/ (length org-notify-actions) 2))
-            (let ((key (nth (* i 2) org-notify-actions))
-                  (text (nth (1+ (* i 2)) org-notify-actions)))
-              (insert-button text 'action 'org-notify-on-action-button
-                             'key key 'buffer buf 'plist plist 'timer timer)
-              (insert "    "))))
-        (shrink-window-if-larger-than-buffer (get-buffer-window buf t))
-        (set-buffer-modified-p nil)       (setq buffer-read-only t)
-        (raise-frame (selected-frame))    (select-window this-window)))))
-
-(defun org-notify-action-notify (plist)
-  "Pop up a notification window."
-  (require 'notifications)
-  (let* ((duration (plist-get plist :duration))
-         (id (notifications-notify
-              :title     (plist-get plist :heading)
-              :body      (org-notify-body-text plist)
-              :timeout   (if duration (* duration 1000))
-              :urgency   (plist-get plist :urgency)
-              :actions   org-notify-actions
-              :on-action 'org-notify-on-action-notify)))
-    (setq org-notify-on-action-map
-          (plist-put org-notify-on-action-map id plist))))
-
-(defun org-notify-action-notify/window (plist)
-  "For a graphics display, pop up a notification window, for a text
-terminal an emacs window."
-  (if (display-graphic-p)
-      (org-notify-action-notify plist)
-    (org-notify-action-window plist)))
-
-;;; Provide a minimal default setup.
-(org-notify-add 'default '(:time "1h" :actions -notify/window
-                                :period "2m" :duration 60))
-
-(provide 'org-notify)
-
-;;; org-notify.el ends here
diff --git a/contrib/lisp/org-panel.el b/contrib/lisp/org-panel.el
deleted file mode 100644
index dec7241..0000000
--- a/contrib/lisp/org-panel.el
+++ /dev/null
@@ -1,638 +0,0 @@
-;;; org-panel.el --- Simple routines for us with bad memory
-;;
-;; Author: Lennart Borgman (lennart O borgman A gmail O com)
-;; Created: Thu Nov 15 15:35:03 2007
-;; Version: 0.21
-;; Lxast-Updated: Wed Nov 21 03:06:03 2007 (3600 +0100)
-;; URL:
-;; Keywords:
-;; Compatibility:
-;;
-;; Features that might be required by this library:
-;;
-;;   `easymenu', `font-lock', `noutline', `org', `outline', `syntax',
-;;   `time-date'.
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;;; Commentary:
-;;
-;; This defines a kind of control panel for `org-mode'. This control
-;; panel should make it fast to move around and edit structure etc.
-;;
-;; To bring up the control panel type
-;;
-;;   M-x orgpan-panel
-;;
-;; Type ? there for help.
-;;
-;; I suggest you add the following to your .emacs for quick access of
-;; the panel:
-;;
-;;   (eval-after-load 'org-mode
-;;     (define-key org-mode-map [(control ?c) ?p] 'orgpan-panel))
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;;; Change log:
-;;
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;; 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 2, 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/>.
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;;; Code:
-
-(require 'org)
-(require 'outline)
-
-;; Fix-me: this is for testing. A minor mode version interferes badly
-;; with emulation minor modes. On the other hand, the other version
-;; interferes badly with (interactive ...).
-(defvar orgpan-minor-mode-version t)
-
-(defface orgpan-field
- '((t (:inherit 'widget-field)))
- "Face for fields."
- :group 'winsize)
-(defvar orgpan-field-face 'orgpan-field)
-
-(defface orgpan-active-field
- '((t (:inherit 'highlight)))
- "Face for fields."
- :group 'winsize)
-(defvar orgpan-active-field-face 'orgpan-active-field)
-
-(defface orgpan-spaceline
- '((t (:height 0.2)))
- "Face for spacing lines."
- :group 'winsize)
-
-(defcustom orgpan-panel-buttons nil
- "Panel style, if non-nil use buttons.
-If there are buttons in the panel they are used to change the way
-the arrow keys work.  The panel looks something like this, with
-the first button chosen:
-
- [Navigate] [Restructure] [TODO/Priority]
- ----------
- up/down, left: Go to, right: Visibility
-
-The line below the buttons try to give a short hint about what
-the arrow keys does.  \(Personally I prefer the version without
-buttons since I then do not have to remember which button is
-active.)"
- :type 'boolean
- :group 'winsize)
-
-;; Fix-me: add org-mode-map
-(defconst orgpan-org-mode-commands nil)
-(defconst orgpan-org-commands
- '(
-   orgpan-copy-subtree
-   orgpan-cut-subtree
-   orgpan-paste-subtree
-   undo
-   ;;
-   ;orgpan-occur
-   ;;
-   org-cycle
-   org-global-cycle
-   outline-up-heading
-   outline-next-visible-heading
-   outline-previous-visible-heading
-   outline-forward-same-level
-   outline-backward-same-level
-   org-todo
-   org-show-todo-tree
-   org-priority-up
-   org-priority-down
-   org-move-subtree-up
-   org-move-subtree-down
-   org-do-promote
-   org-do-demote
-   org-promote-subtree
-   org-demote-subtree))
-
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Hook functions etc
-
-(defun orgpan-delete-panel ()
- "Remove the panel."
- (interactive)
- (when (buffer-live-p orgpan-panel-buffer)
-   (delete-windows-on orgpan-panel-buffer)
-   (kill-buffer orgpan-panel-buffer))
- (setq orgpan-panel-buffer nil)
- (setq orgpan-panel-window nil)
- (orgpan-panel-minor-mode 0)
- (remove-hook 'post-command-hook 'orgpan-minor-post-command)
- (remove-hook 'post-command-hook 'orgpan-mode-post-command)
- ;;(remove-hook 'window-configuration-change-hook 'orgpan-window-config-change)
- )
-
-(defvar orgpan-last-command-was-from-panel nil)
-(defun orgpan-mode-pre-command ()
- (setq orgpan-last-command-was-from-panel nil)
- (condition-case err
-     (if (not (and (windowp orgpan-org-window)
-                   (window-live-p orgpan-org-window)))
-         (progn
-           (setq this-command 'ignore)
-           (orgpan-delete-panel)
-           (message "The window belonging to the panel had disappeared, 
removed panel."))
-       (let ((buf (window-buffer orgpan-org-window)))
-         (when (with-current-buffer buf
-                 (derived-mode-p 'org-mode))
-           (setq orgpan-last-org-buffer buf))
-         ;; Fix me: add a list of those commands that are not
-         ;; meaningful from the panel (for example org-time-stamp)
-         (when (or (memq this-command orgpan-org-commands)
-                   (memq this-command orgpan-org-mode-commands)
-                   ;; For some reason not all org commands are found above:
-                   (string= "org-" (substring (format "%s" this-command) 0 4)))
-           (if (not (with-current-buffer buf
-                      (derived-mode-p 'org-mode)))
-               (progn
-                 (if (buffer-live-p orgpan-org-buffer)
-                     (set-window-buffer orgpan-org-window orgpan-org-buffer)
-                   (message "Please use `l' or `b' to choose an org-mode 
buffer"))
-                 (setq this-command 'ignore))
-             (setq orgpan-org-buffer (window-buffer orgpan-org-window))
-             (setq orgpan-last-command-was-from-panel t)
-             (select-window orgpan-org-window)
-             ;;(when (active-minibuffer-window
-             ;;(set-buffer orgpan-org-buffer)
-             ))))
-   (error (lwarn 't :warning "orgpan-pre: %S" err))))
-
-(defun orgpan-mode-post-command ()
- (condition-case err
-     (progn
-       (unless (and (windowp orgpan-panel-window)
-                    (window-live-p orgpan-panel-window)
-                    (bufferp orgpan-panel-buffer)
-                    (buffer-live-p orgpan-panel-buffer))
-         ;;(orgpan-delete-panel)
-         )
-       (when (and orgpan-last-command-was-from-panel
-                  (windowp orgpan-panel-window)
-                  (window-live-p orgpan-panel-window))
-         (select-window orgpan-panel-window)
-         (when (derived-mode-p 'orgpan-mode)
-           (setq deactivate-mark t)
-           (when orgpan-panel-buttons
-             (unless (and orgpan-point
-                          (= (point) orgpan-point))
-               ;; Go backward so it is possible to click on a "button":
-               (orgpan-backward-field))))))
-   (error (lwarn 't :warning "orgpan-post: %S" err))))
-
-;; (defun orgpan-window-config-change ()
-;;   "Check if any frame is displaying an orgpan panel.
-;; If not remove `orgpan-mode-post-command' and this function from
-;; the hooks."
-;;   (condition-case err
-;;       (unless (and (
-;;       (let ((found-pan nil))
-;;         (dolist (f (frame-list))
-;;           (dolist (w (window-list f 'nomini))
-;;             (with-current-buffer (window-buffer w)
-;;               (when (derived-mode-p 'orgpan-mode)
-;;                 (setq found-pan t)))))
-;;         (unless found-pan
-;;           (remove-hook 'post-command-hook 'orgpan-mode-post-command)
-;;           (remove-hook 'window-configuration-change-hook 
'orgpan-window-config-change)))
-;;     (error (lwarn 't :warning "Error in orgpan-config-change: %S" err))))
-
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Commands
-
-(defun orgpan-last-buffer ()
- "Open last org-mode buffer in panels org window."
- (interactive)
- (let ((buf (window-buffer orgpan-org-window))
-       (last-buf orgpan-last-org-buffer))
-   (when (with-current-buffer buf
-           (derived-mode-p 'org-mode))
-     (setq orgpan-last-org-buffer buf))
-   (when (eq last-buf buf)
-     (setq last-buf nil))
-   (if (not last-buf)
-       (orgpan-switch-buffer)
-     (set-window-buffer orgpan-org-window last-buf))))
-
-(defun orgpan-switch-buffer ()
- "Switch to next org-mode buffer in panels org window."
- (interactive)
- (let ((buf (window-buffer orgpan-org-window))
-       (org-buffers nil))
-   (with-current-buffer buf
-     (when (derived-mode-p 'org-mode)
-       (bury-buffer buf)
-       (setq orgpan-last-org-buffer buf)))
-   (setq org-buffers (delq nil (mapcar (lambda (buf)
-                                         (when (with-current-buffer buf
-                                                 (derived-mode-p 'org-mode))
-                                           buf))
-                                       (buffer-list))))
-   (setq org-buffers (delq buf org-buffers))
-   (set-window-buffer orgpan-org-window (car org-buffers))
-   (setq orgpan-org-buffer (car org-buffers))))
-
-(defun orgpan-paste-subtree ()
- (interactive)
- (if (y-or-n-p "Paste subtree here? ")
-     (org-paste-subtree)
-   (message "Nothing was pasted")))
-
-(defun orgpan-cut-subtree ()
- (interactive)
- (let ((heading (progn
-                  (org-back-to-heading)
-                  (buffer-substring (point) (line-end-position))
-                  )))
-   (if (y-or-n-p (format "Do you want to cut the subtree\n%s\n? " heading))
-       (org-cut-subtree)
-     (message "Nothing was cut"))))
-
-(defun orgpan-copy-subtree ()
- (interactive)
- (let ((heading (progn
-                  (org-back-to-heading)
-                  (buffer-substring (point) (line-end-position))
-                  )))
-   (if (y-or-n-p (format "Do you want to copy the subtree\n%s\n? " heading))
-       (org-copy-subtree)
-     (message "Nothing was copied"))))
-
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Buttons
-
-(defvar orgpan-ovl-help nil)
-
-(defun orgpan-check-panel-mode ()
- (unless (derived-mode-p 'orgpan-mode)
-   (error "Not orgpan-mode in buffer: %s" major-mode)))
-
-(defun orgpan-display-bindings-help ()
- (orgpan-check-panel-mode)
- (setq orgpan-point (point))
- (let* ((ovls (overlays-at (point)))
-        (ovl (car ovls))
-        (help (when ovl (overlay-get ovl 'orgpan-explain))))
-   (dolist (o (overlays-in (point-min) (point-max)))
-     (overlay-put o 'face orgpan-field-face))
-   (overlay-put ovl 'face orgpan-active-field-face)
-   (overlay-put orgpan-ovl-help 'before-string help)))
-
-(defun orgpan-forward-field ()
- (interactive)
- (orgpan-check-panel-mode)
- (let ((pos (next-overlay-change (point))))
-   (unless (overlays-at pos)
-     (setq pos (next-overlay-change pos)))
-   (when (= pos (point-max))
-     (setq pos (point-min))
-     (unless (overlays-at pos)
-       (setq pos (next-overlay-change pos))))
-   (goto-char pos))
- (orgpan-display-bindings-help))
-
-(defun orgpan-backward-field ()
- (interactive)
- (orgpan-check-panel-mode)
- (when (= (point) (point-min))
-   (goto-char (point-max)))
- (let ((pos (previous-overlay-change (point))))
-   (unless (overlays-at pos)
-     (setq pos (previous-overlay-change pos)))
-   (goto-char pos))
- (orgpan-display-bindings-help))
-
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Mode
-
-(defconst orgpan-mode-map
- ;; Fix-me: clean up here!
- ;; Fix-me: viper support
- (let ((map (make-sparse-keymap)))
-   (define-key map [?q] 'orgpan-delete-panel)
-   (define-key map [??] 'orgpan-help)
-   ;; Copying etc
-   (define-key map [?c] 'orgpan-copy-subtree)
-   (define-key map [?x] 'orgpan-cut-subtree)
-   (define-key map [?p] 'orgpan-paste-subtree)
-   (define-key map [?z] 'undo)
-   ;; Buffers:
-   (define-key map [?b] 'orgpan-switch-buffer)
-   (define-key map [?l] 'orgpan-last-buffer)
-   ;; Some keys for moving between headings. Emacs keys for next/prev
-   ;; line seems ok:
-   (define-key map [(control ?p)] 'outline-previous-visible-heading)
-   (define-key map [(control ?n)] 'outline-next-visible-heading)
-   (define-key map [(shift control ?p)] 'outline-backward-same-level)
-   (define-key map [(shift control ?n)] 'outline-forward-same-level)
-   ;; A mnemunic for up:
-   (define-key map [(control ?u)] 'outline-up-heading)
-   ;; Search sparse tree:
-   ;;
-   ;; Fix-me: Search does not work, some problem with
-   ;; interactive. Probably have to turn the whole thing around and
-   ;; always be in the org buffer, but with a minor mode running
-   ;; there.
-   ;;
-   ;;(define-key map [?s] 'org-sparse-tree)
-   (define-key map [?s] 'orgpan-occur)
-   ;; Same as in org-mode:
-   ;;(define-key map [(control ?c)(control ?v)] 'org-show-todo-tree)
-   ;; Fix-me: This leads to strange problems:
-   ;;(define-key map [t] 'ignore)
-   map))
-
-(defun orgpan-occur ()
- "Replacement for `org-occur'.
-Technical reasons."
- (interactive)
- (let ((rgx (read-from-minibuffer "my mini Regexp: ")))
-   (setq orgpan-last-command-was-from-panel t)
-   (select-window orgpan-org-window)
-   (org-occur rgx)))
-
-(defvar orgpan-panel-window nil
- "The window showing `orgpan-panel-buffer'.")
-
-(defvar orgpan-panel-buffer nil
- "The panel buffer.
-There can be only one such buffer at any time.")
-
-(defvar orgpan-org-window nil)
-;;(make-variable-buffer-local 'orgpan-org-window)
-
-;; Fix-me: used?
-(defvar orgpan-org-buffer nil)
-;;(make-variable-buffer-local 'orgpan-org-buffer)
-
-(defvar orgpan-last-org-buffer nil)
-;;(make-variable-buffer-local 'orgpan-last-org-buffer)
-
-(defvar orgpan-point nil)
-;;(make-variable-buffer-local 'orgpan-point)
-
-(defvar viper-emacs-state-mode-list)
-(defvar viper-new-major-mode-buffer-list)
-
-(defun orgpan-avoid-viper-in-buffer ()
- ;; Fix-me: This is ugly. However see `this-major-mode-requires-vi-state':
- (set (make-local-variable 'viper-emacs-state-mode-list) '(orgpan-mode))
- (set (make-local-variable 'viper-new-major-mode-buffer-list) nil)
- (local-set-key [?\ ] 'ignore))
-
-(define-derived-mode orgpan-mode nil "Org-Panel"
- "Mode for org-simple.el control panel."
- (setq buffer-read-only t)
- (unless orgpan-minor-mode-version
-   (add-hook 'pre-command-hook 'orgpan-mode-pre-command nil t)
-   (add-hook 'post-command-hook 'orgpan-mode-post-command t))
- (orgpan-avoid-viper-in-buffer)
- (setq cursor-type nil))
-
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Panel layout
-
-(defun orgpan-insert-field (text keymap explain)
- (insert text)
- (let* ((end (point))
-        (len (length text))
-        (beg (- end len))
-        (ovl (make-overlay beg end)))
-   (overlay-put ovl 'face orgpan-field-face)
-   (overlay-put ovl 'keymap keymap)
-   (overlay-put ovl 'orgpan-explain explain)))
-
-(defconst orgpan-with-keymap
- (let ((map (make-sparse-keymap)))
-   (set-keymap-parent map org-mode-map)
-   ;; Users are used to tabbing between fields:
-   (define-key map [(tab)] 'orgpan-forward-field)
-   (define-key map [(shift tab)] 'orgpan-backward-field)
-   ;; Now we must use something else for visibility (first does not work if 
Viper):
-   (define-key map [(meta tab)] 'org-cycle)
-   (define-key map [(control meta tab)] 'org-global-cycle)
-   map))
-
-(defconst orgpan-without-keymap
- (let ((map (make-sparse-keymap)))
-   (set-keymap-parent map org-mode-map)
-   ;; Visibility (those are in org-mode-map):
-   ;;(define-key map [tab] 'org-cycle)
-   ;;(define-key map [(shift tab)] 'org-global-cycle)
-   ;; Navigate:
-   (define-key map [left] 'outline-up-heading)
-   (define-key map [right] 'org-cycle)
-   (define-key map [up] 'outline-previous-visible-heading)
-   (define-key map [down] 'outline-next-visible-heading)
-   (define-key map [(shift down)] 'outline-forward-same-level)
-   (define-key map [(shift up)] 'outline-backward-same-level)
-   ;; Restructure:
-   (define-key map [(control up)] 'org-move-subtree-up)
-   (define-key map [(control down)] 'org-move-subtree-down)
-   (define-key map [(control left)] 'org-do-promote)
-   (define-key map [(control right)] 'org-do-demote)
-   (define-key map [(control shift left)] 'org-promote-subtree)
-   (define-key map [(control shift right)] 'org-demote-subtree)
-   ;; Todo etc
-   (define-key map [?+] 'org-priority-up)
-   (define-key map [?-] 'org-priority-down)
-   (define-key map [?t] 'org-todo)
-   map))
-
-(defun orgpan-make-panel-without-buttons (buf)
- (with-current-buffer buf
-   (insert (propertize "Org Panel" 'face 'orgpan-active-field))
-   (insert "  ? for help, q quit\n")
-   (insert (propertize "arrows" 'face 'font-lock-keyword-face)
-           ": Go to, "
-           (propertize "C-arrows" 'face 'font-lock-keyword-face)
-           ": Edit tree\n"
-           (propertize "cxpz" 'face 'font-lock-keyword-face)
-           ": copy cut paste undo, "
-           (propertize "tT+-" 'face 'font-lock-keyword-face)
-           ": todo priority, "
-           (propertize "s" 'face 'font-lock-keyword-face)
-           " search"
-           )
-   (set-keymap-parent orgpan-mode-map orgpan-without-keymap)
-   ))
-
-(defun orgpan-make-panel-with-buttons (buf)
- (with-current-buffer buf
-   (let* ((base-map (make-sparse-keymap))
-          (space-line (propertize "\n\n" 'face 'orgpan-spaceline))
-          (arrow-face 'font-lock-keyword-face)
-          (L (propertize "left" 'face arrow-face))
-          (R (propertize "right" 'face arrow-face))
-          (U (propertize "up" 'face arrow-face))
-          (D (propertize "down" 'face arrow-face)))
-     ;;(message D)(sit-for 2)
-     (define-key base-map [left] 'ignore)
-     (define-key base-map [right] 'ignore)
-     (define-key base-map [up] 'ignore)
-     (define-key base-map [down] 'ignore)
-     (define-key base-map [?q] 'delete-window)
-     (define-key base-map [??] 'orgpan-help)
-     ;; Navigating
-     (let ((map (copy-keymap base-map)))
-       (define-key map [left] 'outline-up-heading)
-       (define-key map [right] 'org-cycle)
-       (define-key map [up] 'outline-previous-visible-heading)
-       (define-key map [down] 'outline-next-visible-heading)
-       (define-key map [(shift down)] 'outline-forward-same-level)
-       (define-key map [(shift up)] 'outline-backward-same-level)
-       (orgpan-insert-field "Navigate" map (concat U "/" D ", " L ": Go to, " 
R ": Visibility")))
-     (insert "  ")
-     (let ((map (copy-keymap base-map)))
-       (define-key map [up] 'org-move-subtree-up)
-       (define-key map [down] 'org-move-subtree-down)
-       (define-key map [left] 'org-do-promote)
-       (define-key map [right] 'org-do-demote)
-       (define-key map [(shift left)] 'org-promote-subtree)
-       (define-key map [(shift right)] 'org-demote-subtree)
-       (orgpan-insert-field
-        "Restructure" map
-        (concat U "/" D ": "
-                (propertize "Move" 'face 'font-lock-warning-face)
-                ", " L "/" R ": "
-                (propertize "Level (w S: Subtree Level)" 'face 
'font-lock-warning-face))))
-     (insert "  ")
-     (let ((map (copy-keymap base-map)))
-       (define-key map [up] 'org-priority-up)
-       (define-key map [down] 'org-priority-down)
-       (define-key map [right] 'org-todo)
-       (orgpan-insert-field "TODO/priority" map
-                            (concat R ": TODO, " U "/" D ": Priority")))
-     )
-   (insert "   ? for help, q quit\n")
-   (orgpan-display-bindings-help)
-   (setq orgpan-ovl-help (make-overlay (point) (point)))
-   ))
-
-(defun orgpan-make-panel-buffer ()
- "Make the panel buffer."
- (let* ((buf-name "*Org Panel*"))
-   (when orgpan-panel-buffer (kill-buffer orgpan-panel-buffer))
-   (setq orgpan-panel-buffer (get-buffer-create buf-name))
-   (if orgpan-panel-buttons
-       (orgpan-make-panel-with-buttons orgpan-panel-buffer)
-     (orgpan-make-panel-without-buttons orgpan-panel-buffer))
-   (with-current-buffer orgpan-panel-buffer
-     (orgpan-mode)
-     (goto-char (point-min)))
-   orgpan-panel-buffer))
-
-(defun orgpan-help ()
- (interactive)
- (set-keymap-parent orgpan-with-keymap nil)
- (set-keymap-parent orgpan-without-keymap nil)
- (describe-function 'orgpan-panel)
- (set-keymap-parent orgpan-with-keymap org-mode-map)
- (set-keymap-parent orgpan-without-keymap org-mode-map)
- (message "Use 'l' to remove help window")
- )
-
-(defun orgpan-panel ()
- "Create a control panel for current `org-mode' buffer.
-The control panel may be used to quickly move around and change
-the headings. The idea is that when you want to to a lot of this
-kind of editing you should be able to do that with few
-keystrokes (and without having to remember the complicated
-keystrokes). A typical situation when this perhaps can be useful
-is when you are looking at your notes file \(usually ~/.notes,
-see `remember-data-file') where you have saved quick notes with
-`remember'.
-
-The keys below are defined in the panel. Note that the commands
-are carried out in the `org-mode' buffer that belongs to the
-panel.
-
-\\{orgpan-mode-map}
-
-In addition to the keys above most of the keys in `org-mode' can
-also be used from the panel.
-
-Note: There are two forms of the control panel, one with buttons
-and one without. The default is without, see
-`orgpan-panel-buttons'.  If buttons are used choosing a different
-button changes the binding of the arrow keys."
- (interactive)
- (unless (derived-mode-p 'org-mode)
-   (error "Buffer is not in org-mode"))
- (orgpan-delete-panel)
- (unless orgpan-org-mode-commands
-   (map-keymap (lambda (ev def)
-                 (when (and def
-                            (symbolp def)
-                            (fboundp def))
-                   (setq orgpan-org-mode-commands
-                         (cons def orgpan-org-mode-commands))))
-               org-mode-map))
- ;;(org-back-to-heading)
- ;;(remove-hook 'window-configuration-change-hook 'orgpan-window-config-change)
- (setq orgpan-org-window (selected-window))
- (setq orgpan-panel-window (split-window nil -4 'below))
- (select-window orgpan-panel-window)
- (set-window-buffer (selected-window) (orgpan-make-panel-buffer))
- ;;(set-window-dedicated-p (selected-window) t)
- ;; The minor mode version starts here:
- (when orgpan-minor-mode-version
-   (select-window orgpan-org-window)
-   (orgpan-panel-minor-mode 1)
-   (add-hook 'post-command-hook 'orgpan-minor-post-command t)))
-
-(defun orgpan-minor-post-command ()
- (unless (and
-          ;; Check org window and buffer
-          (windowp orgpan-org-window)
-          (window-live-p orgpan-org-window)
-          (eq orgpan-org-window (selected-window))
-          (derived-mode-p 'org-mode)
-          ;; Check panel window and buffer
-          (windowp orgpan-panel-window)
-          (window-live-p orgpan-panel-window)
-          (bufferp orgpan-panel-buffer)
-          (buffer-live-p orgpan-panel-buffer)
-          (eq (window-buffer orgpan-panel-window) orgpan-panel-buffer)
-          ;; Check minor mode
-          orgpan-panel-minor-mode)
-   (orgpan-delete-panel)))
-
-(define-minor-mode orgpan-panel-minor-mode
- "Minor mode used in `org-mode' buffer when showing panel."
- :keymap orgpan-mode-map
- :lighter " PANEL"
- :group 'orgpan
- )
-
-
-(provide 'org-panel)
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;;; org-panel.el ends here
diff --git a/contrib/lisp/org-passwords.el b/contrib/lisp/org-passwords.el
deleted file mode 100644
index 4bdd804..0000000
--- a/contrib/lisp/org-passwords.el
+++ /dev/null
@@ -1,384 +0,0 @@
-;;; org-passwords.el --- org derived mode for managing passwords
-
-;; Author: Jorge A. Alfaro-Murillo <jorge.alfaro-murillo@yale.edu>
-;; Created: December 26, 2012
-;; Keywords: passwords, password
-
-;; This file is NOT 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:
-
-;; This file contains the code for managing your passwords with
-;; Org-mode. It is part of org/contrib (see https://orgmode.org/). If
-;; you want to contribute with development, or have a problem, do it
-;; here: https://bitbucket.org/alfaromurillo/org-passwords.el
-
-;; A basic setup needs to indicate a passwords file, and a dictionary
-;; for the random words:
-
-;;   (require 'org-passwords)
-;;   (setq org-passwords-file "~/documents/passwords.gpg")
-;;   (setq org-passwords-random-words-dictionary 
"/etc/dictionaries-common/words")
-
-;; Basic usage:
-
-;;   `M-x org-passwords' opens the passwords file in
-;;   `org-passwords-mode'.
-
-;;   `M-x org-passwords-generate-password' generates a random string
-;;   of numbers, lowercase letters and uppercase letters.
-
-;;   `C-u M-x org-passwords-generate-password' generates a random
-;;   string of numbers, lowercase letters, uppercase letters and
-;;   symbols.
-
-;;   `M-x org-passwords-random-words' concatenates random words from
-;;   the dictionary defined by `org-passwords-random-words-dictionary'
-;;   into a string, each word separated by the string defined in
-;;   `org-passwords-random-words-separator'.
-
-;;   `C-u M-x org-passwords-random-words' does the same as above, and
-;;   also makes substitutions according to
-;;   `org-passwords-random-words-substitutions'.
-
-;; It is also useful to set up keybindings for the functions
-;; `org-passwords-copy-username', `org-passwords-copy-password' and
-;; `org-passwords-open-url' in the `org-passwords-mode', to easily
-;; make the passwords and usernames available to the facility for
-;; pasting text of the window system (clipboard on X and MS-Windows,
-;; pasteboard on Nextstep/Mac OS, etc.), without inserting them in the
-;; kill-ring. You can set for example:
-
-;;   (eval-after-load "org-passwords"
-;;     '(progn
-;;        (define-key org-passwords-mode-map
-;;      (kbd "C-c u")
-;;      'org-passwords-copy-username)
-;;        (define-key org-passwords-mode-map
-;;      (kbd "C-c p")
-;;      'org-passwords-copy-password)
-;;      (kbd "C-c o")
-;;      'org-passwords-open-url)))
-
-;; Finally, to enter new passwords, you can use `org-capture' and a
-;; minimal template like:
-
-;;   ("p" "password" entry (file "~/documents/passwords.gpg")
-;;    "* %^{Title}\n  %^{URL}p %^{USERNAME}p %^{PASSWORD}p")
-
-;; When asked for the password you can then call either
-;; `org-passwords-generate-password' or `org-passwords-random-words'.
-;; Be sure to enable recursive minibuffers to call those functions
-;; from the minibuffer:
-
-;;   (setq enable-recursive-minibuffers t)
-
-;;; Code:
-
-(require 'org)
-
-;;;###autoload
-(define-derived-mode org-passwords-mode org-mode
-  "org-passwords-mode"
-  "Mode for storing passwords"
-  nil)
-
-(defgroup org-passwords nil
-  "Options for password management."
-  :group 'org)
-
-(defcustom org-passwords-password-property "PASSWORD"
-  "Name of the property for password entry."
-  :type 'string
-  :group 'org-passwords)
-
-(defcustom org-passwords-username-property "USERNAME"
-  "Name of the property for user name entry."
-  :type 'string
-  :group 'org-passwords)
-
-(defcustom org-passwords-url-property "URL"
-  "Name of the property for URL entry."
-  :type 'string
-  :group 'org-passwords)
-
-(defcustom org-passwords-file nil
-  "Default file name for the file that contains the passwords."
-  :type 'file
-  :group 'org-passwords)
-
-(defcustom org-passwords-time-opened "1 min"
-  "Time that the password file will remain open. It has to be a
-string, a number followed by units."
-  :type 'str
-  :group 'org-passwords)
-
-(defcustom org-passwords-default-password-size "20"
-  "Default number of characters to use in
-org-passwords-generate-password. It has to be a string."
-  :type 'str
-  :group 'org-passwords)
-
-(defcustom org-passwords-random-words-dictionary nil
-  "Default file name for the file that contains a dictionary of
-words for `org-passwords-random-words'. Each non-empty line in
-the file is considered a word."
-  :type 'file
-  :group 'org-passwords)
-
-(defcustom org-passwords-default-random-words-number "5"
-  "Default number of words to use in org-passwords-random-words.
-It has to be a string."
-  :type 'str
-  :group 'org-passwords)
-
-(defvar org-passwords-random-words-separator "-"
-  "A string to separate words in `org-passwords-random-words'.")
-
-(defvar org-passwords-random-words-substitutions
-  '(("a" . "@")
-    ("e" . "3")
-    ("o" . "0"))
-"A list of substitutions to be made with
-`org-passwords-random-words' if it is called with
-`universal-argument'. Each element is pair of
-strings (SUBSTITUTE-THIS . BY-THIS).")
-
-(defun org-passwords-copy-password ()
-  "Makes the password available to other programs. Puts the
-password of the entry at the location of the cursor in the
-facility for pasting text of the window system (clipboard on X
-and MS-Windows, pasteboard on Nextstep/Mac OS, etc.), without
-putting it in the kill ring."
-  (interactive)
-  (funcall interprogram-cut-function
-           (org-entry-get (point)
-                         org-passwords-password-property)))
-
-(defun org-passwords-copy-username ()
-  "Makes the password available to other programs. Puts the
-username of the entry at the location of the cursor in the
-facility for pasting text of the window system (clipboard on X
-and MS-Windows, pasteboard on Nextstep/Mac OS, etc.), without
-putting it in the kill ring."
-  (interactive)
-  (funcall interprogram-cut-function
-           (org-entry-get (point)
-                         org-passwords-username-property
-                         t)))
-
-(defun org-passwords-open-url ()
-  "Browse the URL associated with the entry at the location of
-the cursor."
-  (interactive)
-  (browse-url (org-entry-get (point)
-                           org-passwords-url-property
-                           t)))
-
-;;;###autoload
-(defun org-passwords (&optional arg)
-  "Open the password file. Open the password file defined by the
-variable `org-password-file' in read-only mode and kill that
-buffer later according to the value of the variable
-`org-passwords-time-opened'. It also adds the `org-password-file'
-to the auto-mode-alist so that it is opened with its mode being
-`org-passwords-mode'.
-
-With prefix arg ARG, the command does not set up a timer to kill the buffer.
-
-With a double prefix arg \\[universal-argument] \\[universal-argument], open 
the file for editing.
-"
-  (interactive "P")
-  (if org-passwords-file
-      (progn
-       (add-to-list 'auto-mode-alist
-                    (cons
-                     (regexp-quote
-                      (expand-file-name org-passwords-file))
-                     'org-passwords-mode))
-       (if (equal arg '(4))
-           (find-file-read-only org-passwords-file)
-         (if (equal arg '(16))
-             (find-file org-passwords-file)
-           (progn
-             (find-file-read-only org-passwords-file)
-             (org-passwords-set-up-kill-password-buffer)))))
-    (minibuffer-message "No default password file defined. Set the variable 
`org-password-file'.")))
-
-(defun org-passwords-set-up-kill-password-buffer ()
-  (run-at-time org-passwords-time-opened
-              nil
-              '(lambda ()
-                 (if (get-file-buffer org-passwords-file)
-                     (kill-buffer
-                      (get-file-buffer org-passwords-file))))))
-
-;;; Password generator
-
-;; Set random number seed from current time and pid. Otherwise
-;; `random' gives the same results every time emacs restarts.
-(random t)
-
-(defun org-passwords-generate-password (arg)
-  "Ask a number of characters and insert a password of that size.
-Password has a random string of numbers, lowercase letters, and
-uppercase letters.  Argument ARG include symbols."
-  (interactive "P")
-  (let ((number-of-chars
-        (read-from-minibuffer
-         (concat "Number of characters (default "
-                 org-passwords-default-password-size
-                 "): ")
-         nil
-         nil
-         t
-         nil
-         org-passwords-default-password-size)))
-    (if arg
-       (insert (org-passwords-generate-password-with-symbols "" 
number-of-chars))
-       (insert (org-passwords-generate-password-without-symbols "" 
number-of-chars)))))
-
-(defun org-passwords-generate-password-with-symbols (previous-string 
nums-of-chars)
-  "Return a string consisting of PREVIOUS-STRING and
-NUMS-OF-CHARS random characters."
-  (if (eq nums-of-chars 0) previous-string
-    (org-passwords-generate-password-with-symbols
-     (concat previous-string
-            (char-to-string
-             ;; symbols, letters, numbers are from 33 to 126
-             (+ (random (- 127 33)) 33)))
-     (1- nums-of-chars))))
-
-(defun org-passwords-generate-password-without-symbols (previous-string 
nums-of-chars)
-  "Return string consisting of PREVIOUS-STRING and NUMS-OF-CHARS
-random numbers, lowercase letters, and numbers."
-  (if (eq nums-of-chars 0)
-      previous-string
-      ; There are 10 numbers, 26 lowercase letters and 26 uppercase
-      ; letters. 10 + 26 + 26 = 62. The number characters go from 48
-      ; to 57, the uppercase letters from 65 to 90, and the lowercase
-      ; from 97 to 122. The following makes each equally likely.
-      (let ((temp-value (random 62)))
-       (cond ((< temp-value 10)
-              ; If temp-value<10, then add a number
-              (org-passwords-generate-password-without-symbols
-               (concat previous-string
-                       (char-to-string (+ 48 temp-value)))
-               (1- nums-of-chars)))
-             ((and (> temp-value 9) (< temp-value 36))
-              ; If 9<temp-value<36, then add an uppercase letter
-              (org-passwords-generate-password-without-symbols
-               (concat previous-string
-                       (char-to-string (+ 65 (- temp-value 10))))
-               (1- nums-of-chars)))
-             ((> temp-value 35)
-               ; If temp-value>35, then add a lowecase letter
-              (org-passwords-generate-password-without-symbols
-               (concat previous-string
-                       (char-to-string (+ 97 (- temp-value 36))))
-               (1- nums-of-chars)))))))
-
-;;; Random words
-
-(defun org-passwords-random-words (arg)
-  "Ask for a number of words and inserts a sequence of that many
-random words from the list in the file
-`org-passwords-random-words-dictionary' separated by
-`org-passwords-random-words-separator'. ARG make substitutions in
-the words as defined by
-`org-passwords-random-words-substitutions'."
-  (interactive "P")
-  (if org-passwords-random-words-dictionary
-      (let ((number-of-words
-            (read-from-minibuffer
-             (concat "Number of words (default "
-                     org-passwords-default-random-words-number
-                     "): ")
-             nil
-             nil
-             t
-             nil
-             org-passwords-default-random-words-number))
-           (list-of-words
-            (with-temp-buffer
-              (insert-file-contents
-               org-passwords-random-words-dictionary)
-              (split-string (buffer-string) "\n" t))))
-       (insert
-        (org-passwords-substitute
-         (org-passwords-random-words-attach-number-of-words
-          (nth (random (length list-of-words))
-               list-of-words)
-          (1- number-of-words)
-          list-of-words
-          org-passwords-random-words-separator)
-         (if arg
-             org-passwords-random-words-substitutions
-           nil))))
-    (minibuffer-message
-     "No default dictionary file defined. Set the variable 
`org-passwords-random-words-dictionary'.")))
-
-(defun org-passwords-random-words-attach-number-of-words
-  (previous-string number-of-words list-of-words separator)
-  "Returns a string consisting of PREVIOUS-STRING followed by a
-succession of NUMBER-OF-WORDS random words from the list LIST-OF-WORDS
-separated SEPARATOR."
-  (if (eq number-of-words 0)
-      previous-string
-      (org-passwords-random-words-attach-number-of-words
-       (concat previous-string
-              separator
-              (nth (random (length list-of-words)) list-of-words))
-       (1- number-of-words)
-       list-of-words
-       separator)))
-
-(defun org-passwords-substitute (string-to-change list-of-substitutions)
-  "Substitutes each appearance in STRING-TO-CHANGE of the `car' of
-each element of LIST-OF-SUBSTITUTIONS by the `cdr' of that
-element. For example:
- (org-passwords-substitute \"ab\" \'((\"a\" . \"b\") (\"b\" . \"c\")))
-       => \"bc\"
-Substitutions are made in order of the list, so for example:
- (org-passwords-substitute \"ab\" \'((\"ab\" . \"c\") (\"b\" . \"d\")))
-       => \"c\""
-  (if list-of-substitutions
-      (concat (org-passwords-concat-this-with-string
-              (cdar list-of-substitutions)
-              (mapcar (lambda (x)
-                        (org-passwords-substitute
-                         x
-                         (cdr list-of-substitutions)))
-                      (split-string string-to-change
-                                    (caar list-of-substitutions)))))
-    string-to-change))
-
-(defun org-passwords-concat-this-with-string (this list-of-strings)
-  "Put the string THIS in between every string in LIST-OF-STRINGS. For example:
- (org-passwords-concat-this-with-string \"Here\" \'(\"First\" \"Second\" 
\"Third\"))
-      => \"FirstHereSencondHereThird\""
-  (if (cdr list-of-strings)
-      (concat (car list-of-strings)
-             this
-             (org-passwords-concat-this-with-string
-              this
-              (cdr list-of-strings)))
-    (car list-of-strings)))
-
-(provide 'org-passwords)
-
-;;; org-passwords.el ends here
diff --git a/contrib/lisp/org-registry.el b/contrib/lisp/org-registry.el
deleted file mode 100644
index 402ce30..0000000
--- a/contrib/lisp/org-registry.el
+++ /dev/null
@@ -1,272 +0,0 @@
-;;; org-registry.el --- a registry for Org links
-;;
-;; Copyright 2007-2014 Bastien Guerry
-;;
-;; Emacs Lisp Archive Entry
-;; Filename: org-registry.el
-;; Version: 0.1a
-;; Author: Bastien Guerry <bzg@gnu.org>
-;; Maintainer: Bastien Guerry <bzg@gnu.org>
-;; Keywords: org, wp, registry
-;; Description: Shows Org files where the current buffer is linked
-;; URL: http://www.cognition.ens.fr/~guerry/u/org-registry.el
-;;
-;; This file is not 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, 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:
-;;
-;; This library add a registry to your Org setup.
-;;
-;; Org files are full of links inserted with `org-store-link'. This links
-;; point to e-mail, webpages, files, dirs, info pages, man pages, etc.
-;; Actually, they come from potentially *everywhere* since Org lets you
-;; define your own storing/following functions.
-;;
-;; So, what if you are on a e-mail, webpage or whatever and want to know if
-;; this buffer has already been linked to somewhere in your agenda files?
-;;
-;; This is were org-registry comes in handy.
-;;
-;;     M-x org-registry-show will tell you the name of the file
-;; C-u M-x org-registry-show will directly jump to the file
-;;
-;; In case there are several files where the link lives in:
-;;
-;;     M-x org-registry-show will display them in a new window
-;; C-u M-x org-registry-show will prompt for a file to visit
-;;
-;; Add this to your Org configuration:
-;;
-;; (require 'org-registry)
-;; (org-registry-initialize)
-;;
-;; If you want to update the registry with newly inserted links in the
-;; current buffer: M-x org-registry-update
-;;
-;; If you want this job to be done each time you save an Org buffer,
-;; hook 'org-registry-update to the local 'after-save-hook in org-mode:
-;;
-;; (org-registry-insinuate)
-
-;;; Code:
-
-(eval-when-compile
-  (require 'cl))
-
-(defgroup org-registry nil
-  "A registry for Org."
-  :group 'org)
-
-(defcustom org-registry-file
-  (concat (getenv "HOME") "/.org-registry.el")
-  "The Org registry file."
-  :group 'org-registry
-  :type 'file)
-
-(defcustom org-registry-find-file 'find-file-other-window
-  "How to find visit files."
-  :type 'function
-  :group 'org-registry)
-
-(defvar org-registry-alist nil
-  "An alist containing the Org registry.")
-
-;;;###autoload
-(defun org-registry-show (&optional visit)
-  "Show Org files where there are links pointing to the current
-buffer."
-  (interactive "P")
-  (org-registry-initialize)
-  (let* ((blink (or (org-remember-annotation) ""))
-        (link (when (string-match org-bracket-link-regexp blink)
-                (match-string-no-properties 1 blink)))
-        (desc (or (and (string-match org-bracket-link-regexp blink)
-                       (match-string-no-properties 3 blink)) "No description"))
-        (files (org-registry-assoc-all link))
-        file point selection tmphist)
-    (cond ((and files visit)
-          ;; result(s) to visit
-          (cond ((< 1 (length files))
-                 ;; more than one result
-                 (setq tmphist (mapcar (lambda(entry)
-                                         (format "%s (%d) [%s]"
-                                                 (nth 3 entry) ; file
-                                                 (nth 2 entry) ; point
-                                                 (nth 1 entry))) files))
-                 (setq selection (completing-read "File: " tmphist
-                                                  nil t nil 'tmphist))
-                 (string-match "\\(.+\\) (\\([0-9]+\\))" selection)
-                 (setq file (match-string 1 selection))
-                 (setq point (string-to-number (match-string 2 selection))))
-                ((eq 1 (length files))
-                 ;; just one result
-                 (setq file (nth 3 (car files)))
-                 (setq point (nth 2 (car files)))))
-          ;; visit the (selected) file
-          (funcall org-registry-find-file file)
-          (goto-char point)
-          (unless (org-before-first-heading-p)
-            (org-show-context)))
-         ((and files (not visit))
-          ;; result(s) to display
-          (cond  ((eq 1 (length files))
-                  ;; show one file
-                  (message "Link in file %s (%d) [%s]"
-                           (nth 3 (car files))
-                           (nth 2 (car files))
-                           (nth 1 (car files))))
-                 (t (org-registry-display-files files link))))
-         (t (message "No link to this in org-agenda-files")))))
-
-(defun org-registry-display-files (files link)
-  "Display files in a separate window."
-  (switch-to-buffer-other-window
-   (get-buffer-create " *Org registry info*"))
-  (erase-buffer)
-  (insert (format "Files pointing to %s:\n\n" link))
-  (let (file)
-    (while (setq file (pop files))
-      (insert (format "%s (%d) [%s]\n" (nth 3 file)
-                     (nth 2 file) (nth 1 file)))))
-  (shrink-window-if-larger-than-buffer)
-  (other-window 1))
-
-(defun org-registry-assoc-all (link &optional registry)
-  "Return all associated entries of LINK in the registry."
-  (org-registry-find-all
-   (lambda (entry) (string= link (car entry)))
-   registry))
-
-(defun org-registry-find-all (test &optional registry)
-  "Return all entries satisfying `test' in the registry."
-  (delq nil
-        (mapcar
-         (lambda (x) (and (funcall test x) x))
-         (or registry org-registry-alist))))
-
-;;;###autoload
-(defun org-registry-visit ()
-  "If an Org file contains a link to the current location, visit
-this file."
-  (interactive)
-  (org-registry-show t))
-
-;;;###autoload
-(defun org-registry-initialize (&optional from-scratch)
-  "Initialize `org-registry-alist'.
-If FROM-SCRATCH is non-nil or the registry does not exist yet,
-create a new registry from scratch and eval it. If the registry
-exists, eval `org-registry-file' and make it the new value for
-`org-registry-alist'."
-  (interactive "P")
-  (if (or from-scratch (not (file-exists-p org-registry-file)))
-      ;; create a new registry
-      (let ((files org-agenda-files) file)
-       (while (setq file (pop files))
-         (setq file (expand-file-name file))
-         (mapc (lambda (entry)
-                 (add-to-list 'org-registry-alist entry))
-               (org-registry-get-entries file)))
-       (when from-scratch
-         (org-registry-create org-registry-alist)))
-    ;; eval the registry file
-    (with-temp-buffer
-      (insert-file-contents org-registry-file)
-      (eval-buffer))))
-
-;;;###autoload
-(defun org-registry-insinuate ()
-  "Call `org-registry-update' after saving in Org-mode.
-Use with caution.  This could slow down things a bit."
-  (interactive)
-  (add-hook 'org-mode-hook
-           (lambda() (add-hook 'after-save-hook
-                               'org-registry-update t t))))
-
-(defun org-registry-get-entries (file)
-  "List Org links in FILE that will be put in the registry."
-  (let (bufstr result)
-    (with-temp-buffer
-      (insert-file-contents file)
-      (goto-char (point-min))
-      (while (re-search-forward org-angle-link-re nil t)
-       (let* ((point (match-beginning 0))
-              (link (match-string-no-properties 0))
-              (desc (match-string-no-properties 0)))
-           (add-to-list 'result (list link desc point file))))
-      (goto-char (point-min))
-      (while (re-search-forward org-bracket-link-regexp nil t)
-       (let* ((point (match-beginning 0))
-              (link (match-string-no-properties 1))
-              (desc (or (match-string-no-properties 3) "No description")))
-           (add-to-list 'result (list link desc point file)))))
-    ;; return the list of new entries
-    result))
-
-;;;###autoload
-(defun org-registry-update ()
-  "Update the registry for the current Org file."
-  (interactive)
-  (unless (eq major-mode 'org-mode) (error "Not in org-mode"))
-  (let* ((from-file (expand-file-name (buffer-file-name)))
-        (new-entries (org-registry-get-entries from-file)))
-    (with-temp-buffer
-      (unless (file-exists-p org-registry-file)
-       (org-registry-initialize t))
-      (find-file org-registry-file)
-      (goto-char (point-min))
-      (while (re-search-forward (concat from-file "\")$") nil t)
-       (let ((end (1+ (match-end 0)))
-             (beg (progn (re-search-backward "^(\"" nil t)
-                         (match-beginning 0))))
-       (delete-region beg end)))
-      (goto-char (point-min))
-      (re-search-forward "^(\"" nil t)
-      (goto-char (match-beginning 0))
-      (mapc (lambda (elem)
-             (insert (with-output-to-string (prin1 elem)) "\n"))
-           new-entries)
-      (save-buffer)
-      (kill-buffer (current-buffer)))
-    (message (format "Org registry updated for %s"
-                    (file-name-nondirectory from-file)))))
-
-(defun org-registry-create (entries)
-  "Create `org-registry-file' with ENTRIES."
-  (let (entry)
-    (with-temp-buffer
-      (find-file org-registry-file)
-      (erase-buffer)
-      (insert
-       (with-output-to-string
-        (princ ";; -*- emacs-lisp -*-\n")
-        (princ ";; Org registry\n")
-        (princ ";; You shouldn't try to modify this buffer manually\n\n")
-        (princ "(setq org-registry-alist\n'(\n")
-        (while entries
-          (when (setq entry (pop entries))
-            (prin1 entry)
-            (princ "\n")))
-        (princ "))\n")))
-      (save-buffer)
-      (kill-buffer (current-buffer))))
-  (message "Org registry created"))
-
-(provide 'org-registry)
-
-;;;  User Options, Variables
-
-;;; org-registry.el ends here
diff --git a/contrib/lisp/org-screen.el b/contrib/lisp/org-screen.el
deleted file mode 100644
index 948e93a..0000000
--- a/contrib/lisp/org-screen.el
+++ /dev/null
@@ -1,106 +0,0 @@
-;;; org-screen.el --- Integreate Org-mode with screen.
-
-;; Copyright (c) 2008-2014 Andrew Hyatt
-;;
-;; Author: Andrew Hyatt <ahyatt at gmail dot com>
-;; Maintainer: Carsten Dominik <carsten at orgmode dot org>
-;;
-;; This file is not yet 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, 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:
-;;
-;; This file contains functionality to integrate screen and org-mode.
-;; When using org-mode, it is often useful to take tasks that have
-;; some command-line work associated with them, and associate them
-;; with a screen session.  Screen is used rather than a direct
-;; terminal to facilitate portability of the resulting session.
-;;
-;; To use screen in org, in your .emacs file, simply put this file in
-;; a directory in your load-path and write:
-;;
-;; (require 'org-screen)
-;;
-;; When have a task and want to start some command-line activity
-;; associated with that task, go to the end of your item and type:
-;;
-;; M-x org-screen
-;;
-;; This will prompt you for a name of a screen session.  Type in a
-;; name and it will insert a link into your org file at your current
-;; location.
-;;
-;; When you want to visit the link, go to the link and type C-c C-o to
-;; open the link.
-;;
-;; You may want to get rid of the constant queries about whether you
-;; really want to execute lisp code.  Do so by adding to your .emacs:
-;;
-;; (setq org-confirm-elisp-link-function nil)
-
-(require 'term)
-(require 'org)
-
-(defcustom org-screen-program-name "/usr/bin/screen"
-  "Full location of the screen executable."
-  :group 'org-screen
-  :type 'string)
-
-(defun org-screen (name)
-  "Start a screen session with name"
-  (interactive "MScreen name: ")
-  (save-excursion
-    (org-screen-helper name "-S"))
-  (insert (concat "[[screen:" name "]]")))
-
-(defun org-screen-buffer-name (name)
-  "Returns the buffer name corresponding to the screen name given."
-  (concat "*screen " name "*"))
-
-(defun org-screen-helper (name arg)
-  "This method will create a screen session with a specified name
-and taking the specified screen arguments.  Much of this function
-is copied from ansi-term method."
-
-  ;; Pick the name of the new buffer.
-  (let ((term-ansi-buffer-name
-        (generate-new-buffer-name
-         (org-screen-buffer-name name))))
-    (setq term-ansi-buffer-name
-          (term-ansi-make-term
-          term-ansi-buffer-name org-screen-program-name nil arg name))
-    (set-buffer term-ansi-buffer-name)
-    (term-mode)
-    (term-char-mode)
-    (term-set-escape-char ?\C-x)
-    term-ansi-buffer-name))
-
-(defun org-screen-goto (name)
-  "Open the screen with the specified name in the window"
-  (interactive "MScreen name: ")
-  (let ((screen-buffer-name (org-screen-buffer-name name)))
-    (if (member screen-buffer-name
-                (mapcar 'buffer-name (buffer-list)))
-        (org-pop-to-buffer-same-window screen-buffer-name)
-      (org-pop-to-buffer-same-window (org-screen-helper name "-dr")))))
-
-(if org-link-abbrev-alist
-    (add-to-list 'org-link-abbrev-alist
-                '("screen" . "elisp:(org-screen-goto \"%s\")"))
-  (setq org-link-abbrev-alist
-       '(("screen" . "elisp:(org-screen-goto \"%s\")"))))
-
-(provide 'org-screen)
diff --git a/contrib/lisp/org-screenshot.el b/contrib/lisp/org-screenshot.el
deleted file mode 100644
index f9512ee..0000000
--- a/contrib/lisp/org-screenshot.el
+++ /dev/null
@@ -1,529 +0,0 @@
-;;; org-screenshot.el --- Take and manage screenshots in Org-mode files
-;;
-;; Copyright (C) 2009-2021 Free Software Foundation, Inc.
-;;
-;; Author: Max Mikhanosha <max@openchat.com>
-;; Keywords: outlines, hypermedia, calendar, wp
-;; Homepage: https://orgmode.org
-;; Version: 8.0
-;;
-;; Released under the GNU General Public License version 3
-;; see: http://www.gnu.org/licenses/gpl-3.0.html
-;;
-;; This file is not 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:
-;;
-;; NOTE: This library requires external screenshot taking executable "scrot",
-;; which is available as a package from all major Linux distribution. If your
-;; distribution does not have it, source can be found at:
-;; 
-;; http://freecode.com/projects/scrot
-;;
-;; org-screenshot.el have been tested with scrot version 0.8.
-;; 
-;; Usage:
-;;
-;;   (require 'org-screenshot)
-;;
-;;  Available commands with default bindings
-;;
-;;  `org-screenshot-take'              C-c M-s M-t  and   C-c M-s M-s
-;;  
-;;        Take the screenshot, C-u argument delays 1 second, double C-u 2 
seconds
-;;        triple C-u 3 seconds, and subsequent C-u add 2 seconds to the delay.
-;;
-;;        Screenshot area is selected with the mouse, or left-click on the 
window
-;;        for an entire window.
-;;        
-;;  `org-screenshot-rotate-prev'       C-c M-s M-p   and C-c M-s C-p
-;;  
-;;        Rotate screenshot before the point to one before it (sorted by date)
-;;        
-;;  `org-screenshot-rotate-next'       C-c M-s M-n   and C-c M-s C-n
-;;
-;;        Rotate screenshot before the point to one after it
-;;
-;;  `org-screenshot-show-unused'       C-c M-s M-u   and C-c M-s u
-;;
-;;        Open dired buffer with screenshots that are not used in current
-;;        Org buffer marked
-;;
-;; The screenshot take and rotate commands will update the inline images
-;; if they are already shown, if you are inserting first screenshot in the Org
-;; Buffer (and there are no other images shown), you need to manually display
-;; inline images with C-c C-x C-v
-;;
-;; Screenshot take and rotate commands offer user to continue by by using 
single
-;; keys, in a manner similar to to "repeat-char" of keyboard macros, user can
-;; continue rotating screenshots by pressing just the last key of the binding
-;;
-;; For example: C-c M-s M-t creates the screenshot and then user can
-;; repeatedly press M-p or M-n to rotate it back and forth with
-;; previously taken ones.
-;;
-
-(require 'org)
-(require 'dired)
-
-(defgroup org-screenshot nil
-  "Options for taking and managing screen-shots"
-  :group 'org-link)
-
-(defcustom org-screenshot-image-directory "./images/"
-  "Directory in which screenshot image files will be stored, it
-be automatically created if it doesn't already exist."
-  :type 'string
-  :group 'org-screenshot)
-
-(defcustom org-screenshot-file-name-format "screenshot-%2.2d.png"
-  "The string used to generate screenshot file name. 
-
-Any %d format string recipe will be expanded with `format'
-function with the argument of a screenshot sequence number.
-
-A sequence like %XXXX will be replaced with string of the same
-length as there are X's, consisting of random characters in the
-range of [A-Za-z]."
-  :type 'string
-  :group 'org-screenshot)
-
-(defcustom org-screenshot-max-tries 200
-  "Number of times we will try to generate generate filename that
-does not exist. With default `org-screenshot-name-format' its the
-limit for number of screenshots, before `org-screenshot-take' is
-unable to come up with a unique name."
-  :type 'integer
-  :group 'org-screenshot)
-
-(defvar org-screenshot-map (make-sparse-keymap)
-  "Map for OrgMode screenshot related commands")
-
-;; prefix
-(org-defkey org-mode-map (kbd "C-c M-s") org-screenshot-map)
-
-;; Mnemonic is Control-C Meta "Screenshot" "Take"
-(org-defkey org-screenshot-map (kbd "M-t") 'org-screenshot-take)
-(org-defkey org-screenshot-map (kbd "M-s") 'org-screenshot-take)
-
-;; No reason to require meta key, since its our own keymap
-(org-defkey org-screenshot-map "s" 'org-screenshot-take)
-(org-defkey org-screenshot-map "t" 'org-screenshot-take)
-
-;; Rotations, the fast rotation user hint, would prefer the modifier
-;; used by the original command that started the rotation
-(org-defkey org-screenshot-map (kbd "M-n") 'org-screenshot-rotate-next)
-(org-defkey org-screenshot-map (kbd "M-p") 'org-screenshot-rotate-prev)
-(org-defkey org-screenshot-map (kbd "C-n") 'org-screenshot-rotate-next)
-(org-defkey org-screenshot-map (kbd "C-p") 'org-screenshot-rotate-prev)
-
-;; Show unused image files in Dired
-(org-defkey org-screenshot-map (kbd "M-u") 'org-screenshot-show-unused)
-(org-defkey org-screenshot-map (kbd "u") 'org-screenshot-show-unused)
-
-
-(random t)
-
-(defun org-screenshot-random-string (length)
-  "Generate a random string of LENGTH consisting of random upper
-case and lower case letters."
-  (let ((name (make-string length ?x)))
-    (dotimes (i length)
-      (let ((n (random 52)))
-        (aset name i (if (< n 26)
-                         (+ ?a n)
-                       (+ ?A n -26))))) 
-    name))
-
-(defvar org-screenshot-process nil
-  "Currently running screenshot process")
-
-(defvar org-screenshot-directory-seq-numbers (make-hash-table :test 'equal))
-
-(defun org-screenshot-update-seq-number (directory &optional reset)
-  "Set `org-screenshot-file-name-format' sequence number for the directory.
-When RESET is NIL, increments the number stored, otherwise sets
-RESET as a new number. Intended to be called if screenshot was
-successful.  Updating of sequence number is done in two steps, so
-aborted/canceled screenshot attempts don't increase the number"
-
-  (setq directory (file-name-as-directory directory))
-  (puthash directory (if reset
-                         (if (numberp reset) reset 1)
-                       (1+ (gethash directory
-                                    org-screenshot-directory-seq-numbers
-                                    0)))
-           org-screenshot-directory-seq-numbers))
-
-(defun org-screenshot-generate-file-name (directory)
-  "Use `org-screenshot-name-format' to generate new screenshot
-file name for a specific directory. Keeps re-generating name if
-it already exists, up to `org-screenshot-max-tries'
-times. Returns just the file, without directory part"
-  (setq directory (file-name-as-directory directory))
-  (when (file-exists-p directory)
-    (let ((tries 0)
-          name
-          had-seq
-          (case-fold-search nil))
-      (while (and (< tries org-screenshot-max-tries)
-                  (not name))
-        (incf tries)
-        (let ((tmp org-screenshot-file-name-format)
-              (seq-re "%[-0-9.]*d")
-              (rand-re "%X+"))
-          (when (string-match seq-re tmp)
-            (let ((seq (gethash
-                        directory
-                        org-screenshot-directory-seq-numbers 1))) 
-              (setq tmp 
-                    (replace-regexp-in-string
-                     seq-re (format (match-string 0 tmp) seq)
-                     tmp)
-                    had-seq t)))
-          (when (string-match rand-re tmp)
-            (setq tmp
-                  (replace-regexp-in-string
-                   rand-re (org-screenshot-random-string
-                            (1- (length (match-string 0 tmp))))
-                   tmp t)))
-          (let ((fullname (concat directory tmp))) 
-            (if (file-exists-p fullname)
-                (when had-seq (org-screenshot-update-seq-number directory))
-              (setq name tmp)))))
-      name)))
-
-(defun org-screenshot-image-directory ()
-  "Return the `org-screenshot-image-directory', ensuring there is
-trailing slash, and that it exists"
-  (let ((dir (file-name-as-directory org-screenshot-image-directory)))
-    (if (file-exists-p dir)
-        dir
-      (make-directory dir t)
-      dir)))
-
-(defvar org-screenshot-last-file nil
-  "File name of the last taken or rotated screenshot file,
-without directory")
-
-(defun org-screenshot-process-done (process event file
-                                            orig-buffer
-                                            orig-delay
-                                            orig-event)
-  "Called when \"scrot\" process exits. PROCESS and EVENT are
-same arguments as in `set-process-sentinel'.  ORIG-BUFFER,
-ORIG-DELAY and ORIG-EVENT are Org Buffer, the screenshot delay
-used, and LAST-INPUT-EVENT values from when screenshot was
-initiated.
-"
-  (setq org-screenshot-process nil)
-  (with-current-buffer (process-buffer process) 
-    (if (not (equal event "finished\n"))
-        (progn 
-          (insert event) 
-          (cond ((save-excursion
-                   (goto-char (point-min))
-                   (re-search-forward "Key was pressed" nil t))
-                 (ding)
-                 (message "Key was pressed, screenshot aborted"))
-                (t 
-                 (display-buffer (process-buffer process))
-                 (message "Error running \"scrot\" program")
-                 (ding))))
-      (with-current-buffer orig-buffer 
-        (let ((link (format "[[file:%s]]" file))) 
-          (setq org-screenshot-last-file (file-name-nondirectory file))
-          (let ((beg (point)))
-            (insert link) 
-            (when org-inline-image-overlays
-              (org-display-inline-images nil t beg (point))))
-          (unless (< orig-delay 3)
-            (ding))
-          (org-screenshot-rotate-continue t orig-event))))))
-
-
-;;;###autoload
-(defun org-screenshot-take (&optional delay)
-  "Take a screenshot and insert link to it at point, if image
-display is already on (see \\[org-toggle-inline-images])
-screenshot will be displayed as an image
-
-Screen area for the screenshot is selected with the mouse, left
-click on a window screenshots that window, while left click and
-drag selects a region. Pressing any key cancels the screen shot
-
-With `C-u' universal argument waits one second after target is
-selected before taking the screenshot. With double `C-u' wait two
-seconds.
-
-With triple `C-u' wait 3 seconds, and also rings the bell when
-screenshot is done, any more `C-u' after that increases delay by
-2 seconds
-"
-  (interactive "P")
-
-  ;; probably easier way to count number of C-u C-u out there
-  (setq delay
-        (cond ((null delay) 0)
-              ((integerp delay) delay)
-              ((and (consp delay)
-                    (integerp (car delay))
-                    (plusp (car delay)))
-               (let ((num 1)
-                     (limit (car delay))
-                     (cnt 0))
-                 (while (< num limit)
-                   (setq num (* num 4)
-                         cnt (+ cnt (if (< cnt 3) 1 2))))
-                 cnt))
-              (t (error "Invalid delay"))))
-  (when (and org-screenshot-process
-             (member (process-status org-screenshot-process)
-                     '(run stop)))
-    (error "scrot process is still running"))
-  (let* ((name (org-screenshot-generate-file-name 
(org-screenshot-image-directory)))
-         (file (format "%s%s" (org-screenshot-image-directory)
-                       name))
-         (path (expand-file-name file)))
-    (when (get-buffer "*scrot*")
-      (with-current-buffer (get-buffer "*scrot*")
-        (erase-buffer)))
-    (setq org-screenshot-process
-          (or 
-           (apply 'start-process
-                  (append
-                   (list "scrot" "*scrot*" "scrot" "-s" path)
-                   (when (plusp delay)
-                     (list "-d" (format "%d" delay)))))
-           (error "Unable to start scrot process")))
-    (when org-screenshot-process 
-      (if (plusp delay) 
-          (message "Click on a window, or select a rectangle (delay is %d 
sec)..."
-                   delay)
-        (message "Click on a window, or select a rectangle..."))
-      (set-process-sentinel
-       org-screenshot-process
-       `(lambda (process event)
-          (org-screenshot-process-done
-           process event ,file ,(current-buffer) ,delay 
',last-input-event))))))
-
-(defvar org-screenshot-file-list nil
-  "List of files in `org-screenshot-image-directory' used by
-`org-screenshot-rotate-prev' and `org-screenshot-rotate-next'")
-
-(defvar org-screenshot-rotation-index -1)
-
-(make-variable-buffer-local 'org-screenshot-file-list)
-(make-variable-buffer-local 'org-screenshot-rotation-index)
-
-(defun org-screenshot-rotation-init (lastfile)
-  "Initialize variable `org-screenshot-file-list' variable with
-the list of PNG files in `org-screenshot-image-directory' sorted
-by most recent first"
-  (setq
-   org-screenshot-rotation-index -1
-   org-screenshot-file-list
-   (let ((files (directory-files org-screenshot-image-directory
-                                 t (image-file-name-regexp) t)))
-     (mapcar 'file-name-nondirectory
-             (sort files
-                   (lambda (file1 file2)
-                     (let ((mtime1 (nth 5 (file-attributes file1)))
-                           (mtime2 (nth 5 (file-attributes file2))))
-                       (setq mtime1 (+ (ash (first mtime1) 16)
-                                       (second mtime1)))
-                       (setq mtime2 (+ (ash (first mtime2) 16)
-                                       (second mtime2)))
-                       (> mtime1 mtime2)))))))
-  (let ((n -1) (list org-screenshot-file-list))
-    (while (and list (not (equal (pop list) lastfile)))
-      (incf n))
-    (setq org-screenshot-rotation-index n)))
-
-(defun org-screenshot-do-rotate (dir from-continue-rotating)
-  "Rotate last screenshot with one of the previously taken
-screenshots from the same directory. If DIR is negative, in the
-other direction"
-  (setq org-screenshot-last-file nil)
-  (let* ((ourdir (file-name-as-directory (org-screenshot-image-directory)))
-         done
-         (link-re 
-          ;; taken from `org-display-inline-images'
-          (concat "\\[\\[\\(\\(file:\\)\\|\\([./~]\\)\\)\\([^]\n]+?"
-                  (substring (image-file-name-regexp) 0 -2)
-                  "\\)\\]"))
-         newfile oldfile)
-    (save-excursion 
-      ;; Search for link to image file in the same directory before the point
-      (while (not done)
-        (if (not (re-search-backward link-re (point-min) t))
-            (error "Unable to find link to image from %S directory before 
point" ourdir)
-          (let ((file (concat (or (match-string 3) "") (match-string 4))))
-            (when (equal (file-name-directory file)
-                         ourdir)
-              (setq done t
-                    oldfile (file-name-nondirectory file))))))
-      (when (or (null org-screenshot-file-list)
-                (and (not from-continue-rotating) 
-                     (not (member last-command
-                                  '(org-screenshot-rotate-prev
-                                    org-screenshot-rotate-next)))))
-        (org-screenshot-rotation-init oldfile))
-      (unless (> (length org-screenshot-file-list) 1)
-        (error "Can't rotate a single image file"))
-      (replace-match "" nil nil nil 1)
-
-      (setq org-screenshot-rotation-index
-            (mod (+ org-screenshot-rotation-index dir)
-                 (length org-screenshot-file-list)) 
-            newfile (nth org-screenshot-rotation-index
-                         org-screenshot-file-list))
-      ;; in case we started rotating from the file we just inserted,
-      ;; advance one more time
-      (when (equal oldfile newfile)
-        (setq org-screenshot-rotation-index
-              (mod (+ org-screenshot-rotation-index (if (plusp dir) 1 -1))
-                   (length org-screenshot-file-list))
-              newfile (nth org-screenshot-rotation-index
-                           org-screenshot-file-list)))
-      (replace-match (concat "file:" ourdir
-                             newfile)
-                     t t nil 4))
-    ;; out of save-excursion
-    (setq org-screenshot-last-file newfile)
-    (when org-inline-image-overlays
-      (org-display-inline-images nil t (match-beginning 0) (point)))))
-
-;;;###autoload
-(defun org-screenshot-rotate-prev (dir)
-  "Rotate last screenshot with one of the previously taken
-screenshots from the same directory. If DIR is negative, rotate
-in the other direction"
-  (interactive "p")
-  (org-screenshot-do-rotate dir nil)
-  (when org-screenshot-last-file 
-    (org-screenshot-rotate-continue nil nil)))
-
-;;;###autoload
-(defun org-screenshot-rotate-next (dir)
-  "Rotate last screenshot with one of the previously taken
-screenshots from the same directory. If DIR is negative, rotate
-in the other direction"
-  (interactive "p")
-  (org-screenshot-do-rotate (- dir) nil)
-  (when org-screenshot-last-file 
-    (org-screenshot-rotate-continue nil nil)))
-
-(defun org-screenshot-prefer-same-modifiers (list event)
-  (if (not (eventp nil)) (car list) 
-    (let (ret (keys list))
-      (while (and (null ret) keys)
-        (let ((key (car keys))) 
-          (if (and (= 1 (length key)) 
-                   (equal (event-modifiers event)
-                          (event-modifiers (elt key 0))))
-              (setq ret (car keys))
-            (setq keys (cdr keys)))))
-      (or ret (car list)))))
-
-(defun org-screenshot-rotate-continue (from-take-screenshot orig-event)
-  "Display the message with the name of the last changed
-image-file and inform user that they can rotate by pressing keys
-bound to `org-screenshot-rotate-next' and
-`org-screenshot-rotate-prev' in `org-screenshot-map'
-
-This works similarly to `kmacro-end-or-call-macro' so that user
-can press a long key sequence to invoke the first command, and
-then uses single keys to rotate, until unregognized key is
-entered, at which point event will be unread"
-
-  (let* ((event (if from-take-screenshot orig-event
-                  last-input-event))
-         done
-         (prev-key
-          (org-screenshot-prefer-same-modifiers
-           (where-is-internal 'org-screenshot-rotate-prev
-                              org-screenshot-map nil)
-           event))
-         (next-key
-          (org-screenshot-prefer-same-modifiers
-           (where-is-internal 'org-screenshot-rotate-next
-                              org-screenshot-map nil)
-           event))
-         prev-key-str next-key-str)
-    (when (and (= (length prev-key) 1)
-               (= (length next-key) 1)) 
-      (setq
-       prev-key-str (format-kbd-macro prev-key nil)
-       next-key-str (format-kbd-macro next-key nil)
-       prev-key (elt prev-key 0)
-       next-key (elt next-key 0))
-      (while (not done)
-        (message "%S - '%s' and '%s' to rotate"
-                 org-screenshot-last-file prev-key-str next-key-str)
-        (setq event (read-event))
-        (cond ((equal event prev-key)
-               (clear-this-command-keys t)
-               (org-screenshot-do-rotate 1 t)
-               (setq last-input-event nil))
-              ((equal event next-key)
-               (clear-this-command-keys t)
-               (org-screenshot-do-rotate -1 t)
-               (setq last-input-event nil))
-              (t (setq done t)))) 
-      (when last-input-event
-        (clear-this-command-keys t)
-        (setq unread-command-events (list last-input-event))))))
-
-;;;###autoload
-(defun org-screenshot-show-unused ()
-  "Open A Dired buffer with unused screenshots marked"
-  (interactive)
-  (let ((files-in-buffer)
-       dired-buffer
-       had-any
-       (image-re (image-file-name-regexp))
-       beg end)
-    (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 (image-file-name-regexp) 0 -2)
-                         "\\)\\]"))
-             (case-fold-search t)
-             old file ov img type attrwidth width)
-         (while (re-search-forward re end t)
-           (setq file (concat (or (match-string 3) "") (match-string 4)))
-           (when (and (file-exists-p file)
-                      (equal (file-name-directory file)
-                             (org-screenshot-image-directory)))
-             (push (file-name-nondirectory file)
-                   files-in-buffer))))))
-    (setq dired-buffer (dired-noselect (org-screenshot-image-directory)))
-    (with-current-buffer dired-buffer
-      (dired-unmark-all-files ?\r)
-      (dired-mark-if
-       (let ((file (dired-get-filename 'no-dir t))) 
-        (and file (string-match image-re file)
-             (not (member file files-in-buffer))
-             (setq had-any t)))
-       "Unused screenshot"))
-    (when had-any (pop-to-buffer dired-buffer))))
-
-(provide 'org-screenshot)
diff --git a/contrib/lisp/org-secretary.el b/contrib/lisp/org-secretary.el
deleted file mode 100644
index babfb75..0000000
--- a/contrib/lisp/org-secretary.el
+++ /dev/null
@@ -1,230 +0,0 @@
-;;; org-secretary.el --- Team management with org-mode
-;; Copyright (C) 2010-2014 Juan Reyero
-;;
-;; Author: Juan Reyero <juan _at_ juanreyero _dot_ com>
-;; Keywords: outlines, tasks, team, management
-;; Homepage: http://juanreyero.com/article/emacs/org-teams.html
-;; Version: 0.02
-;;
-;; This file is not part of GNU Emacs.
-;;
-;; This file 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 file 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:
-;;
-;; This module implements helper functions for team management.  It
-;; makes it easy to keep track of the work of several people.  It
-;; keeps context (with whom and where you are) and allows you to use
-;; it to metadata to your notes, and to query the tasks associated
-;; with the people you are with and the place.
-;;
-;; See http://juanreyero.com/article/emacs/org-teams.html for a full
-;; explanation and configuration instructions.
-;;
-;;; Configuration
-;;;;;;;;;;;;;;;;;
-;;
-;; In short; your todos use the TODO keyword, your team's use TASK.
-;; Your org-todo-keywords should look something like this:
-;;
-;; (setq org-todo-keywords
-;;       '((sequence "TODO(t)" "|" "DONE(d)" "CANCELLED(c)")
-;;         (sequence "TASK(f)" "|" "DONE(d)")
-;;         (sequence "MAYBE(m)" "|" "CANCELLED(c)")))
-;;
-;; It helps to distinguish them by color, like this:
-;;
-;; (setq org-todo-keyword-faces
-;;       '(("TODO" . (:foreground "DarkOrange1" :weight bold))
-;;         ("MAYBE" . (:foreground "sea green"))
-;;         ("DONE" . (:foreground "light sea green"))
-;;         ("CANCELLED" . (:foreground "forest green"))
-;;         ("TASK" . (:foreground "blue"))))
-;;
-;; If you want to keep track of stuck projects you should tag your
-;; projects with :prj:, and define:
-;;
-;; (setq org-tags-exclude-from-inheritance '("prj")
-;;       org-stuck-projects '("+prj/-MAYBE-DONE"
-;;                            ("TODO" "TASK") ()))
-;;
-;; Define a tag that marks TASK entries as yours:
-;;
-;; (setq org-sec-me "juanre")
-;;
-;; Finally, you add the special views to your org-agenda-custom-commands:
-;;
-;; (setq org-agenda-custom-commands
-;;       '(("h" "Work todos" tags-todo
-;;          "-personal-doat={.+}-dowith={.+}/!-TASK"
-;;          ((org-agenda-todo-ignore-scheduled t)))
-;;         ("H" "All work todos" tags-todo "-personal/!-TASK-MAYBE"
-;;          ((org-agenda-todo-ignore-scheduled nil)))
-;;         ("A" "Work todos with doat or dowith" tags-todo
-;;          "-personal+doat={.+}|dowith={.+}/!-TASK"
-;;          ((org-agenda-todo-ignore-scheduled nil)))
-;;         ("j" "TODO dowith and TASK with"
-;;          ((org-sec-with-view "TODO dowith")
-;;           (org-sec-where-view "TODO doat")
-;;           (org-sec-assigned-with-view "TASK with")
-;;           (org-sec-stuck-with-view "STUCK with")))
-;;         ("J" "Interactive TODO dowith and TASK with"
-;;          ((org-sec-who-view "TODO dowith")))))
-;;
-;;; Usage
-;;;;;;;;;
-;;
-;;  Do C-c w to say with whom you are meeting (a space-separated list
-;;  of names). Maybe do also C-c W to say where you are.  Then do C-c a
-;;  j to see:
-;;     - Todo items defined with TODO (ie, mine) in which the
-;;       =dowith= property matches any of the people with me.
-;;     - Todo items defined with TODO in which the =doat= property
-;;       matches my current location.
-;;     - Todo items defined with TASK that are tagged with the name
-;;       of any of the people with me (this is, assigned to them).
-;;     - Stuck projects tagged with the name of the people with me.
-;;
-;; Use C-c j to add meta-data with the people with me, the
-;; location and the time to entries.
-
-(require 'org)
-
-(defvar org-sec-me nil
-  "Tag that defines TASK todo entries associated to me")
-
-(defvar org-sec-with nil
-  "Value of the :with: property when doing an
-   org-sec-tag-entry. Change it with org-sec-set-with,
-   set to C-c w.  Defaults to org-sec-me")
-
-(defvar org-sec-where ""
-  "Value of the :at: property when doing an
-   org-sec-tag-entry. Change it with org-sec-set-with,
-   set to C-c W")
-
-(defvar org-sec-with-history '()
-  "History list of :with: properties")
-
-(defvar org-sec-where-history '()
-  "History list of :where: properties")
-
-(defun org-sec-set-with ()
-  "Changes the value of the org-sec-with variable for use in the
-   next call of org-sec-tag-entry.  Leave it empty to default to
-   org-sec-me (you)."
-  (interactive)
-  (setq org-sec-with (let ((w (read-string "With: " nil
-                                           'org-sec-with-history "")))
-                       (if (string= w "")
-                           nil
-                         w))))
-(global-set-key "\C-cw" 'org-sec-set-with)
-
-(defun org-sec-set-where ()
-  "Changes the value of the org-sec-where variable for use
-   in the next call of org-sec-tag-entry."
-  (interactive)
-  (setq org-sec-where
-        (read-string "Where: " nil
-                     'org-sec-where-history "")))
-(global-set-key "\C-cW" 'org-sec-set-where)
-
-(defun org-sec-set-dowith ()
-  "Sets the value of the dowith property."
-  (interactive)
-  (let ((do-with
-         (read-string "Do with: "
-                      nil 'org-sec-dowith-history "")))
-    (unless (string= do-with "")
-      (org-entry-put nil "dowith" do-with))))
-(global-set-key "\C-cd" 'org-sec-set-dowith)
-
-(defun org-sec-set-doat ()
-  "Sets the value of the doat property."
-  (interactive)
-  (let ((do-at (read-string "Do at: "
-                            nil 'org-sec-doat-history "")))
-    (unless (string= do-at "")
-      (org-entry-put nil "doat" do-at))))
-(global-set-key "\C-cD" 'org-sec-set-doat)
-
-(defun org-sec-tag-entry ()
-  "Adds a :with: property with the value of org-sec-with if
-   defined, an :at: property with the value of org-sec-where
-   if defined, and an :on: property with the current time."
-  (interactive)
-  (save-excursion
-    (org-entry-put nil "on" (format-time-string
-                             (org-time-stamp-format 'long)
-                             (current-time)))
-    (unless (string= org-sec-where "")
-      (org-entry-put nil "at" org-sec-where))
-    (if org-sec-with
-        (org-entry-put nil "with" org-sec-with))))
-(global-set-key "\C-cj" 'org-sec-tag-entry)
-
-(defun join (lst sep &optional pre post)
-  (mapconcat (function (lambda (x) (concat pre x post))) lst sep))
-
-(defun org-sec-get-with ()
-  (if org-sec-with
-      org-sec-with
-    org-sec-me))
-
-(defun org-sec-with-view (par &optional who)
-  "Select tasks marked as dowith=who, where who
-   defaults to the value of org-sec-with."
-  (org-tags-view '(4) (join (split-string (if who
-                                              who
-                                            (org-sec-get-with)))
-                            "|" "dowith=\"" "\"")))
-
-(defun org-sec-where-view (par)
-  "Select tasks marked as doat=org-sec-where."
-  (org-tags-view '(4) (concat "doat={" org-sec-where "}")))
-
-(defun org-sec-assigned-with-view (par &optional who)
-  "Select tasks assigned to who, by default org-sec-with."
-  (org-tags-view '(4)
-                 (concat (join (split-string (if who
-                                                 who
-                                               (org-sec-get-with)))
-                               "|")
-                         "/TASK")))
-
-(defun org-sec-stuck-with-view (par &optional who)
-  "Select stuck projects assigned to who, by default
-   org-sec-with."
-  (let ((org-stuck-projects
-         `(,(concat "+prj+"
-                    (join (split-string (if who
-                                            who
-                                          (org-sec-get-with))) "|")
-                    "/-MAYBE-DONE")
-           ("TODO" "TASK") ())))
-    (org-agenda-list-stuck-projects)))
-
-(defun org-sec-who-view (par)
-  "Builds agenda for a given user.  Queried. "
-  (let ((who (read-string "Build todo for user/tag: "
-                          "" "" "")))
-    (org-sec-with-view "TODO dowith" who)
-    (org-sec-assigned-with-view "TASK with" who)
-    (org-sec-stuck-with-view "STUCK with" who)))
-
-(provide 'org-secretary)
-
-;;; org-secretary.el ends here
diff --git a/contrib/lisp/org-static-mathjax.el 
b/contrib/lisp/org-static-mathjax.el
deleted file mode 100644
index ac13ee2..0000000
--- a/contrib/lisp/org-static-mathjax.el
+++ /dev/null
@@ -1,187 +0,0 @@
-;;; org-static-mathjax.el --- Muse-like tags in Org-mode
-;;
-;; Author: Jan Bรถker <jan dot boecker at jboecker dot de>
-
-;; 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:
-;; This elisp code integrates Static MathJax into the
-;; HTML export process of Org-mode.
-;;
-;; The supporting files for this package are in contrib/scripts/staticmathjax
-;; Please read the README.org file in that directory for more information.
-
-;; To use it, evaluate it on startup, add the following to your .emacs:
-
-;; (require 'org-static-mathjax)
-;;
-;; You will then have to customize the following two variables:
-;; - org-static-mathjax-app-ini-path
-;; - org-static-mathjax-local-mathjax-path
-;;
-;; If xulrunner is not in your $PATH, you will also need to customize
-;; org-static-mathjax-xulrunner-path.
-;;
-;; If everything is setup correctly, you can trigger Static MathJax on
-;; export to HTML by adding the following line to your Org file:
-;; #+StaticMathJax: embed-fonts:nil output-file-name:"embedded-math.html"
-;;
-;; You can omit either argument.
-;; embed-fonts defaults to nil. If you do not specify output-file-name,
-;; the exported file is overwritten with the static version.
-;;
-;; If embed-fonts is non-nil, the fonts are embedded directly into the
-;; output file using data: URIs.
-;;
-;; output-file-name specifies the file name of the static version. You
-;; can use any arbitrary lisp form here, for example:
-;; output-file-name:(concat (file-name-sans-extension buffer-file-name) 
"-static.html")
-;;
-;; The StaticMathJax XULRunner application expects a UTF-8 encoded
-;; input file. If the static version displays random characters instead
-;; of your math, add the following line at the top of your Org file:
-;; -*- coding: utf-8; -*-
-;;
-;;; Code:
-
-(defcustom org-static-mathjax-app-ini-path
-  (or (expand-file-name
-       "../scripts/staticmatchjax/application.ini"
-       (file-name-directory (or load-file-name buffer-file-name)))
-      "")
-  "Path to \"application.ini\" of the Static MathJax XULRunner application.
-If you have extracted StaticMathJax to e.g. ~/.local/staticmathjax, set
-this to ~/.local/staticmathjax/application.ini"
-  :type 'string)
-
-(defcustom org-static-mathjax-xulrunner-path
-  "xulrunner"
-  "Path to your xulrunner binary"
-  :type 'string)
-
-(defcustom org-static-mathjax-local-mathjax-path
-  ""
-  "Extract the MathJax zip file somewhere on your local
-hard drive and specify the path here.
-
-The directory has to be writeable, as org-static-mathjax
-creates a temporary file there during export."
-  :type 'string)
-
-(defvar org-static-mathjax-debug
-  nil
-  "If non-nil, org-static-mathjax will print some debug messages")
-
-(defun org-static-mathjax-hook-installer ()
-  "Installs org-static-mathjax-process in after-save-hook.
-
-Sets the following buffer-local variables for org-static-mathjax-process to 
pick up:
-org-static-mathjax-mathjax-path: The path to MathJax.js as used by Org HTML 
export
-org-static-mathjax-options:      The string given with #+STATICMATHJAX: in the 
file"
-  (let ((static-mathjax-option-string (plist-get opt-plist :static-mathjax)))
-       (if static-mathjax-option-string
-               (progn (set (make-local-variable 'org-static-mathjax-options) 
static-mathjax-option-string)
-                          (set (make-local-variable 
'org-static-mathjax-mathjax-path)
-                                       (nth 1 (assq 'path 
org-export-html-mathjax-options)))
-                          (let ((mathjax-options (plist-get opt-plist 
:mathjax)))
-                                (if mathjax-options
-                                        (if (string-match "\\<path:" 
mathjax-options)
-                                                (set 
'org-static-mathjax-mathjax-path
-                                                         (car (read-from-string
-                                                                       
(substring mathjax-options (match-end 0))))))))
-                          (add-hook 'after-save-hook
-                                                'org-static-mathjax-process
-                                                nil t)))))
-
-
-(defun org-static-mathjax-process ()
-  (save-excursion
-       ; some sanity checking
-       (if (or (string= org-static-mathjax-app-ini-path "")
-                       (not (file-exists-p org-static-mathjax-app-ini-path)))
-               (error "Static MathJax: You must customize 
org-static-mathjax-app-ini-path!"))
-       (if (or (string= org-static-mathjax-local-mathjax-path "")
-                       (not (file-exists-p 
org-static-mathjax-local-mathjax-path)))
-               (error "Static MathJax: You must customize 
org-static-mathjax-local-mathjax-path!"))
-
-       ; define variables
-       (let* ((options org-static-mathjax-options)
-                  (output-file-name buffer-file-name)
-                  (input-file-name (let ((temporary-file-directory 
(file-name-directory org-static-mathjax-local-mathjax-path)))
-                                                         (make-temp-file 
"org-static-mathjax-" nil ".html")))
-                  (html-code (buffer-string))
-                  (mathjax-oldpath (concat "src=\"" 
org-static-mathjax-mathjax-path))
-                  (mathjax-newpath (concat "src=\"" 
org-static-mathjax-local-mathjax-path))
-                  embed-fonts)
-         ; read file-local options
-         (mapc
-          (lambda (symbol)
-                (if (string-match (concat "\\<" (symbol-name symbol) ":") 
options)
-                        (set symbol (eval (car (read-from-string
-                                                                        
(substring options (match-end 0))))))))
-          '(embed-fonts output-file-name))
-
-         ; debug
-         (when org-static-mathjax-debug
-               (message "output file name, embed-fonts")
-               (print output-file-name)
-               (print embed-fonts))
-
-         ; open (temporary) input file, copy contents there, replace MathJax 
path with local installation
-         (with-temp-buffer
-               (insert html-code)
-               (goto-char 1)
-               (replace-regexp mathjax-oldpath mathjax-newpath)
-               (write-file input-file-name))
-
-         ; prepare argument list for call-process
-         (let ((call-process-args (list org-static-mathjax-xulrunner-path
-                                                                        nil 
nil nil
-                                                                        
org-static-mathjax-app-ini-path
-                                                                        
input-file-name
-                                                                        
output-file-name)))
-               ; if fonts are embedded, just append the --embed-fonts flag
-               (if embed-fonts
-                       (add-to-list 'call-process-args "--embed-fonts" t))
-               ; if fonts are not embedded, the XULRunner app must replace all 
references
-               ; to the font files with the real location (Firefox inserts 
file:// URLs there,
-               ; because we are using a local MathJax installation here)
-               (if (not embed-fonts)
-                       (progn
-                         (add-to-list 'call-process-args "--final-mathjax-url" 
t)
-                         (add-to-list 'call-process-args
-                                                  (file-name-directory 
org-static-mathjax-mathjax-path)
-                                                  t)))
-
-               ; debug
-               (when org-static-mathjax-debug
-                 (print call-process-args))
-               ; call it
-               (apply 'call-process call-process-args)
-               ; delete our temporary input file
-               (kill-buffer)
-               (delete-file input-file-name)
-               (let ((backup-file (concat input-file-name "~")))
-                 (if (file-exists-p backup-file)
-                         (delete-file backup-file)))))))
-
-(add-to-list 'org-export-inbuffer-options-extra
-'("STATICMATHJAX" :static-mathjax))
-
-(add-hook 'org-export-html-final-hook 'org-static-mathjax-hook-installer)
-
-
-(provide 'org-static-mathjax)
diff --git a/contrib/lisp/org-sudoku.el b/contrib/lisp/org-sudoku.el
deleted file mode 100644
index fd70763..0000000
--- a/contrib/lisp/org-sudoku.el
+++ /dev/null
@@ -1,288 +0,0 @@
-;;; org-sudoku.el --- Create and solve SUDOKU games in Org tables
-
-;; Copyright (C) 2012-2021 Free Software Foundation, Inc.
-;;
-;; Author: Carsten Dominik <carsten at orgmode dot org>
-;; Keywords: outlines, hypermedia, calendar, wp, games
-;; Homepage: https://orgmode.org
-;; Version: 0.01
-;;
-;; This file is not yet 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, 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:
-;;
-;; This is a quick hack to create and solve SUDOKU games in org tables.
-;;
-;; Commands:
-;;
-;; org-sudoku-create         Create a new SUDOKU game
-;; org-sudoku-solve-field    Solve the field at point in a SUDOKU game
-;;                           (this is for cheeting when you are stuck)
-;; org-sudoku-solve          Solve the entire game
-;;
-
-;;; Code
-
-(require 'org)
-(require 'org-table)
-
-;;; Customization
-
-(defvar org-sudoku-size 9
-  "The size of the sudoku game, 9 for a 9x9 game and 4 for a 4x4 game.
-Larger games do not seem to work because of limited resources - even though
-the algorithm is general.")
-
-(defvar org-sudoku-timeout 2.0
-  "Timeout for finding a solution when creating a new game.
-After this timeout, the program starts over from scratch to create
-a game.")
-
-;;; Interactive commands
-
-(defun org-sudoku-create (nfilled)
-  "Create a sudoku game."
-  (interactive "nNumber of pre-filled fields: ")
-  (let ((sizesq org-sudoku-size)
-       game)
-    (loop for i from 1 to org-sudoku-size do
-         (loop for j from 1 to org-sudoku-size do
-               (push (list (cons i j) 0) game)))
-    (setq game (nreverse game))
-    (random t)
-    (setq game (org-sudoku-build-allowed game))
-    (setq game (org-sudoku-set-field game (cons 1 1)
-                                    (1+ (random org-sudoku-size))))
-    (catch 'solved
-      (let ((cnt 0))
-       (while t
-         (catch 'abort
-           (message "Attempt %d to create a game" (setq cnt (1+ cnt)))
-           (setq game1 (org-sudoku-deep-copy game))
-           (setq game1 (org-sudoku-solve-game
-                        game1 'random (+ (float-time) org-sudoku-timeout)))
-           (when game1
-             (setq game game1)
-             (throw 'solved t))))))
-    (let ((sqrtsize (floor (sqrt org-sudoku-size))))
-      (loop for i from 1 to org-sudoku-size do
-           (insert "| |\n")
-           (if (and (= (mod i sqrtsize) 0) (< i org-sudoku-size))
-               (insert "|-\n")))
-      (backward-char 5)
-      (org-table-align))
-    (while (> (length game) nfilled)
-      (setq game (delete (nth (1+ (random (length game))) game) game)))
-    (mapc (lambda (e)
-           (org-table-put (caar e) (cdar e) (int-to-string (nth 1 e))))
-         game)
-    (org-table-align)
-    (org-table-goto-line 1)
-    (org-table-goto-column 1)
-    (message "Enjoy!")))
-
-(defun org-sudoku-solve ()
-  "Solve the sudoku game in the table at point."
-  (interactive)
-  (unless (org-at-table-p)
-    (error "not at a table"))
-  (let (game)
-    (setq game (org-sudoku-get-game))
-    (setq game (org-sudoku-build-allowed game))
-    (setq game (org-sudoku-solve-game game))
-    ;; Insert the values
-    (mapc (lambda (e)
-           (org-table-put (caar e) (cdar e) (int-to-string (nth 1 e))))
-         game)
-    (org-table-align)))
-
-(defun org-sudoku-solve-field ()
-  "Just solve the field at point.
-This works by solving the whole game, then inserting only the single field."
-  (interactive)
-  (unless (org-at-table-p)
-    (error "Not at a table"))
-  (org-table-check-inside-data-field)
-  (let ((i (org-table-current-dline))
-       (j (org-table-current-column))
-       game)
-    (setq game (org-sudoku-get-game))
-    (setq game (org-sudoku-build-allowed game))
-    (setq game (org-sudoku-solve-game game))
-    (if game
-       (progn
-         (org-table-put i j (number-to-string
-                             (nth 1 (assoc (cons i j) game)))
-                        'align)
-         (org-table-goto-line i)
-         (org-table-goto-column j))
-      (error "No solution"))))
-
-;;; Internal functions
-
-(defun org-sudoku-get-game ()
-  "Interpret table at point as sudoku game and read it.
-A game structure is returned."
-  (let (b e g i j game)
-
-    (org-table-goto-line 1)
-    (org-table-goto-column 1)
-    (setq b (point))
-    (org-table-goto-line org-sudoku-size)
-    (org-table-goto-column org-sudoku-size)
-    (setq e (point))
-    (setq g (org-table-copy-region b e))
-    (setq i 0 j 0)
-    (mapc (lambda (c)
-           (setq i (1+ i) j 0)
-           (mapc
-            (lambda (v)
-              (setq j (1+ j))
-              (push (list (cons i j)
-                          (string-to-number v))
-                    game))
-            c))
-         g)
-    (nreverse game)))
-
-(defun org-sudoku-build-allowed (game)
-  (let (i j v numbers)
-    (loop for i from 1 to org-sudoku-size do
-         (push i numbers))
-    (setq numbers (nreverse numbers))
-    ;; add the lists of allowed values for each entry
-    (setq game (mapcar
-               (lambda (e)
-                 (list (car e) (nth 1 e)
-                       (if (= (nth 1 e) 0)
-                           (copy-sequence numbers)
-                         nil)))
-               game))
-    ;; remove the known values from the list of allowed values
-    (mapc
-     (lambda (e)
-       (setq i (caar e) j (cdar e) v (cadr e))
-       (when (> v 0)
-        ;; We do have a value here
-        (mapc
-         (lambda (f)
-           (setq a (assoc f game))
-           (setf (nth 2 a) (delete v (nth 2 a))))
-         (cons (cons i j) (org-sudoku-rel-fields i j)))))
-     game)
-    game))
-
-(defun org-sudoku-find-next-constrained-field (game)
-  (setq game (mapcar (lambda (e) (if (nth 2 e) e nil)) game))
-  (setq game (delq nil game))
-  (let (va vb la lb)
-    (setq game
-         (sort game (lambda (a b)
-                      (setq va (nth 1 a) vb (nth 1 b)
-                            la (length (nth 2 a)) lb (length (nth 2 b)))
-                      (cond
-                       ((and (= va 0) (> vb 0)) t)
-                       ((and (> va 0) (= vb 0)) nil)
-                       ((not (= (* va vb) 0)) nil)
-                       (t (< la lb))))))
-    (if (or (not game) (> 0 (nth 1 (car game))))
-       nil
-      (caar game))))
-
-(defun org-sudoku-solve-game (game &optional random stop-at)
-  "Solve GAME.
-If RANDOM is non-nit, select candidates randomly from a fields option.
-If RANDOM is nil, always start with the first allowed value and try
-solving from there.
-STOP-AT can be a float time, the solver will abort at that time because
-it is probably stuck."
-  (let (e v v1 allowed next g)
-    (when (and stop-at
-              (> (float-time) stop-at))
-      (setq game nil)
-      (throw 'abort nil))
-    (while (setq next (org-sudoku-find-next-constrained-field game))
-      (setq e (assoc next game)
-           v (nth 1 e)
-           allowed (nth 2 e))
-      (catch 'solved
-       (if (= (length allowed) 1)
-           (setq game (org-sudoku-set-field game next (car allowed)))
-         (while allowed
-           (setq g (org-sudoku-deep-copy game))
-           (if (not random)
-               (setq v1 (car allowed))
-             (setq v1 (nth (random (length allowed)) allowed)))
-           (setq g (org-sudoku-set-field g next v1))
-           (setq g (org-sudoku-solve-game g random stop-at))
-           (when g
-             (setq game g)
-             (throw 'solved g)))
-         (setq game nil))))
-    (if (or (not game)
-           (org-sudoku-unknown-field-p game))
-       nil
-      game)))
-
-(defun org-sudoku-unknown-field-p (game)
-  "Are there still unknown fields in the game?"
-  (delq nil (mapcar (lambda (e) (if (> (nth 1 e) 0) nil t)) game)))
-
-(defun org-sudoku-deep-copy (game)
-  "Make a copy of the game so that manipulating the copy does not change the 
parent."
-  (mapcar (lambda(e)
-           (list (car e) (nth 1 e) (copy-sequence (nth 2 e))))
-         game))
-
-(defun org-sudoku-set-field (game field value)
-  "Put VALUE into FIELD, and tell related fields that they cannot be VALUE."
-  (let (i j)
-    (setq i (car field) j (cdr field))
-    (setq a (assoc field game))
-    (setf (nth 1 a) value)
-    (setf (nth 2 a) nil)
-
-    ;; Remove value from all related fields
-    (mapc
-     (lambda (f)
-       (setq a (assoc f game))
-       (setf (nth 2 a) (delete value (nth 2 a))))
-     (org-sudoku-rel-fields i j))
-    game))
-
-(defun org-sudoku-rel-fields (i j)
-  "Compute the list of related fields for field (i j)."
-  (let ((sqrtsize (floor (sqrt org-sudoku-size)))
-       ll imin imax jmin jmax f)
-    (setq f (cons i j))
-    (loop for ii from 1 to org-sudoku-size do
-         (or (= ii i) (push (cons ii j) ll)))
-    (loop for jj from 1 to org-sudoku-size do
-         (or (= jj j) (push (cons i jj) ll)))
-    (setq imin (1+ (* sqrtsize (/ (1- i) sqrtsize)))
-         imax (+ imin sqrtsize -1))
-    (setq jmin (1+ (* sqrtsize (/ (1- j) sqrtsize)))
-         jmax (+ jmin sqrtsize -1))
-    (loop for ii from imin to imax do
-         (loop for jj from jmin to jmax do
-               (setq ff (cons ii jj))
-               (or (equal ff f)
-                   (member ff ll)
-                   (push ff ll))))
-    ll))
-
-;;; org-sudoku ends here
diff --git a/contrib/lisp/org-toc.el b/contrib/lisp/org-toc.el
deleted file mode 100644
index 042d503..0000000
--- a/contrib/lisp/org-toc.el
+++ /dev/null
@@ -1,508 +0,0 @@
-;;; org-toc.el --- Table of contents for Org-mode buffer
-
-;; Copyright 2007-2021 Free Software Foundation, Inc.
-;;
-;; Author: Bastien Guerry <bzg@gnu.org>
-;; Keywords: Org table of contents
-;; Homepage: http://www.cognition.ens.fr/~guerry/u/org-toc.el
-;; Version: 0.8
-
-;; This file is not 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, 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:
-
-;; This library implements a browsable table of contents for Org files.
-
-;; Put this file into your load-path and the following into your ~/.emacs:
-;;   (require 'org-toc)
-
-;;; Code:
-
-(provide 'org-toc)
-(eval-when-compile
-  (require 'cl))
-
-;;; Custom variables:
-(defvar org-toc-base-buffer nil)
-(defvar org-toc-columns-shown nil)
-(defvar org-toc-odd-levels-only nil)
-(defvar org-toc-config-alist nil)
-(defvar org-toc-cycle-global-status nil)
-(defalias 'org-show-table-of-contents 'org-toc-show)
-
-(defgroup org-toc nil
-  "Options concerning the browsable table of contents of Org-mode."
-  :tag "Org TOC"
-  :group 'org)
-
-(defcustom org-toc-default-depth 1
-  "Default depth when invoking `org-toc-show' without argument."
-  :group 'org-toc
-  :type '(choice
-         (const :tag "same as base buffer" nil)
-         (integer :tag "level")))
-
-(defcustom org-toc-follow-mode nil
-  "Non-nil means navigating through the table of contents will
-move the point in the Org buffer accordingly."
-  :group 'org-toc
-  :type 'boolean)
-
-(defcustom org-toc-info-mode nil
-  "Non-nil means navigating through the table of contents will
-show the properties for the current headline in the echo-area."
-  :group 'org-toc
-  :type 'boolean)
-
-(defcustom org-toc-show-subtree-mode nil
-  "Non-nil means show subtree when going to headline or following
-it while browsing the table of contents."
-  :group 'org-toc
-  :type '(choice
-         (const :tag "show subtree" t)
-         (const :tag "show entry" nil)))
-
-(defcustom org-toc-recenter-mode t
-  "Non-nil means recenter the Org buffer when following the
-headlines in the TOC buffer."
-  :group 'org-toc
-  :type 'boolean)
-
-(defcustom org-toc-recenter 0
-  "Where to recenter the Org buffer when unfolding a subtree.
-This variable is only used when `org-toc-recenter-mode' is set to
-'custom. A value >=1000 will call recenter with no arg."
-  :group 'org-toc
-  :type 'integer)
-
-(defcustom org-toc-info-exclude '("ALLTAGS")
-  "A list of excluded properties when displaying info in the
-echo-area. The COLUMNS property is always excluded."
-  :group 'org-toc
-  :type 'lits)
-
-;;; Org TOC mode:
-(defvar org-toc-mode-map (make-sparse-keymap)
-  "Keymap for `org-toc-mode'.")
-
-(defun org-toc-mode ()
-  "A major mode for browsing the table of contents of an Org buffer.
-
-\\{org-toc-mode-map}"
-  (interactive)
-  (kill-all-local-variables)
-  (use-local-map org-toc-mode-map)
-  (setq mode-name "Org TOC")
-  (setq major-mode 'org-toc-mode))
-
-;; toggle modes
-(define-key org-toc-mode-map "F" 'org-toc-follow-mode)
-(define-key org-toc-mode-map "S" 'org-toc-show-subtree-mode)
-(define-key org-toc-mode-map "s" 'org-toc-store-config)
-(define-key org-toc-mode-map "g" 'org-toc-restore-config)
-(define-key org-toc-mode-map "i" 'org-toc-info-mode)
-(define-key org-toc-mode-map "r" 'org-toc-recenter-mode)
-
-;; navigation keys
-(define-key org-toc-mode-map "p" 'org-toc-previous)
-(define-key org-toc-mode-map "n" 'org-toc-next)
-(define-key org-toc-mode-map "f" 'org-toc-forward)
-(define-key org-toc-mode-map "b" 'org-toc-back)
-(define-key org-toc-mode-map [(left)] 'org-toc-back)
-(define-key org-toc-mode-map [(right)] 'org-toc-forward)
-(define-key org-toc-mode-map [(up)] 'org-toc-previous)
-(define-key org-toc-mode-map [(down)] 'org-toc-next)
-(define-key org-toc-mode-map "1" (lambda() (interactive) (org-toc-show 1 
(point))))
-(define-key org-toc-mode-map "2" (lambda() (interactive) (org-toc-show 2 
(point))))
-(define-key org-toc-mode-map "3" (lambda() (interactive) (org-toc-show 3 
(point))))
-(define-key org-toc-mode-map "4" (lambda() (interactive) (org-toc-show 4 
(point))))
-(define-key org-toc-mode-map " " 'org-toc-goto)
-(define-key org-toc-mode-map "q" 'org-toc-quit)
-(define-key org-toc-mode-map "x" 'org-toc-quit)
-;; go to the location and stay in the base buffer
-(define-key org-toc-mode-map [(tab)] 'org-toc-jump)
-(define-key org-toc-mode-map "v" 'org-toc-jump)
-;; go to the location and delete other windows
-(define-key org-toc-mode-map [(return)]
-  (lambda() (interactive) (org-toc-jump t)))
-
-;; special keys
-(define-key org-toc-mode-map "c" 'org-toc-columns)
-(define-key org-toc-mode-map "?" 'org-toc-help)
-(define-key org-toc-mode-map ":" 'org-toc-cycle-subtree)
-(define-key org-toc-mode-map "\C-c\C-o" 'org-open-at-point)
-;; global cycling in the base buffer
-(define-key org-toc-mode-map (kbd "C-S-<iso-lefttab>")
-  'org-toc-cycle-base-buffer)
-;; subtree cycling in the base buffer
-(define-key org-toc-mode-map [(control tab)]
-  (lambda() (interactive) (org-toc-goto nil t)))
-
-;;; Toggle functions:
-(defun org-toc-follow-mode ()
-  "Toggle follow mode in a `org-toc-mode' buffer."
-  (interactive)
-  (setq org-toc-follow-mode (not org-toc-follow-mode))
-  (message "Follow mode is %s"
-          (if org-toc-follow-mode "on" "off")))
-
-(defun org-toc-info-mode ()
-  "Toggle info mode in a `org-toc-mode' buffer."
-  (interactive)
-  (setq org-toc-info-mode (not org-toc-info-mode))
-  (message "Info mode is %s"
-          (if org-toc-info-mode "on" "off")))
-
-(defun org-toc-show-subtree-mode ()
-  "Toggle show subtree mode in a `org-toc-mode' buffer."
-  (interactive)
-  (setq org-toc-show-subtree-mode (not org-toc-show-subtree-mode))
-  (message "Show subtree mode is %s"
-          (if org-toc-show-subtree-mode "on" "off")))
-
-(defun org-toc-recenter-mode (&optional line)
-  "Toggle recenter mode in a `org-toc-mode' buffer. If LINE is
-specified, then make `org-toc-recenter' use this value."
-  (interactive "P")
-  (setq org-toc-recenter-mode (not org-toc-recenter-mode))
-  (when (numberp line)
-    (setq org-toc-recenter-mode t)
-    (setq org-toc-recenter line))
-  (message "Recenter mode is %s"
-          (if org-toc-recenter-mode
-              (format "on, line %d" org-toc-recenter) "off")))
-
-(defun org-toc-cycle-subtree ()
-  "Locally cycle a headline through two states: 'children and
-'folded"
-  (interactive)
-  (let ((beg (point))
-       (end (save-excursion (end-of-line) (point)))
-       (ov (car (overlays-at (point))))
-       status)
-    (if ov (setq status (overlay-get ov 'status))
-      (setq ov (make-overlay beg end)))
-    ;; change the folding status of this headline
-    (cond ((or (null status) (eq status 'folded))
-          (org-show-children)
-          (message "CHILDREN")
-          (overlay-put ov 'status 'children))
-         ((eq status 'children)
-          (show-branches)
-          (message "BRANCHES")
-          (overlay-put ov 'status 'branches))
-         (t (hide-subtree)
-            (message "FOLDED")
-            (overlay-put ov 'status 'folded)))))
-
-;;; Main show function:
-;; FIXME name this org-before-first-heading-p?
-(defun org-toc-before-first-heading-p ()
-  "Before first heading?"
-  (save-excursion
-    (null (re-search-backward org-outline-regexp-bol nil t))))
-
-;;;###autoload
-(defun org-toc-show (&optional depth position)
-  "Show the table of contents of the current Org-mode buffer."
-  (interactive "P")
-  (if (eq major-mode 'org-mode)
-      (progn (setq org-toc-base-buffer (current-buffer))
-            (setq org-toc-odd-levels-only org-odd-levels-only))
-    (if (eq major-mode 'org-toc-mode)
-       (org-pop-to-buffer-same-window org-toc-base-buffer)
-      (error "Not in an Org buffer")))
-  ;; create the new window display
-  (let ((pos (or position
-                (save-excursion
-                  (if (org-toc-before-first-heading-p)
-                      (progn (re-search-forward org-outline-regexp-bol nil t)
-                             (match-beginning 0))
-                    (point))))))
-    (setq org-toc-cycle-global-status org-cycle-global-status)
-    (delete-other-windows)
-    (and (get-buffer "*org-toc*") (kill-buffer "*org-toc*"))
-    (switch-to-buffer-other-window
-     (make-indirect-buffer org-toc-base-buffer "*org-toc*"))
-    ;; make content before 1st headline invisible
-    (goto-char (point-min))
-    (let* ((beg (point-min))
-          (end (and (re-search-forward "^\\*" nil t)
-                    (1- (match-beginning 0))))
-          (ov (make-overlay beg end))
-          (help (format "Table of contents for %s (press ? for a quick 
help):\n"
-                        (buffer-name org-toc-base-buffer))))
-      (overlay-put ov 'invisible t)
-      (overlay-put ov 'before-string help))
-    ;; build the browsable TOC
-    (cond (depth
-          (let* ((dpth (if org-toc-odd-levels-only
-                           (1- (* depth 2)) depth)))
-            (org-content dpth)
-            (setq org-toc-cycle-global-status
-                  `(org-content ,dpth))))
-          ((null org-toc-default-depth)
-           (if (eq org-toc-cycle-global-status 'overview)
-               (progn (org-overview)
-                      (setq org-cycle-global-status 'overview)
-                      (run-hook-with-args 'org-cycle-hook 'overview))
-             (progn (org-overview)
-                    ;; FIXME org-content to show only headlines?
-                    (org-content)
-                    (setq org-cycle-global-status 'contents)
-                    (run-hook-with-args 'org-cycle-hook 'contents))))
-          (t (let* ((dpth0 org-toc-default-depth)
-                    (dpth (if org-toc-odd-levels-only
-                              (1- (* dpth0 2)) dpth0)))
-               (org-content dpth)
-               (setq org-toc-cycle-global-status
-                     `(org-content ,dpth)))))
-    (goto-char pos))
-  (move-beginning-of-line nil)
-  (org-toc-mode)
-  (shrink-window-if-larger-than-buffer)
-  (setq buffer-read-only t))
-
-;;; Navigation functions:
-(defun org-toc-goto (&optional jump cycle)
-  "From Org TOC buffer, follow the targeted subtree in the Org window.
-If JUMP is non-nil, go to the base buffer.
-If JUMP is 'delete, go to the base buffer and delete other windows.
-If CYCLE is non-nil, cycle the targeted subtree in the Org window."
-  (interactive)
-  (let ((pos (point))
-       (toc-buf (current-buffer)))
-    (switch-to-buffer-other-window org-toc-base-buffer)
-    (goto-char pos)
-    (if cycle (org-cycle)
-      (progn (org-overview)
-            (if org-toc-show-subtree-mode
-                (org-show-subtree)
-              (org-show-entry))
-            (org-show-context)))
-    (if org-toc-recenter-mode
-       (if (>= org-toc-recenter 1000) (recenter)
-         (recenter org-toc-recenter)))
-    (cond ((null jump)
-          (switch-to-buffer-other-window toc-buf))
-         ((eq jump 'delete)
-          (delete-other-windows)))))
-
-(defun org-toc-cycle-base-buffer ()
-  "Call `org-cycle' with a prefix argument in the base buffer."
-  (interactive)
-  (switch-to-buffer-other-window org-toc-base-buffer)
-  (org-cycle t)
-  (other-window 1))
-
-(defun org-toc-jump (&optional delete)
-  "From Org TOC buffer, jump to the targeted subtree in the Org window.
-If DELETE is non-nil, delete other windows when in the Org buffer."
-  (interactive "P")
-  (if delete (org-toc-goto 'delete)
-    (org-toc-goto t)))
-
-(defun org-toc-previous ()
-  "Go to the previous headline of the TOC."
-  (interactive)
-  (if (save-excursion
-         (beginning-of-line)
-         (re-search-backward "^\\*" nil t))
-    (outline-previous-visible-heading 1)
-    (message "No previous heading"))
-  (if org-toc-info-mode (org-toc-info))
-  (if org-toc-follow-mode (org-toc-goto)))
-
-(defun org-toc-next ()
-  "Go to the next headline of the TOC."
-  (interactive)
-  (outline-next-visible-heading 1)
-  (if org-toc-info-mode (org-toc-info))
-  (if org-toc-follow-mode (org-toc-goto)))
-
-(defun org-toc-forward ()
-  "Go to the next headline at the same level in the TOC."
-  (interactive)
-  (condition-case nil
-      (outline-forward-same-level 1)
-    (error (message "No next headline at this level")))
-  (if org-toc-info-mode (org-toc-info))
-  (if org-toc-follow-mode (org-toc-goto)))
-
-(defun org-toc-back ()
-  "Go to the previous headline at the same level in the TOC."
-  (interactive)
-  (condition-case nil
-      (outline-backward-same-level 1)
-    (error (message "No previous headline at this level")))
-  (if org-toc-info-mode (org-toc-info))
-  (if org-toc-follow-mode (org-toc-goto)))
-
-(defun org-toc-quit ()
-  "Quit the current Org TOC buffer."
-  (interactive)
-  (kill-buffer)
-  (other-window 1)
-  (delete-other-windows))
-
-;;; Special functions:
-(defun org-toc-columns ()
-  "Toggle columns view in the Org buffer from Org TOC."
-  (interactive)
-  (let ((indirect-buffer (current-buffer)))
-    (org-pop-to-buffer-same-window org-toc-base-buffer)
-    (if (not org-toc-columns-shown)
-       (progn (org-columns)
-              (setq org-toc-columns-shown t))
-      (progn (org-columns-remove-overlays)
-            (setq org-toc-columns-shown nil)))
-    (org-pop-to-buffer-same-window indirect-buffer)))
-
-(defun org-toc-info ()
-  "Show properties of current subtree in the echo-area."
-  (interactive)
-  (let ((pos (point))
-       (indirect-buffer (current-buffer))
-       props prop msg)
-    (org-pop-to-buffer-same-window org-toc-base-buffer)
-    (goto-char pos)
-    (setq props (org-entry-properties))
-    (while (setq prop (pop props))
-      (unless (or (equal (car prop) "COLUMNS")
-                 (member (car prop) org-toc-info-exclude))
-       (let ((p (car prop))
-             (v (cdr prop)))
-         (if (equal p "TAGS")
-             (setq v (mapconcat 'identity (split-string v ":" t) " ")))
-         (setq p (concat p ":"))
-         (add-text-properties 0 (length p) '(face org-special-keyword) p)
-         (setq msg (concat msg p " " v "  ")))))
-    (org-pop-to-buffer-same-window indirect-buffer)
-    (message msg)))
-
-;;; Store and restore TOC configuration:
-(defun org-toc-store-config ()
-  "Store the current status of the tables of contents in
-`org-toc-config-alist'."
-  (interactive)
-  (let ((file (buffer-file-name org-toc-base-buffer))
-       (pos (point))
-       (hlcfg (org-toc-get-headlines-status)))
-    (setq org-toc-config-alist
-         (delete (assoc file org-toc-config-alist)
-                 org-toc-config-alist))
-    (add-to-list 'org-toc-config-alist
-                `(,file ,pos ,org-toc-cycle-global-status ,hlcfg))
-    (message "TOC configuration saved: (%s)"
-            (if (listp org-toc-cycle-global-status)
-                (concat "org-content "
-                        (number-to-string
-                         (cadr org-toc-cycle-global-status)))
-              (symbol-name org-toc-cycle-global-status)))))
-
-(defun org-toc-restore-config ()
-  "Get the stored status in `org-toc-config-alist' and set the
-current table of contents to it."
-  (interactive)
-  (let* ((file (buffer-file-name org-toc-base-buffer))
-        (conf (cdr (assoc file org-toc-config-alist)))
-        (pos (car conf))
-        (status (cadr conf))
-        (hlcfg (caddr conf)) hlcfg0 ov)
-    (cond ((listp status)
-          (org-toc-show (cadr status) (point)))
-         ((eq status 'overview)
-          (org-overview)
-          (setq org-cycle-global-status 'overview)
-          (run-hook-with-args 'org-cycle-hook 'overview))
-         (t
-          (org-overview)
-          (org-content)
-          (setq org-cycle-global-status 'contents)
-          (run-hook-with-args 'org-cycle-hook 'contents)))
-    (while (setq hlcfg0 (pop hlcfg))
-      (save-excursion
-       (goto-char (point-min))
-       (when (search-forward (car hlcfg0) nil t)
-         (unless (overlays-at (match-beginning 0))
-           (setq ov (make-overlay (match-beginning 0)
-                                  (match-end 0))))
-         (cond ((eq (cdr hlcfg0) 'children)
-                (org-show-children)
-                (message "CHILDREN")
-                (overlay-put ov 'status 'children))
-               ((eq (cdr hlcfg0) 'branches)
-                (show-branches)
-                (message "BRANCHES")
-                (overlay-put ov 'status 'branches))))))
-    (goto-char pos)
-    (if org-toc-follow-mode (org-toc-goto))
-    (message "Last TOC configuration restored")
-    (sit-for 1)
-    (if org-toc-info-mode (org-toc-info))))
-
-(defun org-toc-get-headlines-status ()
-  "Return an alist of headlines and their associated folding
-status."
-  (let (output ovs)
-    (save-excursion
-      (goto-char (point-min))
-      (while (and (not (eobp))
-                 (goto-char (next-overlay-change (point))))
-       (when (looking-at org-outline-regexp-bol)
-         (add-to-list
-          'output
-          (cons (buffer-substring-no-properties
-                 (match-beginning 0)
-                 (save-excursion
-                   (end-of-line) (point)))
-                (overlay-get
-                 (car (overlays-at (point))) 'status))))))
-    ;; return an alist like (("* Headline" . 'status))
-    output))
-
-;; In Org TOC buffer, hide headlines below the first level.
-(defun org-toc-help ()
-  "Display a quick help message in the echo-area for `org-toc-mode'."
-  (interactive)
-  (let ((st-start 0)
-       (help-message
-        "\[space\]   show heading                     \[1-4\] hide headlines 
below this level
-\[TAB\]     jump to heading                  \[F\]   toggle follow mode 
(currently %s)
-\[return\]  jump and delete others windows   \[i\]   toggle info mode 
(currently %s)
-\[S-TAB\]   cycle subtree (in Org)           \[S\]   toggle show subtree mode 
(currently %s)
-\[C-S-TAB\] global cycle (in Org)            \[r\]   toggle recenter mode 
(currently %s)
-\[:\]       cycle subtree (in TOC)           \[c\]   toggle column view 
(currently %s)
-\[n/p\]     next/previous heading            \[s\]   save TOC configuration
-\[f/b\]     next/previous heading of same level
-\[q\]       quit the TOC                     \[g\]   restore last TOC 
configuration"))
-    (while (string-match "\\[[^]]+\\]" help-message st-start)
-      (add-text-properties (match-beginning 0)
-                           (match-end 0) '(face bold) help-message)
-      (setq st-start (match-end 0)))
-  (message help-message
-    (if org-toc-follow-mode "on" "off")
-    (if org-toc-info-mode "on" "off")
-    (if org-toc-show-subtree-mode "on" "off")
-    (if org-toc-recenter-mode (format "on, line %s" org-toc-recenter) "off")
-    (if org-toc-columns-shown "on" "off"))))
-
-
-;;;;##########################################################################
-;;;;  User Options, Variables
-;;;;##########################################################################
-
-;;; org-toc.el ends here
diff --git a/contrib/lisp/org-track.el b/contrib/lisp/org-track.el
deleted file mode 100644
index 044707e..0000000
--- a/contrib/lisp/org-track.el
+++ /dev/null
@@ -1,211 +0,0 @@
-;;; org-track.el --- Track the most recent Org-mode version available.
-;;
-;; Copyright (C) 2009-2021 Free Software Foundation, Inc.
-;;
-;; Author: Bastien Guerry <bzg@gnu.org>
-;;         Eric S Fraga   <e.fraga at ucl.ac dot uk>
-;;         Sebastian Rose <sebastian_rose at gmx dot de>
-;;         The Worg people https://orgmode.org/worg/
-;; Keywords: outlines, hypermedia, calendar, wp
-;; Homepage: https://orgmode.org
-;; Version: 6.29a
-;;
-;; Released under the GNU General Public License version 3
-;; see: http://www.gnu.org/licenses/gpl-3.0.html
-;;
-;; This file is not 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:
-;;
-;; WARNING: This library is obsolete, you should use the make targets
-;; to keep track of Org latest developments.
-;;
-;; Download the latest development tarball, unpack and optionally compile it
-;;
-;; Usage:
-;;
-;;   (require 'org-track)
-;;
-;;   ;; ... somewhere in your setup (use customize):
-;;
-;;   (setq org-track-directory "~/test/")
-;;   (setq org-track-compile-sources nil)
-;;   (setq org-track-remove-package t)
-;;
-;;   M-x org-track-update RET
-
-(require 'url-parse)
-(require 'url-handlers)
-(autoload 'url-file-local-copy "url-handlers")
-(autoload 'url-generic-parse-url "url-parse")
-
-
-
-;;; Variables:
-
-(defgroup org-track nil
-  "Track the most recent Org-mode version available.
-
-To use org-track, adjust `org-track-directory'.
-Org will download the archived latest git version for you,
-unpack it into that directory (i.e. a subdirectory
-`org-mode/' is added), create the autoloads file
-`org-loaddefs.el' for you and, optionally, compile the
-sources.
-All you'll have to do is call `M-x org-track-update' from
-time to time."
-  :group 'org)
-
-(defcustom org-track-directory (concat user-emacs-directory "org/lisp")
-  "Directory where your org-mode/ directory lives.
-If that directory does not exist, it will be created."
-  :type 'directory)
-
-(defcustom org-track-compile-sources t
-  "If `nil', never compile org-sources.
-Org will only create the autoloads file `org-loaddefs.el' for
-you then. If `t', compile the sources, too.
-Note, that emacs preferes compiled elisp files over
-non-compiled ones."
-  :type 'boolean)
-
-(defcustom org-track-org-url "https://orgmode.org/";
-  "The URL where the package to download can be found.
-Please append a slash."
-  :type 'string)
-
-(defcustom org-track-org-package "org-latest.tar.gz"
-  "The basename of the package you use.
-Defaults to the development version of Org-mode.
-This should be a *.tar.gz package, since emacs provides all
-you need to unpack it."
-  :type 'string)
-
-(defcustom org-track-remove-package nil
-  "Remove org-latest.tar.gz after updates?"
-  :type 'boolean)
-
-
-
-;;; Frontend
-
-(defun org-track-update ()
-  "Update to current Org-mode version.
-Also, generate autoloads and evtl. compile the sources."
-  (interactive)
-  (let* ((base (file-truename org-track-directory))
-         (org-exists (file-exists-p
-                      (file-truename
-                       (concat base "/org-mode/lisp/org.el"))))
-         (nobase (not (file-directory-p
-                       (file-truename org-track-directory)))))
-    (if nobase
-        (when (y-or-n-p
-               (format "Directory %s does not exist. Create it?" base))
-          (make-directory base t)
-          (setq nobase nil)))
-    (if nobase
-        (message "Not creating %s - giving up." org-track-directory)
-      (condition-case err
-          (progn
-            (org-track-fetch-package)
-            (org-track-compile-org))
-        (error (message "%s" (error-message-string err)))))))
-
-
-
-;;; tar related functions
-
-;; `url-retrieve-synchronously' fetches files synchronously. How can we ensure
-;; that? If the maintainers of that package decide, that an assynchronous
-;; download might be better??? (used by `url-file-local-copy')
-
-;;;###autoload
-(defun org-track-fetch-package (&optional directory)
-  "Fetch Org package depending on `org-track-fetch-package-extension'.
-If DIRECTORY is defined, unpack the package there, i.e. add the
-subdirectory org-mode/ to DIRECTORY."
-  (interactive "Dorg-track directory: ")
-  (let* ((pack (concat
-                (if (string-match "/$" org-track-org-url)
-                    org-track-org-url
-                  (concat org-track-org-url "/"))
-                org-track-org-package))
-         (base (file-truename
-                (or directory org-track-directory)))
-         (target (file-truename
-                  (concat base "/" org-track-org-package)))
-         url download tarbuff)
-    (message "Fetching to %s - this might take some time..."  base)
-    (setq url (url-generic-parse-url pack))
-    (setq download (url-file-local-copy url)) ;; errors if fail
-    (copy-file download target t)
-    (delete-file download)
-    ;; (tar-mode) leads to dubious errors. We use the auto-mode-alist to
-    ;; ensure tar-mode is used:
-    (add-to-list 'auto-mode-alist '("org-latest\\.tar\\.gz\\'" . tar-mode))
-    (setq tarbuff (find-file target))
-    (with-current-buffer tarbuff ;; with-temp-buffer does not work with 
tar-mode??
-      (tar-untar-buffer))
-    (kill-buffer tarbuff)
-    (if org-track-remove-package
-        (delete-file target))))
-
-
-
-;;; Compile Org-mode sources
-
-
-;;;###autoload
-(defun org-track-compile-org (&optional directory)
-  "Compile all *.el files that come with org-mode.
-Generate the autoloads file `org-loaddefs.el'.
-
-DIRECTORY is where the directory org-mode/ lives (i.e. the
-          parent directory of your local repo."
-  (interactive)
-  ;; file-truename expands the filename and removes double slash, if exists:
-  (setq directory (file-truename
-                   (concat
-                    (or directory
-                        (file-truename (concat org-track-directory 
"/org-mode/lisp")))
-                    "/")))
-  (add-to-list 'load-path directory)
-  (let ((list-of-org-files (file-expand-wildcards (concat directory "*.el"))))
-    ;; create the org-loaddefs file
-    (require 'autoload)
-    (setq esf/org-install-file (concat directory "org-loaddefs.el"))
-    (find-file esf/org-install-file)
-    (erase-buffer)
-    (mapc (lambda (x)
-            (generate-file-autoloads x))
-          list-of-org-files)
-    (insert "\n(provide (quote org-loaddefs))\n")
-    (save-buffer)
-    (kill-buffer)
-    (byte-compile-file esf/org-install-file t)
-
-    (mapc (lambda (f)
-            (if (file-exists-p (concat f "c"))
-                (delete-file (concat f "c"))))
-          list-of-org-files)
-    (if org-track-compile-sources
-        (mapc (lambda (f) (byte-compile-file f)) list-of-org-files))))
-
-(provide 'org-track)
-
-;;; org-track.el ends here
diff --git a/contrib/lisp/org-velocity.el b/contrib/lisp/org-velocity.el
deleted file mode 100644
index bfc4d6c..0000000
--- a/contrib/lisp/org-velocity.el
+++ /dev/null
@@ -1,819 +0,0 @@
-;;; org-velocity.el --- something like Notational Velocity for Org. -*- 
lexical-binding: t -*-
-
-;; Copyright (C) 2010-2014 Paul M. Rodriguez
-
-;; Author: Paul M. Rodriguez <paulmrodriguez@gmail.com>
-;; Created: 2010-05-05
-;; Version: 4.1
-
-;; This file is not 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 version 2.
-
-;; 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:
-;; Org-Velocity.el is an interface for Org inspired by the minimalist
-;; notetaking program Notational Velocity. The idea is to let you
-;; amass and access brief notes on many subjects with minimal fuss.
-;; Each note is an entry in an ordinary Org file.
-
-;; Org-Velocity can be used in two ways: when called outside Org, to
-;; store and access notes in a designated bucket file; or, when called
-;; inside Org, as a method for navigating any Org file. (Setting the
-;; option `org-velocity-always-use-bucket' disables navigation inside
-;; Org files by default, although you can still force this behavior by
-;; calling `org-velocity-read' with an argument.)
-
-;; Org-Velocity prompts for search terms in the minibuffer. A list of
-;; headings of entries whose text matches your search is updated as
-;; you type; you can end the search and visit an entry at any time by
-;; clicking on its heading.
-
-;; RET displays the results. If there are no matches, Org-Velocity
-;; offers to create a new entry with your search string as its
-;; heading. If there are matches, it displays a list of results where
-;; the heading of each matching entry is hinted with a number or
-;; letter; clicking a result, or typing the matching hint, opens the
-;; entry for editing in an indirect buffer. 0 forces a new entry; RET
-;; reopens the search for editing.
-
-;; You can customize every step in this process, including the search
-;; method, completion for search terms, and templates for creating new
-;; entries; M-x customize-group RET org-velocity RET to see all the
-;; options.
-
-;; Thanks to Richard Riley, Carsten Dominik, Bastien Guerry, and Jeff
-;; Horn for their suggestions.
-
-;;; Usage:
-;; (require 'org-velocity)
-;; (setq org-velocity-bucket (expand-file-name "bucket.org" org-directory))
-;; (global-set-key (kbd "C-c v") 'org-velocity)
-
-;;; Code:
-(require 'org)
-(require 'button)
-(require 'electric)
-(require 'dabbrev)
-(require 'cl-lib)
-
-(defgroup org-velocity nil
-  "Notational Velocity-style interface for Org."
-  :tag "Org-Velocity"
-  :group 'outlines
-  :group 'hypermedia
-  :group 'org)
-
-(defcustom org-velocity-bucket ""
-  "Where is the bucket file?"
-  :group 'org-velocity
-  :type 'file)
-
-(defcustom org-velocity-show-previews t
-  "Show previews of the text of each heading?"
-  :group 'velocity
-  :type 'boolean
-  :safe 'booleanp)
-
-(defcustom org-velocity-exit-on-match nil
-  "When searching incrementally, exit on a single match?"
-  :group 'org-velocity
-  :type 'boolean
-  :safe 'booleanp)
-
-(defcustom org-velocity-force-new nil
-  "Should exiting the minibuffer with C-j force a new entry?"
-  :group 'org-velocity
-  :type 'boolean
-  :safe 'booleanp)
-
-(defcustom org-velocity-use-search-ring t
-  "Push search to `search-ring' when visiting an entry?
-
-This means that C-s C-s will take you directly to the first
-instance of the search string."
-  :group 'org-velocity
-  :type 'boolean
-  :safe 'booleanp)
-
-(defcustom org-velocity-always-use-bucket nil
-  "Use bucket file even when called from an Org buffer?"
-  :group 'org-velocity
-  :type 'boolean
-  :safe 'booleanp)
-
-(defcustom org-velocity-use-completion nil
-  "Use completion?
-
-Notwithstanding the value of this option, calling
-`dabbrev-expand' always completes against the text of the bucket
-file."
-  :group 'org-velocity
-  :type '(choice
-          (const :tag "Do not use completion" nil)
-          (const :tag "Use completion" t))
-  :safe 'booleanp)
-
-(defcustom org-velocity-search-method 'phrase
-  "Match on whole phrase, any word, or all words?"
-  :group 'org-velocity
-  :type '(choice
-          (const :tag "Match whole phrase" phrase)
-          (const :tag "Match any word" any)
-          (const :tag "Match all words" all)
-          (const :tag "Match a regular expression" regexp))
-  :safe (lambda (v) (memq v '(phrase any all regexp))))
-
-(defcustom org-velocity-capture-templates
-  '(("v"
-     "Velocity entry"
-     entry
-     (file "")
-     "* %:search\n\n%i%?"))
-  "Use these template with `org-capture'.
-Meanwhile `org-default-notes-file' is bound to `org-velocity-bucket-file'.
-The keyword :search inserts the current search.
-See the documentation for `org-capture-templates'."
-  :group 'org-velocity
-  :type (or (get 'org-capture-templates 'custom-type) 'list))
-
-(defcustom org-velocity-heading-level 1
-  "Only match headings at this level or higher.
-0 means to match headings at any level."
-  :group 'org-velocity
-  :type 'integer
-  :safe (lambda (x)
-          (and (integerp x)
-               (>= x 0))))
-
-(defvar crm-separator)                  ;Ensure dynamic binding.
-
-(defsubst org-velocity-grab-preview ()
-  "Grab preview of a subtree.
-The length of the preview is determined by `window-width'.
-
-Replace all contiguous whitespace with single spaces."
-  (let* ((start (progn
-                  (forward-line 1)
-                  (if (looking-at org-property-start-re)
-                      (re-search-forward org-property-end-re)
-                    (1- (point)))))
-         (string+props (buffer-substring
-                        start
-                        (min
-                         (+ start (window-width))
-                         (point-max)))))
-    ;; We want to preserve the text properties so that, for example,
-    ;; we don't end up with the raw text of links in the preview.
-    (with-temp-buffer
-      (insert string+props)
-      (goto-char (point-min))
-      (save-match-data
-        (while (re-search-forward split-string-default-separators
-                                  (point-max)
-                                  t)
-          (replace-match " ")))
-      (buffer-string))))
-
-(cl-defstruct org-velocity-heading buffer position name level preview)
-
-(defsubst org-velocity-nearest-heading (position)
-  "Return last heading at POSITION.
-If there is no last heading, return nil."
-  (save-excursion
-    (goto-char position)
-    (re-search-backward (org-velocity-heading-regexp))
-    (let ((components (org-heading-components)))
-      (make-org-velocity-heading
-       :buffer (current-buffer)
-       :position (point)
-       :name (nth 4 components)
-       :level (nth 0 components)
-       :preview (if org-velocity-show-previews
-                    (org-velocity-grab-preview))))))
-
-(defconst org-velocity-index
-  (eval-when-compile
-    (nconc (number-sequence 49 57)      ;numbers
-           (number-sequence 97 122)    ;lowercase letters
-           (number-sequence 65 90)))   ;uppercase letters
-  "List of chars for indexing results.")
-
-(defconst org-velocity-match-buffer-name "*Velocity matches*")
-
-(cl-defun org-velocity-heading-regexp (&optional (level 
org-velocity-heading-level))
-  "Regexp to match headings at LEVEL or deeper."
-  (if (zerop level)
-      "^\\*+ "
-    (format "^\\*\\{1,%d\\} " level)))
-
-(defvar org-velocity-search nil
-  "Variable to bind to current search.")
-
-(defun org-velocity-buffer-file-name (&optional buffer)
-  "Return the name of the file BUFFER saves to.
-Same as function `buffer-file-name' unless BUFFER is an indirect
-buffer or a minibuffer. In the former case, return the file name
-of the base buffer; in the latter, return the file name of
-`minibuffer-selected-window' (or its base buffer)."
-  (let ((buffer (if (minibufferp buffer)
-                    (window-buffer (minibuffer-selected-window))
-                  buffer)))
-    (buffer-file-name
-     (or (buffer-base-buffer buffer)
-         buffer))))
-
-(defun org-velocity-minibuffer-contents ()
-  "Return the contents of the minibuffer when it is active."
-  (when (active-minibuffer-window)
-    (with-current-buffer (window-buffer (active-minibuffer-window))
-      (minibuffer-contents))))
-
-(defun org-velocity-nix-minibuffer ()
-  "Return the contents of the minibuffer and clear it."
-  (when (active-minibuffer-window)
-    (with-current-buffer (window-buffer (active-minibuffer-window))
-      (prog1 (minibuffer-contents)
-        (delete-minibuffer-contents)))))
-
-(defun org-velocity-bucket-file ()
-  "Return the proper file for Org-Velocity to search.
-If `org-velocity-always-use-bucket' is t, use bucket file;
-complain if missing. Otherwise, if an Org file is current, then
-use it."
-  (let ((org-velocity-bucket
-         (when org-velocity-bucket (expand-file-name org-velocity-bucket)))
-        (buffer
-         (let ((buffer-file (org-velocity-buffer-file-name)))
-           (when buffer-file
-             ;; Use the target in capture buffers.
-             (org-find-base-buffer-visiting buffer-file)))))
-    (if org-velocity-always-use-bucket
-        (or org-velocity-bucket (error "Bucket required but not defined"))
-      (if (and (eq (buffer-local-value 'major-mode (or buffer 
(current-buffer)))
-                   'org-mode)
-               (org-velocity-buffer-file-name))
-          (org-velocity-buffer-file-name)
-        (or org-velocity-bucket
-            (error "No bucket and not an Org file"))))))
-
-(defvar org-velocity-bucket-buffer nil)
-(defvar org-velocity-navigating nil)
-
-(defsubst org-velocity-bucket-buffer ()
-  (or org-velocity-bucket-buffer
-      (find-file-noselect (org-velocity-bucket-file))))
-
-(defsubst org-velocity-match-buffer ()
-  "Return the proper buffer for Org-Velocity to display in."
-  (get-buffer-create org-velocity-match-buffer-name))
-
-(defsubst org-velocity-match-window ()
-  (get-buffer-window (org-velocity-match-buffer)))
-
-(defun org-velocity-beginning-of-headings ()
-  "Goto the start of the first heading."
-  (goto-char (point-min))
-  ;; If we are before the first heading we could still be at the
-  ;; first heading.
-  (or (looking-at (org-velocity-heading-regexp))
-      (re-search-forward (org-velocity-heading-regexp))))
-
-(defun org-velocity-make-indirect-buffer (heading)
-  "Make or switch to an indirect buffer visiting HEADING."
-  (let* ((bucket (org-velocity-heading-buffer heading))
-         (name (org-velocity-heading-name heading))
-         (existing (get-buffer name)))
-    (if (and existing (buffer-base-buffer existing)
-             (equal (buffer-base-buffer existing) bucket))
-        existing
-      (make-indirect-buffer
-       bucket
-       (generate-new-buffer-name (org-velocity-heading-name heading))
-       t))))
-
-(defun org-velocity-capture ()
-  "Record a note with `org-capture'."
-  (let ((org-capture-templates
-         org-velocity-capture-templates))
-    (org-capture nil
-                 ;; This is no longer automatically selected.
-                 (when (null (cdr org-capture-templates))
-                   (caar org-capture-templates)))
-    (when org-capture-mode
-      (rename-buffer org-velocity-search t))))
-
-(defvar org-velocity-saved-winconf nil)
-(make-variable-buffer-local 'org-velocity-saved-winconf)
-
-(defun org-velocity-edit-entry (heading)
-  (if org-velocity-navigating
-      (org-velocity-edit-entry/inline heading)
-    (org-velocity-edit-entry/indirect heading)))
-
-(cl-defun org-velocity-goto-entry (heading &key narrow)
-  (goto-char (org-velocity-heading-position heading))
-  (save-excursion
-    (when narrow
-      (org-narrow-to-subtree))
-    (outline-show-all)))
-
-(defun org-velocity-edit-entry/inline (heading)
-  "Edit entry at HEADING in the original buffer."
-  (let ((buffer (org-velocity-heading-buffer heading)))
-    (pop-to-buffer buffer)
-    (with-current-buffer buffer
-      (org-velocity-goto-entry heading))))
-
-(defun org-velocity-format-header-line (control-string &rest args)
-  (set (make-local-variable 'header-line-format)
-       (apply #'format control-string args)))
-
-(defun org-velocity-edit-entry/indirect (heading)
-  "Edit entry at HEADING in an indirect buffer."
-  (let ((winconf (current-window-configuration))
-        (dd default-directory)
-        (buffer (org-velocity-make-indirect-buffer heading))
-        (inhibit-point-motion-hooks t)
-        (inhibit-field-text-motion t))
-    (with-current-buffer buffer
-      (setq default-directory dd)       ;Inherit default directory.
-      (setq org-velocity-saved-winconf winconf)
-      (org-velocity-goto-entry heading :narrow t)
-      (goto-char (point-max))
-      (add-hook 'org-ctrl-c-ctrl-c-hook 'org-velocity-dismiss nil t))
-    (pop-to-buffer buffer)
-    (org-velocity-format-header-line
-     "%s Use C-c C-c to finish."
-     (abbreviate-file-name
-      (buffer-file-name
-       (org-velocity-heading-buffer heading))))))
-
-(defun org-velocity-dismiss ()
-  "Save current entry and close indirect buffer."
-  (let ((winconf org-velocity-saved-winconf))
-    (prog1 t                            ;Tell hook we're done.
-      (save-buffer)
-      (kill-buffer)
-      (when (window-configuration-p winconf)
-        (set-window-configuration winconf)))))
-
-(defun org-velocity-visit-button (button)
-  (run-hooks 'mouse-leave-buffer-hook)
-  (when org-velocity-use-search-ring
-    (add-to-history 'search-ring
-                    (button-get button 'search)
-                    search-ring-max))
-  (let ((match (button-get button 'match)))
-    (throw 'org-velocity-done match)))
-
-(define-button-type 'org-velocity-button
-  'action #'org-velocity-visit-button
-  'follow-link 'mouse-face)
-
-(defsubst org-velocity-buttonize (heading)
-  "Insert HEADING as a text button with no hints."
-  (insert-text-button
-   (propertize (org-velocity-heading-name heading) 'face 'link)
-   :type 'org-velocity-button
-   'match heading
-   'search org-velocity-search))
-
-(defsubst org-velocity-insert-preview (heading)
-  (when org-velocity-show-previews
-    (insert-char ?\  1)
-    (insert
-     (propertize
-      (org-velocity-heading-preview heading)
-      'face 'shadow))))
-
-(defvar org-velocity-recursive-headings nil)
-(defvar org-velocity-recursive-search nil)
-
-(cl-defun org-velocity-search-with (fun style search
-                                        &key (headings 
org-velocity-recursive-headings))
-  (if headings
-      (save-restriction
-        (dolist (heading headings)
-          (widen)
-          (let ((start (org-velocity-heading-position heading)))
-            (goto-char start)
-            (let ((end (save-excursion
-                         (org-end-of-subtree)
-                         (point))))
-              (narrow-to-region start end)
-              (org-velocity-search-with fun style search
-                                        :headings nil)))))
-    (cl-ecase style
-      ((phrase any regexp)
-       (cl-block nil
-         (while (re-search-forward search nil t)
-           (let ((match (org-velocity-nearest-heading (point))))
-             (funcall fun match))
-           ;; Skip to the next heading.
-           (unless (re-search-forward (org-velocity-heading-regexp) nil t)
-             (cl-return)))))
-      ((all)
-       (let ((keywords
-              (cl-loop for word in (split-string search)
-                       collect (concat "\\<" (regexp-quote word) "\\>"))))
-         (org-map-entries
-          (lambda ()
-            ;; Only search the subtree once.
-            (setq org-map-continue-from
-                  (save-excursion
-                    (org-end-of-subtree)
-                    (point)))
-            (when (cl-loop for word in keywords
-                           always (save-excursion
-                                    (re-search-forward word 
org-map-continue-from t)))
-              (let ((match (org-velocity-nearest-heading (match-end 0))))
-                (funcall fun match))))))))))
-
-(defun org-velocity-all-results (style search)
-  (with-current-buffer (org-velocity-bucket-buffer)
-    (save-excursion
-      (goto-char (point-min))
-      (let (matches)
-        (org-velocity-search-with (lambda (match)
-                                    (push match matches))
-                                  style
-                                  search)
-        (nreverse matches)))))
-
-(defsubst org-velocity-present-match (hint match)
-  (with-current-buffer (org-velocity-match-buffer)
-    (when hint (insert "#" hint " "))
-    (org-velocity-buttonize match)
-    (org-velocity-insert-preview match)
-    (newline)))
-
-(defun org-velocity-present-search (style search hide-hints)
-  (let ((hints org-velocity-index) matches)
-    (cl-block nil
-      (org-velocity-search-with (lambda (match)
-                                  (unless hints
-                                    (cl-return))
-                                  (let ((hint (if hide-hints
-                                                  nil
-                                                (car hints))))
-                                    (org-velocity-present-match hint match))
-                                  (pop hints)
-                                  (push match matches))
-                                style
-                                search))
-    (nreverse matches)))
-
-(defun org-velocity-restrict-search ()
-  (interactive)
-  (let ((search (org-velocity-nix-minibuffer)))
-    (when (equal search "")
-      (error "No search to restrict to"))
-    (push search org-velocity-recursive-search)
-    (setq org-velocity-recursive-headings
-          (org-velocity-all-results
-           org-velocity-search-method
-           search))
-    ;; TODO We could extend the current search instead of starting
-    ;; over.
-    (org-velocity-update-match-header)
-    (minibuffer-message "Restricting search to %s" search)))
-
-(cl-defun org-velocity-update-match-header (&key (match-buffer 
(org-velocity-match-buffer))
-                                                 (bucket-buffer 
(org-velocity-bucket-buffer))
-                                                 (search-method 
org-velocity-search-method))
-  (let ((navigating? org-velocity-navigating)
-        (recursive? org-velocity-recursive-search))
-    (with-current-buffer match-buffer
-      (org-velocity-format-header-line
-       "%s search in %s%s (%s mode)"
-       (capitalize (symbol-name search-method))
-       (abbreviate-file-name (buffer-file-name bucket-buffer))
-       (if (not recursive?)
-           ""
-         (let ((sep " > "))
-           (concat sep (string-join (reverse recursive?) sep))))
-       (if navigating? "nav" "notes")))))
-
-(cl-defun org-velocity-present (search &key hide-hints)
-  "Buttonize matches for SEARCH in `org-velocity-match-buffer'.
-If HIDE-HINTS is non-nil, display entries without indices. SEARCH
-binds `org-velocity-search'.
-
-Return matches."
-  (let ((match-buffer (org-velocity-match-buffer))
-        (bucket-buffer (org-velocity-bucket-buffer))
-        (search-method org-velocity-search-method))
-    (if (and (stringp search) (not (string= "" search)))
-        ;; Fold case when the search string is all lowercase.
-        (let ((case-fold-search (equal search (downcase search)))
-              (truncate-partial-width-windows t))
-          (with-current-buffer match-buffer
-            (erase-buffer)
-            ;; Permanent locals.
-            (setq cursor-type nil
-                  truncate-lines t)
-            (org-velocity-update-match-header
-             :match-buffer match-buffer
-             :bucket-buffer bucket-buffer
-             :search-method search-method))
-          (prog1
-              (with-current-buffer bucket-buffer
-                (widen)
-                (let* ((inhibit-point-motion-hooks t)
-                       (inhibit-field-text-motion t)
-                       (anchored? (string-match-p "^\\s-" search))
-                       (search
-                        (cl-ecase search-method
-                          (all search)
-                          (phrase
-                           (if anchored?
-                               (regexp-quote search)
-                             ;; Anchor the search to the start of a word.
-                             (concat "\\<" (regexp-quote search))))
-                          (any
-                           (concat "\\<" (regexp-opt (split-string search))))
-                          (regexp search))))
-                  (save-excursion
-                    (org-velocity-beginning-of-headings)
-                    (condition-case lossage
-                        (org-velocity-present-search search-method search 
hide-hints)
-                      (invalid-regexp
-                       (minibuffer-message "%s" lossage))))))
-            (with-current-buffer match-buffer
-              (goto-char (point-min)))))
-      (with-current-buffer match-buffer
-        (erase-buffer)))))
-
-(defun org-velocity-store-link ()
-  "Function for `org-store-link-functions'."
-  (if org-velocity-search
-      (org-store-link-props
-       :search org-velocity-search)))
-
-(add-hook 'org-store-link-functions 'org-velocity-store-link)
-
-(cl-defun org-velocity-create (search &key ask)
-  "Create new heading named SEARCH.
-If ASK is non-nil, ask first."
-  (when (or (null ask) (y-or-n-p "No match found, create? "))
-    (let ((org-velocity-search search)
-          (org-default-notes-file (org-velocity-bucket-file))
-          ;; save a stored link
-          org-store-link-plist)
-      (org-velocity-capture))
-    search))
-
-(defun org-velocity-engine (search)
-  "Display a list of headings where SEARCH occurs."
-  (let ((org-velocity-search search))
-    (unless (or
-             (not (stringp search))
-             (string= "" search))      ;exit on empty string
-      (cl-case
-          (if (and org-velocity-force-new (eq last-command-event ?\C-j))
-              :force
-            (let* ((org-velocity-index (org-velocity-adjust-index))
-                   (matches (org-velocity-present search)))
-              (cond ((null matches) :new)
-                    ((null (cdr matches)) :follow)
-                    (t :prompt))))
-        (:prompt (progn
-                   (pop-to-buffer (org-velocity-match-buffer))
-                   (let ((hint (org-velocity-electric-read-hint)))
-                     (when hint (cl-case hint
-                                  (:edit (org-velocity-read nil search))
-                                  (:force (org-velocity-create search))
-                                  (otherwise (org-velocity-activate-button 
hint)))))))
-        (:new (unless (org-velocity-create search :ask t)
-                (org-velocity-read nil search)))
-        (:force (org-velocity-create search))
-        (:follow (if (y-or-n-p "One match, follow? ")
-                     (progn
-                       (set-buffer (org-velocity-match-buffer))
-                       (goto-char (point-min))
-                       (button-activate (next-button (point))))
-                   (org-velocity-read nil search)))))))
-
-(defun org-velocity-activate-button (char)
-  "Go to button on line number associated with CHAR in `org-velocity-index'."
-  (goto-char (point-min))
-  (forward-line (cl-position char org-velocity-index))
-  (goto-char
-   (button-start
-    (next-button (point))))
-  (message "%s" (button-label (button-at (point))))
-  (button-activate (button-at (point))))
-
-(defun org-velocity-electric-undefined ()
-  "Complain about an undefined key."
-  (interactive)
-  (message "%s"
-           (substitute-command-keys
-            "\\[org-velocity-electric-new] for new entry,
-\\[org-velocity-electric-edit] to edit search,
-\\[scroll-up] to scroll up,
-\\[scroll-down] to scroll down,
-\\[keyboard-quit] to quit."))
-  (sit-for 4))
-
-(defun org-velocity-electric-follow (ev)
-  "Follow a hint indexed by keyboard event EV."
-  (interactive (list last-command-event))
-  (if (not (> (cl-position ev org-velocity-index)
-              (1- (count-lines (point-min) (point-max)))))
-      (throw 'org-velocity-select ev)
-    (call-interactively 'org-velocity-electric-undefined)))
-
-(defun org-velocity-electric-edit ()
-  "Edit the search string."
-  (interactive)
-  (throw 'org-velocity-select :edit))
-
-(defun org-velocity-electric-new ()
-  "Force a new entry."
-  (interactive)
-  (throw 'org-velocity-select :force))
-
-(defvar org-velocity-electric-map
-  (let ((map (make-sparse-keymap)))
-    (define-key map [t] 'org-velocity-electric-undefined)
-    (dolist (c org-velocity-index)
-      (define-key map (char-to-string c)
-        'org-velocity-electric-follow))
-    (define-key map "0" 'org-velocity-electric-new)
-    (define-key map "\C-v" 'scroll-up)
-    (define-key map "\M-v" 'scroll-down)
-    (define-key map (kbd "RET") 'org-velocity-electric-edit)
-    (define-key map [mouse-1] nil)
-    (define-key map [mouse-2] nil)
-    (define-key map [escape] 'keyboard-quit)
-    (define-key map "\C-h" 'help-command)
-    map))
-
-(defun org-velocity-electric-read-hint ()
-  "Read index of button electrically."
-  (with-current-buffer (org-velocity-match-buffer)
-    (when (featurep 'evil)
-      ;; NB Idempotent.
-      (evil-make-overriding-map org-velocity-electric-map))
-    (use-local-map org-velocity-electric-map)
-    (catch 'org-velocity-select
-      (Electric-command-loop 'org-velocity-select "Follow: "))))
-
-(defvar org-velocity-incremental-keymap
-  (let ((map (make-sparse-keymap)))
-    (define-key map "\C-v" 'scroll-up)
-    (define-key map "\M-v" 'scroll-down)
-    map))
-
-(defun org-velocity-displaying-completions-p ()
-  "Is there a *Completions* buffer showing?"
-  (get-window-with-predicate
-   (lambda (w)
-     (eq (buffer-local-value 'major-mode (window-buffer w))
-         'completion-list-mode))))
-
-(defun org-velocity-update ()
-  "Display results of search without hinting."
-  (unless (org-velocity-displaying-completions-p)
-    (let* ((search (org-velocity-minibuffer-contents))
-           (matches (org-velocity-present search :hide-hints t)))
-      (cond ((null matches)
-             (select-window (active-minibuffer-window))
-             (unless (or (null search) (= (length search) 0))
-               (minibuffer-message "No match; RET to create")))
-            ((and (null (cdr matches))
-                  org-velocity-exit-on-match)
-             (throw 'click search))
-            (t
-             (with-current-buffer (org-velocity-match-buffer)
-               (use-local-map org-velocity-incremental-keymap)))))))
-
-(defvar dabbrev--last-abbreviation)
-
-(defun org-velocity-dabbrev-completion-list (abbrev)
-  "Return all dabbrev completions for ABBREV."
-  ;; This is based on `dabbrev-completion'.
-  (dabbrev--reset-global-variables)
-  (setq dabbrev--last-abbreviation abbrev)
-  (dabbrev--find-all-expansions abbrev case-fold-search))
-
-(defvar org-velocity-local-completion-map
-  (let ((map (make-sparse-keymap)))
-    (set-keymap-parent map minibuffer-local-completion-map)
-    (define-key map " " 'self-insert-command)
-    (define-key map "?" 'self-insert-command)
-    (define-key map [remap minibuffer-complete] 'minibuffer-complete-word)
-    (define-key map [(control ?@)] 'org-velocity-restrict-search)
-    (define-key map [(control ?\s)] 'org-velocity-restrict-search)
-    map)
-  "Keymap for completion with `completing-read'.")
-
-(defun org-velocity-read-with-completion (prompt)
-  "Completing read with PROMPT."
-  (let ((minibuffer-local-completion-map
-         org-velocity-local-completion-map)
-        (completion-no-auto-exit t)
-        (crm-separator " "))
-    (completing-read prompt
-                     (completion-table-dynamic
-                      'org-velocity-dabbrev-completion-list))))
-
-(cl-defun org-velocity-adjust-index
-    (&optional (match-window (org-velocity-match-window)))
-  "Truncate or extend `org-velocity-index' to the lines in
-MATCH-WINDOW."
-  (with-selected-window match-window
-    (let ((lines (window-height))
-          (hints (length org-velocity-index)))
-      (cond ((= lines hints)
-             org-velocity-index)
-            ;; Truncate the index to the size of
-            ;; the buffer to be displayed.
-            ((< lines hints)
-             (cl-subseq org-velocity-index 0 lines))
-            ;; If the window is so tall we run out of indices, at
-            ;; least make the additional results clickable.
-            ((> lines hints)
-             (append org-velocity-index
-                     (make-list (- lines hints) nil)))))))
-
-(defun org-velocity-incremental-read (prompt)
-  "Read string with PROMPT and display results incrementally.
-Stop searching once there are more matches than can be
-displayed."
-  (let ((res
-         (unwind-protect
-             (let* ((match-window (display-buffer (org-velocity-match-buffer)))
-                    (org-velocity-index (org-velocity-adjust-index 
match-window)))
-               (catch 'click
-                 (add-hook 'post-command-hook 'org-velocity-update)
-                 (cond ((eq org-velocity-search-method 'regexp)
-                        (read-regexp prompt))
-                       (org-velocity-use-completion
-                        (org-velocity-read-with-completion prompt))
-                       (t (read-string prompt)))))
-           (remove-hook 'post-command-hook 'org-velocity-update))))
-    (if (bufferp res) (org-pop-to-buffer-same-window res) res)))
-
-(defun org-velocity (arg &optional search)
-  "Read a search string SEARCH for Org-Velocity interface.
-This means that a buffer will display all headings where SEARCH
-occurs, where one can be selected by a mouse click or by typing
-its index.  If SEARCH does not occur, then a new heading may be
-created named SEARCH.
-
-If `org-velocity-bucket' is defined and
-`org-velocity-always-use-bucket' is non-nil, then the bucket file
-will be used; otherwise, this will work when called in any Org
-file.
-
-Calling with ARG reverses which file โ€“ the current file or the
-bucket file โ€“ to use. If the bucket file would have been used,
-then the current file is used instead, and vice versa."
-  (interactive "P")
-  (let ((org-velocity-always-use-bucket
-         (if org-velocity-always-use-bucket
-             (not arg)
-           arg)))
-    ;; complain if inappropriate
-    (cl-assert (org-velocity-bucket-file))
-    (let* ((starting-buffer (current-buffer))
-           (org-velocity-bucket-buffer
-            (find-file-noselect (org-velocity-bucket-file)))
-           (org-velocity-navigating
-            (eq starting-buffer org-velocity-bucket-buffer))
-           (org-velocity-recursive-headings '())
-           (org-velocity-recursive-search '())
-           (org-velocity-heading-level
-            (if org-velocity-navigating
-                0
-              org-velocity-heading-level))
-           (dabbrev-search-these-buffers-only
-            (list org-velocity-bucket-buffer)))
-      (unwind-protect
-          (let ((match
-                 (catch 'org-velocity-done
-                   (org-velocity-engine
-                    (or search
-                        (org-velocity-incremental-read "Velocity search: ")))
-                   nil)))
-            (when (org-velocity-heading-p match)
-              (org-velocity-edit-entry match)))
-        (kill-buffer (org-velocity-match-buffer))))))
-
-(defalias 'org-velocity-read 'org-velocity)
-
-(provide 'org-velocity)
-
-;;; org-velocity.el ends here
diff --git a/contrib/lisp/org-wikinodes.el b/contrib/lisp/org-wikinodes.el
deleted file mode 100644
index 676f8a3..0000000
--- a/contrib/lisp/org-wikinodes.el
+++ /dev/null
@@ -1,327 +0,0 @@
-;;; org-wikinodes.el --- Wiki-like CamelCase links to outline nodes
-
-;; Copyright (C) 2010-2021 Free Software Foundation, Inc.
-
-;; Author: Carsten Dominik <carsten at orgmode dot org>
-;; Keywords: outlines, hypermedia, calendar, wp
-;; Homepage: https://orgmode.org
-;; Version: 7.01trans
-;;
-;; This file is not 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/>.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(require 'org)
-(eval-when-compile
-  (require 'cl))
-
-(defgroup org-wikinodes nil
-  "Wiki-like CamelCase links words to outline nodes in Org mode."
-  :tag "Org WikiNodes"
-  :group 'org)
-
-(defconst org-wikinodes-camel-regexp "\\<[A-Z]+[a-z]+[A-Z]+[a-z]+[a-zA-Z]*\\>"
-  "Regular expression matching CamelCase words.")
-
-(defcustom org-wikinodes-active t
-  "Should CamelCase links be active in the current file?"
-  :group 'org-wikinodes
-  :type 'boolean)
-(put 'org-wikinodes-active 'safe-local-variable 'booleanp)
-
-(defcustom org-wikinodes-scope 'file
-  "The scope of searches for wiki targets.
-Allowed values are:
-
-file       Search for targets in the current file only
-directory  Search for targets in all org files in the current directory"
-  :group 'org-wikinodes
-  :type '(choice
-         (const :tag "Find targets in current file" file)
-         (const :tag "Find targets in current directory" directory)))
-
-(defcustom org-wikinodes-create-targets 'query
-  "Non-nil means create Wiki target when following a wiki link fails.
-Allowed values are:
-
-nil     never create node, just throw an error if the target does not exist
-query   ask the user what to do
-t       create the node in the current buffer
-\"file.org\"  create the node in the file \"file.org\", in the same directory
-
-If you are using wiki links across files, you need to set `org-wikinodes-scope'
-to `directory'."
-  :group 'org-wikinodes
-  :type '(choice
-         (const :tag "Never automatically create node" nil)
-         (const :tag "In current file" t)
-         (file  :tag "In one special file\n")
-         (const :tag "Query the user" query)))
-
-;;; Link activation
-
-(defun org-wikinodes-activate-links (limit)
-  "Activate CamelCase words as links to Wiki targets."
-  (when org-wikinodes-active
-    (let (case-fold-search)
-      (if (re-search-forward org-wikinodes-camel-regexp limit t)
-         (if (equal (char-after (point-at-bol)) ?*)
-             (progn
-               ;; in  heading - deactivate flyspell
-               (org-remove-flyspell-overlays-in (match-beginning 0)
-                                                (match-end 0))
-               t)
-           ;; this is a wiki link
-           (org-remove-flyspell-overlays-in (match-beginning 0)
-                                            (match-end 0))
-           (add-text-properties (match-beginning 0) (match-end 0)
-                                (list 'mouse-face 'highlight
-                                      'face 'org-link
-                                      'keymap org-mouse-map
-                                      'help-echo "Wiki Link"))
-           t)))))
-
-;;; Following links and creating non-existing target nodes
-
-(defun org-wikinodes-open-at-point ()
-  "Check if the cursor is on a Wiki link and follow the link.
-
-This function goes into `org-open-at-point-functions'."
-  (and org-wikinodes-active
-       (not (org-at-heading-p))
-       (let (case-fold-search) (org-in-regexp org-wikinodes-camel-regexp))
-       (progn (org-wikinodes-follow-link (match-string 0)) t)))
-
-(defun org-wikinodes-follow-link (target)
-  "Follow a wiki link to TARGET.
-
-This need to be found as an exact headline match, either in the current
-buffer, or in any .org file in the current directory, depending on the
-variable `org-wikinodes-scope'.
-
-If a target headline is not found, it may be created according to the
-setting of `org-wikinodes-create-targets'."
-  (if current-prefix-arg (org-wikinodes-clear-directory-targets-cache))
-  (let ((create org-wikinodes-create-targets)
-       visiting buffer m pos file rpl)
-    (setq pos
-         (or (org-find-exact-headline-in-buffer target (current-buffer))
-             (and (eq org-wikinodes-scope 'directory)
-                  (setq file (org-wikinodes-which-file
-                              target (file-name-directory (buffer-file-name))))
-                  (org-find-exact-headline-in-buffer
-                   target (or (get-file-buffer file)
-                              (find-file-noselect file))))))
-    (if pos
-       (progn
-         (org-mark-ring-push (point))
-         (org-goto-marker-or-bmk pos)
-         (move-marker pos nil))
-      (when (eq create 'query)
-       (if (eq org-wikinodes-scope 'directory)
-           (progn
-             (message "Node \"%s\" does not exist.  Should it be created?
-\[RET] in this buffer   [TAB] in another file  [q]uit" target)
-             (setq rpl (read-char-exclusive))
-             (cond
-              ((member rpl '(?\C-g ?q)) (error "Abort"))
-              ((equal rpl ?\C-m) (setq create t))
-              ((equal rpl ?\C-i)
-               (setq create (file-name-nondirectory
-                             (read-file-name "Create in file: "))))
-              (t (error "Invalid selection"))))
-         (if (y-or-n-p (format "Create new node \"%s\" in current buffer? "
-                               target))
-             (setq create t)
-           (error "Abort"))))
-
-      (cond
-       ((not create)
-       ;; We are not allowed to create the new node
-       (error "No match for link to \"%s\"" target))
-       ((stringp create)
-       ;; Make new node in another file
-       (org-mark-ring-push (point))
-       (org-pop-to-buffer-same-window (find-file-noselect create))
-       (goto-char (point-max))
-       (or (bolp) (newline))
-       (insert "\n* " target "\n")
-       (backward-char 1)
-       (org-wikinodes-add-target-to-cache target)
-       (message "New Wiki target `%s' created in file \"%s\""
-                target create))
-       (t
-       ;; Make new node in current buffer
-       (org-mark-ring-push (point))
-       (goto-char (point-max))
-       (or (bolp) (newline))
-       (insert "* " target "\n")
-       (backward-char 1)
-       (org-wikinodes-add-target-to-cache target)
-       (message "New Wiki target `%s' created in current buffer"
-                target))))))
-
-;;; The target cache
-
-(defvar org-wikinodes-directory-targets-cache nil)
-
-(defun org-wikinodes-clear-cache-when-on-target ()
-  "When on a headline that is a Wiki target, clear the cache."
-  (when (and (org-at-heading-p)
-            (org-in-regexp (format org-complex-heading-regexp-format
-                                   org-wikinodes-camel-regexp))
-            (org-in-regexp org-wikinodes-camel-regexp))
-    (org-wikinodes-clear-directory-targets-cache)
-    t))
-
-(defun org-wikinodes-clear-directory-targets-cache ()
-  "Clear the cache where to find wiki targets."
-  (interactive)
-  (setq org-wikinodes-directory-targets-cache nil)
-  (message "Wiki target cache cleared, so that it will update when used 
again"))
-
-(defun org-wikinodes-get-targets ()
-  "Return a list of all wiki targets in the current buffer."
-  (let ((re (format org-complex-heading-regexp-format
-                   org-wikinodes-camel-regexp))
-       (case-fold-search nil)
-       targets)
-    (save-excursion
-      (save-restriction
-       (widen)
-       (goto-char (point-min))
-       (while (re-search-forward re nil t)
-         (push (match-string-no-properties 4) targets))))
-    (nreverse targets)))
-
-(defun org-wikinodes-get-links-for-directory (dir)
-  "Return an alist that connects wiki links to files in directory DIR."
-  (let ((files (directory-files dir nil "\\`[^.#].*\\.org\\'"))
-       (org-inhibit-startup t)
-       target-file-alist file visiting m buffer)
-    (while (setq file (pop files))
-      (setq visiting (org-find-base-buffer-visiting file))
-      (setq buffer (or visiting (find-file-noselect file)))
-      (with-current-buffer buffer
-       (mapc
-        (lambda (target)
-          (setq target-file-alist (cons (cons target file) target-file-alist)))
-        (org-wikinodes-get-targets)))
-      (or visiting (kill-buffer buffer)))
-    target-file-alist))
-
-(defun org-wikinodes-add-target-to-cache (target &optional file)
-  (setq file (or file buffer-file-name (error "No file for new wiki target")))
-  (set-text-properties 0 (length target) nil target)
-  (let ((dir (file-name-directory (expand-file-name file)))
-       a)
-    (setq a (assoc dir org-wikinodes-directory-targets-cache))
-    (if a
-       ;; Push the new target onto the existing list
-       (push (cons target (expand-file-name file)) (cdr a))
-      ;; Call org-wikinodes-which-file so that the cache will be filled
-      (org-wikinodes-which-file target dir))))
-
-(defun org-wikinodes-which-file (target &optional directory)
-  "Return the file for wiki headline TARGET DIRECTORY.
-If there is no such wiki target, return nil."
-  (let* ((directory (expand-file-name (or directory default-directory)))
-        (founddir (assoc directory org-wikinodes-directory-targets-cache))
-        (foundfile (cdr (assoc target (cdr founddir)))))
-    (or foundfile
-       (and (push (cons directory (org-wikinodes-get-links-for-directory 
directory))
-                  org-wikinodes-directory-targets-cache)
-            (cdr (assoc target (cdr (assoc directory
-                                           
org-wikinodes-directory-targets-cache))))))))
-
-;;; Exporting Wiki links
-
-(defvar target)
-(defvar target-alist)
-(defvar last-section-target)
-(defvar org-export-target-aliases)
-(defun org-wikinodes-set-wiki-targets-during-export (_)
-  (let ((line (buffer-substring (point-at-bol) (point-at-eol)))
-       (case-fold-search nil)
-       wtarget a)
-    (when (string-match (format org-complex-heading-regexp-format
-                               org-wikinodes-camel-regexp)
-                       line)
-      (setq wtarget (match-string 4 line))
-      (push (cons wtarget target) target-alist)
-      (setq a (or (assoc last-section-target org-export-target-aliases)
-                 (progn
-                   (push (list last-section-target)
-                         org-export-target-aliases)
-                   (car org-export-target-aliases))))
-      (push (caar target-alist) (cdr a)))))
-
-(defun org-wikinodes-process-links-for-export (_)
-  "Process Wiki links in the export preprocess buffer.
-Try to find target matches in the wiki scope and replace CamelCase words
-with working links."
-  (let ((re org-wikinodes-camel-regexp)
-       (case-fold-search nil)
-       link file)
-    (goto-char (point-min))
-    (while (re-search-forward re nil t)
-      (unless (save-match-data
-               (or (org-at-heading-p)
-                   (org-in-regexp org-bracket-link-regexp)
-                   (org-in-regexp org-plain-link-re)
-                   (org-in-regexp "<<[^<>]+>>")))
-       (setq link (match-string 0))
-       (delete-region (match-beginning 0) (match-end 0))
-       (save-match-data
-         (cond
-          ((org-find-exact-headline-in-buffer link (current-buffer))
-           ;; Found in current buffer
-           (insert (format "[[*%s][%s]]" link link)))
-          ((eq org-wikinodes-scope 'file)
-           ;; No match in file, and other files are not allowed
-           (insert (format "%s" link)))
-          (t ;; No match for this link
-           (insert (format "%s" link)))))))))
-
-;;; Hook the WikiNode mechanism into Org
-
-;; `C-c C-o' should follow wiki links
-(add-hook 'org-open-at-point-functions 'org-wikinodes-open-at-point)
-
-;; `C-c C-c' should clear the cache
-(add-hook 'org-ctrl-c-ctrl-c-hook 'org-wikinodes-clear-cache-when-on-target)
-
-;; Make Wiki haeding create additional link names for headlines
-(add-hook 'org-export-before-parsing-hook
-         'org-wikinodes-set-wiki-targets-during-export)
-
-;; Turn Wiki links into links the exporter will treat correctly
-(add-hook 'org-export-before-parsing-hook
-         'org-wikinodes-process-links-for-export)
-
-;; Activate CamelCase words as part of Org mode font lock
-
-(defun org-wikinodes-add-to-font-lock-keywords ()
-  "Add wikinode CamelCase highlighting to `org-font-lock-extra-keywords'."
-  (let ((m (member '(org-activate-links) org-font-lock-extra-keywords)))
-    (if m (push '(org-wikinodes-activate-links) (cdr m))
-      (message "Failed to add wikinodes to `org-font-lock-extra-keywords'."))))
-
-(add-hook 'org-font-lock-set-keywords-hook
-         'org-wikinodes-add-to-font-lock-keywords)
-
-(provide 'org-wikinodes)
-
-;;; org-wikinodes.el ends here
diff --git a/contrib/lisp/orgtbl-sqlinsert.el b/contrib/lisp/orgtbl-sqlinsert.el
deleted file mode 100644
index 6e1fcba..0000000
--- a/contrib/lisp/orgtbl-sqlinsert.el
+++ /dev/null
@@ -1,118 +0,0 @@
-;;; orgtbl-sqlinsert.el --- orgtbl to SQL insert statements.
-
-;; Copyright (C) 2008-2021  Free Software Foundation
-
-;; Author: Jason Riedy <jason@acm.org>
-;; Keywords: org, tables, sql
-
-;; This file is not 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 this program.  If not, see <http://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; Converts an orgtbl to a sequence of SQL insertion commands.
-;; Table cells are quoted and escaped very conservatively.
-
-;;; Code:
-
-(defun orgtbl-to-sqlinsert (table params)
-  "Convert the orgtbl-mode TABLE to SQL insert statements.
-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.
-
-Names and strings are modified slightly by default.  Single-ticks
-are doubled as per SQL's standard mechanism.  Backslashes and
-dollar signs are deleted.  And tildes are changed to spaces.
-These modifications were chosen for use with TeX.  See
-ORGTBL-SQL-STRIP-AND-QUOTE.
-
-Supports all parameters from ORGTBL-TO-GENERIC.  New to this function
-are:
-
-:sqlname   The name of the database table; defaults to the name of the
-           target region.
-
-:nowebname If not nil, used as a wrapping noweb fragment name.
-
-The most important parameters of ORGTBL-TO-GENERIC for SQL are:
-
-:splice    When set to t, return only insert statements, don't wrap
-           them in a transaction.  Default is nil.
-
-:tstart, :tend
-           The strings used to begin and commit the transaction.
-
-:hfmt      A function that gathers the quoted header names into a
-           dynamically scoped variable HDRLIST.  Probably should
-           not be changed by the user.
-
-The general parameters :skip and :skipcols have already been applied when
-this function is called."
-  (let* (hdrlist
-        (alignment (mapconcat (lambda (x) (if x "r" "l"))
-                              org-table-last-alignment ""))
-        (nowebname (plist-get params :nowebname))
-        (breakvals (plist-get params :breakvals))
-         (firstheader t)
-         (*orgtbl-default-fmt* 'orgtbl-sql-strip-and-quote)
-        (params2
-         (list
-          :sqlname (plist-get params :sqlname)
-          :tstart (lambda () (concat (if nowebname
-                                         (format "<<%s>>= \n" nowebname)
-                                       "")
-                                     "BEGIN TRANSACTION;"))
-          :tend (lambda () (concat "COMMIT;" (if nowebname "\n@ " "")))
-          :hfmt (lambda (f) (progn (if firstheader (push f hdrlist) "")))
-          :hlfmt (lambda (&rest cells) (setq firstheader nil))
-          :lstart (lambda () (concat "INSERT INTO "
-                                     sqlname "( "
-                                     (mapconcat 'identity (reverse hdrlist)
-                                                ", ")
-                                     " )" (if breakvals "\n" " ")
-                                     "VALUES ( "))
-          :lend " );"
-          :sep " , "
-          :hline nil
-          :remove-nil-lines t))
-        (params (org-combine-plists params2 params))
-         (sqlname (plist-get params :sqlname)))
-    (orgtbl-to-generic table params)))
-
-(defun orgtbl-sql-quote (str)
-  "Convert single ticks to doubled single ticks and wrap in single ticks."
-  (concat "'" (mapconcat 'identity (split-string str "'") "''") "'"))
-
-(defun orgtbl-sql-strip-dollars-escapes-tildes (str)
-  "Strip dollarsigns and backslash escapes, replace tildes with spaces."
-  (mapconcat 'identity
-            (split-string (mapconcat 'identity
-                                     (split-string str "\\$\\|\\\\")
-                                     "")
-                          "~")
-            " "))
-
-(defun orgtbl-sql-strip-and-quote (str)
-  "Apply ORGBTL-SQL-QUOTE and ORGTBL-SQL-STRIP-DOLLARS-ESCAPES-TILDES
-to sanitize STR for use in SQL statements."
-  (cond ((stringp str)
-         (orgtbl-sql-quote (orgtbl-sql-strip-dollars-escapes-tildes str)))
-        ((sequencep str) (mapcar 'orgtbl-sql-strip-and-quote str))
-        (t nil)))
-
-(provide 'orgtbl-sqlinsert)
-
-;;; orgtbl-sqlinsert.el ends here
diff --git a/contrib/lisp/ox-bibtex.el b/contrib/lisp/ox-bibtex.el
deleted file mode 100644
index 54f446d..0000000
--- a/contrib/lisp/ox-bibtex.el
+++ /dev/null
@@ -1,430 +0,0 @@
-;;; ox-bibtex.el --- Export bibtex fragments
-
-;; Copyright (C) 2009-2014 Taru Karttunen
-
-;; Author: Taru Karttunen <taruti@taruti.net>
-;;      Nicolas Goaziou <n dot goaziou at gmail dot com>
-;; This file is not currently 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 2, 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 ; see the file COPYING.  If not, write to
-;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-;;
-;; This is an utility to handle BibTeX export to LaTeX, html and ascii
-;; exports.  For HTML and ascii it uses the bibtex2html software from:
-;;
-;;   http://www.lri.fr/~filliatr/bibtex2html/
-;;
-;; For ascii it uses the pandoc software from:
-;;
-;;   http://johnmacfarlane.net/pandoc/
-;;
-;; It also introduces "cite" syntax for Org links.
-;;
-;; The usage is as follows:
-;;
-;;   #+BIBLIOGRAPHY: bibfilename stylename optional-options
-;;
-;; e.g. given foo.bib and using style plain:
-;;
-;;   #+BIBLIOGRAPHY: foo plain option:-d
-;;
-;; "stylename" can also be "nil", in which case no style will be used.
-;;
-;; Full filepaths are also possible:
-;;
-;;   #+BIBLIOGRAPHY: /home/user/Literature/foo.bib plain option:-d
-;;
-;; Optional options are of the form:
-;;
-;;   option:-foobar pass '-foobar' to bibtex2html
-;;
-;; e.g.,
-;;
-;;   option:-d    sort by date
-;;   option:-a    sort as BibTeX (usually by author) *default*
-;;   option:-u    unsorted i.e. same order as in .bib file
-;;   option:-r    reverse the sort
-;;
-;; See the bibtex2html man page for more.  Multiple options can be
-;; combined like:
-;;
-;;   option:-d option:-r
-;;
-;; Limiting to only the entries cited in the document:
-;;
-;;   limit:t
-;;
-;; For LaTeX export this simply inserts the lines
-;;
-;;   \bibliographystyle{plain}
-;;   \bibliography{foo}
-;;
-;; into the TeX file when exporting.
-;;
-;; For HTML export it:
-;; 1) converts all \cite{foo} and [[cite:foo]] to links to the
-;;    bibliography,
-;; 2) creates a foo.html and foo_bib.html,
-;; 3) includes the contents of foo.html in the exported HTML file.
-;;
-;; For ascii export it:
-;; 1) converts all \cite{foo} and [[cite:foo]] to links to the
-;;    bibliography,
-;; 2) creates a foo.txt and foo_bib.html,
-;; 3) includes the contents of foo.txt in the exported ascii file.
-;;
-;; For LaTeX export it:
-;; 1) converts all [[cite:foo]] to \cite{foo}.
-
-;; Initialization
-
-(require 'cl-lib)
-
-;;; Internal Functions
-
-(defun org-bibtex-get-file (keyword)
-  "Return bibliography file as a string.
-KEYWORD is a \"BIBLIOGRAPHY\" keyword. If no file is found,
-return nil instead."
-  (let ((value (org-element-property :value keyword)))
-    (and value
-         (string-match "\\(\\S-+\\)[ \t]+\\(\\S-+\\)\\(.*\\)" value)
-         (match-string 1 value))))
-
-(defun org-bibtex-get-style (keyword)
-  "Return bibliography style as a string.
-KEYWORD is a \"BIBLIOGRAPHY\" keyword. If no style is found,
-return nil instead."
-  (let ((value (org-element-property :value keyword)))
-    (and value
-         (string-match "\\(\\S-+\\)[ \t]+\\(\\S-+\\)\\(.*\\)" value)
-         (match-string 2 value))))
-
-(defun org-bibtex-get-arguments (keyword)
-  "Return \"bibtex2html\" arguments specified by the user.
-KEYWORD is a \"BIBLIOGRAPHY\" keyword. Return value is a plist
-containing `:options' and `:limit' properties.  The former
-contains a list of strings to be passed as options to
-\"bibtex2html\" process.  The latter contains a boolean."
-  (let ((value (org-element-property :value keyword)))
-    (and value
-         (string-match "\\(\\S-+\\)[ \t]+\\(\\S-+\\)\\(.*\\)" value)
-         (let (options limit)
-           (dolist (arg (split-string (match-string 3 value))
-                        ;; Return value.
-                        (list :options (nreverse options) :limit limit))
-             (let* ((s (split-string arg ":"))
-                    (key (car s))
-                    (value (nth 1 s)))
-               (cond ((equal "limit" key)
-                      (setq limit (not (equal "nil" value))))
-                     ((equal "option" key) (push value options)))))))))
-
-(defun org-bibtex-citation-p (object)
-  "Non-nil when OBJECT is a citation."
-  (cl-case (org-element-type object)
-    (link (equal (org-element-property :type object) "cite"))
-    (latex-fragment
-     (string-match "\\`\\\\cite{" (org-element-property :value object)))))
-
-(defun org-bibtex-get-citation-key (citation)
-  "Return key for a given citation, as a string.
-CITATION is a `latex-fragment' or `link' type object satisfying
-to `org-bibtex-citation-p' predicate."
-  (if (eq (org-element-type citation) 'link)
-      (org-element-property :path citation)
-    (let ((value (org-element-property :value citation)))
-      (and (string-match "\\`\\\\cite{" value)
-          (substring value (match-end 0) -1)))))
-
-
-;;; Follow cite: links
-
-(defvar org-bibtex-file nil
-  "Org file of BibTeX entries.")
-
-(defun org-bibtex-goto-citation (&optional citation)
-  "Visit a citation given its ID."
-  (interactive)
-  (let ((citation (or citation (completing-read "Citation: " 
(obe-citations)))))
-    (find-file (or org-bibtex-file
-                  (error "`org-bibtex-file' has not been configured")))
-    (let ((position (org-find-property "CUSTOM_ID" citation)))
-      (and position (progn (goto-char position) t)))))
-
-(let ((jump-fn (car (cl-remove-if-not #'fboundp '(ebib 
org-bibtex-goto-citation)))))
-  (org-add-link-type "cite" jump-fn))
-
-
-
-;;; Filters
-
-(defun org-bibtex-process-bib-files (tree backend info)
-  "Send each bibliography in parse tree to \"bibtex2html\" process.
-Return new parse tree."
-  (when (org-export-derived-backend-p backend 'ascii 'html)
-    ;; Initialize dynamically scoped variables.  The first one
-    ;; contain an alist between keyword objects and their HTML
-    ;; translation.  The second one will contain an alist between
-    ;; citation keys and names in the output (according to style).
-    (setq org-bibtex-html-entries-alist nil
-         org-bibtex-html-keywords-alist nil)
-    (org-element-map tree 'keyword
-      (lambda (keyword)
-       (when (equal (org-element-property :key keyword) "BIBLIOGRAPHY")
-         (let ((arguments (org-bibtex-get-arguments keyword))
-               (file (org-bibtex-get-file keyword))
-               temp-file
-               out-file)
-           ;; Test if filename is given with .bib-extension and strip
-           ;; it off. Filenames with another extensions will be
-           ;; untouched and will finally rise an error in bibtex2html.
-           (setq file (if (equal (file-name-extension file) "bib")
-                          (file-name-sans-extension file) file))
-           ;; Outpufiles of bibtex2html will be put into current working 
directory
-           ;; so define a variable for this.
-           (setq out-file (file-name-sans-extension
-                           (file-name-nondirectory file)))
-           ;; limit is set: collect citations throughout the document
-           ;; in TEMP-FILE and pass it to "bibtex2html" as "-citefile"
-           ;; argument.
-           (when (plist-get arguments :limit)
-             (let ((citations
-                    (org-element-map tree '(latex-fragment link)
-                      (lambda (object)
-                        (and (org-bibtex-citation-p object)
-                             (org-bibtex-get-citation-key object))))))
-               (with-temp-file (setq temp-file (make-temp-file "ox-bibtex"))
-                 (insert (mapconcat 'identity citations "\n")))
-               (setq arguments
-                     (plist-put arguments
-                                :options
-                                (append (plist-get arguments :options)
-                                        (list "-citefile" temp-file))))))
-           ;; Call "bibtex2html" on specified file.
-           (unless (eq 0 (apply
-                          'call-process
-                          (append '("bibtex2html" nil nil nil)
-                                  '("-a" "-nodoc" "-noheader" "-nofooter")
-                                  (let ((style
-                                         (org-not-nil
-                                          (org-bibtex-get-style keyword))))
-                                    (and style (list "--style" style)))
-                                  (plist-get arguments :options)
-                                  (list (concat file ".bib")))))
-             (error "Executing bibtex2html failed"))
-           (and temp-file (delete-file temp-file))
-           ;; Open produced HTML file, and collect Bibtex key names
-           (with-temp-buffer
-             (insert-file-contents (concat out-file ".html"))
-             ;; Update `org-bibtex-html-entries-alist'.
-             (goto-char (point-min))
-             (while (re-search-forward
-                     "a name=\"\\([-_a-zA-Z0-9:]+\\)\">\\([^<]+\\)" nil t)
-               (push (cons (match-string 1) (match-string 2))
-                     org-bibtex-html-entries-alist)))
-           ;; Open produced HTML file, wrap references within a block and
-           ;; return it.
-           (with-temp-buffer
-             (cond
-              ((org-export-derived-backend-p backend 'html)
-               (insert (format "<div id=\"bibliography\">\n<h2>%s</h2>\n"
-                               (org-export-translate "References" :html info)))
-               (insert-file-contents (concat out-file ".html"))
-               (goto-char (point-max))
-               (insert "\n</div>"))
-              ((org-export-derived-backend-p backend 'ascii)
-               ;; convert HTML references to text w/pandoc
-               (unless (eq 0 (call-process "pandoc" nil nil nil
-                                           (concat out-file ".html")
-                                           "-o"
-                                           (concat out-file ".txt")))
-                 (error "Executing pandoc failed"))
-               (insert
-                (format
-                 "%s\n==========\n\n"
-                 (org-export-translate
-                  "References"
-                  (intern (format ":%s" (plist-get info :ascii-charset)))
-                  info)))
-               (insert-file-contents (concat out-file ".txt"))
-               (goto-char (point-min))
-               (while (re-search-forward
-                       "\\[ย \\[bib\\][^ย ]+ย \\(\\]\\||[\n\r]\\)" nil t)
-                 (replace-match ""))
-               (goto-char (point-min))
-               (while (re-search-forward "\\(ย \\]\\|ย \\]\\|ย |\\)" nil t)
-                 (replace-match ""))
-               (goto-char (point-min))
-               (while (re-search-forward "[\n\r]\\([\n\r][\n\r]\\)" nil t)
-                 (replace-match "\\1"))))
-             ;; Update `org-bibtex-html-keywords-alist'.
-             (push (cons keyword (buffer-string))
-                   org-bibtex-html-keywords-alist)))))))
-  ;; Return parse tree unchanged.
-  tree)
-
-(defun org-bibtex-merge-contiguous-citations (tree backend info)
-  "Merge all contiguous citation in parse tree.
-As a side effect, this filter will also turn all \"cite\" links
-into \"\\cite{...}\" LaTeX fragments and will extract options.
-Cite options are placed into square brackets at the beginning of
-the \"\\cite\" command for the LaTeX backend, and are removed for
-the HTML and ASCII backends."
-  (when (org-export-derived-backend-p backend 'html 'latex 'ascii)
-    (org-element-map tree '(link latex-fragment)
-      (lambda (object)
-       (when (org-bibtex-citation-p object)
-         (let ((new-citation (list 'latex-fragment
-                                   (list :value ""
-                                         :post-blank (org-element-property
-                                                      :post-blank object))))
-               option)
-           ;; Insert NEW-CITATION right before OBJECT.
-           (org-element-insert-before new-citation object)
-           ;; Remove all subsequent contiguous citations from parse
-           ;; tree, keeping only their citation key.
-           (let ((keys (list (org-bibtex-get-citation-key object)))
-                 next)
-             (while (and (setq next (org-export-get-next-element object info))
-                         (or (and (stringp next)
-                                  (not (string-match-p "\\S-" next)))
-                             (org-bibtex-citation-p next)))
-               (unless (stringp next)
-                 (push (org-bibtex-get-citation-key next) keys))
-               (org-element-extract-element object)
-               (setq object next))
-             ;; Find any options in keys, e.g., "(Chapter 2)key" has
-             ;; the option "Chapter 2".
-             (setq keys
-                   (mapcar
-                    (lambda (k)
-                      (if (string-match "^(\\([^)]\+\\))\\(.*\\)" k)
-                          (progn
-                            (when (org-export-derived-backend-p backend 'latex)
-                              (setq option (format "[%s]" (match-string 1 k))))
-                            (match-string 2 k))
-                        k))
-                    keys))
-             (org-element-extract-element object)
-             ;; Eventually merge all keys within NEW-CITATION.  Also
-             ;; ensure NEW-CITATION has the same :post-blank property
-             ;; as the last citation removed.
-             (org-element-put-property
-              new-citation
-              :post-blank (org-element-property :post-blank object))
-             (org-element-put-property
-              new-citation
-              :value (format "\\cite%s{%s}"
-                             (or option "")
-                             (mapconcat 'identity (nreverse keys) ",")))))))))
-  tree)
-
-(eval-after-load 'ox
-  '(progn (add-to-list 'org-export-filter-parse-tree-functions
-                      'org-bibtex-process-bib-files)
-         (add-to-list 'org-export-filter-parse-tree-functions
-                      'org-bibtex-merge-contiguous-citations)))
-
-
-
-;;; LaTeX Part
-
-(defadvice org-latex-keyword (around bibtex-keyword)
-  "Translate \"BIBLIOGRAPHY\" keywords into LaTeX syntax.
-Fallback to `latex' back-end for other keywords."
-  (let ((keyword (ad-get-arg 0)))
-    (if (not (equal (org-element-property :key keyword) "BIBLIOGRAPHY"))
-        ad-do-it
-      (let ((file (org-bibtex-get-file keyword))
-            (style (org-not-nil (org-bibtex-get-style keyword))))
-        (setq ad-return-value
-              (when file
-                (concat (and style (format "\\bibliographystyle{%s}\n" style))
-                        (format "\\bibliography{%s}" file))))))))
-
-(ad-activate 'org-latex-keyword)
-
-
-
-;;; HTML Part
-
-(defvar org-bibtex-html-entries-alist nil)  ; Dynamically scoped.
-(defvar org-bibtex-html-keywords-alist nil) ; Dynamically scoped.
-
-
-;;;; Advices
-
-(defadvice org-html-keyword (around bibtex-keyword)
-  "Translate \"BIBLIOGRAPHY\" keywords into HTML syntax.
-Fallback to `html' back-end for other keywords."
-  (let ((keyword (ad-get-arg 0)))
-    (if (not (equal (org-element-property :key keyword) "BIBLIOGRAPHY"))
-        ad-do-it
-      (setq ad-return-value
-            (cdr (assq keyword org-bibtex-html-keywords-alist))))))
-
-(defadvice org-html-latex-fragment (around bibtex-citation)
-  "Translate \"\\cite\" LaTeX fragments into HTML syntax.
-Fallback to `html' back-end for other keywords."
-  (let ((fragment (ad-get-arg 0)))
-    (if (not (org-bibtex-citation-p fragment)) ad-do-it
-      (setq ad-return-value
-            (format "[%s]"
-                   (mapconcat
-                    (lambda (key)
-                      (format "<a href=\"#%s\">%s</a>"
-                              key
-                              (or (cdr (assoc key 
org-bibtex-html-entries-alist))
-                                  key)))
-                    (org-split-string
-                     (org-bibtex-get-citation-key fragment) ",") ","))))))
-
-(ad-activate 'org-html-keyword)
-(ad-activate 'org-html-latex-fragment)
-
-
-;;; Ascii Part
-(defadvice org-ascii-keyword (around bibtex-keyword)
-  "Translate \"BIBLIOGRAPHY\" keywords into ascii syntax.
-Fallback to `ascii' back-end for other keywords."
-  (let ((keyword (ad-get-arg 0)))
-    (if (not (equal (org-element-property :key keyword) "BIBLIOGRAPHY"))
-        ad-do-it
-      (setq ad-return-value
-            (cdr (assq keyword org-bibtex-html-keywords-alist))))))
-
-(defadvice org-ascii-latex-fragment (around bibtex-citation)
-  "Translate \"\\cite\" LaTeX fragments into ascii syntax.
-Fallback to `ascii' back-end for other keywords."
-  (let ((fragment (ad-get-arg 0)))
-    (if (not (org-bibtex-citation-p fragment)) ad-do-it
-      (setq ad-return-value
-            (format "[%s]"
-                   (mapconcat
-                    (lambda (key)
-                      (or (cdr (assoc key org-bibtex-html-entries-alist))
-                          key))
-                    (org-split-string
-                     (org-bibtex-get-citation-key fragment) ",") ","))))))
-
-(ad-activate 'org-ascii-keyword)
-(ad-activate 'org-ascii-latex-fragment)
-
-(provide 'ox-bibtex)
-
-;;; ox-bibtex.el ends here
diff --git a/contrib/lisp/ox-confluence.el b/contrib/lisp/ox-confluence.el
deleted file mode 100644
index 4f40eec..0000000
--- a/contrib/lisp/ox-confluence.el
+++ /dev/null
@@ -1,258 +0,0 @@
-;;; ox-confluence --- Confluence Wiki Back-End for Org Export Engine
-
-;; Copyright (C) 2012, 2014 Sรฉbastien Delafond
-
-;; Author: Sรฉbastien Delafond <sdelafond@gmail.com>
-;; Keywords: outlines, confluence, wiki
-
-;; This file is not 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:
-;;
-;; ox-confluence.el lets you convert Org files to confluence files
-;; using the ox.el export engine.
-;;
-;; Put this file into your load-path and the following into your ~/.emacs:
-;;      (require 'ox-confluence)
-;;
-;; Export Org files to confluence:
-;; M-x org-confluence-export-as-confluence RET
-;;
-;;; Code:
-
-(require 'ox)
-(require 'ox-ascii)
-
-;; Define the backend itself
-(org-export-define-derived-backend 'confluence 'ascii
-  :translate-alist '((bold . org-confluence-bold)
-                    (code . org-confluence-code)
-                    (example-block . org-confluence-example-block)
-                    (fixed-width . org-confluence-fixed-width)
-                    (footnote-definition . org-confluence-empty)
-                    (footnote-reference . org-confluence-empty)
-                    (headline . org-confluence-headline)
-                    (italic . org-confluence-italic)
-                    (item . org-confluence-item)
-                    (link . org-confluence-link)
-                    (paragraph . org-confluence-paragraph)
-                    (property-drawer . org-confluence-property-drawer)
-                    (quote-block . org-confluence-quote-block)
-                    (section . org-confluence-section)
-                    (src-block . org-confluence-src-block)
-                    (strike-through . org-confluence-strike-through)
-                    (table . org-confluence-table)
-                    (table-cell . org-confluence-table-cell)
-                    (table-row . org-confluence-table-row)
-                    (template . org-confluence-template)
-                    (timestamp . org-confluence-timestamp)
-                    (underline . org-confluence-underline)
-                    (verbatim . org-confluence-verbatim))
-  :menu-entry
-  '(?f "Export to Confluence"
-       ((?f "As Confluence buffer" org-confluence-export-as-confluence))))
-
-(defcustom org-confluence-lang-alist
-  '(("sh" . "bash"))
-  "Map from org-babel language name to confluence wiki language name"
-  :type '(alist :key-type string :value-type string))
-
-;; All the functions we use
-(defun org-confluence-bold (bold contents info)
-  (format "*%s*" contents))
-
-(defun org-confluence-empty (empty contents info)
-  "")
-
-(defun org-confluence-example-block (example-block contents info)
-  ;; FIXME: provide a user-controlled variable for theme
-  (let ((content (org-export-format-code-default example-block info)))
-    (org-confluence--block "none" "Confluence" content)))
-
-(defun org-confluence-italic (italic contents info)
-  (format "_%s_" contents))
-
-(defun org-confluence-item (item contents info)
-  (let ((list-type (org-element-property :type (org-export-get-parent item))))
-    (concat
-     (make-string (1+ (org-confluence--li-depth item))
-                  (if (eq list-type 'ordered) ?\# ?\-))
-     " "
-     (pcase (org-element-property :checkbox item)
-       (`on "*{{(X)}}* ")
-       (`off "*{{( )}}* ")
-       (`trans "*{{(\\-)}}* "))
-     (when (eq list-type 'descriptive)
-       (concat "*"
-              (org-export-data (org-element-property :tag item) info)
-              "* - "))
-     (org-trim contents))))
-
-(defun org-confluence-fixed-width (fixed-width contents info)
-  (org-confluence--block
-   "none"
-   "Confluence"
-   (org-trim (org-element-property :value fixed-width))))
-
-(defun org-confluence-verbatim (verbatim contents info)
-  (format "\{\{%s\}\}" (org-element-property :value verbatim)))
-
-(defun org-confluence-code (code contents info)
-  (format "\{\{%s\}\}" (org-element-property :value code)))
-
-(defun org-confluence-headline (headline contents info)
-  (let* ((low-level-rank (org-export-low-level-p headline info))
-        (text (org-export-data (org-element-property :title headline)
-                               info))
-        (todo (org-export-data (org-element-property :todo-keyword headline)
-                               info))
-        (level (org-export-get-relative-level headline info))
-        (todo-text (if (or (not (plist-get info :with-todo-keywords))
-                           (string= todo ""))
-                       ""
-                     (format "*{{%s}}* " todo))))
-    (format "h%s. %s%s\n%s" level todo-text text
-            (if (org-string-nw-p contents) contents ""))))
-
-(defun org-confluence-link (link desc info)
-  (if (string= "radio" (org-element-property :type link))
-      desc
-    (let ((raw-link (org-element-property :raw-link link)))
-      (concat "["
-              (when (org-string-nw-p desc) (format "%s|" desc))
-              (cond
-               ((string-match "^confluence:" raw-link)
-               (replace-regexp-in-string "^confluence:" "" raw-link))
-               (t
-               raw-link))
-              "]"))))
-
-(defun org-confluence-paragraph (paragraph contents info)
-  "Transcode PARAGRAPH element for Confluence.
-CONTENTS is the paragraph contents.  INFO is a plist used as
-a communication channel."
-  contents)
-
-(defun org-confluence-property-drawer (property-drawer contents info)
-  (and (org-string-nw-p contents)
-       (format "\{\{%s\}\}" contents)))
-
-(defun org-confluence-quote-block (quote-block contents info)
-  (format "{quote}\n%s{quote}" contents))
-
-(defun org-confluence-section (section contents info)
-  contents)
-
-(defun org-confluence-src-block (src-block contents info)
-  ;; FIXME: provide a user-controlled variable for theme
-  (let* ((lang (org-element-property :language src-block))
-         (language (or (cdr (assoc lang org-confluence-lang-alist)) lang))
-         (content (org-export-format-code-default src-block info)))
-    (org-confluence--block language "Emacs" content)))
-
-(defun org-confluence-strike-through (strike-through contents info)
-  (format "-%s-" contents))
-
-(defun org-confluence-table (table contents info)
-  contents)
-
-(defun org-confluence-table-row  (table-row contents info)
-  (concat
-   (if (org-string-nw-p contents) (format "|%s" contents)
-     "")
-   (when (org-export-table-row-ends-header-p table-row info)
-     "|")))
-
-(defun org-confluence-table-cell  (table-cell contents info)
-  (let ((table-row (org-export-get-parent table-cell)))
-    (concat (and (org-export-table-row-starts-header-p table-row info) "|")
-           (if (= (length contents) 0) " " contents)
-           "|")))
-
-(defun org-confluence-template (contents info)
-  (let ((depth (plist-get info :with-toc)))
-    (concat (when depth "\{toc\}\n\n") contents)))
-
-(defun org-confluence-timestamp (timestamp _contents _info)
-  "Transcode a TIMESTAMP object from Org to Confluence.
-CONTENTS and INFO are ignored."
-  (let ((translated (org-trim (org-timestamp-translate timestamp))))
-    (if (string-prefix-p "[" translated)
-        (concat "(" (substring translated 1 -1) ")")
-      translated)))
-
-(defun org-confluence-underline (underline contents info)
-  (format "+%s+" contents))
-
-(defun org-confluence--block (language theme contents)
-  (concat "\{code:theme=" theme
-          (when language (format "|language=%s" language))
-          "}\n"
-          contents
-          "\{code\}\n"))
-
-(defun org-confluence--li-depth (item)
-  "Return depth of a list item; -1 means not a list item"
-  ;; FIXME check whether it's worth it to cache depth
-  ;;       (it gets recalculated quite a few times while
-  ;;       traversing a list)
-  (let ((depth -1)
-        (tag))
-    (while (and item
-                (setq tag (car item))
-                (or (eq tag 'item) ; list items interleave with plain-list
-                    (eq tag 'plain-list)))
-      (when (eq tag 'item)
-        (cl-incf depth))
-      (setq item (org-export-get-parent item)))
-    depth))
-
-;; main interactive entrypoint
-(defun org-confluence-export-as-confluence
-  (&optional async subtreep visible-only body-only ext-plist)
-  "Export current buffer to a text buffer.
-
-If narrowing is active in the current buffer, only export its
-narrowed part.
-
-If a region is active, export that region.
-
-A non-nil optional argument ASYNC means the process should happen
-asynchronously.  The resulting buffer should be accessible
-through the `org-export-stack' interface.
-
-When optional argument SUBTREEP is non-nil, export the sub-tree
-at point, extracting information from the headline properties
-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 title, table
-of contents and footnote definitions from output.
-
-EXT-PLIST, when provided, is a property list with external
-parameters overriding Org default settings, but still inferior to
-file-local settings.
-
-Export is done in a buffer named \"*Org CONFLUENCE Export*\", which
-will be displayed when `org-export-show-temporary-export-buffer'
-is non-nil."
-  (interactive)
-  (org-export-to-buffer 'confluence "*org CONFLUENCE Export*"
-    async subtreep visible-only body-only ext-plist (lambda () (text-mode))))
-
-(provide 'ox-confluence)
diff --git a/contrib/lisp/ox-deck.el b/contrib/lisp/ox-deck.el
deleted file mode 100644
index 3b911e1..0000000
--- a/contrib/lisp/ox-deck.el
+++ /dev/null
@@ -1,585 +0,0 @@
-;;; ox-deck.el --- deck.js Presentation Back-End for Org Export Engine
-
-;; Copyright (C) 2013, 2014  Rick Frankel
-
-;; Author: Rick Frankel <emacs at rickster dot com>
-;; Keywords: outlines, hypermedia, slideshow
-
-;; This file is not 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 this program.  If not, see <http://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; This library implements a deck.js presentation back-end for the Org
-;; generic exporter.
-
-;; Installation
-;; -------------
-;; Get a copy of deck.js from http://imakewebthings.com/deck.js/ or
-;; the gitub repository at https://github.com/imakewebthings/deck.js.
-;;
-;; Add the path to the extracted code to the variable
-;; `org-deck-directories' There are a number of customization in the
-;; org-export-deck group, most of which can be overridden with buffer
-;; local customization (starting with DECK_.)
-
-;; See ox.el and ox-html.el for more details on how this exporter
-;; works (it is derived from ox-html.)
-
-;; TODOs
-;; ------
-;; The title page is formatted using format-spec.  This is error prone
-;; when details are missing and may insert empty tags, like <h2></h2>,
-;; for missing values.
-
-(require 'ox-html)
-(eval-when-compile (require 'cl))
-
-(org-export-define-derived-backend 'deck 'html
-  :menu-entry
-  '(?d "Export to deck.js HTML Presentation"
-       ((?H "To temporary buffer" org-deck-export-as-html)
-       (?h "To file" org-deck-export-to-html)
-       (?o "To file and open"
-           (lambda (a s v b)
-             (if a (org-deck-export-to-html t s v b)
-               (org-open-file (org-deck-export-to-html nil s v b)))))))
-  :options-alist
-  '((:description "DESCRIPTION" nil nil newline)
-    (:keywords "KEYWORDS" nil nil space)
-    (:html-link-home "HTML_LINK_HOME" nil nil)
-    (:html-link-up "HTML_LINK_UP" nil nil)
-    (:deck-postamble "DECK_POSTAMBLE" nil org-deck-postamble newline)
-    (:deck-preamble "DECK_PREAMBLE" nil org-deck-preamble newline)
-    (:html-head-include-default-style "HTML_INCLUDE_DEFAULT_STYLE" 
"html-style" nil)
-    (:html-head-include-scripts "HTML_INCLUDE_SCRIPTS" nil nil)
-    (:deck-base-url "DECK_BASE_URL" nil org-deck-base-url)
-    (:deck-theme "DECK_THEME" nil org-deck-theme)
-    (:deck-transition "DECK_TRANSITION" nil org-deck-transition)
-    (:deck-include-extensions "DECK_INCLUDE_EXTENSIONS" nil
-                             org-deck-include-extensions split)
-    (:deck-exclude-extensions "DECK_EXCLUDE_EXTENSIONS" nil
-                             org-deck-exclude-extensions split))
-  :translate-alist
-  '((headline . org-deck-headline)
-    (inner-template . org-deck-inner-template)
-    (item . org-deck-item)
-    (link . org-deck-link)
-    (template . org-deck-template)))
-
-(defgroup org-export-deck nil
-  "Options for exporting Org mode files to deck.js HTML Presentations."
-  :tag "Org Export DECK"
-  :group 'org-export-html)
-
-(defcustom org-deck-directories '("./deck.js")
-  "Directories to search for deck.js components (jquery,
-modernizr; core, extensions and themes directories.)"
-  :group 'org-export-deck
-  :type '(repeat (string :tag "Directory")))
-
-(defun org-deck--cleanup-components (components)
-  (remove-duplicates
-   (car (remove 'nil components))
-   :test (lambda (x y)
-           (string= (file-name-nondirectory x)
-                    (file-name-nondirectory y)))))
-
-(defun org-deck--find-extensions ()
-  "Returns a unique list of all extensions found in
-in the extensions directories under `org-deck-directories'"
-  (org-deck--cleanup-components
-   (mapcar                              ; extensions under existing dirs
-    (lambda (dir)
-      (when (file-directory-p dir) (directory-files dir t "^[^.]")))
-    (mapcar                           ; possible extension directories
-     (lambda (x) (expand-file-name "extensions" x))
-     org-deck-directories))))
-
-(defun org-deck--find-css (type)
-  "Return a unique list of all the css stylesheets in the themes/TYPE
-directories under `org-deck-directories'."
-  (org-deck--cleanup-components
-   (mapcar
-    (lambda (dir)
-      (let ((css-dir (expand-file-name
-                      (concat (file-name-as-directory "themes") type) dir)))
-        (when (file-directory-p css-dir)
-          (directory-files css-dir t  "\\.css$"))))
-    org-deck-directories)))
-
-(defun org-deck-list-components ()
-  "List all available deck extensions, styles and
-transitions (with full paths) to a temporary buffer."
-  (interactive)
-  (let ((outbuf (get-buffer-create "*deck.js Extensions*")))
-    (with-current-buffer outbuf
-      (erase-buffer)
-      (insert "Extensions\n----------\n")
-      (insert (mapconcat 'identity (org-deck--find-extensions) "\n"))
-      (insert "\n\nStyles\n------\n")
-      (insert (mapconcat 'identity (org-deck--find-css "style") "\n"))
-      (insert "\n\nTransitions\n----------\n")
-      (insert (mapconcat 'identity (org-deck--find-css "transition") "\n")))
-    (switch-to-buffer-other-window outbuf)))
-
-(defcustom org-deck-include-extensions nil
-  "If non-nil, list of extensions to include instead of all available.
-Can be overridden or set with the DECK_INCLUDE_EXTENSIONS property.
-During output generation, the extensions found by
-`org-deck--find-extensions' are searched for the appropriate
-files (scripts and/or stylesheets) to include in the generated
-html. The href/src attributes are created relative to `org-deck-base-url'."
-  :group 'org-export-deck
-  :type '(repeat (string :tag "Extension")))
-
-(defcustom org-deck-exclude-extensions nil
-  "If non-nil, list of extensions to exclude.
-Can be overridden or set with the DECK_EXCLUDE_EXTENSIONS property."
-  :group 'org-export-deck
-  :type '(repeat (string :tag "Extension")))
-
-(defcustom org-deck-theme "swiss.css"
-  "deck.js theme. Can be overridden with the DECK_THEME property.
-If this value contains a path component (\"/\"), it is used as a
-literal path (url). Otherwise it is prepended with
-`org-deck-base-url'/themes/style/."
-  :group 'org-export-deck
-  :type 'string)
-
-(defcustom org-deck-transition "fade.css"
-  "deck.js transition theme. Can be overridden with the
-DECK_TRANSITION property.
-If this value contains a path component (\"/\"), it is used as a
-literal path (url). Otherwise it is prepended with
-`org-deck-base-url'/themes/transition/."
-  :group 'org-export-deck
-  :type 'string)
-
-(defcustom org-deck-base-url "deck.js"
-  "Url prefix to deck.js base directory containing the core, extensions
-and themes directories.
-Can be overridden with the DECK_BASE_URL property."
-  :group 'org-export-deck
-  :type 'string)
-
-(defvar org-deck-pre/postamble-styles
-  `((both "left: 5px; width: 100%;")
-    (preamble "position: absolute; top: 10px;")
-    (postamble ""))
-  "Alist of css styles for the preamble, postamble and both respectively.
-Can be overridden in `org-deck-styles'. See also `org-html-divs'.")
-
-(defcustom org-deck-postamble "<h1>%a - %t</h1>"
-  "Non-nil means insert a postamble in HTML export.
-
-When set to a string, use this string
-as the postamble.  When t, insert a string as defined by the
-formatting string in `org-html-postamble-format'.
-
-When set to a function, apply this function and insert the
-returned string.  The function takes the property list of export
-options as its only argument.
-
-This is included in the document at the bottom of the content
-section, and uses the postamble element and id from
-`org-html-divs'. The default places the author and presentation
-title at the bottom of each slide.
-
-The css styling is controlled by `org-deck-pre/postamble-styles'.
-
-Setting :deck-postamble in publishing projects will take
-precedence over this variable."
-  :group 'org-export-deck
-  :type '(choice (const :tag "No postamble" nil)
-                 (const :tag "Default formatting string" t)
-                 (string :tag "Custom formatting string")
-                 (function :tag "Function (must return a string)")))
-
-(defcustom org-deck-preamble nil
-  "Non-nil means insert a preamble in HTML export.
-
-When set to a string, use this string
-as the preamble.  When t, insert a string as defined by the
-formatting string in `org-html-preamble-format'.
-
-When set to a function, apply this function and insert the
-returned string.  The function takes the property list of export
-options as its only argument.
-
-This is included in the document at the top of  content section, and
-uses the preamble element and id from `org-html-divs'. The css
-styling is controlled by `org-deck-pre/postamble-styles'.
-
-Setting :deck-preamble in publishing projects will take
-precedence over this variable."
-  :group 'org-export-deck
-  :type '(choice (const :tag "No preamble" nil)
-                 (const :tag "Default formatting string" t)
-                 (string :tag "Custom formatting string")
-                 (function :tag "Function (must return a string)")))
-
-(defvar org-deck-toc-styles
-  (mapconcat
-   'identity
-   (list
-    "#table-of-contents a {color: inherit;}"
-    "#table-of-contents ul {margin-bottom: 0;}"
-    "#table-of-contents li {padding: 0;}") "\n")
-  "Default css styles used for formatting a table of contents slide.
-Can be overridden in `org-deck-styles'.
-Note that when the headline numbering option is true, a \"list-style: none\"
-is automatically added to avoid both numbers and bullets on the toc entries.")
-
-(defcustom org-deck-styles
-  "
-#title-slide h1 {
-    position: static; padding: 0;
-    margin-top: 10%;
-    -webkit-transform: none;
-    -moz-transform: none;
-    -ms-transform: none;
-    -o-transform: none;
-    transform: none;
-}
-#title-slide h2 {
-    text-align: center;
-    border:none;
-    padding: 0;
-    margin: 0;
-}"
-  "Deck specific CSS styles to include in exported html.
-Defaults to styles for the title page."
-  :group 'org-export-deck
-  :type 'string)
-
-(defcustom org-deck-title-slide-template
-  "<h1>%t</h1>
-<h2>%s</h2>
-<h2>%a</h2>
-<h2>%e</h2>
-<h2>%d</h2>"
-  "Format template to specify title page section.
-See `org-html-postamble-format' for the valid elements which
-can be included.
-
-It will be wrapped in the element defined in the :html-container
-property, and defaults to the value of `org-html-container-element',
-and have the id \"title-slide\"."
-  :group 'org-export-deck
-  :type 'string)
-
-(defun org-deck-toc (depth info)
-  (concat
-   (format "<%s id='table-of-contents' class='slide'>\n"
-           (plist-get info :html-container))
-   (format "<h2>%s</h2>\n" (org-html--translate "Table of Contents" info))
-   (org-html--toc-text
-    (mapcar
-     (lambda (headline)
-       (let* ((class (org-element-property :HTML_CONTAINER_CLASS headline))
-              (section-number
-               (when
-                   (and (not (org-export-low-level-p headline info))
-                        (org-export-numbered-headline-p headline info))
-                 (concat
-                  (mapconcat
-                   'number-to-string
-                   (org-export-get-headline-number headline info) ".") ". ")))
-              (title
-               (concat
-                section-number
-                (replace-regexp-in-string ; remove any links in headline...
-                 "</?a[^>]*>" ""
-                 (org-export-data
-                  (org-element-property :title headline) info)))))
-         (cons
-          (if (and class (string-match-p "\\<slide\\>" class))
-              (format
-               "<a href='#outline-container-%s'>%s</a>"
-               (or (org-element-property :CUSTOM_ID headline)
-                  (concat
-                   "sec-"
-                   (mapconcat
-                    'number-to-string
-                    (org-export-get-headline-number headline info) "-")))
-               title)
-            title)
-          (org-export-get-relative-level headline info))))
-     (org-export-collect-headlines info depth)))
-   (format "</%s>\n" (plist-get info :html-container))))
-
-(defun org-deck--get-packages (info)
-  (let ((prefix (concat (plist-get info :deck-base-url) "/"))
-        (theme (plist-get info :deck-theme))
-        (transition (plist-get info :deck-transition))
-        (include (plist-get info :deck-include-extensions))
-        (exclude (plist-get info :deck-exclude-extensions))
-        (scripts '()) (sheets '()) (snippets '()))
-    (add-to-list 'scripts (concat prefix "jquery.min.js"))
-    (add-to-list 'scripts (concat prefix "core/deck.core.js"))
-    (add-to-list 'scripts (concat prefix "modernizr.custom.js"))
-    (add-to-list 'sheets  (concat prefix "core/deck.core.css"))
-    (mapc
-     (lambda (extdir)
-       (let* ((name (file-name-nondirectory extdir))
-              (dir (file-name-as-directory extdir))
-              (path (concat prefix "extensions/" name "/"))
-              (base (format "deck.%s." name)))
-         (when (and (or (eq nil include) (member name include))
-                    (not (member name exclude)))
-           (when (file-exists-p (concat dir base "js"))
-             (add-to-list 'scripts (concat path base "js")))
-           (when (file-exists-p (concat dir base "css"))
-             (add-to-list 'sheets (concat path base "css")))
-           (when (file-exists-p (concat dir base "html"))
-             (add-to-list 'snippets (concat dir base "html"))))))
-     (org-deck--find-extensions))
-    (if (not (string-match-p "^[[:space:]]*$" theme))
-        (add-to-list 'sheets
-                     (if (file-name-directory theme) theme
-                       (format "%sthemes/style/%s" prefix theme))))
-    (if (not (string-match-p "^[[:space:]]*$" transition))
-        (add-to-list
-         'sheets
-         (if (file-name-directory transition) transition
-           (format "%sthemes/transition/%s" prefix transition))))
-    (list :scripts (nreverse scripts) :sheets (nreverse sheets)
-          :snippets snippets)))
-
-(defun org-deck-inner-template (contents info)
-  "Return body of document string after HTML conversion.
-CONTENTS is the transcoded contents string.  INFO is a plist
-holding export options."
-  (concat contents "\n"))
-
-(defun org-deck-headline (headline contents info)
-  (let ((org-html-toplevel-hlevel 2)
-        (class (or (org-element-property :HTML_CONTAINER_CLASS headline) ""))
-        (level (org-export-get-relative-level headline info)))
-    (when (and (= 1 level) (not (string-match-p "\\<slide\\>" class)))
-      (org-element-put-property headline :HTML_CONTAINER_CLASS (concat class " 
slide")))
-    (org-html-headline headline contents info)))
-
-(defun org-deck-item (item contents info)
-  "Transcode an ITEM element from Org to HTML.
-CONTENTS holds the contents of the item.  INFO is a plist holding
-contextual information.
-If the containing headline has the property :STEP, then
-the \"slide\" class will be added to the to the list element,
- which will make the list into a \"build\"."
-  (let ((text (org-html-item item contents info)))
-    (if (org-export-get-node-property :STEP item t)
-       (progn
-         (replace-regexp-in-string "^<li>" "<li class='slide'>" text)
-         (replace-regexp-in-string "^<li class='checkbox'>" "<li 
class='checkbox slide'>" text))
-      text)))
-
-(defun org-deck-link (link desc info)
-  (replace-regexp-in-string "href=\"#" "href=\"#outline-container-"
-                           (org-export-with-backend 'html link desc info)))
-
-(defun org-deck-template (contents info)
-  "Return complete document string after HTML conversion.
-CONTENTS is the transcoded contents string.  INFO is a plist
-holding export options."
-  (let ((pkg-info (org-deck--get-packages info))
-       (org-html--pre/postamble-class "deck-status")
-       (info (plist-put
-              (plist-put info :html-preamble (plist-get info :deck-preamble))
-              :html-postamble (plist-get info :deck-postamble))))
-    (mapconcat
-     'identity
-     (list
-      (org-html-doctype info)
-      (let ((lang (plist-get info :language)))
-        (mapconcat
-         (lambda (x)
-           (apply
-            'format
-            "<!--%s <html %s lang='%s' xmlns='http://www.w3.org/1999/xhtml'> 
%s<![endif]-->"
-            x))
-         (list `("[if lt IE 7]>" "class='no-js ie6'" ,lang "")
-               `("[if IE 7]>" "class='no-js ie7'" ,lang "")
-               `("[if IE 8]>" "class='no-js ie8'" ,lang "")
-               `("[if gt IE 8]><!-->" "" ,lang "<!--")) "\n"))
-      "<head>"
-      (org-deck--build-meta-info info)
-      (mapconcat
-       (lambda (sheet)
-         (format
-          "<link rel='stylesheet' href='%s' type='text/css' />" sheet))
-       (plist-get pkg-info :sheets) "\n")
-      (mapconcat
-       (lambda (script)
-         (format
-          "<script src='%s' type='text/javascript'></script>" script))
-       (plist-get pkg-info :scripts) "\n")
-      (org-html--build-mathjax-config info)
-      "<script type='text/javascript'>"
-      "  $(document).ready(function () { $.deck('.slide'); });"
-      "</script>"
-      (org-html--build-head info)
-      "<style type='text/css'>"
-      org-deck-toc-styles
-      (when (plist-get info :section-numbers)
-        "#table-of-contents ul li {list-style-type: none;}")
-      (format "#%s, #%s {%s}"
-              (nth 2 (assq 'preamble org-html-divs))
-              (nth 2 (assq 'postamble org-html-divs))
-              (nth 1 (assq 'both org-deck-pre/postamble-styles)))
-      (format "#%s {%s}"
-              (nth 2 (assq 'preamble org-html-divs))
-              (nth 1 (assq 'preamble org-deck-pre/postamble-styles)))
-      (format "#%s {%s}"
-              (nth 2 (assq 'postamble org-html-divs))
-              (nth 1 (assq 'postamble org-deck-pre/postamble-styles)))
-      org-deck-styles
-      "</style>"
-      "</head>"
-      "<body>"
-      (format "<%s id='%s' class='deck-container'>"
-              (nth 1 (assq 'content org-html-divs))
-              (nth 2 (assq 'content org-html-divs)))
-      (org-html--build-pre/postamble 'preamble info)
-      ;; title page
-      (format "<%s id='title-slide' class='slide'>"
-              (plist-get info :html-container))
-      (format-spec org-deck-title-slide-template (org-html-format-spec info))
-      (format "</%s>" (plist-get info :html-container))
-      ;; toc page
-      (let ((depth (plist-get info :with-toc)))
-        (when depth (org-deck-toc depth info)))
-      contents
-      (mapconcat
-       (lambda (snippet)
-         (with-temp-buffer (insert-file-contents snippet)
-                           (buffer-string)))
-       (plist-get pkg-info :snippets) "\n")
-      (org-html--build-pre/postamble 'postamble info)
-      (format "</%s>" (nth 1 (assq 'content org-html-divs)))
-      "</body>"
-      "</html>\n") "\n")))
-
-(defun org-deck--build-meta-info (info)
-  "Return meta tags for exported document.
-INFO is a plist used as a communication channel."
-  (let* ((title (org-export-data (plist-get info :title) info))
-         (author (and (plist-get info :with-author)
-                      (let ((auth (plist-get info :author)))
-                        (and auth (org-export-data auth info)))))
-         (date (and (plist-get info :with-date)
-                    (let ((date (org-export-get-date info)))
-                      (and date (org-export-data date info)))))
-         (description (plist-get info :description))
-         (keywords (plist-get info :keywords)))
-    (mapconcat
-     'identity
-     (list
-      (format "<title>%s</title>" title)
-      (format "<meta http-equiv='Content-Type' content='text/html; 
charset=%s'/>"
-              (or (and org-html-coding-system
-                       (fboundp 'coding-system-get)
-                       (coding-system-get
-                        org-html-coding-system 'mime-charset))
-                  "iso-8859-1"))
-      (mapconcat
-       (lambda (attr)
-         (when (< 0 (length (car attr)))
-           (format "<meta name='%s' content='%s'/>\n"
-                   (nth 1 attr) (car attr))))
-       (list '("Org-mode" "generator")
-             `(,author "author")
-             `(,description "description")
-             `(,keywords "keywords")) "")) "\n")))
-(defun org-deck-export-as-html
-  (&optional async subtreep visible-only body-only ext-plist)
-  "Export current buffer to an HTML buffer.
-
-If narrowing is active in the current buffer, only export its
-narrowed part.
-
-If a region is active, export that region.
-
-A non-nil optional argument ASYNC means the process should happen
-asynchronously.  The resulting buffer should be accessible
-through the `org-export-stack' interface.
-
-When optional argument SUBTREEP is non-nil, export the sub-tree
-at point, extracting information from the headline properties
-first.
-
-When optional argument VISIBLE-ONLY is non-nil, don't export
-contents of hidden elements.
-
-When optional argument BODY-ONLY is non-nil, only write code
-between \"<body>\" and \"</body>\" tags.
-
-EXT-PLIST, when provided, is a property list with external
-parameters overriding Org default settings, but still inferior to
-file-local settings.
-
-Export is done in a buffer named \"*Org deck.js Export*\", which
-will be displayed when `org-export-show-temporary-export-buffer'
-is non-nil."
-  (interactive)
-  (org-export-to-buffer 'deck "*Org deck.js Export*"
-    async subtreep visible-only body-only ext-plist (lambda () (nxml-mode))))
-
-(defun org-deck-export-to-html
-  (&optional async subtreep visible-only body-only ext-plist)
-  "Export current buffer to a deck.js HTML file.
-
-If narrowing is active in the current buffer, only export its
-narrowed part.
-
-If a region is active, export that region.
-
-A non-nil optional argument ASYNC means the process should happen
-asynchronously.  The resulting file should be accessible through
-the `org-export-stack' interface.
-
-When optional argument SUBTREEP is non-nil, export the sub-tree
-at point, extracting information from the headline properties
-first.
-
-When optional argument VISIBLE-ONLY is non-nil, don't export
-contents of hidden elements.
-
-When optional argument BODY-ONLY is non-nil, only write code
-between \"<body>\" and \"</body>\" tags.
-
-EXT-PLIST, when provided, is a property list with external
-parameters overriding Org default settings, but still inferior to
-file-local settings.
-
-Return output file's name."
-  (interactive)
-  (let* ((extension (concat "." org-html-extension))
-         (file (org-export-output-file-name extension subtreep))
-        (org-export-coding-system org-html-coding-system))
-    (org-export-to-file 'deck file
-      async subtreep visible-only body-only ext-plist)))
-
-(defun org-deck-publish-to-html (plist filename pub-dir)
-  "Publish an org file to deck.js HTML Presentation.
-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. Returns output file name."
-  (org-publish-org-to 'deck filename ".html" plist pub-dir))
-
-(provide 'ox-deck)
-
-;;; ox-deck.el ends here
diff --git a/contrib/lisp/ox-extra.el b/contrib/lisp/ox-extra.el
deleted file mode 100644
index 9cd6980..0000000
--- a/contrib/lisp/ox-extra.el
+++ /dev/null
@@ -1,211 +0,0 @@
-;;; ox-extra.el --- Convenience functions for org export
-
-;; Copyright (C) 2014  Aaron Ecay
-
-;; Author: Aaron Ecay <aaronecay@gmail.com>
-
-;; 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 file contains some convenience functions for org export, which
-;; are not part of org's core.  Call `ox-extras-activate' passing a
-;; list of symbols naming extras, which will be installed globally in
-;; your org session.
-;;
-;; For example, you could include the following in your .emacs file:
-;;
-;;    (require 'ox-extra)
-;;    (ox-extras-activate '(latex-header-blocks ignore-headlines))
-;;
-
-;; Currently available extras:
-
-;; - `latex-header-blocks' -- allow the use of latex blocks, the
-;; contents of which which will be interpreted as #+latex_header lines
-;; for export.  These blocks should be tagged with #+header: :header
-;; yes.  For example:
-;; #+header: :header yes
-;; #+begin_export latex
-;;   ...
-;; #+end_export
-
-;; - `ignore-headlines' -- allow a headline (but not its children) to
-;; be ignored.  Any headline tagged with the 'ignore' tag will be
-;; ignored (i.e. will not be included in the export), but any child
-;; headlines will not be ignored (unless explicitly tagged to be
-;; ignored), and will instead have their levels promoted by one.
-
-;; TODO:
-;; - add a function to org-mode-hook that looks for a ox-extras local
-;;   variable and activates the specified extras buffer-locally
-;; - allow specification of desired extras to be activated via
-;;   customize
-
-;;; Code:
-
-(require 'ox)
-(require 'cl-lib)
-
-(defun org-latex-header-blocks-filter (backend)
-  (when (org-export-derived-backend-p backend 'latex)
-    (let ((positions
-          (org-element-map (org-element-parse-buffer 'greater-element nil) 
'export-block
-            (lambda (block)
-              (when (and (string= (org-element-property :type block) "LATEX")
-                         (string= (org-export-read-attribute
-                                   :header block :header)
-                                  "yes"))
-                (list (org-element-property :begin block)
-                      (org-element-property :end block)
-                      (org-element-property :post-affiliated block)))))))
-      (mapc (lambda (pos)
-             (goto-char (nth 2 pos))
-             (cl-destructuring-bind
-                 (beg end &rest ignore)
-                 ;; FIXME: `org-edit-src-find-region-and-lang' was
-                 ;; removed in 9c06f8cce (2014-11-11).
-                 (org-edit-src-find-region-and-lang)
-               (let ((contents-lines (split-string
-                                      (buffer-substring-no-properties beg end)
-                                      "\n")))
-                 (delete-region (nth 0 pos) (nth 1 pos))
-                 (dolist (line contents-lines)
-                   (insert (concat "#+latex_header: "
-                                   (replace-regexp-in-string "\\` *" "" line)
-                                   "\n"))))))
-           ;; go in reverse, to avoid wrecking the numeric positions
-           ;; earlier in the file
-           (reverse positions)))))
-
-
-;; During export headlines which have the "ignore" tag are removed
-;; from the parse tree.  Their contents are retained (leading to a
-;; possibly invalid parse tree, which nevertheless appears to function
-;; correctly with most export backends) all children headlines are
-;; retained and are promoted to the level of the ignored parent
-;; headline.
-;;
-;; This makes it possible to add structure to the original Org-mode
-;; document which does not effect the exported version, such as in the
-;; following examples.
-;;
-;; Wrapping an abstract in a headline
-;;
-;;     * Abstract                        :ignore:
-;;     #+LaTeX: \begin{abstract}
-;;     #+HTML: <div id="abstract">
-;;
-;;     ...
-;;
-;;     #+HTML: </div>
-;;     #+LaTeX: \end{abstract}
-;;
-;; Placing References under a headline (using ox-bibtex in contrib)
-;;
-;;     * References                     :ignore:
-;;     #+BIBLIOGRAPHY: dissertation plain
-;;
-;; Inserting an appendix for LaTeX using the appendix package.
-;;
-;;     * Appendix                       :ignore:
-;;     #+LaTeX: \begin{appendices}
-;;     ** Reproduction
-;;     ...
-;;     ** Definitions
-;;     #+LaTeX: \end{appendices}
-;;
-(defun org-export-ignore-headlines (data backend info)
-  "Remove headlines tagged \"ignore\" retaining contents and promoting 
children.
-Each headline tagged \"ignore\" will be removed retaining its
-contents and promoting any children headlines to the level of the
-parent."
-  (org-element-map data 'headline
-    (lambda (object)
-      (when (member "ignore" (org-element-property :tags object))
-        (let ((level-top (org-element-property :level object))
-              level-diff)
-          (mapc (lambda (el)
-                  ;; recursively promote all nested headlines
-                  (org-element-map el 'headline
-                    (lambda (el)
-                      (when (equal 'headline (org-element-type el))
-                        (unless level-diff
-                          (setq level-diff (- (org-element-property :level el)
-                                              level-top)))
-                        (org-element-put-property el
-                          :level (- (org-element-property :level el)
-                                    level-diff)))))
-                  ;; insert back into parse tree
-                  (org-element-insert-before el object))
-                (org-element-contents object)))
-        (org-element-extract-element object)))
-    info nil)
-  (org-extra--merge-sections data backend info)
-  data)
-
-(defun org-extra--merge-sections (data _backend info)
-  (org-element-map data 'headline
-    (lambda (hl)
-      (let ((sections
-             (cl-loop
-              for el in (org-element-map (org-element-contents hl)
-                            '(headline section) #'identity info)
-              until (eq (org-element-type el) 'headline)
-              collect el)))
-        (when (and sections
-                   (> (length sections) 1))
-          (apply #'org-element-adopt-elements
-                 (car sections)
-                 (cl-mapcan (lambda (s) (org-element-contents s))
-                            (cdr sections)))
-          (mapc #'org-element-extract-element (cdr sections)))))
-    info))
-
-(defconst ox-extras
-  '((latex-header-blocks org-latex-header-blocks-filter 
org-export-before-parsing-hook)
-    (ignore-headlines org-export-ignore-headlines 
org-export-filter-parse-tree-functions))
-  "A list of org export extras that can be enabled.
-
-Should be a list of items of the form (NAME FN HOOK).  NAME is a
-symbol, which can be passed to `ox-extras-activate'.  FN is a
-function which will be added to HOOK.")
-
-(defun ox-extras-activate (extras)
-  "Activate certain org export extras.
-
-EXTRAS should be a list of extras (defined in `ox-extras') which
-should be activated."
-  (dolist (extra extras)
-    (let* ((lst (assq extra ox-extras))
-          (fn (nth 1 lst))
-          (hook (nth 2 lst)))
-      (when (and fn hook)
-       (add-hook hook fn)))))
-
-(defun ox-extras-deactivate (extras)
-  "Deactivate certain org export extras.
-
-This function is the opposite of `ox-extras-activate'.  EXTRAS
-should be a list of extras (defined in `ox-extras') which should
-be activated."
-  (dolist (extra extras)
-    (let* ((lst (assq extra ox-extras))
-          (fn (nth 1 lst))
-          (hook (nth 2 lst)))
-      (when (and fn hook)
-       (remove-hook hook fn)))))
-
-(provide 'ox-extra)
-;;; ox-extra.el ends here
diff --git a/contrib/lisp/ox-freemind.el b/contrib/lisp/ox-freemind.el
deleted file mode 100644
index 11aa148..0000000
--- a/contrib/lisp/ox-freemind.el
+++ /dev/null
@@ -1,527 +0,0 @@
-;;; ox-freemind.el --- Freemind Mindmap Back-End for Org Export Engine
-
-;; Copyright (C) 2013-2021  Free Software Foundation, Inc.
-
-;; Author: Jambunathan K <kjambunathan at gmail dot com>
-;; Keywords: outlines, hypermedia, calendar, wp
-
-;; This file is not 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:
-
-;; This library implements a Freemind Mindmap back-end for Org generic
-;; exporter.
-
-;; To test it, run:
-;;
-;;   M-x org-freemind-export-to-freemind
-;;
-;; in an Org mode buffer.  See ox.el for more details on how this
-;; exporter works.
-
-;;; Code:
-
-;;; Dependencies
-
-(require 'ox-html)
-
-
-
-;;; Define Back-End
-
-(org-export-define-derived-backend 'freemind 'html
-  :menu-entry
-  '(?f "Export to Freemind Mindmap"
-       ((?f "As Freemind Mindmap file" org-freemind-export-to-freemind)
-       (?o "As Freemind Mindmap file and open"
-           (lambda (a s v b)
-             (if a (org-freemind-export-to-freemind t s v b)
-               (org-open-file (org-freemind-export-to-freemind nil s v b)))))))
-  :translate-alist '((headline . org-freemind-headline)
-                    (template . org-freemind-template)
-                    (inner-template . org-freemind-inner-template)
-                    (section . org-freemind-section)
-                    (entity . org-freemind-entity))
-  :filters-alist '((:filter-options . org-freemind-options-function)
-                  (:filter-final-output . org-freemind-final-function)))
-
-
-
-;;; User Configuration Variables
-
-(defgroup org-export-freemind nil
-  "Options for exporting Org mode files to Freemind Mindmap."
-  :tag "Org Export Freemind Mindmap"
-  :group 'org-export)
-
-(defcustom org-freemind-styles
-  '((default . "<node>\n</node>")
-    (0 . "<node COLOR=\"#000000\">\n<font NAME=\"SansSerif\" 
SIZE=\"20\"/>\n</node>")
-    (1 . "<node COLOR=\"#0033ff\">\n<edge STYLE=\"sharp_bezier\" 
WIDTH=\"8\"/>\n<font NAME=\"SansSerif\" SIZE=\"18\"/>\n</node>")
-    (2 . "<node COLOR=\"#00b439\">\n<edge STYLE=\"bezier\" 
WIDTH=\"thin\"/>\n<font NAME=\"SansSerif\" SIZE=\"16\"/>\n</node>")
-    (3 . "<node COLOR=\"#990000\" FOLDED=\"true\">\n<font NAME=\"SansSerif\" 
SIZE=\"14\"/>\n</node>")
-    (4 . "<node COLOR=\"#111111\">\n</node>"))
-  "List of Freemind node styles.
-Each entry is of the form (STYLE-NAME . STYLE-SPEC).  STYLE-NAME
-can be one of an integer (signifying an outline level), a string
-or the symbol `default'.  STYLE-SPEC, a string, is a Freemind
-node style."
-  :type '(alist :options (default 0 1 2 3)
-                :key-type (choice :tag "Style tag"
-                                 (integer :tag "Outline level")
-                                 (const :tag "Default value" default)
-                                 (string :tag "Node style"))
-                :value-type (string :tag "Style spec"))
-  :group 'org-export-freemind)
-
-(defcustom org-freemind-style-map-function 'org-freemind-style-map--automatic
-  "Function to map an Org element to it's node style.
-The mapping function takes two arguments an Org ELEMENT and INFO.
-ELEMENT can be one of the following types - `org-data',
-`headline' or `section'.  INFO is a plist holding contextual
-information during export.  The function must return a STYLE-SPEC
-to be applied to ELEMENT.
-
-See `org-freemind-style-map--automatic' for a sample style
-function.  See `org-freemind-styles' for a list of named styles."
-  :type '(radio
-         (function-item org-freemind-style-map--automatic)
-         (function-item org-freemind-style-map--default)
-         function)
-  :group 'org-export-freemind)
-
-(defcustom org-freemind-section-format 'note
-  "Specify how outline sections are to be formatted.
-If `inline', append it to the contents of it's heading node.  If
-`note', attach it as a note to it's heading node.  If `node',
-attach it as a separate node to it's heading node.
-
-Use `note', if the input Org file contains large sections.  Use
-`node', if the Org file contains mid-sized sections that need to
-stand apart.  Otherwise, use `inline'."
-  :type '(choice
-         (const :tag "Append to outline title" inline)
-         (const :tag "Attach as a note" note)
-         (const :tag "Create a separate node" node))
-  :group 'org-export-freemind)
-
-;;;; Debugging
-
-(defcustom org-freemind-pretty-output nil
-  "Enable this to generate pretty Freemind Mindmap."
-  :type 'boolean
-  :group 'org-export-freemind)
-
-
-;;; Internal Functions
-
-;;;; XML Manipulation
-
-(defun org-freemind--serialize (parsed-xml &optional contents)
-  "Convert PARSED-XML in to XML string.
-PARSED-XML is a parse tree as returned by
-`libxml-parse-xml-region'.  CONTENTS is an optional string.
-
-Ignore CONTENTS, if PARSED-XML is not a sole XML element.
-Otherwise, append CONTENTS to the contents of top-level element
-in PARSED-XML.
-
-This is an inverse function of `libxml-parse-xml-region'.
-
-For purposes of Freemind export, PARSED-XML is a node style
-specification - \"<node ...>...</node>\" - as a parse tree."
-  (when contents
-    (assert (symbolp (car parsed-xml))))
-  (cond
-   ((null parsed-xml) "")
-   ((stringp parsed-xml) parsed-xml)
-   ((symbolp (car parsed-xml))
-    (let ((attributes (mapconcat
-                      (lambda (av)
-                        (format "%s=\"%s\"" (car av) (cdr av)))
-                      (cadr parsed-xml) " ")))
-      (if (or (cddr parsed-xml) contents)
-         (format "\n<%s%s>%s\n</%s>"
-                 (car parsed-xml)
-                 (if (string= attributes "") "" (concat " " attributes))
-                 (concat (org-freemind--serialize (cddr parsed-xml))
-                         contents )
-                 (car parsed-xml))
-       (format "\n<%s%s/>"
-               (car parsed-xml)
-               (if (string= attributes "") "" (concat " " attributes))))))
-   (t (mapconcat #'org-freemind--serialize parsed-xml ""))))
-
-(defun org-freemind--parse-xml (xml-string)
-  "Return parse tree for XML-STRING using `libxml-parse-xml-region'.
-For purposes of Freemind export, XML-STRING is a node style
-specification - \"<node ...>...</node>\" - as a string."
-  (with-temp-buffer
-    (insert (or xml-string ""))
-    (libxml-parse-xml-region (point-min) (point-max))))
-
-
-;;;; Style mappers :: Default and Automatic layout
-
-(defun org-freemind-style-map--automatic (element info)
-  "Return a node style corresponding to relative outline level of ELEMENT.
-ELEMENT can be any of the following types - `org-data',
-`headline' or `section'.  See `org-freemind-styles' for style
-mappings of different outline levels."
-  (let ((style-name
-        (case (org-element-type element)
-          (headline
-           (org-export-get-relative-level element info))
-          (section
-           (let ((parent (org-export-get-parent-headline element)))
-             (if (not parent) 1
-               (1+ (org-export-get-relative-level parent info)))))
-          (t 0))))
-    (or (assoc-default style-name org-freemind-styles)
-       (assoc-default 'default org-freemind-styles)
-       "<node></node>")))
-
-(defun org-freemind-style-map--default (element info)
-  "Return the default style for all ELEMENTs.
-ELEMENT can be any of the following types - `org-data',
-`headline' or `section'.  See `org-freemind-styles' for current
-value of default style."
-  (or (assoc-default 'default org-freemind-styles)
-      "<node></node>"))
-
-
-;;;; Helpers :: Retrieve, apply Freemind styles
-
-(defun org-freemind--get-node-style (element info)
-  "Return Freemind node style applicable for HEADLINE.
-ELEMENT is an Org element of type `org-data', `headline' or
-`section'.  INFO is a plist holding contextual information."
-  (unless (fboundp org-freemind-style-map-function)
-    (setq org-freemind-style-map-function 'org-freemind-style-map--default))
-  (let ((style (funcall org-freemind-style-map-function element info)))
-    ;; Sanitize node style.
-
-    ;; Loop through the attributes of node element and purge those
-    ;; attributes that look suspicious.  This is an extra bit of work
-    ;; that allows one to copy verbatim node styles from an existing
-    ;; Freemind Mindmap file without messing with the exported data.
-    (let* ((data (org-freemind--parse-xml style))
-          (attributes (cadr data))
-          (ignored-attrs '(POSITION FOLDED TEXT CREATED ID
-                                    MODIFIED)))
-      (let (attr)
-       (while (setq attr (pop ignored-attrs))
-         (setq attributes (assq-delete-all attr attributes))))
-      (when data (setcar (cdr data) attributes))
-      (org-freemind--serialize data))))
-
-(defun org-freemind--build-stylized-node (style-1 style-2 &optional contents)
-  "Build a Freemind node with style STYLE-1 + STYLE-2 and add CONTENTS to it.
-STYLE-1 and STYLE-2 are Freemind node styles as a string.
-STYLE-1 is the base node style and STYLE-2 is the overriding
-style that takes precedence over STYLE-1.  CONTENTS is a string.
-
-Return value is a Freemind node with following properties:
-
-  1. The attributes of \"<node ...> </node>\" element is the union
-     of corresponding attributes of STYLE-1 and STYLE-2.  When
-     STYLE-1 and STYLE-2 specify values for the same attribute
-     name, choose the attribute value from STYLE-2.
-
-  2. The children of \"<node ...> </node>\" element is the union of
-     top-level children of STYLE-1 and STYLE-2 with CONTENTS
-     appended to it.  When STYLE-1 and STYLE-2 share a child
-     element of same type, the value chosen is that from STYLE-2.
-
-For example, merging with following parameters
-
-  STYLE-1  =>
-              <node COLOR=\"#00b439\" STYLE=\"Bubble\">
-                <edge STYLE=\"bezier\" WIDTH=\"thin\"/>
-                <font NAME=\"SansSerif\" SIZE=\"16\"/>
-              </node>
-
-  STYLE-2  =>
-              <node COLOR=\"#990000\" FOLDED=\"true\">
-                <font NAME=\"SansSerif\" SIZE=\"14\"/>
-              </node>
-
-  CONTENTS =>
-               <attribute NAME=\"ORGTAG\" VALUE=\"@home\"/>
-
-will result in following node:
-
-  RETURN   =>
-               <node STYLE=\"Bubble\" COLOR=\"#990000\" FOLDED=\"true\">
-                 <edge STYLE=\"bezier\" WIDTH=\"thin\"/>
-                 <font NAME=\"SansSerif\" SIZE=\"14\"/>
-                 <attribute NAME=\"ORGTAG\" VALUE=\"@home\"/>
-               </node>."
-  (let* ((data1 (org-freemind--parse-xml (or style-1 "")))
-        (data2 (org-freemind--parse-xml (or style-2 "")))
-        (attr1 (cadr data1))
-        (attr2 (cadr data2))
-        (merged-attr attr2)
-        (children1 (cddr data1))
-        (children2 (cddr data2))
-        (merged-children children2))
-    (let (attr)
-      (while (setq attr (pop attr1))
-       (unless (assq (car attr) merged-attr)
-         (push attr merged-attr))))
-    (let (child)
-      (while (setq child (pop children1))
-       (when (or (stringp child) (not (assq (car child) merged-children)))
-         (push child merged-children))))
-    (let ((merged-data (nconc (list 'node merged-attr) merged-children)))
-      (org-freemind--serialize merged-data contents))))
-
-
-;;;; Helpers :: Node contents
-
-(defun org-freemind--richcontent (type contents &optional css-style)
-  (let* ((type (case type
-                (note "NOTE")
-                (node "NODE")
-                (t "NODE")))
-        (contents (org-trim contents)))
-    (if (string= (org-trim contents) "") ""
-      (format "\n<richcontent TYPE=\"%s\">%s\n</richcontent>"
-             type
-             (format "\n<html>\n<head>%s\n</head>\n%s\n</html>"
-                     (or css-style "")
-                     (format "<body>\n%s\n</body>" contents))))))
-
-(defun org-freemind--build-node-contents (element contents info)
-  (let* ((title (case (org-element-type element)
-                 (headline
-                  (org-element-property :title element))
-                 (org-data
-                  (plist-get info :title))
-                 (t (error "Shouldn't come here"))))
-        (element-contents (org-element-contents element))
-        (section (assq 'section element-contents))
-        (section-contents
-         (let ((backend (org-export-create-backend
-                         :parent (org-export-backend-name
-                                  (plist-get info :back-end))
-                         :transcoders '((section . (lambda (e c i) c))))))
-           (org-export-data-with-backend section backend info)))
-        (itemized-contents-p (let ((first-child-headline
-                                    (org-element-map element-contents
-                                        'headline 'identity info t)))
-                               (when first-child-headline
-                                 (org-export-low-level-p first-child-headline
-                                                         info))))
-        (node-contents (concat section-contents
-                               (when itemized-contents-p
-                                 contents))))
-    (concat (let ((title (org-export-data title info)))
-             (case org-freemind-section-format
-               (inline
-                 (org-freemind--richcontent
-                  'node (concat (format "\n<h2>%s</h2>" title)
-                                node-contents) ))
-               (note
-                (concat (org-freemind--richcontent
-                         'node (format "\n<p>%s\n</p>" title))
-                        (org-freemind--richcontent
-                         'note node-contents)))
-               (node
-                (concat
-                 (org-freemind--richcontent
-                  'node (format "\n<p>%s\n</p>" title))
-                 (when section
-                   (org-freemind--build-stylized-node
-                    (org-freemind--get-node-style section info) nil
-                    (org-freemind--richcontent 'node node-contents)))))))
-           (unless itemized-contents-p
-             contents))))
-
-
-
-;;; Template
-
-(defun org-freemind-template (contents info)
-  "Return complete document string after Freemind Mindmap conversion.
-CONTENTS is the transcoded contents string.  RAW-DATA is the
-original parsed data.  INFO is a plist holding export options."
-  (format
-   "<map version=\"0.9.0\">\n%s\n</map>"
-   (org-freemind--build-stylized-node
-    (org-freemind--get-node-style nil info) nil
-    (let ((org-data (plist-get info :parse-tree)))
-      (org-freemind--build-node-contents org-data contents info)))))
-
-(defun org-freemind-inner-template (contents info)
-  "Return body of document string after Freemind Mindmap conversion.
-CONTENTS is the transcoded contents string.  INFO is a plist
-holding export options."
-  contents)
-
-;;;; Tags
-
-(defun org-freemind--tags (tags)
-  (mapconcat (lambda (tag)
-              (format "\n<attribute NAME=\"%s\" VALUE=\"%s\"/>" tag ""))
-            tags "\n"))
-
-
-
-;;; Transcode Functions
-
-;;;; Entity
-
-(defun org-freemind-entity (entity contents info)
-  "Transcode an ENTITY object from Org to Freemind Mindmap.
-CONTENTS are the definition itself.  INFO is a plist holding
-contextual information."
-  (org-element-property :utf-8 entity))
-
-;;;; Headline
-
-(defun org-freemind-headline (headline contents info)
-  "Transcode a HEADLINE element from Org to Freemind Mindmap.
-CONTENTS holds the contents of the headline.  INFO is a plist
-holding contextual information."
-  ;; Empty contents?
-  (setq contents (or contents ""))
-  (let* ((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 (and (not (org-export-low-level-p headline info))
-                             (org-export-numbered-headline-p headline info)
-                             (mapconcat 'number-to-string
-                                        (org-export-get-headline-number
-                                         headline info) ".")))
-        ;; Create the headline text.
-        (full-text (org-export-data (org-element-property :title headline)
-                                    info))
-        ;; Headline order (i.e, first digit of the section number)
-        (headline-order (car (org-export-get-headline-number headline info))))
-    (cond
-     ;; Case 1: This is a footnote section: ignore it.
-     ((org-element-property :footnote-section-p headline) nil)
-     ;; Case 2. This is a deep sub-tree, export it as a list item.
-     ;;         Delegate the actual export to `html' backend.
-     ((org-export-low-level-p headline info)
-      (org-html-headline headline contents info))
-     ;; Case 3. Standard headline.  Export it as a section.
-     (t
-      (let* ((section-number (mapconcat 'number-to-string
-                                       (org-export-get-headline-number
-                                        headline info) "-"))
-            (ids (remove 'nil
-                         (list (org-element-property :CUSTOM_ID headline)
-                               (concat "sec-" section-number)
-                               (org-element-property :ID headline))))
-            (preferred-id (car ids))
-            (extra-ids (cdr ids))
-            (left-p (zerop (% headline-order 2))))
-       (org-freemind--build-stylized-node
-        (org-freemind--get-node-style headline info)
-        (format "<node ID=\"%s\" POSITION=\"%s\" FOLDED=\"%s\">\n</node>"
-                preferred-id
-                (if left-p "left" "right")
-                (if (= level 1) "true" "false"))
-        (concat (org-freemind--build-node-contents headline contents info)
-                (org-freemind--tags tags))))))))
-
-
-;;;; Section
-
-(defun org-freemind-section (section contents info)
-  "Transcode a SECTION element from Org to Freemind Mindmap.
-CONTENTS holds the contents of the section.  INFO is a plist
-holding contextual information."
-  (let ((parent (org-export-get-parent-headline section)))
-    (when (and parent (org-export-low-level-p parent info))
-      contents)))
-
-
-
-;;; Filter Functions
-
-(defun org-freemind-final-function (contents backend info)
-  "Return CONTENTS as pretty XML using `indent-region'."
-  (if (not org-freemind-pretty-output) contents
-    (with-temp-buffer
-      (nxml-mode)
-      (insert contents)
-      (indent-region (point-min) (point-max))
-      (buffer-substring-no-properties (point-min) (point-max)))))
-
-(defun org-freemind-options-function (info backend)
-  "Install script in export options when appropriate.
-EXP-PLIST is a plist containing export options.  BACKEND is the
-export back-end currently used."
-  ;; Freemind/Freeplane doesn't seem to like named html entities in
-  ;; richcontent.  For now, turn off smart quote processing so that
-  ;; entities like "&rsquo;" & friends are avoided in the exported
-  ;; output.
-  (plist-put info :with-smart-quotes nil))
-
-
-
-;;; End-user functions
-
-;;;###autoload
-(defun org-freemind-export-to-freemind
-  (&optional async subtreep visible-only body-only ext-plist)
-  "Export current buffer to a Freemind Mindmap file.
-
-If narrowing is active in the current buffer, only export its
-narrowed part.
-
-If a region is active, export that region.
-
-A non-nil optional argument ASYNC means the process should happen
-asynchronously.  The resulting file should be accessible through
-the `org-export-stack' interface.
-
-When optional argument SUBTREEP is non-nil, export the sub-tree
-at point, extracting information from the headline properties
-first.
-
-When optional argument VISIBLE-ONLY is non-nil, don't export
-contents of hidden elements.
-
-When optional argument BODY-ONLY is non-nil, only write code
-between \"<body>\" and \"</body>\" tags.
-
-EXT-PLIST, when provided, is a property list with external
-parameters overriding Org default settings, but still inferior to
-file-local settings.
-
-Return output file's name."
-  (interactive)
-  (let* ((extension (concat ".mm" ))
-        (file (org-export-output-file-name extension subtreep))
-        (org-export-coding-system 'utf-8))
-    (org-export-to-file 'freemind file
-      async subtreep visible-only body-only ext-plist)))
-
-(provide 'ox-freemind)
-
-;;; ox-freemind.el ends here
diff --git a/contrib/lisp/ox-groff.el b/contrib/lisp/ox-groff.el
deleted file mode 100644
index edf80a4..0000000
--- a/contrib/lisp/ox-groff.el
+++ /dev/null
@@ -1,1960 +0,0 @@
-;;; ox-groff.el --- Groff Back-End for Org Export Engine
-
-;; Copyright (C) 2011-2021  Free Software Foundation, Inc.
-
-;; Author: Nicolas Goaziou <n.goaziou at gmail dot com>
-;; Author: Luis R Anaya <papoanaya aroba hot mail punto com>
-;; Keywords: outlines, hypermedia, calendar, wp
-
-;; This file is not 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 this program.  If not, see <http://www.gnu.org/licenses/>.
-;;; Commentary:
-;;
-;; This library implements a Groff Memorandum Macro back-end for Org
-;; generic exporter.
-;;
-;; To test it, run
-;;
-;;   M-: (org-export-to-buffer 'groff "*Test Groff*") RET
-;;
-;; in an org-mode buffer then switch to the buffer to see the Groff
-;; export.  See ox.el for more details on how this exporter works.
-;;
-;; It introduces two new buffer keywords: "GROFF_CLASS" and
-;; "GROFF_CLASS_OPTIONS".
-
-;;; Code:
-
-(eval-when-compile (require 'cl))
-(require 'ox)
-
-(defvar orgtbl-exp-regexp)
-
-
-;;; Define Back-End
-
-(org-export-define-backend 'groff
-  '((bold . org-groff-bold)
-    (center-block . org-groff-center-block)
-    (clock . org-groff-clock)
-    (code . org-groff-code)
-    (drawer . org-groff-drawer)
-    (dynamic-block . org-groff-dynamic-block)
-    (entity . org-groff-entity)
-    (example-block . org-groff-example-block)
-    (export-block . org-groff-export-block)
-    (export-snippet . org-groff-export-snippet)
-    (fixed-width . org-groff-fixed-width)
-    (footnote-definition . org-groff-footnote-definition)
-    (footnote-reference . org-groff-footnote-reference)
-    (headline . org-groff-headline)
-    (horizontal-rule . org-groff-horizontal-rule)
-    (inline-src-block . org-groff-inline-src-block)
-    (inlinetask . org-groff-inlinetask)
-    (italic . org-groff-italic)
-    (item . org-groff-item)
-    (keyword . org-groff-keyword)
-    (line-break . org-groff-line-break)
-    (link . org-groff-link)
-    (node-property . org-groff-node-property)
-    (paragraph . org-groff-paragraph)
-    (plain-list . org-groff-plain-list)
-    (plain-text . org-groff-plain-text)
-    (planning . org-groff-planning)
-    (property-drawer . org-groff-property-drawer)
-    (quote-block . org-groff-quote-block)
-    (radio-target . org-groff-radio-target)
-    (section . org-groff-section)
-    (special-block . org-groff-special-block)
-    (src-block . org-groff-src-block)
-    (statistics-cookie . org-groff-statistics-cookie)
-    (strike-through . org-groff-strike-through)
-    (subscript . org-groff-subscript)
-    (superscript . org-groff-superscript)
-    (table . org-groff-table)
-    (table-cell . org-groff-table-cell)
-    (table-row . org-groff-table-row)
-    (target . org-groff-target)
-    (template . org-groff-template)
-    (timestamp . org-groff-timestamp)
-    (underline . org-groff-underline)
-    (verbatim . org-groff-verbatim)
-    (verse-block . org-groff-verse-block))
-  :menu-entry
-  '(?g "Export to GROFF"
-       ((?g "As GROFF file" org-groff-export-to-groff)
-       (?p "As PDF file" org-groff-export-to-pdf)
-       (?o "As PDF file and open"
-           (lambda (a s v b)
-             (if a (org-groff-export-to-pdf t s v b)
-               (org-open-file (org-groff-export-to-pdf nil s v b)))))))
-  :options-alist
-  '((:groff-class "GROFF_CLASS" nil org-groff-default-class t)
-    (:groff-class-options "GROFF_CLASS_OPTIONS" nil nil t)
-    (:groff-header-extra "GROFF_HEADER" nil nil newline)))
-
-
-
-;;; User Configurable Variables
-
-(defgroup org-export-groff nil
-  "Options for exporting Org mode files to Groff."
-  :tag "Org Export Groff"
-  :group 'org-export)
-
-;;; Preamble
-
-(defcustom org-groff-default-class "internal"
-  "The default Groff class."
-  :group 'org-export-groff
-  :type '(string :tag "Groff class"))
-
-(defcustom org-groff-classes
-  '(("file" ".MT 1"
-     (:heading 'default :type "memo" :last-section "toc"))
-    ("internal" ".MT 0"
-     (:heading 'default :type "memo" :last-section "toc"))
-    ("programmer" ".MT 2"
-     (:heading 'default :type "memo" :last-section "toc"))
-    ("engineer" ".MT 3"
-     (:heading 'default :type "memo" :last-section "toc"))
-    ("external" ".MT 4"
-     (:heading 'default :type "memo" :last-section "toc"))
-    ("letter" ".MT 5"
-     (:heading 'default :type "memo" :last-section "sign"))
-    ("custom" ".so file"
-     (:heading custom-function :type "custom" :last-section "toc"))
-    ("dummy" ""
-     (:heading 'default :type "memo"))
-    ("ms" "ms"
-     (:heading 'default :type "cover" :last-section "toc"))
-    ("se_ms" "se_ms"
-     (:heading 'default :type "cover" :last-section "toc"))
-    ("block" "BL"
-     (:heading 'default :type "letter" :last-section "sign"))
-    ("semiblock" "SB"
-     (:heading 'default :type "letter" :last-section "sign"))
-    ("fullblock" "FB"
-     (:heading 'default :type "letter" :last-section "sign"))
-    ("simplified" "SP"
-     (:heading 'default :type "letter" :last-section "sign"))
-    ("none" "" (:heading 'default :type "custom")))
-
-  ;; none means, no Cover or Memorandum Type and no calls to AU, AT, ND and TL
-  ;; This is to facilitate the creation of custom pages.
-
-  ;; dummy means, no Cover or Memorandum Type but calls to AU, AT, ND and TL
-  ;; are made. This is to facilitate Abstract Insertion.
-
-  "This list describes the attributes for the documents being created.
-   It allows for the creation of new "
-  :group 'org-export-groff
-  :type '(repeat
-          (list (string :tag "Document Type")
-                (string :tag "Header")
-                (repeat :tag "Options" :inline t
-                        (choice
-                         (list :tag "Heading")
-                         (function :tag "Hook computing sectioning"))))))
-
-;;; Headline
-
-(defconst org-groff-special-tags
-  '("FROM" "TO" "ABSTRACT" "APPENDIX" "BODY" "NS"))
-
-(defcustom org-groff-format-headline-function nil
-  "Function to format headline text.
-
-This function will be called with 5 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.
-
-As an example, one could set the variable to the following, in
-order to reproduce the default set-up:
-
-\(defun org-groff-format-headline (todo todo-type priority text tags)
-  \"Default format function for a headline.\"
-  \(concat (when todo
-            \(format \"\\fB%s\\fP \" todo))
-         \(when priority
-            \(format \"[\\#%c] \" priority))
-         text
-         \(when tags
-            \(format \" %s \"
-              \(mapconcat 'identity tags \":\"))))"
-  :group 'org-export-groff
-  :type 'function)
-
-;;; Timestamps
-
-(defcustom org-groff-active-timestamp-format "\\fI%s\\fP"
-  "A printf format string to be applied to active timestamps."
-  :group 'org-export-groff
-  :type 'string)
-
-(defcustom org-groff-inactive-timestamp-format "\\fI%s\\fP"
-  "A printf format string to be applied to inactive timestamps."
-  :group 'org-export-groff
-  :type 'string)
-
-(defcustom org-groff-diary-timestamp-format "\\fI%s\\fP"
-  "A printf format string to be applied to diary timestamps."
-  :group 'org-export-groff
-  :type 'string)
-
-;;; Links
-
-(defcustom org-groff-inline-image-rules
-  '(("file" . "\\.\\(jpg\\|png\\|pdf\\|ps\\|eps\\|pic\\)\\'")
-    ("fuzzy" . "\\.\\(jpg\\|png\\|pdf\\|ps\\|eps\\|pic\\)\\'"))
-  "Rules characterizing image files that can be inlined into Groff.
-
-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.
-
-Note that, by default, the image extensions actually allowed
-depend on the way the Groff file is processed.  When used with
-pdfgroff, pdf, jpg and png images are OK.  When processing
-through dvi to Postscript, only ps and eps are allowed.  The
-default we use here encompasses both."
-  :group 'org-export-groff
-  :type '(alist :key-type (string :tag "Type")
-                :value-type (regexp :tag "Path")))
-
-(defcustom org-groff-link-with-unknown-path-format "\\fI%s\\fP"
-  "Format string for links with unknown path type."
-  :group 'org-export-groff
-  :type 'string)
-
-;;; Tables
-
-(defcustom org-groff-tables-centered t
-  "When non-nil, tables are exported in a center environment."
-  :group 'org-export-groff
-  :type 'boolean)
-
-(defcustom org-groff-tables-verbatim nil
-  "When non-nil, tables are exported verbatim."
-  :group 'org-export-groff
-  :type 'boolean)
-
-(defcustom org-groff-table-scientific-notation "%sE%s"
-  "Format string to display numbers in scientific notation.
-The format should have \"%s\" twice, for mantissa and exponent
-\(i.e. \"%s\\\\times10^{%s}\").
-
-When nil, no transformation is made."
-  :group 'org-export-groff
-  :type '(choice
-          (string :tag "Format string")
-          (const :tag "No formatting")))
-
-;;; Text markup
-
-(defcustom org-groff-text-markup-alist
-   '((bold . "\\fB%s\\fP")
-    (code . "\\fC%s\\fP")
-    (italic . "\\fI%s\\fP")
-    (strike-through . "\\fC%s\\fP")  ; Strike through and underline
-    (underline . "\\fI%s\\fP")       ; need to be revised.
-    (verbatim .   "protectedtexttt"))
-  "Alist of Groff expressions to convert text markup.
-
-The key must be a symbol among `bold', `code', `italic',
-`strike-through', `underline' and `verbatim'.  The value is
-a formatting string to wrap fontified text with it.
-
-If no association can be found for a given markup, text will be
-returned as-is."
-  :group 'org-export-groff
-  :type 'alist
-  :options '(bold code italic strike-through underline verbatim))
-
-;;; Drawers
-
-(defcustom org-groff-format-drawer-function nil
-  "Function called to format a drawer in Groff code.
-
-The function must accept two parameters:
-  NAME      the drawer name, like \"LOGBOOK\"
-  CONTENTS  the contents of the drawer.
-
-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 behaviour:
-
-\(defun org-groff-format-drawer-default \(name contents\)
-  \"Format a drawer element for Groff export.\"
-  contents\)"
-  :group 'org-export-groff
-  :type 'function)
-
-;;; Inlinetasks
-
-(defcustom org-groff-format-inlinetask-function nil
-  "Function called to format an inlinetask in Groff 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.
-
-For example, the variable could be set to the following function
-in order to mimic default behaviour:
-
-\(defun org-groff-format-inlinetask \(todo type priority name tags contents\)
-\"Format an inline task element for Groff export.\"
-  \(let ((full-title
-        \(concat
-         \(when todo
-            \(format \"\\fB%s\\fP \" todo))
-         \(when priority (format \"[\\#%c] \" priority))
-         title
-         \(when tags
-            \(format \":%s:\"
-                    \(mapconcat 'identity tags \":\")))))
-    \(format (concat \".DS L\\n\"
-                   \"%s\\n\\n\"
-                   \"%s\"
-                   \".DE\")
-           full-title contents))"
-  :group 'org-export-groff
-  :type 'function)
-
-;; Src blocks
-
-(defcustom org-groff-source-highlight nil
-  "Use GNU source highlight to embellish source blocks "
-  :group 'org-export-groff
-  :type 'boolean)
-
-(defcustom org-groff-source-highlight-langs
-  '((emacs-lisp "lisp") (lisp "lisp") (clojure "lisp")
-    (scheme "scheme")
-    (c "c") (cc "cpp") (csharp "csharp") (d "d")
-    (fortran "fortran") (cobol "cobol") (pascal "pascal")
-    (ada "ada") (asm "asm")
-    (perl "perl") (cperl "perl")
-    (python "python") (ruby "ruby") (tcl "tcl") (lua "lua")
-    (java "java") (javascript "javascript")
-    (tex "latex")
-    (shell-script "sh") (awk "awk") (diff "diff") (m4 "m4")
-    (ocaml "caml") (caml "caml")
-    (sql "sql") (sqlite "sql")
-    (html "html") (css "css") (xml "xml")
-    (bat "bat") (bison "bison") (clipper "clipper")
-    (ldap "ldap") (opa "opa")
-    (php "php") (postscript "postscript") (prolog "prolog")
-    (properties "properties") (makefile "makefile")
-    (tml "tml") (vala "vala") (vbscript "vbscript") (xorg "xorg"))
-  "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
-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-groff
-  :type '(repeat
-          (list
-           (symbol :tag "Major mode       ")
-           (string :tag "Listings language"))))
-
-(defcustom org-groff-source-highlight-options nil
-  "Association list of options for the groff listings package.
-
-These options are supplied as a comma-separated list to the
-\\lstset command.  Each element of the association list should be
-a list containing two strings: the name of the option, and the
-value.  For example,
-
-  (setq org-groff-source-highlight-options
-    '((\"basicstyle\" \"\\small\")
-      (\"keywordstyle\" \"\\color{black}\\bfseries\\underbar\")))
-
-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."
-  :group 'org-export-groff
-  :type '(repeat
-          (list
-           (string :tag "Listings option name ")
-           (string :tag "Listings option value"))))
-
-(defvar org-groff-custom-lang-environments nil
-  "Alist mapping languages to language-specific Groff environments.
-
-It is used during export of src blocks by the listings and
-groff packages.  For example,
-
-  \(setq org-groff-custom-lang-environments
-     '\(\(python \"pythoncode\"\)\)\)
-
-would have the effect that if org encounters begin_src python
-during groff export it will use pythoncode as the source-highlight
-language.")
-
-;;; Plain text
-
-(defcustom org-groff-special-char
-  '(("(c)" . "\\\\(co")
-    ("(tm)" . "\\\\(tm")
-    ("(rg)" . "\\\\(rg"))
-  "CONS list in which the value of the car
-  is replace on the value of the CDR. "
-  :group 'org-export-groff
-  :type '(list
-          (cons :tag "Character Substitute"
-                (string :tag "Original Character Group")
-                (string :tag "Replacement Character"))))
-
-;;; Compilation
-
-(defcustom org-groff-pdf-process
-  '("pic %f | tbl | eqn | groff -mm | ps2pdf - > %b.pdf"
-    "pic %f | tbl | eqn | groff -mm | ps2pdf - > %b.pdf"
-    "pic %f | tbl | eqn | groff -mm | ps2pdf - > %b.pdf")
-
-  "Commands to process a Groff 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
-extension) and %o by the base directory of the file."
-  :group 'org-export-pdf
-  :type '(choice
-          (repeat :tag "Shell command sequence"
-                  (string :tag "Shell command"))
-          (const :tag "2 runs of pdfgroff"
-                 ("pic %f | tbl | eqn | groff -mm | ps2pdf - > %b.pdf"
-                  "pic %f | tbl | eqn | groff -mm | ps2pdf - > %b.pdf"))
-          (const :tag "3 runs of pdfgroff"
-                 ("pic %f | tbl | eqn | groff -mm | ps2pdf - > %b.pdf"
-                  "pic %f | tbl | eqn | groff -mm | ps2pdf - > %b.pdf"
-                  "pic %f | tbl | eqn | groff -mm | ps2pdf - > %b.pdf"))
-          (function)))
-
-(defcustom org-groff-logfiles-extensions
-  '("aux" "idx" "log" "out" "toc" "nav" "snm" "vrb")
-  "The list of file extensions to consider as Groff logfiles."
-  :group 'org-export-groff
-  :type '(repeat (string :tag "Extension")))
-
-(defcustom org-groff-remove-logfiles t
-  "Non-nil means remove the logfiles produced by PDF production.
-These are the .aux, .log, .out, and .toc files."
-  :group 'org-export-groff
-  :type 'boolean)
-
-(defcustom org-groff-organization "Org User"
-  "Name of the organization used to populate the .AF command."
-  :group 'org-export-groff
-  :type 'string)
-
-(defcustom org-groff-raster-to-ps nil
-  "Command used to convert raster to EPS. Nil for no conversion. Make sure that
-   `org-groff-inline-image-rules' is adjusted accordingly if not conversion is 
being
-   done. In this case, remove the entries for jpg and png in the file and 
fuzzy lists."
-  :group 'org-export-groff
-  :type '(choice
-         (repeat :tag "Shell Command Sequence" (string :tag "Shell Command"))
-         (const :tag "sam2p" "a=%s;b=%s;sam2p ${a} ${b} ;grep -v BeginData 
${b} > b_${b};mv b_${b} ${b}" )
-         (const :tag "NetPNM"  "a=%s;b=%s;pngtopnm ${a} | pnmtops -noturn > 
${b}" )
-         (const :tag "None" nil)))
-
-(defvar org-groff-registered-references nil)
-(defvar org-groff-special-content nil)
-
-
-
-;;; Internal Functions
-
-(defun org-groff--caption/label-string (element info)
-  "Return caption and label Groff string for ELEMENT.
-
-INFO is a plist holding contextual information.  If there's no
-caption nor label, return the empty string.
-
-For non-floats, see `org-groff--wrap-label'."
-  (let ((main (org-export-get-caption element))
-       (short (org-export-get-caption element t))
-       (label (org-element-property :name element)))
-    (cond ((and (not main) (not label)) "")
-         ((not main) (format "\\fI%s\\fP" label))
-         ;; Option caption format with short name.
-         (short (format "%s\n.br\n - %s\n"
-                        (org-export-data short info)
-                        (org-export-data main info)))
-         ;; Standard caption format.
-         (t (format "\\fR%s\\fP" (org-export-data main info))))))
-
-(defun org-groff--wrap-label (element output)
-  "Wrap label associated to ELEMENT around OUTPUT, if appropriate.
-This function shouldn't be used for floats.  See
-`org-groff--caption/label-string'."
-  (let ((label (org-element-property :name element)))
-    (if (or (not output) (not label) (string= output "") (string= label ""))
-        output
-      (concat (format "%s\n.br\n" label) output))))
-
-(defun org-groff--text-markup (text markup)
-  "Format TEXT depending on MARKUP text markup.
-See `org-groff-text-markup-alist' for details."
-  (let ((fmt (cdr (assq markup org-groff-text-markup-alist))))
-    (cond
-     ;; No format string: Return raw text.
-     ((not fmt) text)
-     ((string= "protectedtexttt" fmt)
-      (let ((start 0)
-            (trans '(("\\" . "\\")))
-            (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))
-        (format "\\fC%s\\fP" text)))
-     ;; Else use format string.
-     (t (format fmt text)))))
-
-
-(defun org-groff--get-tagged-content  (tag info)
-  (cdr  (assoc tag org-groff-special-content)))
-
-(defun org-groff--mt-head (title contents attr info)
-  (concat
-
-   ;; 1. Insert Organization
-   (let ((firm-option (plist-get attr :firm)))
-     (cond
-      ((stringp firm-option)
-       (format ".AF \"%s\" \n" firm-option))
-      (t (format ".AF \"%s\" \n" (or org-groff-organization "")))))
-
-   ;; 2. Title
-   (let ((title (if (plist-get info :with-title) title ""))
-        (subtitle1 (plist-get attr :subtitle1))
-         (subtitle2 (plist-get attr :subtitle2)))
-
-     (cond
-      ((string= "" title)
-       (format ".TL \"%s\" \"%s\" \n%s\n"
-               (or subtitle1 "")
-               (or subtitle2 "") " "))
-
-      ((not (or subtitle1 subtitle2))
-       (format ".TL\n%s\n"
-               (or title "")))
-      (t
-       (format ".TL \"%s\" \"%s \" \n%s\n"
-               (or subtitle1 "")
-               (or subtitle2 "") title))))
-
-   ;; 3. Author.
-   ;; In Groff, .AU *MUST* be placed after .TL
-   ;; If From, populate with data from From else
-   ;;
-   (let ((author (and (plist-get info :with-author)
-                      (let ((auth (plist-get info :author)))
-                        (and auth (org-export-data auth info)))))
-         (email (and (plist-get info :with-email)
-                     (org-export-data (plist-get info :email) info)))
-         (from-data  (org-groff--get-tagged-content "FROM" info))
-
-         (to-data  (org-groff--get-tagged-content "TO" info)))
-
-     (cond
-      ((and author from-data)
-       (let ((au-line
-              (mapconcat
-               (lambda (from-line)
-                 (format " \"%s\" " from-line))
-               (split-string
-                (setq from-data
-                      (replace-regexp-in-string "\\.P\n" "" from-data)) "\n") 
"")))
-
-         (concat
-          (format ".AU \"%s\" " author) au-line "\n")))
-
-      ((and author email (not (string= "" email)))
-       (format ".AU \"%s\" \"%s\"\n" author email))
-
-      (author (format ".AU \"%s\"\n" author))
-
-      (t ".AU \"\" \n")))
-
-
-   ;; 4. Author Title, if present
-   (let ((at-item (plist-get attr :author-title)))
-     (if (and at-item (stringp at-item))
-         (format ".AT \"%s\" \n" at-item)
-       ""))
-
-   ;; 5. Date.
-   (when (plist-get info :with-date)
-     (let ((date (org-export-data (org-export-get-date info) info)))
-       (and (org-string-nw-p date) (format ".ND \"%s\"\n" date))))
-
-   ;;
-   ;; If Abstract, then Populate Abstract
-   ;;
-
-   (let ((abstract-data (org-groff--get-tagged-content "ABSTRACT" info))
-         (to-data (org-groff--get-tagged-content "TO" info)))
-     (cond
-      (abstract-data
-       (format ".AS\n%s\n.AE\n" abstract-data))
-      (to-data
-       (format ".AS\n%s\n.AE\n" to-data))))))
-
-(defun org-groff--letter-head (title contents attr info)
-  (let ((author (and (plist-get info :with-author)
-                     (let ((auth (plist-get info :author)))
-                       (and auth (org-export-data auth info)))))
-        (email (and (plist-get info :with-email)
-                    (org-export-data (plist-get info :email) info)))
-        (from-data  (org-groff--get-tagged-content "FROM" info))
-        (at-item (plist-get attr :author-title))
-        (to-data  (org-groff--get-tagged-content "TO" info)))
-
-
-    ;; If FROM then get data from FROM
-    (if from-data 
-        (setq from-data
-              (replace-regexp-in-string "\\.P\n" "" from-data))
-      (setq from-data ""))
-    
-    (if to-data 
-        (setq to-data
-              (replace-regexp-in-string "\\.P\n" "" to-data))
-      (setq from-data ""))
-    
-    (concat
-     (cond
-      (from-data
-       (format ".WA \"%s\" \"%s\" \n%s\n.WE\n" author (or at-item "") 
from-data))
-      ((and author email (not (string= "" email)))
-       (format ".WA \"%s\"\n \"%s\"\n.WE\n" author email))
-      (author (format ".WA \"%s\"\n.WE\n" author))
-      (t ".WA \"\" \n.WE\n"))
-
-     ;; If TO then get data from TO
-
-     (when to-data
-       (format ".IA \n%s\n.IE\n" to-data)))))
-
-
-;;; Template
-
-(defun org-groff-template (contents info)
-  "Return complete document string after Groff conversion.
-CONTENTS is the transcoded contents string.  INFO is a plist
-holding export options."
-  (let* ((title (org-export-data (plist-get info :title) info))
-         (attr (read
-                (format "(%s)"
-                        (mapconcat
-                         #'identity
-                         (list (plist-get info :groff-class-options))
-                         " "))))
-         (class (plist-get info :groff-class))
-         (class-options (plist-get info :groff-class-options))
-         (classes (assoc class org-groff-classes))
-         (classes-options (car (last classes)))
-         (heading-option (plist-get classes-options :heading))
-         (type-option (plist-get classes-options :type))
-         (last-option (plist-get classes-options :last-section))
-         (hyphenate (plist-get attr :hyphenate))
-         (justify-right (plist-get attr :justify-right))
-
-         (document-class-string
-          (progn
-            (org-element-normalize-string
-             (let* ((header (nth 1 (assoc class org-groff-classes)))
-                    (document-class-item (if (stringp header) header "")))
-               document-class-item)))))
-
-
-    (concat
-     (if justify-right
-         (case justify-right
-           ('yes ".SA 1 \n")
-           ('no ".SA 0 \n")
-           (t ""))
-       "")
-
-     (if hyphenate
-         (case hyphenate
-           ('yes ".nr Hy 1 \n")
-           ('no ".nr Hy 0 \n")
-           (t ""))
-       "")
-
-     (cond
-      ((string= type-option "custom") "")
-
-      ((and (stringp document-class-string)
-            (string= type-option "cover"))
-
-       (concat
-        (format ".COVER %s\n" document-class-string)
-        (org-groff--mt-head title contents attr info)
-        ".COVEND\n"))
-
-      ((string= type-option "memo")
-       (concat
-        (org-groff--mt-head title contents attr info)
-        document-class-string))
-      ((string= type-option "letter")
-       (concat
-        (org-groff--letter-head title contents attr info)
-        (let ((sa-item (plist-get attr :salutation))
-              (cn-item (plist-get attr :confidential))
-              (sj-item (plist-get attr :subject))
-              (rn-item (plist-get attr :reference))
-              (at-item (plist-get attr :attention)))
-
-          (concat
-
-           (if (stringp sa-item)
-               (format ".LO SA \"%s\" \n"  sa-item)
-             ".LO SA\n")
-
-           (when cn-item
-             (if (stringp cn-item)
-                 (format ".LO CN \"%s\"\n" cn-item)
-               ".LO CN\n"))
-
-           (when (and at-item (stringp at-item))
-             (format ".LO AT \"%s\" \n"  at-item))
-           (when (and title rn-item)
-             (format ".LO RN \"%s\"\n" title))
-
-           (when (and sj-item (stringp sj-item))
-             (format ".LO SJ \"%s\" \n"  sj-item))
-
-
-           ".LT " document-class-string  "\n"))))
-
-      (t ""))
-
-     contents
-
-     (cond
-      ((string= last-option "toc")
-       ".TC")
-      ((string= last-option "sign")
-       (let ((fc-item (plist-get attr :closing)))
-         (concat (if (stringp fc-item)
-                     (format ".FC \"%s\" \n" fc-item)
-                   ".FC\n")
-                 ".SG\n")))
-      (t ""))
-
-     (progn
-       (mapconcat
-        (lambda (item)
-          (when (string= (car item) "NS")
-            (replace-regexp-in-string
-                    "\\.P\n" "" (cdr item))))
-        (reverse org-groff-special-content) "\n")))))
-
-
-
-;;; Transcode Functions
-
-;;; Babel Call
-;;
-;; Babel Calls are ignored.
-
-
-;;; Bold
-
-(defun org-groff-bold (bold contents info)
-  "Transcode BOLD from Org to Groff.
-CONTENTS is the text with bold markup.  INFO is a plist holding
-contextual information."
-  (org-groff--text-markup contents 'bold))
-
-;;; Center Block
-
-(defun org-groff-center-block (center-block contents info)
-  "Transcode a CENTER-BLOCK element from Org to Groff.
-CONTENTS holds the contents of the center block.  INFO is a plist
-holding contextual information."
-  (org-groff--wrap-label
-   center-block
-   (format ".DS C \n%s\n.DE" contents)))
-
-;;; Clock
-
-(defun org-groff-clock (clock contents info)
-  "Transcode a CLOCK element from Org to Groff.
-CONTENTS is nil.  INFO is a plist holding contextual
-information."
-  (concat
-   (format "\\fB%s\\fP " org-clock-string)
-   (format org-groff-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-groff-code (code contents info)
-  "Transcode a CODE object from Org to Groff.
-CONTENTS is nil.  INFO is a plist used as a communication
-channel."
-  (org-groff--text-markup (org-element-property :value code) 'code))
-
-;;; Comments and Comment Blocks are ignored.
-
-;;; Drawer
-
-(defun org-groff-drawer (drawer contents info)
-  "Transcode a DRAWER element from Org to Groff.
-CONTENTS holds the contents of the block.  INFO is a plist
-holding contextual information."
-  (let* ((name (org-element-property :drawer-name drawer))
-         (output (if (functionp org-groff-format-drawer-function)
-                     (funcall org-groff-format-drawer-function
-                              name contents)
-                   ;; If there's no user defined function: simply
-                   ;; display contents of the drawer.
-                   contents)))
-    (org-groff--wrap-label drawer output)))
-
-;;; Dynamic Block
-
-(defun org-groff-dynamic-block (dynamic-block contents info)
-  "Transcode a DYNAMIC-BLOCK element from Org to Groff.
-CONTENTS holds the contents of the block.  INFO is a plist
-holding contextual information.  See `org-export-data'."
-  (org-groff--wrap-label dynamic-block contents))
-
-;;; Entity
-
-(defun org-groff-entity (entity contents info)
-  "Transcode an ENTITY object from Org to Groff.
-CONTENTS are the definition itself.  INFO is a plist holding
-contextual information."
-  (org-element-property :utf-8 entity))
-
-;;; Example Block
-
-(defun org-groff-example-block (example-block contents info)
-  "Transcode an EXAMPLE-BLOCK element from Org to Groff.
-CONTENTS is nil.  INFO is a plist holding contextual
-information."
-  (org-groff--wrap-label
-   example-block
-   (format ".DS L\n%s\n.DE"
-           (org-export-format-code-default example-block info))))
-
-;;; Export Block
-
-(defun org-groff-export-block (export-block contents info)
-  "Transcode a EXPORT-BLOCK element from Org to Groff.
-CONTENTS is nil.  INFO is a plist holding contextual information."
-  (when (string= (org-element-property :type export-block) "GROFF")
-    (org-remove-indentation (org-element-property :value export-block))))
-
-;;; Export Snippet
-
-(defun org-groff-export-snippet (export-snippet contents info)
-  "Transcode a EXPORT-SNIPPET object from Org to Groff.
-CONTENTS is nil.  INFO is a plist holding contextual information."
-  (when (eq (org-export-snippet-backend export-snippet) 'groff)
-    (org-element-property :value export-snippet)))
-
-;;; Fixed Width
-
-(defun org-groff-fixed-width (fixed-width contents info)
-  "Transcode a FIXED-WIDTH element from Org to Groff.
-CONTENTS is nil.  INFO is a plist holding contextual information."
-  (org-groff--wrap-label
-   fixed-width
-   (format "\\fC\n%s\n\\fP"
-           (org-remove-indentation
-            (org-element-property :value fixed-width)))))
-
-;;; Footnote Definition
-;;
-;; Footnote Definitions are ignored.
-;;
-;; Footnotes are handled automatically in GROFF.  Although manual
-;; references can be added, not really required.
-
-(defun org-groff-footnote-reference (footnote-reference contents info)
-  ;; Changing from info to footnote-reference
-  (let* ((raw (org-export-get-footnote-definition footnote-reference info))
-                (n (org-export-get-footnote-number footnote-reference info))
-                (data (org-trim (org-export-data raw info)))
-         (ref-id (plist-get (nth 1 footnote-reference) :label)))
-    ;; It is a reference
-    (if (string-match "fn:rl" ref-id)
-        (if (member ref-id org-groff-registered-references)
-            (format "\\*[%s]" ref-id)
-          (progn
-            (push ref-id org-groff-registered-references)
-            (format "\\*(Rf\n.RS \"%s\" \n%s\n.RF\n" ref-id  data)))
-      ;; else it is a footnote
-      (format "\\u\\s-2%s\\d\\s+2\n.FS %s\n%s\n.FE\n" n n data))))
-
-;;; Headline
-
-(defun org-groff-headline (headline contents info)
-  "Transcode a HEADLINE element from Org to Groff.
-CONTENTS holds the contents of the headline.  INFO is a plist
-holding contextual information."
-  (let* ((class (plist-get info :groff-class))
-         (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.
-         (classes (assoc class org-groff-classes))
-         (classes-options (car (last classes)))
-         (heading-option (plist-get classes-options :heading))
-         (section-fmt
-          (progn
-            (cond
-             ((and (symbolp heading-option)
-                   (fboundp heading-option))
-              (funcall heading-option level numberedp))
-             ((> level 7) nil)
-             (t (if numberedp
-                    (concat ".H " (number-to-string level) " \"%s\"\n%s")
-                  ".HU \"%s\"\n%s")))))
-         ;; End of section-fmt
-         (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)))
-         ;; Create the headline text along with a no-tag version.  The
-         ;; latter is required to remove tags from table of contents.
-         (full-text (if (functionp org-groff-format-headline-function)
-                        ;; User-defined formatting function.
-                        (funcall org-groff-format-headline-function
-                                 todo todo-type priority text tags)
-                      ;; Default formatting.
-                      (concat
-                       (when todo
-                         (format "\\fB%s\\fP " todo))
-                       (when priority (format " [\\#%c] " priority))
-                       text
-                       (when tags
-                         (format " \\fC%s\\fP " (org-make-tag-string tags))))))
-         (full-text-no-tag
-          (if (functionp org-groff-format-headline-function)
-              ;; User-defined formatting function.
-              (funcall org-groff-format-headline-function
-                       todo todo-type priority text nil)
-            ;; Default formatting.
-            (concat
-             (when todo (format "\\fB%s\\fP " todo))
-             (when priority (format " [\\#%c] " priority))
-             text)))
-         ;; Associate some \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 "")
-         (pre-blanks
-          (make-string (org-element-property :pre-blank headline) 10)))
-
-    (cond
-     ;; Case 1: Special Tag
-     ((member (car  tags)  org-groff-special-tags)
-      (cond
-       ((string= (car tags) "BODY") contents)
-
-       ((string= (car tags) "NS")
-        (progn
-          (push (cons (car tags)
-                      (format ".NS \"%s\" 1 \n%s"
-                              (car (org-element-property :title headline))
-                              (or contents " ")))
-                org-groff-special-content) nil))
-
-       (t
-        (progn
-          (push (cons  (car tags) contents) org-groff-special-content)
-          nil))))
-
-     ;; Case 2: This is a footnote section: ignore it.
-     ((org-element-property :footnote-section-p headline) nil)
-
-     ;; Case 3: This is a deep sub-tree: export it as a list item.
-     ;;         Also export as items headlines for which no section
-     ;;         format has been found.
-     ((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" (if numberedp ".AL 1\n" ".DL \n")))
-              ;; Itemize headline
-              ".LI\n" full-text "\n" headline-label pre-blanks contents)))
-        ;; 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]*\\'"
-           (concat "\n.LE")
-           low-level-body))))
-
-     ;; Case 4. Standard headline.  Export it as a section.
-     (t
-      (format section-fmt full-text
-              (concat headline-label pre-blanks contents))))))
-
-;;; Horizontal Rule
-;; Not supported
-
-;;; Inline Babel Call
-;;
-;; Inline Babel Calls are ignored.
-
-;;; Inline Src Block
-
-(defun org-groff-inline-src-block (inline-src-block contents info)
-  "Transcode an INLINE-SRC-BLOCK element from Org to Groff.
-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-groff-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-groff-source-highlight-langs)))
-
-             (cmd (concat (expand-file-name "source-highlight")
-                          " -s " lst-lang
-                          " -f groff_mm_color "
-                          " -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 ".DS I\n\\fC\\m[black]%s\\m[]\\fP\n.DE\n"
-                  code))))
-
-     ;; Do not use a special package: transcode it verbatim.
-     (t
-      (concat ".DS I\n" "\\fC" code "\\fP\n.DE\n")))))
-
-;;; Inlinetask
-
-(defun org-groff-inlinetask (inlinetask contents info)
-  "Transcode an INLINETASK element from Org to Groff.
-CONTENTS holds the contents of the block.  INFO is a plist
-holding contextual information."
-  (let ((title (org-export-data (org-element-property :title inlinetask) info))
-        (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 (org-element-property :todo-type inlinetask))
-        (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-groff-format-inlinetask-function' is provided, call it
-    ;; with appropriate arguments.
-    (if (functionp org-groff-format-inlinetask-function)
-        (funcall org-groff-format-inlinetask-function
-                 todo todo-type priority title tags contents)
-      ;; Otherwise, use a default template.
-      (org-groff--wrap-label
-       inlinetask
-       (let ((full-title
-              (concat
-               (when todo (format "\\fB%s\\fP " todo))
-               (when priority (format " [\\#%c] " priority))
-               title
-               (when tags (format " \\fC%s\\fP " (org-make-tag-string 
tags))))))
-         (format (concat "\n.DS I\n"
-                         "%s\n"
-                         ".sp"
-                         "%s\n"
-                         ".DE")
-                 full-title contents))))))
-
-;;; Italic
-
-(defun org-groff-italic (italic contents info)
-  "Transcode ITALIC from Org to Groff.
-CONTENTS is the text with italic markup.  INFO is a plist holding
-contextual information."
-  (org-groff--text-markup contents 'italic))
-
-;;; Item
-
-(defun org-groff-item (item contents info)
-  "Transcode an ITEM element from Org to Groff.
-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'")))
-         (tag (let ((tag (org-element-property :tag item)))
-                ;; Check-boxes must belong to the tag.
-                (and tag (format "%s"
-                                 (concat checkbox
-                                         (org-export-data tag info)))))))
-
-       (cond
-        ((or checkbox tag)
-         (concat ".LI ""\"" (or tag (concat "\\ " checkbox)) "\""
-              "\n"
-              (org-trim (or contents " "))))
-     ((eq type 'ordered)
-      (concat ".LI"
-              "\n"
-              (org-trim (or contents " "))))
-     (t
-      (let* ((bullet (org-trim bullet))
-             (marker (cond  ((string= "-" bullet) "\\(em")
-                            ((string= "*" bullet) "\\(bu")
-                            (t "\\(dg"))))
-        (concat ".LI " marker "\n"
-                (org-trim (or contents " "))))))))
-
-;;; Keyword
-
-(defun org-groff-keyword (keyword contents info)
-  "Transcode a KEYWORD element from Org to Groff.
-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 "GROFF") value)
-     (t nil))))
-
-;;; Line Break
-
-(defun org-groff-line-break (line-break contents info)
-  "Transcode a LINE-BREAK object from Org to Groff.
-CONTENTS is nil.  INFO is a plist holding contextual information."
-  ".br\n")
-
-;;; Link
-;; Inline images just place a call to .PSPIC or .PS/.PE
-;;  and load the graph.
-
-(defun org-groff-link--inline-image (link info)
-  "Return Groff code for an inline image.
-LINK is the link pointing to the inline image.  INFO is a plist
-used as a communication channel."
-  (let* ((parent (org-export-get-parent-element link))
-         (path (let ((raw-path (org-element-property :path link)))
-                 (if (not (file-name-absolute-p raw-path)) raw-path
-                   (expand-file-name raw-path))))
-         (attr (org-export-read-attribute :attr_groff link))
-         (placement
-          (let ((pos (plist-get attr :position)))
-           (cond ((string= pos 'center) "")
-                 ((string= pos 'left) "-L")
-                 ((string= pos 'right) "-R")
-                 (t ""))))
-        (width  (or (plist-get attr :width) ""))
-        (height (or (plist-get attr :height) ""))
-        (caption (and (not (plist-get attr :disable-caption))
-                      (org-groff--caption/label-string parent info))))
-    ;; Now clear ATTR from any special keyword and set a default value
-    ;; if nothing is left.  Return proper string.
-    (concat
-     (cond
-      ((and org-groff-raster-to-ps
-            (or  (string-match ".\.png$" path)
-                 (string-match ".\.jpg$" path)))
-       (let ((eps-path (concat path ".eps")))
-         (shell-command (format org-groff-raster-to-ps path eps-path))
-         (format "\n.DS L F\n.PSPIC %s \"%s\" %s %s\n.DE "
-                 placement eps-path width height)))
-      ((string-match ".\.pic$" path)
-       (format "\n.PS\ncopy \"%s\"\n.PE" path))
-      (t (format "\n.DS L F\n.PSPIC %s \"%s\" %s %s\n.DE "
-                 placement path width height)))
-     (and caption (format "\n.FG \"%s\"" caption)))))
-
-(defun org-groff-link (link desc info)
-  "Transcode a LINK object from Org to Groff.
-
-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 (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-groff-inline-image-rules))
-         (path (cond
-                ((member type '("http" "https" "ftp" "mailto"))
-                 (concat type ":" raw-path))
-                ((string= type "file") (org-export-file-uri raw-path))
-                (t raw-path))))
-    (cond
-     ((org-export-custom-protocol-maybe link desc 'groff info))
-     ;; Image file.
-     (imagep (org-groff-link--inline-image link info))
-     ;; import groff files
-     ((and (string= type "file")
-           (string-match ".\.groff$" raw-path))
-      (concat ".so " raw-path "\n"))
-     ;; Radio link: transcode target's contents and use them as link's
-     ;; description.
-     ((string= type "radio")
-      (let ((destination (org-export-resolve-radio-link link info)))
-        (if (not destination) desc
-          (format "\\fI [%s] \\fP"
-                 (org-export-get-reference destination info)))))
-
-     ;; 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)
-          ;; Id link points to an external file.
-          (plain-text
-           (if desc (format "%s \\fBat\\fP \\fIfile://%s\\fP" desc destination)
-             (format "\\fI file://%s \\fP" destination)))
-          ;; Fuzzy link points nowhere.
-          ('nil
-           (format org-groff-link-with-unknown-path-format
-                   (or desc
-                       (org-export-data
-                        (org-element-property :raw-link link) info))))
-          ;; LINK points to a headline.  If headlines are numbered and
-          ;; the link has no description, display headline's number.
-          ;; Otherwise, display description or headline's title.
-          (headline
-           (let ((label ""))
-             (if (and (plist-get info :section-numbers) (not desc))
-                 (format "\\fI%s\\fP" label)
-               (format "\\fI%s\\fP"
-                       (or desc
-                           (org-export-data
-                            (org-element-property :title destination) 
info))))))
-          ;; Fuzzy link points to a target.  Do as above.
-          (otherwise
-           (let ((ref (org-export-get-reference destination info)))
-             (if (not desc) (format "\\fI%s\\fP" ref)
-               (format "%s \\fBat\\fP \\fI%s\\fP" desc ref)))))))
-     ;; External link with a description part.
-     ((and path desc) (format "%s \\fBat\\fP \\fI%s\\fP" path desc))
-     ;; External link without a description part.
-     (path (format "\\fI%s\\fP" path))
-     ;; No path, only description.  Try to do something useful.
-     (t (format org-groff-link-with-unknown-path-format desc)))))
-
-;;; Node Property
-
-(defun org-groff-node-property (node-property contents info)
-  "Transcode a NODE-PROPERTY element from Org to Groff.
-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-groff-paragraph (paragraph contents info)
-  "Transcode a PARAGRAPH element from Org to Groff.
-CONTENTS is the contents of the paragraph, as a string.  INFO is
-the plist used as a communication channel."
-  (let ((parent (plist-get (nth 1 paragraph) :parent)))
-    (when parent
-      (let* ((parent-type (car parent))
-             (fixed-paragraph "")
-             (class (plist-get info :groff-class))
-             (class-options (plist-get info :groff-class-options))
-             (classes (assoc class org-groff-classes))
-             (classes-options (car (last classes)))
-             (paragraph-option (plist-get classes-options :paragraph)))
-        (cond
-         ((and (symbolp paragraph-option)
-               (fboundp paragraph-option))
-          (funcall paragraph-option parent-type parent contents))
-         ((and (eq parent-type 'item)
-               (plist-get (nth 1 parent) :bullet))
-          (setq fixed-paragraph (concat "" contents)))
-         ((eq parent-type 'section)
-          (setq fixed-paragraph (concat ".P\n" contents)))
-         ((eq parent-type 'footnote-definition)
-          (setq fixed-paragraph (concat "" contents)))
-         (t (setq fixed-paragraph (concat "" contents))))
-        fixed-paragraph))))
-
-;;; Plain List
-
-(defun org-groff-plain-list (plain-list contents info)
-  "Transcode a PLAIN-LIST element from Org to Groff.
-CONTENTS is the contents of the list.  INFO is a plist holding
-contextual information."
-  (let* ((type (org-element-property :type plain-list))
-         (attr (mapconcat #'identity
-                          (org-element-property :attr_groff plain-list)
-                          " "))
-         (groff-type (cond
-                      ((eq type 'ordered) ".AL")
-                      ((eq type 'unordered) ".BL")
-                      ((eq type 'descriptive) ".VL 2.0i"))))
-    (org-groff--wrap-label
-     plain-list
-     (format "%s\n%s\n.LE" groff-type contents))))
-
-;;; Plain Text
-
-(defun org-groff-plain-text (text info)
-  "Transcode a TEXT string from Org to Groff.
-TEXT is the string to transcode.  INFO is a plist holding
-contextual information."
-(let ((output text))
-  ;; Protect various characters.
-  (setq output (replace-regexp-in-string
-               "\\(?:[^\\]\\|^\\)\\(\\\\\\)\\(?:[^%$#&{}~^_\\]\\|$\\)"
-               "$\\" output nil t 1))
-  ;; 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 :utf-8 info text)))
-  ;; Handle Special Characters
-  (if org-groff-special-char
-      (dolist (special-char-list org-groff-special-char)
-       (setq output
-             (replace-regexp-in-string (car special-char-list)
-                                       (cdr special-char-list) output))))
-  ;; Handle break preservation if required.
-  (when (plist-get info :preserve-breaks)
-    (setq output (replace-regexp-in-string
-                 "\\(\\\\\\\\\\)?[ \t]*\n" ".br\n" output)))
-  ;; Return value.
-  output))
-
-;;; Planning
-
-(defun org-groff-planning (planning contents info)
-  "Transcode a PLANNING element from Org to Groff.
-CONTENTS is nil.  INFO is a plist holding contextual
-information."
-  (concat
-   (mapconcat
-    'identity
-    (delq nil
-          (list
-           (let ((closed (org-element-property :closed planning)))
-             (when closed
-               (concat
-                (format "\\fR %s \\fP" org-closed-string)
-                (format org-groff-inactive-timestamp-format
-                        (org-timestamp-translate closed)))))
-           (let ((deadline (org-element-property :deadline planning)))
-             (when deadline
-               (concat
-                (format "\\fB %s \\fP" org-deadline-string)
-                (format org-groff-active-timestamp-format
-                        (org-timestamp-translate deadline)))))
-           (let ((scheduled (org-element-property :scheduled planning)))
-             (when scheduled
-               (concat
-                (format "\\fR %s \\fP" org-scheduled-string)
-                (format org-groff-active-timestamp-format
-                        (org-timestamp-translate scheduled)))))))
-    "")
-   ""))
-
-;;;; Property Drawer
-
-(defun org-groff-property-drawer (property-drawer contents info)
-  "Transcode a PROPERTY-DRAWER element from Org to Groff.
-CONTENTS holds the contents of the drawer.  INFO is a plist
-holding contextual information."
-  (and (org-string-nw-p contents)
-       (format "\\fC\n%s\\fP" contents)))
-
-;;; Quote Block
-
-(defun org-groff-quote-block (quote-block contents info)
-  "Transcode a QUOTE-BLOCK element from Org to Groff.
-CONTENTS holds the contents of the block.  INFO is a plist
-holding contextual information."
-  (org-groff--wrap-label
-   quote-block
-   (format ".DS I\n.I\n%s\n.R\n.DE" contents)))
-
-;;; Radio Target
-
-(defun org-groff-radio-target (radio-target text info)
-  "Transcode a RADIO-TARGET object from Org to Groff.
-TEXT is the text of the target.  INFO is a plist holding
-contextual information."
-  (format "%s - %s" (org-export-get-reference radio-target info) text))
-
-;;; Section
-
-(defun org-groff-section (section contents info)
-  "Transcode a SECTION element from Org to Groff.
-CONTENTS holds the contents of the section.  INFO is a plist
-holding contextual information."
-  contents)
-
-;;; Special Block
-
-(defun org-groff-special-block (special-block contents info)
-  "Transcode a SPECIAL-BLOCK element from Org to Groff.
-CONTENTS holds the contents of the block.  INFO is a plist
-holding contextual information."
-  (let ((type (org-element-property :type special-block)))
-    (org-groff--wrap-label
-     special-block
-     (format "%s\n" contents))))
-
-;;; Src Block
-
-(defun org-groff-src-block (src-block contents info)
-  "Transcode a SRC-BLOCK element from Org to Groff.
-CONTENTS holds the contents of the item.  INFO is a plist holding
-contextual information."
-  (let* ((lang (org-element-property :language src-block))
-         (label (org-element-property :name src-block))
-         (code (org-element-property :value src-block))
-         (custom-env (and lang
-                          (cadr (assq (intern lang)
-                                      org-groff-custom-lang-environments))))
-         (num-start (org-export-get-loc src-block info))
-         (retain-labels (org-element-property :retain-labels src-block))
-         (caption (and (not (org-export-read-attribute
-                            :attr_groff src-block :disable-caption))
-                      (org-groff--caption/label-string src-block info))))
-
-    (cond
-     ;; Case 1.  No source fontification.
-     ((not org-groff-source-highlight)
-      (concat
-       (format ".DS I\n\\fC%s\\fP\n.DE\n"
-              (org-export-format-code-default src-block info))
-       (and caption (format ".EX \"%s\" " caption))))
-
-     ;; Case 2.  Source fontification.
-     (org-groff-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 src-block))
-            (lst-lang (cadr (assq (intern org-lang)
-                                  org-groff-source-highlight-langs)))
-
-            (cmd (concat "source-highlight"
-                         " -s " lst-lang
-                         " -f groff_mm_color "
-                         " -i " in-file
-                         " -o " out-file)))
-
-       (concat
-        (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)
-              (format "%s\n"  code-block))
-          (format ".DS I\n\\fC\\m[black]%s\\m[]\\fP\n.DE\n"
-                  code))
-        (and caption (format ".EX \"%s\" " caption))))))))
-
-
-;;; Statistics Cookie
-
-(defun org-groff-statistics-cookie (statistics-cookie contents info)
-  "Transcode a STATISTICS-COOKIE object from Org to Groff.
-CONTENTS is nil.  INFO is a plist holding contextual information."
-  (org-element-property :value statistics-cookie))
-
-
-;;; Strike-Through
-
-(defun org-groff-strike-through (strike-through contents info)
-  "Transcode STRIKE-THROUGH from Org to Groff.
-CONTENTS is the text with strike-through markup.  INFO is a plist
-holding contextual information."
-  (org-groff--text-markup contents 'strike-through))
-
-;;; Subscript
-
-(defun org-groff-subscript (subscript contents info)
-  "Transcode a SUBSCRIPT object from Org to Groff.
-CONTENTS is the contents of the object.  INFO is a plist holding
-contextual information."
-  (format  "\\d\\s-2%s\\s+2\\u" contents))
-
-;;; Superscript "^_%s$
-
-(defun org-groff-superscript (superscript contents info)
-  "Transcode a SUPERSCRIPT object from Org to Groff.
-CONTENTS is the contents of the object.  INFO is a plist holding
-contextual information."
-  (format  "\\u\\s-2%s\\s+2\\d" contents))
-
-
-;;; Table
-;;
-;; `org-groff-table' is the entry point for table transcoding.  It
-;; takes care of tables with a "verbatim" attribute.  Otherwise, it
-;; delegates the job to  `org-groff-table--org-table' function,
-;; depending of the type of the table.
-;;
-;; `org-groff-table--align-string' is a subroutine used to build
-;; alignment string for Org tables.
-
-(defun org-groff-table (table contents info)
-  "Transcode a TABLE element from Org to Groff.
-CONTENTS is the contents of the table.  INFO is a plist holding
-contextual information."
-  (cond
-   ;; Case 1: verbatim table.
-   ((or org-groff-tables-verbatim
-        (let ((attr (read (format "(%s)"
-                 (mapconcat
-                  #'identity
-                                   (org-element-property :attr_groff table) " 
")))))
-          (and attr (plist-get attr :verbatim))))
-
-    (format ".DS L\n\\fC%s\\fP\n.DE"
-            ;; Re-create table, without affiliated keywords.
-            (org-trim
-             (org-element-interpret-data
-              `(table nil ,@(org-element-contents table))))))
-
-   ;; Case 2: Standard table.
-   (t (org-groff-table--org-table table contents info))))
-
-(defun org-groff-table--align-string (divider table info)
-  "Return an appropriate Groff alignment string.
-TABLE is the considered table.  INFO is a plist used as
-a communication channel."
-  (let (alignment)
-    ;; Extract column groups and alignment from first (non-rule) row.
-    (org-element-map
-       (org-element-map table 'table-row
-         (lambda (row)
-           (and (eq (org-element-property :type row) 'standard) row))
-         info 'first-match)
-       'table-cell
-      (lambda (cell)
-       (let* ((borders (org-export-table-cell-borders cell info))
-              (raw-width (org-export-table-cell-width cell info))
-              (width-cm (when raw-width (/ raw-width 5)))
-              (width (if raw-width (format "w(%dc)"
-                                           (if (< width-cm 1) 1 width-cm)) 
"")))
-         ;; Check left border for the first cell only.
-         ;; Alignment is nil on assignment
-
-         (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)))
-          alignment)
-         (when (memq 'right borders) (push "|" alignment))))
-      info)
-    (apply 'concat (reverse alignment))))
-
-(defun org-groff-table--org-table (table contents info)
-  "Return appropriate Groff code for an Org table.
-
-TABLE is the table type element to transcode.  CONTENTS is its
-contents, as a string.  INFO is a plist used as a communication
-channel.
-
-This function assumes TABLE has `org' as its `:type' attribute."
-  (let* ((attr (org-export-read-attribute :attr_groff table))
-        (label (org-element-property :name table))
-         (caption (and (not (plist-get attr :disable-caption))
-                      (org-groff--caption/label-string table info)))
-         (divider (if (plist-get attr :divider) "|" " "))
-
-         ;; Determine alignment string.
-         (alignment (org-groff-table--align-string divider table info))
-
-         ;; Extract others display options.
-
-         (lines (org-split-string contents "\n"))
-
-         (attr-list
-         (delq nil
-               (list (and (plist-get attr :expand) "expand")
-                     (let ((placement (plist-get attr :placement)))
-                       (cond ((string= placement 'center) "center")
-                             ((string= placement 'left) nil)
-                             (t (if org-groff-tables-centered "center" ""))))
-                     (or (plist-get attr :boxtype) "box"))))
-
-         (title-line  (plist-get attr :title-line))
-         (long-cells (plist-get attr :long-cells))
-
-         (table-format
-          (concat
-           (or (car attr-list) "")
-           (or
-            (let (output-list)
-             (when (cdr attr-list)
-               (dolist (attr-item (cdr attr-list))
-                  (setq output-list (concat output-list
-                                           (format ",%s" attr-item)))))
-              output-list) "")))
-         (first-line
-          (when lines (org-split-string (car lines) "\t"))))
-    ;; Prepare the final format string for the table.
-
-
-    (cond
-     ;; Others.
-     (lines
-      (concat ".TS\n " table-format ";\n"
-             (format "%s.\n"
-                     (let ((final-line ""))
-                       (when title-line
-                         (dotimes (i (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))
-                           (setq final-line (concat final-line "c" divider))))
-                       final-line))
-
-             (format "%s.TE\n"
-                     (let ((final-line "")
-                           (long-line "")
-                           (lines (org-split-string contents "\n")))
-
-                       (dolist (line-item lines)
-                         (setq long-line "")
-
-                         (if long-cells
-                             (progn
-                               (if (string= line-item "_")
-                                   (setq long-line (format "%s\n" line-item))
-                                 ;; else string =
-                                 (let ((cell-item-list (org-split-string 
line-item "\t")))
-                                   (dolist (cell-item cell-item-list)
-
-                                     (cond  ((eq cell-item (car (last 
cell-item-list)))
-                                             (setq long-line (concat long-line
-                                                                     (format 
"T{\n%s\nT}\t\n"  cell-item))))
-                                            (t
-                                             (setq long-line (concat long-line
-                                                                     (format 
"T{\n%s\nT}\t"  cell-item))))))
-                                   long-line))
-                               ;; else long cells
-                               (setq final-line (concat final-line long-line)))
-
-                           (setq final-line (concat final-line line-item 
"\n"))))
-                       final-line))
-
-             (if caption (format ".TB \"%s\"" caption) ""))))))
-
-;;; Table Cell
-
-(defun org-groff-table-cell (table-cell contents info)
-  "Transcode a TABLE-CELL element from Org to Groff
-CONTENTS is the cell contents.  INFO is a plist used as
-a communication channel."
-  (progn
-    (concat (if (and contents
-                     org-groff-table-scientific-notation
-                     (string-match orgtbl-exp-regexp contents))
-                ;; Use appropriate format string for scientific
-                ;; notation.
-                (format org-groff-table-scientific-notation
-                        (match-string 1 contents)
-                        (match-string 2 contents))
-              contents)
-            (when (org-export-get-next-element table-cell info) "\t"))))
-
-
-;;; Table Row
-
-(defun org-groff-table-row (table-row contents info)
-  "Transcode a TABLE-ROW element from Org to Groff
-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 (mapconcat 'identity
-                            (org-element-property
-                             :attr_groff (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)))
-      (concat
-       ;; Mark horizontal lines
-       (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_"))))))
-
-;;; Target
-
-(defun org-groff-target (target contents info)
-  "Transcode a TARGET object from Org to Groff.
-CONTENTS is nil.  INFO is a plist holding contextual
-information."
-  (format "\\fI%s\\fP" (org-export-get-reference target info)))
-
-;;; Timestamp
-
-(defun org-groff-timestamp (timestamp contents info)
-  "Transcode a TIMESTAMP object from Org to Groff.
-CONTENTS is nil.  INFO is a plist holding contextual
-information."
-  (let ((value (org-groff-plain-text
-               (org-timestamp-translate timestamp) info)))
-    (case (org-element-property :type timestamp)
-      ((active active-range)
-       (format org-groff-active-timestamp-format value))
-      ((inactive inactive-range)
-       (format org-groff-inactive-timestamp-format value))
-      (t (format org-groff-diary-timestamp-format value)))))
-
-;;; Underline
-
-(defun org-groff-underline (underline contents info)
-  "Transcode UNDERLINE from Org to Groff.
-CONTENTS is the text with underline markup.  INFO is a plist
-holding contextual information."
-  (org-groff--text-markup contents 'underline))
-
-;;; Verbatim
-
-(defun org-groff-verbatim (verbatim contents info)
-  "Transcode a VERBATIM object from Org to Groff.
-CONTENTS is nil.  INFO is a plist used as a communication
-channel."
-  (org-groff--text-markup (org-element-property :value verbatim) 'verbatim))
-
-;;; Verse Block
-
-(defun org-groff-verse-block (verse-block contents info)
-  "Transcode a VERSE-BLOCK element from Org to Groff.
-CONTENTS is verse block contents. INFO is a plist holding
-contextual information."
-  (format ".DS C\n.ft HI\n%s\n.ft\n.DE" contents))
-
-
-;;; Interactive functions
-
-(defun org-groff-export-to-groff
-  (&optional async subtreep visible-only body-only ext-plist)
-  "Export current buffer to a Groff file.
-
-If narrowing is active in the current buffer, only export its
-narrowed part.
-
-If a region is active, export that region.
-
-A non-nil optional argument ASYNC means the process should happen
-asynchronously.  The resulting file should be accessible through
-the `org-export-stack' interface.
-
-When optional argument SUBTREEP is non-nil, export the sub-tree
-at point, extracting information from the headline properties
-first.
-
-When optional argument VISIBLE-ONLY is non-nil, don't export
-contents of hidden elements.
-
-EXT-PLIST, when provided, is a property list with external
-parameters overriding Org default settings, but still inferior to
-file-local settings.
-
-Return output file's name."
-  (interactive)
-  (let ((outfile (org-export-output-file-name ".groff" subtreep))
-       (org-groff-registered-references nil)
-       (org-groff-special-content nil))
-    (org-export-to-file 'groff outfile
-      async subtreep visible-only body-only ext-plist)))
-
-(defun org-groff-export-to-pdf
-  (&optional async subtreep visible-only body-only ext-plist)
-  "Export current buffer to Groff then process through to PDF.
-
-If narrowing is active in the current buffer, only export its
-narrowed part.
-
-If a region is active, export that region.
-
-A non-nil optional argument ASYNC means the process should happen
-asynchronously.  The resulting file should be accessible through
-the `org-export-stack' interface.
-
-When optional argument SUBTREEP is non-nil, export the sub-tree
-at point, extracting information from the headline properties
-first.
-
-When optional argument VISIBLE-ONLY is non-nil, don't export
-contents of hidden elements.
-
-EXT-PLIST, when provided, is a property list with external
-parameters overriding Org default settings, but still inferior to
-file-local settings.
-
-Return PDF file's name."
-  (interactive)
-  (let ((outfile (org-export-output-file-name ".groff" subtreep)))
-    (org-export-to-file 'groff outfile
-      async subtreep visible-only body-only ext-plist
-      (lambda (file) (org-groff-compile file)))))
-
-(defun org-groff-compile (file)
-  "Compile a Groff file.
-
-FILE is the name of the file being compiled.  Processing is done
-through the command specified in `org-groff-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))
-        (time (current-time))
-        ;; Properly set working directory for compilation.
-        (default-directory (if (file-name-absolute-p file)
-                               (file-name-directory full-name)
-                             default-directory))
-         errors)
-    (message (format "Processing Groff file %s ..." file))
-    (save-window-excursion
-      (cond
-       ;; A function is provided: Apply it.
-       ((functionp org-groff-pdf-process)
-       (funcall org-groff-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-groff-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-groff-pdf-process)
-         ;; Collect standard errors from output buffer.
-         (setq errors (org-groff-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 (or (not (file-exists-p pdffile))
-               ;; Only compare times up to whole seconds as some
-               ;; filesystems (e.g. HFS+) do not retain any finer
-               ;; granularity.
-               (time-less-p (cl-subseq (nth 5 (file-attributes pdffile)) 0 2)
-                            (cl-subseq time 0 2)))
-           (error (concat (format "PDF file %s wasn't produced" pdffile)
-                          (when errors (concat ": " errors))))
-         ;; Else remove log files, when specified, and signal end of
-         ;; process to user, along with any error encountered.
-         (when org-groff-remove-logfiles
-           (dolist (ext org-groff-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-groff-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)))
-
-
-(provide 'ox-groff)
-;;; ox-groff.el ends here
diff --git a/contrib/lisp/ox-rss.el b/contrib/lisp/ox-rss.el
deleted file mode 100644
index 8e8e81a..0000000
--- a/contrib/lisp/ox-rss.el
+++ /dev/null
@@ -1,419 +0,0 @@
-;;; ox-rss.el --- RSS 2.0 Back-End for Org Export Engine
-
-;; Copyright (C) 2013-2015  Bastien Guerry
-
-;; Author: Bastien Guerry <bzg@gnu.org>
-;; Keywords: org, wp, blog, feed, rss
-
-;; This file is not yet 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:
-
-;; This library implements an RSS 2.0 back-end for Org exporter, based
-;; on the `html' back-end.
-;;
-;; It requires Emacs 24.1 at least.
-;;
-;; It provides two commands for export, depending on the desired output:
-;; `org-rss-export-as-rss' (temporary buffer) and `org-rss-export-to-rss'
-;; (as a ".xml" file).
-;;
-;; This backend understands three new option keywords:
-;;
-;; #+RSS_EXTENSION: xml
-;; #+RSS_IMAGE_URL: http://myblog.org/mypicture.jpg
-;; #+RSS_FEED_URL: http://myblog.org/feeds/blog.xml
-;;
-;; It uses #+HTML_LINK_HOME: to set the base url of the feed.
-;;
-;; Exporting an Org file to RSS modifies each top-level entry by adding a
-;; PUBDATE property.  If `org-rss-use-entry-url-as-guid', it will also add
-;; an ID property, later used as the guid for the feed's item.
-;;
-;; The top-level headline is used as the title of each RSS item unless
-;; an RSS_TITLE property is set on the headline.
-;;
-;; You typically want to use it within a publishing project like this:
-;;
-;; (add-to-list
-;;  'org-publish-project-alist
-;;  '("homepage_rss"
-;;    :base-directory "~/myhomepage/"
-;;    :base-extension "org"
-;;    :rss-image-url "http://lumiere.ens.fr/~guerry/images/faces/15.png";
-;;    :html-link-home "http://lumiere.ens.fr/~guerry/";
-;;    :html-link-use-abs-url t
-;;    :rss-extension "xml"
-;;    :publishing-directory "/home/guerry/public_html/"
-;;    :publishing-function (org-rss-publish-to-rss)
-;;    :section-numbers nil
-;;    :exclude ".*"            ;; To exclude all files...
-;;    :include ("index.org")   ;; ... except index.org.
-;;    :table-of-contents nil))
-;;
-;; ... then rsync /home/guerry/public_html/ with your server.
-;;
-;; By default, the permalink for a blog entry points to the headline.
-;; You can specify a different one by using the :RSS_PERMALINK:
-;; property within an entry.
-
-;;; Code:
-
-(require 'ox-html)
-(declare-function url-encode-url "url-util" (url))
-
-;;; Variables and options
-
-(defgroup org-export-rss nil
-  "Options specific to RSS export back-end."
-  :tag "Org RSS"
-  :group 'org-export
-  :version "24.4"
-  :package-version '(Org . "8.0"))
-
-(defcustom org-rss-image-url 
"https://orgmode.org/img/org-mode-unicorn-logo.png";
-  "The URL of the image for the RSS feed."
-  :group 'org-export-rss
-  :type 'string)
-
-(defcustom org-rss-extension "xml"
-  "File extension for the RSS 2.0 feed."
-  :group 'org-export-rss
-  :type 'string)
-
-(defcustom org-rss-categories 'from-tags
-  "Where to extract items category information from.
-The default is to extract categories from the tags of the
-headlines.  When set to another value, extract the category
-from the :CATEGORY: property of the entry."
-  :group 'org-export-rss
-  :type '(choice
-         (const :tag "From tags" from-tags)
-         (const :tag "From the category property" from-category)))
-
-(defcustom org-rss-use-entry-url-as-guid t
-  "Use the URL for the <guid> metatag?
-When nil, Org will create ids using `org-icalendar-create-uid'."
-  :group 'org-export-rss
-  :type 'boolean)
-
-;;; Define backend
-
-(org-export-define-derived-backend 'rss 'html
-  :menu-entry
-  '(?r "Export to RSS"
-       ((?R "As RSS buffer"
-           (lambda (a s v b) (org-rss-export-as-rss a s v)))
-       (?r "As RSS file" (lambda (a s v b) (org-rss-export-to-rss a s v)))
-       (?o "As RSS file and open"
-           (lambda (a s v b)
-             (if a (org-rss-export-to-rss t s v)
-               (org-open-file (org-rss-export-to-rss nil s v)))))))
-  :options-alist
-  '((:description "DESCRIPTION" nil nil newline)
-    (:keywords "KEYWORDS" nil nil space)
-    (:with-toc nil nil nil) ;; Never include HTML's toc
-    (:rss-extension "RSS_EXTENSION" nil org-rss-extension)
-    (:rss-image-url "RSS_IMAGE_URL" nil org-rss-image-url)
-    (:rss-feed-url "RSS_FEED_URL" nil nil t)
-    (:rss-categories nil nil org-rss-categories))
-  :filters-alist '((:filter-final-output . org-rss-final-function))
-  :translate-alist '((headline . org-rss-headline)
-                    (comment . (lambda (&rest args) ""))
-                    (comment-block . (lambda (&rest args) ""))
-                    (timestamp . (lambda (&rest args) ""))
-                    (plain-text . org-rss-plain-text)
-                    (section . org-rss-section)
-                    (template . org-rss-template)))
-
-;;; Export functions
-
-;;;###autoload
-(defun org-rss-export-as-rss (&optional async subtreep visible-only)
-  "Export current buffer to an RSS buffer.
-
-If narrowing is active in the current buffer, only export its
-narrowed part.
-
-If a region is active, export that region.
-
-A non-nil optional argument ASYNC means the process should happen
-asynchronously.  The resulting buffer should be accessible
-through the `org-export-stack' interface.
-
-When optional argument SUBTREEP is non-nil, export the sub-tree
-at point, extracting information from the headline properties
-first.
-
-When optional argument VISIBLE-ONLY is non-nil, don't export
-contents of hidden elements.
-
-Export is done in a buffer named \"*Org RSS Export*\", which will
-be displayed when `org-export-show-temporary-export-buffer' is
-non-nil."
-  (interactive)
-  (let ((file (buffer-file-name (buffer-base-buffer))))
-    (org-icalendar-create-uid file 'warn-user)
-    (org-rss-add-pubdate-property))
-  (org-export-to-buffer 'rss "*Org RSS Export*"
-    async subtreep visible-only nil nil (lambda () (text-mode))))
-
-;;;###autoload
-(defun org-rss-export-to-rss (&optional async subtreep visible-only)
-  "Export current buffer to an RSS file.
-
-If narrowing is active in the current buffer, only export its
-narrowed part.
-
-If a region is active, export that region.
-
-A non-nil optional argument ASYNC means the process should happen
-asynchronously.  The resulting file should be accessible through
-the `org-export-stack' interface.
-
-When optional argument SUBTREEP is non-nil, export the sub-tree
-at point, extracting information from the headline properties
-first.
-
-When optional argument VISIBLE-ONLY is non-nil, don't export
-contents of hidden elements.
-
-Return output file's name."
-  (interactive)
-  (let ((file (buffer-file-name (buffer-base-buffer))))
-    (org-icalendar-create-uid file 'warn-user)
-    (org-rss-add-pubdate-property))
-  (let ((outfile (org-export-output-file-name
-                 (concat "." org-rss-extension) subtreep)))
-    (org-export-to-file 'rss outfile async subtreep visible-only)))
-
-;;;###autoload
-(defun org-rss-publish-to-rss (plist filename pub-dir)
-  "Publish an org file to RSS.
-
-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."
-  (let ((bf (get-file-buffer filename)))
-    (if bf
-         (with-current-buffer bf
-           (org-icalendar-create-uid filename 'warn-user)
-           (org-rss-add-pubdate-property)
-           (write-file filename))
-      (find-file filename)
-      (org-icalendar-create-uid filename 'warn-user)
-      (org-rss-add-pubdate-property)
-      (write-file filename) (kill-buffer)))
-  (org-publish-org-to
-   'rss filename (concat "." org-rss-extension) plist pub-dir))
-
-;;; Main transcoding functions
-
-(defun org-rss-headline (headline contents info)
-  "Transcode HEADLINE element into RSS format.
-CONTENTS is the headline contents.  INFO is a plist used as a
-communication channel."
-  (if (> (org-export-get-relative-level headline info) 1)
-      (org-export-data-with-backend headline 'html info)
-    (unless (org-element-property :footnote-section-p headline)
-      (let* ((email (org-export-data (plist-get info :email) info))
-            (author (and (plist-get info :with-author)
-                         (let ((auth (plist-get info :author)))
-                           (and auth (org-export-data auth info)))))
-            (htmlext (plist-get info :html-extension))
-            (hl-number (org-export-get-headline-number headline info))
-            (hl-home (file-name-as-directory (plist-get info :html-link-home)))
-            (hl-pdir (plist-get info :publishing-directory))
-            (hl-perm (org-element-property :RSS_PERMALINK headline))
-            (anchor (org-export-get-reference headline info))
-            (category (org-rss-plain-text
-                       (or (org-element-property :CATEGORY headline) "") info))
-            (pubdate0 (org-element-property :PUBDATE headline))
-            (pubdate (let ((system-time-locale "C"))
-                       (if (and pubdate0 (not (string-empty-p pubdate0)))
-                           (format-time-string
-                            "%a, %d %b %Y %H:%M:%S %z"
-                            (org-time-string-to-time pubdate0)))))
-            (title (org-rss-plain-text
-                    (or (org-element-property :RSS_TITLE headline)
-                        (replace-regexp-in-string
-                         org-bracket-link-regexp
-                         (lambda (m) (or (match-string 3 m)
-                                         (match-string 1 m)))
-                         (org-element-property :raw-value headline))) info))
-            (publink
-             (or (and hl-perm (concat (or hl-home hl-pdir) hl-perm))
-                 (concat
-                  (or hl-home hl-pdir)
-                  (file-name-nondirectory
-                   (file-name-sans-extension
-                    (plist-get info :input-file))) "." htmlext "#" anchor)))
-            (guid (if org-rss-use-entry-url-as-guid
-                      publink
-                    (org-rss-plain-text
-                     (or (org-element-property :ID headline)
-                         (org-element-property :CUSTOM_ID headline)
-                         publink)
-                     info))))
-       (if (not pubdate) "" ;; Skip entries with no PUBDATE prop
-         (format
-          (concat
-           "<item>\n"
-           "<title>%s</title>\n"
-           "<link>%s</link>\n"
-           "<author>%s (%s)</author>\n"
-           "<guid isPermaLink=\"false\">%s</guid>\n"
-           "<pubDate>%s</pubDate>\n"
-           (org-rss-build-categories headline info) "\n"
-           "<description><![CDATA[%s]]></description>\n"
-           "</item>\n")
-          title publink email author guid pubdate contents))))))
-
-(defun org-rss-build-categories (headline info)
-  "Build categories for the RSS item."
-  (if (eq (plist-get info :rss-categories) 'from-tags)
-      (mapconcat
-       (lambda (c) (format "<category><![CDATA[%s]]></category>" c))
-       (org-element-property :tags headline)
-       "\n")
-    (let ((c (org-element-property :CATEGORY headline)))
-      (format "<category><![CDATA[%s]]></category>" c))))
-
-(defun org-rss-template (contents info)
-  "Return complete document string after RSS conversion.
-CONTENTS is the transcoded contents string.  INFO is a plist used
-as a communication channel."
-  (concat
-   (format "<?xml version=\"1.0\" encoding=\"%s\"?>"
-          (symbol-name org-html-coding-system))
-   "\n<rss version=\"2.0\"
-       xmlns:content=\"http://purl.org/rss/1.0/modules/content/\";
-       xmlns:wfw=\"http://wellformedweb.org/CommentAPI/\";
-       xmlns:dc=\"http://purl.org/dc/elements/1.1/\";
-       xmlns:atom=\"http://www.w3.org/2005/Atom\";
-       xmlns:sy=\"http://purl.org/rss/1.0/modules/syndication/\";
-       xmlns:slash=\"http://purl.org/rss/1.0/modules/slash/\";
-       xmlns:georss=\"http://www.georss.org/georss\";
-        xmlns:geo=\"http://www.w3.org/2003/01/geo/wgs84_pos#\";
-        xmlns:media=\"http://search.yahoo.com/mrss/\";>"
-   "<channel>"
-   (org-rss-build-channel-info info) "\n"
-   contents
-   "</channel>\n"
-   "</rss>"))
-
-(defun org-rss-build-channel-info (info)
-  "Build the RSS channel information."
-  (let* ((system-time-locale "C")
-        (title (org-export-data (plist-get info :title) info))
-        (email (org-export-data (plist-get info :email) info))
-        (author (and (plist-get info :with-author)
-                     (let ((auth (plist-get info :author)))
-                       (and auth (org-export-data auth info)))))
-        (date (format-time-string "%a, %d %b %Y %H:%M:%S %z")) ;; RFC 882
-        (description (org-export-data (plist-get info :description) info))
-        (lang (plist-get info :language))
-        (keywords (plist-get info :keywords))
-        (rssext (plist-get info :rss-extension))
-        (blogurl (or (plist-get info :html-link-home)
-                     (plist-get info :publishing-directory)))
-        (image (url-encode-url (plist-get info :rss-image-url)))
-        (ifile (plist-get info :input-file))
-        (publink
-         (or (plist-get info :rss-feed-url)
-             (concat (file-name-as-directory blogurl)
-                     (file-name-nondirectory
-                      (file-name-sans-extension ifile))
-                     "." rssext))))
-    (format
-     "\n<title>%s</title>
-<atom:link href=\"%s\" rel=\"self\" type=\"application/rss+xml\" />
-<link>%s</link>
-<description><![CDATA[%s]]></description>
-<language>%s</language>
-<pubDate>%s</pubDate>
-<lastBuildDate>%s</lastBuildDate>
-<generator>%s</generator>
-<webMaster>%s (%s)</webMaster>
-<image>
-<url>%s</url>
-<title>%s</title>
-<link>%s</link>
-</image>
-"
-     title publink blogurl description lang date date
-     (concat (format "Emacs %d.%d"
-                    emacs-major-version
-                    emacs-minor-version)
-            " Org-mode " (org-version))
-     email author image title blogurl)))
-
-(defun org-rss-section (section contents info)
-  "Transcode SECTION element into RSS format.
-CONTENTS is the section contents.  INFO is a plist used as
-a communication channel."
-  contents)
-
-(defun org-rss-timestamp (timestamp contents info)
-  "Transcode a TIMESTAMP object from Org to RSS.
-CONTENTS is nil.  INFO is a plist holding contextual
-information."
-  (org-html-encode-plain-text
-   (org-timestamp-translate timestamp)))
-
-(defun org-rss-plain-text (contents info)
-  "Convert plain text into RSS encoded text."
-  (let (output)
-    (setq output (org-html-encode-plain-text contents)
-         output (org-export-activate-smart-quotes
-                 output :html info))))
-
-;;; Filters
-
-(defun org-rss-final-function (contents backend info)
-  "Prettify the RSS output."
-  (with-temp-buffer
-    (xml-mode)
-    (insert contents)
-    (indent-region (point-min) (point-max))
-    (buffer-substring-no-properties (point-min) (point-max))))
-
-;;; Miscellaneous
-
-(defun org-rss-add-pubdate-property ()
-  "Set the PUBDATE property for top-level headlines."
-  (let (msg)
-    (org-map-entries
-     (lambda ()
-       (let* ((entry (org-element-at-point))
-             (level (org-element-property :level entry)))
-        (when (= level 1)
-          (unless (org-entry-get (point) "PUBDATE")
-            (setq msg t)
-            (org-set-property
-             "PUBDATE" (format-time-string
-                        (cdr org-time-stamp-formats)))))))
-     nil nil 'comment 'archive)
-    (when msg
-      (message "Property PUBDATE added to top-level entries in %s"
-              (buffer-file-name))
-      (sit-for 2))))
-
-(provide 'ox-rss)
-
-;;; ox-rss.el ends here
diff --git a/contrib/lisp/ox-s5.el b/contrib/lisp/ox-s5.el
deleted file mode 100644
index 2433325..0000000
--- a/contrib/lisp/ox-s5.el
+++ /dev/null
@@ -1,433 +0,0 @@
-;;; ox-s5.el --- S5 Presentation Back-End for Org Export Engine
-
-;; Copyright (C) 2011-2014  Rick Frankel
-
-;; Author: Rick Frankel <emacs at rickster dot com>
-;; Keywords: outlines, hypermedia, S5, wp
-
-;; This file is not 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 this program.  If not, see <http://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; This library implements an S5 Presentation back-end for the Org
-;; generic exporter.
-
-;; Installation
-;; ------------
-;; Get the s5 scripts from
-;;    http://meyerweb.com/eric/tools/s5/
-;; (Note that the default s5 version is set for using the alpha, 1.2a2.
-;; Copy the ui dir to somewhere reachable from your published presentation
-;; The default (`org-s5-ui-url') is set to "ui" (e.g., in the
-;; same directory as the html file).
-
-;; Usage
-;; -----
-;; Follow the general instructions at the above website. To generate
-;; incremental builds, you can set the HTML_CONTAINER_CLASS on an
-;; object to "incremental" to make it build. If you want an outline to
-;; build, set the :INCREMENTAL property on the parent headline.
-
-;; To test it, run:
-;;
-;;   M-x org-s5-export-as-html
-;;
-;; in an Org mode buffer.  See ox.el and ox-html.el for more details
-;; on how this exporter works.
-
-;; TODOs
-;; ------
-;; The title page is formatted using format-spec.  This is error prone
-;; when details are missing and may insert empty tags, like <h2></h2>,
-;; for missing values.
-
-(require 'ox-html)
-(eval-when-compile (require 'cl))
-
-(org-export-define-derived-backend 's5 'html
-  :menu-entry
-  '(?s "Export to S5 HTML Presentation"
-       ((?H "To temporary buffer" org-s5-export-as-html)
-       (?h "To file" org-s5-export-to-html)
-       (?o "To file and open"
-           (lambda (a s v b)
-             (if a (org-s5-export-to-html t s v b)
-               (org-open-file (org-s5-export-to-html nil s v b)))))))
-  :options-alist
-  '((:html-link-home "HTML_LINK_HOME" nil nil)
-    (:html-link-up "HTML_LINK_UP" nil nil)
-    (:s5-postamble "S5_POSTAMBLE" nil org-s5-postamble newline)
-    (:s5-preamble "S5_PREAMBLE" nil org-s5-preamble newline)
-    (:html-head-include-default-style "HTML_INCLUDE_DEFAULT_STYLE" nil nil)
-    (:html-head-include-scripts "HTML_INCLUDE_SCRIPTS" nil nil)
-    (:s5-version "S5_VERSION" nil org-s5-version)
-    (:s5-theme-file "S5_THEME_FILE" nil org-s5-theme-file)
-    (:s5-ui-url "S5_UI_URL" nil org-s5-ui-url)
-    (:s5-default-view "S5_DEFAULT_VIEW" nil org-s5-default-view)
-    (:s5-control-visibility "S5_CONTROL_VISIBILITY" nil
-                           org-s5-control-visibility))
-  :translate-alist
-  '((headline . org-s5-headline)
-    (plain-list . org-s5-plain-list)
-    (inner-template . org-s5-inner-template)
-    (template . org-s5-template)))
-
-(defgroup org-export-s5 nil
-  "Options for exporting Org mode files to S5 HTML Presentations."
-  :tag "Org Export S5"
-  :group 'org-export-html)
-
-(defcustom org-s5-version "1.2a2"
-  "Version of s5 being used (for version metadata.) Defaults to
-s5 v2 alpha 2.
-Can be overridden with S5_VERSION."
-  :group 'org-export-s5
-  :type 'string)
-
-(defcustom org-s5-theme-file nil
-"Url to S5 theme (slides.css) file. Can be overridden with the
-S5_THEME_FILE property. If nil, defaults to
-`org-s5-ui-url'/default/slides.css. If it starts with anything but
-\"http\" or \"/\", it is used as-is. Otherwise the link in generated
-relative to `org-s5-ui-url'.
-The links for all other required stylesheets and scripts will be
-generated relative to `org-s5-ui-url'/default."
-  :group 'org-export-s5
-  :type 'string)
-
-(defcustom org-s5-ui-url "ui"
-  "Base url to directory containing S5 \"default\" subdirectory
-and the \"s5-notes.html\" file.
-Can be overridden with the S5_UI_URL property."
-  :group 'org-export-s5
-  :type 'string)
-
-(defcustom org-s5-default-view 'slideshow
-  "Setting for \"defaultView\" meta info."
-  :group 'org-export-s5
-  :type '(choice (const slideshow) (const outline)))
-
-(defcustom org-s5-control-visibility 'hidden
-  "Setting for \"controlVis\" meta info."
-  :group 'org-export-s5
-  :type '(choice (const hidden) (const visibile)))
-
-(defvar org-s5--divs
-  '((preamble  "div" "header")
-    (content   "div" "content")
-    (postamble "div" "footer"))
-  "Alist of the three section elements for HTML export.
-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.
-
-If you set `org-html-container-element' to \"li\", \"ol\" will be
-uses as the content ELEMENT_TYPE, generating an XOXO format
-slideshow.
-
-Note that changing the preamble or postamble will break the
-core S5 stylesheets.")
-
-(defcustom org-s5-postamble "<h1>%a - %t</h1>"
-  "Preamble inserted into the S5 layout section.
-When set to a string, use this string as the postamble.
-
-When set to a function, apply this function and insert the
-returned string.  The function takes the property list of export
-options as its only argument.
-
-Setting the S5_POSTAMBLE option -- or the :s5-postamble in publishing
-projects -- will take precedence over this variable.
-
-Note that the default css styling will break if this is set to nil
-or an empty string."
-  :group 'org-export-s5
-  :type '(choice (const :tag "No postamble" "&#x20;")
-                (string :tag "Custom formatting string")
-                (function :tag "Function (must return a string)")))
-
-(defcustom org-s5-preamble "&#x20;"
-  "Peamble inserted into the S5 layout section.
-
-When set to a string, use this string as the preamble.
-
-When set to a function, apply this function and insert the
-returned string.  The function takes the property list of export
-options as its only argument.
-
-Setting S5_PREAMBLE option -- or the :s5-preamble in publishing
-projects -- will take precedence over this variable.
-
-Note that the default css styling will break if this is set to nil
-or an empty string."
-  :group 'org-export-s5
-  :type '(choice (const :tag "No preamble" "&#x20;")
-                (string :tag "Custom formatting string")
-                (function :tag "Function (must return a string)")))
-
-(defcustom org-s5-title-slide-template
-  "<h1>%t</h1>
-<h2>%s</h2>
-<h2>%a</h2>
-<h3>%e</h3>
-<h4>%d</h4>"
-  "Format template to specify title page section.
-See `org-html-postamble-format' for the valid elements which
-can be included.
-
-It will be wrapped in the element defined in the :html-container
-property, and defaults to the value of `org-html-container-element',
-and have the id \"title-slide\"."
-  :group 'org-export-s5
-  :type 'string)
-
-(defun org-s5--format-toc-headline (headline info)
-  "Return an appropriate table of contents entry for HEADLINE.
-Note that (currently) the S5 exporter does not support deep links,
-so the table of contents is not \"active\".
-INFO is a plist used as a communication channel."
-  (let* ((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)
-               (concat (mapconcat 'number-to-string headline-number ".") ". 
")))
-         (tags (and (eq (plist-get info :with-tags) t)
-                    (org-export-get-tags headline info))))
-    (concat section-number
-            (org-export-data
-             (org-export-get-alt-title headline info) info)
-            (and tags "&nbsp;&nbsp;&nbsp;") (org-html--tags tags info))))
-
-(defun org-s5-toc (depth info)
-  (let* ((headlines (org-export-collect-headlines info depth))
-         (toc-entries
-          (mapcar (lambda (headline)
-                    (cons (org-s5--format-toc-headline headline info)
-                          (org-export-get-relative-level headline info)))
-                  (org-export-collect-headlines info depth))))
-    (when toc-entries
-      (concat
-       (format "<%s id='table-of-contents' class='slide'>\n"
-               (plist-get info :html-container))
-       (format "<h1>%s</h1>\n"
-               (org-html--translate "Table of Contents" info))
-       "<div id=\"text-table-of-contents\">"
-       (org-html--toc-text toc-entries)
-       "</div>\n"
-       (format "</%s>\n" (plist-get info :html-container))))))
-
-(defun org-s5--build-head (info)
-  (let* ((dir (plist-get info :s5-ui-url))
-         (theme (or (plist-get info :s5-theme-file) "default/slides.css")))
-    (mapconcat
-     'identity
-     (list
-      "<!-- style sheet links -->"
-      (mapconcat
-       (lambda (list)
-         (format
-          (concat
-           "<link rel='stylesheet' href='%s/default/%s' type='text/css'"
-           " media='%s' id='%s' />")
-          dir (nth 0 list) (nth 1 list) (nth 2 list)))
-       (list
-        '("outline.css" "screen" "outlineStyle")
-        '("print.css" "print" "slidePrint")
-        '("opera.css" "projection" "operaFix")) "\n")
-      (format (concat
-               "<link rel='stylesheet' href='%s' type='text/css'"
-               " media='screen' id='slideProj' />")
-              (if (string-match-p "^\\(http\\|/\\)" theme) theme
-                (concat dir "/" theme)))
-      "<!-- S5 JS -->"
-      (concat
-       "<script src='" dir
-       "/default/slides.js' type='text/javascript'></script>")) "\n")))
-
-(defun org-s5--build-meta-info (info)
-  (concat
-   (org-html--build-meta-info info)
-   (format "<meta name=\"version\" content=\"S5 %s\" />\n"
-           (plist-get info :s5-version))
-   (format "<meta name='defaultView' content='%s' />\n"
-           (plist-get info :s5-default-view))
-   (format "<meta name='controlVis' content='%s' />"
-           (plist-get info :s5-control-visibility))))
-
-(defun org-s5-headline (headline contents info)
-  (let ((org-html-toplevel-hlevel 1)
-        (class (or (org-element-property :HTML_CONTAINER_CLASS headline) ""))
-        (level (org-export-get-relative-level headline info)))
-    (when (and (= 1 level) (not (string-match-p "\\<slide\\>" class)))
-      (org-element-put-property headline :HTML_CONTAINER_CLASS (concat class " 
slide")))
-    (org-html-headline headline contents info)))
-
-(defun org-s5-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.
-If a containing headline has the property :INCREMENTAL,
-then the \"incremental\" class will be added to the to the list,
-which will make the list into a \"build\"."
-  (let* ((type (org-element-property :type plain-list))
-        (tag (case type
-               (ordered "ol")
-               (unordered "ul")
-               (descriptive "dl"))))
-    (format "%s\n%s%s"
-            (format
-             "<%s class='org-%s%s'>" tag tag
-             (if (org-export-get-node-property :INCREMENTAL plain-list t)
-                 " incremental" ""))
-            contents
-           (format "</%s>" tag))))
-
-(defun org-s5-inner-template (contents info)
-  "Return body of document string after HTML conversion.
-CONTENTS is the transcoded contents string.  INFO is a plist
-holding export options."
-  (concat contents "\n"))
-
-(defun org-s5-template (contents info)
-  "Return complete document string after HTML conversion.
-CONTENTS is the transcoded contents string.  INFO is a plist
-holding export options."
-  (let ((info (plist-put
-              (plist-put
-               (plist-put info :html-preamble (plist-get info :s5-preamble))
-               :html-postamble
-               (plist-get info :s5-postamble))
-              :html-divs
-              (if (equal "li" (plist-get info :html-container))
-                  (cons '(content "ol" "content") org-s5--divs)
-                org-s5--divs))))
-    (mapconcat
-     'identity
-     (list
-      (org-html-doctype info)
-      (format "<html xmlns=\"http://www.w3.org/1999/xhtml\"; lang=\"%s\" 
xml:lang=\"%s\">"
-             (plist-get info :language) (plist-get info :language))
-      "<head>"
-      (org-s5--build-meta-info info)
-      (org-s5--build-head info)
-      (org-html--build-head info)
-      (org-html--build-mathjax-config info)
-      "</head>"
-      "<body>"
-      "<div class=\"layout\">"
-      "<div id=\"controls\"><!-- no edit --></div>"
-      "<div id=\"currentSlide\"><!-- no edit --></div>"
-      (org-html--build-pre/postamble 'preamble info)
-      (org-html--build-pre/postamble 'postamble info)
-      "</div>"
-      (format "<%s id=\"%s\" class=\"presentation\">"
-             (nth 1 (assq 'content org-html-divs))
-             (nth 2 (assq 'content org-html-divs)))
-      ;; title page
-      (format "<%s id='title-slide' class='slide'>"
-             (plist-get info :html-container))
-      (format-spec org-s5-title-slide-template (org-html-format-spec info))
-      (format "</%s>" (plist-get info :html-container))
-      ;; table of contents.
-      (let ((depth (plist-get info :with-toc)))
-       (when depth (org-s5-toc depth info)))
-      contents
-      (format "</%s>" (nth 1 (assq 'content org-html-divs)))
-      "</body>"
-      "</html>\n") "\n")))
-
-(defun org-s5-export-as-html
-  (&optional async subtreep visible-only body-only ext-plist)
-  "Export current buffer to an HTML buffer.
-
-If narrowing is active in the current buffer, only export its
-narrowed part.
-
-If a region is active, export that region.
-
-A non-nil optional argument ASYNC means the process should happen
-asynchronously.  The resulting buffer should be accessible
-through the `org-export-stack' interface.
-
-When optional argument SUBTREEP is non-nil, export the sub-tree
-at point, extracting information from the headline properties
-first.
-
-When optional argument VISIBLE-ONLY is non-nil, don't export
-contents of hidden elements.
-
-When optional argument BODY-ONLY is non-nil, only write code
-between \"<body>\" and \"</body>\" tags.
-
-EXT-PLIST, when provided, is a property list with external
-parameters overriding Org default settings, but still inferior to
-file-local settings.
-
-Export is done in a buffer named \"*Org S5 Export*\", which
-will be displayed when `org-export-show-temporary-export-buffer'
-is non-nil."
-  (interactive)
-  (org-export-to-buffer 's5 "*Org S5 Export*"
-    async subtreep visible-only body-only ext-plist (lambda () (nxml-mode))))
-
-(defun org-s5-export-to-html
-  (&optional async subtreep visible-only body-only ext-plist)
-  "Export current buffer to a S5 HTML file.
-
-If narrowing is active in the current buffer, only export its
-narrowed part.
-
-If a region is active, export that region.
-
-A non-nil optional argument ASYNC means the process should happen
-asynchronously.  The resulting file should be accessible through
-the `org-export-stack' interface.
-
-When optional argument SUBTREEP is non-nil, export the sub-tree
-at point, extracting information from the headline properties
-first.
-
-When optional argument VISIBLE-ONLY is non-nil, don't export
-contents of hidden elements.
-
-When optional argument BODY-ONLY is non-nil, only write code
-between \"<body>\" and \"</body>\" tags.
-
-EXT-PLIST, when provided, is a property list with external
-parameters overriding Org default settings, but still inferior to
-file-local settings.
-
-Return output file's name."
-  (interactive)
-  (let* ((extension (concat "." org-html-extension))
-         (file (org-export-output-file-name extension subtreep))
-         (org-export-coding-system org-html-coding-system))
-    (org-export-to-file 's5 file
-      async subtreep visible-only body-only ext-plist)))
-
-(defun org-s5-publish-to-html (plist filename pub-dir)
-  "Publish an org file to S5 HTML Presentation.
-
-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 's5 filename ".html" plist pub-dir))
-
-(provide 'ox-s5)
-
-;;; ox-s5.el ends here
diff --git a/contrib/lisp/ox-taskjuggler.el b/contrib/lisp/ox-taskjuggler.el
deleted file mode 100644
index f405290..0000000
--- a/contrib/lisp/ox-taskjuggler.el
+++ /dev/null
@@ -1,1034 +0,0 @@
-;;; ox-taskjuggler.el --- TaskJuggler Back-End for Org Export Engine
-;;
-;; Copyright (C) 2007-2021 Free Software Foundation, Inc.
-;;
-;; Emacs Lisp Archive Entry
-;; Filename: ox-taskjuggler.el
-;; Author: Christian Egli
-;;      Nicolas Goaziou <n dot goaziou at gmail dot com>
-;; Maintainer: Christian Egli
-;; Keywords: org, taskjuggler, project planning
-;; Description: Converts an Org mode buffer into a TaskJuggler project plan
-
-;; This file is not 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 this program.  If not, see <http://www.gnu.org/licenses/>.
-
-;;; Commentary:
-;;
-;; This library implements a TaskJuggler exporter for Org mode.
-;; TaskJuggler is a project planing tool that uses a text format to
-;; define projects, tasks and resources, so it is a natural fit for
-;; Org mode.  It can produce all sorts of reports for tasks or
-;; resources in either HTML, CSV or PDF.  TaskJuggler is implemented
-;; in Ruby and should therefore run on any platform.
-;;
-;; The exporter does not export all the nodes of a document or
-;; strictly follow the order of the nodes in the document.
-;;
-;; Instead the TaskJuggler exporter looks for a tree that defines the
-;; tasks and a optionally tree that defines the resources for this
-;; project.  It then creates a TaskJuggler file based on these trees
-;; and the attributes defined in all the nodes.
-;;
-;; * Installation
-;;
-;; Put this file into your load-path and the following line into your
-;; ~/.emacs:
-;;
-;;   (add-to-list 'org-export-backends 'taskjuggler)
-;;
-;; or customize `org-export-backends' variable.
-;;
-;; The interactive functions are the following:
-;;
-;; M-x `org-taskjuggler-export'
-;; M-x `org-taskjuggler-export-and-open'
-;;
-;; * Tasks
-;;
-;; Let's illustrate the usage with a small example.  Create your tasks
-;; as you usually do with org-mode.  Assign efforts to each task using
-;; properties (it's easiest to do this in the column view).  You
-;; should end up with something similar to the example by Peter Jones
-;; in:
-;;
-;;   
http://www.devalot.com/assets/articles/2008/07/project-planning/project-planning.org.
-;;
-;; Now mark the top node of your tasks with a tag named
-;; "taskjuggler_project" (or whatever you customized
-;; `org-taskjuggler-project-tag' to).  You are now ready to export the
-;; project plan with `org-taskjuggler-export-and-open' which will
-;; export the project plan and open a Gantt chart in TaskJugglerUI.
-;;
-;; * Resources
-;;
-;; Next you can define resources and assign those to work on specific
-;; tasks.  You can group your resources hierarchically.  Tag the top
-;; node of the resources with "taskjuggler_resource" (or whatever you
-;; customized `org-taskjuggler-resource-tag' to).  You can optionally
-;; assign an identifier (named "resource_id") to the resources (using
-;; the standard org properties commands) or you can let the exporter
-;; generate identifiers automatically (the exporter picks the first
-;; word of the headline as the identifier as long as it is unique, see
-;; the documentation of `org-taskjuggler--build-unique-id').  Using that
-;; identifier you can then allocate resources to tasks.  This is again
-;; done with the "allocate" property on the tasks.  Do this in column
-;; view or when on the task type
-;;
-;;  C-c C-x p allocate RET <resource_id> RET
-;;
-;; Once the allocations are done you can again export to TaskJuggler
-;; and check in the Resource Allocation Graph which person is working
-;; on what task at what time.
-;;
-;; * Export of properties
-;;
-;; The exporter also takes TODO state information into consideration,
-;; i.e. if a task is marked as done it will have the corresponding
-;; attribute in TaskJuggler ("complete 100").  Also it will export any
-;; property on a task resource or resource node which is known to
-;; TaskJuggler, such as limits, vacation, shift, booking, efficiency,
-;; journalentry, rate for resources or account, start, note, duration,
-;; end, journalentry, milestone, reference, responsible, scheduling,
-;; etc for tasks.
-;;
-;; * Dependencies
-;;
-;; The exporter will handle dependencies that are defined in the tasks
-;; either with the ORDERED attribute (see TODO dependencies in the Org
-;; mode manual) or with the BLOCKER attribute (see org-depend.el) or
-;; alternatively with a depends attribute.  Both the BLOCKER and the
-;; depends attribute can be either "previous-sibling" or a reference
-;; to an identifier (named "task_id") which is defined for another
-;; task in the project.  BLOCKER and the depends attribute can define
-;; multiple dependencies separated by either space or comma.  You can
-;; also specify optional attributes on the dependency by simply
-;; appending it.  The following examples should illustrate this:
-;;
-;; * Training material
-;;   :PROPERTIES:
-;;   :task_id:  training_material
-;;   :ORDERED:  t
-;;   :END:
-;; ** Markup Guidelines
-;;    :PROPERTIES:
-;;    :Effort:   2d
-;;    :END:
-;; ** Workflow Guidelines
-;;    :PROPERTIES:
-;;    :Effort:   2d
-;;    :END:
-;; * Presentation
-;;   :PROPERTIES:
-;;   :Effort:   2d
-;;   :BLOCKER:  training_material { gapduration 1d } some_other_task
-;;   :END:
-;;
-;;;; * TODO
-;;   - Look at org-keyword-properties, org-global-properties and
-;;     org-global-properties-fixed
-;;   - What about property inheritance and org-property-inherit-p?
-;;   - Use TYPE_TODO as an way to assign resources
-;;   - Add support for org-export-with-planning
-;;
-;;; Code:
-
-(eval-when-compile (require 'cl))
-
-(require 'ox)
-
-
-
-;;; User Variables
-
-(defgroup org-export-taskjuggler nil
-  "Options specific for TaskJuggler export back-end."
-  :tag "Org Export TaskJuggler"
-  :group 'org-export)
-
-(defcustom org-taskjuggler-extension ".tjp"
-  "Extension of TaskJuggler files."
-  :group 'org-export-taskjuggler
-  :type 'string)
-
-(defcustom org-taskjuggler-project-tag "taskjuggler_project"
-  "Tag marking project's tasks.
-This tag is used to find the tree containing all the tasks for
-the project."
-  :group 'org-export-taskjuggler
-  :type 'string)
-
-(defcustom org-taskjuggler-resource-tag "taskjuggler_resource"
-  "Tag marking project's resources.
-This tag is used to find the tree containing all the resources
-for the project."
-  :group 'org-export-taskjuggler
-  :type 'string)
-
-(defcustom org-taskjuggler-report-tag "taskjuggler_report"
-  "Tag marking project's reports.
-This tag is used to find the tree containing all the reports for
-the project."
-  :group 'org-export-taskjuggler
-  :type 'string)
-
-(defcustom org-taskjuggler-target-version 3.0
-  "Which version of TaskJuggler the exporter is targeting.
-By default a project plan is exported which conforms to version
-3.x of TaskJuggler.  For a project plan that is compatible with
-versions of TaskJuggler older than 3.0 set this to 2.4.
-
-If you change this variable be sure to also change
-`org-taskjuggler-default-reports' as the format of reports has
-changed considerably between version 2.x and 3.x of TaskJuggler"
-  :group 'org-export-taskjuggler
-  :type 'number)
-
-(defcustom org-taskjuggler-default-project-version "1.0"
-  "Default version string for the project.
-This value can also be set with the \":VERSION:\" property
-associated to the headline defining the project."
-  :group 'org-export-taskjuggler
-  :type 'string)
-
-(defcustom org-taskjuggler-default-project-duration 280
-  "Default project duration.
-The value will be used if no start and end date have been defined
-in the root node of the task tree, i.e. the tree that has been
-marked with `org-taskjuggler-project-tag'"
-  :group 'org-export-taskjuggler
-  :type 'integer)
-
-(defcustom org-taskjuggler-default-reports
-  '("textreport report \"Plan\" {
-  formats html
-  header '== %title =='
-
-  center -8<-
-    [#Plan Plan] | [#Resource_Allocation Resource Allocation]
-    ----
-    === Plan ===
-    <[report id=\"plan\"]>
-    ----
-    === Resource Allocation ===
-    <[report id=\"resourceGraph\"]>
-  ->8-
-}
-
-# A traditional Gantt chart with a project overview.
-taskreport plan \"\" {
-  headline \"Project Plan\"
-  columns bsi, name, start, end, effort, chart
-  loadunit shortauto
-  hideresource 1
-}
-
-# A graph showing resource allocation. It identifies whether each
-# resource is under- or over-allocated for.
-resourcereport resourceGraph \"\" {
-  headline \"Resource Allocation Graph\"
-  columns no, name, effort, weekly
-  loadunit shortauto
-  hidetask ~(isleaf() & isleaf_())
-  sorttasks plan.start.up
-}")
-  "Default reports for the project.
-These are sensible default reports to give a good out-of-the-box
-result when exporting without defining any reports.  \"%title\"
-anywhere in the reports will be replaced with the document title.
-If you want to define your own reports you can change them here
-or simply define the default reports so that they include an
-external report definition as follows:
-
-include reports.tji
-
-These default are made to work with tj3.  If you are targeting
-TaskJuggler 2.4 (see `org-taskjuggler-target-version') please
-change these defaults to something like the following:
-
-taskreport \"Gantt Chart\" {
-  headline \"Project Gantt Chart\"
-  columns hierarchindex, name, start, end, effort, duration, completed, chart
-  timeformat \"%Y-%m-%d\"
-  hideresource 1
-  loadunit shortauto
-}
-
-resourcereport \"Resource Graph\" {
-  headline \"Resource Allocation Graph\"
-  columns no, name, utilization, freeload, chart
-  loadunit shortauto
-  sorttasks startup
-  hidetask ~isleaf()
-}"
-  :group 'org-export-taskjuggler
-  :type '(repeat (string :tag "Report")))
-
-(defcustom org-taskjuggler-default-global-header ""
-  "Default global header for the project.
-This goes before project declaration, and might be useful for
-early macros."
-  :group 'org-export-taskjuggler
-  :type '(string :tag "Preamble"))
-
-(defcustom org-taskjuggler-default-global-properties
-  "shift s40 \"Part time shift\" {
-  workinghours wed, thu, fri off
-}
-"
-  "Default global properties for the project.
-
-Here you typically define global properties such as shifts,
-accounts, rates, vacation, macros and flags.  Any property that
-is allowed within the TaskJuggler file can be inserted.  You
-could for example include another TaskJuggler file.
-
-The global properties are inserted after the project declaration
-but before any resource and task declarations."
-  :group 'org-export-taskjuggler
-  :type '(string :tag "Preamble"))
-
-(defcustom org-taskjuggler-valid-task-attributes
-  '(account start note duration endbuffer endcredit end
-           flags journalentry length limits maxend maxstart minend
-           minstart period reference responsible scheduling
-           startbuffer startcredit statusnote chargeset charge)
-  "Valid attributes for Taskjuggler tasks.
-If one of these appears as a property for a headline, it will be
-exported with the corresponding task.
-
-Note that multiline properties are not supported, so attributes
-like note or journalentry have to be on a single line."
-  :group 'org-export-taskjuggler)
-
-(defcustom org-taskjuggler-valid-project-attributes
-  '(timingresolution timezone alertlevels currency currencyformat
-  dailyworkinghours extend includejournalentry now numberformat
-  outputdir scenario shorttimeformat timeformat trackingscenario
-  weekstartsmonday weekstartssunday workinghours
-  yearlyworkingdays)
-  "Valid attributes for Taskjuggler project.
-If one of these appears as a property for a headline that is a
-project definition, it will be exported with the corresponding
-task. Attribute 'timingresolution' should be the first in the
-list."
-  :group 'org-export-taskjuggler)
-
-(defcustom org-taskjuggler-valid-resource-attributes
-  '(limits vacation shift booking efficiency journalentry rate
-          workinghours flags)
-  "Valid attributes for Taskjuggler resources.
-If one of these appears as a property for a headline, it will be
-exported with the corresponding resource."
-  :group 'org-export-taskjuggler)
-
-(defcustom org-taskjuggler-valid-report-attributes
-  '(headline columns definitions timeformat hideresource hidetask
-            loadunit sorttasks formats period)
-  "Valid attributes for Taskjuggler reports.
-If one of these appears as a property for a headline, it will be
-exported with the corresponding report."
-  :group 'org-export-taskjuggler)
-
-(defcustom org-taskjuggler-process-command
-  "tj3 --silent --no-color --output-dir %o %f"
-  "Command to process a Taskjuggler file.
-The command will be given to the shell as a command to process a
-Taskjuggler file.  \"%f\" in the command will be replaced by the
-full file name, \"%o\" by the reports directory (see
-`org-taskjuggler-reports-directory').
-
-If you are targeting Taskjuggler 2.4 (see
-`org-taskjuggler-target-version') this setting is ignored."
-  :group 'org-export-taskjuggler)
-
-(defcustom org-taskjuggler-reports-directory "reports"
-  "Default directory to generate the Taskjuggler reports in.
-The command `org-taskjuggler-process-command' generates the
-reports and associated files such as CSS inside this directory.
-
-If the directory is not an absolute path it is relative to the
-directory of the exported file.  The directory is created if it
-doesn't exist.
-
-If you are targeting Taskjuggler 2.4 (see
-`org-taskjuggler-target-version') this setting is ignored."
-  :group 'org-export-taskjuggler)
-
-(defcustom org-taskjuggler-keep-project-as-task t
-  "Non-nil keeps the project headline as an umbrella task for all tasks.
-Setting this to nil will allow maintaining completely separated
-task buckets, while still sharing the same resources pool."
-  :group 'org-export-taskjuggler
-  :type 'boolean)
-
-
-
-;;; Hooks
-
-(defvar org-taskjuggler-final-hook nil
-  "Hook run after a TaskJuggler files has been saved.
-This hook is run with the name of the file as argument.")
-
-
-
-;;; Back-End Definition
-
-(org-export-define-backend 'taskjuggler
-  '((template . org-taskjuggler-project-plan))
-  :menu-entry
-  '(?J "Export to TaskJuggler"
-       ((?j "As TJP file" (lambda (a s v b) (org-taskjuggler-export a s v)))
-       (?p "As TJP file and process"
-           (lambda (a s v b)
-             (if a (org-taskjuggler-export a s v)
-               (org-taskjuggler-export-and-process s v))))
-       (?o "As TJP file, process and open"
-           (lambda (a s v b)
-             (if a (org-taskjuggler-export a s v)
-               (org-taskjuggler-export-process-and-open s v))))))
-  ;; This property will be used to store unique ids in communication
-  ;; channel.  Ids will be retrieved with `org-taskjuggler-get-id'.
-  :options-alist '((:taskjuggler-unique-ids nil nil nil)))
-
-
-
-;;; Unique IDs
-
-(defun org-taskjuggler-assign-task-ids (tasks info)
-  "Assign a unique ID to each task in TASKS.
-TASKS is a list of headlines.  INFO is a plist used as a
-communication channel.  Return value is an alist between
-headlines and their associated ID.  IDs are hierarchical, which
-means they only need to be unique among the task siblings."
-  (let* (alist
-        build-id                       ; For byte-compiler.
-         (build-id
-          (lambda (tasks local-ids)
-            (org-element-map tasks 'headline
-              (lambda (task)
-                (let ((id (org-taskjuggler--build-unique-id task local-ids)))
-                  (push id local-ids)
-                  (push (cons task id) alist)
-                  (funcall build-id (org-element-contents task) nil)))
-              info nil 'headline))))
-    (funcall build-id tasks nil)
-    alist))
-
-(defun org-taskjuggler-assign-resource-ids (resources info)
-  "Assign a unique ID to each resource within RESOURCES.
-RESOURCES is a list of headlines.  INFO is a plist used as a
-communication channel.  Return value is an alist between
-headlines and their associated ID."
-  (let (ids)
-    (org-element-map resources 'headline
-      (lambda (resource)
-        (let ((id (org-taskjuggler--build-unique-id resource ids)))
-          (push id ids)
-          (cons resource id)))
-      info)))
-
-
-
-;;; Accessors
-
-(defun org-taskjuggler-get-project (info)
-  "Return project in parse tree.
-INFO is a plist used as a communication channel.  First headline
-in buffer with `org-taskjuggler-project-tag' defines the project.
-If no such task is defined, pick the first headline in buffer.
-If there is no headline at all, return nil."
-  (let ((tree (plist-get info :parse-tree)))
-    (or (org-element-map tree 'headline
-         (lambda (hl)
-           (and (member org-taskjuggler-project-tag
-                        (org-export-get-tags hl info))
-                hl))
-         info t)
-       (org-element-map tree 'headline 'identity info t))))
-
-(defun org-taskjuggler-get-id (item info)
-  "Return id for task or resource ITEM.
-ITEM is a headline.  INFO is a plist used as a communication
-channel.  Return value is a string."
-  (cdr (assq item (plist-get info :taskjuggler-unique-ids))))
-
-(defun org-taskjuggler-get-name (item)
-  "Return name for task or resource ITEM.
-ITEM is a headline.  Return value is a string."
-  ;; Quote double quotes in name.
-  (replace-regexp-in-string
-   "\"" "\\\"" (org-element-property :raw-value item) t t))
-
-(defun org-taskjuggler-get-start (item)
-  "Return start date for task or resource ITEM.
-ITEM is a headline.  Return value is a string or nil if ITEM
-doesn't have any start date defined."
-  (let ((scheduled (org-element-property :scheduled item)))
-    (or
-     (and scheduled (org-timestamp-format scheduled "%Y-%02m-%02d"))
-     (and (memq 'start org-taskjuggler-valid-task-attributes)
-         (org-element-property :START item)))))
-
-(defun org-taskjuggler-get-end (item)
-  "Return end date for task or resource ITEM.
-ITEM is a headline.  Return value is a string or nil if ITEM
-doesn't have any end date defined."
-  (let ((deadline (org-element-property :deadline item)))
-    (and deadline (org-timestamp-format deadline "%Y-%02m-%02d"))))
-
-
-
-;;; Internal Functions
-
-(defun org-taskjuggler--indent-string (s)
-  "Indent string S by 2 spaces.
-Return new string.  If S is the empty string, return it."
-  (if (equal "" s) s (replace-regexp-in-string "^ *\\S-" "  \\&" s)))
-
-(defun org-taskjuggler--build-attributes (item attributes)
-  "Return attributes string for ITEM.
-ITEM is a project, task, resource or report headline.  ATTRIBUTES
-is a list of symbols representing valid attributes for ITEM."
-  (mapconcat
-   (lambda (attribute)
-     (let ((value (org-element-property
-                   (intern (upcase (format ":%s" attribute)))
-                   item)))
-       (and value (format "%s %s\n" attribute value))))
-   (remq nil attributes) ""))
-
-(defun org-taskjuggler--build-unique-id (item unique-ids)
-  "Return a unique id for a given task or a resource.
-ITEM is an `headline' type element representing the task or
-resource.  Its id is derived from its name and made unique
-against UNIQUE-IDS.  If the (downcased) first token of the
-headline is not unique try to add more (downcased) tokens of the
-headline or finally add more underscore characters (\"_\")."
-  (let ((id (org-string-nw-p (org-element-property :TASK_ID item))))
-    ;; If an id is specified, use it, as long as it's unique.
-    (if (and id (not (member id unique-ids))) id
-      (let* ((parts (split-string (org-element-property :raw-value item)))
-            (id (org-taskjuggler--clean-id (downcase (pop parts)))))
-       ;; Try to add more parts of the headline to make it unique.
-       (while (and (car parts) (member id unique-ids))
-         (setq id (concat id "_"
-                          (org-taskjuggler--clean-id (downcase (pop parts))))))
-       ;; If it's still not unique, add "_".
-       (while (member id unique-ids)
-         (setq id (concat id "_")))
-       id))))
-
-(defun org-taskjuggler--clean-id (id)
-  "Clean and return ID to make it acceptable for TaskJuggler.
-ID is a string."
-  ;; Replace non-ascii by "_".
-  (replace-regexp-in-string
-   "[^a-zA-Z0-9_]" "_"
-   ;; Make sure id doesn't start with a number.
-   (replace-regexp-in-string "^\\([0-9]\\)" "_\\1" id)))
-
-
-
-;;; Dependencies
-
-(defun org-taskjuggler-resolve-dependencies (task info)
-  "Return a list of all tasks TASK depends on.
-TASK is a headline.  INFO is a plist used as a communication
-channel."
-  (let ((deps-ids
-         ;; Get all dependencies specified in BLOCKER and DEPENDS task
-         ;; properties.  Clean options from them.
-         (let ((deps (concat (org-element-property :BLOCKER task)
-                             (org-element-property :DEPENDS task))))
-           (and deps
-                (split-string (replace-regexp-in-string "{.*?}" "" deps)
-                             "[ ,]* +"))))
-        depends)
-    (when deps-ids
-      ;; Find tasks with :task_id: property matching id in DEPS-IDS.
-      ;; Add them to DEPENDS.
-      (let* ((project (org-taskjuggler-get-project info))
-             (tasks (if org-taskjuggler-keep-project-as-task project
-                      (org-element-contents project))))
-        (setq depends
-              (org-element-map tasks 'headline
-                (lambda (task)
-                  (let ((task-id (or (org-element-property :TASK_ID task)
-                                    (org-element-property :ID task))))
-                    (and task-id (member task-id deps-ids) task)))
-                info)))
-      ;; Check BLOCKER and DEPENDS properties.  If "previous-sibling"
-      ;; belongs to DEPS-ID, add it to DEPENDS.
-      (when (and (member-ignore-case "previous-sibling" deps-ids)
-                 (not (org-export-first-sibling-p task info)))
-        (let ((prev (org-export-get-previous-element task info)))
-          (and (not (memq prev depends)) (push prev depends)))))
-    ;; Check ORDERED status of parent.
-    (let ((parent (org-export-get-parent task)))
-      (when (and parent
-                 (org-element-property :ORDERED parent)
-                 (not (org-export-first-sibling-p task info)))
-        (push (org-export-get-previous-element task info) depends)))
-    ;; Return dependencies.
-    depends))
-
-(defun org-taskjuggler-format-dependencies (dependencies task info)
-  "Format DEPENDENCIES to match TaskJuggler syntax.
-DEPENDENCIES is list of dependencies for TASK, as returned by
-`org-taskjuggler-resolve-depedencies'.  TASK is a headline.
-INFO is a plist used as a communication channel.  Return value
-doesn't include leading \"depends\"."
-  (let* ((dep-str (concat (org-element-property :BLOCKER task)
-                         " "
-                         (org-element-property :DEPENDS task)))
-        (get-path
-         (lambda (dep)
-           ;; Return path to DEP relatively to TASK.
-           (let ((parent (org-export-get-parent task))
-                 (exclamations 1)
-                 (option
-                  (let ((id (org-element-property :TASK_ID dep)))
-                    (and id
-                         (string-match (concat id " +\\({.*?}\\)") dep-str)
-                         (match-string-no-properties 1 dep-str))))
-                 path)
-             ;; Compute number of exclamation marks by looking for the
-             ;; common ancestor between TASK and DEP.
-             (while (not (org-element-map parent 'headline
-                           (lambda (hl) (eq hl dep))))
-               (incf exclamations)
-               (setq parent (org-export-get-parent parent)))
-             ;; Build path from DEP to PARENT.
-             (while (not (eq parent dep))
-               (push (org-taskjuggler-get-id dep info) path)
-               (setq dep (org-export-get-parent dep)))
-             ;; Return full path.  Add dependency options, if any.
-             (concat (make-string exclamations ?!)
-                     (mapconcat 'identity path ".")
-                     (and option (concat " " option)))))))
-    ;; Return dependencies string, without the leading "depends".
-    (mapconcat (lambda (dep) (funcall get-path dep)) dependencies ", ")))
-
-
-
-;;; Translator Functions
-
-(defun org-taskjuggler-project-plan (contents info)
-  "Build TaskJuggler project plan.
-CONTENTS is ignored.  INFO is a plist holding export options.
-Return complete project plan as a string in TaskJuggler syntax."
-  (let* ((tree (plist-get info :parse-tree))
-         (project (or (org-taskjuggler-get-project info)
-                      (error "No project specified"))))
-    (concat
-     ;; 1. Insert header.
-     (org-element-normalize-string org-taskjuggler-default-global-header)
-     ;; 2. Insert project.
-     (org-taskjuggler--build-project project info)
-     ;; 3. Insert global properties.
-     (org-element-normalize-string org-taskjuggler-default-global-properties)
-     ;; 4. Insert resources.  Provide a default one if none is
-     ;;    specified.
-     (let ((main-resources
-            ;; Collect contents from various trees marked with
-            ;; `org-taskjuggler-resource-tag'.  Only gather top level
-            ;; resources.
-            (apply 'append
-                   (org-element-map tree 'headline
-                     (lambda (hl)
-                       (and (member org-taskjuggler-resource-tag
-                                    (org-export-get-tags hl info))
-                            (org-element-map (org-element-contents hl) 
'headline
-                              'identity info nil 'headline)))
-                     info nil 'headline))))
-       ;; Assign a unique ID to each resource.  Store it under
-       ;; `:taskjuggler-unique-ids' property in INFO.
-       (setq info
-             (plist-put info :taskjuggler-unique-ids
-                        (org-taskjuggler-assign-resource-ids
-                         main-resources info)))
-       (concat
-        (if main-resources
-            (mapconcat
-             (lambda (resource) (org-taskjuggler--build-resource resource 
info))
-             main-resources "")
-          (format "resource %s \"%s\" {\n}\n" (user-login-name) 
user-full-name))
-        ;; 5. Insert tasks.
-        (let ((main-tasks
-               ;; If `org-taskjuggler-keep-project-as-task' is
-               ;; non-nil, there is only one task.  Otherwise, every
-               ;; direct children of PROJECT is a top level task.
-               (if org-taskjuggler-keep-project-as-task (list project)
-                 (or (org-element-map (org-element-contents project) 'headline
-                       'identity info nil 'headline)
-                     (error "No task specified")))))
-          ;; Assign a unique ID to each task.  Add it to
-          ;; `:taskjuggler-unique-ids' property in INFO.
-          (setq info
-                (plist-put info :taskjuggler-unique-ids
-                           (append
-                            (org-taskjuggler-assign-task-ids main-tasks info)
-                            (plist-get info :taskjuggler-unique-ids))))
-          ;; If no resource is allocated among tasks, allocate one to
-          ;; the first task.
-          (unless (org-element-map main-tasks 'headline
-                    (lambda (task) (org-element-property :ALLOCATE task))
-                    info t)
-            (org-element-put-property
-             (car main-tasks) :ALLOCATE
-             (or (org-taskjuggler-get-id (car main-resources) info)
-                 (user-login-name))))
-          (mapconcat
-           (lambda (task) (org-taskjuggler--build-task task info))
-           main-tasks ""))
-        ;; 6. Insert reports.  If no report is defined, insert default
-        ;;    reports.
-        (let ((main-reports
-               ;; Collect contents from various trees marked with
-               ;; `org-taskjuggler-report-tag'.  Only gather top level
-               ;; reports.
-               (apply 'append
-                      (org-element-map tree 'headline
-                        (lambda (hl)
-                          (and (member org-taskjuggler-report-tag
-                                       (org-export-get-tags hl info))
-                               (org-element-map (org-element-contents hl)
-                                   'headline 'identity info nil 'headline)))
-                        info nil 'headline))))
-          (if main-reports
-              (mapconcat
-               (lambda (report) (org-taskjuggler--build-report report info))
-               main-reports "")
-           ;; insert title in default reports
-           (let* ((title (org-export-data (plist-get info :title) info))
-                  (report-title (if (string= title "")
-                                    (org-taskjuggler-get-name project)
-                                  title)))
-             (mapconcat
-              'org-element-normalize-string
-              (mapcar
-               (function
-                (lambda (report)
-                  (replace-regexp-in-string "%title" report-title  report t 
t)))
-               org-taskjuggler-default-reports) "")))))))))
-
-(defun org-taskjuggler--build-project (project info)
-  "Return a project declaration.
-PROJECT is a headline.  INFO is a plist used as a communication
-channel.  If no start date is specified, start today.  If no end
-date is specified, end `org-taskjuggler-default-project-duration'
-days from now."
-  (concat
-   ;; Opening project.
-   (format "project %s \"%s\" \"%s\" %s %s {\n"
-          (org-taskjuggler-get-id project info)
-          (org-taskjuggler-get-name project)
-          ;; Version is obtained through :TASKJUGGLER_VERSION:
-          ;; property or `org-taskjuggler-default-project-version'.
-          (or (org-element-property :VERSION project)
-              org-taskjuggler-default-project-version)
-          (or (org-taskjuggler-get-start project)
-              (format-time-string "%Y-%m-%d"))
-          (let ((end (org-taskjuggler-get-end project)))
-            (or (and end (format "- %s" end))
-                (format "+%sd"
-                        org-taskjuggler-default-project-duration))))
-   ;; Add attributes.
-   (org-taskjuggler--indent-string
-    (org-taskjuggler--build-attributes
-     project org-taskjuggler-valid-project-attributes))
-   ;; Closing project.
-   "}\n"))
-
-(defun org-taskjuggler--build-resource (resource info)
-  "Return a resource declaration.
-
-RESOURCE is a headline.  INFO is a plist used as a communication
-channel.
-
-All valid attributes from RESOURCE are inserted.  If RESOURCE
-defines a property \"resource_id\" it will be used as the id for
-this resource.  Otherwise it will use the ID property.  If
-neither is defined a unique id will be associated to it."
-  (concat
-   ;; Opening resource.
-   (format "resource %s \"%s\" {\n"
-           (org-taskjuggler--clean-id
-            (or (org-element-property :RESOURCE_ID resource)
-                (org-element-property :ID resource)
-                (org-taskjuggler-get-id resource info)))
-           (org-taskjuggler-get-name resource))
-   ;; Add attributes.
-   (org-taskjuggler--indent-string
-    (org-taskjuggler--build-attributes
-     resource org-taskjuggler-valid-resource-attributes))
-   ;; Add inner resources.
-   (org-taskjuggler--indent-string
-    (mapconcat
-     'identity
-     (org-element-map (org-element-contents resource) 'headline
-       (lambda (hl) (org-taskjuggler--build-resource hl info))
-       info nil 'headline)
-     ""))
-   ;; Closing resource.
-   "}\n"))
-
-(defun org-taskjuggler--build-report (report info)
-  "Return a report declaration.
-REPORT is a headline.  INFO is a plist used as a communication
-channel."
-  (concat
-   ;; Opening report.
-   (format "%s \"%s\" {\n"
-           (or (org-element-property :REPORT_KIND report) "taskreport")
-           (org-taskjuggler-get-name report))
-   ;; Add attributes.
-   (org-taskjuggler--indent-string
-    (org-taskjuggler--build-attributes
-     report org-taskjuggler-valid-report-attributes))
-   ;; Add inner reports.
-   (org-taskjuggler--indent-string
-    (mapconcat
-     'identity
-     (org-element-map (org-element-contents report) 'headline
-       (lambda (hl) (org-taskjuggler--build-report hl info))
-       info nil 'headline)
-     ""))
-   ;; Closing report.
-   "}\n"))
-
-(defun org-taskjuggler--build-task (task info)
-  "Return a task declaration.
-
-TASK is a headline.  INFO is a plist used as a communication
-channel.
-
-All valid attributes from TASK are inserted.  If TASK defines
-a property \"task_id\" it will be used as the id for this task.
-Otherwise it will use the ID property.  If neither is defined
-a unique id will be associated to it."
-  (let* ((allocate (org-element-property :ALLOCATE task))
-         (complete
-          (if (eq (org-element-property :todo-type task) 'done) "100"
-            (org-element-property :COMPLETE task)))
-         (depends (org-taskjuggler-resolve-dependencies task info))
-         (effort (let ((property
-                       (intern (concat ":" (upcase org-effort-property)))))
-                  (org-element-property property task)))
-         (milestone
-          (or (org-element-property :MILESTONE task)
-              (not (or (org-element-map (org-element-contents task) 'headline
-                        'identity info t)  ; Has task any child?
-                      effort
-                      (org-element-property :LENGTH task)
-                      (org-element-property :DURATION task)
-                      (and (org-taskjuggler-get-start task)
-                           (org-taskjuggler-get-end task))
-                      (org-element-property :PERIOD task)))))
-         (priority
-          (let ((pri (org-element-property :priority task)))
-            (and pri
-                 (max 1 (/ (* 1000 (- org-priority-lowest pri))
-                           (- org-priority-lowest org-priority-highest)))))))
-    (concat
-     ;; Opening task.
-     (format "task %s \"%s\" {\n"
-             (org-taskjuggler-get-id task info)
-             (org-taskjuggler-get-name task))
-     ;; Add default attributes.
-     (and depends
-          (format "  depends %s\n"
-                  (org-taskjuggler-format-dependencies depends task info)))
-     (and allocate
-          (format "  purge %s\n  allocate %s\n"
-                  ;; Compatibility for previous TaskJuggler versions.
-                  (if (>= org-taskjuggler-target-version 3.0) "allocate"
-                    "allocations")
-                  allocate))
-     (and complete (format "  complete %s\n" complete))
-     (and effort (format "  effort %s\n" effort))
-     (and priority (format "  priority %s\n" priority))
-     (and milestone "  milestone\n")
-     ;; Add other valid attributes.
-     (org-taskjuggler--indent-string
-      (org-taskjuggler--build-attributes
-       task org-taskjuggler-valid-task-attributes))
-     ;; Add inner tasks.
-     (org-taskjuggler--indent-string
-      (mapconcat 'identity
-                 (org-element-map (org-element-contents task) 'headline
-                   (lambda (hl) (org-taskjuggler--build-task hl info))
-                   info nil 'headline)
-                 ""))
-     ;; Closing task.
-     "}\n")))
-
-
-
-;;; Interactive Functions
-
-;;;###autoload
-(defun org-taskjuggler-export (&optional async subtreep visible-only)
-  "Export current buffer to a TaskJuggler file.
-
-The exporter looks for a tree with tag that matches
-`org-taskjuggler-project-tag' and takes this as the tasks for
-this project.  The first node of this tree defines the project
-properties such as project name and project period.
-
-If there is a tree with tag that matches
-`org-taskjuggler-resource-tag' this tree is taken as resources
-for the project.  If no resources are specified, a default
-resource is created and allocated to the project.
-
-Also the TaskJuggler project will be created with default reports
-as defined in `org-taskjuggler-default-reports'.
-
-If narrowing is active in the current buffer, only export its
-narrowed part.
-
-If a region is active, export that region.
-
-A non-nil optional argument ASYNC means the process should happen
-asynchronously.  The resulting file should be accessible through
-the `org-export-stack' interface.
-
-When optional argument SUBTREEP is non-nil, export the sub-tree
-at point, extracting information from the headline properties
-first.
-
-When optional argument VISIBLE-ONLY is non-nil, don't export
-contents of hidden elements.
-
-Return output file's name."
-  (interactive)
-  (let ((outfile
-         (org-export-output-file-name org-taskjuggler-extension subtreep)))
-    (org-export-to-file 'taskjuggler outfile
-      async subtreep visible-only nil nil
-      (lambda (file)
-       (run-hook-with-args 'org-taskjuggler-final-hook file) nil))))
-
-;;;###autoload
-(defun org-taskjuggler-export-and-process (&optional subtreep visible-only)
-  "Export current buffer to a TaskJuggler file and process it.
-
-The exporter looks for a tree with tag that matches
-`org-taskjuggler-project-tag' and takes this as the tasks for
-this project.  The first node of this tree defines the project
-properties such as project name and project period.
-
-If there is a tree with tag that matches
-`org-taskjuggler-resource-tag' this tree is taken as resources
-for the project.  If no resources are specified, a default
-resource is created and allocated to the project.
-
-Also the TaskJuggler project will be created with default reports
-as defined in `org-taskjuggler-default-reports'.
-
-If narrowing is active in the current buffer, only export its
-narrowed part.
-
-If a region is active, export that region.
-
-When optional argument SUBTREEP is non-nil, export the sub-tree
-at point, extracting information from the headline properties
-first.
-
-When optional argument VISIBLE-ONLY is non-nil, don't export
-contents of hidden elements.
-
-Return a list of reports."
-  (interactive)
-  (let ((file (org-taskjuggler-export nil subtreep visible-only)))
-    (org-taskjuggler-compile file)))
-
-;;;###autoload
-(defun org-taskjuggler-export-process-and-open (&optional subtreep 
visible-only)
-  "Export current buffer to a TaskJuggler file, process and open it.
-
-Export and process the file using
-`org-taskjuggler-export-and-process' and open the generated
-reports with a browser.
-
-If you are targeting TaskJuggler 2.4 (see
-`org-taskjuggler-target-version') the processing and display of
-the reports is done using the TaskJuggler GUI."
-  (interactive)
-  (if (< org-taskjuggler-target-version 3.0)
-      (let* ((process-name "TaskJugglerUI")
-            (command
-             (concat process-name " "
-                     (org-taskjuggler-export nil subtreep visible-only))))
-       (start-process-shell-command process-name nil command))
-    (dolist (report (org-taskjuggler-export-and-process subtreep visible-only))
-      (org-open-file report))))
-
-(defun org-taskjuggler-compile (file)
-  "Compile a TaskJuggler file.
-
-FILE is the name of the file being compiled.  Processing is done
-through the command given in `org-taskjuggler-process-command'.
-
-Return a list of reports."
-  (let* ((full-name (file-truename file))
-        (out-dir
-         (expand-file-name
-          org-taskjuggler-reports-directory (file-name-directory file)))
-        errors)
-    (message (format "Processing TaskJuggler file %s..." file))
-    (save-window-excursion
-      (let ((outbuf (get-buffer-create "*Org Taskjuggler Output*")))
-       (unless (file-directory-p out-dir)
-         (make-directory out-dir t))
-       (with-current-buffer outbuf (erase-buffer))
-       (shell-command
-        (replace-regexp-in-string
-         "%f" (shell-quote-argument full-name)
-         (replace-regexp-in-string
-          "%o" (shell-quote-argument out-dir)
-          org-taskjuggler-process-command t t) t t) outbuf)
-       ;; Collect standard errors from output buffer.
-       (setq errors (org-taskjuggler--collect-errors outbuf)))
-      (if (not errors)
-         (message "Process completed.")
-       (error (format "TaskJuggler failed with errors: %s" errors))))
-    (file-expand-wildcards (format "%s/*.html" out-dir))))
-
-(defun org-taskjuggler--collect-errors (buffer)
-  "Collect some kind of errors from \"tj3\" 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))
-      (let ((case-fold-search t)
-           (errors ""))
-       (while (re-search-forward "^.+:[0-9]+: \\(.*\\)$" nil t)
-         (setq errors (concat errors " " (match-string 1))))
-       (and (org-string-nw-p errors) (org-trim errors))))))
-
-
-(provide 'ox-taskjuggler)
-
-;; Local variables:
-;; sentence-end-double-space: t
-;; End:
-
-;;; ox-taskjuggler.el ends here
diff --git a/contrib/scripts/.gitignore b/contrib/scripts/.gitignore
deleted file mode 100644
index 20d5925..0000000
--- a/contrib/scripts/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-plantuml.jar
diff --git a/contrib/scripts/StartOzServer.oz b/contrib/scripts/StartOzServer.oz
deleted file mode 100644
index 79b86a8..0000000
--- a/contrib/scripts/StartOzServer.oz
+++ /dev/null
@@ -1,231 +0,0 @@
-%%% *************************************************************
-%%% Copyright (C) 2009-2013 Torsten Anders (www.torsten-anders.de) 
-%%% 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 2
-%%% 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.
-%%% *************************************************************
-
-%%
-%% This code implements the Oz-side of the Org-babel Oz interface. It
-%% creates a socket server (to which org-babel-oz.el then
-%% connects). Any input to this socket must be an Oz expression. The
-%% input is fed to the OPI oz compiler, and the results are send back
-%% via the socket.
-%%
-
-
-declare
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Accessing the OPI compiler
-%%
-
-MyCompiler = Emacs.condSend.compiler
-
-
-/* % testing
-
-%% Feed an expression (result browsed)
-{MyCompiler enqueue(setSwitch(expression true))}
-{Browse
- {MyCompiler enqueue(feedVirtualString("1 + 2" return(result: $)))}}
-{MyCompiler enqueue(setSwitch(expression false))}
-
-%% It is really the OPI: I can use declare!
-{MyCompiler enqueue(setSwitch(expression false))}
-{MyCompiler enqueue(feedVirtualString("declare X=3\n{Browse X*X}"))}
-
-%% Note: expressions starting with keyword declare need keyword in 
-{MyCompiler enqueue(setSwitch(expression true))}
-{Browse
- {MyCompiler enqueue(feedVirtualString("declare X=3\nin X*X" return(result: 
$)))}}
-{MyCompiler enqueue(setSwitch(expression false))}
-
-%% Alternatively you use a session with multiple feeds: first declare 
(statement), and then feed an expression
-{MyCompiler enqueue(setSwitch(expression false))}
-{MyCompiler enqueue(feedVirtualString("declare X=7" return))}
-{MyCompiler enqueue(setSwitch(expression true))}
-{Browse
- {MyCompiler enqueue(feedVirtualString("X*X" return(result: $)))}}
-{MyCompiler enqueue(setSwitch(expression false))}
-
-%% !!?? does not work?
-%% return nil in case of any error (division by 0)
-{MyCompiler enqueue(setSwitch(expression true))}
-{Browse
- {MyCompiler enqueue(feedVirtualString(
-                       {Accum ["try\n"
-%                                     "skip\n" % do something in any case..
-                                      "1 div 0" % my code
-%                                     "1" % my code
-                                      "\ncatch E then {Error.printException 
E}\n"
-                                      "error\n" % always return nil
-                                      "end\n"]
-                        List.append}
-                       return(result: $)))}}
-{MyCompiler enqueue(setSwitch(expression false))}
-
-
-%% !! catching some exceptions does not work??
-
-%% exception is not caught
-try {Bla} catch E then {Error.printException E} {Browse nil} end
-
-%% exception is caught
-try {Browse 1 div 0} catch E then {Error.printException E} {Browse nil} end
-{Browse ok}
-
-
-*/
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Socket interface
-%%
-
-
-%%
-%% Create socket
-%%
-
-MyPort = 6001
-
-/** %% Creates a TCP socket server. Expects a Host (e.g., 'localhost') and a 
PortNo and returns a server plus its corresponding client. This client is an 
instance of Open.socket, and is the interface for reading and writing into the 
socket.
-%% MakeServer blocks until the server listens. However, waiting until a 
connection has been accepted happens in its own thread (i.e. MakeServer does 
only block until the server listens).
-%% NB: A port can be used only once, so assign it carefully. In case this 
postnnumber was shortly used before, you may need to wait a bit before reusing 
it.
-%% */
-%% !! Alternatively, let it assign automatically and output the port number..
-%%
-%% NOTE: for supporting multiple connections see 
http://www.mozart-oz.org/documentation/op/node13.html#section.sockets.accept
-proc {MakeServer Host PortNo ?MyServer ?MyClient}
-   proc {Accept MyClient}
-      thread H in % P
-        %% suspends until a connection has been accepted
-        {MyServer accept(host:H
-                         acceptClass:Open.socket  
-                         accepted:?MyClient)} 
-%          {Myserver accept(host:H port:P)} % suspends until a connection has 
been accepted
-        %% !!?? port number of client is usually created randomly..
-        {System.showInfo "% connection accepted from host "#H}
-      end
-      %% !!??? 
-      %% If Accept is called recursively, then server accepts multiple 
connections. These share the same compiler instance (e.g. variable bindings are 
shared). For multiple independent compiler instances call the OzServer 
application multiple times.
-      %% However, how shall the output for multiple connections be sorted?? 
Would using the different client sockets created with the Server accept method 
work?
-      %% NB: The number of clients accepted concurrently must be limited to 
the number set by {MyServer listen}
-        % {Accept}
-   end
-in
-   MyServer = {New Open.socket init}
-   %% To avoid problems with portnumbers, the port could be assigned 
automatically and then output..
-   %%{MyServer bind(port:PortNo)}
-   {MyServer bind(host:Host takePort:PortNo)}
-   {MyServer listen}
-   {System.showInfo "% OzServer started at host "#Host#" and port "#PortNo}
-   MyClient = {Accept}
-end
-%%
-MySocket = {MakeServer localhost MyPort _/*MyServer*/}
-
-
-%%
-%% Read socket input 
-%%
-
-declare
-%% Copied from OzServer/source/Socket.oz
-local
-   proc {Aux Socket Size Stream}
-      In = {Socket read(list:$
-                       size:Size)}
-   in
-      {Wait In}
-      %% !! Is this the right way to stop the processing??
-      %%
-      %% abort condition when client stream ended (i.e. nothing was sent)
-      if In == nil
-      then {System.showInfo "socket stream ended"}
-        Stream = nil
-      else Stream = In | {Aux Socket Size}
-      end
-   end
-in
-   /** %% The socket Server returns a stream of the strings it receives. The 
Server always waits until someone writes something into the socket, then the 
input is immediately written to a stream and the Server waits again.
-   %% */
-   proc {ReadToStream Socket Size Xs}
-      thread {Aux Socket Size Xs} end
-   end
-end
-
-/* % test
-
-MyStream = {ReadToStream MySocket 1024}
-
-*/
-
-/* % test
-
-%% writing
-{MySocket write(vs:"this is a test")}
-
-*/
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Send socket input to compiler and send results back to socket
-%%
-
-%% NOTE: Input code must be expression
-thread 
-   {ForAll {ReadToStream MySocket 1024}
-    proc {$ Code}
-       Result
-       %% Catch any exception (so the will not cause blocking) and return nil 
in that case
-       FullCode = {Accum ["try\n"
-%                               "skip\n" % do something in any case..
-                                Code
-                                "\ncatch E then {Error.printException E}\n"
-                                "error\n" % in case of an error, return 
'error' 
-                                "end\n"]
-                  List.append}
-    in
-       %% ?? Should I make setting switches etc atomic?
-       {MyCompiler enqueue(setSwitch(expression true))}
-       {MyCompiler enqueue(feedVirtualString(FullCode return(result: 
?Result)))}
-       {MyCompiler enqueue(setSwitch(expression false))}
-       %%
-       {Wait Result}
-       {MySocket write(vs: if {VirtualString.is Result}
-                          then Result
-                          else {Value.toVirtualString Result 1000 1000}
-                          end)}
-       {Show 'Org-babel result: '#Result}
-    end}
-end
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Aux defs
-%%
-
-/** %% Binds the accumulation of the binary function Fn on all neighbors in Xs 
to Y. E.g., Accum returns the sum in Xs if Fn is Number.'+'.
-%% */
-proc {Accum Xs Fn Y}
-   {List.foldL Xs.2 Fn Xs.1 Y}
-end
-
-
-
-
-
-   
-
diff --git a/contrib/scripts/dir2org.zsh b/contrib/scripts/dir2org.zsh
deleted file mode 100755
index f91ff17..0000000
--- a/contrib/scripts/dir2org.zsh
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/usr/bin/env zsh
-
-# desc:
-#
-# Output an org compatible structure representing the filesystem from
-# the point passed on the command line (or . by default).
-#
-# options:
-#     none
-#
-# usage:
-#     dir2org.zsh [DIR]...
-#
-# author:
-#     Phil Jackson (phil@shellarchive.co.uk)
-
-set -e
-
-function headline {
-    local depth="${1}"
-    local text="${2}"
-
-    printf "%${depth}s %s" "" | tr ' ' '*'
-    echo " ${text}"
-}
-
-function scan_and_populate {
-    local depth="${1}"
-    local dir="${2}"
-
-    headline ${depth} "${dir}"
-
-    # if there is no files in dir then just move on
-    [[ $(ls "${dir}" | wc -l) -eq 0 ]] && return
-
-    (( depth += 1 ))
-
-    for f in $(ls -d "${dir}"/*); do
-        if [ -d "${f}" ]; then
-            scan_and_populate ${depth} "${f}"
-        else
-            headline ${depth} "[[file://${f}][${${f##*/}%.*}]]"
-        fi
-    done
-
-    (( depth -= 1 ))
-}
-
-function main {
-    local scan_dir="${1:-$(pwd)}"
-    local depth=0
-
-    scan_and_populate ${depth} "${scan_dir}"
-}
-
-main "${@}"
diff --git a/contrib/scripts/ditaa.jar b/contrib/scripts/ditaa.jar
deleted file mode 100644
index 5894de4..0000000
Binary files a/contrib/scripts/ditaa.jar and /dev/null differ
diff --git a/contrib/scripts/docco.css b/contrib/scripts/docco.css
deleted file mode 100644
index 9030b6c..0000000
--- a/contrib/scripts/docco.css
+++ /dev/null
@@ -1,185 +0,0 @@
-/*--------------------- Layout and Typography ----------------------------*/
-body {
-  font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif;
-  font-size: 15px;
-  line-height: 22px;
-  color: #252519;
-  margin: 0; padding: 0;
-}
-a {
-  color: #261a3b;
-}
-  a:visited {
-    color: #261a3b;
-  }
-p {
-  margin: 0 0 15px 0;
-}
-h1, h2, h3, h4, h5, h6 {
-  margin: 0px 0 15px 0;
-}
-  h1 {
-    margin-top: 40px;
-  }
-#container {
-  position: relative;
-}
-#background {
-  position: fixed;
-  top: 0; left: 525px; right: 0; bottom: 0;
-  background: #f5f5ff;
-  border-left: 1px solid #e5e5ee;
-  z-index: -1;
-}
-#jump_to, #jump_page {
-  background: white;
-  -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777;
-  -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px;
-  font: 10px Arial;
-  text-transform: uppercase;
-  cursor: pointer;
-  text-align: right;
-}
-#jump_to, #jump_wrapper {
-  position: fixed;
-  right: 0; top: 0;
-  padding: 5px 10px;
-}
-  #jump_wrapper {
-    padding: 0;
-    display: none;
-  }
-    #jump_to:hover #jump_wrapper {
-      display: block;
-    }
-    #jump_page {
-      padding: 5px 0 3px;
-      margin: 0 0 25px 25px;
-    }
-      #jump_page .source {
-        display: block;
-        padding: 5px 10px;
-        text-decoration: none;
-        border-top: 1px solid #eee;
-      }
-        #jump_page .source:hover {
-          background: #f5f5ff;
-        }
-        #jump_page .source:first-child {
-        }
-table td {
-  border: 0;
-  outline: 0;
-}
-  td.docs, th.docs {
-    max-width: 450px;
-    min-width: 450px;
-    min-height: 5px;
-    padding: 10px 25px 1px 50px;
-    overflow-x: hidden;
-    vertical-align: top;
-    text-align: left;
-  }
-    .docs pre {
-      margin: 15px 0 15px;
-      padding-left: 15px;
-    }
-    .docs p tt, .docs p code {
-      background: #f8f8ff;
-      border: 1px solid #dedede;
-      font-size: 12px;
-      padding: 0 0.2em;
-    }
-    .pilwrap {
-      position: relative;
-    }
-      .pilcrow {
-        font: 12px Arial;
-        text-decoration: none;
-        color: #454545;
-        position: absolute;
-        top: 3px; left: -20px;
-        padding: 1px 2px;
-        opacity: 0;
-        -webkit-transition: opacity 0.2s linear;
-      }
-        td.docs:hover .pilcrow {
-          opacity: 1;
-        }
-  td.code, th.code {
-    padding: 14px 15px 16px 25px;
-    width: 100%;
-    vertical-align: top;
-    border-left: 1px solid #e5e5ee;
-  }
-    pre, tt, code {
-      font-size: 12px; line-height: 18px;
-      font-family: Menlo, Monaco, Consolas, "Lucida Console", monospace;
-      margin: 0; padding: 0;
-    }
-
-
-/*---------------------- Syntax Highlighting -----------------------------*/
-td.linenos { background-color: #f0f0f0; padding-right: 10px; }
-span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; }
-body .hll { background-color: #ffffcc }
-body .c { color: #408080; font-style: italic }  /* Comment */
-body .err { border: 1px solid #FF0000 }         /* Error */
-body .k { color: #954121 }                      /* Keyword */
-body .o { color: #666666 }                      /* Operator */
-body .cm { color: #408080; font-style: italic } /* Comment.Multiline */
-body .cp { color: #BC7A00 }                     /* Comment.Preproc */
-body .c1 { color: #408080; font-style: italic } /* Comment.Single */
-body .cs { color: #408080; font-style: italic } /* Comment.Special */
-body .gd { color: #A00000 }                     /* Generic.Deleted */
-body .ge { font-style: italic }                 /* Generic.Emph */
-body .gr { color: #FF0000 }                     /* Generic.Error */
-body .gh { color: #000080; font-weight: bold }  /* Generic.Heading */
-body .gi { color: #00A000 }                     /* Generic.Inserted */
-body .go { color: #808080 }                     /* Generic.Output */
-body .gp { color: #000080; font-weight: bold }  /* Generic.Prompt */
-body .gs { font-weight: bold }                  /* Generic.Strong */
-body .gu { color: #800080; font-weight: bold }  /* Generic.Subheading */
-body .gt { color: #0040D0 }                     /* Generic.Traceback */
-body .kc { color: #954121 }                     /* Keyword.Constant */
-body .kd { color: #954121; font-weight: bold }  /* Keyword.Declaration */
-body .kn { color: #954121; font-weight: bold }  /* Keyword.Namespace */
-body .kp { color: #954121 }                     /* Keyword.Pseudo */
-body .kr { color: #954121; font-weight: bold }  /* Keyword.Reserved */
-body .kt { color: #B00040 }                     /* Keyword.Type */
-body .m { color: #666666 }                      /* Literal.Number */
-body .s { color: #219161 }                      /* Literal.String */
-body .na { color: #7D9029 }                     /* Name.Attribute */
-body .nb { color: #954121 }                     /* Name.Builtin */
-body .nc { color: #0000FF; font-weight: bold }  /* Name.Class */
-body .no { color: #880000 }                     /* Name.Constant */
-body .nd { color: #AA22FF }                     /* Name.Decorator */
-body .ni { color: #999999; font-weight: bold }  /* Name.Entity */
-body .ne { color: #D2413A; font-weight: bold }  /* Name.Exception */
-body .nf { color: #0000FF }                     /* Name.Function */
-body .nl { color: #A0A000 }                     /* Name.Label */
-body .nn { color: #0000FF; font-weight: bold }  /* Name.Namespace */
-body .nt { color: #954121; font-weight: bold }  /* Name.Tag */
-body .nv { color: #19469D }                     /* Name.Variable */
-body .ow { color: #AA22FF; font-weight: bold }  /* Operator.Word */
-body .w { color: #bbbbbb }                      /* Text.Whitespace */
-body .mf { color: #666666 }                     /* Literal.Number.Float */
-body .mh { color: #666666 }                     /* Literal.Number.Hex */
-body .mi { color: #666666 }                     /* Literal.Number.Integer */
-body .mo { color: #666666 }                     /* Literal.Number.Oct */
-body .sb { color: #219161 }                     /* Literal.String.Backtick */
-body .sc { color: #219161 }                     /* Literal.String.Char */
-body .sd { color: #219161; font-style: italic } /* Literal.String.Doc */
-body .s2 { color: #219161 }                     /* Literal.String.Double */
-body .se { color: #BB6622; font-weight: bold }  /* Literal.String.Escape */
-body .sh { color: #219161 }                     /* Literal.String.Heredoc */
-body .si { color: #BB6688; font-weight: bold }  /* Literal.String.Interpol */
-body .sx { color: #954121 }                     /* Literal.String.Other */
-body .sr { color: #BB6688 }                     /* Literal.String.Regex */
-body .s1 { color: #219161 }                     /* Literal.String.Single */
-body .ss { color: #19469D }                     /* Literal.String.Symbol */
-body .bp { color: #954121 }                     /* Name.Builtin.Pseudo */
-body .vc { color: #19469D }                     /* Name.Variable.Class */
-body .vg { color: #19469D }                     /* Name.Variable.Global */
-body .vi { color: #19469D }                     /* Name.Variable.Instance */
-body .il { color: #666666 }                     /* Literal.Number.Integer.Long 
*/
\ No newline at end of file
diff --git a/contrib/scripts/org-docco.org b/contrib/scripts/org-docco.org
deleted file mode 100644
index bfa5040..0000000
--- a/contrib/scripts/org-docco.org
+++ /dev/null
@@ -1,206 +0,0 @@
-#+Title: Org-Docco
-#+Author: Eric Schulte
-#+Style: <link rel="stylesheet" href="docco.css" type="text/css">
-#+Property: tangle yes
-
-The =docco= tool (see http://jashkenas.github.com/docco/) generates
-HTML from JavaScript source code providing an attractive side-by-side
-display of source code and comments.  This file (see 
[[https://orgmode.org/cgit.cgi/org-mode.git/plain/contrib/scripts/org-docco.org][org-docco.org]])
-generates the same type of output from Org-mode documents with code
-embedded in code blocks.
-
-The way this works is an Org-mode document with embedded code blocks
-is exported to html using the standard Org-mode export functions.
-This file defines a new function named =org-docco-buffer= which, when
-added to the =org-export-html-final-hook=, will be run automatically
-as part of the Org-mod export process doccoizing your Org-mode
-document.
-
-A pure source code file can be extracted (or "/tangled/") from the
-Org-mode document using the normal =org-babel-tangle= function.  See
-[[https://orgmode.org/manual/Working-With-Source-Code.html][Working With 
Source Code]] chapter of the Org-mode manual for more
-information on using code blocks in Org-mode files.
-
-*Disclaimer*: this currently only works on /very/ simple Org-mode
-files which have no headings but rather are just a collection of
-alternating text and code blocks.  It wouldn't be difficult to
-generalize the following code so that it could be run in particular
-sub-trees but I simply don't have the time to do so myself, and this
-version perfectly satisfies my own limit needs.  I make no promises to
-support this code moving forward.  /Caveat Emptor/
-
-#+begin_src emacs-lisp :padline no
-;;; org-docco.el --- docco type html generation from Org-mode
-
-;; Copyright (C) 2012 Eric Schulte
-
-;; Author: Eric Schulte
-;; Keywords: org-mode, literate programming, html
-;; Homepage: https://orgmode.org/worg/org-contrib/org-mime.php
-;; Version: 0.01
-
-;; This file is not 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; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
-
-;;; Commentary:
-
-;; <- look over there
-#+end_src
-
-The =cl= package provides all of the state-changing functions used
-below e.g., =push= and =incf=.  It looks like a namespace-safe version
-of =cl= may soon be permissible for use in official Emacs packages.
-#+begin_src emacs-lisp
-;;; Code:
-(require 'cl)
-#+end_src
-
-This is a function which returns the buffer positions of matching
-regular expressions.  It has two special features...
-1. It only counts matched instances of =beg-re= and =end-re= which are
-   properly nested, so for example if =beg-re= and =end-re= are set to
-   =(= and =)= respectively and we run this against the following,
-   : 1    2       3 4   5     6
-   : |    |       | |   |     |
-   : v    v       v v   v     v
-   : (foo (bar baz) (qux) quux)
-   it will return 1 and 6 rather than 1 and 3.
-2. It uses 
[[www.gnu.org/s/emacs/manual/html_node/elisp/Markers.html][markers]] which save 
their position in a buffer even as the
-   buffer is changed (e.g., by me adding in extra HTML text).
-#+begin_src emacs-lisp
-(defun org-docco-balanced-re (beg-re end-re)
-  "Return the beginning and of a balanced regexp."
-  (save-excursion
-    (save-match-data
-      (let ((both-re (concat "\\(" beg-re "\\|" end-re "\\)"))
-            (beg-count 0) (end-count 0)
-            beg end)
-        (when (re-search-forward beg-re nil t)
-          (goto-char (match-beginning 0))
-          (setq beg (point-marker))
-          (incf beg-count)
-          (goto-char (match-end 0))
-          (while (and (not end) (re-search-forward both-re nil t))
-            (goto-char (match-beginning 0))
-            (cond ((looking-at beg-re) (incf beg-count))
-                  ((looking-at end-re) (incf end-count))
-                  (:otherwise (error "miss-matched")))
-            (goto-char (match-end 0))
-            (when (= beg-count end-count) (setq end (point-marker))))
-          (when end (cons beg end)))))))
-#+end_src
-
-This ugly large function does the actual conversion.  It wraps the
-entire main content =div= of the exported Org-mode html into a single
-large table.  Each row of the table has documentation on the left side
-and code on the right side.  This function has two parts.
-1. We use =(org-docco-balanced-re "<div" "</div>")= to find the
-   beginning and end of the main content div.  We then break up this
-   div at =<pre></pre>= boundaries with multiple calls to
-   =(org-docco-balanced-re "<pre class\"src" "</pre>")=.
-2. With all documentation/code boundaries in hand we step through the
-   buffer inserting the table html code at boundary locations.
-#+begin_src emacs-lisp
-(defun org-docco-buffer ()
-  "Call from within an HTML buffer to doccoize it."
-  (interactive)
-  (let ((table-start "<table>\n")
-        (doc-row-start  "<tr><th class=\"docs\">\n") (doc-row-end  "</th>\n")
-        (code-row-start "    <td class=\"code\">\n") (code-row-end 
"</td></tr>\n")
-        (table-end "</table>" )
-        pair transition-points next)
-    (save-excursion
-      (save-match-data
-        (goto-char (point-min))
-        (when (re-search-forward "<div id=\"content\">" nil t)
-          (goto-char (match-end 0))
-          (push (point-marker) transition-points)
-          (goto-char (match-beginning 0))
-          (setq pair (org-docco-balanced-re "<div" "</div>"))
-          (while (setq next (org-docco-balanced-re "<pre class=\"src" 
"</pre>"))
-            (goto-char (cdr next))
-            (push (car next) transition-points)
-            (push (cdr next) transition-points))
-          (goto-char (cdr pair))
-          (push (and (re-search-backward "</div>" nil t) (point-marker))
-                transition-points)
-          ;; collected transitions, so build the table
-          (setq transition-points (nreverse transition-points))
-          (goto-char (pop transition-points))
-          (insert table-start doc-row-start)
-          (while (> (length transition-points) 1)
-            (goto-char (pop transition-points))
-            (insert doc-row-end code-row-start)
-            (goto-char (pop transition-points))
-            (insert code-row-end doc-row-start))
-          (goto-char (pop transition-points))
-          (insert code-row-end table-end)
-          (unless (null transition-points)
-            (error "leftover points")))))))
-#+end_src
-
-We'll use Emacs 
[[http://www.gnu.org/software/emacs/manual/html_node/emacs/Specifying-File-Variables.html][File
 Local Variables]] and the
-=org-export-html-final-hook= to control which buffers have
-=org-docco-buffer= run as part of their export process.
-#+begin_src emacs-lisp
-  (defvar org-docco-doccoize-me nil
-    "File local variable controlling if html export should be doccoized.")
-  (make-local-variable 'org-docco-doccoize-me)
-#+end_src
-
-A simple function will conditionally process HTML output based on the
-value of this variable.
-#+begin_src emacs-lisp
-  (defun org-docco-buffer-maybe ()
-    (when org-docco-doccoize-me (org-docco-buffer)))
-#+end_src
-
-Finally this function is added to the =org-export-html-final-hook=.
-#+begin_src emacs-lisp
-  (add-hook 'org-export-html-final-hook #'org-docco-buffer-maybe)
-#+end_src
-
-That's it.  To use this simply;
-1. Checkout this file from https://github.com/eschulte/org-docco,
-   : git clone git://github.com/eschulte/org-docco.git
-   and open it using Emacs.
-2. Tangle =org-docco.el= out of this file by calling
-   =org-babel-tangle= or =C-c C-v t=.
-3. Load the resulting Emacs Lisp file.
-4. Execute the following in any Org-mode buffer to add file local
-   variable declarations which will enable post-processed with
-   =org-docco-buffer=.
-   : (add-file-local-variable 'org-export-html-postamble nil)
-   : (add-file-local-variable 'org-export-html-style-include-default nil)
-   : (add-file-local-variable 'org-docco-doccoize-me t)
-   And add the following style declaration to make use of the
-   =docco.css= style sheet taken directly from
-   https://github.com/jashkenas/docco.
-   : #+Style: <link rel="stylesheet" href="docco.css" type="text/css">
-
-#+begin_src emacs-lisp
-(provide 'org-docco)
-;;; org-docco.el ends here
-#+end_src
-
-# Local Variables:
-# org-export-html-postamble: nil
-# org-export-html-style-include-default: nil
-# org-docco-doccoize-me: t
-# End:
diff --git a/contrib/scripts/org2hpda b/contrib/scripts/org2hpda
deleted file mode 100755
index 07f29d9..0000000
--- a/contrib/scripts/org2hpda
+++ /dev/null
@@ -1,106 +0,0 @@
-# org2hpda - a small utility to generate hipster pda style printouts from org 
mode 
-# Copyright (C) 2007-2013  Christian Egli
-# 
-# Version: 0.6
-#
-# 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:
-# ===========
-#
-# set cal-tex-diary to true so that diary entries show up in the calendar 
-#
-# Usage:
-# ======
-#
-# run this makefile with 
-#
-#  make -f org2hpda
-#
-# The makfile will take the entries from your diary file and generate
-# two PDFs containing nicely printed weekly and monthly calendars. One
-# is done in the style of a pocketMod (http://www.pocketmod.com/) and
-# the other is done in the style of the Hipster PDA
-# (http://en.wikipedia.org/wiki/Hipster_PDA). 
-#
-# Requirements:
-# =============
-#
-# the pdf* commands are part of the pdfjam package which can be found
-# at http://www.warwick.ac.uk/go/pdfjam
-
-EMACS = emacs -batch -l ~/.emacs
-LATEX = latex
-DIARY = $($(EMACS) -eval "diary-file")
-
-# Number of weeks to be printed. Should be a multiple of 4, because 4
-# of them are merged on one page. Can be set when invoking the script
-# as follows: make NUMBER_OF_WEEKS=8 -f org2hpda
-NUMBER_OF_WEEKS = 4 
-
-hipsterFiles =  weekCalendar.pdf yearCalendar.pdf monthCalendar3.pdf 
monthCalendar2.pdf monthCalendar1.pdf
-pocketModFiles =  weekCalendar.pdf yearCalendar-rotated.pdf \
-       monthCalendar3-rotated.pdf monthCalendar2-rotated.pdf 
monthCalendar1-rotated.pdf
-
-all: pocketMod.pdf hipsterPDA.pdf
-
-%.dvi: %.tex
-       # Quick hack to massage the LaTeX produced by cal-tex
-       # quote '@', then increase font size of week calendars,
-       # increase font of diary entries in moth calendar and 
-       # finally reduce links to their destination, i.e. 
-       # change '[[http://foo][bar]]' to 'bar'
-       sed     -e 's/\\verb|@|/\@/g' \
-               -e 's/documentclass\[11pt\]/documentclass[12pt]/g' \
-               -e 's/{\\tiny \\raggedright #3}/{\\small \\raggedright #3}/g' \
-               -e 's/\[\[[^]]\+\]\[\([^]]\+\)\]\]/\1/g' \
-               < $< > /tmp/temp-org-file.$$$$; mv /tmp/temp-org-file.$$$$ $<
-       $(LATEX) $^
-
-%.pdf: %.dvi
-       dvipdf $^
-
-%-rotated.pdf: %.pdf
-       cp $^ $@
-       for n in 1 2 3; do \
-               pdf90 --quiet --outfile tmp.pdf $@; mv tmp.pdf $@; \
-       done
-
-weekCalendar.tex: $(DIARY)
-       $(EMACS) -eval "(progn (calendar) (cal-tex-cursor-week-iso 
$(NUMBER_OF_WEEKS)) (with-current-buffer cal-tex-buffer (write-file \"$@\")))"
-
-monthCalendar1.tex: $(DIARY)
-        $(EMACS) -eval "(progn (calendar) (cal-tex-cursor-month-landscape 1) 
(with-current-buffer cal-tex-buffer (write-file \"$@\")))"
-
-monthCalendar2.tex: $(DIARY)
-        $(EMACS) -eval "(progn (calendar) (calendar-forward-month 1) 
(cal-tex-cursor-month-landscape 1) (with-current-buffer cal-tex-buffer 
(write-file \"$@\")))"
-
-monthCalendar3.tex: $(DIARY)
-        $(EMACS) -eval "(progn (calendar) (calendar-forward-month 2) 
(cal-tex-cursor-month-landscape 1) (with-current-buffer cal-tex-buffer 
(write-file \"$@\")))"
-
-yearCalendar.tex: $(DIARY)
-        $(EMACS) -eval "(progn (calendar) (calendar-forward-month 2) 
(cal-tex-cursor-year-landscape 1) (with-current-buffer cal-tex-buffer 
(write-file \"$@\")))"
-
-pocketMod.pdf: $(pocketModFiles)
-       pdfjoin --quiet --outfile tmp.pdf $^
-       pdfnup tmp.pdf --quiet --outfile $@ --nup 4x2 --frame true
-
-hipsterPDA.pdf: $(hipsterFiles)
-       pdfnup weekCalendar.pdf --quiet --outfile page1.pdf --batch --nup 2x2 
--frame true --no-landscape
-       pdfjoin --quiet --outfile tmp.pdf monthCalendar[1-3]-rotated.pdf 
yearCalendar-rotated.pdf
-       pdfnup tmp.pdf --quiet --outfile page2.pdf --batch --nup 2x2 --frame 
true --no-landscape
-       pdfjoin --quiet --outfile $@ page1.pdf page2.pdf
-
-clean:
-       rm -rf *.aux *.dvi *.tex *.log *.pdf
diff --git a/contrib/scripts/staticmathjax/.gitignore 
b/contrib/scripts/staticmathjax/.gitignore
deleted file mode 100644
index b25c15b..0000000
--- a/contrib/scripts/staticmathjax/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-*~
diff --git a/contrib/scripts/staticmathjax/README.org 
b/contrib/scripts/staticmathjax/README.org
deleted file mode 100644
index d15bf95..0000000
--- a/contrib/scripts/staticmathjax/README.org
+++ /dev/null
@@ -1,79 +0,0 @@
-Static MathJax v0.1 README
-#+AUTHOR: Jan Bรถcker <jan.boecker@jboecker.de>
-
-Static MathJax is a XULRunner application which loads a HTML input
-file that uses MathJax into a browser, waits until MathJax is done
-processing, and then writes the formatted result to an output HTML
-file.
-
-I have only tested exports from Emacs Org-mode as input files.  (As of
-2010-08-14, MathJax is used by default with HTML exports in the
-current Org development version.)
-
-Optionally, references to the math fonts used will be converted to
-"data:" URIs, thus embedding the font data into the HTML file itself.
-(see [[http://en.wikipedia.org/wiki/Data_URI_scheme]])
-
-The code is licensed under the GNU General Public License version
-2, or, at your option, any later version.
-
-
-* Usage
-  To run Static MathJax, an existing XULRunner installation is
-  required. From the directory to which you unpacked Static MathJax,
-  run:
-    
-  xulrunner application.ini <--embed-fonts | --final-mathjax-url <URL>>
-  <input file> <output file>
-
-  If you prefer to call "staticmathjax" instead of "xulrunner
-  application.ini", link xulrunner-stub into the directory:
-  ln /usr/lib/xulrunner-1.9.2.8/xulrunner-stub ./staticmathjax
-  
-  - input file :: 
-      name of the input file (the result of a HTML export
-      from Org-mode). It is assumed that this file uses the
-         UTF-8 character encoding.
-
-  - output file ::
-      name of the output file.
-
-  - --embed-fonts :: 
-      if specified, the math fonts will be embedded into
-         the output file using data: URIs
-
-  - --final-mathjax-url <URL> :: 
-         if --embed-fonts is not specified, this
-      must be the URL to a MathJax installation folder (e.g. "MathJax"
-      if MathJax is installed in a subdirectory, or
-      "https://orgmode.org/mathjax"; to use the version hosted on the Org
-      website.
-         
-         All references to math fonts in the output file will point to
-         this directory.
-
-* Caveats
-  
-  The input file must not use a MathJax installation on the
-  web. Otherwise, due to a security feature of Firefox, MathJax will
-  fallback to image fonts.  If you have unpacked MathJax to a
-  subdirectory "MathJax", specify the following in your Org file:
-  
-  #+MathJax: path:"MathJax"
-
-  The math is rendered in Firefox, so MathJax applies its
-  Firefox-specific settings. When viewing the output files in other
-  browsers, it will look slightly different than the result that
-  running MathJax in that browser would produce.
-
-  Internet Explorer does not use the correct font, because it only
-  supports the EOT font format. For all other browsers (including
-  Firefox), MathJax uses the OTF font format.
-  
-  Embedding fonts into the HTML file wastes some space due to the
-  base64 encoding used in data: URIs.
-
-  I have found no way to access stdout or set an exit code in an
-  XULRunner app, so any code which calls Static MathJax has no idea if
-  processing was successful and when an error occurs, graphical
-  message boxes are displayed.
diff --git a/contrib/scripts/staticmathjax/application.ini 
b/contrib/scripts/staticmathjax/application.ini
deleted file mode 100644
index 522376d..0000000
--- a/contrib/scripts/staticmathjax/application.ini
+++ /dev/null
@@ -1,11 +0,0 @@
-[App]
-Vendor=Jan Boecker
-Name=StaticMathJax
-Version=0.2
-BuildID=2
-Copyright=Copyright (c) 2010, 2013 Jan Boecker
-ID=xulapp@jboecker.de
-
-[Gecko]
-MinVersion=1.8
-
diff --git a/contrib/scripts/staticmathjax/chrome/chrome.manifest 
b/contrib/scripts/staticmathjax/chrome/chrome.manifest
deleted file mode 100644
index a05d8c8..0000000
--- a/contrib/scripts/staticmathjax/chrome/chrome.manifest
+++ /dev/null
@@ -1 +0,0 @@
-content staticmathjax file:content/
diff --git a/contrib/scripts/staticmathjax/chrome/content/main.js 
b/contrib/scripts/staticmathjax/chrome/content/main.js
deleted file mode 100644
index 2e71f3b..0000000
--- a/contrib/scripts/staticmathjax/chrome/content/main.js
+++ /dev/null
@@ -1,198 +0,0 @@
-var docFrame;
-var logtextbox;
-var destFile;
-var embedFonts = false;
-var finalMathJaxURL = null;
-
-function log(text)
-{
-       logtextbox.setAttribute("value", logtextbox.getAttribute("value") + 
"\n" + text);
-}
-
-function init()
-{
-       try {
-               docFrame = document.getElementById("docFrame");
-               logtextbox = document.getElementById("logtextbox");
-
-               // parse command line arguments
-               var cmdLine = window.arguments[0];
-               cmdLine = 
cmdLine.QueryInterface(Components.interfaces.nsICommandLine);
-               
-               embedFonts = cmdLine.handleFlag("embed-fonts", false);
-               finalMathJaxURL = 
cmdLine.handleFlagWithParam("final-mathjax-url", false);
-               
-               if (!embedFonts && !finalMathJaxURL) {
-                       alert("You must eiher specify --embed-fonts or 
--final-mathjax-url");
-                       window.close();
-                       return;
-               }
-               
-               sourceFilePath = cmdLine.getArgument(0);
-               destFilePath = cmdLine.getArgument(1);
-               if ( !sourceFilePath || !destFilePath ) {
-                       alert("Not enough parameters, expecting two 
arguments:\nInput file, output file");
-                       window.close();
-                       return;
-               }
-               
-               sourceFile = cmdLine.resolveFile(sourceFilePath);
-               if (! (sourceFile.exists() && sourceFile.isFile()) ) {
-                       alert("Invalid source file path.");
-                       window.close();
-                       return;
-               }
-               sourceURI = cmdLine.resolveURI(sourceFilePath);
-               
-               // create a nsIFile object for the output file
-               try{
-                       destFile = 
cmdLine.resolveURI(destFilePath).QueryInterface(Components.interfaces.nsIFileURL).file;
-               }catch(e){
-                       alert("Invalid destination file.\n\nException:\n" + e);
-                       window.close();
-                       return;
-               }
-               
-               // add iframeLoaded() as an onload event handler, then navigate 
to the source file
-               docFrame.addEventListener("DOMContentLoaded", iframeLoaded, 
true);
-               docFrame.setAttribute("src", sourceURI.spec);
-
-       } catch (e) {
-               alert("Error in init():\n\n" + e);
-               window.close();
-               return;
-       }
-}
-
-function iframeLoaded()
-{
-       /*
-       // print every MathJax signal to the log
-       docFrame.contentWindow.MathJax.Hub.Startup.signal.Interest(
-       function (message) {log("Startup: "+message)}
-       );
-       docFrame.contentWindow.MathJax.Hub.signal.Interest(
-       function (message) {log("Hub: "+message)}
-       );
-       */
-
-       // tell MathJax to call serialize() when finished
-       docFrame.contentWindow.MathJax.Hub.Register.StartupHook("End", 
function() {serialize();});
-}
-
-function fileURLtoDataURI(url)
-{
-       var ios = Components.classes["@mozilla.org/network/io-service;1"]
-               .getService(Components.interfaces.nsIIOService);
-       var url_object = ios.newURI(url, "", null);
-       var file = 
url_object.QueryInterface(Components.interfaces.nsIFileURL).file;
-                                                               
-       var data = "";  
-       var fstream = 
Components.classes["@mozilla.org/network/file-input-stream;1"].  
-               createInstance(Components.interfaces.nsIFileInputStream);
-       fstream.init(file, -1, -1, false);
-       var bstream = Components.classes["@mozilla.org/binaryinputstream;1"].  
-               createInstance(Components.interfaces.nsIBinaryInputStream);  
-       bstream.setInputStream(fstream);  
-                               
-       var bytes = bstream.readBytes(bstream.available());
-       b64bytes = btoa(bytes);
-
-       return "data:;base64," + b64bytes;
-
-}
-
-function serialize()
-{
-       var MathJaxURL = docFrame.contentWindow.MathJax.Hub.config.root;
-
-       var searchURIList = new Array();
-       var replacementURIList = new Array();
-       
-       log("serialize: preprocessing");
-
-       // remove the MathJax status message window
-       msgdiv = docFrame.contentDocument.getElementById("MathJax_Message");
-       msgdiv.parentNode.removeChild(msgdiv);
-       
-       /* Loop through all CSS rules to find all @font-face rules.
-          At this point, they refer to local absolute paths using file:// URLs.
-          Replace them either with appropriate URLs relative to finalMathJaxURL
-          or with data URIs. */
-       
-       for (var i = 0; i<docFrame.contentDocument.styleSheets.length; i++) {
-               var stylesheet = docFrame.contentDocument.styleSheets[i];
-               
-               for (var j=0; j< stylesheet.cssRules.length; j++) {
-                       var rule = stylesheet.cssRules[j];
-                       if (rule.cssText.match("font-face")) {
-
-                               url = rule.style.getPropertyValue("src");
-                               url = url.match(/url\(\"(.+)\"\)/)[1];
-                               
-                               // Since the properties seem read-only here, we 
populate
-                               // searchURIList and replacementURIList to do 
text substitution
-                               // after serialization
-                               searchURIList.push(url);
-                               if (embedFonts) {
-                                       
replacementURIList.push(fileURLtoDataURI(url));
-                               } else {
-                                       
replacementURIList.push(url.replace(MathJaxURL, finalMathJaxURL));
-                               }                               
-                       }
-               }
-       }
-
-
-       // find and remove the MathJax <script> tag
-       try{
-               var scriptTags = 
docFrame.contentDocument.getElementsByTagName("script");
-               for (var i=0; i<scriptTags.length; i++) {
-                       if (scriptTags[i].getAttribute("src") && 
scriptTags[i].getAttribute("src").match(/MathJax.js/i))
-                               
scriptTags[i].parentNode.removeChild(scriptTags[i]);
-               }
-       }catch(e){alert(e);}
-
-       log("serialize: serializing");
-
-       var serializer = new XMLSerializer();
-       var xhtml = serializer.serializeToString(docFrame.contentDocument);
-       
-       log("serialize: postprocessing");
-       // make the MathJax URL relative again
-       //      xhtml = xhtml.replace(findMathJaxURL, "MathJax");
-       
-       try{
-               r1 = 
RegExp("&lt;!--/\\*--&gt;&lt;!\\[CDATA\\[/\\*&gt;&lt;!--\\*/", "g");
-               xhtml = xhtml.replace(r1, "");
-               r2 = RegExp("/\\*\\]\\]&gt;\\*/--&gt;", "g");
-               xhtml = xhtml.replace(r2, "");
-               r3 = RegExp("/\\*\\]\\]&gt;\\*///--&gt;", "g");
-               xhtml = xhtml.replace(r3, "");
-       }catch(e){alert(e);}
-       for (var i=0; i<searchURIList.length; i++)
-               xhtml = xhtml.replace(searchURIList[i], replacementURIList[i]);
-       
-       save(xhtml);
-       window.close();
-}
-
-function save(xhtml)
-{
-       try {
-               var foStream = 
Components.classes["@mozilla.org/network/file-output-stream;1"].
-                       
createInstance(Components.interfaces.nsIFileOutputStream);
-
-               foStream.init(destFile, 0x02 | 0x08 | 0x20, 0666, 0); 
-               // write, create, truncate
-
-               // write in UTF-8 encoding
-               var converter = 
Components.classes["@mozilla.org/intl/converter-output-stream;1"].
-                       
createInstance(Components.interfaces.nsIConverterOutputStream);
-               converter.init(foStream, "UTF-8", 0, 0);
-               converter.writeString(xhtml);
-               converter.close(); // this closes foStream
-       } catch (e) {
-               alert("Error in save():\n\n" + e);
-       }
-}
diff --git a/contrib/scripts/staticmathjax/chrome/content/main.xul 
b/contrib/scripts/staticmathjax/chrome/content/main.xul
deleted file mode 100644
index 35a00f2..0000000
--- a/contrib/scripts/staticmathjax/chrome/content/main.xul
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
-
-<window onload="init();" id="main" title="Static MathJax" width="300" 
height="300"
-xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";>
-
-<script language="JavaScript" src="chrome://staticmathjax/content/main.js"/>
-
-  <browser flex="1" id="docFrame" src="" style="background-color:white;"/>
-  <textbox flex="1" id="logtextbox" multiline="true" style="display:none;"/>
-</window>
diff --git a/contrib/scripts/staticmathjax/defaults/preferences/prefs.js 
b/contrib/scripts/staticmathjax/defaults/preferences/prefs.js
deleted file mode 100644
index 0532ce0..0000000
--- a/contrib/scripts/staticmathjax/defaults/preferences/prefs.js
+++ /dev/null
@@ -1 +0,0 @@
-pref("toolkit.defaultChromeURI", "chrome://staticmathjax/content/main.xul");
diff --git a/contrib/scripts/x11idle.c b/contrib/scripts/x11idle.c
deleted file mode 100644
index 22cefe1..0000000
--- a/contrib/scripts/x11idle.c
+++ /dev/null
@@ -1,28 +0,0 @@
-#include <X11/extensions/scrnsaver.h>
-#include <stdio.h>
-
-/* Based on code from
- * http://coderrr.wordpress.com/2008/04/20/getting-idle-time-in-unix/
- *
- * compile with 'gcc -l Xss x11idle.c -o x11idle' and copy x11idle into your
- * path
- */
-main() {
-    XScreenSaverInfo *info = XScreenSaverAllocInfo();
-    //open the display specified by the DISPLAY environment variable
-    Display *display = XOpenDisplay(0);
-
-    //display could be null if there is no X server running
-    if (info == NULL || display == NULL) {
-    return -1;
-    }
-
-    //X11 is running, try to retrieve info
-    if (XScreenSaverQueryInfo(display, DefaultRootWindow(display), info) == 0) 
{
-       return -1;
-    }
-
-    //info was retrieved successfully, print idle time
-    printf("%lu\n", info->idle);
-    return 0;
-}
diff --git a/doc/Makefile b/doc/Makefile
index f6da9a1..b0255a8 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -28,9 +28,9 @@ guide::               orgguide.texi org-version.inc
 endif
 
 org.texi orgguide.texi:        org-manual.org org-guide.org
-       $(BATCH) \
-         --eval '(add-to-list '"'"'load-path "../lisp")' \
-         --eval '(load "../mk/org-fixup.el")' \
+       $(BATCH)                                      \
+         --eval '(add-to-list `load-path "../lisp")' \
+         --eval '(load "../mk/org-fixup.el")'        \
          --eval '(org-make-manuals)'
 
 org-version.inc:       org.texi
@@ -58,6 +58,7 @@ clean:
              *.aux *.cp *.cps *.dvi *.fn *.fns *.ky *.kys *.pg *.pgs *.toc \
               *.tp *.tps *.vr *.vrs *.log *.ps
 cleanall:      clean
+       $(RM) org.texi orgguide.texi
        $(RMR) guide manual
 
 clean-install:
@@ -88,8 +89,8 @@ ifneq ($(SERVERMK),)
 endif
 
 %_letter.tex:  %.tex
-       $(BATCH) \
-         --eval '(add-to-list '"'"'load-path "../lisp")' \
-         --eval '(load "org-compat.el")' \
-         --eval '(load "../mk/org-fixup.el")' \
+       $(BATCH)                                      \
+         --eval '(add-to-list `load-path "../lisp")' \
+         --eval '(load "org-compat.el")'             \
+         --eval '(load "../mk/org-fixup.el")'        \
          --eval '(org-make-letterformat "$(<F)" "$(@F)")'
diff --git a/doc/fdl.org b/doc/fdl.org
index 30c7d93..2cc082b 100644
--- a/doc/fdl.org
+++ b/doc/fdl.org
@@ -7,7 +7,7 @@ Version 1.3, 3 November 2008
 
 #+begin_verse
 Copyright \copy{} 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc.
-http://fsf.org/
+https://fsf.org/
 
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.
@@ -404,7 +404,7 @@ of this license document, but changing it is not allowed.
     the GNU Free Documentation License from time to time.  Such new
     versions will be similar in spirit to the present version, but may
     differ in detail to address new problems or concerns.  See
-    http://www.gnu.org/copyleft/.
+    https://www.gnu.org/copyleft/.
 
     Each version of the License is given a distinguishing version
     number.  If the Document specifies that a particular numbered
diff --git a/doc/htmlxref.cnf b/doc/htmlxref.cnf
index 13aa8ce..a5eb584 100644
--- a/doc/htmlxref.cnf
+++ b/doc/htmlxref.cnf
@@ -1,2 +1,2 @@
-calc           mono    
http://www.gnu.org/software/emacs/manual/html_mono/calc.html
-calc           node    http://www.gnu.org/software/emacs/manual/html_node/calc/
+calc           mono    
https://www.gnu.org/software/emacs/manual/html_mono/calc.html
+calc           node    
https://www.gnu.org/software/emacs/manual/html_node/calc/
diff --git a/doc/org-guide.org b/doc/org-guide.org
index 06b726b..aa793f1 100644
--- a/doc/org-guide.org
+++ b/doc/org-guide.org
@@ -59,7 +59,6 @@ subdirectories to the Emacs load path.  To do this, add the 
following
 line to your Emacs init file:
 
 : (add-to-list 'load-path "~/path/to/orgdir/lisp")
-: (add-to-list 'load-path "~/path/to/orgdir/contrib/lisp" t)
 
 #+texinfo: @noindent
 If you have been using git or a tar ball to get Org, you need to run
@@ -77,9 +76,9 @@ keys for three commands that are useful in any Emacs buffer, 
not just
 Org buffers.  Please choose suitable keys yourself.
 
 #+begin_src emacs-lisp
-(global-set-key (kbd "C-c l") 'org-store-link)
-(global-set-key (kbd "C-c a") 'org-agenda)
-(global-set-key (kbd "C-c c") 'org-capture)
+(global-set-key (kbd "C-c l") #'org-store-link)
+(global-set-key (kbd "C-c a") #'org-agenda)
+(global-set-key (kbd "C-c c") #'org-capture)
 #+end_src
 
 Files with extension =.org= will be put into Org mode automatically.
@@ -169,8 +168,8 @@ Org uses just two commands, bound to {{{kbd(TAB)}}} and
 When Emacs first visits an Org file, the global state is set to
 OVERVIEW, i.e., only the top level headlines are visible.  This can be
 configured through the variable ~org-startup-folded~, or on a per-file
-basis by adding a =STARTUP= keyword to =overview=, =content=, or
-=showall=, like this:
+basis by adding a =STARTUP= keyword to =overview=, =content=,
+=showall=, =showeverything= or =show<n>levels= (n = 2..5) like this:
 
 : #+STARTUP: content
 
diff --git a/doc/org-manual.org b/doc/org-manual.org
index f40f68b..4366315 100644
--- a/doc/org-manual.org
+++ b/doc/org-manual.org
@@ -82,11 +82,8 @@ probably do not need to install it.  Most users will simply 
activate
 Org and begin exploring its many features.
 
 If, for one reason or another, you want to install Org on top of this
-pre-packaged version, there are three ways to do it:
-
-- by using the Emacs package system;
-- by downloading Org as an archive; or
-- by using Org's git repository.
+pre-packaged version, you can use the Emacs package system or clone
+Org's git repository.
 
 We *strongly recommend* sticking to a single installation method.
 
@@ -106,32 +103,6 @@ visited, i.e., where no Org built-in function have been 
loaded.
 Otherwise autoload Org functions will mess up the installation.
 #+end_quote
 
-If you want to use Org's package repository, check out the 
[[https://orgmode.org/elpa.html][Org ELPA
-page]].
-
-*** Downloading Org as an archive
-:PROPERTIES:
-:UNNUMBERED: notoc
-:END:
-
-You can download Org latest release from [[https://orgmode.org/][Org's 
website]].  In this case,
-make sure you set the load path correctly in your Emacs init file:
-
-#+begin_src emacs-lisp
-(add-to-list 'load-path "~/path/to/orgdir/lisp")
-#+end_src
-
-The downloaded archive contains contributed libraries that are not
-included in Emacs.  If you want to use them, add the =contrib/=
-directory to your load path:
-
-#+begin_src emacs-lisp
-(add-to-list 'load-path "~/path/to/orgdir/contrib/lisp" t)
-#+end_src
-
-Optionally, you can compile the files and/or install them in your
-system.  Run =make help= to list compilation and installation options.
-
 *** Using Org's git repository
 :PROPERTIES:
 :UNNUMBERED: notoc
@@ -161,6 +132,16 @@ list of compilation/installation options.
 For more detailed explanations on Org's build system, please check the
 Org Build System page on 
[[https://orgmode.org/worg/dev/org-build-system.html][Worg]].
 
+*** Installing Org's contributed packages
+:PROPERTIES:
+:UNNUMBERED: notoc
+:END:
+
+Org's repository used to contain =contrib/= directory for add-ons
+contributed by others.  As of Org 9.5, the directory has bee moved to
+this new dedicated [[https://git.sr.ht/~bzg/org-contrib][org-contrib]] 
repository, which you can install
+separately.
+
 ** Activation
 :PROPERTIES:
 :DESCRIPTION: How to activate Org for certain buffers.
@@ -189,9 +170,9 @@ to globally available keys, like the ones reserved for 
users (see
 please modify the keys to your own liking.
 
 #+begin_src emacs-lisp
-(global-set-key (kbd "C-c l") 'org-store-link)
-(global-set-key (kbd "C-c a") 'org-agenda)
-(global-set-key (kbd "C-c c") 'org-capture)
+(global-set-key (kbd "C-c l") #'org-store-link)
+(global-set-key (kbd "C-c a") #'org-agenda)
+(global-set-key (kbd "C-c c") #'org-capture)
 #+end_src
 
 #+cindex: Org mode, turning on
@@ -273,7 +254,6 @@ shown below.
 
 ;; Add latest Org mode to load path.
 (add-to-list 'load-path (expand-file-name "/path/to/org-mode/lisp"))
-(add-to-list 'load-path (expand-file-name "/path/to/org-mode/contrib/lisp" t))
 #+end_src
 
 If an error occurs, a "backtrace" can be very useful---see below on
@@ -577,6 +557,10 @@ buffer:
 ,#+STARTUP: overview
 ,#+STARTUP: content
 ,#+STARTUP: showall
+,#+STARTUP: show2levels
+,#+STARTUP: show3levels
+,#+STARTUP: show4levels
+,#+STARTUP: show5levels
 ,#+STARTUP: showeverything
 #+end_example
 
@@ -656,10 +640,10 @@ The following commands jump to other headlines in the 
buffer.
   where you can use the following keys to find your destination:
 
   #+attr_texinfo: :columns 0.3 0.7
-  | {{{kbd(TAB)}}}                  | Cycle visibility.               |
+  | {{{kbd(TAB)}}}            | Cycle visibility.               |
   | {{{kbd(DOWN)}}} / {{{kbd(UP)}}} | Next/previous visible headline. |
-  | {{{kbd(RET)}}}                  | Select this location.           |
-  | {{{kbd(/)}}}                    | Do a Sparse-tree search         |
+  | {{{kbd(RET)}}}            | Select this location.           |
+  | {{{kbd(/)}}}              | Do a Sparse-tree search         |
 
   #+texinfo: @noindent
   The following keys work if you turn off ~org-goto-auto-isearch~
@@ -667,9 +651,9 @@ The following commands jump to other headlines in the 
buffer.
   #+attr_texinfo: :columns 0.3 0.7
   | {{{kbd(n)}}} / {{{kbd(p)}}}   | Next/previous visible headline.    |
   | {{{kbd(f)}}} / {{{kbd(b)}}}   | Next/previous headline same level. |
-  | {{{kbd(u)}}}                  | One level up.                      |
+  | {{{kbd(u)}}}            | One level up.                      |
   | {{{kbd(0)}}} ... {{{kbd(9)}}} | Digit argument.                    |
-  | {{{kbd(q)}}}                  | Quit.                              |
+  | {{{kbd(q)}}}            | Quit.                              |
 
   #+vindex: org-goto-interface
   #+texinfo: @noindent
@@ -932,16 +916,16 @@ commands can be accessed through a dispatcher:
   #+kindex: C-c / /
   #+findex: 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 the body of an entry, headline and body are made
-  visible.  In order to provide minimal context, also the full
-  hierarchy of headlines above the match is shown, as well as the
-  headline following the match.  Each match is also highlighted; the
-  highlights disappear when the buffer is changed by an editing
-  command, or by pressing {{{kbd(C-c C-c)}}}[fn:8].  When called with
-  a {{{kbd(C-u)}}} prefix argument, previous highlights are kept, so
-  several calls to this command can be stacked.
+  Prompts for a regexp (see [[*Regular Expressions]]) 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 the body of an entry, headline
+  and body are made visible.  In order to provide minimal context,
+  also the full hierarchy of headlines above the match is shown, as
+  well as the headline following the match.  Each match is also
+  highlighted; the highlights disappear when the buffer is changed by
+  an editing command, or by pressing {{{kbd(C-c C-c)}}}[fn:8].  When
+  called with a {{{kbd(C-u)}}} prefix argument, previous highlights
+  are kept, so several calls to this command can be stacked.
 
 - {{{kbd(M-g n)}}} or {{{kbd(M-g M-n)}}} (~next-error~) ::
 
@@ -1805,7 +1789,7 @@ mode with {{{kbd(M-x orgtbl-mode)}}}.  To turn it on by 
default, for
 example in Message mode, use
 
 #+begin_src emacs-lisp
-(add-hook 'message-mode-hook 'turn-on-orgtbl)
+(add-hook 'message-mode-hook #'turn-on-orgtbl)
 #+end_src
 
 Furthermore, with some special setup, it is possible to maintain
@@ -2074,6 +2058,14 @@ variable ~org-calc-default-modes~.
 
   Fraction and symbolic modes of Calc.
 
+- =u= ::
+
+  Units simplification mode of Calc.  Calc is also a symbolic
+  calculator and is capable of working with values having a unit,
+  represented with numerals followed by a unit string in Org table
+  cells.  This mode instructs Calc to simplify the units in the
+  computed expression before returning the result.
+
 - =T=, =t=, =U= ::
 
   Duration computations in Calc or Lisp, [[*Durations and time values]].
@@ -2169,38 +2161,54 @@ It is also possible to write a formula in Emacs Lisp.  
This can be
 useful for string manipulation and control structures, if Calc's
 functionality is not enough.
 
-If a formula starts with a single-quote followed by an opening
-parenthesis, then it is evaluated as a Lisp form.  The evaluation
-should return either a string or a number.  Just as with Calc
-formulas, you can specify modes and a ~printf~ format after
-a semicolon.
+A formula is evaluated as a Lisp form when it starts with a
+single-quote followed by an opening parenthesis.  Cell table
+references are interpolated into the Lisp form before execution.  The
+evaluation should return either a string or a number.  Evaluation
+modes and a ~printf~ format used to render the returned values can be
+specified after a semicolon.
+
+By default, references are interpolated as literal Lisp strings: the
+field content is replaced in the Lisp form stripped of leading and
+trailing white space and surrounded in double-quotes.  For example:
 
-With Emacs Lisp forms, you need to be conscious about the way field
-references are interpolated into the form.  By default, a reference is
-interpolated as a Lisp string (in double-quotes) containing the field.
-If you provide the =N= mode switch, all referenced elements are
-numbers---non-number fields will be zero---and interpolated as Lisp
-numbers, without quotes.  If you provide the =L= flag, all fields are
-interpolated literally, without quotes.  For example, if you want a
-reference to be interpreted as a string by the Lisp form, enclose the
-reference operator itself in double-quotes, like ="$3"=.  Ranges are
-inserted as space-separated fields, so you can embed them in list or
-vector syntax.
+: '(concat $1 $2)
 
-Here are a few examples---note how the =N= mode is used when we do
-computations in Lisp:
+#+texinfo: @noindent
+concatenates the content of columns 1 and column 2.
 
-- ='(concat (substring $1 1 2) (substring $1 0 1) (substring $1 2))= ::
+When the =N= flag is used, all referenced elements are parsed as
+numbers and interpolated as Lisp numbers, without quotes.  Fields that
+cannot be parsed as numbers are interpolated as zeros.  For example:
 
-  Swap the first two characters of the content of column 1.
+: '(+ $1 $2);N
 
-- ='(+ $1 $2);N= ::
+#+texinfo: @noindent
+adds columns 1 and 2, equivalent to Calc's =$1+$2=.  Ranges are
+inserted as space-separated fields, so they can be embedded in list or
+vector syntax.  For example:
 
-  Add columns 1 and 2, equivalent to Calc's =$1+$2=.
+: '(apply '+ '($1..$4));N
 
-- ='(apply '+ '($1..$4));N= ::
+#+texinfo: @noindent
+computes the sum of columns 1 to 4, like Calc's =vsum($1..$4)=.
+
+When the =L= flag is used, all fields are interpolated literally: the
+cell content is replaced in the Lisp form stripped of leading and
+trailing white space and without quotes.  If a reference is intended
+to be interpreted as a string by the Lisp form, the reference operator
+itself should be enclosed in double-quotes, like ="$3"=.  The =L= flag
+is useful when strings and numbers are used in the same Lisp form.  For
+example:
 
-  Compute the sum of columns 1 to 4, like Calc's =vsum($1..$4)=.
+: '(substring "$1" $2 $3);L
+
+#+texinfo: @noindent
+extracts the part of the string in column 1 between the character
+positions specified in the integers in column 2 and 3 and it is easier
+to read than the equivalent:
+
+: '(substring $1 (string-to-number $2) (string-to-number $3))
 
 *** Durations and time values
 :PROPERTIES:
@@ -2797,7 +2805,7 @@ either graphically or in ASCII art.
 
 #+cindex: @samp{PLOT}, keyword
 Org Plot can produce 2D and 3D graphs of information stored in Org
-tables using [[http://www.gnuplot.info/][Gnuplot]] and 
[[http://cars9.uchicago.edu/~ravel/software/gnuplot-mode.html][Gnuplot mode]].  
To see this in action, ensure
+tables using [[https://www.gnuplot.info/][Gnuplot]] and 
[[http://cars9.uchicago.edu/~ravel/software/gnuplot-mode.html][Gnuplot mode]].  
To see this in action, ensure
 that you have both Gnuplot and Gnuplot mode installed on your system,
 then call {{{kbd(C-c \quot g)}}} or {{{kbd(M-x org-plot/gnuplot)}}} on the
 following table.
@@ -2813,6 +2821,19 @@ following table.
 | Morelia   |    257.56 |   17.67 |
 #+end_example
 
+Org Plot supports a range of plot types, and provides the ability to add more.
+For example, a radar plot can be generated like so:
+#+begin_example
+,#+PLOT: title:"An evaluation of plaintext document formats" transpose:yes 
type:radar min:0 max:4
+| Format            | Fine-grained-control | Initial Effort | Syntax 
simplicity | Editor Support | Integrations | Ease-of-referencing | Versatility |
+|-------------------+----------------------+----------------+-------------------+----------------+--------------+---------------------+-------------|
+| Word              |                    2 |              4 |                 
4 |              2 |            3 |                   2 |           2 |
+| LaTeX             |                    4 |              1 |                 
1 |              3 |            2 |                   4 |           3 |
+| Org Mode          |                    4 |              2 |               
3.5 |              1 |            4 |                   4 |           4 |
+| Markdown          |                    1 |              3 |                 
3 |              4 |            3 |                   3 |           1 |
+| Markdown + Pandoc |                  2.5 |            2.5 |               
2.5 |              3 |            3 |                   3 |           2 |
+#+end_example
+
 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 =PLOT= keyword
@@ -2843,9 +2864,15 @@ For more information and examples see the 
[[https://orgmode.org/worg/org-tutoria
   the third and fourth columns.  Defaults to graphing all other
   columns aside from the =ind= column.
 
+- transpose ::
+
+  When =y=, =yes=, or =t= attempt to transpose the table data before
+  plotting.  Also recognises the shorthand option =trans=.
+
 - =type= ::
 
-  Specify whether the plot is =2d=, =3d=, or =grid=.
+  Specify the type of the plot, by default one of  =2d=, =3d=, =radar=, or 
=grid=.
+  Available types can be customised with ~org-plot/preset-plot-types~.
 
 - =with= ::
 
@@ -2872,6 +2899,27 @@ For more information and examples see the 
[[https://orgmode.org/worg/org-tutoria
   When plotting =3d= or =grid= types, set this to =t= to graph a flat
   mapping rather than a =3d= slope.
 
+- min ::
+
+  Provides a minimum axis value that may be used by a plot type.
+  Implicitly assumes the =y= axis is being referred to.  Can
+  explicitly provide a value for a either the =x= or =y= axis with
+  =xmin= and =ymin=.
+
+- max ::
+
+  Provides a maximum axis value that may be used by a plot type.
+  Implicitly assumes the =y= axis is being referred to.  Can
+  explicitly provide a value for a either the =x= or =y= axis with
+  =xmax= and =ymax=.
+
+- ticks ::
+
+  Provides a desired number of axis ticks to display, that may be used
+  by a plot type.  If none is given a plot type that requires ticks
+  will use ~org--plot/sensible-tick-num~ to try to determine a good
+  value.
+
 - =timefmt= ::
 
   Specify format of Org mode timestamps as they will be parsed by
@@ -3113,14 +3161,14 @@ Here is the full set of built-in link types:
 
 - =file= ::
 
-   File links.  File name may be remote, absolute, or relative.
+  File links.  File name may be remote, absolute, or relative.
 
-   Additionally, you can specify a line number, or a text search.
-   In Org files, you may link to a headline name, a custom ID, or a
-   code reference instead.
+  Additionally, you can specify a line number, or a text search.
+  In Org files, you may link to a headline name, a custom ID, or a
+  code reference instead.
 
-   As a special case, "file" prefix may be omitted if the file name
-   is complete, e.g., it starts with =./=, or =/=.
+  As a special case, "file" prefix may be omitted if the file name
+  is complete, e.g., it starts with =./=, or =/=.
 
 - =attachment= ::
 
@@ -3224,9 +3272,10 @@ options:
 #+cindex: VM links
 #+cindex: Wanderlust links
 On top of these built-in link types, additional ones are available
-through the =contrib/= directory (see [[*Installation]]).  For example,
-these links to VM or Wanderlust messages are available when you load
-the corresponding libraries from the =contrib/= directory:
+through the =org-contrib= repository (see [[*Installation]]).  For
+example, these links to VM or Wanderlust messages are available when
+you load the corresponding libraries from the =org-contrib=
+repository:
 
 | =vm:folder=                            | VM folder link          |
 | =vm:folder#id=                         | VM message link         |
@@ -3243,7 +3292,7 @@ A link should be enclosed in double brackets and may 
contain
 descriptive text to be displayed instead of the URL (see [[*Link
 Format]]), for example:
 
-: [[http://www.gnu.org/software/emacs/][GNU Emacs]]
+: [[https://www.gnu.org/software/emacs/][GNU Emacs]]
 
 If the description is a file name or URL that points to an image, HTML
 export (see [[*HTML Export]]) inlines the image as a clickable button.  If
@@ -3291,8 +3340,9 @@ current buffer:
   =ID= property for the link[fn:29].  So using this command in Org
   buffers potentially creates two links: a human-readable link 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.
+  entry is moved from file to file.  The =ID= property can be either a
+  UUID (default) or a timestamp, depending on ~org-id-method~.  Later,
+  when inserting the link, you need to decide which one to use.
 
 - /Email/News clients: VM, Rmail, Wanderlust, MH-E, Gnus/ ::
 
@@ -3474,8 +3524,8 @@ generally, act on links.
 
   #+begin_src emacs-lisp
   (with-eval-after-load 'org
-    (define-key org-mode-map (kbd "M-n") 'org-next-link)
-    (define-key org-mode-map (kbd "M-p") 'org-previous-link))
+    (define-key org-mode-map (kbd "M-n") #'org-next-link)
+    (define-key org-mode-map (kbd "M-p") #'org-previous-link))
   #+end_src
 
 ** Using Links Outside Org
@@ -3516,7 +3566,7 @@ replacement text.  Here is an example:
 #+begin_src emacs-lisp
 (setq org-link-abbrev-alist
       '(("bugzilla"        . "http://10.1.2.9/bugzilla/show_bug.cgi?id=";)
-        ("Nu Html Checker" . "https://validator.w3.org/nu/?doc=%h";) 
+        ("Nu Html Checker" . "https://validator.w3.org/nu/?doc=%h";)
        ("duckduckgo"      . "https://duckduckgo.com/?q=%s";)
         ("omap"            . 
"http://nominatim.openstreetmap.org/search?q=%s&polygon=1";)
         ("ads"             . 
"https://ui.adsabs.harvard.edu/search/q=%20author%3A\"%s\"";)))
@@ -3536,7 +3586,7 @@ the link.  Such a function will be called with the tag as 
the only
 argument.
 
 With the above setting, you could link to a specific bug with
-=[[bugzilla:129]]=, search the web for =OrgMode= with =[[google:OrgMode]]=,
+=[[bugzilla:129]]=, search the web for =OrgMode= with =[[duckduckgo:OrgMode]]=,
 show the map location of the Free Software Foundation =[[gmap:51
 Franklin Street, Boston]]= or of Carsten office =[[omap:Science Park 904,
 Amsterdam, The Netherlands]]= and find out what the Org author is doing
@@ -3548,7 +3598,7 @@ can define them in the file with
 #+cindex: @samp{LINK}, keyword
 #+begin_example
 ,#+LINK: bugzilla  http://10.1.2.9/bugzilla/show_bug.cgi?id=
-,#+LINK: google    http://www.google.com/search?q=%s
+,#+LINK: duckduckgo https://duckduckgo.com/?q=%s
 #+end_example
 
 In-buffer completion (see [[*Completion]]) can be used after =[= to
@@ -3616,10 +3666,10 @@ link, together with explanations for each:
 
 - =/REGEXP/= ::
 
-  Do a regular expression search for {{{var(REGEXP)}}}.  This uses the
-  Emacs command ~occur~ to list all matches in a separate window.  If
-  the target file is in Org mode, ~org-occur~ is used to create
-  a sparse tree with the matches.
+  Do a regular expression search for {{{var(REGEXP)}}} (see [[*Regular
+  Expressions]]).  This uses the Emacs command ~occur~ to list all
+  matches in a separate window.  If the target file is in Org mode,
+  ~org-occur~ is used to create a sparse tree with the matches.
 
 As a degenerate case, a file link with an empty file name can be used
 to search the current file.  For example, =[[file:::find me]]= does
@@ -3944,9 +3994,9 @@ interpretation, but it means the same as =#+TODO=, or
 A setup for using several sets in parallel would be:
 
 #+begin_example
-,#+TODO: TODO | DONE
-,#+TODO: REPORT BUG KNOWNCAUSE | FIXED
-,#+TODO: | CANCELED
+,#+TODO: TODO(t) | DONE(d)
+,#+TODO: REPORT(r) BUG(b) KNOWNCAUSE(k) | FIXED(f)
+,#+TODO: | CANCELED(c)
 #+end_example
 
 #+cindex: completion, of option keywords
@@ -4070,7 +4120,7 @@ checkboxes is blocked from switching to DONE.
 
 If you need more complex dependency structures, for example
 dependencies between entries in different trees or files, check out
-the contributed module =org-depend.el=.
+the module =org-depend.el= in the =org-contrib= repository.
 
 ** Progress Logging
 :PROPERTIES:
@@ -4158,10 +4208,6 @@ example, with the setting
       '((sequence "TODO(t)" "WAIT(w@/!)" "|" "DONE(d!)" "CANCELED(c@)")))
 #+end_src
 
-#+texinfo: @noindent
-To record a timestamp without a note for TODO keywords configured with
-=@=, just type {{{kbd(C-c C-c)}}} to enter a blank note when prompted.
-
 #+vindex: org-log-done
 You not only define global TODO keywords and fast access keys, but
 also request that a time is recorded when the entry is set to =DONE=,
@@ -4181,6 +4227,9 @@ to a buffer:
 
 : #+TODO: TODO(t) WAIT(w@/!) | DONE(d!) CANCELED(c@)
 
+To record a timestamp without a note for TODO keywords configured with
+=@=, just type {{{kbd(C-c C-c)}}} to enter a blank note when prompted.
+
 #+cindex: @samp{LOGGING}, property
 In order to define logging settings that are local to a subtree or
 a single item, define a =LOGGING= property in this entry.  Any
@@ -4443,7 +4492,7 @@ all children are done, you can use the following setup:
   (let (org-log-done org-log-states)   ; turn off logging
     (org-todo (if (= n-not-done 0) "DONE" "TODO"))))
 
-(add-hook 'org-after-todo-statistics-hook 'org-summary-todo)
+(add-hook 'org-after-todo-statistics-hook #'org-summary-todo)
 #+end_src
 
 Another possibility is the use of checkboxes to identify (a hierarchy
@@ -4794,9 +4843,10 @@ In this interface, you can also use the following 
special keys:
 
   #+kindex: TAB
   Enter a tag in the minibuffer, even if the tag is not in the
-  predefined list.  You can complete on all tags present in the
-  buffer.  You can also add several tags: just separate them with
-  a comma.
+  predefined list.  You can complete on all tags present in the buffer
+  and globally pre-defined tags from ~org-tag-alist~ and
+  ~org-tag-persistent-alist~.  You can also add several tags: just
+  separate them with a comma.
 
 - {{{kbd(SPC)}}} ::
 
@@ -4931,8 +4981,9 @@ mutually exclusive.
 
 Furthermore, the members of a 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 curly brackets.  Here is an expanded example:
+tag structure (see [[*Regular Expressions]]).  The regular expressions in
+the group must be specified within curly brackets.  Here is an
+expanded example:
 
 #+begin_example
 ,#+TAGS: [ Vision : {V@.+} ]
@@ -5274,7 +5325,7 @@ single property:
   tree is created with all entries that define this property with the
   given value.  If you enclose the value in curly braces, it is
   interpreted as a regular expression and matched against the property
-  values.
+  values (see [[*Regular Expressions]]).
 
 ** Property Inheritance
 :PROPERTIES:
@@ -5737,8 +5788,8 @@ block.  If there is a =TBLFM= keyword after the table, 
the table is
 recalculated automatically after an update.
 
 An alternative way to capture and process property values into a table
-is provided by Eric Schulte's =org-collector.el=, which is
-a contributed package[fn:58].  It provides a general API to collect
+is provided by Eric Schulte's =org-collector.el=, which is a package
+in =org-contrib=[fn:58].  It provides a general API to collect
 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.
@@ -6022,6 +6073,7 @@ dash(es) as the separator in the former case and use =+= 
as the
 separator in the latter case, e.g.:
 
 | =11am-1:15pm=  | \rArr{} 11:00-13:15   |
+| =11h-13h15=    | \rArr{} same as above |
 | =11am--1:15pm= | \rArr{} same as above |
 | =11am+2:15=    | \rArr{} same as above |
 
@@ -7197,6 +7249,16 @@ special command:
   Copying works like refiling, except that the original note is not
   deleted.
 
+- {{{kbd(C-c C-M-w)}}} (~org-refile-reverse~) ::
+
+  #+kindex: C-c C-M-w
+  #+findex: org-refile-reverse
+  Works like refiling, except that it temporarily toggles how the
+  value of ~org-reverse-note-order~ applies to the current buffer.  So
+  if ~org-refile~ would append the entry as the last entry under the
+  target header, ~org-refile-reverse~ will prepend it as the first
+  entry, and vice-versa.
+
 ** Archiving
 :PROPERTIES:
 :DESCRIPTION: What to do with finished products.
@@ -7746,6 +7808,9 @@ Now lets look at the elements of a template definition.  
Each entry in
 
     Do not save the target file after finishing the capture.
 
+  - ~:refile-targets :: Temporarily set ~org-refile-targets~ to the
+    value of this property.
+
 **** Template expansion
 :PROPERTIES:
 :DESCRIPTION: Filling in information about time and context.
@@ -7804,6 +7869,10 @@ here:
 
   Like =%a=, but only insert the literal link.
 
+- =%L= ::
+
+  Like =%l=, but without brackets (the link content itself).
+
 - =%c= ::
 
   Current kill ring head.
@@ -7859,7 +7928,8 @@ here:
 
 - =%^{PROP}p= ::
 
-  Prompt the user for a value for property {{{var(PROP)}}}.
+  Prompt the user for a value for property {{{var(PROP)}}}.  You may
+  specify a default value with =%^{PROP|default}=.
 
 - =%^{PROMPT}= ::
 
@@ -8199,7 +8269,7 @@ To make Org mode take care of versioning of attachments 
for you, add
 the following to your Emacs config:
 
 #+begin_src emacs-lisp
-  (require 'org-attach-git)
+(require 'org-attach-git)
 #+end_src
 
 *** Attach from Dired
@@ -8259,7 +8329,7 @@ variable has detailed information.  With the following
 #+begin_src emacs-lisp
 (setq org-feed-alist
       '(("Slashdot"
-         "http://rss.slashdot.org/Slashdot/slashdot";
+         "https://rss.slashdot.org/Slashdot/slashdot";
          "~/txt/org/feeds.org" "Slashdot Entries")))
 #+end_src
 
@@ -8847,8 +8917,9 @@ only tags.
 
 #+cindex: regular expressions, with tags search
 Instead of a tag, you may also specify a regular expression enclosed
-in curly braces.  For example, =work+{^boss.*}= matches headlines that
-contain the tag =:work:= and any tag /starting/ with =boss=.
+in curly braces (see [[*Regular Expressions]]).  For example,
+=work+{^boss.*}= matches headlines that contain the tag =:work:= and
+any tag /starting/ with =boss=.
 
 #+cindex: group tags, as regular expressions
 Group tags (see [[*Tag Hierarchy]]) are expanded as regular expressions.
@@ -8888,7 +8959,7 @@ to test the value of a property.  Here is a complex 
example:
 
 #+begin_example
 +work-boss+PRIORITY="A"+Coffee="unlimited"+Effort<2
-         +With={Sarah|Denny}+SCHEDULED>="<2008-10-11>"
+         +With={Sarah\|Denny}+SCHEDULED>="<2008-10-11>"
 #+end_example
 
 #+texinfo: @noindent
@@ -8918,7 +8989,7 @@ So the search string in the example finds entries tagged 
=work= but
 not =boss=, which also have a priority value =A=, a =Coffee= property
 with the value =unlimited=, an =EFFORT= property that is numerically
 smaller than 2, a =With= property that is matched by the regular
-expression =Sarah|Denny=, and that are scheduled on or after October
+expression =Sarah\|Denny=, and that are scheduled on or after October
 11, 2008.
 
 You can configure Org mode to use property inheritance during
@@ -9296,16 +9367,16 @@ filter elements are accumulated.
 
   selects entries with category =work= and effort estimates below 10
   minutes, and deselects entries with tag =John= or matching the
-  regexp =plot=.  You can leave =+= out if that does not lead to
-  ambiguities.  The sequence of elements is arbitrary.  The filter
-  syntax assumes that there is no overlap between categories and tags.
-  Otherwise, tags take priority.  If you reply to the prompt with the
-  empty string, all filtering is removed.  If a filter is specified,
-  it replaces all current filters.  But if you call the command with
-  a double prefix argument, or if you add an additional =+= (e.g.,
-  =++work=) to the front of the string, the new filter elements are
-  added to the active ones.  A single prefix argument applies the
-  entire filter in a negative sense.
+  regexp =plot= (see [[*Regular Expressions]]).  You can leave =+= out if
+  that does not lead to ambiguities.  The sequence of elements is
+  arbitrary.  The filter syntax assumes that there is no overlap
+  between categories and tags.  Otherwise, tags take priority.  If you
+  reply to the prompt with the empty string, all filtering is removed.
+  If a filter is specified, it replaces all current filters.  But if
+  you call the command with a double prefix argument, or if you add an
+  additional =+= (e.g., =++work=) to the front of the string, the new
+  filter elements are added to the active ones.  A single prefix
+  argument applies the entire filter in a negative sense.
 
 - {{{kbd(|)}}} (~org-agenda-filter-remove-all~) ::
 
@@ -10863,7 +10934,7 @@ pretty output for a number of export back-ends.
 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
-[[http://www.mathjax.org][MathJax]] (see [[*Math formatting in HTML export]]) 
or transcode the math
+[[https://www.mathjax.org][MathJax]] (see [[*Math formatting in HTML export]]) 
or transcode the math
 into images (see [[*Previewing LaTeX fragments]]).
 
 LaTeX fragments do not need any special marking at all.  The following
@@ -10968,7 +11039,7 @@ current buffer with {{{kbd(M-x org-cdlatex-mode)}}}, or 
for all Org
 files with
 
 #+begin_src emacs-lisp
-(add-hook 'org-mode-hook 'turn-on-org-cdlatex)
+(add-hook 'org-mode-hook #'turn-on-org-cdlatex)
 #+end_src
 
 When this mode is enabled, the following features are present (for
@@ -11304,7 +11375,7 @@ The following command handles footnotes:
   #+attr_texinfo: :columns 0.1 0.9
   | {{{kbd(s)}}} | Sort the footnote definitions by reference sequence.        
       |
   | {{{kbd(r)}}} | Renumber the simple =fn:N= footnotes.                       
       |
-  | {{{kbd(S)}}} | Short for first {{{kbd(r)}}}, then {{{kbd(s)}}} action.     
       |
+  | {{{kbd(S)}}} | Short for first {{{kbd(r)}}}, then {{{kbd(s)}}} action.     
                   |
   | {{{kbd(n)}}} | Rename all footnotes into a =fn:1= ... =fn:n= sequence.     
       |
   | {{{kbd(d)}}} | Delete the footnote at point, including definition and 
references. |
 
@@ -11361,7 +11432,7 @@ Users can install libraries for additional formats from 
the Emacs
 packaging system.  For easy discovery, these packages have a common
 naming scheme: ~ox-NAME~, where {{{var(NAME)}}} is a format.  For
 example, ~ox-koma-letter~ for /koma-letter/ back-end.  More libraries
-can be found in the =contrib/= directory (see [[*Installation]]).
+can be found in the =org-contrib= repository (see [[*Installation]]).
 
 #+vindex: org-export-backends
 Org only loads back-ends for the following formats by default: ASCII,
@@ -11452,7 +11523,7 @@ further alter what is exported, and how.
 
   Toggle visible-only export.  This is useful for exporting only
   certain parts of an Org document by adjusting the visibility of
-  particular headings.
+  particular headings.  See also [[*Sparse Trees]].
 
 ** Export Settings
 :PROPERTIES:
@@ -11961,7 +12032,7 @@ example
 #+texinfo: @noindent
 becomes
 
-: Rose is red, violet's blue. Life's ordered: Org assists you.
+: Rose is red, violet's blue.  Life's ordered: Org assists you.
 
 As a special case, Org parses any replacement text starting with
 =(eval= as an Emacs Lisp expression and evaluates it accordingly.
@@ -12552,6 +12623,9 @@ settings described in [[*Export Settings]].
   multiple =DESCRIPTION= lines.  The exporter takes care of wrapping
   the lines properly.
 
+  The exporter includes a number of other meta tags, which can be customized
+  by modifying ~org-html-meta-tags~.
+
 - =HTML_DOCTYPE= ::
 
   #+cindex: @samp{HTML_DOCTYPE}, keyword
@@ -12693,8 +12767,8 @@ exports to:
 #+begin_src html
 <video controls="controls" width="350">
   <source src="movie.mp4" type="video/mp4">
-    <source src="movie.ogg" type="video/ogg">
-      <p>Your browser does not support the video tag.</p>
+  <source src="movie.ogg" type="video/ogg">
+  <p>Your browser does not support the video tag.</p>
 </video>
 #+end_src
 
@@ -12925,7 +12999,7 @@ as-is.
 
 #+vindex: org-html-mathjax-options~
 LaTeX math snippets (see [[*LaTeX fragments]]) can be displayed in two
-different ways on HTML pages.  The default is to use the 
[[http://www.mathjax.org][MathJax]],
+different ways on HTML pages.  The default is to use the 
[[https://www.mathjax.org][MathJax]],
 which should work out of the box with Org[fn:129][fn:130].  Some MathJax
 display options can be configured via ~org-html-mathjax-options~, or
 in the buffer.  For example, with the following settings,
@@ -13698,7 +13772,7 @@ objects through the attributes =:float= and =:options=. 
 For =:float=:
 The LaTeX export back-end passes string values in =:options= to LaTeX
 packages for customization of that specific source block.  In the
 example below, the =:options= are set for Minted.  Minted is a source
-code highlighting LaTeX package with many configurable options.
+code highlighting LaTeX package with many configurable options[fn:134].
 
 #+begin_example
 ,#+ATTR_LATEX: :options commentstyle=\bfseries
@@ -13801,6 +13875,95 @@ The LaTeX export back-end converts horizontal rules by 
the specified
 -----
 #+end_example
 
+*** Verse blocks in LaTeX export
+:PROPERTIES:
+:DESCRIPTION: Attributes specific to special blocks.
+:END:
+
+#+cindex: verse blocks, in @LaTeX{} export
+#+cindex: @samp{ATTR_LATEX}, keyword
+
+The LaTeX export back-end accepts four attributes for verse blocks:
+=:lines=, =:center=, =:versewidth= and =:latexcode=.  The three first
+require the external LaTeX package =verse.sty=, which is an extension
+of the standard LaTeX environment.
+
+- =:lines= :: To add marginal verse numbering.  Its value is an
+  integer, the sequence in which the verses should be numbered.
+- =:center= :: With value =t= all the verses on the page are optically
+  centered (a typographic convention for poetry), taking as a
+  reference the longest verse, which must be indicated by the
+  attribute =:versewidth=.
+- =:versewidth= :: Its value is a literal text string with the longest
+  verse.
+- =:latexcode= :: It accepts any arbitrary LaTeX code that can be
+  included within a LaTeX =verse= environment.
+
+A complete example with Shakespeare's first sonnet:
+
+#+begin_src org
+,#+ATTR_LATEX: :center t :latexcode \color{red} :lines 5
+,#+ATTR_LATEX: :versewidth Feedโ€™st thy lightโ€™s flame with self-substantial 
fuel,
+,#+BEGIN_VERSE
+From fairest creatures we desire increase,
+That thereby beautyโ€™s rose might never die,
+But as the riper should by time decease
+His tender heir might bear his memory
+But thou, contracted to thine own bright eyes,
+Feedโ€™st thy lightโ€™s flame with self-substantial fuel,
+Making a famine where abundance lies,
+Thyself thy foe, to thy sweet self too cruel.
+Thou that art now the worldโ€™s fresh ornament,
+And only herald to the gaudy spring,
+Within thine own bud buriest thy content,
+And, tender churl, makโ€™st waste in niggardly.
+Pity the world, or else this glutton be,
+To eat the worldโ€™s due, by the grave and thee.
+,#+END_VERSE
+#+end_src
+
+*** Quote blocks in LaTeX export
+:PROPERTIES:
+:DESCRIPTION: Attributes specific to quote blocks.
+:END:
+
+#+cindex: quote blocks, in @LaTeX{} export
+#+cindex: @samp{ATTR_LATEX}, keyword
+#+cindex: org-latex-default-quote-environment
+
+The LaTeX export back-end accepts two attributes for quote blocks:
+=:environment=, for an arbitrary quoting environment (the default
+value is that of ~org-latex-default-quote-environment~: ~"quote"~) and
+=:options=.  For example, to choose the environment =quotation=,
+included as an alternative to =quote= in standard LaTeX classes:
+
+#+begin_example
+,#+ATTR_LATEX: :environment quotation
+,#+BEGIN_QUOTE
+some text...
+,#+END_QUOTE
+#+end_example
+
+To choose the =foreigndisplayquote= environment, included in the LaTeX
+package =csquotes=, with the =german= option, use this syntax:
+
+#+begin_example
+,#+LATEX_HEADER:\usepackage[autostyle=true]{csquotes}
+,#+ATTR_LATEX: :environment foreigndisplayquote :options {german}
+,#+BEGIN_QUOTE
+some text in German...
+,#+END_QUOTE
+#+end_example
+
+#+texinfo: @noindent
+which is exported to LaTeX as
+
+#+begin_example
+\begin{foreigndisplayquote}{german}
+some text in German...
+\end{foreigndisplayquote}
+#+end_example
+
 ** Markdown Export
 :PROPERTIES:
 :DESCRIPTION: Exporting to Markdown.
@@ -13860,7 +14023,7 @@ a limit to a level before the absolute limit (see 
[[*Export Settings]]).
 
 The ODT export back-end handles creating of OpenDocument Text (ODT)
 format.  Documents created by this exporter use the
-{{{cite(OpenDocument-v1.2 specification)}}}[fn:134] and are compatible
+{{{cite(OpenDocument-v1.2 specification)}}}[fn:135] and are compatible
 with LibreOffice 3.4.
 
 *** Pre-requisites for ODT export
@@ -14261,7 +14424,7 @@ document in one of the following ways:
   variables ~org-latex-to-mathml-convert-command~ and
   ~org-latex-to-mathml-jar-file~.
 
-  If you prefer to use MathToWeb[fn:135] as your converter, you can
+  If you prefer to use MathToWeb[fn:136] as your converter, you can
   configure the above variables as shown below.
 
   #+begin_src emacs-lisp
@@ -14272,7 +14435,7 @@ document in one of the following ways:
   #+end_src
 
   #+texinfo: @noindent
-  or, to use LaTeXโ€‹ML[fn:136] instead,
+  or, to use LaTeXโ€‹ML[fn:137] instead,
 
   #+begin_src emacs-lisp
   (setq org-latex-to-mathml-convert-command
@@ -14591,7 +14754,7 @@ with the =#+ATTR_ODT= line.  For a discussion on 
default formatting of
 tables, see [[*Tables in ODT export]].
 
 This feature closely mimics the way table templates are defined in the
-OpenDocument-v1.2 specification[fn:137].
+OpenDocument-v1.2 specification[fn:138].
 
 #+vindex: org-odt-table-styles
 For quick preview of this feature, install the settings below and export the
@@ -14625,7 +14788,7 @@ templates, define new styles there.
 
 To use this feature proceed as follows:
 
-1. Create a table template[fn:138].
+1. Create a table template[fn:139].
 
    A table template is set of =table-cell= and =paragraph= styles for
    each of the following table cell categories:
@@ -14664,7 +14827,7 @@ To use this feature proceed as follows:
    =</office:automatic-styles>= element of the content template file
    (see [[x-orgodtcontenttemplate-xml][Factory styles]]).
 
-2. Define a table style[fn:139].
+2. Define a table style[fn:140].
 
    #+vindex: org-odt-table-styles
    To define a table style, create an entry for the style in the
@@ -15159,7 +15322,7 @@ To specify the author of the quotation, use the 
=:author= attribute.
 ,#+BEGIN_QUOTE
 The Lady of the Lake, her arm clad in the purest shimmering samite,
 held aloft Excalibur from the bosom of the water, signifying by divine
-providence that I, Arthur, was to carry Excalibur. That is why I am
+providence that I, Arthur, was to carry Excalibur.  That is why I am
 your king.
 ,#+END_QUOTE
 #+end_example
@@ -15422,7 +15585,7 @@ BACKEND is the export back-end being used, as a symbol."
   (org-map-entries
    (lambda () (delete-region (point) (line-beginning-position 2)))))
 
-(add-hook 'org-export-before-parsing-hook 'my-headline-removal)
+(add-hook 'org-export-before-parsing-hook #'my-headline-removal)
 #+end_src
 
 *** Filters
@@ -15778,7 +15941,7 @@ If you want to publish the Org file as an =.org= file 
but with
 ~org-org-publish-to-org~.  This produces =file.org= and puts it in the
 publishing directory.  If you want a htmlized version of this file,
 set the parameter ~:htmlized-source~ to ~t~.  It produces
-=file.org.html= in the publishing directory[fn:140].
+=file.org.html= in the publishing directory[fn:141].
 
 Other files like images only need to be copied to the publishing
 destination; for this you can use ~org-publish-attachment~.  For
@@ -16348,6 +16511,129 @@ of the commands above, or by customizing the variable
 particular if files include other files via =SETUPFILE= or =INCLUDE=
 keywords.
 
+* Citation handling
+:PROPERTIES:
+:DESCRIPTION: create, follow and export citations.
+:END:
+#+cindex: citation
+
+As of Org 9.5, a new library =oc.el= provides tooling to handle
+citations in Org via "citation processors" that offer some or all of
+the following capabilities:
+
+- "activate" :: Fontification, tooltip preview, etc.
+- "follow" :: At-point actions on citations via ~org-open-at-point~.
+- "insert" :: Add and edit citations via ~org-cite-insert~.
+- "export" :: Via different libraries for different target formats.
+
+The user can configure these with ~org-cite-active-processor~,
+~org-cite-follow-processor~, ~org-cite-insert-processor~, and
+~org-cite-export-processors~ respectively.
+
+The included "basic" processor provides all four capabilities.
+
+** Citations
+
+Before adding citations, first set one-or-more bibliographies, either
+globally with ~org-cite-global-bibliography~, or locally using one or
+more "bibliography" keywords.
+
+#+begin_example
+#+bibliography: SomeFile.bib
+#+bibliography: /some/other/file.json
+#+bibliography: "/some/file/with spaces/in its name.bib"
+#+end_example
+
+One can then insert and edit citations using ~org-cite-insert~, called
+with {{{kbd(M-x org-cite-insert)}}}.
+
+A /citation/ requires one or more citation /key(s)/, elements
+identifying a reference in the bibliography.
+
+- Each citation is surrounded by brackets and uses the =cite= type.
+
+- Each key starts with the character =@=.
+
+- Each key can be qualified by a /prefix/ (e.g. "see ") and/or a
+  /suffix/ (e.g. "p. 123"), giving informations useful or necessary fo
+  the comprehension of the citation but not included in the reference.
+
+- A single citation can cite more than one reference ; the keys are
+  separated by semicolons ; the formatting of such citation groups is
+  specified by the style.
+
+- One can also specify a stylistic variation for the citations by
+  inserting a =/= and a style name between the =cite= keyword and the
+  colon ; this usially makes sense only for the author-year styles.
+
+#+begin_example
+[cite/style:common prefix ;prefix @key suffix; ... ; common suffix]
+#+end_example
+
+The only mandatory elements are:
+
+- The =cite= keyword and the colon.
+- The =@= character immediately preceding each key.
+- The brackets surrounding the citation(s) (group).
+
+** Citation export processors
+
+Org currently includes the following export processors:
+
+- Two processors can export to a variety of formats, including =latex=
+  (and therefore =pdf=), =html=, =odt= and plain (UTF8) text:
+
+  - basic :: a basic export processors, well adapted to situations
+    where backward compatibility is not a requirement and formatting
+    needs are minimal;
+
+  - csl :: this export processor uses format files written in 
[[https://en.wikipedia.org/wiki/Citation_Style_Language][Citation
+    Style Language]] via 
[[https://github.com/andras-simonyi/citeproc-el][citeproc-el]];
+
+- In contrast, two other processors target LaTeX and LaTeX-derived
+  formats exclusively:
+
+  - natbib :: this export processor uses =bibtex=, the historical
+    bibliographic processor used with LaTeX, thus allowing the use of
+    data and style files compatible with this processor (including a
+    large number of publishers' styles).  It uses citation commands
+    implemented in the LaTeX package =natbib=, allowing more stylistic
+    variants that LaTeX's =\cite= command.
+
+  - biblatex :: this backend allows the use of data and formats
+    prepared for =biblatex=, an alternate bibliographic processor used
+    with LaTeX, which overcomes some serious =bibtex= limitations, but
+    has not (yet?) been widely adopted by publishers.
+
+The =#+cite_export:= keyword specifies the export processor and the
+citation (and possibly reference) style(s); for example (all arguments
+are optional)
+
+#+begin_example
+#+cite_export: basic author author-year
+#+end_example
+
+specifies the "basic" export processor with citations inserted as
+author's name and references indexed by author's names and year;
+
+#+begin_example
+#+cite_export: csl /some/path/to/vancouver-brackets.csl
+#+end_example
+
+specifies the "csl" processor and CSL style, which in this case
+defines numeric citations and numeric references according to the
+=Vancouver= specification (as style used in many medical journals),
+following a typesetting variation putting citations between brackets;
+
+#+begin_example
+#+cite_export: natbib kluwer
+#+end_example
+
+specifies the "natbib" export processor with a label citation style
+conformant to the Harvard style and the specification of the
+Wolkers-Kluwer publisher; since it relies on the =bibtex= processor of
+your LaTeX installation, it won't export to anything but PDF.
+
 * Working with Source Code
 :PROPERTIES:
 :DESCRIPTION: Export, evaluate, and tangle code blocks.
@@ -16737,7 +17023,11 @@ the =var= header argument.
 body.  {{{var(ASSIGN)}}} is a literal value, such as a string,
 a number, a reference to a table, a list, a literal example, another
 code block---with or without arguments---or the results of evaluating
-a code block.
+a code block.  {{{var(ASSIGN)}}} may specify a filename for references
+to elements in a different file, using a =:= to separate the filename
+from the reference.
+
+: :var NAME=FILE:REFERENCE
 
 Here are examples of passing values by reference:
 
@@ -16816,6 +17106,9 @@ Here are examples of passing values by reference:
   | two | 16 | 17 | 18 | 19 | 20 |
   #+end_example
 
+To refer to a table in another file, join the filename and table name with
+a colon, for example: =:var table=other-file.org:example-table=.
+
 - list ::
 
   A simple named list.
@@ -17157,13 +17450,13 @@ See [[*Languages]] to enable other languages.
 #+kindex: C-c C-v e
 #+findex: org-babel-execute-src-block
 Org provides many ways to execute code blocks.  {{{kbd(C-c C-c)}}} or
-{{{kbd(C-c C-v e)}}} with the point on a code block[fn:141] calls the
+{{{kbd(C-c C-v e)}}} with the point on a code block[fn:142] calls the
 ~org-babel-execute-src-block~ function, which executes the code in the
 block, collects the results, and inserts them in the buffer.
 
 #+cindex: @samp{CALL}, keyword
 #+vindex: org-babel-inline-result-wrap
-By calling a named code block[fn:142] from an Org mode buffer or
+By calling a named code block[fn:143] from an Org mode buffer or
 a table.  Org can call the named code blocks from the current Org mode
 buffer or from the "Library of Babel" (see [[*Library of Babel]]).
 
@@ -17364,7 +17657,7 @@ they are mutually exclusive.
 
 - =value= ::
 
-  Default for most Babel libraries[fn:142].  Functional mode.  Org
+  Default for most Babel libraries[fn:143].  Functional mode.  Org
   gets the value by wrapping the code in a function definition in the
   language of the source block.  That is why when using =:results
   value=, code should execute like a function and return a value.  For
@@ -17489,10 +17782,12 @@ default behavior is to automatically determine the 
result type.
   #+end_example
 
   #+cindex: @samp{file-desc}, header argument
-  The =file-desc= header argument defines the description (see
-  [[*Link Format]]) for the link.  If =file-desc= is present but has no value,
+  The =file-desc= header argument defines the description (see [[*Link
+  Format]]) for the link.  If =file-desc= is present but has no value,
   the =file= value is used as the link description.  When this
-  argument is not present, the description is omitted.
+  argument is not present, the description is omitted.  If you want to
+  provide the =file-desc= argument but omit the description, you can
+  provide it with an empty vector (i.e., :file-desc []).
 
   #+cindex: @samp{sep}, header argument
   By default, Org assumes that a table written to a file has
@@ -17550,7 +17845,7 @@ follows from the type specified above.
 
   #+begin_example
   ,#+begin_src shell :results file link :file "download.tar.gz"
-  wget -c "http://example.com/download.tar.gz";
+  wget -c "https://example.com/download.tar.gz";
   ,#+end_src
   #+end_example
 
@@ -17596,15 +17891,20 @@ value listed above.  E.g.,
 
 Handling options after collecting the results.
 
+- =replace= ::
+
+  Default.  Insert results in the Org buffer.  Remove previous
+  results.  Usage example: =:results output replace=.
+
 - =silent= ::
 
   Do not insert results in the Org mode buffer, but echo them in the
   minibuffer.  Usage example: =:results output silent=.
 
-- =replace= ::
+- =none= ::
 
-  Default.  Insert results in the Org buffer.  Remove previous
-  results.  Usage example: =:results output replace=.
+  Do not process results at all.  No inserting in the Org mode buffer
+  nor echo them in the minibuffer.  Usage example: =:results none=.
 
 - =append= ::
 
@@ -17930,35 +18230,8 @@ code block header arguments:
 #+cindex: source code, languages
 #+cindex: code block, languages
 
-Code blocks in the following languages are supported.
-
-#+attr_texinfo: :columns 0.25 0.25 0.25 0.20
-| Language   | Identifier    | Language       | Identifier   |
-|------------+---------------+----------------+--------------|
-| Asymptote  | =asymptote=   | Lisp           | =lisp=       |
-| Awk        | =awk=         | Lua            | =lua=        |
-| C          | =C=           | MATLAB         | =matlab=     |
-| C++        | =C++=[fn:143] | Mscgen         | =mscgen=     |
-| Clojure    | =clojure=     | Objective Caml | =ocaml=      |
-| CSS        | =css=         | Octave         | =octave=     |
-| D          | =D=[fn:144]   | Org mode       | =org=        |
-| ditaa      | =ditaa=       | Oz             | =oz=         |
-| Emacs Calc | =calc=        | Perl           | =perl=       |
-| Emacs Lisp | =emacs-lisp=  | Plantuml       | =plantuml=   |
-| Eshell     | =eshell=      | Processing.js  | =processing= |
-| Fortran    | =fortran=     | Python         | =python=     |
-| Gnuplot    | =gnuplot=     | R              | =R=          |
-| GNU Screen | =screen=      | Ruby           | =ruby=       |
-| Graphviz   | =dot=         | Sass           | =sass=       |
-| Haskell    | =haskell=     | Scheme         | =scheme=     |
-| Java       | =java=        | Sed            | =sed=        |
-| Javascript | =js=          | shell          | =sh=         |
-| LaTeX      | =latex=       | SQL            | =sql=        |
-| Ledger     | =ledger=      | SQLite         | =sqlite=     |
-| Lilypond   | =lilypond=    | Vala           | =vala=       |
-
-Additional documentation for some languages is at
-https://orgmode.org/worg/org-contrib/babel/languages.html.
+Code blocks in dozens of languages are supported.  See Worg for
+[[https://orgmode.org/worg/org-contrib/babel/languages/index.html][language 
specific documentation]].
 
 #+vindex: org-babel-load-languages
 By default, only Emacs Lisp is enabled for evaluation.  To enable or
@@ -18072,7 +18345,7 @@ for Python and Emacs Lisp languages.
 
 #+cindex: @samp{noweb-ref}, header argument
 Source code blocks can include references to other source code blocks,
-using a noweb[fn:145] style syntax:
+using a noweb[fn:144] style syntax:
 
 : <<CODE-BLOCK-ID>>
 
@@ -18583,14 +18856,14 @@ Org Tempo expands snippets to structures defined in
 ~org-structure-template-alist~ and ~org-tempo-keywords-alist~.  For
 example, {{{kbd(< s TAB)}}} creates a code block.  Enable it by
 customizing ~org-modules~ or add =(require 'org-tempo)= to your Emacs
-init file[fn:146].
+init file[fn:145].
 
 #+attr_texinfo: :columns 0.1 0.9
 | {{{kbd(a)}}} | =#+BEGIN_EXPORT ascii= ... =#+END_EXPORT= |
 | {{{kbd(c)}}} | =#+BEGIN_CENTER= ... =#+END_CENTER=       |
 | {{{kbd(C)}}} | =#+BEGIN_COMMENT= ... =#+END_COMMENT=     |
 | {{{kbd(e)}}} | =#+BEGIN_EXAMPLE= ... =#+END_EXAMPLE=     |
-| {{{kbd(E)}}} | =#+BEGIN_EXPORT= ... =#+END_EXPORT= |
+| {{{kbd(E)}}} | =#+BEGIN_EXPORT= ... =#+END_EXPORT=       |
 | {{{kbd(h)}}} | =#+BEGIN_EXPORT html= ... =#+END_EXPORT=  |
 | {{{kbd(l)}}} | =#+BEGIN_EXPORT latex= ... =#+END_EXPORT= |
 | {{{kbd(q)}}} | =#+BEGIN_QUOTE= ... =#+END_QUOTE=         |
@@ -18617,14 +18890,14 @@ the variable ~org-use-speed-commands~ to a non-~nil~ 
value.  To
 trigger a Speed Key, point must be at the beginning of an Org
 headline, before any of the stars.
 
-#+vindex: org-speed-commands-user
+#+vindex: org-speed-commands
 #+findex: org-speed-command-help
 Org comes with a pre-defined list of Speed Keys.  To add or modify
-Speed Keys, customize the variable, ~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
-point is at the beginning of an Org headline, shows currently active
-Speed Keys, including the user-defined ones.
+Speed Keys, customize the option ~org-speed-commands~.  For more
+details, see the variable's docstring.  With Speed Keys activated,
+{{{kbd(M-x org-speed-command-help)}}}, or {{{kbd(?)}}} when point is at the
+beginning of an Org headline, shows currently active Speed Keys,
+including the user-defined ones.
 
 ** A Cleaner Outline View
 :PROPERTIES:
@@ -18663,7 +18936,7 @@ in the desired amount with hard spaces and hiding 
leading stars.
 To display the buffer in the indented view, activate Org Indent minor
 mode, using {{{kbd(M-x org-indent-mode)}}}.  Text lines that are not
 headlines are prefixed with virtual spaces to vertically align with
-the headline text[fn:147].
+the headline text[fn:146].
 
 #+vindex: org-indent-indentation-per-level
 To make more horizontal space, the headlines are shifted by two
@@ -18691,15 +18964,15 @@ use =STARTUP= keyword as follows:
 
 It is possible to use hard spaces to achieve the indentation instead,
 if the bare ASCII file should have the indented look also outside
-Emacs[fn:148].  With Org's support, you have to indent all lines to
+Emacs[fn:147].  With Org's support, you have to indent all lines to
 line up with the outline headers.  You would use these
-settings[fn:149]:
+settings[fn:148]:
 
-  #+begin_src emacs-lisp
-  (setq org-adapt-indentation t
-        org-hide-leading-stars t
-        org-odd-levels-only t)
-  #+end_src
+#+begin_src emacs-lisp
+(setq org-adapt-indentation t
+      org-hide-leading-stars t
+      org-odd-levels-only t)
+#+end_src
 
 - /Indentation of text below headlines/ (~org-adapt-indentation~) ::
 
@@ -18956,11 +19229,15 @@ changes.
   | =overview=       | Top-level headlines only.  |
   | =content=        | All headlines.             |
   | =showall=        | No folding on any entry.   |
+  | =show2levels=    | Headline levels 1-2.       |
+  | =show3levels=    | Headline levels 1-3.       |
+  | =show4levels=    | Headline levels 1-4.       |
+  | =show5levels=    | Headline levels 1-5.       |
   | =showeverything= | Show even drawer contents. |
 
   #+vindex: org-startup-indented
   Dynamic virtual indentation is controlled by the variable
-  ~org-startup-indented~[fn:150].
+  ~org-startup-indented~[fn:149].
 
   | =indent=   | Start with Org Indent mode turned on.  |
   | =noindent= | Start with Org Indent mode turned off. |
@@ -19096,6 +19373,22 @@ changes.
   These lines set the TODO keywords and their interpretation in the
   current file.  The corresponding variable is ~org-todo-keywords~.
 
+** Regular Expressions
+:PROPERTIES:
+:DESCRIPTION: Elisp regular expressions.
+:END:
+#+cindex: regular expressions syntax
+#+cindex: regular expressions, in searches
+
+Org, as an Emacs mode, makes use of Elisp regular expressions for
+searching, matching and filtering.  Elisp regular expressions have a
+somewhat different syntax then some common standards.  Most notably,
+alternation is indicated using =\|= and matching groups are denoted by
+=\(...\)=.  For example the string =home\|work= matches either =home=
+or =work=.
+
+For more information, see [[info:emacs::Regexps][Regular Expressions in 
Emacs]].
+
 ** Org Syntax
 :PROPERTIES:
 :DESCRIPTION: Formal description of Org's syntax.
@@ -19572,10 +19865,19 @@ To use this feature from a browser, add a bookmark 
with an arbitrary
 name, e.g., =Org: store-link= and enter this as /Location/:
 
 #+begin_example
+javascript:location.href='org-protocol://store-link?' +
+      new URLSearchParams({url:location.href, title:document.title});
+#+end_example
+
+Title is an optional parameter.  Another expression was recommended earlier:
+
+#+begin_example
 javascript:location.href='org-protocol://store-link?url='+
       encodeURIComponent(location.href);
 #+end_example
 
+The latter form is compatible with older Org versions from 9.0 to 9.4.
+
 *** The ~capture~ protocol
 :PROPERTIES:
 :DESCRIPTION: Fill a buffer with external information.
@@ -19592,12 +19894,25 @@ To use this feature, add a bookmark with an arbitrary 
name, e.g.,
 =Org: capture=, and enter this as =Location=:
 
 #+begin_example
+javascript:location.href='org-protocol://capture?' +
+      new URLSearchParams({
+            template: 'x', url: window.location.href,
+            title: document.title, body: window.getSelection()});
+#+end_example
+
+You might have seen another expression:
+
+#+begin_example
 javascript:location.href='org-protocol://capture?template=x'+
       '&url='+encodeURIComponent(window.location.href)+
       '&title='+encodeURIComponent(document.title)+
       '&body='+encodeURIComponent(window.getSelection());
 #+end_example
 
+It is a bit more cluttered than the former one, but it is compatible
+with previous Org versions 9.0-9.4.  In these versions encoding of
+space as "+" character was not supported by URI decoder.
+
 #+vindex: org-protocol-default-template-key
 The capture template to be used can be specified in the bookmark (like
 =X= above).  If unspecified, the template key is set in the variable
@@ -19653,13 +19968,13 @@ click the bookmark and start editing.
 #+cindex: rewritten URL in open-source protocol
 #+cindex: protocol, open-source rewritten URL
 However, such mapping may not always yield the desired results.
-Suppose you maintain an online store located at =http://example.com/=.
+Suppose you maintain an online store located at =https://example.com/=.
 The local sources reside in =/home/user/example/=.  It is common
 practice to serve all products in such a store through one file and
 rewrite URLs that do not match an existing file on the server.  That
-way, a request to =http://example.com/print/posters.html= might be
+way, a request to =https://example.com/print/posters.html= might be
 rewritten on the server to something like
-=http://example.com/shop/products.php/posters.html.php=.  The
+=https://example.com/shop/products.php/posters.html.php=.  The
 ~open-source~ handler probably cannot find a file named
 =/home/user/example/print/posters.html.php= and fails.
 
@@ -19674,7 +19989,7 @@ adding ~:rewrites~ rules like this:
 #+begin_src emacs-lisp
 (setq org-protocol-project-alist
       '(("example.com"
-         :base-url "http://example.com/";
+         :base-url "https://example.com/";
          :working-directory "/home/user/example/"
          :online-suffix ".php"
          :working-suffix ".php"
@@ -19705,8 +20020,8 @@ an Org file that is part of a publishing project.
 :END:
 
 Org Crypt encrypts the text of an entry, but not the headline, or
-properties.  Behind the scene, it uses the Emacs EasyPG library to
-encrypt and decrypt files.
+properties.  Behind the scene, it uses the [[info:epa][Emacs EasyPG Library]] 
to
+encrypt and decrypt files, and EasyPG needs a correct [[info:gnupg][GnuPG]] 
setup.
 
 #+vindex: org-crypt-tag-matcher
 Any text below a headline that has a =crypt= tag is automatically
@@ -19779,7 +20094,7 @@ Tags]]) only for those set in these variables.
 
 #+vindex: org-mobile-directory
 The mobile application needs access to a file directory on
-a server[fn:151] to interact with Emacs.  Pass its location through
+a server[fn:150] to interact with Emacs.  Pass its location through
 the ~org-mobile-directory~ variable.  If you can mount that directory
 locally just set the variable to point to that directory:
 
@@ -19800,7 +20115,7 @@ With a public server, consider encrypting the files.  
Org also
 requires OpenSSL installed on the local computer.  To turn on
 encryption, set the same password in the mobile application and in
 Emacs.  Set the password in the variable
-~org-mobile-use-encryption~[fn:152].  Note that even after the mobile
+~org-mobile-use-encryption~[fn:151].  Note that even after the mobile
 application encrypts the file contents, the file name remains visible
 on the file systems of the local computer, the server, and the mobile
 device.
@@ -19816,15 +20131,15 @@ The command ~org-mobile-push~ copies files listed in
 ~org-mobile-files~ into the staging area.  Files include agenda files
 (as listed in ~org-agenda-files~).  Customize ~org-mobile-files~ to
 add other files.  File names are staged with paths relative to
-~org-directory~, so all files should be inside this directory[fn:153].
+~org-directory~, so all files should be inside this directory[fn:152].
 
 Push creates a special Org file =agendas.org= with custom agenda views
-defined by the user[fn:154].
+defined by the user[fn:153].
 
 Finally, Org writes the file =index.org=, containing links to other
 files.  The mobile application reads this file first from the server
 to determine what other files to download for agendas.  For faster
-downloads, it is expected to only read files whose checksums[fn:155]
+downloads, it is expected to only read files whose checksums[fn:154]
 have changed.
 
 *** Pulling from the mobile application
@@ -19841,7 +20156,7 @@ data in an inbox file format, through the following 
steps:
 
 1.
    #+vindex: org-mobile-inbox-for-pull
-   Org moves all entries found in =mobileorg.org=[fn:156] and appends
+   Org moves all entries found in =mobileorg.org=[fn:155] and appends
    them to the file pointed to by the variable
    ~org-mobile-inbox-for-pull~.  It should reside neither in the
    staging area nor on the server.  Each captured entry and each
@@ -19905,12 +20220,10 @@ https://orgmode.org/worg/doc.html#hooks.
 :END:
 #+cindex: add-on packages
 
-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
-https://orgmode.org.  See the =contrib/README= file in the source code
-directory for a list of contributed files.  Worg page with more
+Various authors wrote a large number of add-on packages for Org.  Some
+of these packages used to be part of the =org-mode= repository but are
+now hosted in a separate =org-contrib= repository
+[[https://git.sr.ht/~bzg/org-contrib][here]].  A Worg page with more
 information is at: https://orgmode.org/worg/org-contrib/.
 
 ** Adding Hyperlink Types
@@ -20137,9 +20450,9 @@ of these strategies:
 #+cindex: @LaTeX{}, and Orgtbl mode
 
 To wrap a source table in LaTeX, use the =comment= environment
-provided by =comment.sty=[fn:157].  To activate it, put
+provided by =comment.sty=[fn:156].  To activate it, put
 ~\usepackage{comment}~ in the document header.  Orgtbl mode inserts
-a radio table skeleton[fn:158] with the command {{{kbd(M-x
+a radio table skeleton[fn:157] with the command {{{kbd(M-x
 orgtbl-insert-radio-table)}}}, which prompts for a table name.  For
 example, if =salesfigures= is the name, the template inserts:
 
@@ -20158,7 +20471,7 @@ The line =#+ORGTBL: SEND= tells Orgtbl mode to use the 
function
 ~orgtbl-to-latex~ to convert the table to LaTeX format, then insert
 the table at the target (receive) location named =salesfigures=.  Now
 the table is ready for data entry.  It can even use spreadsheet
-features[fn:159]:
+features[fn:158]:
 
 #+begin_example
 % BEGIN RECEIVE ORGTBL salesfigures
@@ -20374,7 +20687,7 @@ Dynamic blocks, like any other block, can be narrowed 
with
 #+vindex: org-agenda-skip-function
 #+vindex: org-agenda-skip-function-global
 Org provides a special hook to further limit items in agenda views:
-~agenda~, ~agenda*~[fn:160], ~todo~, ~alltodo~, ~tags~, ~tags-todo~,
+~agenda~, ~agenda*~[fn:159], ~todo~, ~alltodo~, ~tags~, ~tags-todo~,
 ~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.
@@ -20417,7 +20730,7 @@ meaningful string suitable for the agenda view.
 #+vindex: org-agenda-skip-function
 Search for entries with a limit set on levels for the custom search.
 This is a general approach to creating custom searches in Org.  To
-include all levels, use =LEVEL>0=[fn:161].  Then to selectively pick
+include all levels, use =LEVEL>0=[fn:160].  Then to selectively pick
 the matched entries, use ~org-agenda-skip-function~, which also
 accepts Lisp forms, such as ~org-agenda-skip-entry-if~ and
 ~org-agenda-skip-subtree-if~.  For example:
@@ -21110,6 +21423,9 @@ be complete if the ones above were not mentioned in 
this manual.
 
 - Jason\nbsp{}F.\nbsp{}McBrayer suggested agenda export to CSV format.
 
+- Kyle Meyer helped setting up the [[https://public-inbox.org/][public-inbox]] 
archive of the [[https://orgmode.org/list/][Org
+  mailing list]] and has been fixing many bugs.
+
 - Max Mikhanosha came up with the idea of refiling.
 
 - Dmitri Minaev sent a patch to set priority limits on a per-file
@@ -21147,6 +21463,9 @@ be complete if the ones above were not mentioned in 
this manual.
 - Martin Pohlack provided the code snippet to bundle character
   insertion into bundles of 20 for undo.
 
+- Ihor Radchenko helped with fixing bugs and improving the user
+  experience regarding Org's speed.
+
 - T.\nbsp{}V.\nbsp{}Raman reported bugs and suggested improvements.
 
 - Matthias Rempe (Oelde) provided ideas, Windows support, and quality
@@ -21177,7 +21496,7 @@ be complete if the ones above were not mentioned in 
this manual.
   literal examples, and remote highlighting for referenced code lines.
 
 - Stathis Sideris wrote the =ditaa.jar= ASCII to PNG converter that is
-  now packaged into Org's =contrib/= directory.
+  now packaged into the [[https://git.sr.ht/~bzg/org-contrib][org-contrib]] 
repository.
 
 - Daniel Sinder came up with the idea of internal archiving by locking
   subtrees.
@@ -21300,7 +21619,7 @@ modify this GNU manual."
 * Footnotes
 
 [fn:1] If you do not use Font Lock globally turn it on in Org buffer
-with =(add-hook 'org-mode-hook 'turn-on-font-lock)=.
+with =(add-hook 'org-mode-hook #'turn-on-font-lock)=.
 
 [fn:2] Please consider subscribing to the mailing list in order to
 minimize the work the mailing list moderators have to do.
@@ -21601,12 +21920,12 @@ lognoteclock-out=.
 line---the line is broken here only to fit it into the manual.
 
 [fn:81] On computers using macOS, idleness is based on actual user
-idleness, not just Emacs' idle time.  For X11, you can install
-a utility program =x11idle.c=, available in the =contrib/scripts/=
-directory of the Org Git distribution, or install the xprintidle
-package and set it to the variable ~org-clock-x11idle-program-name~ if
-you are running Debian, to get the same general treatment of idleness.
-On other systems, idle time refers to Emacs idle time only.
+idleness, not just Emacs' idle time.  For X11, you can install a
+utility program =x11idle.c=, available in the =org-contrib/=
+repository, or install the xprintidle package and set it to the
+variable ~org-clock-x11idle-program-name~ if you are running Debian,
+to get the same general treatment of idleness.  On other systems, idle
+time refers to Emacs idle time only.
 
 [fn:82] Please note the pitfalls of summing hierarchical data in
 a flat list (see [[*Using Column View in the Agenda]]).
@@ -21768,7 +22087,7 @@ this timestamp are exported.
 
 [fn:123] For export to LaTeX format---or LaTeX-related formats such as
 Beamer---, the =org-latex-package-alist= variable needs further
-configuration. See [[LaTeX specific export settings]].
+configuration.  See [[LaTeX specific export settings]].
 
 [fn:124] At the moment, some export back-ends do not obey this
 specification.  For example, LaTeX export excludes every unnumbered
@@ -21791,7 +22110,7 @@ to make it visible.  The tag serves as a visual aid and 
has no
 semantic relevance.
 
 [fn:129] By default Org loads MathJax from [[https://cdnjs.com][cdnjs.com]] as 
recommended by
-[[http://www.mathjax.org][MathJax]].
+[[https://www.mathjax.org][MathJax]].
 
 [fn:130] Please note that exported formulas are part of an HTML
 document, and that signs such as =<=, =>=, or =&= have special
@@ -21808,93 +22127,89 @@ use the variables ~org-html-todo-kwd-class-prefix~ and
 for different files.  However, "smart" LaTeX compilation systems, such
 as latexmk, can select the correct bibliography compiler.
 
-[fn:134] See 
[[http://docs.oasis-open.org/office/v1.2/OpenDocument-v1.2.html][Open Document 
Format for Office Applications
+[fn:134] Minted uses an external Python package for code highlighting,
+which requires the flag =-shell-escape= to be added to
+~org-latex-pdf-process~.
+
+[fn:135] See 
[[http://docs.oasis-open.org/office/v1.2/OpenDocument-v1.2.html][Open Document 
Format for Office Applications
 (OpenDocument) Version 1.2]].
 
-[fn:135] See [[http://www.mathtoweb.com/cgi-bin/mathtoweb_home.pl][MathToWeb]].
+[fn:136] See [[http://www.mathtoweb.com/cgi-bin/mathtoweb_home.pl][MathToWeb]].
 
-[fn:136] See [[http://dlmf.nist.gov/LaTeXML/]].
+[fn:137] See [[http://dlmf.nist.gov/LaTeXML/]].
 
-[fn:137] 
[[http://docs.oasis-open.org/office/v1.2/OpenDocument-v1.2.html][OpenDocument-v1.2
 Specification]]
+[fn:138] 
[[http://docs.oasis-open.org/office/v1.2/OpenDocument-v1.2.html][OpenDocument-v1.2
 Specification]]
 
-[fn:138] See the =<table:table-template>= element of the
+[fn:139] See the =<table:table-template>= element of the
 OpenDocument-v1.2 specification.
 
-[fn:139] See the attributes =table:template-name=,
+[fn:140] See the attributes =table:template-name=,
 =table:use-first-row-styles=, =table:use-last-row-styles=,
 =table:use-first-column-styles=, =table:use-last-column-styles=,
 =table:use-banding-rows-styles=, and =table:use-banding-column-styles=
 of the =<table:table>= element in the OpenDocument-v1.2 specification.
 
-[fn:140] If the publishing directory is the same as the source
+[fn:141] If the publishing directory is the same as the source
 directory, =file.org= is exported as =file.org.org=, so you probably
 do not want to do this.
 
-[fn:141] The option ~org-babel-no-eval-on-ctrl-c-ctrl-c~ can be used
+[fn:142] The option ~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.
 
-[fn:142] Actually, the constructs =call_<name>()= and =src_<lang>{}=
+[fn:143] Actually, the constructs =call_<name>()= and =src_<lang>{}=
 are not evaluated when they appear in a keyword (see [[*Summary of
 In-Buffer Settings]]).
 
-[fn:143] C++ language is handled in =ob-C.el=.  Even though the
-identifier for such source blocks is =C++=, you activate it by loading
-the C language.
-
-[fn:144] D language is handled in =ob-C.el=.  Even though the
-identifier for such source blocks is =D=, you activate it by loading
-the C language.
-
-[fn:145] For noweb literate programming details, see
+[fn:144] For noweb literate programming details, see
 http://www.cs.tufts.edu/~nr/noweb/.
 
-[fn:146] For more information, please refer to the commentary section
+[fn:145] For more information, please refer to the commentary section
 in =org-tempo.el=.
 
-[fn:147] Org Indent mode also sets ~wrap-prefix~ correctly for
+[fn:146] Org Indent mode also sets ~wrap-prefix~ correctly for
 indenting and wrapping long lines of headlines or text.  This minor
 mode also handles Visual Line mode and directly applied settings
 through ~word-wrap~.
 
-[fn:148] This works, but requires extra effort.  Org Indent mode is
+[fn:147] This works, but requires extra effort.  Org Indent mode is
 more convenient for most applications.
 
-[fn:149] ~org-adapt-indentation~ can also be set to ='headline-data=,
+[fn:148] ~org-adapt-indentation~ can also be set to ='headline-data=,
 in which case only data lines below the headline will be indented.
 
-[fn:150] Note that Org Indent mode also sets the ~wrap-prefix~
+[fn:149] Note that Org Indent mode also sets the ~wrap-prefix~
 property, such that Visual Line mode (or purely setting ~word-wrap~)
 wraps long lines, including headlines, correctly indented.
 
-[fn:151] For a server to host files, consider using a WebDAV server,
+[fn:150] For a server to host files, consider using a WebDAV server,
 such as [[https://nextcloud.com][Nextcloud]].  Additional help is at this 
[[https://orgmode.org/worg/org-faq.html#mobileorg_webdav][FAQ entry]].
 
-[fn:152] If Emacs is configured for safe storing of passwords, then
+[fn:151] If Emacs is configured for safe storing of passwords, then
 configure the variable ~org-mobile-encryption-password~; please read
 the docstring of that variable.
 
-[fn:153] Symbolic links in ~org-directory~ need to have the same name
+[fn:152] Symbolic links in ~org-directory~ need to have the same name
 as their targets.
 
-[fn:154] While creating the agendas, Org mode forces =ID= properties
+[fn:153] While creating the agendas, Org mode forces =ID= properties
 on all referenced entries, so that these entries can be uniquely
 identified if Org Mobile flags them for further action.  To avoid
 setting properties configure the variable
 ~org-mobile-force-id-on-agenda-items~ to ~nil~.  Org mode then relies
 on outline paths, assuming they are unique.
 
-[fn:155] Checksums are stored automatically in the file
+[fn:154] Checksums are stored automatically in the file
 =checksums.dat=.
 
-[fn:156] The file will be empty after this operation.
+[fn:155] The file will be empty after this operation.
 
-[fn:157] https://www.ctan.org/pkg/comment
+[fn:156] https://www.ctan.org/pkg/comment
 
-[fn:158] By default this works only for LaTeX, HTML, and Texinfo.
+[fn:157] By default this works only for LaTeX, HTML, and Texinfo.
 Configure the variable ~orgtbl-radio-table-templates~ to install
 templates for other modes.
 
-[fn:159] If the =TBLFM= keyword contains an odd number of dollar
+[fn:158] If the =TBLFM= keyword 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 =comment= environment that is used to balance the dollar
@@ -21902,9 +22217,9 @@ expressions.  If you are using AUCTeX with the 
font-latex library,
 a much better solution is to add the =comment= environment to the
 variable ~LaTeX-verbatim-environments~.
 
-[fn:160] The ~agenda*~ view is the same as ~agenda~ except that it
+[fn:159] The ~agenda*~ view is the same as ~agenda~ except that it
 only considers /appointments/, i.e., scheduled and deadline items that
 have a time specification =[h]h:mm= in their time-stamps.
 
-[fn:161] Note that, for ~org-odd-levels-only~, a level number
+[fn:160] Note that, for ~org-odd-levels-only~, a level number
 corresponds to order in the hierarchy, not to the number of stars.
diff --git a/doc/orgcard.tex b/doc/orgcard.tex
index f78cb88..a4400e7 100644
--- a/doc/orgcard.tex
+++ b/doc/orgcard.tex
@@ -15,7 +15,7 @@
 \pdflayout=(0l)
 
 % Nothing else needs to be changed below this line.
-% Copyright (C) 1987, 1993, 1996-1997, 2001-2021 Free Software
+% Copyright (C) 1987, 1993, 1996--1997, 2001--2021 Free Software
 % Foundation, Inc.
 
 % This document is free software: you can redistribute it and/or modify
diff --git a/doc/pdflayout.sty b/doc/pdflayout.sty
index 16b7ecb..7fb6afd 100644
--- a/doc/pdflayout.sty
+++ b/doc/pdflayout.sty
@@ -13,7 +13,7 @@
 % 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/>.
+% along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
 
 % This file defines `\pdflayout':
 %  - \pdflayout=(0) is A4 portrait,
diff --git a/doc/texinfo.tex b/doc/texinfo.tex
index 5f5818d..f3c25b9 100644
--- a/doc/texinfo.tex
+++ b/doc/texinfo.tex
@@ -20,7 +20,7 @@
 % 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/>.
+% along with this program.  If not, see <https://www.gnu.org/licenses/>.
 %
 % As a special exception, when this file is read by TeX when processing
 % a Texinfo source document, you may use the result without
@@ -29,9 +29,9 @@
 %
 % Please try the latest version of texinfo.tex before submitting bug
 % reports; you can get the latest version from:
-%   http://ftp.gnu.org/gnu/texinfo/ (the Texinfo release area), or
-%   http://ftpmirror.gnu.org/texinfo/ (same, via a mirror), or
-%   http://www.gnu.org/software/texinfo/ (the Texinfo home page)
+%   https://ftp.gnu.org/gnu/texinfo/ (the Texinfo release area), or
+%   https://ftpmirror.gnu.org/texinfo/ (same, via a mirror), or
+%   https://www.gnu.org/software/texinfo/ (the Texinfo home page)
 % The texinfo.tex in any given distribution could well be out
 % of date, so if that's what you're using, please check.
 %
@@ -55,7 +55,7 @@
 % extent.  You can get the existing language-specific files from the
 % full Texinfo distribution.
 %
-% The GNU Texinfo home page is http://www.gnu.org/software/texinfo.
+% The GNU Texinfo home page is https://www.gnu.org/software/texinfo.
 
 
 \message{Loading texinfo [version \texinfoversion]:}
@@ -3101,7 +3101,7 @@ end
 % We use the free feym* fonts from the eurosym package by Henrik
 % Theiling, which support regular, slanted, bold and bold slanted (and
 % "outlined" (blackboard board, sort of) versions, which we don't need).
-% It is available from http://www.ctan.org/tex-archive/fonts/eurosym.
+% It is available from https://www.ctan.org/tex-archive/fonts/eurosym.
 %
 % Although only regular is the truly official Euro symbol, we ignore
 % that.  The Euro is designed to be slightly taller than the regular
diff --git a/etc/Makefile b/etc/Makefile
index 8b06158..ab5c988 100644
--- a/etc/Makefile
+++ b/etc/Makefile
@@ -1,4 +1,4 @@
-ETCDIRS = styles schema
+ETCDIRS = styles schema csl
 -include local.mk      # optional local customization
 
 .NOTPARALLEL:  # always run this make serially
diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index 3860fc5..17f8512 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -3,6 +3,7 @@ ORG NEWS -- history of user-visible changes.   -*- mode: org; 
coding: utf-8 -*-
 #+STARTUP: overview
 
 #+LINK: doc https://orgmode.org/worg/doc.html#%s
+#+LINK: msg https://list.orgmode.org/%s/
 #+LINK: git https://git.savannah.gnu.org/cgit/emacs/org-mode.git/commit/?id=%s
 
 Copyright (C) 2012-2021 Free Software Foundation, Inc.
@@ -11,6 +12,565 @@ See the end of the file for license conditions.
 Please send Org bug reports to mailto:emacs-orgmode@gnu.org.
 
 * Version 9.5 (not yet released)
+
+** Important announcements and breaking changes
+
+*** The =contrib/= now lives in a separate repository
+
+Org's repository has been trimmed from the =contrib/= directory.
+
+The old contents of the =contrib/= directory now lives in a separate
+repository at https://git.sr.ht/~bzg/org-contrib.
+
+You can install this repository by cloning it and updating your
+~load-path~ accordingly.  You can also install =org-contrib= as a
+[[https://elpa.nongnu.org/nongnu/][NonGNU ELPA]] package.
+
+*** Org ELPA and Org archives won't be available for Org > 9.5
+
+[[https://orgmode.org/elpa.html][Org ELPA]] is still available for installing 
Org 9.5, either with or
+without contributed packages, but future versions won't be available
+via Org ELPA, as we are deprecating this installation method.
+
+Also, Org 9.5 is available as =tar.gz= and =zip= archives, but this
+installation method is also deprecated.
+
+If you want to install the latest stable versions of Org, please use
+the GNU ELPA package.  If you want to install the contributed files,
+please use the NonGNU ELPA package.  If you want to keep up with the
+latest unstable Org, please install from the Git repository.
+
+See https://orgmode.org/org.html#Installation for the details.
+
+*** =ditaa.jar= is not bundled with Org anymore
+
+=ditaa.jar= used to be bundled with Org but it is not anymore.
+See [[https://github.com/stathissideris/ditaa][the ditaa repository]] on how 
to install it.
+
+*** ~org-adapt-indentation~ now defaults to =nil=
+
+If you want to automatically indent headlines' metadata, set it to
+=headline-data=.
+
+If you want to automatically indent every line to the headline's
+current indentation, set it to =t=.
+
+Indent added by =RET= and =C-j= also depends on the value of
+~electric-indent-mode~.  Enabling this mode by default in 9.4 revealed
+some bugs caused confusing behavior.  If you disabled
+~electric-indent-mode~ for this reason, it is time to try it again.
+Hopefully problems have been fixed.  See 
[[https://orgmode.org/worg/org-faq.html#indentation][this FAQ]] for more 
details.
+
+*** ~org-speed-commands-user~ is obsolete, use ~org-speed-commands~
+
+Setting ~org-speed-commands-user~ in your configuration won't have any
+effect.  Please set ~org-speed-commands~ instead, which see.
+
+*** Some =ob-*.el= files have been moved to the org-contrib repo
+
+These files have been moved to https://git.sr.ht/~bzg/org-contrib:
+
+- ob-abc.el
+- ob-asymptote.el
+- ob-coq.el
+- ob-ebnf.el
+- ob-hledger.el
+- ob-io.el
+- ob-J.el
+- ob-ledger.el
+- ob-mscgen.el
+- ob-picolisp.el
+- ob-shen.el
+- ob-stan.el
+- ob-vala.el
+
+See the discussion [[msg::87bl9rq29m.fsf@gnu.org][here]].
+
+*** Compatibility with Emacs versions
+
+We made it explicit that we aim at keeping the latest stable version
+of Org compatible with at least Emacs V, V-1 and V-2, where V is the
+stable major version of Emacs.
+
+For example, if the current major version of Emacs is 28.x, then the
+latest stable version of Org should be compatible with Emacs 28.x,
+27.x and 26.x โ€“ but not with Emacs 25.x.
+
+See [[https://orgmode.org/worg/org-maintenance.html#emacs-compatibility][this 
note on Worg]] and [[git::519947e508e081e71bf67db99e27b1c171ba4dfe][this 
commit]].
+
+** New features
+
+*** New citation engine
+
+Org 9.5 provides a new library =oc.el= which provides tooling to
+handle citations in Org, e.g., activate, follow, insert, and export
+them, respectively called "activate", "follow", "insert" and "export"
+capabilities.  Libraries responsible for providing some, or all, of
+these capabilities are called "citation processors".
+
+The manual contains a few pointers to let you start and you may want
+to check [[https://blog.tecosaur.com/tmio/2021-07-31-citations.html][this blog 
post]].  If you need help using this new features,
+please ask on the mailing list.
+
+Thanks to Nicolas Goaziou for implementing this, to Bruce Dโ€™Arcus for
+helping him and to John Kitchin for paving the way with =org-ref.el=.
+
+*** Async session evaluation
+
+The =:async= header argument can be used for asynchronous evaluation
+in session blocks for certain languages.
+
+Currently, async evaluation is supported in Python.  There is also
+functionality to implement async evaluation in other languages that
+use comint, but this needs to be done on a per-language basis.
+
+By default, async evaluation is disabled unless the =:async= header
+argument is present.  You can also set =:async no= to force it off
+(for example if you've set =:async= in a property drawer).
+
+Async evaluation is disabled during export.
+*** ~ox-koma-letter.el~ is now part of Org's core
+
+~ox-koma-letter.el~ provides a KOMA scrlttr2 back-end for the Org
+export engine.  It used to be in the =contrib/= directory but it is
+now part of Org's core.
+
+*** Support exporting DOI links
+
+Org now supports export for DOI links, through its new =ol-doi.el=
+library.  For backward compatibility, it is loaded by default.
+
+*** Add a new ~:refile-targets~ template option
+
+When exiting capture mode via ~org-capture-refile~, the variable
+~org-refile-targets~ will be temporarily bound to the value of this
+template option.
+
+*** New startup options =#+startup: show<n>levels=
+
+These startup options complement the existing =overview=, =content=,
+=showall=, =showeverything= with a way to start the document with n
+levels shown, where n goes from 2 to 5.
+
+Example:
+
+: #+startup: show3levels
+
+*** New =u= table formula flag to enable Calc units simplification mode
+
+A new =u= mode flag for Calc formulas in Org tables has been added to
+enable Calc units simplification mode.
+
+*** Support fontification of inline export snippets
+
+See [[msg:87im57fh8j.fsf@gmail.com][this thread]].
+
+*** New command =org-refile-reverse= bound to =C-c C-M-w=
+
+You can now use =C-c C-M-w= to run ~org-refile-reverse~.
+
+It is almost identical to ~org-refile~, except that it temporarily
+toggles how ~org-reverse-note-order~ applies to the current buffer.
+So if ~org-refile~ would append the entry as the last entry under the
+target heading, ~org-refile-reverse~ will prepend it as the first
+entry, and vice-versa.
+
+*** LaTeX attribute ~:float~ now passes through arbitrary values
+
+LaTeX users are able to define arbitrary float types, e.g. with the
+float package.  The Org mode LaTeX exporter is now able to process and
+export arbitrary float types.  The user is responsible for ensuring
+that Org mode configures LaTeX to process any new float type.
+
+*** Support verse and quote blocks in LaTeX export
+
+The LaTeX export back-end accepts four attributes for verse blocks:
+=:lines=, =:center=, =:versewidth= and =:latexcode=. The three first
+require the external LaTeX package =verse.sty=, which is an extension
+of the standard LaTeX environment.
+
+The LaTeX export back-end accepts two attributes for quote blocks:
+=:environment=, for an arbitrary quoting environment (the default
+value is that of =org-latex-default-quote-environment=: ="quote"=) and
+=:options=.
+
+*** =org-set-tags-command= selects tags from ~org-global-tags-completion-table~
+
+Let ~org-set-tags-command~ TAB fast tag completion interface complete
+tags including from both buffer local and user defined persistent
+global list (~org-tag-alist~ and ~org-tag-persistent-alist~).  Now
+option ~org-complete-tags-always-offer-all-agenda-tags~ is honored.
+
+*** Clocktable option =:formula %= now shows the per-file time percentages
+
+This change only has an effect when multiple files are contributing to
+a given clocktable (such as when =:scope agenda= has been specified).
+The existing behavior is that such tables have an extra 'File' column,
+and each individual file that contributes has its own summary line
+with the headline value '*File time*'.  Those summary rows also
+produce a rollup time value for the file in the 'Time' column.
+
+Prior to this change, the built-in =%= formula did not produce a
+calculation for those per-file times in the '%' column (the relevant
+cells in the '%' column were blank).  With this change, the percentage
+contribution of each individual file time to the total time is shown.
+
+The more agenda files you have, the more useful this behavior becomes.
+
+*** =ob-python.el= improvements to =:return= header argument
+
+The =:return= header argument in =ob-python= now works for session
+blocks as well as non-session blocks.  Also, it now works with the
+=:epilogue= header argument -- previously, setting the =:return=
+header would cause the =:epilogue= to be ignored.
+
+This change allows more easily moving boilerplate out of the main code
+block and into the header. For example, for plotting, we need to add
+boilerplate to save the figure to a file and return the
+filename. Instead of doing this within the code block, we can now
+handle it through the header arguments as follows:
+
+#+BEGIN_SRC org
+,#+header: :var fname="/home/jack/tmp/plot.svg"
+,#+header: :epilogue plt.savefig(fname)
+,#+header: :return fname
+,#+begin_src python :results value file
+  import matplotlib, numpy
+  import matplotlib.pyplot as plt
+  fig=plt.figure(figsize=(4,2))
+  x=numpy.linspace(-15,15)
+  plt.plot(numpy.sin(x)/x)
+  fig.tight_layout()
+,#+end_src
+
+,#+RESULTS:
+[[file:/home/jack/tmp/plot.svg]]
+#+END_SRC
+
+As another example, we can use =:return= with the external 
[[https://pypi.org/project/tabulate/][tabulate]]
+package, to convert pandas Dataframes into orgmode tables:
+
+#+begin_src org
+,#+header: :prologue from tabulate import tabulate
+,#+header: :return tabulate(table, headers=table.columns, tablefmt="orgtbl")
+,#+begin_src python :results value raw :session
+  import pandas as pd
+  table = pd.DataFrame({
+      "a": [1,2,3],
+      "b": [4,5,6]
+  })
+,#+end_src
+
+,#+RESULTS:
+|   | a | b |
+|---+---+---|
+| 0 | 1 | 4 |
+| 1 | 2 | 5 |
+| 2 | 3 | 6 |
+#+end_src
+
+*** Display images with width proportional to the buffer text width
+
+Previously, if you used a =:width= attribute like =#+attr_html: :width 70%= or
+=#+attr_latex: :width 0.7\linewidth= this would be interpreted as a 70px wide 
and
+0.7px wide width specification respectively.
+
+Now, percentages are transformed into floats (i.e. 70% becomes 0.7),
+and float width specifications between 0.0 and 2.0 are now interpreted
+as that portion of the text width in the buffer. For instance, the
+above examples of =70%= and =0.7\linewidth= will result in an image
+with width equal to the pixel-width of the buffer text multiplied by 0.7.
+
+This functionality is implemented in a new function,
+~org-display-inline-image--width~ which contains the width
+determination logic previously in ~org-display-inline-images~ and the
+new behaviour.
+
+** New options
+*** Option ~org-hidden-keywords~ now also applies to #+SUBTITLE:
+
+The option ~org-hidden-keywords~ previously applied
+to #+TITLE:, #+AUTHOR:, #+DATE:, and #+EMAIL:.  Now it can also be
+used to hide the #+SUBTITLE: keyword.
+
+*** New formatting directive ~%L~ for org-capture
+
+The new ~%L~ formatting directive contains the bare link target, and
+may be used to create links with programmatically generated
+descriptions.
+
+*** New option ~org-id-ts-format~
+
+Earlier, IDs generated using =ts= method had a hard-coded format (i.e. 
=20200923T160237.891616=).
+The new option allows user to customise the format.
+Defaults are unchanged.
+
+*** New argument for ~file-desc~ babel header
+
+It is now possible to provide the =file-desc= header argument for a
+babel source block but omit the description by passing an empty vector
+as an argument (i.e., :file-desc []).  This can be useful because
+providing =file-desc= without an argument results in the result of
+=file= being used in the description.  Previously, the only way to
+omit a file description was to omit the header argument entirely,
+which made it difficult/impossible to provide a default value for
+=file-desc=.
+
+*** New option to set ~org-link-file-path-type~ to a function
+
+~org-link-file-path-type~ can now be set to a function that takes the
+full filename as an argument and returns the path to link to.
+
+For example, if you use ~project.el~, you can set this function to use
+relative links within a project as follows:
+
+#+begin_src emacs-lisp
+(setq (org-link-file-path-type
+       (lambda (path)
+         (let* ((proj (project-current))
+                (root (if proj (project-root proj) default-directory)))
+           (if (string-prefix-p (expand-file-name root) path)
+               (file-relative-name path)
+             (abbreviate-file-name path))))))
+#+end_src
+
+*** New options and new behavior for babel LaTeX SVG image files
+
+Org babel now uses a two-stage process for converting latex source
+blocks to SVG image files (when the extension of the output file is
+~.svg~).  The first stage in the process converts the latex block into
+a PDF file, which is then converted into an SVG file in the second
+stage.  The TeX->PDF part uses the existing infrastructure for
+~org-babel-latex-tex-to-pdf~.  The PDF->SVG part uses a command
+specified in a new customization,
+~org-babel-latex-pdf-svg-process~. By default, this uses inkscape for
+conversion, but since it is fully customizable, any other command can
+be used in its place. For instance, dvisvgm might be used here. This
+two-part processing replaces the previous use of htlatex to process
+LaTeX directly to SVG (htlatex is still used for HTML conversion).
+
+Conversion to SVG exposes a number of additional customizations that
+give the user full control over the contents of the latex source
+block. ~org-babel-latex-preamble~, ~org-babel-latex-begin-env~ and
+~org-babel-latex-end-env~ are new customization options added to allow
+the user to specify the preamble and code that preceedes and proceeds
+the contents of the source block.
+
+*** New option ~org-html-meta-tags~ allows for HTML meta tags customization
+
+New variable ~org-html-meta-tags~ makes it possible to customize the
+=<meta>= tags used in an HTML export.  Accepts either a static list of
+values, or a function that generates such a list (see
+~org-html-meta-tags-default~ as an example of the latter).
+
+*** Option ~org-agenda-bulk-custom-functions~ now supports collecting bulk 
arguments
+
+When specifying a custom agenda bulk option, you can now also specify
+a function which collects the arguments to be used with each call to
+the custom function.
+
+*** New faces to improve the contextuality of Org agenda views
+
+Four new faces improve certain styles and offer more flexibility for
+some Org agenda views: ~org-agenda-date-weekend-today~,
+~org-imminent-deadline~, ~org-agenda-structure-secondary~,
+~org-agenda-structure-filter~.  They inherit from existing faces in
+order to remain backward-compatible.
+
+Quoting from [[https://list.orgmode.org/87lf7q7gpq.fsf@protesilaos.com/][this 
thread]]:
+
+#+begin_quote
++ The 'org-imminent-deadline' is useful to disambiguate generic
+  warnings from deadlines.  For example, a warning could be rendered
+  in a yellow colored text and have a bold weight, whereas a deadline
+  might be red and styled with italics.
+
++ The 'org-agenda-structure-filter' applies to all tag/term filters
+  in agenda views that search for keywords or patterns.  It is
+  designed to inherit from 'org-agenda-structure' in addition to the
+  'org-warning' face that was present before (and removes the
+  generic 'warning' face from one place).  This offers the benefit
+  of consistency, as, say, an increase in font height or a change in
+  font family in 'org-agenda-structure' will propagate to the filter
+  as well.  The whole header line thus looks part of a singular
+  design.
+
++ The 'org-agenda-structure-secondary' complements the above for those
+  same views where a description follows the header.  For instance, the
+  tags view provides information to "Press N r" to filter by a
+  numbered tag.  Themes/users may prefer to disambiguate this line
+  from the header above it, such as by using a less intense color or by
+  reducing its height relative to the 'org-agenda-structure'.
+
++ The 'org-agenda-date-weekend-today' provides the option to
+  differentiate the current date on a weekend from the current date on
+  weekdays.
+#+end_quote
+
+*** New option ~org-clock-ask-before-exiting~
+
+By default, a function is now added to ~kill-emacs-query-functions~
+that asks whether to clock out and save when there's a running clock.
+Customize ~org-clock-ask-before-exiting~~ to nil to disable this new
+behavior.
+
+*** Option ~org-html-inline-image-rules~ now includes .webp
+
+By default ox-html now inlines webp images.
+
+*** ~org-html-head-include-scripts~ is now =nil= by default
+
+See [[msg:498dbe2e-0cd2-c81e-7960-4a26c566a1f7@memebeam.org][this thread]].
+
+*** New option ~org-html-content-class~
+
+This is the CSS class name to use for the top level content wrapper.
+
+*** New option ~org-babel-plantuml-svg-text-to-path~
+
+This option, nil by default, allows to add a SVG-specific post-export
+step that runs inkscape text-to-path replacement over the output file.
+
+*** You can now configure ~org-html-scripts~ and ~org-html-style-default~
+
+~org-html-scripts~ and ~org-html-style-default~ used to be constants,
+you can now configure them.
+
+*** New option ~org-attach-git-dir~
+
+~org-attach-git-dir~ will decide whether to use ~org-attach-git-dir~
+(the default) or use the attachment directory of the current node, if
+it is correctly configured as a Git repository.
+
+*** Some faces now use fixed-pitch
+
+See [[msg:875z8njaol.fsf@protesilaos.com][this thread]].
+
+*** New option ~org-attach-sync-delete-empty-dir~
+
+~org-attach-sync-delete-empty-dir~ controls the deletion of an empty
+attachment directory at calls of ~org-attach-sync~.  There is
+Never delete, Always delete and Query the user (default).
+
+*** ~org-babel-default-header-args~ can now be specified as closures or strings
+
+~org-babel-default-header-args~ now also accepts closures that
+evaluate to a string. Previously, only direct strings were
+supported. These closures are evaluated when point is at the source
+block, which allows them to make use of contextual information at the
+relevant source block. One example that illustrates the usefulness of
+this addition (also given in the documentation for
+~org-babel-default-header-args~) is:
+
+#+begin_src elisp
+(defun org-src-sha ()
+  (let ((elem (org-element-at-point)))
+    (concat (sha1 (org-element-property :value elem)) \".svg\")))
+
+(setq org-babel-default-header-args:latex
+      `((:results . \"file link replace\")
+        (:file . (lambda () (org-src-sha)))))
+#+end_src
+
+This will set the ~:file~ header argument to the sha1 checksum of the
+contents of the current latex source block.
+
+Finally, the closures are only evaluated if they're not overridden for
+a source block. This improves efficiency in cases where the result of
+a compute-expensive closure would otherwise be discarded.
+
+** Miscellaneous
+*** =org-bibtex= includes =doi= and =url= entries when exporting to BiBTeX
+=doi= and =url= entries have been made optional for some publication
+types and will be exported if present for those types.
+*** Missing or empty placeholders in "eval" macros are now =nil=
+They used to be the empty string.
+*** =org-goto-first-child= now works before first heading
+
+When point is before first heading =org-goto-first-child= will move
+point to the first child heading, or return nil if no heading exist
+in buffer.  This is in line with the fact that everything before first
+heading is regarded as outline level 0, i.e. the parent level of all
+headings in the buffer.
+
+Previously =org-goto-first-child= would do nothing before first
+heading, except return nil.
+
+*** Faces of all the heading text elements now conform to the headline face
+
+In the past, faces of todo keywords, emphasised text, tags, and
+priority cookies inherited =default= face.  The resulting headline
+fontification was not always consistent, as discussed in 
[[https://lists.gnu.org/archive/html/emacs-orgmode/2020-09/msg00331.html][this 
bug
+report]].  Now, the relevant faces adapt to face used to fontify the
+current headline level.
+
+Users who prefer to keep the old behaviour should change their face
+customisation explicitly stating that =default= face is inherited.
+
+Example of old face customisation:
+
+#+begin_src emacs-lisp
+(setq org-todo-keyword-faces '(("TODO"
+                                :background "chocolate"
+                                :height 0.75)))
+#+end_src
+
+To preserve the old behaviour the above customisation should be
+changed to
+
+#+begin_src emacs-lisp
+(setq org-todo-keyword-faces '(("TODO"
+                                :inherit default
+                                :background "chocolate"
+                                :height 0.75)))
+#+end_src
+
+*** Storing ID-links before first heading uses title as description
+
+Storing links to files using ~org-store-link~ (=<C-c l>=) when
+~org-id-link-to-org-use-id~ is not nil will now store the title as
+description of the link, if available.  If no title exists it falls
+back to the filename as before.
+
+*** Change in =org-tags-expand= signature
+
+The function does not allow for a third optional parameter anymore.
+*** LaTeX environment =#+results= are now removed
+
+If a babel src block produces a raw LaTeX environment, it will now be
+recognised as a result, and so replaced when re-evaluated.
+
+*** Tag completion now uses =completing-read-multiple=
+
+Tag completion now uses =completing-read-multiple= with a simple
+completion table, which should allow better interoperability with
+custom completion functions.
+
+*** Providing =directory-empty-p= from Emacs 28 as =org-directory-empty-p=
+
+*** =org-get-last-sibling= marked as obsolete
+
+Use =org-get-previous-sibling= instead.  This is just a rename to have
+a more consistent naming.  E.g. recall the pair of funtctions
+=next-line= / =previous-line=.
+
+*** Make org-protocol compatible with =URLSearchParams= JavaScript class
+
+Decoder of query part of org-protocol URI recognizes "+" as an encoded
+space characters now, so it is possible to avoid call to =encodeURIComponent=
+for each parameter and use more readable expression in bookmarklet:
+
+#+begin_example
+'org-protocol://store-link?' + new URLSearchParams({
+      url: location.href, title: document.title})
+#+end_example
+
+*** Remove obsolete LaTeX packages from ~org-latex-default-packages-alist~
+
+The LaTeX packages =grffile= and =textcomp= are redundant, with their
+capabilities being merged into =graphicx= and the LaTeX core
+respectively a while ago.
+
 * Version 9.4
 ** Incompatible changes
 *** Possibly broken internal file links: please check and fix
@@ -125,7 +685,7 @@ explicitly:
 
 Alternatively, if you wish to keep =RET= as the "smart-return" key,
 but dislike Org's default indentation of sections, you may prefer to
-customize ~org-adapt-indentation~ to either =nil= or =headline-data=.
+customize ~org-adapt-indentation~ to either nil or =headline-data=.
 
 *** New allowed value for ~org-adapt-indentation~
 
@@ -381,14 +941,14 @@ The value of a shell script's execution is its exit code. 
 But most
 users expect the results of executing a shell script to be its output,
 not its exit code.
 
-So we introduced this option, that you can set to =nil= if you want
-to stick using ~:results value~ as the implicit header.
+So we introduced this option, that you can set to nil if you want to
+stick using ~:results value~ as the implicit header.
 
 In all Babel libraries, the absence of a ~:results~ header should
 produce the same result than setting ~:results value~, unless there is
 an option to explicitly create an exception.
 
-See 
[[https://list.orgmode.org/CA+A2iZaziAfMeGpBqL6qGrzrWEVvLvC0DUw++T4gCF3NGuW-DQ@mail.gmail.com/][this
 thread]] for more context.
+See 
[[msg:CA+A2iZaziAfMeGpBqL6qGrzrWEVvLvC0DUw++T4gCF3NGuW-DQ@mail.gmail.com][this 
thread]] for more context.
 
 *** New option in ~org-attach-store-link-p~
 
@@ -748,7 +1308,7 @@ removed.
 For those who hate breaking changes, even though the changes are made
 to clean things up; fear not.  ATTACH_DIR will still continue to work.
 It's just not documented any longer.  When you get the chance, run the
-code above to clean things up anyways!
+code above to clean things up anyway!
 
 **** New hooks
 Two hooks are added to org-attach:
@@ -1198,7 +1758,7 @@ With this output format, create a link to the file 
specified in
 
 #+begin_example
 ,#+begin_src shell :dir "data/tmp" :results link :file "crackzor_1.0.c.gz"
-wget -c "http://ben.akrin.com/crackzor/crackzor_1.0.c.gz";
+wget -c "https://ben.akrin.com/crackzor/crackzor_1.0.c.gz";
 ,#+end_src
 
 ,#+results:
@@ -1538,7 +2098,9 @@ Use "/!" markup when filtering TODO keywords to get only 
not-done TODO
 keywords.
 
 *** ~org-split-string~ returns ~("")~ when called on an empty string
+
 It used to return nil.
+
 *** Removal of =ob-scala.el=
 
 See [[https://github.com/ensime/emacs-scala-mode/issues/114][this github 
issue]].
@@ -1606,7 +2168,8 @@ before this let form.
 
 Creation of a new setting to specify the Cider timeout.  By setting
 the =org-babel-clojure-sync-nrepl-timeout= setting option.  The value
-is in seconds and if set to =nil= then no timeout will occur.
+is in seconds and if set to nil then no timeout will occur.
+
 **** Clojure: new header ~:show-process~
 
 A new block code header has been created for Org Babel that enables
@@ -1649,7 +2212,7 @@ this ~:prologue "fpprintprec: 2; linel: 50;"~ for 
presenting Maxima
 results in a beamer presentation.
 **** PlantUML: add support for header arguments
 
-[[http://plantuml.com/][Plantuml]] source blocks now support the 
[[https://orgmode.org/manual/prologue.html#prologue][~:prologue~]], 
[[https://orgmode.org/manual/epilogue.html#epilogue][~:epilogue~]] and
+[[https://plantuml.com/][Plantuml]] source blocks now support the 
[[https://orgmode.org/manual/prologue.html#prologue][~:prologue~]], 
[[https://orgmode.org/manual/epilogue.html#epilogue][~:epilogue~]] and
 [[https://orgmode.org/manual/var.html#var][~:var~]] header arguments.
 
 **** SQL: new engine added ~sqsh~
@@ -1822,9 +2385,8 @@ removed from Gnus circa September 2010.
 
 *** ~org-agenda-repeating-timestamp-show-all~ is removed.
 
-For an equivalent to a =nil= value, set
-~org-agenda-show-future-repeats~ to nil and
-~org-agenda-prefer-last-repeat~ to =t=.
+For an equivalent to a nil value, set ~org-agenda-show-future-repeats~
+to nil and ~org-agenda-prefer-last-repeat~ to =t=.
 
 *** ~org-gnus-nnimap-query-article-no-from-file~ is removed.
 
@@ -1842,7 +2404,7 @@ equivalent to the removed format string.
 
 *** ~org-enable-table-editor~ is removed.
 
-Setting it to a =nil= value broke some other features (e.g., speed
+Setting it to a nil value broke some other features (e.g., speed
 keys).
 
 *** ~org-export-use-babel~ cannot be set to ~inline-only~
@@ -2285,7 +2847,7 @@ The postgresql engine in a sql code block supports now 
~:dbport~ nd
 
 **** Support for additional plantuml output formats
 
-The support for output formats of [[http://plantuml.com/][plantuml]] has been 
extended to now
+The support for output formats of [[https://plantuml.com/][plantuml]] has been 
extended to now
 include:
 
 All Diagrams:
@@ -2318,7 +2880,7 @@ Alice <-- Bob: another authentication Response
 #+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
+setup in addition to plantuml.  See [[https://plantuml.com/pdf.html]] for
 details and setup information.
 
 *** Rewrite of radio lists
@@ -3448,11 +4010,11 @@ then inline code snippets will be wrapped into the 
formatting string.
 ** New contributed packages
 
 - =ox-bibtex.el= by Nicolas Goaziou :: an utility to handle BibTeX
-     export to both LaTeX and HTML exports.  It uses the 
[[http://www.lri.fr/~filliatr/bibtex2html/][bibtex2html]]
+     export to both LaTeX and HTML exports.  It uses the 
[[https://www.lri.fr/~filliatr/bibtex2html/][bibtex2html]]
      software.
 
 - =org-screenshot.el= by Max Mikhanosha :: an utility to handle
-     screenshots easily from Org, using the external tool 
[[http://freecode.com/projects/scrot][scrot]].
+     screenshots easily from Org, using the external tool 
[[https://freecode.com/projects/scrot][scrot]].
 
 ** Miscellaneous
 
@@ -3603,7 +4165,7 @@ manual for details and check 
[[https://orgmode.org/worg/org-8.0.html][this Worg
 *** ~ox-md.el~ by Nicolas Goaziou
 
     =ox-md.el= allows you to export Org files to Markdown files, using the
-    vanilla [[http://daringfireball.net/projects/markdown/][Markdown syntax]].
+    vanilla [[https://daringfireball.net/projects/markdown/][Markdown syntax]].
 
 *** ~ox-texinfo.el~ by Jonathan Leech-Pepin
 
@@ -3613,14 +4175,14 @@ manual for details and check 
[[https://orgmode.org/worg/org-8.0.html][this Worg
 
 *** ~ob-julia.el~ by G. Jay Kerns
 
-    [[http://julialang.org/][Julia]] is a new programming language.
+    [[https://julialang.org/][Julia]] is a new programming language.
 
     =ob-julia.el= provides Org Babel support for evaluating Julia source
     code.
 
 *** ~ob-mathomatic.el~ by Luis Anaya
 
-    [[http://www.mathomatic.org/][mathomatic]] a portable, command-line, 
educational CAS and calculator
+    [[https://www.mathomatic.org/][mathomatic]] a portable, command-line, 
educational CAS and calculator
     software, written entirely in the C programming language.
 
     ~ob-mathomatic.el~ provides Org Babel support for evaluating mathomatic
@@ -3628,7 +4190,7 @@ manual for details and check 
[[https://orgmode.org/worg/org-8.0.html][this Worg
 
 *** ~ob-tcl.el~ by Luis Anaya
 
-    ~ob-tcl.el~ provides Org Babel support for evaluating 
[[http://www.tcl.tk/][Tcl]] source code.
+    ~ob-tcl.el~ provides Org Babel support for evaluating 
[[https://www.tcl.tk/][Tcl]] source code.
 
 *** ~org-bullets.el~ by Evgeni Sabof
 
@@ -3654,7 +4216,7 @@ manual for details and check 
[[https://orgmode.org/worg/org-8.0.html][this Worg
     presentations.  ~ox-deck.el~ exports Org files to HTML presentations
     using =deck.js=.
 
-    [[http://meyerweb.com/eric/tools/s5/][s5]] is a set of scripts which also 
allows to display HTML pages as
+    [[https://meyerweb.com/eric/tools/s5/][s5]] is a set of scripts which also 
allows to display HTML pages as
     presentations.  ~ox-s5.el~ exports Org files to HTML presentations
     using =s5=.
 
@@ -3761,13 +4323,13 @@ forward and backward.
 
 Now Org will sort this list
 
-: - [[http://abc.org][B]]
-: - [[http://def.org][A]]
+: - [[https://abc.org][B]]
+: - [[https://def.org][A]]
 
 like this:
 
-: - [[http://def.org][A]]
-: - [[http://abc.org][B]]
+: - [[https://def.org][A]]
+: - [[https://abc.org][B]]
 
 by comparing the descriptions, not the links.
 Same when sorting headlines instead of list items.
@@ -4271,8 +4833,8 @@ found here: 
https://orgmode.org/worg/org-tutorials/org-outside-org.html
 
 Here are two screencasts demonstrating Thorsten's tools:
 
-- [[http://youtu.be/nqE6YxlY0rw]["Modern conventions for Emacs Lisp files"]]
-- [[http://www.youtube.com/watch?v%3DII-xYw5VGFM][Exploring Bernt Hansen's 
Org-mode tutorial with 'navi-mode']]
+- [[https://youtu.be/nqE6YxlY0rw]["Modern conventions for Emacs Lisp files"]]
+- [[https://www.youtube.com/watch?v%3DII-xYw5VGFM][Exploring Bernt Hansen's 
Org-mode tutorial with 'navi-mode']]
 
 *** MobileOrg for iOS
 
@@ -4302,7 +4864,7 @@ lines even if `org-use-tag-inheritance' was nil.  The 
default is now
 to *never* display inherited tags in agenda lines, but to /know/ about
 them when the agenda type is listed in 
[[doc::org-agenda-use-tag-inheritance][org-agenda-use-tag-inheritance]].
 
-** New default value nil for 
[[doc::org-agenda-dim-blocked-tasks][org-agenda-dim-blocked-tasks]]
+** New default value =nil= for 
[[doc::org-agenda-dim-blocked-tasks][org-agenda-dim-blocked-tasks]]
 
 Using `nil' as the default value speeds up the agenda generation.  You
 can hit `#' (or `C-u #') in agenda buffers to temporarily dim (or turn
@@ -5131,7 +5693,7 @@ that Calc formulas can operate on them.
 
     The new system has a technically cleaner implementation and more
     possibilities for capturing different types of data.  See
-    
[[https://list.orgmode.org/C46F10DC-DE51-43D4-AFFE-F71E440D1E1F@gmail.com][Carsten's
 announcement]] for more details.
+    [[msg:C46F10DC-DE51-43D4-AFFE-F71E440D1E1F@gmail.com][Carsten's 
announcement]] for more details.
 
     To switch over to the new system:
 
@@ -5262,7 +5824,7 @@ that Calc formulas can operate on them.
 
 **** Modified link escaping
 
-     David Maus worked on `org-link-escape'.  See 
[[https://list.orgmode.org/87k4gysacq.wl%dmaus@ictsoc.de][his message]]:
+     David Maus worked on `org-link-escape'.  See 
[[msg:87k4gysacq.wl%dmaus@ictsoc.de][his message]]:
 
      : Percent escaping is used in Org mode to escape certain characters
      : in links that would either break the parser (e.g. square brackets
diff --git a/etc/csl/chicago-author-date.csl b/etc/csl/chicago-author-date.csl
new file mode 100644
index 0000000..d066efa
--- /dev/null
+++ b/etc/csl/chicago-author-date.csl
@@ -0,0 +1,644 @@
+<?xml version="1.0" encoding="utf-8"?>
+<style xmlns="http://purl.org/net/xbiblio/csl"; class="in-text" version="1.0" 
demote-non-dropping-particle="display-and-sort" page-range-format="chicago">
+  <info>
+    <title>Chicago Manual of Style 17th edition (author-date)</title>
+    <id>http://www.zotero.org/styles/chicago-author-date</id>
+    <link href="http://www.zotero.org/styles/chicago-author-date"; rel="self"/>
+    <link href="http://www.chicagomanualofstyle.org/tools_citationguide.html"; 
rel="documentation"/>
+    <author>
+      <name>Julian Onions</name>
+      <email>julian.onions@gmail.com</email>
+    </author>
+    <contributor>
+      <name>Sebastian Karcher</name>
+    </contributor>
+    <contributor>
+      <name>Richard Karnesky</name>
+      <email>karnesky+zotero@gmail.com</email>
+      <uri>http://arc.nucapt.northwestern.edu/Richard_Karnesky</uri>
+    </contributor>
+    <contributor>
+      <name>Andrew Dunning</name>
+      <email>andrew.dunning@utoronto.ca</email>
+    </contributor>
+    <category citation-format="author-date"/>
+    <category field="generic-base"/>
+    <summary>The author-date variant of the Chicago style</summary>
+    <updated>2017-10-12T12:00:00+00:00</updated>
+    <rights license="http://creativecommons.org/licenses/by-sa/3.0/";>This work 
is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights>
+  </info>
+  <locale xml:lang="en">
+    <terms>
+      <term name="editor" form="verb-short">ed.</term>
+      <term name="container-author" form="verb">by</term>
+      <term name="translator" form="verb-short">trans.</term>
+      <term name="editortranslator" form="verb">
+        <single>edited and translated by</single>
+        <multiple>edited and translated by</multiple>
+      </term>
+      <term name="translator" form="short">trans.</term>
+    </terms>
+  </locale>
+  <macro name="secondary-contributors">
+    <choose>
+      <if type="chapter paper-conference" match="none">
+        <group delimiter=". ">
+          <names variable="editor translator" delimiter=". ">
+            <label form="verb" text-case="capitalize-first" suffix=" "/>
+            <name and="text" delimiter=", "/>
+          </names>
+          <names variable="director" delimiter=". ">
+            <label form="verb" text-case="capitalize-first" suffix=" "/>
+            <name and="text" delimiter=", "/>
+          </names>
+        </group>
+      </if>
+    </choose>
+  </macro>
+  <macro name="container-contributors">
+    <choose>
+      <if type="chapter paper-conference" match="any">
+        <group prefix=", " delimiter=", ">
+          <names variable="container-author" delimiter=", ">
+            <label form="verb" suffix=" "/>
+            <name and="text" delimiter=", "/>
+          </names>
+          <names variable="editor translator" delimiter=", ">
+            <label form="verb" suffix=" "/>
+            <name and="text" delimiter=", "/>
+          </names>
+        </group>
+      </if>
+    </choose>
+  </macro>
+  <macro name="editor">
+    <names variable="editor">
+      <name name-as-sort-order="first" and="text" sort-separator=", " 
delimiter=", " delimiter-precedes-last="always"/>
+      <label form="short" prefix=", "/>
+    </names>
+  </macro>
+  <macro name="translator">
+    <names variable="translator">
+      <name name-as-sort-order="first" and="text" sort-separator=", " 
delimiter=", " delimiter-precedes-last="always"/>
+      <label form="short" prefix=", "/>
+    </names>
+  </macro>
+  <macro name="recipient">
+    <choose>
+      <if type="personal_communication">
+        <choose>
+          <if variable="genre">
+            <text variable="genre" text-case="capitalize-first"/>
+          </if>
+          <else>
+            <text term="letter" text-case="capitalize-first"/>
+          </else>
+        </choose>
+      </if>
+    </choose>
+    <names variable="recipient" delimiter=", ">
+      <label form="verb" prefix=" " text-case="lowercase" suffix=" "/>
+      <name and="text" delimiter=", "/>
+    </names>
+  </macro>
+  <macro name="substitute-title">
+    <choose>
+      <if type="article-magazine article-newspaper review review-book" 
match="any">
+        <text macro="container-title"/>
+      </if>
+    </choose>
+  </macro>
+  <macro name="contributors">
+    <group delimiter=". ">
+      <names variable="author">
+        <name and="text" name-as-sort-order="first" sort-separator=", " 
delimiter=", " delimiter-precedes-last="always"/>
+        <label form="short" prefix=", "/>
+        <substitute>
+          <names variable="editor"/>
+          <names variable="translator"/>
+          <names variable="director"/>
+          <text macro="substitute-title"/>
+          <text macro="title"/>
+        </substitute>
+      </names>
+      <text macro="recipient"/>
+    </group>
+  </macro>
+  <macro name="contributors-short">
+    <names variable="author">
+      <name form="short" and="text" delimiter=", " initialize-with=". "/>
+      <substitute>
+        <names variable="editor"/>
+        <names variable="translator"/>
+        <names variable="director"/>
+        <text macro="substitute-title"/>
+        <text macro="title"/>
+      </substitute>
+    </names>
+  </macro>
+  <macro name="interviewer">
+    <names variable="interviewer" delimiter=", ">
+      <label form="verb" prefix=" " text-case="capitalize-first" suffix=" "/>
+      <name and="text" delimiter=", "/>
+    </names>
+  </macro>
+  <macro name="archive">
+    <group delimiter=". ">
+      <text variable="archive_location" text-case="capitalize-first"/>
+      <text variable="archive"/>
+      <text variable="archive-place"/>
+    </group>
+  </macro>
+  <macro name="access">
+    <group delimiter=". ">
+      <choose>
+        <if type="graphic report" match="any">
+          <text macro="archive"/>
+        </if>
+        <else-if type="article-journal bill book chapter legal_case 
legislation motion_picture paper-conference" match="none">
+          <text macro="archive"/>
+        </else-if>
+      </choose>
+      <choose>
+        <if type="webpage post-weblog" match="any">
+          <date variable="issued" form="text"/>
+        </if>
+      </choose>
+      <choose>
+        <if variable="issued" match="none">
+          <group delimiter=" ">
+            <text term="accessed" text-case="capitalize-first"/>
+            <date variable="accessed" form="text"/>
+          </group>
+        </if>
+      </choose>
+      <choose>
+        <if type="legal_case" match="none">
+          <choose>
+            <if variable="DOI">
+              <text variable="DOI" prefix="https://doi.org/"/>
+            </if>
+            <else>
+              <text variable="URL"/>
+            </else>
+          </choose>
+        </if>
+      </choose>
+    </group>
+  </macro>
+  <macro name="title">
+    <choose>
+      <if variable="title" match="none">
+        <choose>
+          <if type="personal_communication" match="none">
+            <text variable="genre" text-case="capitalize-first"/>
+          </if>
+        </choose>
+      </if>
+      <else-if type="bill book graphic legislation motion_picture song" 
match="any">
+        <text variable="title" text-case="title" font-style="italic"/>
+        <group prefix=" (" suffix=")" delimiter=" ">
+          <text term="version"/>
+          <text variable="version"/>
+        </group>
+      </else-if>
+      <else-if variable="reviewed-author">
+        <choose>
+          <if variable="reviewed-title">
+            <group delimiter=". ">
+              <text variable="title" text-case="title" quotes="true"/>
+              <group delimiter=", ">
+                <text variable="reviewed-title" text-case="title" 
font-style="italic" prefix="Review of "/>
+                <names variable="reviewed-author">
+                  <label form="verb-short" text-case="lowercase" suffix=" "/>
+                  <name and="text" delimiter=", "/>
+                </names>
+              </group>
+            </group>
+          </if>
+          <else>
+            <group delimiter=", ">
+              <text variable="title" text-case="title" font-style="italic" 
prefix="Review of "/>
+              <names variable="reviewed-author">
+                <label form="verb-short" text-case="lowercase" suffix=" "/>
+                <name and="text" delimiter=", "/>
+              </names>
+            </group>
+          </else>
+        </choose>
+      </else-if>
+      <else-if type="legal_case interview patent" match="any">
+        <text variable="title"/>
+      </else-if>
+      <else>
+        <text variable="title" text-case="title" quotes="true"/>
+      </else>
+    </choose>
+  </macro>
+  <macro name="edition">
+    <choose>
+      <if type="bill book graphic legal_case legislation motion_picture report 
song" match="any">
+        <choose>
+          <if is-numeric="edition">
+            <group delimiter=" " prefix=". ">
+              <number variable="edition" form="ordinal"/>
+              <text term="edition" form="short" strip-periods="true"/>
+            </group>
+          </if>
+          <else>
+            <text variable="edition" text-case="capitalize-first" prefix=". "/>
+          </else>
+        </choose>
+      </if>
+      <else-if type="chapter paper-conference" match="any">
+        <choose>
+          <if is-numeric="edition">
+            <group delimiter=" " prefix=", ">
+              <number variable="edition" form="ordinal"/>
+              <text term="edition" form="short"/>
+            </group>
+          </if>
+          <else>
+            <text variable="edition" prefix=", "/>
+          </else>
+        </choose>
+      </else-if>
+    </choose>
+  </macro>
+  <macro name="locators">
+    <choose>
+      <if type="article-journal">
+        <choose>
+          <if variable="volume">
+            <text variable="volume" prefix=" "/>
+            <group prefix=" (" suffix=")">
+              <choose>
+                <if variable="issue">
+                  <text variable="issue"/>
+                </if>
+                <else>
+                  <date variable="issued">
+                    <date-part name="month"/>
+                  </date>
+                </else>
+              </choose>
+            </group>
+          </if>
+          <else-if variable="issue">
+            <group delimiter=" " prefix=", ">
+              <text term="issue" form="short"/>
+              <text variable="issue"/>
+              <date variable="issued" prefix="(" suffix=")">
+                <date-part name="month"/>
+              </date>
+            </group>
+          </else-if>
+          <else>
+            <date variable="issued" prefix=", ">
+              <date-part name="month"/>
+            </date>
+          </else>
+        </choose>
+      </if>
+      <else-if type="legal_case">
+        <text variable="volume" prefix=", "/>
+        <text variable="container-title" prefix=" "/>
+        <text variable="page" prefix=" "/>
+      </else-if>
+      <else-if type="bill book graphic legal_case legislation motion_picture 
report song" match="any">
+        <group prefix=". " delimiter=". ">
+          <group>
+            <text term="volume" form="short" text-case="capitalize-first" 
suffix=" "/>
+            <number variable="volume" form="numeric"/>
+          </group>
+          <group>
+            <number variable="number-of-volumes" form="numeric"/>
+            <text term="volume" form="short" prefix=" " plural="true"/>
+          </group>
+        </group>
+      </else-if>
+      <else-if type="chapter paper-conference" match="any">
+        <choose>
+          <if variable="page" match="none">
+            <group prefix=". ">
+              <text term="volume" form="short" text-case="capitalize-first" 
suffix=" "/>
+              <number variable="volume" form="numeric"/>
+            </group>
+          </if>
+        </choose>
+      </else-if>
+    </choose>
+  </macro>
+  <macro name="locators-chapter">
+    <choose>
+      <if type="chapter paper-conference" match="any">
+        <choose>
+          <if variable="page">
+            <group prefix=", ">
+              <text variable="volume" suffix=":"/>
+              <text variable="page"/>
+            </group>
+          </if>
+        </choose>
+      </if>
+    </choose>
+  </macro>
+  <macro name="locators-article">
+    <choose>
+      <if type="article-newspaper">
+        <group prefix=", " delimiter=", ">
+          <group delimiter=" ">
+            <text variable="edition"/>
+            <text term="edition"/>
+          </group>
+          <group>
+            <text term="section" form="short" suffix=" "/>
+            <text variable="section"/>
+          </group>
+        </group>
+      </if>
+      <else-if type="article-journal">
+        <choose>
+          <if variable="volume issue" match="any">
+            <text variable="page" prefix=":"/>
+          </if>
+          <else>
+            <text variable="page" prefix=", "/>
+          </else>
+        </choose>
+      </else-if>
+    </choose>
+  </macro>
+  <macro name="point-locators">
+    <choose>
+      <if variable="locator">
+        <choose>
+          <if locator="page" match="none">
+            <choose>
+              <if type="bill book graphic legal_case legislation 
motion_picture report song" match="any">
+                <choose>
+                  <if variable="volume">
+                    <group>
+                      <text term="volume" form="short" suffix=" "/>
+                      <number variable="volume" form="numeric"/>
+                      <label variable="locator" form="short" prefix=", " 
suffix=" "/>
+                    </group>
+                  </if>
+                  <else>
+                    <label variable="locator" form="short" suffix=" "/>
+                  </else>
+                </choose>
+              </if>
+              <else>
+                <label variable="locator" form="short" suffix=" "/>
+              </else>
+            </choose>
+          </if>
+          <else-if type="bill book graphic legal_case legislation 
motion_picture report song" match="any">
+            <number variable="volume" form="numeric" suffix=":"/>
+          </else-if>
+        </choose>
+        <text variable="locator"/>
+      </if>
+    </choose>
+  </macro>
+  <macro name="container-prefix">
+    <text term="in" text-case="capitalize-first"/>
+  </macro>
+  <macro name="container-title">
+    <choose>
+      <if type="chapter paper-conference" match="any">
+        <text macro="container-prefix" suffix=" "/>
+      </if>
+    </choose>
+    <choose>
+      <if type="webpage">
+        <text variable="container-title" text-case="title"/>
+      </if>
+      <else-if type="legal_case" match="none">
+       <group delimiter=" ">
+        <text variable="container-title" text-case="title" 
font-style="italic"/>
+       <choose>
+         <if type="post-weblog">
+           <text value="(blog)"/>
+         </if>
+       </choose>
+         </group>
+      </else-if>
+    </choose>
+  </macro>
+  <macro name="publisher">
+    <group delimiter=": ">
+      <text variable="publisher-place"/>
+      <text variable="publisher"/>
+    </group>
+  </macro>
+  <macro name="date">
+    <choose>
+      <if variable="issued">
+        <group delimiter=" ">
+          <date variable="original-date" form="text" date-parts="year" 
prefix="(" suffix=")"/>
+          <date variable="issued">
+            <date-part name="year"/>
+          </date>
+        </group>
+      </if>
+      <else-if variable="status">
+        <text variable="status" text-case="capitalize-first"/>
+      </else-if>
+      <else>
+        <text term="no date" form="short"/>
+      </else>
+    </choose>
+  </macro>
+  <macro name="date-in-text">
+    <choose>
+      <if variable="issued">
+        <group delimiter=" ">
+          <date variable="original-date" form="text" date-parts="year" 
prefix="[" suffix="]"/>
+          <date variable="issued">
+            <date-part name="year"/>
+          </date>
+        </group>
+      </if>
+      <else-if variable="status">
+        <text variable="status"/>
+      </else-if>
+      <else>
+        <text term="no date" form="short"/>
+      </else>
+    </choose>
+  </macro>
+  <macro name="day-month">
+    <date variable="issued">
+      <date-part name="month"/>
+      <date-part name="day" prefix=" "/>
+    </date>
+  </macro>
+  <macro name="collection-title">
+    <choose>
+      <if match="none" type="article-journal">
+        <choose>
+          <if match="none" is-numeric="collection-number">
+            <group delimiter=", ">
+              <text variable="collection-title" text-case="title"/>
+              <text variable="collection-number"/>
+            </group>
+          </if>
+          <else>
+            <group delimiter=" ">
+              <text variable="collection-title" text-case="title"/>
+              <text variable="collection-number"/>
+            </group>
+          </else>
+        </choose>
+      </if>
+    </choose>
+  </macro>
+  <macro name="collection-title-journal">
+    <choose>
+      <if type="article-journal">
+        <group delimiter=" ">
+          <text variable="collection-title"/>
+          <text variable="collection-number"/>
+        </group>
+      </if>
+    </choose>
+  </macro>
+  <macro name="event">
+    <group>
+      <text term="presented at" suffix=" "/>
+      <text variable="event"/>
+    </group>
+  </macro>
+  <macro name="description">
+    <choose>
+      <if type="interview">
+        <group delimiter=". ">
+          <text macro="interviewer"/>
+          <text variable="medium" text-case="capitalize-first"/>
+        </group>
+      </if>
+      <else-if type="patent">
+        <group delimiter=" " prefix=". ">
+          <text variable="authority"/>
+          <text variable="number"/>
+        </group>
+      </else-if>
+      <else>
+        <text variable="medium" text-case="capitalize-first" prefix=". "/>
+      </else>
+    </choose>
+    <choose>
+      <if variable="title" match="none"/>
+      <else-if type="thesis personal_communication speech" match="any"/>
+      <else>
+        <group delimiter=" " prefix=". ">
+          <text variable="genre" text-case="capitalize-first"/>
+          <choose>
+            <if type="report">
+              <text variable="number"/>
+            </if>
+          </choose>
+        </group>
+      </else>
+    </choose>
+  </macro>
+  <macro name="issue">
+    <choose>
+      <if type="legal_case">
+        <text variable="authority" prefix=". "/>
+      </if>
+      <else-if type="speech">
+        <group prefix=". " delimiter=", ">
+          <group delimiter=" ">
+            <text variable="genre" text-case="capitalize-first"/>
+            <text macro="event"/>
+          </group>
+          <text variable="event-place"/>
+          <text macro="day-month"/>
+        </group>
+      </else-if>
+      <else-if type="article-newspaper article-magazine 
personal_communication" match="any">
+        <date variable="issued" form="text" prefix=", "/>
+      </else-if>
+      <else-if type="patent">
+        <group delimiter=", " prefix=", ">
+          <group delimiter=" ">
+            <!--Needs Localization-->
+            <text value="filed"/>
+            <date variable="submitted" form="text"/>
+          </group>
+          <group delimiter=" ">
+            <choose>
+              <if variable="issued submitted" match="all">
+                <text term="and"/>
+              </if>
+            </choose>
+            <!--Needs Localization-->
+            <text value="issued"/>
+            <date variable="issued" form="text"/>
+          </group>
+        </group>
+      </else-if>
+      <else>
+        <group prefix=". " delimiter=", ">
+          <choose>
+            <if type="thesis">
+              <text variable="genre" text-case="capitalize-first"/>
+            </if>
+          </choose>
+          <text macro="publisher"/>
+        </group>
+      </else>
+    </choose>
+  </macro>
+  <citation et-al-min="4" et-al-use-first="1" 
disambiguate-add-year-suffix="true" disambiguate-add-names="true" 
disambiguate-add-givenname="true" givenname-disambiguation-rule="primary-name" 
collapse="year">
+    <layout prefix="(" suffix=")" delimiter="; ">
+      <group delimiter=", ">
+        <choose>
+          <if variable="issued accessed" match="any">
+            <group delimiter=" ">
+              <text macro="contributors-short"/>
+              <text macro="date-in-text"/>
+            </group>
+          </if>
+          <!---comma before forthcoming and n.d.-->
+          <else>
+            <group delimiter=", ">
+              <text macro="contributors-short"/>
+              <text macro="date-in-text"/>
+            </group>
+          </else>
+        </choose>
+        <text macro="point-locators"/>
+      </group>
+    </layout>
+  </citation>
+  <bibliography hanging-indent="true" et-al-min="11" et-al-use-first="7" 
subsequent-author-substitute="&#8212;&#8212;&#8212;" entry-spacing="0">
+    <sort>
+      <key macro="contributors"/>
+      <key variable="issued"/>
+      <key variable="title"/>
+    </sort>
+    <layout suffix=".">
+      <group delimiter=". ">
+        <text macro="contributors"/>
+        <text macro="date"/>
+        <text macro="title"/>
+      </group>
+      <text macro="description"/>
+      <text macro="secondary-contributors" prefix=". "/>
+      <text macro="container-title" prefix=". "/>
+      <text macro="container-contributors"/>
+      <text macro="edition"/>
+      <text macro="locators-chapter"/>
+      <text macro="collection-title-journal" prefix=", " suffix=", "/>
+      <text macro="locators"/>
+      <text macro="collection-title" prefix=". "/>
+      <text macro="issue"/>
+      <text macro="locators-article"/>
+      <text macro="access" prefix=". "/>
+    </layout>
+  </bibliography>
+</style>
diff --git a/etc/csl/locales-en-US.xml b/etc/csl/locales-en-US.xml
new file mode 100644
index 0000000..a5e95df
--- /dev/null
+++ b/etc/csl/locales-en-US.xml
@@ -0,0 +1,348 @@
+<?xml version="1.0" encoding="utf-8"?>
+<locale xmlns="http://purl.org/net/xbiblio/csl"; version="1.0" xml:lang="en-US">
+  <info>
+    <rights license="http://creativecommons.org/licenses/by-sa/3.0/";>This work 
is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights>
+    <updated>2015-10-10T23:31:02+00:00</updated>
+  </info>
+  <style-options punctuation-in-quote="true"/>
+  <date form="text">
+    <date-part name="month" suffix=" "/>
+    <date-part name="day" suffix=", "/>
+    <date-part name="year"/>
+  </date>
+  <date form="numeric">
+    <date-part name="month" form="numeric-leading-zeros" suffix="/"/>
+    <date-part name="day" form="numeric-leading-zeros" suffix="/"/>
+    <date-part name="year"/>
+  </date>
+  <terms>
+    <term name="accessed">accessed</term>
+    <term name="and">and</term>
+    <term name="and others">and others</term>
+    <term name="anonymous">anonymous</term>
+    <term name="anonymous" form="short">anon.</term>
+    <term name="at">at</term>
+    <term name="available at">available at</term>
+    <term name="by">by</term>
+    <term name="circa">circa</term>
+    <term name="circa" form="short">c.</term>
+    <term name="cited">cited</term>
+    <term name="edition">
+      <single>edition</single>
+      <multiple>editions</multiple>
+    </term>
+    <term name="edition" form="short">ed.</term>
+    <term name="et-al">et al.</term>
+    <term name="forthcoming">forthcoming</term>
+    <term name="from">from</term>
+    <term name="ibid">ibid.</term>
+    <term name="in">in</term>
+    <term name="in press">in press</term>
+    <term name="internet">internet</term>
+    <term name="interview">interview</term>
+    <term name="letter">letter</term>
+    <term name="no date">no date</term>
+    <term name="no date" form="short">n.d.</term>
+    <term name="online">online</term>
+    <term name="presented at">presented at the</term>
+    <term name="reference">
+      <single>reference</single>
+      <multiple>references</multiple>
+    </term>
+    <term name="reference" form="short">
+      <single>ref.</single>
+      <multiple>refs.</multiple>
+    </term>
+    <term name="retrieved">retrieved</term>
+    <term name="scale">scale</term>
+    <term name="version">version</term>
+
+    <!-- ANNO DOMINI; BEFORE CHRIST -->
+    <term name="ad">AD</term>
+    <term name="bc">BC</term>
+
+    <!-- PUNCTUATION -->
+    <term name="open-quote">โ€œ</term>
+    <term name="close-quote">โ€</term>
+    <term name="open-inner-quote">โ€˜</term>
+    <term name="close-inner-quote">โ€™</term>
+    <term name="page-range-delimiter">โ€“</term>
+
+    <!-- ORDINALS -->
+    <term name="ordinal">th</term>
+    <term name="ordinal-01">st</term>
+    <term name="ordinal-02">nd</term>
+    <term name="ordinal-03">rd</term>
+    <term name="ordinal-11">th</term>
+    <term name="ordinal-12">th</term>
+    <term name="ordinal-13">th</term>
+
+    <!-- LONG ORDINALS -->
+    <term name="long-ordinal-01">first</term>
+    <term name="long-ordinal-02">second</term>
+    <term name="long-ordinal-03">third</term>
+    <term name="long-ordinal-04">fourth</term>
+    <term name="long-ordinal-05">fifth</term>
+    <term name="long-ordinal-06">sixth</term>
+    <term name="long-ordinal-07">seventh</term>
+    <term name="long-ordinal-08">eighth</term>
+    <term name="long-ordinal-09">ninth</term>
+    <term name="long-ordinal-10">tenth</term>
+
+    <!-- LONG LOCATOR FORMS -->
+    <term name="book">
+      <single>book</single>
+      <multiple>books</multiple>
+    </term>
+    <term name="chapter">
+      <single>chapter</single>
+      <multiple>chapters</multiple>
+    </term>
+    <term name="column">
+      <single>column</single>
+      <multiple>columns</multiple>
+    </term>
+    <term name="figure">
+      <single>figure</single>
+      <multiple>figures</multiple>
+    </term>
+    <term name="folio">
+      <single>folio</single>
+      <multiple>folios</multiple>
+    </term>
+    <term name="issue">
+      <single>number</single>
+      <multiple>numbers</multiple>
+    </term>
+    <term name="line">
+      <single>line</single>
+      <multiple>lines</multiple>
+    </term>
+    <term name="note">
+      <single>note</single>
+      <multiple>notes</multiple>
+    </term>
+    <term name="opus">
+      <single>opus</single>
+      <multiple>opera</multiple>
+    </term>
+    <term name="page">
+      <single>page</single>
+      <multiple>pages</multiple>
+    </term>
+    <term name="number-of-pages">
+      <single>page</single>
+      <multiple>pages</multiple>
+    </term>
+    <term name="paragraph">
+      <single>paragraph</single>
+      <multiple>paragraphs</multiple>
+    </term>
+    <term name="part">
+      <single>part</single>
+      <multiple>parts</multiple>
+    </term>
+    <term name="section">
+      <single>section</single>
+      <multiple>sections</multiple>
+    </term>
+    <term name="sub verbo">
+      <single>sub verbo</single>
+      <multiple>sub verbis</multiple>
+    </term>
+    <term name="verse">
+      <single>verse</single>
+      <multiple>verses</multiple>
+    </term>
+    <term name="volume">
+      <single>volume</single>
+      <multiple>volumes</multiple>
+    </term>
+
+    <!-- SHORT LOCATOR FORMS -->
+    <term name="book" form="short">
+      <single>bk.</single>
+      <multiple>bks.</multiple>
+    </term>
+    <term name="chapter" form="short">
+      <single>chap.</single>
+      <multiple>chaps.</multiple>
+    </term>
+    <term name="column" form="short">
+      <single>col.</single>
+      <multiple>cols.</multiple>
+    </term>
+    <term name="figure" form="short">
+      <single>fig.</single>
+      <multiple>figs.</multiple>
+    </term>
+    <term name="folio" form="short">
+      <single>fol.</single>
+      <multiple>fols.</multiple>
+    </term>
+    <term name="issue" form="short">
+      <single>no.</single>
+      <multiple>nos.</multiple>
+    </term>
+    <term name="line" form="short">
+      <single>l.</single>
+      <multiple>ll.</multiple>
+    </term>
+    <term name="note" form="short">
+      <single>n.</single>
+      <multiple>nn.</multiple>
+    </term>
+    <term name="opus" form="short">
+      <single>op.</single>
+      <multiple>opp.</multiple>
+    </term>
+    <term name="page" form="short">
+      <single>p.</single>
+      <multiple>pp.</multiple>
+    </term>
+    <term name="number-of-pages" form="short">
+      <single>p.</single>
+      <multiple>pp.</multiple>
+    </term>
+    <term name="paragraph" form="short">
+      <single>para.</single>
+      <multiple>paras.</multiple>
+    </term>
+    <term name="part" form="short">
+      <single>pt.</single>
+      <multiple>pts.</multiple>
+    </term>
+    <term name="section" form="short">
+      <single>sec.</single>
+      <multiple>secs.</multiple>
+    </term>
+    <term name="sub verbo" form="short">
+      <single>s.v.</single>
+      <multiple>s.vv.</multiple>
+    </term>
+    <term name="verse" form="short">
+      <single>v.</single>
+      <multiple>vv.</multiple>
+    </term>
+    <term name="volume" form="short">
+      <single>vol.</single>
+      <multiple>vols.</multiple>
+    </term>
+
+    <!-- SYMBOL LOCATOR FORMS -->
+    <term name="paragraph" form="symbol">
+      <single>ยถ</single>
+      <multiple>ยถยถ</multiple>
+    </term>
+    <term name="section" form="symbol">
+      <single>ยง</single>
+      <multiple>ยงยง</multiple>
+    </term>
+
+    <!-- LONG ROLE FORMS -->
+    <term name="director">
+      <single>director</single>
+      <multiple>directors</multiple>
+    </term>
+    <term name="editor">
+      <single>editor</single>
+      <multiple>editors</multiple>
+    </term>
+    <term name="editorial-director">
+      <single>editor</single>
+      <multiple>editors</multiple>
+    </term>
+    <term name="illustrator">
+      <single>illustrator</single>
+      <multiple>illustrators</multiple>
+    </term>
+    <term name="translator">
+      <single>translator</single>
+      <multiple>translators</multiple>
+    </term>
+    <term name="editortranslator">
+      <single>editor &amp; translator</single>
+      <multiple>editors &amp; translators</multiple>
+    </term>
+
+    <!-- SHORT ROLE FORMS -->
+    <term name="director" form="short">
+      <single>dir.</single>
+      <multiple>dirs.</multiple>
+    </term>
+    <term name="editor" form="short">
+      <single>ed.</single>
+      <multiple>eds.</multiple>
+    </term>
+    <term name="editorial-director" form="short">
+      <single>ed.</single>
+      <multiple>eds.</multiple>
+    </term>
+    <term name="illustrator" form="short">
+      <single>ill.</single>
+      <multiple>ills.</multiple>
+    </term>
+    <term name="translator" form="short">
+      <single>tran.</single>
+      <multiple>trans.</multiple>
+    </term>
+    <term name="editortranslator" form="short">
+      <single>ed. &amp; tran.</single>
+      <multiple>eds. &amp; trans.</multiple>
+    </term>
+
+    <!-- VERB ROLE FORMS -->
+    <term name="container-author" form="verb">by</term>
+    <term name="director" form="verb">directed by</term>
+    <term name="editor" form="verb">edited by</term>
+    <term name="editorial-director" form="verb">edited by</term>
+    <term name="illustrator" form="verb">illustrated by</term>
+    <term name="interviewer" form="verb">interview by</term>
+    <term name="recipient" form="verb">to</term>
+    <term name="reviewed-author" form="verb">by</term>
+    <term name="translator" form="verb">translated by</term>
+    <term name="editortranslator" form="verb">edited &amp; translated by</term>
+
+    <!-- SHORT VERB ROLE FORMS -->
+    <term name="director" form="verb-short">dir. by</term>
+    <term name="editor" form="verb-short">ed. by</term>
+    <term name="editorial-director" form="verb-short">ed. by</term>
+    <term name="illustrator" form="verb-short">illus. by</term>
+    <term name="translator" form="verb-short">trans. by</term>
+    <term name="editortranslator" form="verb-short">ed. &amp; trans. by</term>
+
+    <!-- LONG MONTH FORMS -->
+    <term name="month-01">January</term>
+    <term name="month-02">February</term>
+    <term name="month-03">March</term>
+    <term name="month-04">April</term>
+    <term name="month-05">May</term>
+    <term name="month-06">June</term>
+    <term name="month-07">July</term>
+    <term name="month-08">August</term>
+    <term name="month-09">September</term>
+    <term name="month-10">October</term>
+    <term name="month-11">November</term>
+    <term name="month-12">December</term>
+
+    <!-- SHORT MONTH FORMS -->
+    <term name="month-01" form="short">Jan.</term>
+    <term name="month-02" form="short">Feb.</term>
+    <term name="month-03" form="short">Mar.</term>
+    <term name="month-04" form="short">Apr.</term>
+    <term name="month-05" form="short">May</term>
+    <term name="month-06" form="short">Jun.</term>
+    <term name="month-07" form="short">Jul.</term>
+    <term name="month-08" form="short">Aug.</term>
+    <term name="month-09" form="short">Sep.</term>
+    <term name="month-10" form="short">Oct.</term>
+    <term name="month-11" form="short">Nov.</term>
+    <term name="month-12" form="short">Dec.</term>
+
+    <!-- SEASONS -->
+    <term name="season-01">Spring</term>
+    <term name="season-02">Summer</term>
+    <term name="season-03">Autumn</term>
+    <term name="season-04">Winter</term>
+  </terms>
+</locale>
diff --git a/etc/schema/OpenDocument-schema-v1.3+libreoffice.rnc 
b/etc/schema/OpenDocument-schema-v1.3+libreoffice.rnc
new file mode 100644
index 0000000..5239c84
--- /dev/null
+++ b/etc/schema/OpenDocument-schema-v1.3+libreoffice.rnc
@@ -0,0 +1,892 @@
+# Open Document Format for Office Applications (OpenDocument) Version 1.3
+# OASIS Standard, In progress
+# Relax-NG Schema
+# Source: https://tools.oasis-open.org/version-control/svn/office/
+# Copyright (c) OASIS Open 2002-2015. 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 calcext =
+  "urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0"
+namespace chart = "urn:oasis:names:tc:opendocument:xmlns:chart:1.0"
+namespace chartooo = "http://openoffice.org/2010/chart";
+namespace config = "urn:oasis:names:tc:opendocument:xmlns:config:1.0"
+namespace css3t = "http://www.w3.org/TR/css3-text/";
+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 drawooo = "http://openoffice.org/2010/draw";
+namespace field =
+  "urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field: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 loext =
+  "urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0"
+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 officeooo = "http://openoffice.org/2009/office";
+namespace presentation =
+  "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0"
+namespace rng = "http://relaxng.org/ns/structure/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 tableooo = "http://openoffice.org/2009/table";
+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";
+
+include "OpenDocument-schema-v1.3.rnc" {
+  office-document-common-attrs =
+    attribute office:version {
+      # FIXME remove this hack once we write 1.3
+      "1.3" | "1.2"
+    }
+    & attribute grddl:transformation {
+        list { anyIRI* }
+      }?
+  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 }?
+    & # FIXME remove this once the export bug is fixed
+      attribute draw:fit-to-size {
+        "true" | "false" | "all" | "shrink-to-fit"
+      }?
+    & 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 { signedZeroToHundredPercent }
+      # https://issues.oasis-open.org/browse/OFFICE-3821
+      ?
+    & 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 }?
+    & # TODO: no proposal for loext:shadow-blur
+      attribute loext:shadow-blur { length }?
+    & 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 }?
+    & # https://issues.oasis-open.org/browse/OFFICE-4047
+      attribute loext:allow-overlap { boolean }?
+    & # TODO: no proposal for loext:glow*
+      attribute loext:glow-radius { length }?
+    & attribute loext:glow-color { color }?
+    & attribute loext:glow-transparency { zeroToHundredPercent }?
+    & # TODO: no proposal for loext:softedge-radius
+      attribute loext:softedge-radius { length }?
+  draw-text =
+    (text-p
+     | text-list
+     | # https://issues.oasis-open.org/browse/OFFICE-3761
+       loext-table)*
+  office-annotation-attlist &=
+    attribute office:display { boolean }?
+    & common-office-annotation-name-attlist?
+    & attribute loext:resolved { boolean }?
+  style-style-content =
+    (attribute style:family { "text" },
+     style-text-properties?)
+    | (attribute style:family { "paragraph" },
+       # TODO no proposal
+       loext-graphic-properties?,
+       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" },
+       # TODO no proposal
+       loext-graphic-properties?,
+       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?)
+  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?,
+      # TODO no proposal
+      table-first-row-even-column?,
+      table-last-row-even-column?,
+      table-first-row-end-column?,
+      table-first-row-start-column?,
+      table-last-row-end-column?,
+      table-last-row-start-column?
+    }
+  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)?,
+      # TODO no proposal
+      loext-signatureline?,
+      loext-qrcode?
+    }
+  common-value-and-type-attlist =
+    (attribute office:value-type { "float" },
+     attribute calcext:value-type { "float" }?,
+     attribute office:value { double })
+    | (attribute office:value-type { "percentage" },
+       attribute calcext:value-type { "percentage" }?,
+       attribute office:value { double })
+    | (attribute office:value-type { "currency" },
+       attribute calcext:value-type { "currency" }?,
+       attribute office:value { double },
+       attribute office:currency { \string }?)
+    | (attribute office:value-type { "date" },
+       attribute calcext:value-type { "date" }?,
+       attribute office:date-value { dateOrDateTime })
+    | (attribute office:value-type { "time" },
+       attribute calcext:value-type { "time" }?,
+       attribute office:time-value { duration })
+    | (attribute office:value-type { "boolean" },
+       attribute calcext:value-type { "boolean" }?,
+       attribute office:boolean-value { boolean })
+    | (attribute office:value-type { "string" },
+       # OFFICE-3759
+       attribute calcext:value-type { "string" | "error" }?,
+       attribute office:string-value { \string }?)
+  chart-axis =
+    element chart:axis {
+      chart-axis-attlist,
+      # OFFICE-2119
+      ((attribute chartooo:axis-type { "auto" },
+        chartooo-date-scale?)
+       | (attribute chartooo:axis-type { "date" },
+          chartooo-date-scale)
+       | attribute chartooo:axis-type { "text" })?,
+      chart-title?,
+      chart-categories?,
+      chart-grid*
+    }
+  table-table =
+    element table:table {
+      table-table-attlist,
+      table-title?,
+      table-desc?,
+      # TODO add to proposal, OFFICE-2112
+      table-table-protection?,
+      table-table-source?,
+      office-dde-source?,
+      table-scenario?,
+      office-forms?,
+      table-shapes?,
+      table-columns-and-groups,
+      table-rows-and-groups,
+      table-named-expressions?,
+      # TODO no proposal, this is wild guessing, OFFICE-3785
+      element calcext:conditional-formats {
+        element calcext:conditional-format {
+          attribute calcext:target-range-address { cellRangeAddress },
+          (element calcext:condition {
+             attribute calcext:apply-style-name { styleNameRef },
+             attribute calcext:value { \string },
+             attribute calcext:base-cell-address { cellAddress }
+           }+
+           | element calcext:data-bar {
+               attribute calcext:max-length { \string },
+               attribute calcext:negative-color { color },
+               attribute calcext:positive-color { color },
+               attribute calcext:axis-color { color },
+               attribute calcext:axis-position { "middle" }?,
+               element calcext:formatting-entry {
+                 attribute calcext:value { \string },
+                 attribute calcext:type {
+                   "auto-minimum"
+                   | "auto-maximum"
+                   | "minimum"
+                   | "maximum"
+                   | "percent"
+                   | "percentile"
+                   | "number"
+                   | "formula"
+                 }
+               },
+               element calcext:formatting-entry {
+                 attribute calcext:value { \string },
+                 attribute calcext:type {
+                   "auto-minimum"
+                   | "auto-maximum"
+                   | "minimum"
+                   | "maximum"
+                   | "percent"
+                   | "percentile"
+                   | "number"
+                   | "formula"
+                 }
+               }
+             }
+           | element calcext:color-scale {
+               element calcext:color-scale-entry {
+                 attribute calcext:value { \string },
+                 attribute calcext:type {
+                   "minimum"
+                   | "maximum"
+                   | "percent"
+                   | "percentile"
+                   | "number"
+                   | "formula"
+                 },
+                 attribute calcext:color { color }
+               },
+               element calcext:color-scale-entry {
+                 attribute calcext:value { \string },
+                 attribute calcext:type {
+                   "minimum"
+                   | "maximum"
+                   | "percent"
+                   | "percentile"
+                   | "number"
+                   | "formula"
+                 },
+                 attribute calcext:color { color }
+               },
+               element calcext:color-scale-entry {
+                 attribute calcext:value { \string },
+                 attribute calcext:type {
+                   "minimum"
+                   | "maximum"
+                   | "percent"
+                   | "percentile"
+                   | "number"
+                   | "formula"
+                 },
+                 attribute calcext:color { color }
+               }?
+             })
+        }+
+      }?
+    }
+  # TODO no proposal
+  draw-object =
+    element draw:object {
+      draw-object-attlist,
+      loext-text,
+      (common-draw-data-attlist | office-document | math-math)
+    }
+  draw-object-ole =
+    element draw:object-ole {
+      draw-object-ole-attlist,
+      loext-text,
+      (common-draw-data-attlist | office-binary-data)
+    }
+  # FIXME: one test exports 250 here, which is probably a bug
+  fontWeight =
+    "normal"
+    | "bold"
+    | "100"
+    | "200"
+    | "250"
+    | "300"
+    | "400"
+    | "500"
+    | "600"
+    | "700"
+    | "800"
+    | "900"
+}
+# TODO no proposal
+loext-p =
+  element loext:p { paragraph-attrs, paragraph-content-or-hyperlink* }
+loext-text = (loext-p | text-list | loext-table)*
+# OFFICE-2119
+chartooo-date-scale =
+  element chartooo:date-scale {
+    attribute chart:base-time-unit { chart-time-unit }?
+    & (attribute chart:major-interval-value { positiveInteger },
+       attribute chart:major-interval-unit { chart-time-unit })?
+    & (attribute chart:minor-interval-value { positiveInteger },
+       attribute chart:minor-interval-unit { chart-time-unit })?
+  }
+chart-time-unit = "days" | "months" | "years"
+# TODO no proposal
+loext-signatureline =
+  element loext:signatureline {
+    attribute loext:id { \string },
+    attribute loext:suggested-signer-name { \string },
+    attribute loext:suggested-signer-title { \string },
+    attribute loext:suggested-signer-email { \string },
+    attribute loext:signing-instructions { \string },
+    attribute loext:show-sign-date { boolean },
+    attribute loext:can-add-comment { boolean }
+  }
+loext-qrcode =
+  element loext:qrcode {
+    attribute office:string-value { \string },
+    attribute loext:qrcode-errorcorrection {
+      "low" | "medium" | "quartile" | "high"
+    },
+    attribute loext:qrcode-border { nonNegativeInteger }
+  }
+# https://issues.oasis-open.org/browse/OFFICE-3761
+loext-table =
+  element loext:table {
+    table-table-attlist,
+    table-title?,
+    table-desc?,
+    table-table-source?,
+    office-dde-source?,
+    table-scenario?,
+    office-forms?,
+    table-shapes?,
+    loext-columns-and-groups,
+    loext-rows-and-groups,
+    table-named-expressions?
+  }
+loext-rows-and-groups = (table-table-row-group | loext-rows-no-group)+
+loext-rows-no-group =
+  (loext-rows, (table-table-header-rows, loext-rows?)?)
+  | (table-table-header-rows, loext-rows?)
+loext-rows =
+  table-table-rows | (text-soft-page-break?, loext-table-row)+
+loext-table-row =
+  element loext:table-row {
+    table-table-row-attlist,
+    (loext-table-cell | loext-covered-table-cell)+
+  }
+loext-table-cell =
+  element loext:table-cell {
+    table-table-cell-attlist,
+    table-table-cell-attlist-extra,
+    table-table-cell-content
+  }
+loext-covered-table-cell =
+  element loext:covered-table-cell {
+    table-table-cell-attlist, table-table-cell-content
+  }
+loext-columns-and-groups =
+  (table-table-column-group | loext-columns-no-group)+
+loext-columns-no-group =
+  (loext-columns, (table-table-header-columns, loext-columns?)?)
+  | (table-table-header-columns, loext-columns?)
+loext-columns = loext-table-columns | loext-table-column+
+loext-table-columns =
+  element loext:table-columns { loext-table-column+ }
+loext-table-column =
+  element loext:table-column { table-table-column-attlist, empty }
+loext-graphic-properties =
+  element loext:graphic-properties {
+    style-graphic-properties-content-strict
+  }
+table-first-row-even-column =
+  element loext:first-row-even-column {
+    common-table-template-attlist, empty
+  }
+table-last-row-even-column =
+  element loext:last-row-even-column {
+    common-table-template-attlist, empty
+  }
+table-first-row-end-column =
+  element loext:first-row-end-column {
+    common-table-template-attlist, empty
+  }
+table-first-row-start-column =
+  element loext:first-row-start-column {
+    common-table-template-attlist, empty
+  }
+table-last-row-end-column =
+  element loext:last-row-end-column {
+    common-table-template-attlist, empty
+  }
+table-last-row-start-column =
+  element loext:last-row-start-column {
+    common-table-template-attlist, empty
+  }
+common-draw-rel-size-attlist &=
+  # OFFICE-3854
+  attribute loext:rel-width-rel {
+    "page"
+    | [
+        # TODO layout-environment ?
+
+      ]
+      "paragraph"
+  }?,
+  attribute loext:rel-height-rel { "page" | "paragraph" }?
+common-svg-font-face-xlink-attlist &=
+  # TODO no proposal
+  attribute loext:font-style { fontStyle }?,
+  attribute loext:font-weight { fontWeight }?
+# TODO no proposal
+
+# there's no ref-attrs so add it here
+text-common-ref-content &=
+  attribute loext:reference-language { language }?
+style-list-level-label-alignment-attlist &=
+  # TODO no proposal
+  attribute loext:label-followed-by {
+    "listtab" | "space" | "nothing" | "newline"
+  }?
+style-ruby-properties-attlist &=
+  # TODO proposal, OFFICE-3944
+  attribute loext:ruby-position {
+    "above" | "below" | "inter-character"
+  }?
+style-text-properties-attlist &=
+  # TODO no proposal
+  attribute officeooo:rsid { \string }?,
+  attribute officeooo:paragraph-rsid { \string }?,
+  # https://issues.oasis-open.org/browse/OFFICE-4049
+  attribute loext:opacity { zeroToHundredPercent }?
+style-text-properties-attlist &=
+  # OFFICE-3843
+  attribute loext:padding { nonNegativeLength }?,
+  attribute loext:padding-left { nonNegativeLength }?,
+  attribute loext:padding-right { nonNegativeLength }?,
+  attribute loext:padding-top { nonNegativeLength }?,
+  attribute loext:padding-bottom { nonNegativeLength }?,
+  attribute loext:border { \string }?,
+  attribute loext:border-left { \string }?,
+  attribute loext:border-right { \string }?,
+  attribute loext:border-top { \string }?,
+  attribute loext:border-bottom { \string }?,
+  attribute loext:shadow { shadowType }?
+# TODO no proposal
+style-chart-properties-attlist &=
+  attribute loext:try-staggering-first { boolean }?
+# TODO no proposal
+style-chart-properties-attlist &=
+  attribute loext:std-weight { \string }?
+# TODO no proposal
+chart-series-attlist &= attribute loext:label-string { \string }?
+# OFFICE-1148
+style-chart-properties-attlist &=
+  attribute loext:regression-max-degree { positiveInteger }?,
+  attribute loext:regression-force-intercept { boolean }?,
+  attribute loext:regression-intercept-value { double }?,
+  attribute loext:regression-name { \string }?,
+  attribute loext:regression-period { \string }?,
+  attribute loext:regression-extrapolate-forward { \string }?,
+  attribute loext:regression-extrapolate-backward { \string }?
+# TODO no proposal
+table-data-pilot-field-attlist &=
+  attribute tableooo:display-name { \string }?
+# TODO no proposal, 9009663d
+chart-chart-attlist &= attribute loext:data-pilot-source { \string }?
+# OFFICE-2112, TODO half of this missing in proposal
+table-table-protection =
+  element loext:table-protection {
+    attribute loext:select-protected-cells { boolean }?,
+    attribute loext:select-unprotected-cells { boolean }?,
+    attribute loext:insert-columns { boolean }?,
+    attribute loext:insert-rows { boolean }?,
+    attribute loext:delete-columns { boolean }?,
+    attribute loext:delete-rows { boolean }?
+  }
+office-spreadsheet-attlist &=
+  attribute loext:protection-key-digest-algorithm-2 { anyURI }?
+table-table-attlist &=
+  attribute loext:protection-key-digest-algorithm-2 { anyURI }?
+# https://issues.oasis-open.org/browse/OFFICE-2317
+vertJustifyValues = "auto" | "distribute"
+common-text-justify =
+  attribute css3t:text-justify { vertJustifyValues }?
+style-vertical-justify =
+  attribute loext:vertical-justify { vertJustifyValues }?,
+  attribute style:vertical-justify { vertJustifyValues }?
+style-paragraph-properties-attlist &=
+  (common-text-justify, style-vertical-justify)?
+style-table-cell-properties-attlist &=
+  (common-text-justify, style-vertical-justify)?
+number-fraction-attlist &=
+  # OFFICE-3695
+
+  # TODO no proposal, 1544a26ac9f7dd60605dd21e9cbe29d490aafdce
+  attribute loext:max-numerator-digits { positiveInteger }?
+# TODO no proposal
+table-data-pilot-level-attlist &=
+  attribute calcext:repeat-item-labels { boolean }?
+# TODO no proposal
+draw-enhanced-geometry-attlist &=
+  attribute drawooo:sub-view-size { \string }?,
+  attribute drawooo:enhanced-path { \string }?
+# TODO no proposal
+draw-custom-shape-attlist &= common-draw-rel-size-attlist
+# TODO no proposal
+style-page-layout-properties-attlist &=
+  style-graphic-fill-properties-attlist
+style-header-footer-properties-attlist &=
+  style-graphic-fill-properties-attlist
+# TODO no proposal
+text-index-entry-tab-stop-attrs &= attribute style:with-tab { boolean }?
+# TODO no proposal
+style-text-properties-attlist &=
+  attribute loext:char-shading-value { \string }?
+# TODO no proposal
+text-bookmark-start-attlist &=
+  (attribute loext:hidden { boolean },
+   attribute loext:condition { \string }?)?
+# TODO no proposal; see 7a5d79f2297a43d0a854e304b0792164272edfe0
+
+# FIXME this is almost certainly incomplete: need to figure out which elements 
can have this and which named pattern can be extended with it to get exactly 
these elements
+form-checkbox-attlist &= attribute form:input-required { boolean }?
+# https://issues.oasis-open.org/browse/OFFICE-4030
+common-writing-mode-attlist &= attribute loext:writing-mode { "bt-lr" }?
+# https://issues.oasis-open.org/browse/OFFICE-4073
+common-vertical-rel-attlist &=
+  attribute loext:vertical-rel {
+    "page-content-top" | "page-content-bottom"
+  }?
+# https://issues.oasis-open.org/browse/OFFICE-4105
+style-page-layout-properties-attlist &=
+  attribute loext:margin-gutter { length }?
+# just a test-case for user-defined attributes, move along, nothing to see 
here...
+style-table-cell-properties-attlist &= attribute proName { \string }?
+# TODO no proposal
+chart-data-point-attlist &=
+  attribute loext:custom-label-field { \string }?
+# TODO no proposal
+style-text-properties-attlist &=
+  attribute loext:hyphenation-no-caps { boolean }?
+# TODO no proposal
+chart-data-point-attlist &=
+  (attribute loext:custom-label-pos-x { double },
+   attribute loext:custom-label-pos-y { double })?
+# TODO no proposal
+chart-legend-attlist &= attribute loext:overlay { boolean }?
+# https://issues.oasis-open.org/browse/OFFICE-3936
+style-chart-properties-attlist &=
+  attribute loext:major-origin { double }?
+# TODO no proposal
+text-index-entry-chapter-attrs &=
+  attribute loext:outline-content-visible { boolean }?
+# https://issues.oasis-open.org/browse/OFFICE-2096
+paragraph-content |=
+  element field:fieldmark-start {
+    attribute text:name { \string },
+    attribute field:type {
+      # TODO <rng:ref name="namespacedToken"/>
+      \string
+    },
+    element field:param {
+      attribute field:name { \string },
+      attribute field:value { \string }
+    }*
+  }
+paragraph-content |= element field:fieldmark-end { empty }
+paragraph-content |=
+  element field:fieldmark {
+    attribute text:name { \string },
+    attribute field:type {
+      # TODO <rng:ref name="namespacedToken"/>
+      \string
+    },
+    element field:param {
+      attribute field:name { \string },
+      attribute field:value { \string }
+    }*
+  }
+# TODO no proposal
+animation-element |=
+  element loext:animatePhysics {
+    common-anim-target-attlist,
+    common-timing-attlist,
+    animate-physics-attlist
+  }
+animate-physics-attlist =
+  # default value: 0
+  attribute loext:velocity-x { double }?,
+  # default value: 0
+  attribute loext:velocity-y { double }?,
+  # default value: 0.1
+  attribute loext:bounciness {
+    xsd:double { minInclusive = "0" maxInclusive = "1" }
+  }?,
+  # default value: 1
+  attribute loext:density {
+    xsd:double { minInclusive = "0" }
+  }?
+# TODO no proposal
+style-chart-properties-attlist &=
+  attribute loext:custom-leader-lines { boolean }?
+# TODO no proposal
+style-chart-properties-attlist &=
+  attribute loext:external-data { \string }?
diff --git a/etc/schema/od-schema-v1.2-os.rnc 
b/etc/schema/OpenDocument-schema-v1.3.rnc
similarity index 96%
rename from etc/schema/od-schema-v1.2-os.rnc
rename to etc/schema/OpenDocument-schema-v1.3.rnc
index 8d679d6..2a78679 100644
--- a/etc/schema/od-schema-v1.2-os.rnc
+++ b/etc/schema/OpenDocument-schema-v1.3.rnc
@@ -1,33 +1,16 @@
-# 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.
+# Open Document Format for Office Applications (OpenDocument) Version 1.3
+# Committee Specification 02
+# 30 October 2020
+# Copyright (c) OASIS Open 2020. All Rights Reserved.
+# Source: https://docs.oasis-open.org/office/OpenDocument/v1.3/cs02/schemas/
+# Latest stage of specification: 
https://docs.oasis-open.org/office/OpenDocument/v1.3/OpenDocument-v1.3-part1-introduction.html
+# TC IPR Statement: https://www.oasis-open.org/committees/office/ipr.php
 #
-# 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.
+#    Open Document Format for Office Applications (OpenDocument) Version 1.3
+#    Relax-NG Schema
+#    OpenDocument-v1.3-schema.rng
+
+# https://issues.oasis-open.org/browse/OFFICE-2153
 
 namespace anim = "urn:oasis:names:tc:opendocument:xmlns:animation:1.0"
 namespace chart = "urn:oasis:names:tc:opendocument:xmlns:chart:1.0"
@@ -46,6 +29,7 @@ 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 rng = "http://relaxng.org/ns/structure/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"
@@ -58,2090 +42,1874 @@ 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
+CURIE =
+  xsd:string { pattern = "(([\i-[:]][\c-[:]]*)?:)?.+" minLength = "1" }
+CURIEs = list { CURIE+ }
+ID = xsd:ID
+IDREF = xsd:IDREF
+IDREFS = xsd:IDREFS
+NCName = xsd:NCName
+SafeCURIE =
+  xsd:string {
+    pattern = "\[(([\i-[:]][\c-[:]]*)?:)?.+\]"
+    minLength = "3"
   }
-office-document-common-attrs =
-  attribute office:version { "1.2" }
-  & attribute grddl:transformation {
-      list { anyIRI* }
+URIorSafeCURIE = anyURI | SafeCURIE
+angle = xsd:string
+anim-animate-color-attlist =
+  attribute anim:color-interpolation { "rgb" | "hsl" }?
+  & attribute anim:color-interpolation-direction {
+      "clockwise" | "counter-clockwise"
     }?
-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
+anim-animate-motion-attlist =
+  attribute svg:path { pathData }?
+  & attribute svg:origin { \string }?
+  & attribute smil:calcMode {
+      "discrete" | "linear" | "paced" | "spline"
+    }?
+anim-animate-transform-attlist =
+  attribute svg:type {
+    "translate" | "scale" | "rotate" | "skewX" | "skewY"
   }
-  | element office:drawing {
-      office-drawing-attlist,
-      office-drawing-content-prelude,
-      office-drawing-content-main,
-      office-drawing-content-epilogue
+anim-audio-attlist =
+  attribute xlink:href { anyIRI }?
+  & attribute anim:audio-level { double }?
+anim-command-attlist = attribute anim:command { \string }
+anim-iterate-attlist =
+  common-anim-target-attlist
+  & attribute anim:iterate-type { \string }?
+  & attribute anim:iterate-interval { duration }?
+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" }?
+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 office:presentation {
-      office-presentation-attlist,
-      office-presentation-content-prelude,
-      office-presentation-content-main,
-      office-presentation-content-epilogue
+  | 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 office:spreadsheet {
-      office-spreadsheet-attlist,
-      office-spreadsheet-content-prelude,
-      office-spreadsheet-content-main,
-      office-spreadsheet-content-epilogue
+  | 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 office:chart {
-      office-chart-attlist,
-      office-chart-content-prelude,
-      office-chart-content-main,
-      office-chart-content-epilogue
+  | 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 office:image {
-      office-image-attlist,
-      office-image-content-prelude,
-      office-image-content-main,
-      office-image-content-epilogue
+  | 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
     }
-  | 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"
+  | element anim:par {
+      common-anim-attlist,
+      common-timing-attlist,
+      common-endsync-timing-attlist,
+      animation-element*
     }
-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 anim:seq {
+      common-anim-attlist,
+      common-endsync-timing-attlist,
+      common-timing-attlist,
+      animation-element*
     }
-  | element meta:hyperlink-behaviour {
-      attribute office:target-frame-name { targetFrameName }?,
-      attribute xlink:show { "new" | "replace" }?
+  | element anim:iterate {
+      common-anim-attlist,
+      anim-iterate-attlist,
+      common-timing-attlist,
+      common-endsync-timing-attlist,
+      animation-element*
     }
-  | 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 anim:audio {
+      common-anim-attlist,
+      anim-audio-attlist,
+      common-basic-timing-attlist
     }
-  | 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)
+  | 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 }
+      }*
     }
-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*
+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
+any-number = number-number | number-scientific-number | number-fraction
+any-time = number-hours | number-am-pm | number-minutes | number-seconds
+anyAttListOrElements =
+  attribute * { text }*,
+  anyElements
+anyElements =
+  element * {
+    mixed { anyAttListOrElements }
+  }*
+anyIRI =
+  xsd:anyURI
+  >> dc:description [
+       "An IRI-reference as defined in [RFC3987]. See ODF 1.3 Part 3 section 
18.3."
+     ]
+anyURI = xsd:anyURI
+base64Binary = xsd:base64Binary
+boolean = "true" | "false"
+borderWidths = list { positiveLength, positiveLength, positiveLength }
+bound-column = attribute form:bound-column { \string }?
+button-type = attribute form:button-type { types }?
+cellAddress =
+  xsd:string {
+    pattern = "($?([^\. ']+|'([^']|'')+'))?\.$?[A-Z]+$?[0-9]+"
   }
-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*
+cellRangeAddress =
+  xsd:string {
+    pattern =
+      "($?([^\. ']+|'([^']|'')+'))?\.$?[A-Z]+$?[0-9]+(:($?([^\. 
']+|'([^']|'')+'))?\.$?[A-Z]+$?[0-9]+)?"
   }
-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
+  | 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'
+     ]
+change-mark-attr = attribute text:change-id { IDREF }
+change-marks =
+  element text:change { change-mark-attr }
+  | element text:change-start { change-mark-attr }
+  | element text:change-end { change-mark-attr }
+character = xsd:string { length = "1" }
+chart-axis =
+  element chart:axis {
+    chart-axis-attlist, chart-title?, chart-categories?, chart-grid*
   }
-text-list-header-attr = xml-id?
-text-numbered-paragraph =
-  element text:numbered-paragraph {
-    text-numbered-paragraph-attr, text-number?, (text-p | text-h)
+chart-axis-attlist =
+  attribute chart:dimension { chart-dimension }
+  & attribute chart:name { \string }?
+  & attribute chart:style-name { styleNameRef }?
+chart-categories =
+  element chart:categories {
+    attribute table:cell-range-address { cellRangeAddressList }?
   }
-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 })?
+chart-chart =
+  element chart:chart {
+    chart-chart-attlist,
+    chart-title?,
+    chart-subtitle?,
+    chart-footer?,
+    chart-legend?,
+    chart-plot-area,
+    shape*,
+    # https://issues.oasis-open.org/browse/OFFICE-2123
+    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?
-text-section =
-  element text:section {
-    text-section-attlist,
-    (text-section-source | text-section-source-dde | empty),
-    text-content*
+chart-coordinate-region =
+  element chart:coordinate-region {
+    chart-coordinate-region-attlist, empty
   }
-text-section-attlist =
-  common-section-attlist
-  & (attribute text:display { "true" | "none" }
-     | (attribute text:display { "condition" },
-        attribute text:condition { \string })
+chart-coordinate-region-attlist =
+  common-draw-position-attlist, common-draw-size-attlist
+# https://issues.oasis-open.org/browse/OFFICE-3928
+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-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-dimension = "x" | "y" | "z"
+chart-domain =
+  element chart:domain {
+    attribute table:cell-range-address { cellRangeAddressList }?
+  }
+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-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-floor = element chart:floor { chart-floor-attlist, empty }
+chart-floor-attlist =
+  attribute svg:width { length }?
+  & attribute chart:style-name { styleNameRef }?
+chart-footer = element chart:footer { chart-title-attlist, text-p? }
+chart-grid = element chart:grid { chart-grid-attlist }
+chart-grid-attlist =
+  attribute chart:class { "major" | "minor" }?
+  & attribute chart:style-name { styleNameRef }?
+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 },
+        common-draw-size-attlist
+        # https://issues.oasis-open.org/browse/OFFICE-3883
+        )
      | 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 }?
+  & 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-plot-area =
+  element chart:plot-area {
+    chart-plot-area-attlist,
+    # https://issues.oasis-open.org/browse/OFFICE-3928
+    chart-coordinate-region?,
+    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?
-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
+chart-regression-curve =
+  element chart:regression-curve {
+    chart-regression-curve-attlist, chart-equation?
   }
-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 }?
+chart-regression-curve-attlist =
+  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-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 }
+chart-subtitle = element chart:subtitle { chart-title-attlist, text-p? }
+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-wall = element chart:wall { chart-wall-attlist, empty }
+chart-wall-attlist =
+  attribute svg:width { length }?
+  & attribute chart:style-name { styleNameRef }?
+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}[ ]*\)"
+  }
+color = xsd:string { pattern = "#[0-9a-fA-F]{6}" }
+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 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 form:formatted-text {
+      form-formatted-text-attlist, common-form-control-content
     }
-  | element text:meta {
-      text-meta-attlist, paragraph-content-or-hyperlink*
+  | 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
     }
-  | (text-bookmark | text-bookmark-start | text-bookmark-end)
-  | element text:reference-mark {
-      attribute text:name { \string }
+  | 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 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 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 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 form:combobox {
+      form-combobox-attlist, common-form-control-content, form-item*
     }
-  | element text:user-index-mark-start {
-      text-id, text-outline-level, text-index-name
+  | element form:listbox {
+      form-listbox-attlist, common-form-control-content, form-option*
     }
-  | 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 form:checkbox {
+      form-checkbox-attlist, common-form-control-content
     }
-  | 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-anim-add-accum-attlist =
+  attribute smil:accumulate { "none" | "sum" }?
+  & attribute smil:additive { "replace" | "sum" }?
+common-anim-attlist =
+  attribute presentation:node-type {
+    "default"
+    | "on-click"
+    | "with-previous"
+    | "after-previous"
+    | "timing-root"
+    | "main-sequence"
+    | "interactive-sequence"
   }?
-  & common-field-fixed-attlist
-text-template-name-attlist =
-  attribute text:display {
-    "full" | "path" | "name" | "name-and-extension" | "area" | "title"
+  & 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 }?)?
+common-anim-named-target-attlist =
+  attribute smil:attributeName { \string }
+common-anim-set-values-attlist = attribute smil:to { \string }?
+common-anim-spline-mode-attlist =
+  attribute smil:calcMode {
+    "discrete" | "linear" | "paced" | "spline"
   }?
-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"
+common-anim-target-attlist =
+  attribute smil:targetElement { IDREF }?
+  & attribute anim:sub-item { \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-auto-reorder-attlist =
+  attribute number:automatic-order { boolean }?
+common-background-color-attlist =
+  attribute fo:background-color { "transparent" | color }?
+common-background-transparency-attlist =
+  attribute style:background-transparency { zeroToHundredPercent }?
+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-begin-end-timing-attlist =
+  attribute smil:begin { \string }?
+  & attribute smil:end { \string }?
+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 }?
+common-break-attlist =
+  attribute fo:break-before { "auto" | "column" | "page" }?,
+  attribute fo:break-after { "auto" | "column" | "page" }?
+common-calendar-attlist =
+  attribute number:calendar {
+    "gregorian"
+    | "gengou"
+    | "ROC"
+    | "hanja_yoil"
+    | "hanja"
+    | "hijri"
+    | "jewish"
+    | "buddhist"
+    | \string
   }?
-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-contour-attlist = attribute draw:recreate-on-edit { boolean }
+common-control-id-attlist =
+  xml-id,
+  attribute form:id { NCName }?
+common-convert-empty-attlist =
+  attribute form:convert-empty-to-null { boolean }?
+common-current-value-attlist = attribute form:current-value { \string }?
+common-data-field-attlist = attribute form:data-field { \string }?
+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-db-default-value = common-value-and-type-attlist?
+common-db-object-description = attribute db:description { \string }?
+common-db-object-name = attribute db:name { \string }
+common-db-object-title = attribute db:title { \string }?
+common-db-table-name-attlist =
+  attribute db:name { \string }
+  & attribute db:catalog-name { \string }?
+  & attribute db:schema-name { \string }?
+common-db-table-style-name =
+  attribute db:style-name { styleNameRef }?
+  & attribute db:default-row-style-name { styleNameRef }?
+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 }?
+common-decimal-places-attlist =
+  attribute number:decimal-places { integer }?,
+  (attribute number:min-decimal-places { integer }?)
+  # https://issues.oasis-open.org/browse/OFFICE-3860  added 
number:min-decimal-places
+
+common-delay-for-repeat = attribute form:delay-for-repeat { duration }?
+common-disabled-attlist = attribute form:disabled { boolean }?
+common-dr3d-transform-attlist = attribute dr3d:transform { \string }?
+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" }?
+common-draw-caption-id-attlist = attribute draw:caption-id { IDREF }?
+common-draw-circle-ellipse-attlist =
+  attribute draw:kind { "full" | "section" | "cut" | "arc" }?
+  & attribute draw:start-angle { angle }?
+  & attribute draw:end-angle { angle }?
+common-draw-circle-ellipse-pos-attlist =
+  attribute svg:cx { coordinate },
+  attribute svg:cy { coordinate }
+common-draw-data-attlist =
+  attribute xlink:type { "simple" },
+  attribute xlink:href { anyIRI },
+  attribute xlink:show { "embed" }?,
+  attribute xlink:actuate { "onLoad" }?
+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 }?
+common-draw-id-attlist =
+  (xml-id,
+   attribute draw:id { NCName }?)?
+common-draw-layer-name-attlist = attribute draw:layer { \string }?
+common-draw-mime-type-attlist = attribute draw:mime-type { \string }?
+# https://issues.oasis-open.org/browse/OFFICE-3943
+common-draw-name-attlist = attribute draw:name { \string }?
+common-draw-path-data-attlist = attribute svg:d { pathData }
+common-draw-points-attlist = attribute draw:points { points }
+common-draw-position-attlist =
+  attribute svg:x { coordinate }?,
+  attribute svg:y { coordinate }?
+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" }?
+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
+common-draw-size-attlist =
+  attribute svg:width { length }?,
+  attribute svg:height { length }?
+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-transform-attlist = attribute draw:transform { \string }?
+common-draw-viewbox-attlist =
+  attribute svg:viewBox {
+    list { integer, integer, integer, integer }
+  }
+common-draw-z-index-attlist =
+  attribute draw:z-index { nonNegativeInteger }?
+common-dur-timing-attlist = attribute smil:dur { \string }?
+common-editable-attlist = attribute style:editable { boolean }?
+common-endsync-timing-attlist =
+  attribute smil:endsync { "first" | "last" | "all" | "media" | IDREF }?
+common-field-data-style-name-attlist =
+  attribute style:data-style-name { styleNameRef }?
+common-field-database-name =
+  attribute text:database-name { \string }?
+  | form-connection-resource
+common-field-database-table =
+  common-field-database-table-attlist, common-field-database-name
+common-field-database-table-attlist =
+  attribute text:table-name { \string }
+  & attribute text:table-type { "table" | "query" | "command" }?
 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-display-value-formula-none-attlist =
+  attribute text:display { "value" | "formula" | "none" }?
+common-field-display-value-none-attlist =
+  attribute text:display { "value" | "none" }?
+common-field-fixed-attlist = attribute text:fixed { boolean }?
 common-field-formula-attlist = attribute text:formula { \string }?
-common-field-data-style-name-attlist =
-  attribute style:data-style-name { styleNameRef }?
+common-field-name-attlist = attribute text:name { variableName }
 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"
+common-fill-default-attlist =
+  attribute smil:fillDefault {
+    "remove" | "freeze" | "hold" | "transition" | "auto" | "inherit"
+  }?
+common-fill-timing-attlist =
+  attribute smil:fill {
+    "remove" | "freeze" | "hold" | "auto" | "default" | "transition"
+  }?
+common-form-control-attlist =
+  attribute form:name { \string }?
+  & attribute form:control-implementation { namespacedToken }?
+common-form-control-content = form-properties?, office-event-listeners?
+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" }?)
+common-form-visual-effect-attlist =
+  attribute form:visual-effect { "flat" | "3d" }?
+common-format-source-attlist =
+  attribute number:format-source { "fixed" | "language" }?
+common-horizontal-margin-attlist =
+  attribute fo:margin-left { length | percent }?,
+  attribute fo:margin-right { length | percent }?
+common-in-content-meta-attlist =
+  attribute xhtml:about { URIorSafeCURIE },
+  attribute xhtml:property { CURIEs },
+  common-meta-literal-attlist
+common-keep-with-next-attlist =
+  attribute fo:keep-with-next { "auto" | "always" }?
+common-linked-cell =
+  attribute form:linked-cell { cellAddress | \string }?
+common-margin-attlist =
+  attribute fo:margin { nonNegativeLength | percent }?
+common-maxlength-attlist =
+  attribute form:max-length { nonNegativeInteger }?
+common-meta-literal-attlist =
+  attribute xhtml:datatype { CURIE }?,
+  attribute xhtml:content { \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
+common-num-format-prefix-suffix-attlist =
+  attribute style:num-prefix { \string }?,
+  attribute style:num-suffix { \string }?
+common-number-attlist =
+  attribute number:min-integer-digits { integer }?
+  & attribute number:grouping { 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
+common-office-annotation-name-attlist =
+  attribute office:name { \string }
+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-page-number-attlist =
+  attribute style:page-number {
+    (nonNegativeInteger | "auto")
+    # https://issues.oasis-open.org/browse/OFFICE-3923
+
+  }?
+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 }?
+common-presentation-header-footer-attlist =
+  attribute presentation:use-header-name { \string }?
+  & attribute presentation:use-footer-name { \string }?
+  & attribute presentation:use-date-time-name { \string }?
+common-printable-attlist = attribute form:printable { boolean }?
+common-readonly-attlist = attribute form:readonly { boolean }?
+common-ref-format-values = "page" | "chapter" | "direction" | "text"
+common-repeat = attribute form:repeat { boolean }?
+common-repeat-timing-attlist =
+  attribute smil:repeatDur { \string }?,
+  attribute smil:repeatCount { nonNegativeDecimal | "indefinite" }?
+common-restart-default-attlist =
+  attribute smil:restartDefault {
+    "never" | "always" | "whenNotActive" | "inherit"
+  }?
+common-restart-timing-attlist =
+  attribute smil:restart {
+    "never" | "always" | "whenNotActive" | "default"
+  }?
+common-rotation-angle-attlist =
+  attribute style:rotation-angle { angle }?
+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?
+common-shadow-attlist = attribute style:shadow { shadowType }?
+common-source-cell-range =
+  attribute form:source-cell-range { cellRangeAddress | \string }?
+common-spin-button = attribute form:spin-button { boolean }?
+common-spline-anim-value-attlist =
+  attribute smil:keyTimes { \string }?
+  & attribute smil:keySplines { \string }?
+common-stock-marker-attlist =
+  attribute chart:style-name { styleNameRef }?
+common-style-direction-attlist =
+  attribute style:direction { "ltr" | "ttb" }?
+common-style-header-footer-attlist =
+  attribute style:display { boolean }?
+common-svg-font-face-xlink-attlist =
+  attribute xlink:type { "simple" },
+  attribute xlink:href { anyIRI },
+  attribute xlink:actuate { "onRequest" }?
+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 }?
+common-tab-attlist =
+  attribute form:tab-index { nonNegativeInteger }?
+  & attribute form:tab-stop { boolean }?
+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 }
+common-table-change-attlist =
+  attribute table:id { \string }
+  & attribute table:acceptance-state {
+      "accepted" | "rejected" | "pending"
     }?
-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
+  & attribute table:rejecting-change-id { \string }?
+common-table-range-attlist =
+  common-table-cell-address-attlist
+  | common-table-cell-range-address-attlist
+common-table-template-attlist =
+  attribute table:style-name { styleNameRef },
+  attribute table:paragraph-style-name { styleNameRef }?
+common-text-align =
+  attribute fo:text-align {
+    "start" | "end" | "left" | "right" | "center" | "justify"
+  }?
+common-text-anchor-attlist =
+  attribute text:anchor-type {
+    "page" | "frame" | "paragraph" | "char" | "as-char"
+  }?
+  & attribute text:anchor-page-number { positiveInteger }?
+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-time-manip-attlist =
+  attribute smil:accelerate { zeroToOneDecimal }?
+  & attribute smil:decelerate { zeroToOneDecimal }?
+  & attribute smil:autoReverse { boolean }?
+common-timing-attlist =
+  common-basic-timing-attlist, common-time-manip-attlist
+common-title-attlist = attribute form:title { \string }?
+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-value-attlist = attribute form:value { \string }?
+common-value-type-attlist = attribute office:value-type { valueType }
+common-vertical-margin-attlist =
+  attribute fo:margin-top { nonNegativeLength | percent }?,
+  attribute fo:margin-bottom { nonNegativeLength | percent }?
+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-writing-mode-attlist =
+  attribute style:writing-mode {
+    "lr-tb" | "rl-tb" | "tb-rl" | "tb-lr" | "lr" | "rl" | "tb" | "page"
+  }?
+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-entry =
+  element config:config-item-map-entry {
+    config-config-item-map-entry-attlist, config-items
   }
-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?
+config-config-item-map-entry-attlist =
+  attribute config:name { \string }?
+config-config-item-map-indexed =
+  element config:config-item-map-indexed {
+    config-config-item-map-indexed-attlist,
+    config-config-item-map-entry+
   }
-text-table-index-entry-template =
-  element text:table-index-entry-template {
-    text-illustration-index-entry-content
+config-config-item-map-indexed-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+
   }
-text-object-index =
-  element text:object-index {
-    common-section-attlist, text-object-index-source, text-index-body
+config-config-item-map-named-attlist = attribute config:name { \string }
+config-config-item-set =
+  element config:config-item-set {
+    config-config-item-set-attlist, config-items
   }
-text-object-index-source =
-  element text:object-index-source {
-    text-object-index-source-attrs,
-    text-index-title-template?,
-    text-object-index-entry-template?
+config-config-item-set-attlist = attribute config:name { \string }
+config-items =
+  (config-config-item
+   | config-config-item-set
+   | config-config-item-map-named
+   | config-config-item-map-indexed)+
+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
+    }
+coordinate = length
+countryCode = xsd:token { pattern = "[A-Za-z0-9]{1,8}" }
+currency-symbol-and-text =
+  number-currency-symbol,
+  number-text-with-fillchar
+  # https://issues.oasis-open.org/browse/OFFICE-3765
+  ?
+current-selected = attribute form:current-selected { boolean }?
+custom-shape-type = "non-primitive" | \string
+date = xsd:date
+dateOrDateTime = xsd:date | xsd:dateTime
+dateTime = xsd:dateTime
+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?
   }
-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
+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-apply-command = attribute db:apply-command { 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-character-set =
+  element db:character-set { db-character-set-attlist, empty }
+db-character-set-attlist = attribute db:encoding { textEncoding }?
+db-column =
+  element db:column {
+    db-column-attlist,
+    common-db-object-name,
+    common-db-object-title,
+    common-db-object-description,
+    common-db-default-value
   }
-text-user-index =
-  element text:user-index {
-    common-section-attlist, text-user-index-source, text-index-body
+db-column-attlist =
+  attribute db:visible { boolean }?
+  & attribute db:style-name { styleNameRef }?
+  & attribute db:default-cell-style-name { styleNameRef }?
+db-column-definition =
+  element db:column-definition {
+    db-column-definition-attlist, common-db-default-value
   }
-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*
+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-column-definitions =
+  element db:column-definitions {
+    db-column-definitions-attlist, db-column-definition+
   }
-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)*
+db-column-definitions-attlist = empty
+db-columns = element db:columns { db-columns-attlist, db-column+ }
+db-columns-attlist = empty
+db-command = attribute db:command { \string }
+db-component =
+  element db:component {
+    db-component-attlist,
+    common-db-object-name,
+    common-db-object-title,
+    common-db-object-description,
+    (office-document | math-math)?
   }
-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
+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-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)*
   }
-text-alphabetical-index-source =
-  element text:alphabetical-index-source {
-    text-alphabetical-index-source-attrs,
-    text-index-title-template?,
-    text-alphabetical-index-entry-template*
+db-component-collection-attlist = empty
+db-connection-data =
+  element db:connection-data {
+    db-connection-data-attlist,
+    (db-database-description | db-connection-resource),
+    db-login?
   }
-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 }
+db-connection-data-attlist = empty
+db-connection-resource =
+  element db:connection-resource {
+    db-connection-resource-attlist, empty
   }
-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)*
+db-connection-resource-attlist =
+  attribute xlink:type { "simple" },
+  attribute xlink:href { anyIRI },
+  attribute xlink:show { "none" }?,
+  attribute xlink:actuate { "onRequest" }?
+db-data-source =
+  element db:data-source {
+    db-data-source-attlist,
+    db-connection-data,
+    db-driver-settings?,
+    db-application-connection-settings?
   }
-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
+db-data-source-attlist = empty
+db-data-source-setting =
+  element db:data-source-setting {
+    db-data-source-setting-attlist, db-data-source-setting-value+
   }
-text-bibliography-source =
-  element text:bibliography-source {
-    text-index-title-template?, text-bibliography-entry-template*
+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
   }
-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)*
+db-data-source-setting-value-attlist = empty
+db-data-source-settings =
+  element db:data-source-settings {
+    db-data-source-settings-attlist, db-data-source-setting+
   }
-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*
+db-data-source-settings-attlist = empty
+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-database-description =
+  element db:database-description {
+    db-database-description-attlist,
+    (db-file-based-database | db-server-database)
   }
-text-index-source-style =
-  element text:index-source-style {
-    attribute text:style-name { styleName },
-    empty
+db-database-description-attlist = empty
+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-driver-settings =
+  element db:driver-settings {
+    db-driver-settings-attlist,
+    db-auto-increment?,
+    db-delimiter?,
+    db-character-set?,
+    db-table-settings?
   }
-text-index-title-template =
-  element text:index-title-template {
-    attribute text:style-name { styleNameRef }?,
-    text
+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-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-filter-statement =
+  element db:filter-statement { db-command, db-apply-command, empty }
+db-forms =
+  element db:forms {
+    db-forms-attlist, (db-component | db-component-collection)*
   }
-text-index-entry-chapter =
-  element text:index-entry-chapter {
-    attribute text:style-name { styleNameRef }?,
-    text-index-entry-chapter-attrs
+db-forms-attlist = empty
+db-host-and-port =
+  attribute db:hostname { \string },
+  attribute db:port { positiveInteger }?
+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-column =
+  element db:index-column { db-index-column-attlist, empty }
+db-index-column-attlist =
+  attribute db:name { \string }
+  & attribute db:is-ascending { boolean }?
+db-index-columns = element db:index-columns { db-index-column+ }
+db-indices = element db:indices { db-indices-attlist, db-index+ }
+db-indices-attlist = empty
+db-is-first-row-header-line =
+  attribute db:is-first-row-header-line { boolean }?
+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-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-key-columns =
+  element db:key-columns { db-key-columns-attlist, db-key-column+ }
+db-key-columns-attlist = empty
+db-keys = element db:keys { db-keys-attlist, db-key+ }
+db-keys-attlist = empty
+db-local-socket-name = attribute db:local-socket { \string }?
+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-order-statement =
+  element db:order-statement { db-command, db-apply-command, empty }
+db-queries =
+  element db:queries {
+    db-queries-attlist, (db-query | db-query-collection)*
   }
-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 }?
+db-queries-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?
   }
-text-index-entry-page-number =
-  element text:index-entry-page-number {
-    attribute text:style-name { styleNameRef }?
+db-query-attlist =
+  attribute db:command { \string }
+  & attribute db:escape-processing { boolean }?
+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)*
   }
-text-index-entry-span =
-  element text:index-entry-span {
-    attribute text:style-name { styleNameRef }?,
-    text
+db-query-collection-attlist = empty
+db-reports =
+  element db:reports {
+    db-reports-attlist, (db-component | db-component-collection)*
   }
-text-index-entry-bibliography =
-  element text:index-entry-bibliography {
-    text-index-entry-bibliography-attrs
+db-reports-attlist = empty
+db-schema-definition =
+  element db:schema-definition {
+    db-schema-definition-attlist, db-table-definitions
   }
-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
+db-schema-definition-attlist = empty
+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-show-deleted = attribute db:show-deleted { boolean }?
+db-table-definition =
+  element db:table-definition {
+    common-db-table-name-attlist,
+    db-table-definition-attlist,
+    db-column-definitions,
+    db-keys?,
+    db-indices?
   }
-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 }?
+db-table-definition-attlist = attribute db:type { \string }?
+db-table-definitions =
+  element db:table-definitions {
+    db-table-definitions-attlist, db-table-definition*
   }
-text-index-entry-link-end =
-  element text:index-entry-link-end {
-    attribute text:style-name { styleNameRef }?
+db-table-definitions-attlist = empty
+db-table-exclude-filter =
+  element db:table-exclude-filter {
+    db-table-exclude-filter-attlist, db-table-filter-pattern+
   }
-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?
+db-table-exclude-filter-attlist = empty
+db-table-filter =
+  element db:table-filter {
+    db-table-filter-attlist,
+    db-table-include-filter?,
+    db-table-exclude-filter?
   }
-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)+
+db-table-filter-attlist = empty
+db-table-filter-pattern =
+  element db:table-filter-pattern {
+    db-table-filter-pattern-attlist, \string
   }
-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
+db-table-filter-pattern-attlist = empty
+db-table-include-filter =
+  element db:table-include-filter {
+    db-table-include-filter-attlist, db-table-filter-pattern+
   }
-table-covered-table-cell =
-  element table:covered-table-cell {
-    table-table-cell-attlist, table-table-cell-content
+db-table-include-filter-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?
   }
-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
+db-table-presentation-attlist = empty
+db-table-presentations =
+  element db:table-representations {
+    db-table-presentations-attlist, db-table-presentation*
   }
-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)+
+db-table-presentations-attlist = empty
+db-table-setting =
+  element db:table-setting {
+    db-table-setting-attlist, db-delimiter?, db-character-set?, empty
   }
-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
+db-table-setting-attlist = db-is-first-row-header-line, db-show-deleted
+db-table-settings = element db:table-settings { db-table-setting* }
+db-table-type = element db:table-type { db-table-type-attlist, \string }
+db-table-type-attlist = empty
+db-table-type-filter =
+  element db:table-type-filter {
+    db-table-type-filter-attlist, db-table-type*
   }
-table-table-row-group-attlist = attribute table:display { boolean }?
-cellAddress =
-  xsd:string {
-    pattern = "($?([^\. ']+|'([^']|'')+'))?\.$?[A-Z]+$?[0-9]+"
+db-table-type-filter-attlist = empty
+db-update-table =
+  element db:update-table { common-db-table-name-attlist }
+dc-creator = element dc:creator { \string }
+dc-date = element dc:date { dateTime }
+distance = length
+double = xsd:double
+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
   }
-cellRangeAddress =
-  xsd:string {
-    pattern =
-      "($?([^\. ']+|'([^']|'')+'))?\.$?[A-Z]+$?[0-9]+(:($?([^\. 
']+|'([^']|'')+'))?\.$?[A-Z]+$?[0-9]+)?"
+dr3d-cube-attlist =
+  attribute dr3d:min-edge { vector3D }?,
+  attribute dr3d:max-edge { 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
   }
-  | 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),
+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-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
   }
-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?
+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*
   }
-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
+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 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 }?,
+  & attribute dr3d:ambient-color { color }?
+  & attribute dr3d:lighting-mode { boolean }?
+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
   }
-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))?
+dr3d-sphere-attlist =
+  attribute dr3d:center { vector3D }?
+  & attribute dr3d:size { vector3D }?
+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-applet =
+  element draw:applet {
+    draw-applet-attlist, common-draw-data-attlist?, draw-param*
   }
-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*
+draw-applet-attlist =
+  attribute draw:code { \string }?
+  & attribute draw:object { \string }?
+  & attribute draw:archive { \string }?
+  & attribute draw:may-script { boolean }?
+  & xml-id?
+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?
   }
-table-error-message =
-  element table:error-message {
-    attribute table:title { \string }?,
-    attribute table:display { boolean }?,
-    attribute table:message-type {
-      "stop" | "warning" | "information"
-    }?,
-    text-p*
+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?
   }
-table-error-macro =
-  element table:error-macro {
-    attribute table:execute { boolean }?
+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?
   }
-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)*
+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
   }
-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
+draw-caption-attlist =
+  (attribute draw:caption-point-x { coordinate },
+   attribute draw:caption-point-y { coordinate })?
+  & attribute draw:corner-radius { nonNegativeLength }?
+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
   }
-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
+draw-circle-attlist = attribute svg:r { 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
   }
-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
+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 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)
+  & attribute svg:d { pathData }?
+draw-contour-path =
+  element draw:contour-path {
+    common-contour-attlist,
+    common-draw-size-attlist,
+    common-draw-viewbox-attlist,
+    common-draw-path-data-attlist,
+    empty
   }
-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)+
+draw-contour-polygon =
+  element draw:contour-polygon {
+    common-contour-attlist,
+    common-draw-size-attlist,
+    common-draw-viewbox-attlist,
+    common-draw-points-attlist,
+    empty
   }
-table-filter-or =
-  element table:filter-or {
-    (table-filter-and | table-filter-condition)+
+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*
   }
-table-filter-condition =
-  element table:filter-condition {
-    table-filter-condition-attlist, table-filter-set-item*
+draw-control-attlist = attribute draw:control { IDREF }
+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?
   }
-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
+draw-custom-shape-attlist =
+  attribute draw:engine { namespacedToken }?
+  & attribute draw:data { \string }?
+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
   }
-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+
+draw-ellipse-attlist =
+  attribute svg:rx { length },
+  attribute svg:ry { length }
+draw-enhanced-geometry =
+  element draw:enhanced-geometry {
+    draw-enhanced-geometry-attlist, draw-equation*, draw-handle*
   }
-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
+draw-enhanced-geometry-attlist =
+  attribute draw:type { custom-shape-type }?
+  & attribute svg:viewBox {
+      list { integer, integer, integer, integer }
     }?
-  & 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
+  & 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 }?
+draw-equation = element draw:equation { draw-equation-attlist, empty }
+draw-equation-attlist =
+  attribute draw:name { \string }?
+  & attribute draw:formula { \string }?
+draw-fill-image =
+  element draw:fill-image {
+    draw-fill-image-attlist,
+    # XLink duplicate declaration removed. see common-draw-data-attlist
+    ((common-draw-data-attlist, empty) | office-binary-data)
+    # https://issues.oasis-open.org/browse/OFFICE-3933
+
   }
-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
+draw-fill-image-attlist =
+  attribute draw:name { styleName }
+  & attribute draw:display-name { \string }?
+  & attribute svg:width { length }?
+  & attribute svg:height { length }?
+draw-floating-frame =
+  element draw:floating-frame {
+    draw-floating-frame-attlist, common-draw-data-attlist
   }
-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
+draw-floating-frame-attlist =
+  attribute draw:frame-name { \string }?
+  & xml-id?
+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)?
   }
-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
+draw-frame-attlist = attribute draw:copy-of { \string }?
+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*
   }
-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
+draw-g-attlist = attribute svg:y { coordinate }?
+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"
+    }
+draw-gradient =
+  element draw:gradient {
+    common-draw-gradient-attlist, draw-gradient-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
+draw-gradient-attlist =
+  attribute draw:start-color { color }?
+  & attribute draw:end-color { color }?
+  & attribute draw:start-intensity { zeroToHundredPercent }?
+  & attribute draw:end-intensity { zeroToHundredPercent }?
+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 }?
+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-image =
+  element draw:image {
+    draw-image-attlist,
+    (common-draw-data-attlist | office-binary-data),
+    draw-text
   }
-  & 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)*
+draw-image-attlist =
+  attribute draw:filter-name { \string }?
+  & common-draw-mime-type-attlist
+  & # https://issues.oasis-open.org/browse/OFFICE-3943
+    xml-id?
+draw-image-map =
+  element draw:image-map {
+    (draw-area-rectangle | draw-area-circle | draw-area-polygon)*
   }
-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?
+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-layer-set = element draw:layer-set { draw-layer* }
+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
   }
-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 },
+draw-line-attlist =
+  attribute svg:x1 { coordinate }
+  & attribute svg:y1 { coordinate }
+  & attribute svg:x2 { coordinate }
+  & attribute svg:y2 { coordinate }
+draw-marker =
+  element draw:marker {
+    draw-marker-attlist,
+    common-draw-viewbox-attlist,
+    common-draw-path-data-attlist,
     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
+draw-marker-attlist =
+  attribute draw:name { styleName }
+  & attribute draw:display-name { \string }?
+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
   }
-table-deletion =
-  element table:deletion {
-    table-deletion-attlist,
-    common-table-change-attlist,
-    office-change-info,
-    table-dependencies?,
-    table-deletions?,
-    table-cut-offs?
+draw-measure-attlist =
+  attribute svg:x1 { coordinate }
+  & attribute svg:y1 { coordinate }
+  & attribute svg:x2 { coordinate }
+  & attribute svg:y2 { coordinate }
+draw-object =
+  element draw:object {
+    draw-object-attlist,
+    (common-draw-data-attlist | office-document | math-math)
   }
-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*)
+draw-object-attlist =
+  attribute draw:notify-on-update-of-ranges {
+    cellRangeAddressList | \string
+  }?
+  & xml-id?
+draw-object-ole =
+  element draw:object-ole {
+    draw-object-ole-attlist,
+    (common-draw-data-attlist | office-binary-data)
   }
-table-insertion-cut-off =
-  element table:insertion-cut-off {
-    table-insertion-cut-off-attlist, empty
+draw-object-ole-attlist =
+  attribute draw:class-id { \string }?
+  & xml-id?
+draw-opacity =
+  element draw:opacity {
+    common-draw-gradient-attlist, draw-opacity-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-opacity-attlist =
+  attribute draw:start { zeroToHundredPercent }?,
+  attribute draw:end { zeroToHundredPercent }?
+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 }?
@@ -2153,34 +1921,29 @@ draw-page-attlist =
   & (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,
+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-param = element draw:param { draw-param-attlist, empty }
+draw-param-attlist =
+  attribute draw:name { \string }?
+  & attribute draw:value { \string }?
+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?,
@@ -2189,13 +1952,18 @@ draw-rect =
     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,
+draw-plugin =
+  element draw:plugin {
+    draw-plugin-attlist, common-draw-data-attlist, draw-param*
+  }
+draw-plugin-attlist = common-draw-mime-type-attlist & xml-id?
+# https://issues.oasis-open.org/browse/OFFICE-3943
+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?,
@@ -2204,11 +1972,6 @@ draw-line =
     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,
@@ -2223,13 +1986,11 @@ draw-polyline =
     draw-glue-point*,
     draw-text
   }
-common-draw-points-attlist = attribute draw:points { points }
-draw-polygon =
-  element draw:polygon {
-    common-draw-points-attlist,
+draw-rect =
+  element draw:rect {
+    draw-rect-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?,
@@ -2238,6 +1999,10 @@ draw-polygon =
     draw-glue-point*,
     draw-text
   }
+draw-rect-attlist =
+  attribute draw:corner-radius { nonNegativeLength }?
+  | (attribute svg:rx { nonNegativeLength }?,
+     attribute svg:ry { nonNegativeLength }?)
 draw-regular-polygon =
   element draw:regular-polygon {
     draw-regular-polygon-attlist,
@@ -2258,262 +2023,18 @@ draw-regular-polygon-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-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 }?
 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 =
@@ -2525,2177 +2046,539 @@ draw-text-box-attlist =
   & 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,
+dropdown = attribute form:dropdown { boolean }?
+duration = xsd:duration
+extrusionOrigin =
+  xsd:double { minInclusive = "-0.5" maxInclusive = "0.5" }
+fontFamilyGeneric =
+  "roman" | "swiss" | "modern" | "decorative" | "script" | "system"
+fontPitch = "fixed" | "variable"
+fontStyle = "normal" | "italic" | "oblique"
+fontVariant = "normal" | "small-caps"
+fontWeight =
+  "normal"
+  | "bold"
+  | "100"
+  | "200"
+  | "300"
+  | "400"
+  | "500"
+  | "600"
+  | "700"
+  | "800"
+  | "900"
+for = attribute form:for { \string }?
+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-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 }?
+form-column =
+  element form:column { form-column-attlist, column-controls+ }
+form-column-attlist =
+  common-form-control-attlist, label, text-style-name
+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-connection-resource =
+  element form:connection-resource {
+    attribute xlink:href { anyIRI },
     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?
+form-control-attlist =
+  common-form-control-attlist,
+  common-control-id-attlist,
+  xforms-bind-attlist
+form-date-attlist =
+  attribute form:value { date }?
+  & attribute form:current-value { date }?
+  & attribute form:min-value { date }?
+  & attribute form:max-value { date }?
+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-fixed-text-attlist =
+  form-control-attlist
+  & for
+  & common-disabled-attlist
+  & label
+  & common-printable-attlist
+  & common-title-attlist
+  & attribute form:multi-line { boolean }?
+form-form =
+  element form:form {
+    common-form-control-attlist,
+    form-form-attlist,
+    form-properties?,
+    office-event-listeners?,
+    (controls | form-form)*,
+    form-connection-resource?
   }
-common-draw-area-attlist =
+form-form-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
+   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 }?
+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 }?
+form-frame-attlist =
+  form-control-attlist,
+  common-disabled-attlist,
+  for,
+  label,
+  common-printable-attlist,
+  common-title-attlist
+form-generic-control-attlist = form-control-attlist
+form-grid-attlist =
+  form-control-attlist,
+  common-disabled-attlist,
+  common-printable-attlist,
+  common-tab-attlist,
+  common-title-attlist
+form-hidden-attlist = form-control-attlist, common-value-attlist
+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-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-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 }?
+form-number-attlist =
+  attribute form:value { double }?
+  & attribute form:current-value { double }?
+  & attribute form:min-value { double }?
+  & attribute form:max-value { double }?
+form-option = element form:option { form-option-attlist, text }
+form-option-attlist =
+  current-selected, selected, label, common-value-attlist
+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-properties = element form:properties { form-property+ }
+form-property =
+  element form:property {
+    form-property-name, form-property-value-and-type-attlist
   }
-svg-font-face-name =
-  element svg:font-face-name {
-    attribute svg:name { \string }?,
-    empty
+  | element form:list-property {
+      form-property-name, form-property-type-and-value-list
+    }
+form-property-name = attribute form:property-name { \string }
+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" }
+form-property-value-and-type-attlist =
+  common-value-and-type-attlist
+  | attribute office:value-type { "void" }
+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-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-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-time-attlist =
+  attribute form:value { time }?
+  & attribute form:current-value { time }?
+  & attribute form:min-value { time }?
+  & attribute form:max-value { time }?
+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" }?
+gradient-style =
+  "linear" | "axial" | "radial" | "ellipsoid" | "square" | "rectangular"
+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?)
+heading-attrs =
+  attribute text:outline-level { positiveInteger }
+  & attribute text:restart-numbering { boolean }?
+  & attribute text:start-value { nonNegativeInteger }?
+  & attribute text:is-list-header { boolean }?
+horiBackPos = "left" | "center" | "right"
+horizontal-mirror =
+  "horizontal" | "horizontal-on-odd" | "horizontal-on-even"
+image-data = attribute form:image-data { anyIRI }?
+index-content-main = text-content | text-index-title
+integer = xsd:integer
+label = attribute form:label { \string }?
+labelPositions =
+  "avoid-overlap"
+  | "center"
+  | "top"
+  | "top-right"
+  | "right"
+  | "bottom-right"
+  | "bottom"
+  | "bottom-left"
+  | "left"
+  | "top-left"
+  | "inside"
+  | "outside"
+  | "near-origin"
+language = xsd:language
+languageCode = xsd:token { pattern = "[A-Za-z]{1,8}" }
+length =
+  xsd:string {
+    pattern =
+      "-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc)|(px))"
   }
-svg-definition-src =
-  element svg:definition-src {
-    common-svg-font-face-xlink-attlist, empty
+lineMode = "continuous" | "skip-white-space"
+lineStyle =
+  "none"
+  | "solid"
+  | "dotted"
+  | "dash"
+  | "long-dash"
+  | "dot-dash"
+  | "dot-dot-dash"
+  | "wave"
+lineType = "none" | "single" | "double"
+lineWidth =
+  "auto"
+  | "normal"
+  | "bold"
+  | "thin"
+  | "medium"
+  | "thick"
+  | positiveInteger
+  | percent
+  | positiveLength
+list-linkage-type =
+  attribute form:list-linkage-type {
+    "selection" | "selection-indices"
+  }?
+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"
+  }?
+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 })*
+meta-date-string = element meta:date-string { \string }
+namespacedToken = xsd:QName { pattern = "[^:]+:[^:]+" }
+navigation = "none" | "current" | "parent"
+nonNegativeDecimal = xsd:decimal { minInclusive = "0.0" }
+nonNegativeInteger = xsd:nonNegativeInteger
+nonNegativeLength =
+  xsd:string {
+    pattern =
+      "([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc)|(px))"
   }
-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 {
+nonNegativePixelLength =
+  xsd:string { pattern = "([0-9]+(\.[0-9]*)?|\.[0-9]+)(px)" }
+number-am-pm = element number:am-pm { empty }
+number-and-text =
+  number-number,
+  (number-text-with-fillchar?)
+  # https://issues.oasis-open.org/browse/OFFICE-3765
+
+number-boolean = element number:boolean { empty }
+number-boolean-style =
+  element number:boolean-style {
     common-data-style-attlist,
     style-text-properties?,
     number-text?,
-    (any-number, number-text?)?,
+    (number-boolean, 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-text-with-fillchar?,
+    # https://issues.oasis-open.org/browse/OFFICE-3765
     ((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*
+  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-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?)+,
+    number-text-with-fillchar?,
+    # https://issues.oasis-open.org/browse/OFFICE-3765
+    (any-date,
+     (number-text-with-fillchar?)
+     # https://issues.oasis-open.org/browse/OFFICE-3765
+     )+,
     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-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-embedded-text =
+  element number:embedded-text { number-embedded-text-attlist, text }
+number-embedded-text-attlist = attribute number:position { integer }
+number-era =
+  element number:era {
+    number-era-attlist, common-calendar-attlist, empty
+  }
+number-era-attlist = attribute number:style { "short" | "long" }?
+number-fill-character = element number:fill-character { text }
+# https://issues.oasis-open.org/browse/OFFICE-3765
+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 }?
+  & (attribute number:max-denominator-value { positiveInteger }?)
+    # https://issues.oasis-open.org/browse/OFFICE-3695 max-denominator-value
+
+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-month =
   element number:month {
     number-month-attlist, common-calendar-attlist, empty
@@ -4704,743 +2587,991 @@ 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-number =
+  element number:number {
+    number-number-attlist,
+    common-decimal-places-attlist,
+    common-number-attlist,
+    number-embedded-text*
   }
-number-year-attlist = attribute number:style { "short" | "long" }?
-number-era =
-  element number:era {
-    number-era-attlist, common-calendar-attlist, empty
+number-number-attlist =
+  attribute number:decimal-replacement { \string }?
+  & attribute number:display-factor { double }?
+number-number-style =
+  element number:number-style {
+    common-data-style-attlist,
+    style-text-properties?,
+    number-text-with-fillchar?,
+    # https://issues.oasis-open.org/browse/OFFICE-3765
+    (any-number, number-text-with-fillchar?)?,
+    # https://issues.oasis-open.org/browse/OFFICE-3765
+    style-map*
   }
-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-percentage-style =
+  element number:percentage-style {
+    common-data-style-attlist,
+    style-text-properties?,
+    number-text-with-fillchar?,
+    # https://issues.oasis-open.org/browse/OFFICE-3765
+    number-and-text?,
+    style-map*
   }
-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*
+number-scientific-number =
+  element number:scientific-number {
+    number-scientific-number-attlist,
+    common-decimal-places-attlist,
+    common-number-attlist,
+    empty
   }
-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-scientific-number-attlist =
+  attribute number:min-exponent-digits { integer }?
+  & attribute number:exponent-interval { positiveInteger }?
+  & # https://issues.oasis-open.org/browse/OFFICE-1828 exponent-interval
+    attribute number:forced-exponent-sign { boolean }
+    # https://issues.oasis-open.org/browse/OFFICE-3860 added 
number:forced-exponent-sign
+    ?
 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 {
+number-text = element number:text { text }
+number-text-content = element number:text-content { empty }
+number-text-style =
+  element number:text-style {
     common-data-style-attlist,
     style-text-properties?,
-    number-text?,
-    (number-boolean, number-text?)?,
+    number-text-with-fillchar?,
+    # https://issues.oasis-open.org/browse/OFFICE-3765
+    (number-text-content,
+     (number-text-with-fillchar?)
+     # https://issues.oasis-open.org/browse/OFFICE-3765
+     )*,
     style-map*
   }
-number-boolean = element number:boolean { empty }
-number-text-style =
-  element number:text-style {
+number-text-with-fillchar =
+  number-text?, (number-fill-character, number-text?)?
+# https://issues.oasis-open.org/browse/OFFICE-3765
+number-time-style =
+  element number:time-style {
+    number-time-style-attlist,
     common-data-style-attlist,
+    common-format-source-attlist,
     style-text-properties?,
-    number-text?,
-    (number-text-content, number-text?)*,
+    number-text-with-fillchar?,
+    # https://issues.oasis-open.org/browse/OFFICE-3765
+    (any-time,
+     (number-text-with-fillchar?)
+     # https://issues.oasis-open.org/browse/OFFICE-3765
+     )+,
     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?
+number-time-style-attlist =
+  attribute number:truncate-on-overflow { boolean }?
+number-week-of-year =
+  element number:week-of-year { common-calendar-attlist, empty }
+number-year =
+  element number:year {
+    number-year-attlist, common-calendar-attlist, empty
+  }
+number-year-attlist = attribute number:style { "short" | "long" }?
+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?,
+    element meta:creator-initials { text }?,
+    # https://issues.oasis-open.org/browse/OFFICE-3776
+    (text-p | text-list)*
+  }
+office-annotation-attlist =
+  attribute office:display { boolean }?
+  & common-office-annotation-name-attlist?
+office-annotation-end =
+  element office:annotation-end { office-annotation-end-attlist }
+office-annotation-end-attlist = common-office-annotation-name-attlist
+office-automatic-styles =
+  element office:automatic-styles { styles & style-page-layout* }?
+office-binary-data = element office:binary-data { base64Binary }
+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-change-info =
+  element office:change-info { dc-creator, dc-date, text-p* }
+office-chart-attlist = empty
+office-chart-content-epilogue = table-functions
+office-chart-content-main = chart-chart
+office-chart-content-prelude = text-decls, table-decls
+office-database =
+  element office:database {
+    db-data-source,
+    db-forms?,
+    db-reports?,
+    db-queries?,
+    db-table-presentations?,
+    db-schema-definition?
   }
-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
+office-dde-source =
+  element office:dde-source {
+    office-dde-source-attlist, common-dde-connection-decl-attlist
   }
-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"
+office-dde-source-attlist =
+  attribute office:name { \string }?
+  & attribute office:conversion-mode {
+      "into-default-style-data-style"
+      | "into-english-number"
+      | "keep-text"
     }?
-  & attribute text:footnotes-position {
-      "text" | "page" | "section" | "document"
+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-attrs = attribute office:mimetype { \string }
+office-document-common-attrs =
+  attribute office:version { "1.3" }
+  & attribute grddl:transformation {
+      list { anyIRI* }
     }?
-  & 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*
+office-document-content =
+  element office:document-content {
+    office-document-common-attrs,
+    office-scripts,
+    office-font-face-decls,
+    office-automatic-styles,
+    office-body
   }
-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*
+office-document-meta =
+  element office:document-meta {
+    office-document-common-attrs, office-meta
   }
-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?
+office-document-settings =
+  element office:document-settings {
+    office-document-common-attrs, office-settings
+  }
+office-document-styles =
+  element office:document-styles {
+    office-document-common-attrs,
+    office-font-face-decls,
+    office-styles,
+    office-automatic-styles,
+    office-master-styles
+  }
+office-drawing-attlist = empty
+office-drawing-content-epilogue = table-functions
+office-drawing-content-main = draw-page*
+office-drawing-content-prelude = text-decls, table-decls
+office-event-listeners =
+  element office:event-listeners {
+    (script-event-listener | presentation-event-listener)*
+  }
+office-font-face-decls =
+  element office:font-face-decls { style-font-face* }?
+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 }?
+office-image-attlist = empty
+office-image-content-epilogue = empty
+office-image-content-main = draw-frame
+office-image-content-prelude = empty
+office-master-styles =
+  element office:master-styles {
+    style-master-page* & style-handout-master? & draw-layer-set?
+  }?
+office-meta = element office:meta { office-meta-content-strict }?
+office-meta-content-strict = office-meta-data*
+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)
+    }
+office-presentation-attlist = empty
+office-presentation-content-epilogue =
+  presentation-settings, table-functions
+office-presentation-content-main = draw-page*
+office-presentation-content-prelude =
+  text-decls, table-decls, presentation-decls
+# removed from text as well
+# <rng:define name="office-process-content">
+#   <rng:optional>
+#     <rng:attribute name="office:process-content">
+#       <rng:ref name="boolean"/>
+#     </rng:attribute>
+#   </rng:optional>
+# </rng:define>
+office-script =
+  element office:script {
+    office-script-attlist,
+    mixed { anyElements }
   }
-  | element text:list-level-style-bullet {
-      text-list-level-style-attr,
-      text-list-level-style-bullet-attr,
-      style-list-level-properties?,
-      style-text-properties?
+office-script-attlist = attribute script:language { \string }
+office-scripts =
+  element office:scripts { office-script*, office-event-listeners? }?
+office-settings = element office:settings { config-config-item-set+ }?
+office-spreadsheet-attlist =
+  attribute table:structure-protected { boolean }?,
+  attribute table:protection-key { \string }?,
+  attribute table:protection-key-digest-algorithm { anyIRI }?
+office-spreadsheet-content-epilogue = table-functions
+office-spreadsheet-content-main = table-table*
+office-spreadsheet-content-prelude =
+  table-tracked-changes?, text-decls, table-decls
+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-text-attlist =
+  attribute text:global { boolean }?
+  & attribute text:use-soft-page-breaks { boolean }?
+office-text-content-epilogue = table-functions
+office-text-content-main =
+  text-content*
+  | (text-page-sequence, (shape)*)
+office-text-content-prelude =
+  office-forms, text-tracked-changes, text-decls, table-decls
+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?
+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 }
+  | text-drop-down
+  | # OFFICE-3881
+    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:list-level-style-image {
-      text-list-level-style-attr,
-      text-list-level-style-image-attr,
-      style-list-level-properties?
+  | element text:database-display {
+      text-database-display-attlist, text
     }
-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*
+  | 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 }
+paragraph-content-or-hyperlink = paragraph-content | text-a
+pathData = xsd:string
+percent = xsd:string { pattern = "-?([0-9]+(\.[0-9]*)?|\.[0-9]+)%" }
+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}[ ]*\)"
   }
-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
+points =
+  xsd:string { pattern = "-?[0-9]+,-?[0-9]+([ ]+-?[0-9]+,-?[0-9]+)*" }
+positiveInteger = xsd:positiveInteger
+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))"
   }
-style-page-layout-properties =
-  element style:page-layout-properties {
-    style-page-layout-properties-content-strict
+presentation-animation-elements =
+  presentation-show-shape
+  | presentation-show-text
+  | presentation-hide-shape
+  | presentation-hide-text
+  | presentation-dim
+  | presentation-play
+presentation-animation-group =
+  element presentation:animation-group {
+    presentation-animation-elements*
   }
-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
+presentation-animations =
+  element presentation:animations {
+    (presentation-animation-elements | presentation-animation-group)*
   }
-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 {
+presentation-classes =
+  "title"
+  | "outline"
+  | "subtitle"
+  | "text"
+  | "graphic"
+  | "object"
+  | "chart"
+  | "table"
+  | "orgchart"
+  | "page"
+  | "notes"
+  | "handout"
+  | "header"
+  | "footer"
+  | "date-time"
+  | "page-number"
+presentation-date-time-decl-attlist =
+  attribute presentation:name { \string }
+  & attribute presentation:source { "fixed" | "current-date" }
+  & attribute style:data-style-name { styleNameRef }?
+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-decls = presentation-decl*
+presentation-dim =
+  element presentation:dim {
+    presentation-dim-attlist, presentation-sound?
+  }
+presentation-dim-attlist =
+  attribute draw:shape-id { IDREF }
+  & attribute draw:color { color }
+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"
-      | list {
-          ("none" | "accent" | "dot" | "circle" | "disc"),
-          ("above" | "below")
-        }
+      | "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-footer-decl-attlist =
+  attribute presentation:name { \string }
+presentation-header-decl-attlist =
+  attribute presentation:name { \string }
+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-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 }?
+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
+  }
+presentation-play =
+  element presentation:play { presentation-play-attlist, empty }
+presentation-play-attlist =
+  attribute draw:shape-id { IDREF },
+  attribute presentation:speed { presentationSpeeds }?
+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 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 =
+  & attribute presentation:stay-on-top { boolean }?
+  & attribute presentation:show-end-of-presentation-slide { boolean }?
+presentation-shape-attlist =
+  attribute presentation:class { presentation-classes }?
+  & attribute presentation:placeholder { boolean }?
+  & attribute presentation:user-transformed { boolean }?
+presentation-show =
+  element presentation:show { presentation-show-attlist, empty }
+presentation-show-attlist =
+  attribute presentation:name { \string }
+  & attribute presentation:pages { \string }
+presentation-show-shape =
+  element presentation:show-shape {
+    common-presentation-effect-attlist, presentation-sound?
+  }
+presentation-show-text =
+  element presentation:show-text {
+    common-presentation-effect-attlist, presentation-sound?
+  }
+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?
+presentationEffectDirections =
   "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
+  | "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"
+presentationEffects =
+  "none"
+  | "fade"
+  | "move"
+  | "stripes"
+  | "open"
+  | "close"
+  | "dissolve"
+  | "wavyline"
+  | "random"
+  | "lines"
+  | "laser"
+  | "appear"
+  | "hide"
+  | "move-short"
+  | "checkerboard"
+  | "rotate"
+  | "stretch"
+presentationSpeeds = "slow" | "medium" | "fast"
+region-content = text-p*
+relativeLength = xsd:string { pattern = "[0-9]+\*" }
+rowOrCol = "row" | "column"
+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" }?))
+scriptCode = xsd:token { pattern = "[A-Za-z0-9]{1,8}" }
+selected = attribute form:selected { boolean }?
+shadowType = "none" | \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
+shapes3d =
+  dr3d-scene | dr3d-extrude | dr3d-sphere | dr3d-rotate | dr3d-cube
+signedZeroToHundredPercent =
+  xsd:string {
+    pattern = "-?([0-9]?[0-9](\.[0-9]*)?|100(\.0*)?|\.[0-9]+)%"
   }
-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 }?
+size = attribute form:size { nonNegativeInteger }?
+states = "unchecked" | "checked" | "unknown"
+\string = xsd:string
 style-background-image =
   element style:background-image {
     style-background-image-attlist,
@@ -5459,74 +3590,159 @@ style-background-image-attlist =
     }?
   & 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-chart-properties =
+  element style:chart-properties {
+    style-chart-properties-content-strict
+  }
+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"
+      | "step-start"
+      | "step-end"
+      | "step-center-x"
+      | "step-center-y"
+    }?
+  & 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"
+      | "moving-average"
+      | "exponential"
+      | "power"
+      | "polynomial"
     }?
-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 }?
+  & attribute chart:regression-max-degree { positiveInteger }?
+  & attribute chart:regression-force-intercept { boolean }?
+  & attribute chart:regression-intercept-value { double }?
+  & attribute chart:regression-name { \string }?
+  & # https://issues.oasis-open.org/browse/OFFICE-3958
+    attribute chart:regression-period { positiveInteger }?
+  & attribute chart:regression-moving-type {
+      "prior" | "central" | "averaged-abscissa"
+    }?
+  & # https://issues.oasis-open.org/browse/OFFICE-3959
+    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 }?
+  & (attribute chart:data-label-series { boolean }?)
+    # https://issues.oasis-open.org/browse/OFFICE-2117
+
+style-chart-properties-content-strict =
+  style-chart-properties-attlist, style-chart-properties-elements
+style-chart-properties-elements = empty
 style-column = element style:column { style-column-attlist }
 style-column-attlist =
   attribute style:rel-width { relativeLength }
@@ -5543,132 +3759,235 @@ style-column-sep-attlist =
   & 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-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-default-page-layout =
+  element style:default-page-layout { style-page-layout-content }
+style-default-style =
+  element style:default-style { style-style-content }
+style-drawing-page-properties =
+  element style:drawing-page-properties {
+    style-drawing-page-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-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-content-strict =
+  style-graphic-fill-properties-attlist,
+  style-drawing-page-properties-attlist,
+  style-drawing-page-properties-elements
+style-drawing-page-properties-elements = presentation-sound?
+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 }?
+style-font-face =
+  element style:font-face {
+    style-font-face-attlist, svg-font-face-src?, svg-definition-src?
   }
-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-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 }?
+style-footer =
+  element style:footer {
+    common-style-header-footer-attlist, header-footer-content
   }
-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"
+style-footer-first =
+  element style:footer-first {
+    common-style-header-footer-attlist,
+    header-footer-content
+    # https://issues.oasis-open.org/browse/OFFICE-3789
+
+  }
+style-footer-left =
+  element style:footer-left {
+    common-style-header-footer-attlist, header-footer-content
+  }
+style-footer-style =
+  element style:footer-style { style-header-footer-properties? }
+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-graphic-fill-properties-attlist =
+  attribute draw:fill {
+    "none" | "solid" | "bitmap" | "gradient" | "hatch"
   }?
-  & 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 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 style:cell-protect {
-      "none"
-      | "hidden-and-protected"
-      | list { ("protected" | "formula-hidden")+ }
+  & attribute draw:tile-repeat-offset {
+      list { zeroToHundredPercent, ("horizontal" | "vertical") }
     }?
-  & 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
+  & attribute draw:opacity { zeroToHundredPercent }?
+  & attribute draw:opacity-name { styleNameRef }?
+  & attribute svg:fill-rule { "nonzero" | "evenodd" }?
+style-graphic-properties =
+  element style:graphic-properties {
+    style-graphic-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 }?
@@ -5717,7 +4036,9 @@ style-graphic-properties-attlist =
       "greyscale" | "mono" | "watermark" | "standard"
     }?
   & attribute draw:color-inversion { boolean }?
-  & attribute draw:luminance { zeroToHundredPercent }?
+  & attribute draw:luminance { signedZeroToHundredPercent }
+    # https://issues.oasis-open.org/browse/OFFICE-3821
+    ?
   & attribute draw:contrast { percent }?
   & attribute draw:gamma { percent }?
   & attribute draw:red { signedZeroToHundredPercent }?
@@ -5758,497 +4079,2316 @@ style-graphic-properties-attlist =
       | "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: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-properties-content-strict =
+  style-graphic-properties-attlist,
+  style-graphic-fill-properties-attlist,
+  style-graphic-properties-elements
+style-graphic-properties-elements =
+  text-list-style? & style-background-image & style-columns
+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 }?
+style-header =
+  element style:header {
+    common-style-header-footer-attlist, header-footer-content
+  }
+style-header-first =
+  element style:header-first {
+    common-style-header-footer-attlist,
+    header-footer-content
+    # https://issues.oasis-open.org/browse/OFFICE-3789
+
+  }
+style-header-footer-properties =
+  element style:header-footer-properties {
+    style-header-footer-properties-content-strict
+  }
+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-content-strict =
+  style-header-footer-properties-attlist,
+  style-header-footer-properties-elements
+style-header-footer-properties-elements = style-background-image
+style-header-left =
+  element style:header-left {
+    common-style-header-footer-attlist, header-footer-content
+  }
+style-header-style =
+  element style:header-style { style-header-footer-properties? }
+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-list-level-properties =
+  element style:list-level-properties {
+    style-list-level-properties-content-strict
+  }
+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"
     }?
-  & 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"
+style-list-level-properties-content-strict =
+  style-list-level-properties-attlist,
+  style-list-level-properties-elements
+style-list-level-properties-elements = style-list-level-label-alignment
+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-master-page =
+  element style:master-page {
+    style-master-page-attlist,
+    (style-header,
+     style-header-left?,
+     (style-header-first?)
+     # https://issues.oasis-open.org/browse/OFFICE-3789
+     )?,
+    (style-footer,
+     style-footer-left?,
+     (style-footer-first?)
+     # https://issues.oasis-open.org/browse/OFFICE-3789
+     )?,
+    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-num-letter-sync-attlist =
+  attribute style:num-letter-sync { boolean }?
+style-page-layout =
+  element style:page-layout {
+    style-page-layout-attlist, style-page-layout-content
+  }
+style-page-layout-attlist =
+  attribute style:name { styleName }
+  & attribute style:page-usage {
+      "all" | "left" | "right" | "mirrored"
     }?
-  & 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"
+style-page-layout-content =
+  style-page-layout-properties?,
+  style-header-style?,
+  style-footer-style?
+style-page-layout-properties =
+  element style:page-layout-properties {
+    style-page-layout-properties-content-strict
+  }
+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 dr3d:texture-generation-mode-y {
-      "object" | "parallel" | "sphere"
+  & 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:scale-to-X { positiveInteger }?,
+        attribute style:scale-to-Y { positiveInteger }?))
+  & # https://issues.oasis-open.org/browse/OFFICE-3857
+    attribute style:table-centering {
+      "horizontal" | "vertical" | "both" | "none"
     }?
-  & 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 }?
+  & 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-content-strict =
+  style-page-layout-properties-attlist,
+  style-page-layout-properties-elements
+style-page-layout-properties-elements =
+  style-background-image & style-columns & style-footnote-sep
+style-paragraph-properties =
+  element style:paragraph-properties {
+    style-paragraph-properties-content-strict
+  }
+style-paragraph-properties-attlist =
+  attribute style:contextual-spacing { boolean }?
+  & # https://issues.oasis-open.org/browse/OFFICE-3767
+    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
-  & attribute style:print-content { boolean }?
-  & attribute style:protect {
-      "none"
-      | list { ("content" | "position" | "size")+ }
+  & 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"
     }?
-  & attribute style:horizontal-pos {
+  & 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
+style-paragraph-properties-content-strict =
+  style-paragraph-properties-attlist,
+  style-paragraph-properties-elements
+style-paragraph-properties-elements =
+  style-tab-stops & style-drop-cap & style-background-image
+style-presentation-page-layout =
+  element style:presentation-page-layout {
+    attribute style:name { styleName },
+    attribute style:display-name { \string }?,
+    presentation-placeholder*
+  }
+style-region-center = element style:region-center { region-content }
+style-region-left = element style:region-left { region-content }
+style-region-right = element style:region-right { region-content }
+style-ruby-properties =
+  element style:ruby-properties { style-ruby-properties-content-strict }
+style-ruby-properties-attlist =
+  attribute style:ruby-position { "above" | "below" }?
+  & attribute style:ruby-align {
       "left"
       | "center"
       | "right"
-      | "from-left"
-      | "inside"
-      | "outside"
-      | "from-inside"
+      | "distribute-letter"
+      | "distribute-space"
     }?
-  & 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"
+style-ruby-properties-content-strict =
+  style-ruby-properties-attlist, style-ruby-properties-elements
+style-ruby-properties-elements = empty
+style-section-properties =
+  element style:section-properties {
+    style-section-properties-content-strict
+  }
+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-content-strict =
+  style-section-properties-attlist, style-section-properties-elements
+style-section-properties-elements =
+  style-background-image & style-columns & text-notes-configuration*
+style-style =
+  element style:style {
+    style-style-attlist, style-style-content, style-map*
+  }
+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-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?)
+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-tab-stops = element style:tab-stops { style-tab-stop* }?
+style-table-cell-properties =
+  element style:table-cell-properties {
+    style-table-cell-properties-content-strict
+  }
+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-vertical-pos-attlist
-  & common-vertical-rel-attlist
-  & common-text-anchor-attlist
+  & 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 }?
+style-table-cell-properties-content-strict =
+  style-table-cell-properties-attlist,
+  style-table-cell-properties-elements
+style-table-cell-properties-elements = style-background-image
+style-table-column-properties =
+  element style:table-column-properties {
+    style-table-column-properties-content-strict
+  }
+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-column-properties-content-strict =
+  style-table-column-properties-attlist,
+  style-table-column-properties-elements
+style-table-column-properties-elements = empty
+style-table-properties =
+  element style:table-properties {
+    style-table-properties-content-strict
+  }
+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 }?
+  & (attribute table:tab-color { color }?)
+    # https://issues.oasis-open.org/browse/OFFICE-2173
+
+style-table-properties-content-strict =
+  style-table-properties-attlist, style-table-properties-elements
+style-table-properties-elements = style-background-image
+style-table-row-properties =
+  element style:table-row-properties {
+    style-table-row-properties-content-strict
+  }
+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-content-strict =
+  style-table-row-properties-attlist,
+  style-table-row-properties-elements
+style-table-row-properties-elements = style-background-image
+style-text-properties =
+  element style:text-properties { style-text-properties-content-strict }
+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
-  & common-background-transparency-attlist
-  & common-editable-attlist
-  & attribute style:wrap {
+  & 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"
-      | "left"
-      | "right"
-      | "parallel"
-      | "dynamic"
-      | "run-through"
-      | "biggest"
+      | list {
+          ("none" | "accent" | "dot" | "circle" | "disc"),
+          ("above" | "below")
+        }
     }?
-  & attribute style:wrap-dynamic-threshold { nonNegativeLength }?
-  & attribute style:number-wrapped-paragraphs {
-      "no-limit" | positiveInteger
+  & 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)
+style-text-properties-content-strict =
+  style-text-properties-attlist, style-text-properties-elements
+style-text-properties-elements = empty
+styleName = xsd:NCName
+styleNameRef = xsd:NCName | empty
+styleNameRefs = list { xsd:NCName* }
+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*
+svg-definition-src =
+  element svg:definition-src {
+    common-svg-font-face-xlink-attlist, empty
+  }
+svg-desc = element svg:desc { text }
+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-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-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 }?
+  }
+svg-title = element svg:title { text }
+tab-cycles = "records" | "current" | "page"
+table-background =
+  element table:background { table-background-attlist, empty }
+table-background-attlist = attribute table:style-name { styleNameRef }
+table-body = element table:body { common-table-template-attlist, empty }
+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 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 table:automatic-find-labels { boolean }?
+  & attribute table:use-regular-expressions { boolean }?
+  & attribute table:use-wildcards { boolean }?
+  & attribute table:null-year { positiveInteger }?
+table-calculation-settings =
+  element table:calculation-settings {
+    table-calculation-setting-attlist,
+    table-null-date?,
+    table-iteration?
+  }
+table-cell-address =
+  element table:cell-address {
+    common-table-cell-address-attlist, empty
+  }
+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-content-deletion =
+  element table:cell-content-deletion {
+    attribute table:id { \string }?,
+    table-cell-address?,
+    table-change-track-table-cell?
+  }
+table-cell-range-source =
+  element table:cell-range-source {
+    table-table-cell-range-source-attlist,
+    table-linked-source-attlist,
+    empty
+  }
+table-change-deletion =
+  element table:change-deletion {
+    attribute table:id { \string }?,
+    empty
+  }
+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-columns = table-table-columns | table-table-column+
+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-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-content-validation =
+  element table:content-validation {
+    table-validation-attlist,
+    table-help-message?,
+    (table-error-message | (table-error-macro, office-event-listeners))?
+  }
+table-content-validations =
+  element table:content-validations { table-content-validation+ }
+table-covered-table-cell =
+  element table:covered-table-cell {
+    table-table-cell-attlist, table-table-cell-content
+  }
+table-cut-offs =
+  element table:cut-offs {
+    table-movement-cut-off+
+    | (table-insertion-cut-off, table-movement-cut-off*)
+  }
+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-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 style:mirror {
+  & attribute table:used-hierarchy { integer }?
+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"
-      | "vertical"
-      | horizontal-mirror
-      | list { "vertical", horizontal-mirror }
-      | list { horizontal-mirror, "vertical" }
+      | "member-difference"
+      | "member-percentage"
+      | "member-percentage-difference"
+      | "running-total"
+      | "row-percentage"
+      | "column-percentage"
+      | "total-percentage"
+      | "index"
+    }
+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-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"
+    }?
+# https://issues.oasis-open.org/browse/OFFICE-2118
+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-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-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-members =
+  element table:data-pilot-members { table-data-pilot-member* }
+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-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-subtotals =
+  element table:data-pilot-subtotals { table-data-pilot-subtotal* }
+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-data-pilot-tables =
+  element table:data-pilot-tables { table-data-pilot-table* }
+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-ranges =
+  element table:database-ranges { table-database-range* }
+table-database-source-query =
+  element table:database-source-table {
+    table-database-source-table-attlist, empty
+  }
+table-database-source-query-attlist =
+  attribute table:database-name { \string }
+  & attribute table:query-name { \string }
+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-table =
+  element table:database-source-query {
+    table-database-source-query-attlist, empty
+  }
+table-database-source-table-attlist =
+  attribute table:database-name { \string }
+  & attribute table:database-table-name { \string }
+table-dde-link =
+  element table:dde-link { office-dde-source, table-table }
+table-dde-links = element table:dde-links { table-dde-link+ }
+table-decls =
+  table-calculation-settings?,
+  table-content-validations?,
+  table-label-ranges?
+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-deletions =
+  element table:deletions {
+    (table-cell-content-deletion | table-change-deletion)+
+  }
+table-dependencies = element table:dependencies { table-dependency+ }
+table-dependency =
+  element table:dependency {
+    attribute table:id { \string },
+    empty
+  }
+table-desc = element table:desc { text }
+table-detective =
+  element table:detective { table-highlighted-range*, table-operation* }
+table-error-macro =
+  element table:error-macro {
+    attribute table:execute { boolean }?
+  }
+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-even-columns =
+  element table:even-columns { common-table-template-attlist, empty }
+table-even-rows =
+  element table:even-rows { common-table-template-attlist, empty }
+table-filter =
+  element table:filter {
+    table-filter-attlist,
+    (table-filter-condition | table-filter-and | table-filter-or)
+  }
+table-filter-and =
+  element table:filter-and {
+    (table-filter-or | table-filter-condition)+
+  }
+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-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-or =
+  element table:filter-or {
+    (table-filter-and | table-filter-condition)+
+  }
+table-filter-set-item =
+  element table:filter-set-item {
+    attribute table:value { \string },
+    empty
+  }
+table-first-column =
+  element table:first-column { common-table-template-attlist, empty }
+table-first-row =
+  element table:first-row { common-table-template-attlist, empty }
+table-functions =
+  table-named-expressions?,
+  table-database-ranges?,
+  table-data-pilot-tables?,
+  table-consolidation?,
+  table-dde-links?
+table-help-message =
+  element table:help-message {
+    attribute table:title { \string }?,
+    attribute table:display { boolean }?,
+    text-p*
+  }
+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 }
+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-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-iteration =
+  element table:iteration {
+    attribute table:status { "enable" | "disable" }?,
+    attribute table:steps { positiveInteger }?,
+    attribute table:maximum-difference { double }?,
+    empty
+  }
+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-label-ranges = element table:label-ranges { table-label-range* }
+table-last-column =
+  element table:last-column { common-table-template-attlist, empty }
+table-last-row =
+  element table:last-row { common-table-template-attlist, empty }
+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-movement =
+  element table:movement {
+    common-table-change-attlist,
+    table-source-range-address,
+    table-target-range-address,
+    office-change-info,
+    table-dependencies?,
+    table-deletions?
+  }
+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-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-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-null-date =
+  element table:null-date {
+    attribute table:value-type { "date" }?,
+    attribute table:date-value { date }?,
+    empty
+  }
+table-odd-columns =
+  element table:odd-columns { common-table-template-attlist, empty }
+table-odd-rows =
+  element table:odd-rows { common-table-template-attlist, empty }
+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-previous =
+  element table:previous {
+    attribute table:id { \string }?,
+    table-change-track-table-cell
+  }
+table-rows =
+  table-table-rows | (text-soft-page-break?, table-table-row)+
+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-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-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"
     }?
-  & attribute fo:clip { "auto" | clipShape }?
-  & attribute draw:wrap-influence-on-position {
-      "iterative" | "once-concurrent" | "once-successive"
+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
     }?
-  & 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 table:order { "ascending" | "descending" }?
+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-source-cell-range =
+  element table:source-cell-range {
+    table-source-cell-range-attlist, table-filter?
+  }
+table-source-cell-range-attlist =
+  # OFFICE-3665
+  (attribute table:cell-range-address { cellRangeAddress }
+   | (attribute table:name { \string },
+      attribute table:cell-range-address { cellRangeAddress }?))
+table-source-range-address =
+  element table:source-range-address {
+    common-table-range-attlist, empty
+  }
+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-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-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-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-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-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-table-cell =
+  element table:table-cell {
+    table-table-cell-attlist,
+    table-table-cell-attlist-extra,
+    table-table-cell-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-cell-content =
+  table-cell-range-source?,
+  office-annotation?,
+  table-detective?,
+  text-content*
+table-table-cell-range-source-attlist =
+  attribute table:name { \string }
+  & attribute table:last-column-spanned { positiveInteger }
+  & attribute table:last-row-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-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-columns =
+  element table:table-columns { table-table-column+ }
+table-table-header-columns =
+  element table:table-header-columns { table-table-column+ }
+table-table-header-rows =
+  element table:table-header-rows {
+    (text-soft-page-break?, table-table-row)+
+  }
+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-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 }?
+table-table-rows =
+  element table:table-rows { (text-soft-page-break?, table-table-row)+ }
+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-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 }
+table-target-range-address =
+  element table:target-range-address {
+    common-table-range-attlist, empty
+  }
+table-title = element table:title { text }
+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-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"
     }?
-  & attribute draw:ole-draw-aspect { nonNegativeInteger }?
-style-graphic-fill-properties-attlist =
-  attribute draw:fill {
-    "none" | "solid" | "bitmap" | "gradient" | "hatch"
+table-visibility-value = "visible" | "collapse" | "filter"
+target-frame = attribute office:target-frame { targetFrameName }?
+target-location = attribute xlink:href { anyIRI }?
+targetFrameName = "_self" | "_blank" | "_parent" | "_top" | \string
+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-alphabetical-index =
+  element text:alphabetical-index {
+    common-section-attlist,
+    text-alphabetical-index-source,
+    text-index-body
+  }
+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-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-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-bibliography =
+  element text:bibliography {
+    common-section-attlist, text-bibliography-source, text-index-body
+  }
+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-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-bibliography-source =
+  element text:bibliography-source {
+    text-index-title-template?, text-bibliography-entry-template*
+  }
+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-bookmark = element text:bookmark { text-bookmark-attlist, empty }
+text-bookmark-attlist =
+  attribute text:name { \string }
+  & xml-id?
+text-bookmark-end =
+  element text:bookmark-end { text-bookmark-end-attlist, empty }
+text-bookmark-end-attlist = attribute text:name { \string }
+text-bookmark-ref-content =
+  attribute text:reference-format {
+    common-ref-format-values
+    | "number-no-superior"
+    | "number-all-superior"
+    | "number"
   }?
-  & 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") }
+text-bookmark-start =
+  element text:bookmark-start { text-bookmark-start-attlist, empty }
+text-bookmark-start-attlist =
+  attribute text:name { \string }
+  & xml-id?
+  & common-in-content-meta-attlist?
+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 }
+text-chapter-attlist =
+  attribute text:display {
+    "name"
+    | "number"
+    | "number-and-name"
+    | "plain-number-and-name"
+    | "plain-number"
+  }
+  & attribute text:outline-level { nonNegativeInteger }
+text-common-ref-content =
+  text
+  & attribute text:ref-name { \string }?
+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-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
+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-date-attlist =
+  (common-field-fixed-attlist & common-field-data-style-name-attlist)
+  & attribute text:date-value { dateOrDateTime }?
+  & attribute text:date-adjust { duration }?
+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 }
+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?
+text-drop-down =
+  element text:drop-down {
+    attribute text:name { \string },
+    element text:label {
+      attribute text:value { \string }?,
+      attribute text:current-selected { boolean }?
+    }*,
+    text
+  }
+text-file-name-attlist =
+  attribute text:display {
+    "full" | "path" | "name" | "name-and-extension"
+  }?
+  & common-field-fixed-attlist
+text-get-page-variable-attlist = common-field-num-format-attlist
+text-h =
+  element text:h {
+    heading-attrs,
+    paragraph-attrs,
+    text-number?,
+    paragraph-content-or-hyperlink*
+  }
+text-hidden-paragraph-attlist =
+  attribute text:condition { \string }
+  & attribute text:is-hidden { boolean }?
+text-hidden-text-attlist =
+  attribute text:condition { \string }
+  & attribute text:string-value { \string }
+  & attribute text:is-hidden { boolean }?
+text-id = attribute text:id { \string }
+text-illustration-index =
+  element text:illustration-index {
+    common-section-attlist,
+    text-illustration-index-source,
+    text-index-body
+  }
+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-index-entry-link-start
+   | text-index-entry-link-end
+     # https://issues.oasis-open.org/browse/OFFICE-3941
+     )*
+text-illustration-index-entry-template =
+  element text:illustration-index-entry-template {
+    text-illustration-index-entry-content
+  }
+text-illustration-index-entry-template-attrs =
+  attribute text:style-name { styleNameRef }
+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"
     }?
-  & 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"
+text-index-body = element text:index-body { index-content-main* }
+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-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"
   }?
-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}[ ]*\)"
+  & attribute text:outline-level { positiveInteger }?
+text-index-entry-link-end =
+  element text:index-entry-link-end {
+    attribute text:style-name { styleNameRef }?
   }
-nonNegativePixelLength =
-  xsd:string { pattern = "([0-9]+(\.[0-9]*)?|\.[0-9]+)(px)" }
-style-chart-properties =
-  element style:chart-properties {
-    style-chart-properties-content-strict
+text-index-entry-link-start =
+  element text:index-entry-link-start {
+    attribute text:style-name { styleNameRef }?
   }
-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"
+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-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-text =
+  element text:index-entry-text {
+    attribute text:style-name { styleNameRef }?
+  }
+text-index-name = attribute text:index-name { \string }
+text-index-scope-attr =
+  attribute text:index-scope { "document" | "chapter" }?
+text-index-source-style =
+  element text:index-source-style {
+    attribute text:style-name { styleNameRef },
+    empty
+  }
+# https://issues.oasis-open.org/browse/OFFICE-3675
+text-index-source-styles =
+  element text:index-source-styles {
+    attribute text:outline-level { positiveInteger },
+    text-index-source-style*
+  }
+text-index-title =
+  element text:index-title {
+    common-section-attlist, index-content-main*
+  }
+text-index-title-template =
+  element text:index-title-template {
+    attribute text:style-name { styleNameRef }?,
+    text
+  }
+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 chart:tick-mark-position {
-      "at-labels" | "at-axis" | "at-labels-and-axis"
+  & 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-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-header =
+  element text:list-header {
+    text-list-header-attr, text-list-item-content
+  }
+text-list-header-attr = xml-id?
+text-list-item =
+  element text:list-item { text-list-item-attr, text-list-item-content }
+text-list-item-attr =
+  attribute text:start-value { nonNegativeInteger }?
+  & attribute text:style-override { styleNameRef }?
+  & xml-id?
+text-list-item-content =
+  text-number?, (text-p | text-h | text-list | text-soft-page-break)*
+text-list-level-style-attr = attribute text:level { 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-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-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-meta-attlist = common-in-content-meta-attlist? & xml-id?
+text-meta-field-attlist = xml-id & common-field-data-style-name-attlist
+text-note-class = attribute text:note-class { "footnote" | "endnote" }
+text-note-ref-content =
+  attribute text:reference-format { common-ref-format-values }?
+  & text-note-class
+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 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 text:footnotes-position {
+      "text" | "page" | "section" | "document"
     }?
-  & 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))"
+  & element text:note-continuation-notice-forward { text }?
+  & element text:note-continuation-notice-backward { text }?
+text-number = element text:number { \string }
+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-object-index =
+  element text:object-index {
+    common-section-attlist, text-object-index-source, text-index-body
+  }
+text-object-index-entry-template =
+  element text:object-index-entry-template {
+    text-illustration-index-entry-content
+  }
+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-outline-level = attribute text:outline-level { positiveInteger }?
+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 }?
+text-outline-style =
+  element text:outline-style {
+    text-outline-style-attr, text-outline-level-style+
+  }
+text-outline-style-attr = attribute style:name { styleName }
+text-p =
+  element text:p { paragraph-attrs, paragraph-content-or-hyperlink* }
+text-page = element text:page { text-page-attlist, empty }
+text-page-attlist = attribute text:master-page-name { styleNameRef }
+text-page-continuation-attlist =
+  attribute text:select-page { "previous" | "next" }
+  & attribute text:string-value { \string }?
+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-sequence = element text:page-sequence { text-page+ }
+text-placeholder-attlist =
+  attribute text:placeholder-type {
+    "text" | "table" | "text-box" | "image" | "object"
   }
-nonNegativeLength =
-  xsd:string {
-    pattern =
-      "([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc)|(px))"
+  & common-field-description-attlist
+text-relative-tab-stop-position-attr =
+  attribute text:relative-tab-stop-position { boolean }?
+text-section =
+  element text:section {
+    text-section-attlist,
+    (text-section-source | text-section-source-dde | empty),
+    text-content*
   }
-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))"
+text-section-attlist =
+  common-section-attlist
+  & (attribute text:display { "true" | "none" }
+     | (attribute text:display { "condition" },
+        attribute text:condition { \string })
+     | empty)
+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-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-content =
+  attribute text:reference-format {
+    common-ref-format-values
+    | "category-and-value"
+    | "caption"
+    | "value"
+  }?
+text-sequence-ref-name = attribute text:ref-name { \string }?
+text-set-page-variable-attlist =
+  attribute text:active { boolean }?
+  & attribute text:page-adjust { integer }?
+text-soft-page-break = element text:soft-page-break { empty }
+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-style-name = attribute form:text-style-name { styleNameRef }?
+text-tab-attr = attribute text:tab-ref { nonNegativeInteger }?
+text-table-index =
+  element text:table-index {
+    common-section-attlist, text-table-index-source, text-index-body
   }
-percent = xsd:string { pattern = "-?([0-9]+(\.[0-9]*)?|\.[0-9]+)%" }
-zeroToHundredPercent =
-  xsd:string {
-    pattern = "([0-9]?[0-9](\.[0-9]*)?|100(\.0*)?|\.[0-9]+)%"
+text-table-index-entry-template =
+  element text:table-index-entry-template {
+    text-illustration-index-entry-content
   }
-signedZeroToHundredPercent =
-  xsd:string {
-    pattern = "-?([0-9]?[0-9](\.[0-9]*)?|100(\.0*)?|\.[0-9]+)%"
+text-table-index-source =
+  element text:table-index-source {
+    text-illustration-index-source-attrs,
+    text-index-title-template?,
+    text-table-index-entry-template?
   }
-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"
+text-table-of-content =
+  element text:table-of-content {
+    common-section-attlist,
+    text-table-of-content-source,
+    text-index-body
   }
-URIorSafeCURIE = anyURI | SafeCURIE
-styleName = xsd:NCName
-styleNameRef = xsd:NCName | empty
-styleNameRefs = list { xsd:NCName* }
-variableName = xsd:string
-targetFrameName = "_self" | "_blank" | "_parent" | "_top" | \string
+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 =
+  element text:table-of-content-entry-template {
+    text-table-of-content-entry-template-attlist,
+    text-table-of-content-children*
+  }
+text-table-of-content-entry-template-attlist =
+  attribute text:outline-level { positiveInteger }
+  & attribute text:style-name { styleNameRef }
+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-template-name-attlist =
+  attribute text:display {
+    "full" | "path" | "name" | "name-and-extension" | "area" | "title"
+  }?
+text-time-attlist =
+  (common-field-fixed-attlist & common-field-data-style-name-attlist)
+  & attribute text:time-value { timeOrDateTime }?
+  & attribute text:time-adjust { duration }?
+text-toc-mark-start-attrs = text-id, text-outline-level
+text-tracked-changes =
+  element text:tracked-changes {
+    text-tracked-changes-attr, text-changed-region*
+  }?
+text-tracked-changes-attr = attribute text:track-changes { boolean }?
+text-user-field-decl =
+  element text:user-field-decl {
+    common-field-name-attlist,
+    common-field-formula-attlist?,
+    common-value-and-type-attlist
+  }
+text-user-index =
+  element text:user-index {
+    common-section-attlist, text-user-index-source, text-index-body
+  }
+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-index-entry-link-start
+     | text-index-entry-link-end
+       # https://issues.oasis-open.org/browse/OFFICE-3941
+       )*
+  }
+text-user-index-entry-template-attrs =
+  attribute text:outline-level { positiveInteger }
+  & attribute text:style-name { styleNameRef }
+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-variable-decl =
+  element text:variable-decl {
+    common-field-name-attlist, common-value-type-attlist
+  }
+textEncoding = xsd:string { pattern = "[A-Za-z][A-Za-z0-9._\-]*" }
+time = xsd:time
+timeOrDateTime = xsd:time | xsd:dateTime
+types = "submit" | "reset" | "push" | "url"
 valueType =
   "float"
   | "time"
@@ -6257,24 +6397,18 @@ valueType =
   | "currency"
   | "boolean"
   | "string"
-points =
-  xsd:string { pattern = "-?[0-9]+,-?[0-9]+([ ]+-?[0-9]+,-?[0-9]+)*" }
-pathData = xsd:string
+variableName = 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 }
-  }*
+vertBackPos = "top" | "center" | "bottom"
+xforms-bind-attlist = attribute xforms:bind { \string }?
+xforms-model = element xforms:model { anyAttListOrElements }
+xml-id = attribute xml:id { ID }
+zeroToHundredPercent =
+  xsd:string {
+    pattern = "([0-9]?[0-9](\.[0-9]*)?|100(\.0*)?|\.[0-9]+)%"
+  }
+zeroToOneDecimal = xsd:decimal { minInclusive = "0" maxInclusive = "1" }
diff --git a/etc/schema/schemas.xml b/etc/schema/schemas.xml
index f1e0ed7..3e6ed7b 100644
--- a/etc/schema/schemas.xml
+++ b/etc/schema/schemas.xml
@@ -1,7 +1,12 @@
 <?xml version="1.0"?>
 <locatingRules xmlns="http://thaiopensource.com/ns/locating-rules/1.0";>
+  <namespace ns="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
typeId="LibreOffice"/>
+  <namespace 
ns="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" 
typeId="LibreOffice"/>
+  <namespace 
ns="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" 
typeId="LibreOffice"/>
+  <namespace ns="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" 
typeId="OpenDocument Manifest"/>
+
   <documentElement prefix="office" typeId="OpenDocument"/>
   <documentElement prefix="manifest" localName="manifest" typeId="OpenDocument 
Manifest"/>
-  <typeId id="OpenDocument" uri="od-schema-v1.2-os.rnc"/>
+  <typeId id="LibreOffice" uri="OpenDocument-schema-v1.3+libreoffice.rnc"/>
   <typeId id="OpenDocument Manifest" uri="od-manifest-schema-v1.2-os.rnc"/>
 </locatingRules>
diff --git a/lisp/ob-C.el b/lisp/ob-C.el
index fdfe332..842e0d3 100644
--- a/lisp/ob-C.el
+++ b/lisp/ob-C.el
@@ -95,8 +95,7 @@ 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."
+  "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)
@@ -105,8 +104,7 @@ 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 its
-header arguments."
+  "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)
@@ -115,8 +113,7 @@ 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."
+  "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)
@@ -125,8 +122,7 @@ 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 its
-header arguments."
+  "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)
@@ -197,13 +193,11 @@ or `org-babel-execute:C++' or `org-babel-execute:D'."
       )))
 
 (defun org-babel-C-expand-C++ (body params)
-  "Expand a block of C or C++ code with org-babel according to
-its header arguments."
+  "Expand a block of C/C++ code with org-babel according to 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."
+  "Expand a block of C/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")))
@@ -272,8 +266,7 @@ its header arguments."
                  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."
+  "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")))
@@ -348,7 +341,7 @@ FORMAT can be either a format string or a function which is 
called with VAL."
             (list
              (if (eq org-babel-c-variant 'd) "string" "const char*")
              "\"%s\""))
-           (_ (error "unknown type %S" basetype)))))
+            (_ (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
@@ -405,8 +398,7 @@ FORMAT can be either a format string or a function which is 
called with VAL."
    (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."
+  "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)))
@@ -446,8 +438,7 @@ of the same value."
       (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."
+  "Generate a utility function to convert a column name into a column number."
   (pcase org-babel-c-variant
     ((or `c `cpp)
      (concat
@@ -487,18 +478,18 @@ specifying a variable with the name of the table."
                                 ((or `c `cpp) "const char*")
                                 (`d "string"))))))
     (concat
-      (pcase org-babel-c-variant
-       ((or `c `cpp)
-         (format "const char* %s_header[%d] = {%s};"
-                 table
-                 (length headers)
-                 (mapconcat (lambda (h) (format "\"%s\"" h)) headers ",")))
-       (`d
-         (format "string[%d] %s_header = [%s];"
-                 (length headers)
-                 table
-                 (mapconcat (lambda (h) (format "\"%s\"" h)) headers ","))))
-      "\n"
+     (pcase org-babel-c-variant
+       ((or `c `cpp)
+        (format "const char* %s_header[%d] = {%s};"
+                table
+                (length headers)
+                (mapconcat (lambda (h) (format "\"%s\"" h)) headers ",")))
+       (`d
+        (format "string[%d] %s_header = [%s];"
+                (length headers)
+                table
+                (mapconcat (lambda (h) (format "\"%s\"" h)) headers ","))))
+     "\n"
      (pcase org-babel-c-variant
        ((or `c `cpp)
        (format
diff --git a/lisp/ob-J.el b/lisp/ob-J.el
deleted file mode 100644
index 0c5591d..0000000
--- a/lisp/ob-J.el
+++ /dev/null
@@ -1,189 +0,0 @@
-;;; ob-J.el --- Babel Functions for J                -*- lexical-binding: t; 
-*-
-
-;; Copyright (C) 2011-2021 Free Software Foundation, Inc.
-
-;; Author: Oleh Krehel
-;; Maintainer: Joseph Novakovich <josephnovakovich@gmail.com>
-;; Keywords: literate programming, reproducible research
-;; Homepage: https://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 <https://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)
-(require 'org-macs)
-
-(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)))
-        (sit-time (let ((sit (assq :sit params)))
-                    (if sit (cdr sit) .1)))
-         (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 sit-time)))))
-
-(defun org-babel-J-eval-string (str sit-time)
-  "Sends STR to the `j-console-cmd' session and executes 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 sit-time)
-       (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/ob-R.el b/lisp/ob-R.el
index 89430de..169e1d6 100644
--- a/lisp/ob-R.el
+++ b/lisp/ob-R.el
@@ -4,6 +4,7 @@
 
 ;; Author: Eric Schulte
 ;;     Dan Davison
+;; Maintainer: Jeremie Juste
 ;; Keywords: literate programming, reproducible research, R, statistics
 ;; Homepage: https://orgmode.org
 
@@ -39,6 +40,13 @@
 (declare-function ess-wait-for-process "ext:ess-inf"
                  (&optional proc sec-prompt wait force-redisplay))
 
+;; FIXME: Temporary declaration to silence the byte-compiler
+(defvar user-inject-src-param)
+(defvar ess-eval-visibly-tmp)
+(defvar ess-eval-visibly)
+(defvar ess-inject-source)
+(defvar user-inject-src-param)
+
 (defconst org-babel-header-args:R
   '((width              . :any)
     (height             . :any)
@@ -157,6 +165,7 @@ This function is called by `org-babel-execute-src-block'."
   (save-excursion
     (let* ((result-params (cdr (assq :result-params params)))
           (result-type (cdr (assq :result-type params)))
+           (async (org-babel-comint-use-async params))
            (session (org-babel-R-initiate-session
                     (cdr (assq :session params)) params))
           (graphics-file (and (member "graphics" (assq :result-params params))
@@ -183,7 +192,8 @@ This function is called by `org-babel-execute-src-block'."
                  (cdr (assq :colname-names params)) colnames-p))
             (or (equal "yes" rownames-p)
                 (org-babel-pick-name
-                 (cdr (assq :rowname-names params)) rownames-p)))))
+                 (cdr (assq :rowname-names params)) rownames-p))
+             async)))
       (if graphics-file nil result))))
 
 (defun org-babel-prep-session:R (session params)
@@ -321,7 +331,7 @@ Each member of this list is a list with three members:
         (device-info (or (assq (intern (concat ":" device))
                                org-babel-R-graphics-devices)
                           (assq :png org-babel-R-graphics-devices)))
-        (extra-args (cdr (assq :R-dev-args params))) filearg args)
+         (extra-args (cdr (assq :R-dev-args params))) filearg args)
     (setq device (nth 1 device-info))
     (setq filearg (nth 2 device-info))
     (setq args (mapconcat
@@ -348,7 +358,7 @@ Each member of this list is a list with three members:
                         {
                             tfile<-tempfile()
                             write.table(object, file=tfile, sep=\"\\t\",
-                                        na=\"nil\",row.names=%s,col.names=%s,
+                                        na=\"\",row.names=%s,col.names=%s,
                                         quote=FALSE)
                             file.rename(tfile,transfer.file)
                         },
@@ -361,7 +371,7 @@ Each member of this list is a list with three members:
             )
     }
 }(object=%s,transfer.file=\"%s\")"
-  "A template for an R command to evaluate a block of code and write the 
result to a file.
+  "Template for an R command to evaluate a block of code and write result to 
file.
 
 Has four %s escapes to be filled in:
 1. Row names, \"TRUE\" or \"FALSE\"
@@ -370,11 +380,14 @@ Has four %s escapes to be filled in:
 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)
+    (session body result-type result-params column-names-p row-names-p async)
   "Evaluate R code in BODY."
   (if session
-      (org-babel-R-evaluate-session
-       session body result-type result-params column-names-p row-names-p)
+      (if async
+          (ob-session-async-org-babel-R-evaluate-session
+           session body result-type result-params column-names-p row-names-p)
+        (org-babel-R-evaluate-session
+         session body result-type result-params column-names-p row-names-p))
     (org-babel-R-evaluate-external-process
      body result-type result-params column-names-p row-names-p)))
 
@@ -450,11 +463,13 @@ last statement in BODY, as elisp."
                      (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
-                                   (list body org-babel-R-eoe-indicator)
-                                   "\n"))
-                (inferior-ess-send-input)))))) "\n"))))
+              (with-current-buffer session
+                (let ((comint-prompt-regexp (concat "^" comint-prompt-regexp)))
+                  (org-babel-comint-with-output (session 
org-babel-R-eoe-output)
+                    (insert (mapconcat 'org-babel-chomp
+                                       (list body org-babel-R-eoe-indicator)
+                                       "\n"))
+                    (inferior-ess-send-input)))))))) "\n"))))
 
 (defun org-babel-R-process-value-result (result column-names-p)
   "R-specific processing of return value.
@@ -465,6 +480,91 @@ Insert hline if column names in output have been 
requested."
        (error "Could not parse R result"))
     result))
 
+
+;;; async evaluation
+
+(defconst ob-session-async-R-indicator "'ob_comint_async_R_%s_%s'")
+
+(defun ob-session-async-org-babel-R-evaluate-session
+    (session body result-type _ column-names-p row-names-p)
+  "Asynchronously evaluate BODY in SESSION.
+Returns a placeholder string for insertion, to later be replaced
+by `org-babel-comint-async-filter'."
+  (org-babel-comint-async-register
+   session (current-buffer)
+   "^\\(?:[>.+] \\)*\\[1\\] \"ob_comint_async_R_\\(.+?\\)_\\(.+\\)\"$"
+   'org-babel-chomp
+   'ob-session-async-R-value-callback)
+  (cl-case result-type
+    (value
+     (let ((tmp-file (org-babel-temp-file "R-")))
+       (with-temp-buffer
+         (insert
+          (org-babel-chomp body))
+         (let ((ess-local-process-name
+                (process-name (get-buffer-process session))))
+           (ess-eval-buffer nil)))
+       (with-temp-buffer
+        (insert
+         (mapconcat
+           'org-babel-chomp
+           (list (format org-babel-R-write-object-command
+                         (if row-names-p "TRUE" "FALSE")
+                         (if column-names-p
+                             (if row-names-p "NA" "TRUE")
+                           "FALSE")
+                         ".Last.value"
+                         (org-babel-process-file-name tmp-file 'noquote))
+                 (format ob-session-async-R-indicator
+                         "file" tmp-file))
+           "\n"))
+        (let ((ess-local-process-name
+               (process-name (get-buffer-process session))))
+          (ess-eval-buffer nil)))
+       tmp-file))
+    (output
+     (let ((uuid (md5 (number-to-string (random 100000000))))
+           (ess-local-process-name
+            (process-name (get-buffer-process session))))
+       (with-temp-buffer
+         (insert (format ob-session-async-R-indicator
+                        "start" uuid))
+         (insert "\n")
+         (insert body)
+         (insert "\n")
+         (insert (format ob-session-async-R-indicator
+                        "end" uuid))
+         (setq ess-eval-visibly-tmp ess-eval-visibly)
+         (setq user-inject-src-param ess-inject-source)
+         (setq ess-eval-visibly nil)
+         (setq ess-inject-source 'function-and-buffer)
+         (ess-eval-buffer nil))
+       (setq ess-eval-visibly ess-eval-visibly-tmp)
+       (setq ess-inject-source user-inject-src-param)
+       uuid))))
+
+(defun ob-session-async-R-value-callback (params tmp-file)
+  "Callback for async value results.
+Assigned locally to `ob-session-async-file-callback' in R
+comint buffers used for asynchronous Babel evaluation."
+  (let* ((graphics-file (and (member "graphics" (assq :result-params params))
+                            (org-babel-graphical-output-file params)))
+        (colnames-p (unless graphics-file (cdr (assq :colnames params)))))
+    (org-babel-R-process-value-result
+     (org-babel-result-cond (assq :result-params params)
+       (with-temp-buffer
+         (insert-file-contents tmp-file)
+         (org-babel-chomp (buffer-string) "\n"))
+       (org-babel-import-elisp-from-file tmp-file '(16)))
+     (or (equal "yes" colnames-p)
+        (org-babel-pick-name
+         (cdr (assq :colname-names params)) colnames-p)))))
+
+
+
+;;; ob-session-async-R.el ends here
+
+
 (provide 'ob-R)
 
 ;;; ob-R.el ends here
diff --git a/lisp/ob-abc.el b/lisp/ob-abc.el
deleted file mode 100644
index 404e39f..0000000
--- a/lisp/ob-abc.el
+++ /dev/null
@@ -1,90 +0,0 @@
-;;; ob-abc.el --- Org Babel Functions for ABC -*- lexical-binding: t; -*-
-
-;; Copyright (C) 2013-2021 Free Software Foundation, Inc.
-
-;; Author: William Waites
-;; Keywords: literate programming, music
-;; Homepage: https://www.tardis.ed.ac.uk/~wwaites
-
-;; 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 <https://www.gnu.org/licenses/>.
-
-;;; 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/ob-asymptote.el b/lisp/ob-asymptote.el
deleted file mode 100644
index bfb5b79..0000000
--- a/lisp/ob-asymptote.el
+++ /dev/null
@@ -1,137 +0,0 @@
-;;; ob-asymptote.el --- Babel Functions for Asymptote -*- lexical-binding: t; 
-*-
-
-;; Copyright (C) 2009-2021 Free Software Foundation, Inc.
-
-;; Author: Eric Schulte
-;; Keywords: literate programming, reproducible research
-;; Homepage: https://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 <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; Org-Babel support for evaluating asymptote source code.
-;;
-;; This differs from most standard languages in that
-;;
-;; 1) there is no such thing as a "session" in asymptote
-;;
-;; 2) we are generally only going to return results of type "file"
-;;
-;; 3) we are adding the "file" and "cmdline" header arguments, if file
-;;    is omitted then the -V option is passed to the asy command for
-;;    interactive viewing
-
-;;; Requirements:
-
-;; - The asymptote program :: http://asymptote.sourceforge.net/
-;;
-;; - asy-mode :: Major mode for editing asymptote files
-
-;;; Code:
-(require 'ob)
-
-(defvar org-babel-tangle-lang-exts)
-(add-to-list 'org-babel-tangle-lang-exts '("asymptote" . "asy"))
-
-(defvar org-babel-default-header-args:asymptote
-  '((:results . "file") (:exports . "results"))
-  "Default arguments when evaluating an Asymptote source block.")
-
-(defun org-babel-execute:asymptote (body params)
-  "Execute a block of Asymptote code.
-This function is called by `org-babel-execute-src-block'."
-  (let* ((out-file (cdr (assq :file params)))
-         (format (or (file-name-extension out-file)
-                     "pdf"))
-         (cmdline (cdr (assq :cmdline params)))
-         (in-file (org-babel-temp-file "asymptote-"))
-         (cmd
-         (concat "asy "
-                 (if out-file
-                     (concat
-                      "-globalwrite -f " format
-                      " -o " (org-babel-process-file-name out-file))
-                   "-V")
-                 " " cmdline
-                 " " (org-babel-process-file-name in-file))))
-    (with-temp-file in-file
-      (insert (org-babel-expand-body:generic
-              body params
-              (org-babel-variable-assignments:asymptote params))))
-    (message cmd) (shell-command cmd)
-    nil)) ;; signal that output has already been written to file
-
-(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"))
-
-(defun org-babel-variable-assignments:asymptote (params)
-  "Return list of asymptote statements assigning the block's variables."
-  (mapcar #'org-babel-asymptote-var-to-asymptote
-         (org-babel--get-vars params)))
-
-(defun org-babel-asymptote-var-to-asymptote (pair)
-  "Convert an elisp value into an Asymptote variable.
-The elisp value PAIR is converted into Asymptote 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 "real %S=%S;" var val))
-     ((stringp val)
-      (format "string %S=\"%s\";" var val))
-     ((and (listp val) (not (listp (car val))))
-      (let* ((type (org-babel-asymptote-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-asymptote-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-asymptote-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 `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)
-
-;;; ob-asymptote.el ends here
diff --git a/lisp/ob-awk.el b/lisp/ob-awk.el
index b41d70f..28e9d32 100644
--- a/lisp/ob-awk.el
+++ b/lisp/ob-awk.el
@@ -3,6 +3,7 @@
 ;; Copyright (C) 2011-2021 Free Software Foundation, Inc.
 
 ;; Author: Eric Schulte
+;; Maintainer: Tyler Smith <tyler@plantarum.ca>
 ;; Keywords: literate programming, reproducible research
 ;; Homepage: https://orgmode.org
 
@@ -58,12 +59,12 @@ This function is called by `org-babel-execute-src-block'."
         (code-file (let ((file (org-babel-temp-file "awk-")))
                       (with-temp-file file (insert full-body)) file))
         (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))))
+                 (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
                         (append
                          (list org-babel-awk-command
diff --git a/lisp/ob-calc.el b/lisp/ob-calc.el
index 39ebce1..5962d38 100644
--- a/lisp/ob-calc.el
+++ b/lisp/ob-calc.el
@@ -3,6 +3,7 @@
 ;; Copyright (C) 2010-2021 Free Software Foundation, Inc.
 
 ;; Author: Eric Schulte
+;; Maintainer: Tom Gillespie <tgbugs@gmail.com>
 ;; Keywords: literate programming, reproducible research
 ;; Homepage: https://orgmode.org
 
@@ -90,7 +91,7 @@
   (save-excursion
     (with-current-buffer (get-buffer "*Calculator*")
       (prog1
-        (calc-eval (calc-top 1))
+          (calc-eval (calc-top 1))
         (calc-pop 1)))))
 
 (defun org-babel-calc-maybe-resolve-var (el)
diff --git a/lisp/ob-clojure.el b/lisp/ob-clojure.el
index df2d691..3b995d9 100644
--- a/lisp/ob-clojure.el
+++ b/lisp/ob-clojure.el
@@ -3,6 +3,7 @@
 ;; Copyright (C) 2009-2021 Free Software Foundation, Inc.
 
 ;; Author: Joel Boehland, Eric Schulte, Oleh Krehel, Frederick Giasson
+;; Maintainer: Bastien Guerry <bzg@gnu.org>
 ;;
 ;; Keywords: literate programming, reproducible research
 ;; Homepage: https://orgmode.org
@@ -38,7 +39,7 @@
 
 ;; 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
+;; web page: https://technomancy.us/126
 
 ;;; Code:
 (require 'ob)
diff --git a/lisp/ob-comint.el b/lisp/ob-comint.el
index 18d4f3c..20ae76f 100644
--- a/lisp/ob-comint.el
+++ b/lisp/ob-comint.el
@@ -44,7 +44,7 @@
 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))
+  (declare (indent 1) (debug t))
   `(progn
      (unless (org-babel-comint-buffer-livep ,buffer)
        (error "Buffer %s does not exist or has no process" ,buffer))
@@ -53,7 +53,6 @@ executed inside the protection of `save-excursion' and
         (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)
   "Evaluate BODY in BUFFER and return process output.
@@ -67,7 +66,7 @@ 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))
+  (declare (indent 1) (debug (sexp body)))
   (let ((buffer (nth 0 meta))
        (eoe-indicator (nth 1 meta))
        (remove-echo (nth 2 meta))
@@ -94,12 +93,7 @@ or user `keyboard-quit' during execution of body."
                               (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)))
-          )
+          (accept-process-output (get-buffer-process (current-buffer))))
         ;; replace cut dangling text
         (goto-char (process-mark (get-buffer-process (current-buffer))))
         (insert dangling-text)
@@ -112,7 +106,6 @@ or user `keyboard-quit' during execution of 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))
 
 (defun org-babel-comint-input-command (buffer cmd)
   "Pass CMD to BUFFER.
@@ -137,7 +130,7 @@ statement (not large blocks of code)."
       (accept-process-output (get-buffer-process buffer)))))
 
 (defun org-babel-comint-eval-invisibly-and-wait-for-file
-  (buffer file string &optional period)
+    (buffer file string &optional period)
   "Evaluate STRING in BUFFER invisibly.
 Don't return until FILE exists.  Code in STRING must ensure that
 FILE exists at end of evaluation."
@@ -149,6 +142,171 @@ FILE exists at end of evaluation."
    (if (= (aref string (1- (length string))) ?\n) string (concat string "\n")))
   (while (not (file-exists-p file)) (sit-for (or period 0.25))))
 
+
+;;; Async evaluation
+
+(defvar-local org-babel-comint-async-indicator nil
+  "Regular expression that `org-babel-comint-async-filter' scans for.
+It should have 2 parenthesized expressions,
+e.g. \"org_babel_async_\\(start\\|end\\|file\\)_\\(.*\\)\".  The
+first parenthesized expression determines whether the token is
+delimiting a result block, or whether the result is in a file.
+If delimiting a block, the second expression gives a UUID for the
+location to insert the result.  Otherwise, the result is in a tmp
+file, and the second expression gives the file name.")
+
+(defvar-local org-babel-comint-async-buffers nil
+  "List of Org mode buffers to check for Babel async output results.")
+
+(defvar-local org-babel-comint-async-file-callback nil
+  "Callback to clean and insert Babel async results from a temp file.
+The callback function takes two arguments: the alist of params of the Babel
+source block, and the name of the temp file.")
+
+(defvar-local org-babel-comint-async-chunk-callback nil
+  "Callback function to clean Babel async output results before insertion.
+Its single argument is a string consisting of output from the
+comint process.  It should return a string that will be be passed
+to `org-babel-insert-result'.")
+
+(defvar-local org-babel-comint-async-dangling nil
+  "Dangling piece of the last process output, in case
+`org-babel-comint-async-indicator' is spread across multiple
+comint outputs due to buffering.")
+
+(defun org-babel-comint-use-async (params)
+  "Determine whether to use session async evaluation.
+PARAMS are the header arguments as passed to
+`org-babel-execute:lang'."
+  (let ((async (assq :async params))
+        (session (assq :session params)))
+    (and async
+        (not org-babel-exp-reference-buffer)
+         (not (equal (cdr async) "no"))
+         (not (equal (cdr session) "none")))))
+
+(defun org-babel-comint-async-filter (string)
+  "Captures Babel async output from comint buffer back to Org mode buffers.
+This function is added as a hook to `comint-output-filter-functions'.
+STRING contains the output originally inserted into the comint buffer."
+  ;; Remove outdated Org mode buffers
+  (setq org-babel-comint-async-buffers
+       (cl-loop for buf in org-babel-comint-async-buffers
+                if (buffer-live-p buf)
+                collect buf))
+  (let* ((indicator org-babel-comint-async-indicator)
+        (org-buffers org-babel-comint-async-buffers)
+        (file-callback org-babel-comint-async-file-callback)
+        (combined-string (concat org-babel-comint-async-dangling string))
+        (new-dangling combined-string)
+        ;; list of UUID's matched by `org-babel-comint-async-indicator'
+        uuid-list)
+    (with-temp-buffer
+      (insert combined-string)
+      (goto-char (point-min))
+      (while (re-search-forward indicator nil t)
+       ;; update dangling
+       (setq new-dangling (buffer-substring (point) (point-max)))
+       (cond ((equal (match-string 1) "end")
+              ;; save UUID for insertion later
+              (push (match-string 2) uuid-list))
+             ((equal (match-string 1) "file")
+              ;; insert results from tmp-file
+              (let ((tmp-file (match-string 2)))
+                (cl-loop for buf in org-buffers
+                         until
+                         (with-current-buffer buf
+                           (save-excursion
+                             (goto-char (point-min))
+                             (when (search-forward tmp-file nil t)
+                               (org-babel-previous-src-block)
+                                (let* ((info (org-babel-get-src-block-info))
+                                       (params (nth 2 info))
+                                       (result-params
+                                        (cdr (assq :result-params params))))
+                                  (org-babel-insert-result
+                                   (funcall file-callback
+                                            (nth
+                                             2 (org-babel-get-src-block-info))
+                                            tmp-file)
+                                   result-params info))
+                               t))))))))
+      ;; Truncate dangling to only the most recent output
+      (when (> (length new-dangling) (length string))
+       (setq new-dangling string)))
+    (setq-local org-babel-comint-async-dangling new-dangling)
+    (when uuid-list
+      ;; Search for results in the comint buffer
+      (save-excursion
+       (goto-char (point-max))
+       (while uuid-list
+         (re-search-backward indicator)
+         (when (equal (match-string 1) "end")
+           (let* ((uuid (match-string-no-properties 2))
+                  (res-str-raw
+                   (buffer-substring
+                    ;; move point to beginning of indicator
+                     (- (match-beginning 0) 1)
+                    ;; find the matching start indicator
+                    (cl-loop
+                      do (re-search-backward indicator)
+                     until (and (equal (match-string 1) "start")
+                                (equal (match-string 2) uuid))
+                     finally return (+ 1 (match-end 0)))))
+                  ;; Apply callback to clean up the result
+                  (res-str (funcall org-babel-comint-async-chunk-callback
+                                     res-str-raw)))
+             ;; Search for uuid in associated org-buffers to insert results
+             (cl-loop for buf in org-buffers
+                      until (with-current-buffer buf
+                              (save-excursion
+                                (goto-char (point-min))
+                                (when (search-forward uuid nil t)
+                                  (org-babel-previous-src-block)
+                                   (let* ((info (org-babel-get-src-block-info))
+                                          (params (nth 2 info))
+                                          (result-params
+                                           (cdr (assq :result-params params))))
+                                    (org-babel-insert-result
+                                      res-str result-params info))
+                                  t))))
+             ;; Remove uuid from the list to search for
+             (setq uuid-list (delete uuid uuid-list)))))))))
+
+(defun org-babel-comint-async-register
+    (session-buffer org-buffer indicator-regexp
+                   chunk-callback file-callback)
+  "Set local org-babel-comint-async variables in SESSION-BUFFER.
+ORG-BUFFER is added to `org-babel-comint-async-buffers' if not
+present.  `org-babel-comint-async-indicator',
+`org-babel-comint-async-chunk-callback', and
+`org-babel-comint-async-file-callback' are set to
+INDICATOR-REGEXP, CHUNK-CALLBACK, and FILE-CALLBACK
+respectively."
+  (org-babel-comint-in-buffer session-buffer
+    (setq org-babel-comint-async-indicator indicator-regexp
+         org-babel-comint-async-chunk-callback chunk-callback
+         org-babel-comint-async-file-callback file-callback)
+    (unless (memq org-buffer org-babel-comint-async-buffers)
+      (setq org-babel-comint-async-buffers
+           (cons org-buffer org-babel-comint-async-buffers)))
+    (add-hook 'comint-output-filter-functions
+             'org-babel-comint-async-filter nil t)))
+
+(defmacro org-babel-comint-async-delete-dangling-and-eval
+    (session-buffer &rest body)
+  "Remove dangling text in SESSION-BUFFER and evaluate BODY.
+This is analogous to `org-babel-comint-with-output', but meant
+for asynchronous output, and much shorter because inserting the
+result is delegated to `org-babel-comint-async-filter'."
+  (declare (indent 1) (debug t))
+  `(org-babel-comint-in-buffer ,session-buffer
+     (goto-char (process-mark (get-buffer-process (current-buffer))))
+     (delete-region (point) (point-max))
+     ,@body))
+
 (provide 'ob-comint)
 
+
+
 ;;; ob-comint.el ends here
diff --git a/lisp/ob-coq.el b/lisp/ob-coq.el
deleted file mode 100644
index c77e8c9..0000000
--- a/lisp/ob-coq.el
+++ /dev/null
@@ -1,80 +0,0 @@
-;;; ob-coq.el --- Babel Functions for Coq            -*- lexical-binding: t; 
-*-
-
-;; Copyright (C) 2010-2021 Free Software Foundation, Inc.
-
-;; Author: Eric Schulte
-;; Keywords: literate programming, reproducible research
-;; Homepage: https://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 <https://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.
-;;
-;; https://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)
-
-;;; ob-coq.el ends here
diff --git a/lisp/ob-core.el b/lisp/ob-core.el
index b1aee1b..06a2a88 100644
--- a/lisp/ob-core.el
+++ b/lisp/ob-core.el
@@ -290,9 +290,9 @@ environment, to override this check."
                     (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)))
+                (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
@@ -472,7 +472,35 @@ For the format of SAFE-LIST, see 
`org-babel-safe-header-args'."
 (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.")
+  "Default arguments to use when evaluating a source block.
+
+This is a list in which each element is an alist.  Each key
+corresponds to a header argument, and each value to that header's
+value.  The value can either be a string or a closure that
+evaluates to a string.  The closure is evaluated when the source
+block is being evaluated (e.g. during execution or export), with
+point at the source block.  It is not possible to use an
+arbitrary function symbol (e.g. 'some-func), since org uses
+lexical binding.  To achieve the same functionality, call the
+function within a closure (e.g. (lambda () (some-func))).
+
+To understand how closures can be used as default header
+arguments, imagine you'd like to set the file name output of a
+latex source block to a sha1 of its contents.  We could achieve
+this with:
+
+(defun org-src-sha ()
+  (let ((elem (org-element-at-point)))
+    (concat (sha1 (org-element-property :value elem)) \".svg\")))
+
+(setq org-babel-default-header-args:latex
+      `((:results . \"file link replace\")
+        (:file . (lambda () (org-src-sha)))))
+
+Because the closure is evaluated with point at the source block,
+the call to `org-element-at-point' above will always retrieve
+information about the current source block.")
+
 (put 'org-babel-default-header-args 'safe-local-variable
      (org-babel-header-args-safe-fn org-babel-safe-header-args))
 
@@ -538,7 +566,7 @@ to raise errors for all languages.")
   "Number of initial characters to show of a hidden results hash.")
 
 (defvar org-babel-after-execute-hook nil
-  "Hook for functions to be called after `org-babel-execute-src-block'")
+  "Hook for functions to be called after `org-babel-execute-src-block'.")
 
 (defun org-babel-named-src-block-regexp-for-name (&optional name)
   "Generate a regexp used to match a source block named NAME.
@@ -581,7 +609,17 @@ multiple blocks are being executed (e.g., in chained 
execution
 through use of the :var header argument) this marker points to
 the outer-most code block.")
 
-(defvar *this*)
+(defun org-babel-eval-headers (headers)
+  "Compute header list set with HEADERS.
+
+Evaluate all header arguments set to functions prior to returning
+the list of header arguments."
+  (let ((lst nil))
+    (dolist (elem headers)
+      (if (and (cdr elem) (functionp (cdr elem)))
+          (push `(,(car elem) . ,(funcall (cdr elem))) lst)
+        (push elem lst)))
+    (reverse lst)))
 
 (defun org-babel-get-src-block-info (&optional light datum)
   "Extract information from a source block or inline source block.
@@ -646,6 +684,16 @@ a list with the following pattern:
       (replace-regexp-in-string
        (org-src-coderef-regexp coderef) "" expand nil nil 1))))
 
+(defun org-babel--file-desc (params result)
+  "Retrieve file description."
+  (pcase (assq :file-desc params)
+    (`nil nil)
+    (`(:file-desc) result)
+    (`(:file-desc . ,(and (pred stringp) val)) val)))
+
+(defvar *this*) ; Dynamically bound in `org-babel-execute-src-block'
+                ; and `org-babel-read'
+
 ;;;###autoload
 (defun org-babel-execute-src-block (&optional arg info params)
   "Execute the current source code block.
@@ -749,8 +797,7 @@ block."
                    (let ((*this* (if (not file) result
                                    (org-babel-result-to-file
                                     file
-                                    (let ((desc (assq :file-desc params)))
-                                      (and desc (or (cdr desc) result)))))))
+                                    (org-babel--file-desc params result)))))
                      (setq result (org-babel-ref-resolve post))
                      (when file
                        (setq result-params (remove "file" result-params))))))
@@ -802,27 +849,6 @@ arguments and pop open the results in a preview buffer."
         expanded (concat "*Org-Babel Preview " (buffer-name) "[ " lang " ]*"))
       expanded)))
 
-(defun org-babel-edit-distance (s1 s2)
-  "Return the edit (levenshtein) distance between strings S1 S2."
-  (let* ((l1 (length s1))
-        (l2 (length s2))
-        (dist (vconcat (mapcar (lambda (_) (make-vector (1+ l2) nil))
-                               (number-sequence 1 (1+ l1)))))
-        (in (lambda (i j) (aref (aref dist i) j))))
-    (setf (aref (aref dist 0) 0) 0)
-    (dolist (j (number-sequence 1 l2))
-      (setf (aref (aref dist 0) j) j))
-    (dolist (i (number-sequence 1 l1))
-      (setf (aref (aref dist i) 0) i)
-      (dolist (j (number-sequence 1 l2))
-       (setf (aref (aref dist i) j)
-             (min
-              (1+ (funcall in (1- i) j))
-              (1+ (funcall in i (1- j)))
-              (+ (if (equal (aref s1 (1- i)) (aref s2 (1- j))) 0 1)
-                 (funcall in (1- i) (1- j)))))))
-    (funcall in l1 l2)))
-
 (defun org-babel-combine-header-arg-lists (original &rest others)
   "Combine a number of lists of header argument names and arguments."
   (let ((results (copy-sequence original)))
@@ -851,7 +877,7 @@ arguments and pop open the results in a preview buffer."
                                   (match-string 4))))))
       (dolist (name names)
        (when (and (not (string= header name))
-                  (<= (org-babel-edit-distance header name) too-close)
+                  (<= (org-string-distance header name) too-close)
                   (not (member header names)))
          (error "Supplied header \"%S\" is suspiciously close to \"%S\""
                 header name))))
@@ -1100,7 +1126,7 @@ end-header-args -- point at the end of the header-args
 body ------------- string holding the body of the code block
 beg-body --------- point at the beginning of the body
 end-body --------- point at the end of the body"
-  (declare (indent 1))
+  (declare (indent 1) (debug t))
   (let ((tempvar (make-symbol "file")))
     `(let* ((case-fold-search t)
            (,tempvar ,file)
@@ -1139,7 +1165,6 @@ end-body --------- point at the end of the body"
               (goto-char end-block)))))
        (unless visited-p (kill-buffer to-be-removed))
        (goto-char point))))
-(def-edebug-spec org-babel-map-src-blocks (form body))
 
 ;;;###autoload
 (defmacro org-babel-map-inline-src-blocks (file &rest body)
@@ -1354,7 +1379,7 @@ the `org-mode-hook'."
        (goto-char (match-beginning 0))
        (org-babel-hide-hash)
        (goto-char (match-end 0))))))
-(add-hook 'org-mode-hook 'org-babel-hide-all-hashes)
+(add-hook 'org-mode-hook #'org-babel-hide-all-hashes)
 
 (defun org-babel-hash-at-point (&optional point)
   "Return the value of the hash at POINT.
@@ -1372,7 +1397,7 @@ This can be called with `\\[org-ctrl-c-ctrl-c]'."
 Add `org-babel-hide-result' as an invisibility spec for hiding
 portions of results lines."
   (add-to-invisibility-spec '(org-babel-hide-result . t)))
-(add-hook 'org-mode-hook 'org-babel-result-hide-spec)
+(add-hook 'org-mode-hook #'org-babel-result-hide-spec)
 
 (defvar org-babel-hide-result-overlays nil
   "Overlays hiding results.")
@@ -1443,11 +1468,11 @@ portions of results lines."
        (push ov org-babel-hide-result-overlays)))))
 
 ;; org-tab-after-check-for-cycling-hook
-(add-hook 'org-tab-first-hook 'org-babel-hide-result-toggle-maybe)
+(add-hook 'org-tab-first-hook #'org-babel-hide-result-toggle-maybe)
 ;; Remove overlays when changing major mode
 (add-hook 'org-mode-hook
          (lambda () (add-hook 'change-major-mode-hook
-                         'org-babel-show-result-all 'append 'local)))
+                              #'org-babel-show-result-all 'append 'local)))
 
 (defun org-babel-params-from-properties (&optional lang no-eval)
   "Retrieve source block parameters specified as properties.
@@ -1551,11 +1576,11 @@ balanced instances of \"[ \t]:\", set ALTS to ((32 9) . 
58)."
        (first= (lambda (str) (= ch (aref str 0)))))
     (reverse
      (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))
-                      (cons el acc))))
-                list :initial-value nil))))
+                 (let ((head (car acc)))
+                   (if (and head (or (funcall last= head) (funcall first= el)))
+                       (cons (concat head el) (cdr acc))
+                     (cons el acc))))
+               list :initial-value nil))))
 
 (defun org-babel-parse-header-arguments (string &optional no-eval)
   "Parse header arguments in STRING.
@@ -1629,7 +1654,7 @@ shown below.
                                (t 'value))))
      (cl-remove-if
       (lambda (x) (memq (car x) '(:colname-names :rowname-names :result-params
-                                           :result-type :var)))
+                                                :result-type :var)))
       params))))
 
 ;; row and column names
@@ -1699,9 +1724,12 @@ of the vars, cnames and rnames."
     (list
      (mapcar
       (lambda (var)
-        (when (listp (cdr var))
+        (when (proper-list-p (cdr var))
           (when (and (not (equal colnames "no"))
-                     (or colnames (and (eq (nth 1 (cdr var)) 'hline)
+                     ;; Compatibility note: avoid `length>', which
+                     ;; isn't available until Emacs 28.
+                     (or colnames (and (> (length (cdr var)) 1)
+                                       (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))
@@ -1721,7 +1749,7 @@ of the vars, cnames and rnames."
 (defun org-babel-reassemble-table (table colnames rownames)
   "Add column and row names to a table.
 Given a TABLE and set of COLNAMES and ROWNAMES add the names
-to the table for reinsertion to org-mode."
+to the table for reinsertion to `org-mode'."
   (if (listp table)
       (let ((table (if (and rownames (= (length table) (length rownames)))
                        (org-babel-put-rownames table rownames) table)))
@@ -1756,7 +1784,7 @@ If the point is not on a source block then return nil."
   "Go to the beginning of the current code block."
   (interactive)
   (let ((head (org-babel-where-is-src-block-head)))
-     (if head (goto-char head) (error "Not currently in a code block"))))
+    (if head (goto-char head) (error "Not currently in a code block"))))
 
 ;;;###autoload
 (defun org-babel-goto-named-src-block (name)
@@ -2200,6 +2228,10 @@ silent -- no results are inserted into the Org buffer but
           ingested by Emacs (a potentially time consuming
           process).
 
+none ---- no results are inserted into the Org buffer nor
+          echoed to the minibuffer. they are not processed into
+          Emacs-lisp objects at all.
+
 file ---- the results are interpreted as a file path, and are
           inserted into the buffer using the Org file syntax.
 
@@ -2257,9 +2289,8 @@ INFO may provide the values of these header arguments (in 
the
         (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))))))
+                        result
+                        (org-babel--file-desc (nth 2 info) result)))))
        ((listp result))
        (t (setq result (format "%S" result))))
   (if (and result-params (member "silent" result-params))
@@ -2325,7 +2356,7 @@ INFO may provide the values of these header arguments (in 
the
                      (if results-switches (concat " " results-switches) ""))
                (let ((wrap
                       (lambda (start finish &optional no-escape no-newlines
-                                inline-start inline-finish)
+                                     inline-start inline-finish)
                         (when inline
                           (setq start inline-start)
                           (setq finish inline-finish)
@@ -2554,8 +2585,9 @@ in the buffer."
         (let ((element (org-element-at-point)))
           (if (memq (org-element-type element)
                     ;; Possible results types.
-                    '(drawer example-block export-block fixed-width item
-                             plain-list special-block src-block table))
+                     '(drawer example-block export-block fixed-width
+                              special-block src-block item plain-list table
+                              latex-environment))
               (save-excursion
                 (goto-char (min (point-max) ;for narrowed buffers
                                 (org-element-property :end element)))
@@ -2571,9 +2603,9 @@ file's directory then expand relative links."
     (let ((same-directory?
           (and (buffer-file-name (buffer-base-buffer))
                (not (string= (expand-file-name default-directory)
-                           (expand-file-name
-                            (file-name-directory
-                             (buffer-file-name (buffer-base-buffer)))))))))
+                             (expand-file-name
+                              (file-name-directory
+                               (buffer-file-name (buffer-base-buffer)))))))))
       (format "[[file:%s]%s]"
              (if (and default-directory
                       (buffer-file-name (buffer-base-buffer)) same-directory?)
@@ -2707,12 +2739,17 @@ parameters when merging lists."
                                  results-exclusive-groups
                                  results
                                  (split-string
-                                  (if (stringp value) value (eval value t))))))
+                                  (cond ((stringp value) value)
+                                         ((functionp value) (funcall value))
+                                         (t (eval value t)))))))
          (`(:exports . ,value)
           (setq exports (funcall merge
                                  exports-exclusive-groups
                                  exports
-                                 (split-string (or value "")))))
+                                 (split-string
+                                   (cond ((and value (functionp value)) 
(funcall value))
+                                         (value value)
+                                         (t ""))))))
          ;; 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
@@ -2727,14 +2764,14 @@ parameters when merging lists."
                              (cdr (assq param params))))
          (setq params
                (cl-remove-if (lambda (pair) (and (equal (car pair) param)
-                                            (null (cdr pair))))
+                                                 (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))
+    (org-babel-eval-headers params)))
 
 (defun org-babel-noweb-p (params context)
   "Check if PARAMS require expansion in CONTEXT.
@@ -2843,8 +2880,6 @@ block but are passed literally to the \"example-block\"."
                     (setq cache nil)
                     (let ((raw (org-babel-ref-resolve id)))
                       (if (stringp raw) raw (format "%S" raw))))
-                   ;; Retrieve from the Library of Babel.
-                   ((nth 2 (assoc-string id org-babel-library-of-babel)))
                    ;; Return the contents of headlines literally.
                    ((org-babel-ref-goto-headline-id id)
                     (org-babel-ref-headline-body))
@@ -2857,6 +2892,8 @@ block but are passed literally to the \"example-block\"."
                              (not (org-in-commented-heading-p))
                              (funcall expand-body
                                       (org-babel-get-src-block-info t))))))
+                   ;; Retrieve from the Library of Babel.
+                   ((nth 2 (assoc-string id org-babel-library-of-babel)))
                    ;; All Noweb references were cached in a previous
                    ;; run.  Extract the information from the cache.
                    ((hash-table-p cache)
@@ -2977,7 +3014,7 @@ block but are passed literally to the \"example-block\"."
 
 (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
+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
@@ -2995,7 +3032,7 @@ situations in which is it not appropriate."
   "If STRING represents a number return its value.
 Otherwise return nil."
   (unless (or (string-match-p "\\s-" (org-trim string))
-             (not (string-match-p "^[0-9-e.+ ]+$" string)))
+             (not (string-match-p "^[0-9e.+ -]+$" string)))
     (let ((interned-string (ignore-errors (read string))))
       (when (numberp interned-string)
        interned-string))))
@@ -3075,8 +3112,7 @@ Emacs shutdown."))
 
 (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)
-          (debug (form form &rest form)))
+  (declare (indent 1) (debug t))
   (org-with-gensyms (params)
     `(let ((,params ,result-params))
        (unless (member "none" ,params)
@@ -3093,7 +3129,6 @@ Emacs shutdown."))
                      (not (member "table" ,params))))
             ,scalar-form
           ,@table-forms)))))
-(def-edebug-spec org-babel-result-cond (form form body))
 
 (defun org-babel-temp-file (prefix &optional suffix)
   "Create a temporary file in the `org-babel-temporary-directory'.
@@ -3136,7 +3171,7 @@ of `org-babel-temporary-directory'."
                    org-babel-temporary-directory
                  "[directory not defined]"))))))
 
-(add-hook 'kill-emacs-hook 'org-babel-remove-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.
@@ -3151,7 +3186,7 @@ For the format of SAFE-LIST, see 
`org-babel-safe-header-args'."
          (and entry
               (consp entry)
               (cond ((functionp (cdr entry))
-                      (funcall (cdr entry) (cdr pair)))
+                     (funcall (cdr entry) (cdr pair)))
                     ((listp (cdr entry))
                      (member (cdr pair) (cdr entry)))
                     (t nil)))))))
@@ -3171,10 +3206,10 @@ 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)
+        (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))
diff --git a/lisp/ob-dot.el b/lisp/ob-dot.el
index d13261b..8e05a59 100644
--- a/lisp/ob-dot.el
+++ b/lisp/ob-dot.el
@@ -3,6 +3,7 @@
 ;; Copyright (C) 2009-2021 Free Software Foundation, Inc.
 
 ;; Author: Eric Schulte
+;; Maintainer: Justin Abrahms
 ;; Keywords: literate programming, reproducible research
 ;; Homepage: https://orgmode.org
 
@@ -25,7 +26,7 @@
 
 ;; Org-Babel support for evaluating dot source code.
 ;;
-;; For information on dot see http://www.graphviz.org/
+;; For information on dot see https://www.graphviz.org/
 ;;
 ;; This differs from most standard languages in that
 ;;
diff --git a/lisp/ob-ebnf.el b/lisp/ob-ebnf.el
deleted file mode 100644
index 58666a4..0000000
--- a/lisp/ob-ebnf.el
+++ /dev/null
@@ -1,81 +0,0 @@
-;;; ob-ebnf.el --- Babel Functions for EBNF          -*- lexical-binding: t; 
-*-
-
-;; Copyright (C) 2013-2021 Free Software Foundation, Inc.
-
-;; Author: Michael Gauland
-;; Keywords: literate programming, reproducible research
-;; Homepage: https://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 <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; Org-Babel support for using ebnf2ps to generate encapsulated postscript
-;; railroad diagrams. It recognizes 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 customize 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/ob-eshell.el b/lisp/ob-eshell.el
index 6ae0fc6..d74c4fc 100644
--- a/lisp/ob-eshell.el
+++ b/lisp/ob-eshell.el
@@ -3,8 +3,9 @@
 ;; Copyright (C) 2018-2021 Free Software Foundation, Inc.
 
 ;; Author: stardiviner <numbchild@gmail.com>
+;; Maintainer: stardiviner <numbchild@gmail.com>
+;; Homepage: https://github.com/stardiviner/ob-eshell
 ;; Keywords: literate programming, reproducible research
-;; Homepage: https://orgmode.org
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/ob-eval.el b/lisp/ob-eval.el
index b0fca7b..cfd8022 100644
--- a/lisp/ob-eval.el
+++ b/lisp/ob-eval.el
@@ -41,20 +41,22 @@
     (display-buffer buf))
   (message "Babel evaluation exited with code %S" exit-code))
 
-(defun org-babel-eval (cmd body)
-  "Run CMD on BODY.
-If CMD succeeds then return its results, otherwise display
-STDERR with `org-babel-eval-error-notify'."
-  (let ((err-buff (get-buffer-create " *Org-Babel Error*")) exit-code)
-    (with-current-buffer err-buff (erase-buffer))
+(defun org-babel-eval (command query)
+  "Run COMMAND on QUERY.
+Writes QUERY into a temp-buffer that is processed with
+`org-babel--shell-command-on-region'.  If COMMAND succeeds then return
+its results, otherwise display STDERR with
+`org-babel-eval-error-notify'."
+  (let ((error-buffer (get-buffer-create " *Org-Babel Error*")) exit-code)
+    (with-current-buffer error-buffer (erase-buffer))
     (with-temp-buffer
-      (insert body)
+      (insert query)
       (setq exit-code
            (org-babel--shell-command-on-region
-            (point-min) (point-max) cmd err-buff))
+            command error-buffer))
       (if (or (not (numberp exit-code)) (> exit-code 0))
          (progn
-           (with-current-buffer err-buff
+           (with-current-buffer error-buffer
              (org-babel-eval-error-notify exit-code (buffer-string)))
            (save-excursion
              (when (get-buffer org-babel-error-buffer-name)
@@ -71,26 +73,19 @@ STDERR with `org-babel-eval-error-notify'."
   (with-temp-buffer (insert-file-contents file)
                    (buffer-string)))
 
-(defun org-babel--shell-command-on-region (start end command error-buffer)
+(defun org-babel--shell-command-on-region (command error-buffer)
   "Execute COMMAND in an inferior shell with region as input.
+Stripped down version of `shell-command-on-region' for internal use in
+Babel only.  This lets us work around errors in the original function
+in various versions of Emacs.  This expects the query to be run to be
+in the current temp buffer.  This is written into
+input-file.  ERROR-BUFFER is the name of the file which
+`org-babel-eval' has created to use for any error messages that are
+returned."
 
-Stripped down version of shell-command-on-region for internal use
-in Babel only.  This lets us work around errors in the original
-function in various versions of Emacs.
-"
   (let ((input-file (org-babel-temp-file "ob-input-"))
        (error-file (if error-buffer (org-babel-temp-file "ob-error-") nil))
-       ;; Unfortunately, `executable-find' does not support file name
-       ;; handlers.  Therefore, we could use it in the local case
-       ;; only.
-       (shell-file-name
-        (cond ((and (not (file-remote-p default-directory))
-                    (executable-find shell-file-name))
-               shell-file-name)
-              ((file-executable-p
-                (concat (file-remote-p default-directory) shell-file-name))
-               shell-file-name)
-              ("/bin/sh")))
+       (shell-file-name (org-babel--get-shell-file-name))
        exit-status)
     ;; There is an error in `process-file' when `error-file' exists.
     ;; This is fixed in Emacs trunk as of 2012-12-21; let's use this
@@ -99,18 +94,13 @@ function in various versions of Emacs.
       (delete-file error-file))
     ;; we always call this with 'replace, remove conditional
     ;; Replace specified region with output from command.
-    (let ((swap (< start end)))
-      (goto-char start)
-      (push-mark (point) 'nomsg)
-      (write-region start end input-file)
-      (delete-region start end)
-      (setq exit-status
-           (process-file shell-file-name input-file
-                         (if error-file
-                             (list t error-file)
-                           t)
-                         nil shell-command-switch command))
-      (when swap (exchange-point-and-mark)))
+    (org-babel--write-temp-buffer-input-file input-file)
+    (setq exit-status
+         (process-file shell-file-name input-file
+                       (if error-file
+                           (list t error-file)
+                         t)
+                       nil shell-command-switch command))
 
     (when (and input-file (file-exists-p input-file)
               ;; bind org-babel--debug-input around the call to keep
@@ -135,6 +125,16 @@ function in various versions of Emacs.
       (delete-file error-file))
     exit-status))
 
+(defun org-babel--write-temp-buffer-input-file (input-file)
+  "Write the contents of the current temp buffer into INPUT-FILE."
+  (let ((start (point-min))
+        (end (point-max)))
+    (goto-char start)
+    (push-mark (point) 'nomsg)
+    (write-region start end input-file)
+    (delete-region start end)
+    (exchange-point-and-mark)))
+
 (defun org-babel-eval-wipe-error-buffer ()
   "Delete the contents of the Org code block error buffer.
 This buffer is named by `org-babel-error-buffer-name'."
@@ -142,6 +142,19 @@ This buffer is named by `org-babel-error-buffer-name'."
     (with-current-buffer org-babel-error-buffer-name
       (delete-region (point-min) (point-max)))))
 
+(defun org-babel--get-shell-file-name ()
+  "Return system `shell-file-name', defaulting to /bin/sh.
+Unfortunately, `executable-find' does not support file name
+handlers.  Therefore, we could use it in the local case only."
+  ;; FIXME: This is generic enough that it should probably be in emacs, not 
org-mode
+  (cond ((and (not (file-remote-p default-directory))
+             (executable-find shell-file-name))
+        shell-file-name)
+       ((file-executable-p
+         (concat (file-remote-p default-directory) shell-file-name))
+        shell-file-name)
+       ("/bin/sh")))
+
 (provide 'ob-eval)
 
 ;;; ob-eval.el ends here
diff --git a/lisp/ob-exp.el b/lisp/ob-exp.el
index e9b304b..d10d228 100644
--- a/lisp/ob-exp.el
+++ b/lisp/ob-exp.el
@@ -292,11 +292,11 @@ this template."
   "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 (assq :session (nth 2 
info)))))
-                         (unless (equal "none" session)
-                           (org-babel-exp-results info type 'silent)))))
+                              (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)))))
+                             (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))
@@ -396,10 +396,10 @@ inhibit insertion of results into the buffer."
        (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")))))))
+                 (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
diff --git a/lisp/ob-forth.el b/lisp/ob-forth.el
index 3b521bc..74dbc02 100644
--- a/lisp/ob-forth.el
+++ b/lisp/ob-forth.el
@@ -75,8 +75,8 @@ This function is called by `org-babel-execute-src-block'."
                   ((string= "\n:" case)
                    ;; Report errors.
                    (org-babel-eval-error-notify 1
-                    (buffer-substring
-                     (+ (match-beginning 0) 1) (point-max)))
+                                                (buffer-substring
+                                                 (+ (match-beginning 0) 1) 
(point-max)))
                    nil))))
              (split-string (org-trim
                             (org-babel-expand-body:generic body params))
diff --git a/lisp/ob-fortran.el b/lisp/ob-fortran.el
index 99afa0d..2e55498 100644
--- a/lisp/ob-fortran.el
+++ b/lisp/ob-fortran.el
@@ -40,9 +40,11 @@
 
 (defvar org-babel-default-header-args:fortran '())
 
-(defvar org-babel-fortran-compiler "gfortran"
-  "fortran command used to compile a fortran source code file into an
-  executable.")
+(defcustom org-babel-fortran-compiler "gfortran"
+  "Fortran command used to compile Fortran source code file."
+  :group 'org-babel
+  :package-version '(Org . "9.5")
+  :type  'string)
 
 (defun org-babel-execute:fortran (body params)
   "This function should only be called by `org-babel-execute:fortran'."
@@ -155,7 +157,7 @@ of the same value."
       (format "real, parameter :: %S(%d) = %s\n"
              var (length val) (org-babel-fortran-transform-list val)))
      (t
-      (error "the type of parameter %s is not supported by ob-fortran" var)))))
+      (error "The type of parameter %s is not supported by ob-fortran" var)))))
 
 (defun org-babel-fortran-transform-list (val)
   "Return a fortran representation of enclose syntactic lists."
diff --git a/lisp/ob-gnuplot.el b/lisp/ob-gnuplot.el
index 6489c23..3c84e4d 100644
--- a/lisp/ob-gnuplot.el
+++ b/lisp/ob-gnuplot.el
@@ -3,6 +3,7 @@
 ;; Copyright (C) 2009-2021 Free Software Foundation, Inc.
 
 ;; Author: Eric Schulte
+;; Maintainer: Ihor Radchenko <yantar92@gmail.com>
 ;; Keywords: literate programming, reproducible research
 ;; Homepage: https://orgmode.org
 
@@ -33,7 +34,7 @@
 
 ;;; Requirements:
 
-;; - gnuplot :: http://www.gnuplot.info/
+;; - gnuplot :: https://www.gnuplot.info/
 ;;
 ;; - gnuplot-mode :: you can search the web for the latest active one.
 
@@ -47,6 +48,8 @@
 (declare-function gnuplot-send-string-to-gnuplot "ext:gnuplot-mode" (str txt))
 (declare-function gnuplot-send-buffer-to-gnuplot "ext:gnuplot-mode" ())
 
+(defvar org-babel-temporary-directory)
+
 (defvar org-babel-default-header-args:gnuplot
   '((:results . "file") (:exports . "results") (:session . nil))
   "Default arguments to use when evaluating a gnuplot source block.")
@@ -85,14 +88,29 @@ code."
        (cons
        (car pair) ;; variable name
        (let* ((val (cdr pair)) ;; variable value
-              (lp  (listp val)))
+              (lp  (proper-list-p val)))
          (if lp
              (org-babel-gnuplot-table-to-data
               (let* ((first  (car val))
                      (tablep (or (listp first) (symbolp first))))
                 (if tablep val (mapcar 'list val)))
               (org-babel-temp-file "gnuplot-") params)
-         val))))
+           (if (and (stringp val)
+                    (file-remote-p val)  ;; check if val is a remote file
+                    (file-exists-p val)) ;; call to file-exists-p is slow, 
maybe remove it
+               (let* ((local-name (concat ;; create a unique filename to avoid 
multiple downloads
+                                   org-babel-temporary-directory
+                                   "/gnuplot/"
+                                   (file-remote-p val 'host)
+                                   (org-babel-local-file-name val))))
+                 (if (and (file-exists-p local-name) ;; only download file if 
remote is newer
+                          (file-newer-than-file-p local-name val))
+                     local-name
+                   (make-directory (file-name-directory local-name) t)
+                   (copy-file val local-name t)
+                   ))
+             val
+             )))))
      (org-babel--get-vars params))))
 
 (defun org-babel-expand-body:gnuplot (body params)
diff --git a/lisp/ob-groovy.el b/lisp/ob-groovy.el
index fa847dd..b3ff34a 100644
--- a/lisp/ob-groovy.el
+++ b/lisp/ob-groovy.el
@@ -3,6 +3,7 @@
 ;; Copyright (C) 2013-2021 Free Software Foundation, Inc.
 
 ;; Author: Miro Bezjak
+;; Maintainer: Palak Mathur
 ;; Keywords: literate programming, reproducible research
 ;; Homepage: https://orgmode.org
 
@@ -25,7 +26,7 @@
 ;; Currently only supports the external execution.  No session support yet.
 
 ;;; Requirements:
-;; - Groovy language :: http://groovy.codehaus.org
+;; - Groovy language :: https://groovy-lang.org
 ;; - Groovy major mode :: Can be installed from MELPA or
 ;;   https://github.com/russel/Emacs-Groovy-Mode
 
diff --git a/lisp/ob-haskell.el b/lisp/ob-haskell.el
index d7ac1b0..971e1ce 100644
--- a/lisp/ob-haskell.el
+++ b/lisp/ob-haskell.el
@@ -3,6 +3,7 @@
 ;; Copyright (C) 2009-2021 Free Software Foundation, Inc.
 
 ;; Author: Eric Schulte
+;; Maintainer: Lawrence Bottorff <borgauf@gmail.com>
 ;; Keywords: literate programming, reproducible research
 ;; Homepage: https://orgmode.org
 
@@ -33,9 +34,9 @@
 
 ;;; Requirements:
 
-;; - haskell-mode: http://www.iro.umontreal.ca/~monnier/elisp/#haskell-mode
-;; - inf-haskell: http://www.iro.umontreal.ca/~monnier/elisp/#haskell-mode
-;; - (optionally) lhs2tex: http://people.cs.uu.nl/andres/lhs2tex/
+;; - haskell-mode: https://www.iro.umontreal.ca/~monnier/elisp/#haskell-mode
+;; - inf-haskell: https://www.iro.umontreal.ca/~monnier/elisp/#haskell-mode
+;; - (optionally) lhs2tex: https://people.cs.uu.nl/andres/lhs2tex/
 
 ;;; Code:
 (require 'ob)
@@ -69,11 +70,11 @@ a parameter, such as \"ghc -v\"."
   :package-version '(Org "9.4")
   :type 'string)
 
-(defconst org-babel-header-args:haskell '(compile . :any)
+(defconst org-babel-header-args:haskell '((compile . :any))
   "Haskell-specific header arguments.")
 
 (defun org-babel-haskell-execute (body params)
-  "This function should only be called by `org-babel-execute:haskell'"
+  "This function should only be called by `org-babel-execute:haskell'."
   (let* ((tmp-src-file (org-babel-temp-file "Haskell-src-" ".hs"))
          (tmp-bin-file
           (org-babel-process-file-name
diff --git a/lisp/ob-hledger.el b/lisp/ob-hledger.el
deleted file mode 100644
index 3d2f46c..0000000
--- a/lisp/ob-hledger.el
+++ /dev/null
@@ -1,69 +0,0 @@
-;;  ob-hledger.el --- Babel Functions for hledger      -*- lexical-binding: t; 
-*-
-
-;; Copyright (C) 2010-2021 Free Software Foundation, Inc.
-
-;; Author: Simon Michael
-;; Keywords: literate programming, reproducible research, plain text accounting
-;; Homepage: https://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 <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; Babel support for evaluating hledger entries.
-;;
-;; Based on ob-ledger.el.
-;; If the source block is empty, hledger will use a default journal file,
-;; probably ~/.hledger.journal (it may not notice your $LEDGER_FILE env var).
-;; So make ~/.hledger.journal a symbolic link to the real file if necessary.
-
-;; TODO Unit tests are more than welcome, too.
-
-;;; Code:
-(require 'ob)
-
-(defvar org-babel-default-header-args:hledger
-  '((:results . "output") (:exports . "results") (:cmdline . "bal"))
-  "Default arguments to use when evaluating a hledger source block.")
-
-(defun org-babel-execute:hledger (body params)
-  "Execute a block of hledger entries with org-babel.
-This function is called by `org-babel-execute-src-block'."
-  (message "executing hledger source code block")
-  (letrec ( ;(result-params (split-string (or (cdr (assq :results params)) 
"")))
-          (cmdline (cdr (assq :cmdline params)))
-          (in-file (org-babel-temp-file "hledger-"))
-          (out-file (org-babel-temp-file "hledger-output-"))
-          (hledgercmd (concat "hledger"
-                              (if (> (length body) 0)
-                                  (concat " -f " (org-babel-process-file-name 
in-file))
-                                "")
-                              " " cmdline)))
-    (with-temp-file in-file (insert body))
-;; TODO This is calling for some refactoring:
-;;  (concat "hledger" (if ...) " " cmdline)
-;; could be built only once and bound to a symbol.
-    (message "%s" hledgercmd)
-    (with-output-to-string
-      (shell-command (concat hledgercmd " > " (org-babel-process-file-name 
out-file))))
-    (with-temp-buffer (insert-file-contents out-file) (buffer-string))))
-
-(defun org-babel-prep-session:hledger (_session _params)
-  (error "hledger does not support sessions"))
-
-(provide 'ob-hledger)
-
-;;; ob-hledger.el ends here
diff --git a/lisp/ob-io.el b/lisp/ob-io.el
deleted file mode 100644
index 63d2b6c..0000000
--- a/lisp/ob-io.el
+++ /dev/null
@@ -1,105 +0,0 @@
-;;; ob-io.el --- Babel Functions for Io              -*- lexical-binding: t; 
-*-
-
-;; Copyright (C) 2012-2021 Free Software Foundation, Inc.
-
-;; Author: Andrzej Lichnerowicz
-;; Keywords: literate programming, reproducible research
-;; Homepage: https://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 <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-;; Currently only supports the external execution.  No session support yet.
-;; :results output -- runs in scripting mode
-;; :results output repl -- runs in repl mode
-
-;;; Requirements:
-;; - Io language :: http://iolanguage.org/
-;; - Io major mode :: Can be installed from Io sources
-;;  
https://github.com/stevedekorte/io/blob/master/extras/SyntaxHighlighters/Emacs/io-mode.el
-
-;;; Code:
-(require 'ob)
-
-(defvar org-babel-tangle-lang-exts) ;; Autoloaded
-(add-to-list 'org-babel-tangle-lang-exts '("io" . "io"))
-(defvar org-babel-default-header-args:io '())
-(defvar org-babel-io-command "io"
-  "Name of the command to use for executing Io code.")
-
-(defun org-babel-execute:io (body params)
-  "Execute a block of Io code with org-babel.
-This function is 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)))
-         (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-io-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-io-wrapper-method
-  "(
-%s
-) asString print
-")
-
-
-(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
-in BODY as elisp."
-  (when session (error "Sessions are not (yet) supported for Io"))
-  (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-script-escape raw)))))))
-
-(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)
-  "If there is not a current inferior-process-buffer in SESSION
-then create.  Return the initialized session.  Sessions are not
-supported in Io."
-  nil)
-
-(provide 'ob-io)
-
-;;; ob-io.el ends here
diff --git a/lisp/ob-java.el b/lisp/ob-java.el
index b1d517e..60ef33b 100644
--- a/lisp/ob-java.el
+++ b/lisp/ob-java.el
@@ -1,8 +1,10 @@
-;;; ob-java.el --- Babel Functions for Java          -*- lexical-binding: t; 
-*-
+;;; ob-java.el --- org-babel functions for java evaluation -*- 
lexical-binding: t -*-
 
 ;; Copyright (C) 2011-2021 Free Software Foundation, Inc.
 
-;; Author: Eric Schulte
+;; Authors: Eric Schulte
+;;          Dan Davison
+;; Maintainer: Ian Martins <ianxm@jhu.edu>
 ;; Keywords: literate programming, reproducible research
 ;; Homepage: https://orgmode.org
 
@@ -23,8 +25,7 @@
 
 ;;; Commentary:
 
-;; Currently this only supports the external compilation and execution
-;; of java code blocks (i.e., no session support).
+;; Org-Babel support for evaluating java source code.
 
 ;;; Code:
 (require 'ob)
@@ -32,52 +33,455 @@
 (defvar org-babel-tangle-lang-exts)
 (add-to-list 'org-babel-tangle-lang-exts '("java" . "java"))
 
+(defvar org-babel-temporary-directory) ; from ob-core
+
+(defvar org-babel-default-header-args:java '((:results . "output")
+                                            (:dir . "."))
+  "Default header args for java source blocks.
+The docs say functional mode should be the default [1], but
+ob-java didn't originally support functional mode, so we keep
+scripting mode as the default for now to maintain previous
+behavior.
+
+Most languages write tempfiles to babel's temporary directory,
+but ob-java originally had to write them to the current
+directory, so we keep that as the default behavior.
+
+[1] https://orgmode.org/manual/Results-of-Evaluation.html";)
+
+(defconst org-babel-header-args:java '((imports . :any))
+  "Java-specific header arguments.")
+
 (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"
+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"
+  :package-version '(Org . "9.5")
   :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"
+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
+  :package-version '(Org . "9.5")
+  :type 'string)
+
+(defcustom org-babel-java-hline-to "null"
+  "Replace hlines in incoming tables with this when translating to java."
   :group 'org-babel
-  :version "24.3"
+  :package-version '(Org . "9.5")
   :type 'string)
 
+(defcustom org-babel-java-null-to 'hline
+  "Replace `null' in java tables with this before returning."
+  :group 'org-babel
+  :package-version '(Org . "9.5")
+  :type 'symbol)
+
+(defconst org-babel-java--package-re (rx line-start (0+ space) "package"
+                                        (1+ space) (group (1+ (in alnum ?_ 
?.))) ; capture the package name
+                                        (0+ space) ?\; line-end)
+  "Regexp for the package statement.")
+(defconst org-babel-java--imports-re (rx line-start (0+ space) "import"
+                                         (opt (1+ space) "static")
+                                        (1+ space) (group (1+ (in alnum ?_ ?. 
?*))) ; capture the fully qualified class name
+                                        (0+ space) ?\; line-end)
+  "Regexp for import statements.")
+(defconst org-babel-java--class-re (rx line-start (0+ space) (opt (seq 
"public" (1+ space)))
+                                      "class" (1+ space)
+                                      (group (1+ (in alnum ?_))) ; capture the 
class name
+                                      (0+ space) ?{)
+  "Regexp for the class declaration.")
+(defconst org-babel-java--main-re (rx line-start (0+ space) "public"
+                                     (1+ space) "static"
+                                     (1+ space) "void"
+                                     (1+ space) "main"
+                                     (0+ space) ?\(
+                                     (0+ space) "String"
+                                     (0+ space) (1+ (in alnum ?_ ?\[ ?\] 
space)) ; "[] args" or "args[]"
+                                     (0+ space) ?\)
+                                     (0+ space) (opt "throws" (1+ (in alnum ?_ 
?, ?. space)))
+                                     ?{)
+  "Regexp for the main method declaration.")
+(defconst org-babel-java--any-method-re (rx line-start
+                                           (0+ space) (opt (seq (1+ alnum) (1+ 
space)))   ; visibility
+                                           (opt (seq "static" (1+ space)))     
           ; binding
+                                           (1+ (in alnum ?_ ?\[ ?\]))          
           ; return type
+                                            (1+ space) (1+ (in alnum ?_))      
            ; method name
+                                           (0+ space) ?\(
+                                           (0+ space) (0+ (in alnum ?_ ?\[ ?\] 
?, space)) ; params
+                                           (0+ space) ?\)
+                                           (0+ space) (opt "throws" (1+ (in 
alnum ?_ ?, ?. space)))
+                                           ?{)
+  "Regexp for any method.")
+(defconst org-babel-java--result-wrapper "\n    public static String 
__toString(Object val) {
+        if (val instanceof String) {
+            return \"\\\"\" + val + \"\\\"\";
+        } else if (val == null) {
+            return \"null\";
+        } else if (val.getClass().isArray()) {
+            StringBuffer sb = new StringBuffer();
+            Object[] vals = (Object[])val;
+            sb.append(\"[\");
+            for (int ii=0; ii<vals.length; ii++) {
+                sb.append(__toString(vals[ii]));
+                if (ii<vals.length-1)
+                    sb.append(\",\");
+            }
+            sb.append(\"]\");
+            return sb.toString();
+        } else if (val instanceof List) {
+            StringBuffer sb = new StringBuffer();
+            List vals = (List)val;
+            sb.append(\"[\");
+            for (int ii=0; ii<vals.size(); ii++) {
+                sb.append(__toString(vals.get(ii)));
+                if (ii<vals.size()-1)
+                    sb.append(\",\");
+            }
+            sb.append(\"]\");
+            return sb.toString();
+        } else {
+            return String.valueOf(val);
+        }
+    }
+
+    public static void main(String[] args) throws IOException {
+        BufferedWriter output = new BufferedWriter(new FileWriter(\"%s\"));
+        output.write(__toString(_main(args)));
+        output.close();
+    }"
+  "Code to inject into a class so that we can capture the value it returns.
+This implementation was inspired by ob-python, although not as
+elegant.  This modified the source block to write out the value
+it wants to return to a temporary file so that ob-java can read
+it back.  The name of the temporary file to write must be
+replaced in this string.")
+
 (defun org-babel-execute:java (body 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 (assq :cmpflag params)) ""))
-        (cmdline (or (cdr (assq :cmdline params)) ""))
-        (cmdargs (or (cdr (assq :cmdargs 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) "")
+  "Execute a java source block with BODY code and PARAMS params."
+  (let* (;; allow header overrides
+         (org-babel-java-compiler
+          (or (cdr (assq :javac params))
+              org-babel-java-compiler))
+         (org-babel-java-command
+          (or (cdr (assq :java params))
+              org-babel-java-command))
+         ;; if true, run from babel temp directory
+         (run-from-temp (not (cdr (assq :dir params))))
+         ;; class and package
+         (fullclassname (or (cdr (assq :classname params))
+                            (org-babel-java-find-classname body)))
+         ;; just the class name
+         (classname (car (last (split-string fullclassname "\\."))))
+         ;; just the package name
+         (packagename (if (string-match-p "\\." fullclassname)
+                          (file-name-base fullclassname)))
+         ;; the base dir that contains the top level package dir
+         (basedir (file-name-as-directory (if run-from-temp
+                                              (if (file-remote-p 
default-directory)
+                                                  (concat
+                                                   (file-remote-p 
default-directory)
+                                                   
org-babel-remote-temporary-directory)
+                                                org-babel-temporary-directory)
+                                            default-directory)))
+         ;; the dir to write the source file
+         (packagedir (if (and (not run-from-temp) packagename)
+                         (file-name-as-directory
+                          (concat basedir (replace-regexp-in-string "\\\." "/" 
packagename)))
+                       basedir))
+         ;; the filename of the source file
+         (src-file (concat packagedir classname ".java"))
+         ;; compiler flags
+         (cmpflag (or (cdr (assq :cmpflag params)) ""))
+         ;; runtime flags
+         (cmdline (or (cdr (assq :cmdline params)) ""))
+         ;; command line args
+         (cmdargs (or (cdr (assq :cmdargs params)) ""))
+         ;; the command to compile and run
+         (cmd (concat org-babel-java-compiler " " cmpflag " "
+                      (org-babel-process-file-name src-file 'noquote)
+                      " && " org-babel-java-command
+                      " -cp " (org-babel-process-file-name basedir 'noquote)
+                      " " cmdline " " (if run-from-temp classname 
fullclassname)
+                      " " cmdargs))
+         ;; header args for result processing
+         (result-type (cdr (assq :result-type params)))
+         (result-params (cdr (assq :result-params params)))
+         (result-file (and (eq result-type 'value)
+                           (org-babel-temp-file "java-")))
+         ;; the expanded body of the source block
+         (full-body (org-babel-expand-body:java body params)))
+
     ;; 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 " " 
cmdargs) "")))
-      (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)))))))
+    (unless (or (not packagedir) (file-exists-p packagedir))
+      (make-directory packagedir 'parents))
+
+    ;; write the source file
+    (setq full-body (org-babel-java--expand-for-evaluation
+                     full-body run-from-temp result-type result-file))
+    (with-temp-file src-file (insert full-body))
+
+    ;; compile, run, process result
+    (org-babel-reassemble-table
+     (org-babel-java-evaluate cmd result-type result-params result-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))))))
+
+;; helper functions
+
+(defun org-babel-java-find-classname (body)
+  "Try to find fully qualified class name in BODY.
+Look through BODY for the package and class.  If found, put them
+together into a fully qualified class name and return.  Else just
+return class name.  If that isn't found either, default to Main."
+  (let ((package (if (string-match org-babel-java--package-re body)
+                     (match-string 1 body)))
+        (class (if (string-match org-babel-java--class-re body)
+                   (match-string 1 body))))
+    (or (and package class (concat package "." class))
+        (and class class)
+        (and package (concat package ".Main"))
+        "Main")))
+
+(defun org-babel-java--expand-for-evaluation (body suppress-package-p 
result-type result-file)
+  "Expand source block for evaluation.
+In order to return a value we have to add a __toString method.
+In order to prevent classes without main methods from erroring we
+add a dummy main method if one is not provided.  These
+manipulations are done outside of `org-babel--expand-body' so
+that they are hidden from tangles.
+
+BODY is the file content before instrumentation.
+
+SUPPRESS-PACKAGE-P if true, suppress the package statement.
+
+RESULT-TYPE is taken from params.
+
+RESULT-FILE is the temp file to write the result."
+  (with-temp-buffer
+    (insert body)
+
+    ;; suppress package statement
+    (goto-char (point-min))
+    (when (and suppress-package-p
+               (re-search-forward org-babel-java--package-re nil t))
+      (replace-match ""))
+
+    ;; add a dummy main method if needed
+    (goto-char (point-min))
+    (when (not (re-search-forward org-babel-java--main-re nil t))
+      (org-babel-java--move-past org-babel-java--class-re)
+      (insert "\n    public static void main(String[] args) {
+        System.out.print(\"success\");
+    }\n\n"))
+
+    ;; special handling to return value
+    (when (eq result-type 'value)
+      (goto-char (point-min))
+      (org-babel-java--move-past org-babel-java--class-re)
+      (insert (format org-babel-java--result-wrapper
+                      (org-babel-process-file-name result-file 'noquote)))
+      (search-forward "public static void main(") ; rename existing main
+      (replace-match "public static Object _main("))
+
+    ;; add imports
+    (org-babel-java--import-maybe "java.util" "List")
+    (org-babel-java--import-maybe "java.util" "Arrays")
+    (org-babel-java--import-maybe "java.io" "BufferedWriter")
+    (org-babel-java--import-maybe "java.io" "FileWriter")
+    (org-babel-java--import-maybe "java.io" "IOException")
+
+    (buffer-string)))
+
+(defun org-babel-java--move-past (re)
+  "Move point past the first occurrence of the given regexp RE."
+  (while (re-search-forward re nil t)
+    (goto-char (1+ (match-end 0)))))
+
+(defun org-babel-java--import-maybe (package class)
+  "Import from PACKAGE the given CLASS if it is used and not already imported."
+  (let (class-found import-found)
+    (goto-char (point-min))
+    (setq class-found (re-search-forward class nil t))
+    (goto-char (point-min))
+    (setq import-found
+          (re-search-forward (concat "^import .*" package ".*\\(?:\\*\\|" 
class "\\);") nil t))
+    (when (and class-found (not import-found))
+      (org-babel-java--move-past org-babel-java--package-re)
+      (insert (concat "import " package "." class ";\n")))))
+
+(defun org-babel-expand-body:java (body params)
+  "Expand BODY with PARAMS.
+BODY could be a few statements, or could include a full class
+definition specifying package, imports, and class.  Because we
+allow this flexibility in what the source block can contain, it
+is simplest to expand the code block from the inside out."
+  (let* ((fullclassname (or (cdr (assq :classname params)) ; class and package
+                            (org-babel-java-find-classname body)))
+         (classname (car (last (split-string fullclassname "\\.")))) ; just 
class name
+         (packagename (if (string-match-p "\\." fullclassname)       ; just 
package name
+                          (file-name-base fullclassname)))
+         (var-lines (org-babel-variable-assignments:java params))
+         (imports-val (assq :imports params))
+         (imports (if imports-val
+                      (split-string (org-babel-read (cdr imports-val) nil) " ")
+                    nil)))
+    (with-temp-buffer
+      (insert body)
+
+      ;; wrap main.  If there are methods defined, but no main method
+      ;; and no class, wrap everything in a generic main method.
+      (goto-char (point-min))
+      (when (and (not (re-search-forward org-babel-java--main-re nil t))
+                 (not (re-search-forward org-babel-java--any-method-re nil t)))
+        (org-babel-java--move-past org-babel-java--package-re) ; if package is 
defined, move past it
+        (org-babel-java--move-past org-babel-java--imports-re) ; if imports 
are defined, move past them
+        (insert "public static void main(String[] args) {\n")
+        (indent-code-rigidly (point) (point-max) 4)
+        (goto-char (point-max))
+        (insert "\n}"))
+
+      ;; wrap class.  If there's no class, wrap everything in a
+      ;; generic class.
+      (goto-char (point-min))
+      (when (not (re-search-forward org-babel-java--class-re nil t))
+        (org-babel-java--move-past org-babel-java--package-re) ; if package is 
defined, move past it
+        (org-babel-java--move-past org-babel-java--imports-re) ; if imports 
are defined, move past them
+        (insert (concat "\npublic class " (file-name-base classname) " {\n"))
+        (indent-code-rigidly (point) (point-max) 4)
+        (goto-char (point-max))
+        (insert "\n}"))
+      (goto-char (point-min))
+
+      ;; insert variables from source block headers
+      (when var-lines
+        (goto-char (point-min))
+        (org-babel-java--move-past org-babel-java--class-re)   ; move inside 
class
+        (insert (mapconcat 'identity var-lines "\n"))
+        (insert "\n"))
+
+      ;; add imports from source block headers
+      (when imports
+        (goto-char (point-min))
+        (org-babel-java--move-past org-babel-java--package-re) ; if package is 
defined, move past it
+        (insert (mapconcat (lambda (package) (concat "import " package ";")) 
imports "\n") "\n"))
+
+      ;; add package at the top
+      (goto-char (point-min))
+      (when (and packagename (not (re-search-forward 
org-babel-java--package-re nil t)))
+        (insert (concat "package " packagename ";\n")))
+
+      ;; return expanded body
+      (buffer-string))))
+
+(defun org-babel-variable-assignments:java (params)
+  "Return a list of java statements assigning the block's variables.
+variables are contained in PARAMS."
+  (mapcar
+   (lambda (pair)
+     (let* ((type-data (org-babel-java-val-to-type (cdr pair)))
+            (basetype (car type-data))
+            (var-to-java (lambda (var) (funcall #'org-babel-java-var-to-java 
var basetype))))
+       (format "    static %s %s = %s;"
+               (cdr type-data)                     ; type
+               (car pair)                          ; name
+               (funcall var-to-java (cdr pair))))) ; value
+   (org-babel--get-vars params)))
+
+(defun org-babel-java-var-to-java (var basetype)
+  "Convert an elisp value to a java variable.
+Convert an elisp value, VAR, of type BASETYPE into a string of
+java source code specifying a variable of the same value."
+  (cond ((and (sequencep var) (not (stringp var)))
+         (let ((var-to-java (lambda (var) (funcall 
#'org-babel-java-var-to-java var basetype))))
+           (concat "Arrays.asList(" (mapconcat var-to-java var ", ") ")")))
+        ((eq var 'hline) org-babel-java-hline-to)
+        ((eq basetype 'integerp) (format "%d" var))
+        ((eq basetype 'floatp) (format "%f" var))
+        ((eq basetype 'stringp) (if (and (stringp var) (string-match-p ".\n+." 
var))
+                                    (error "Java does not support multiline 
string literals")
+                                  (format "\"%s\"" var)))))
+
+(defun org-babel-java-val-to-type (val)
+  "Determine the type of VAL.
+Return (BASETYPE . LISTTYPE), where BASETYPE is a symbol
+representing the type of the individual items in VAL, and
+LISTTYPE is a string name of the type parameter for a container
+for BASETYPE items."
+  (let* ((basetype (org-babel-java-val-to-base-type val))
+         (basetype-str (pcase basetype
+                         (`integerp "Integer")
+                         (`floatp "Double")
+                         (`stringp "String")
+                         (_ (error "Unknown type %S" basetype)))))
+    (cond
+     ((and (listp val) (listp (car val))) ; a table
+      (cons basetype (format "List<List<%s>>" basetype-str)))
+     ((or (listp val) (vectorp val))      ; a list declared in the source 
block header
+      (cons basetype (format "List<%s>" basetype-str)))
+     (t                                   ; return base type
+      (cons basetype basetype-str)))))
+
+(defun org-babel-java-val-to-base-type (val)
+  "Determine the base type of VAL.
+VAL 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) 'integerp)
+   ((floatp val) 'floatp)
+   ((or (listp val) (vectorp val))
+    (let ((type nil))
+      (mapc (lambda (v)
+              (pcase (org-babel-java-val-to-base-type v)
+                (`stringp (setq type 'stringp))
+                (`floatp
+                 (when (or (not type) (eq type 'integerp))
+                   (setq type 'floatp)))
+                (`integerp
+                 (unless type (setq type 'integerp)))))
+            val)
+      type))
+   (t 'stringp)))
+
+(defun org-babel-java-table-or-string (results)
+  "Convert RESULTS into an appropriate elisp value.
+If the results look like a list or vector, 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 'null el)
+                                 org-babel-java-null-to
+                               el))
+                res)
+      res)))
+
+(defun org-babel-java-evaluate (cmd result-type result-params result-file)
+  "Evaluate using an external java process.
+CMD the command to execute.
+
+If RESULT-TYPE equals `output' then return standard output as a
+string.  If RESULT-TYPE equals `value' then return the value
+returned by the source block, as elisp.
+
+RESULT-PARAMS input params used to format the response.
+
+RESULT-FILE filename of the tempfile to store the returned value in
+for `value' RESULT-TYPE.  Not used for `output' RESULT-TYPE."
+  (let ((raw (pcase result-type
+               (`output (org-babel-eval cmd ""))
+               (`value (org-babel-eval cmd "")
+                       (org-babel-eval-read-file result-file)))))
+    (org-babel-result-cond result-params raw
+                           (org-babel-java-table-or-string raw))))
 
 (provide 'ob-java)
 
diff --git a/lisp/ob-js.el b/lisp/ob-js.el
index b2a971e..5d1be61 100644
--- a/lisp/ob-js.el
+++ b/lisp/ob-js.el
@@ -158,8 +158,8 @@ specifying a variable of the same value."
    (org-babel--get-vars params)))
 
 (defun org-babel-js-initiate-session (&optional session _params)
-  "If there is not a current inferior-process-buffer in `SESSION'
-then create.  Return the initialized session."
+  "If there is not a current inferior-process-buffer in `SESSION' then create.
+Return the initialized session."
   (cond
    ((string= session "none")
     (warn "Session evaluation of ob-js is not supported"))
diff --git a/contrib/lisp/ob-julia.el b/lisp/ob-julia.el
similarity index 60%
rename from contrib/lisp/ob-julia.el
rename to lisp/ob-julia.el
index 41c8b5a..2f051a5 100644
--- a/contrib/lisp/ob-julia.el
+++ b/lisp/ob-julia.el
@@ -1,45 +1,43 @@
 ;;; ob-julia.el --- org-babel functions for julia code evaluation
 
-;; Copyright (C) 2013, 2014 G. Jay Kerns
-;; Author: G. Jay Kerns, based on ob-R.el by Eric Schulte and Dan Davison
+;; Copyright (C) 2013-2021 Free Software Foundation, Inc.
+;; Authors: G. Jay Kerns, based on ob-R.el by Eric Schulte and Dan Davison
+;; Maintainer: Pedro Bruel <pedro.bruel@gmail.com>
+;; Keywords: literate programming, reproducible research, scientific computing
+;; Homepage: https://github.com/phrb/ob-julia
 
 ;; This file is not 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, or (at your option)
-;; any later version.
-;;
+;; 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; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 
-;; The file provides Org-Babel support for evaluating julia code.
-;;
-;; See https://github.com/gjkerns/ob-julia/blob/master/ob-julia-doc.org
-;; for detailed instructions on how to get started.  The git repository
-;; contains more documentation: git://github.com/gjkerns/ob-julia.git
+;; Org-Babel support for evaluating julia code
 
 ;;; Code:
-(require 'ob)
 (require 'cl-lib)
+(require 'ob)
 
 (declare-function orgtbl-to-csv "org-table" (table params))
 (declare-function julia "ext:ess-julia" (&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 ess-wait-for-process "ext:ess-inf"
+                 (&optional proc sec-prompt wait force-redisplay))
 
-(defconst org-babel-header-args:julia
+(defvar org-babel-header-args:julia
   '((width              . :any)
     (horizontal                 . :any)
     (results             . ((file list vector table scalar verbatim)
@@ -52,31 +50,33 @@
 
 (defvar org-babel-default-header-args:julia '())
 
-(defcustom org-babel-julia-command inferior-julia-program-name
+(defcustom org-babel-julia-command "julia"
   "Name of command to use for executing julia code."
-  :group 'org-babel
-  :version "24.4"
+  :version "24.3"
   :package-version '(Org . "8.0")
+  :group 'org-babel
   :type 'string)
 
+(defvar ess-current-process-name) ; dynamically scoped
 (defvar ess-local-process-name) ; dynamically scoped
 (defun org-babel-edit-prep:julia (info)
   (let ((session (cdr (assq :session (nth 2 info)))))
-    (when (and session (string-match "^\\*\\(.+?\\)\\*$" session))
-      (save-match-data (org-babel-julia-initiate-session session nil)))))
+    (when (and session
+              (string-prefix-p "*"  session)
+              (string-suffix-p "*" session))
+      (org-babel-julia-initiate-session session nil))))
 
-(defun org-babel-expand-body:julia (body params &optional graphics-file)
+(defun org-babel-expand-body:julia (body params &optional _graphics-file)
   "Expand BODY according to PARAMS, return the expanded body."
-  (let ((graphics-file
-        (or graphics-file (org-babel-julia-graphical-output-file params))))
-    (mapconcat
-     #'identity
-     ((lambda (inside)
-       (if graphics-file
-            inside
-         inside))
-      (append (org-babel-variable-assignments:julia params)
-             (list body))) "\n")))
+  (mapconcat 'identity
+            (append
+             (when (cdr (assq :prologue params))
+               (list (cdr (assq :prologue params))))
+             (org-babel-variable-assignments:julia params)
+             (list body)
+             (when (cdr (assq :epilogue params))
+               (list (cdr (assq :epilogue params)))))
+            "\n"))
 
 (defun org-babel-execute:julia (body params)
   "Execute a block of julia code.
@@ -86,9 +86,10 @@ This function is called by `org-babel-execute-src-block'."
           (result-type (cdr (assq :result-type params)))
            (session (org-babel-julia-initiate-session
                     (cdr (assq :session params)) params))
-          (colnames-p (cdr (assq :colnames params)))
-          (rownames-p (cdr (assq :rownames params)))
-          (graphics-file (org-babel-julia-graphical-output-file params))
+          (graphics-file (and (member "graphics" (assq :result-params params))
+                              (org-babel-graphical-output-file params)))
+          (colnames-p (unless graphics-file (cdr (assq :colnames params))))
+          (rownames-p (unless graphics-file (cdr (assq :rownames params))))
           (full-body (org-babel-expand-body:julia body params graphics-file))
           (result
            (org-babel-julia-evaluate
@@ -101,6 +102,12 @@ This function is called by `org-babel-execute-src-block'."
                  (cdr (assq :rowname-names params)) rownames-p)))))
       (if graphics-file nil result))))
 
+(defun org-babel-normalize-newline (result)
+  (replace-regexp-in-string
+   "\\(\n\r?\\)\\{2,\\}"
+   "\n"
+   result))
+
 (defun org-babel-prep-session:julia (session params)
   "Prepare SESSION according to the header arguments specified in PARAMS."
   (let* ((session (org-babel-julia-initiate-session session params))
@@ -138,7 +145,7 @@ This function is called by `org-babel-execute-src-block'."
               (cdr (nth i vars))
               (cdr (nth i (cdr (assq :colname-names params))))
               (cdr (nth i (cdr (assq :rowname-names params)))))))
-      (org-number-sequence 0 (1- (length vars)))))))
+      (number-sequence 0 (1- (length vars)))))))
 
 (defun org-babel-julia-quote-csv-field (s)
   "Quote field S for export to julia."
@@ -149,40 +156,43 @@ This function is called by `org-babel-execute-src-block'."
 (defun org-babel-julia-assign-elisp (name value colnames-p rownames-p)
   "Construct julia code assigning the elisp VALUE to a variable named NAME."
   (if (listp value)
-      (let ((max (apply #'max (mapcar #'length (cl-remove-if-not
-                                               #'sequencep value))))
-           (min (apply #'min (mapcar #'length (cl-remove-if-not
-                                               #'sequencep value))))
-           (transition-file (org-babel-temp-file "julia-import-")))
-        ;; ensure VALUE has an orgtbl structure (depth of at least 2)
+      (let* ((lengths (mapcar 'length (cl-remove-if-not 'sequencep value)))
+             (max (if lengths (apply 'max lengths) 0))
+             (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-csv value '(:fmt org-babel-julia-quote-csv-field))
-          "\n"))
-       (let ((file (org-babel-process-file-name transition-file 'noquote))
-             (header (if (or (eq (nth 1 value) 'hline) colnames-p)
-                         "TRUE" "FALSE"))
-             (row-names (if rownames-p "1" "NULL")))
-         (if (= max min)
-             (format "%s = readcsv(\"%s\")" name file)
-           (format "%s = readcsv(\"%s\")"
-                   name file))))
+        (let ((file (orgtbl-to-csv value '(:fmt 
org-babel-julia-quote-csv-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 = begin
+    using CSV
+    CSV.read(\"%s\")
+end" name file)
+            (format "%s = begin
+    using CSV
+    CSV.read(\"%s\")
+end"
+                    name file))))
     (format "%s = %s" name (org-babel-julia-quote-csv-field value))))
 
 (defvar ess-ask-for-ess-directory) ; dynamically scoped
-
 (defun org-babel-julia-initiate-session (session params)
   "If there is not a current julia process then create one."
   (unless (string= session "none")
-    (let ((session (or session "*julia*"))
+    (let ((session (or session "*Julia*"))
          (ess-ask-for-ess-directory
-          (and (and (boundp 'ess-ask-for-ess-directory) 
ess-ask-for-ess-directory)
+          (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
-         (require 'ess) (julia)
+         (when (get-buffer session)
+           ;; Session buffer exists, but with dead process
+           (set-buffer session))
+          (require 'ess) (set-buffer (julia))
          (rename-buffer
           (if (bufferp session)
               (buffer-name session)
@@ -191,30 +201,57 @@ This function is called by `org-babel-execute-src-block'."
               (buffer-name))))
          (current-buffer))))))
 
-(defun org-babel-julia-associate-session (session)
-  "Associate julia code buffer with a julia session.
-Make SESSION be the inferior ESS process associated with the
-current code buffer."
-  (setq ess-local-process-name
-       (process-name (get-buffer-process session)))
-  (ess-make-buffer-current))
+                                        ; (defun 
org-babel-julia-associate-session (session)
+                                        ;   "Associate julia code buffer with 
a julia session.
+                                        ; Make SESSION be the inferior ESS 
process associated with the
+                                        ; current code buffer."
+                                        ;   (setq ess-local-process-name
+                                        ;      (process-name 
(get-buffer-process session)))
+                                        ;   (ess-make-buffer-current))
 
 (defun org-babel-julia-graphical-output-file (params)
   "Name of file to which julia should send graphical output."
   (and (member "graphics" (cdr (assq :result-params params)))
        (cdr (assq :file params))))
 
-(defvar org-babel-julia-eoe-indicator "print(\"org_babel_julia_eoe\")")
-(defvar org-babel-julia-eoe-output "org_babel_julia_eoe")
-
-(defvar org-babel-julia-write-object-command "writecsv(\"%s\",%s)")
-
-;; The following was a very complicated write object command
-;; The replacement needs to add error catching
-;(defvar org-babel-julia-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-julia-eoe-indicator "print(\"org_babel_julia_eoe\")")
+(defconst org-babel-julia-eoe-output "org_babel_julia_eoe")
+
+(defconst org-babel-julia-write-object-command "begin
+    local p_ans = %s
+    local p_tmp_file = \"%s\"
+
+    try
+        using CSV, DataFrames
+
+        if typeof(p_ans) <: DataFrame
+           p_ans_df = p_ans
+        else
+            p_ans_df = DataFrame(:ans => p_ans)
+        end
+
+        CSV.write(p_tmp_file,
+                  p_ans_df,
+                  writeheader = %s,
+                  transform = (col, val) -> something(val, missing),
+                  missingstring = \"nil\",
+                  quotestrings = false)
+        p_ans
+    catch e
+        err_msg = \"Source block evaluation failed. $e\"
+        CSV.write(p_tmp_file,
+                  DataFrame(:ans => err_msg),
+                  writeheader = false,
+                  transform = (col, val) -> something(val, missing),
+                  missingstring = \"nil\",
+                  quotestrings = false)
+
+        err_msg
+    end
+end")
 
 (defun org-babel-julia-evaluate
-  (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 julia code in BODY."
   (if session
       (org-babel-julia-evaluate-session
@@ -223,7 +260,7 @@ current code buffer."
      body result-type result-params column-names-p row-names-p)))
 
 (defun org-babel-julia-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 julia process.
 If RESULT-TYPE equals 'output then return standard output as a
 string.  If RESULT-TYPE equals 'value then return the value of the
@@ -233,8 +270,10 @@ last statement in BODY, as elisp."
      (let ((tmp-file (org-babel-temp-file "julia-")))
        (org-babel-eval org-babel-julia-command
                       (format org-babel-julia-write-object-command
+                              (format "begin %s end" body)
                               (org-babel-process-file-name tmp-file 'noquote)
-                              (format "begin\n%s\nend" body)))
+                               (if column-names-p "true" "false")
+                               ))
        (org-babel-julia-process-value-result
        (org-babel-result-cond result-params
          (with-temp-buffer
@@ -245,7 +284,7 @@ last statement in BODY, as elisp."
     (output (org-babel-eval org-babel-julia-command body))))
 
 (defun org-babel-julia-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
@@ -262,7 +301,10 @@ last statement in BODY, as elisp."
        (org-babel-comint-eval-invisibly-and-wait-for-file
        session tmp-file
        (format org-babel-julia-write-object-command
-               (org-babel-process-file-name tmp-file 'noquote) "ans"))
+                "ans"
+               (org-babel-process-file-name tmp-file 'noquote)
+                (if column-names-p "true" "false")
+                ))
        (org-babel-julia-process-value-result
        (org-babel-result-cond result-params
          (with-temp-buffer
@@ -272,7 +314,7 @@ last statement in BODY, as elisp."
        column-names-p)))
     (output
      (mapconcat
-      #'org-babel-chomp
+      'org-babel-chomp
       (butlast
        (delq nil
             (mapcar
@@ -280,14 +322,15 @@ 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-julia-eoe-output)
-                (insert (mapconcat #'org-babel-chomp
+                (insert (mapconcat 'org-babel-chomp
                                    (list body org-babel-julia-eoe-indicator)
                                    "\n"))
-                (inferior-ess-send-input)))))) "\n"))))
+                 (inferior-ess-send-input)))))) "\n"))))
 
 (defun org-babel-julia-process-value-result (result column-names-p)
   "julia-specific processing of return value.
diff --git a/lisp/ob-latex.el b/lisp/ob-latex.el
index 138f474..7c65256 100644
--- a/lisp/ob-latex.el
+++ b/lisp/ob-latex.el
@@ -66,7 +66,46 @@
   "LaTeX-specific header arguments.")
 
 (defcustom org-babel-latex-htlatex "htlatex"
-  "The htlatex command to enable conversion of latex to SVG or HTML."
+  "The htlatex command to enable conversion of LaTeX to SVG or HTML."
+  :group 'org-babel
+  :type 'string)
+
+(defcustom org-babel-latex-preamble
+  (lambda (_)
+    "\\documentclass[preview]{standalone}
+\\def\\pgfsysdriver{pgfsys-tex4ht.def}
+")
+  "Closure which evaluates at runtime to the LaTeX preamble.
+
+It takes 1 argument which is the parameters of the source block."
+  :group 'org-babel
+  :type 'function)
+
+(defcustom org-babel-latex-begin-env
+  (lambda (_)
+    "\\begin{document}")
+  "Function that evaluates to the begin part of the document environment.
+
+It takes 1 argument which is the parameters of the source block.
+This allows adding additional code that will be ignored when
+exporting the literal LaTeX source."
+  :group 'org-babel
+  :type 'function)
+
+(defcustom org-babel-latex-end-env
+  (lambda (_)
+    "\\end{document}")
+  "Closure which evaluates at runtime to the end part of the document 
environment.
+
+It takes 1 argument which is the parameters of the source block.
+This allows adding additional code that will be ignored when
+exporting the literal LaTeX source."
+  :group 'org-babel
+  :type 'function)
+
+(defcustom org-babel-latex-pdf-svg-process
+  "inkscape --pdf-poppler %f -T -l -o %O"
+  "Command to convert a PDF file to an SVG file."
   :group 'org-babel
   :type 'string)
 
@@ -112,14 +151,28 @@ This function is called by `org-babel-execute-src-block'."
           (let ((org-format-latex-header
                 (concat org-format-latex-header "\n"
                         (mapconcat #'identity headers "\n"))))
-          (org-create-formula-image
-            body out-file org-format-latex-options in-buffer)))
+           (org-create-formula-image
+             body out-file org-format-latex-options in-buffer)))
+        ((string= "svg" extension)
+         (with-temp-file tex-file
+           (insert (concat (funcall org-babel-latex-preamble params)
+                           (mapconcat #'identity headers "\n")
+                           (funcall org-babel-latex-begin-env params)
+                           body
+                           (funcall org-babel-latex-end-env params))))
+         (let ((tmp-pdf (org-babel-latex-tex-to-pdf tex-file)))
+            (let* ((log-buf (get-buffer-create "*Org Babel LaTeX Output*"))
+                   (err-msg "org babel latex failed")
+                   (img-out (org-compile-file
+                            tmp-pdf
+                             (list org-babel-latex-pdf-svg-process)
+                             extension err-msg log-buf)))
+              (shell-command (format "mv %s %s" img-out 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)))
-        ((and (or (string= "svg" extension)
-                  (string= "html" extension))
+        ((and (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
diff --git a/lisp/ob-ledger.el b/lisp/ob-ledger.el
deleted file mode 100644
index a117f85..0000000
--- a/lisp/ob-ledger.el
+++ /dev/null
@@ -1,68 +0,0 @@
-;;; ob-ledger.el --- Babel Functions for Ledger      -*- lexical-binding: t; 
-*-
-
-;; Copyright (C) 2010-2021 Free Software Foundation, Inc.
-
-;; Author: Eric S Fraga
-;; Keywords: literate programming, reproducible research, accounting
-;; Homepage: https://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 <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; Org-Babel support for evaluating ledger entries.
-;;
-;; This differs from most standard languages in that
-;;
-;; 1) there is no such thing as a "session" in ledger
-;;
-;; 2) we are generally only going to return output from the ledger program
-;;
-;; 3) we are adding the "cmdline" header argument
-;;
-;; 4) there are no variables
-
-;;; Code:
-(require 'ob)
-
-(defvar org-babel-default-header-args:ledger
-  '((:results . "output") (:cmdline . "bal"))
-  "Default arguments to use when evaluating a ledger source block.")
-
-(defun org-babel-execute:ledger (body params)
-  "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 ((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))
-    (message "%s" (concat "ledger"
-                         " -f " (org-babel-process-file-name in-file)
-                         " " cmdline))
-    (with-output-to-string
-      (shell-command (concat "ledger"
-                            " -f " (org-babel-process-file-name in-file)
-                            " " cmdline
-                            " > " (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)
-  (error "Ledger does not support sessions"))
-
-(provide 'ob-ledger)
-
-;;; ob-ledger.el ends here
diff --git a/lisp/ob-lilypond.el b/lisp/ob-lilypond.el
index e0557eb..410d53b 100644
--- a/lisp/ob-lilypond.el
+++ b/lisp/ob-lilypond.el
@@ -27,9 +27,9 @@
 ;; https://orgmode.org/worg/org-contrib/babel/languages/ob-doc-lilypond.html
 ;;
 ;; Lilypond documentation can be found at
-;; http://lilypond.org/manuals.html
+;; https://lilypond.org/manuals.html
 ;;
-;; This depends on epstopdf --- See http://www.ctan.org/pkg/epstopdf.
+;; This depends on epstopdf --- See https://www.ctan.org/pkg/epstopdf.
 
 ;;; Code:
 (require 'ob)
@@ -43,6 +43,15 @@
 (defvar org-babel-default-header-args:lilypond '()
   "Default header arguments for lilypond code blocks.
 NOTE: The arguments are determined at lilypond compile time.
+See `org-babel-lilypond-set-header-args'
+To configure, see `ob-lilypond-header-args'
+.")
+
+(defvar ob-lilypond-header-args
+  '((:results . "file") (:exports . "results"))
+  "User-configurable header arguments for lilypond code blocks.
+NOTE: The final value used by org-babel is computed at compile-time
+and stored in  `org-babel-default-header-args:lilypond'
 See `org-babel-lilypond-set-header-args'.")
 
 (defvar org-babel-lilypond-compile-post-tangle t
@@ -196,9 +205,9 @@ specific arguments to =org-babel-tangle=."
 If error in compilation, attempt to mark the error in lilypond org file."
   (when org-babel-lilypond-compile-post-tangle
     (let ((org-babel-lilypond-tangled-file (org-babel-lilypond-switch-extension
-                            (buffer-file-name) ".lilypond"))
+                                            (buffer-file-name) ".lilypond"))
           (org-babel-lilypond-temp-file (org-babel-lilypond-switch-extension
-                         (buffer-file-name) ".ly")))
+                                         (buffer-file-name) ".ly")))
       (if (not (file-exists-p org-babel-lilypond-tangled-file))
          (error "Error: Tangle Failed!")
        (when (file-exists-p org-babel-lilypond-temp-file)
@@ -220,7 +229,7 @@ If error in compilation, attempt to mark the error in 
lilypond org file."
 FILE-NAME is full path to lilypond (.ly) file."
   (message "Compiling LilyPond...")
   (let ((arg-1 org-babel-lilypond-ly-command) ;program
-        (arg-2 nil)                    ;infile
+        ;; (arg-2 nil)                    ;infile
         (arg-3 "*lilypond*")           ;buffer
        (arg-4 t)                      ;display
        (arg-5 (if org-babel-lilypond-gen-png  "--png"  "")) ;&rest...
@@ -231,10 +240,10 @@ FILE-NAME is full path to lilypond (.ly) file."
         (arg-10 (concat "--output=" (file-name-sans-extension file-name)))
         (arg-11 file-name))
     (if test
-        `(,arg-1 ,arg-2 ,arg-3 ,arg-4 ,arg-5 ,arg-6
+        `(,arg-1 ,nil ,arg-3 ,arg-4 ,arg-5 ,arg-6 ;; arg-2
                  ,arg-7 ,arg-8 ,arg-9 ,arg-10 ,arg-11)
       (call-process
-       arg-1 arg-2 arg-3 arg-4 arg-5 arg-6
+       arg-1 nil arg-3 arg-4 arg-5 arg-6 ;; arg-2
        arg-7 arg-8 arg-9 arg-10 arg-11))))
 
 (defun org-babel-lilypond-check-for-compile-error (file-name &optional test)
@@ -394,7 +403,7 @@ If TEST is non-nil, the shell command is returned and is 
not run."
   "Utility command to swap current FILE-NAME extension with EXT."
   (concat (file-name-sans-extension
            file-name)
-        ext))
+         ext))
 
 (defun org-babel-lilypond-get-header-args (mode)
   "Default arguments to use when evaluating a lilypond source block.
@@ -406,8 +415,7 @@ These depend upon whether we are in Arrange mode i.e. MODE 
is t."
            (:cache . "yes")
            (:comments . "yes")))
         (t
-         '((:results . "file")
-           (:exports . "results")))))
+         ob-lilypond-header-args)))
 
 (defun org-babel-lilypond-set-header-args (mode)
   "Set org-babel-default-header-args:lilypond
diff --git a/lisp/ob-lisp.el b/lisp/ob-lisp.el
index 87b9241..b32b122 100644
--- a/lisp/ob-lisp.el
+++ b/lisp/ob-lisp.el
@@ -33,7 +33,7 @@
 ;; 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/
+;; - https://common-lisp.net/project/slime/
 
 ;;; Code:
 (require 'ob)
diff --git a/lisp/ob-lua.el b/lisp/ob-lua.el
index 11503e4..a4a964a 100644
--- a/lisp/ob-lua.el
+++ b/lisp/ob-lua.el
@@ -21,6 +21,10 @@
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
 
+;;; Commentary:
+
+;; Org-Babel support for evaluating lua source code.
+
 ;; Requirements:
 ;; for session support, lua-mode is needed.
 ;; lua-mode is not part of GNU Emacs/orgmode, but can be obtained
@@ -30,8 +34,6 @@
 
 ;; However, sessions are not yet working.
 
-;; Org-Babel support for evaluating lua source code.
-
 ;;; Code:
 (require 'ob)
 (require 'org-macs)
diff --git a/lisp/ob-makefile.el b/lisp/ob-makefile.el
index 69ab6fe..eae64cf 100644
--- a/lisp/ob-makefile.el
+++ b/lisp/ob-makefile.el
@@ -37,8 +37,7 @@ This function is called by `org-babel-execute-src-block'."
   body)
 
 (defun org-babel-prep-session:makefile (_session _params)
-  "Return an error if the :session header argument is set.  Make
-does not support sessions."
+  "Signal error; Make does not support sessions."
   (error "Makefile sessions are nonsensical"))
 
 (provide 'ob-makefile)
diff --git a/lisp/ob-mscgen.el b/lisp/ob-mscgen.el
deleted file mode 100644
index 999d4f4..0000000
--- a/lisp/ob-mscgen.el
+++ /dev/null
@@ -1,81 +0,0 @@
-;;; ob-msc.el --- Babel Functions for Mscgen         -*- lexical-binding: t; 
-*-
-
-;; Copyright (C) 2010-2021 Free Software Foundation, Inc.
-
-;; Author: Juan Pechiar
-;; Keywords: literate programming, reproducible research
-;; Homepage: https://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 <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-;;
-;; This software provides EMACS org-babel export support for message
-;; sequence charts.  The mscgen utility is used for processing the
-;; sequence definition, and must therefore be installed in the system.
-;;
-;; Mscgen is available and documented at
-;; http://www.mcternan.me.uk/mscgen/index.html
-;;
-;; This code is directly inspired by Eric Schulte's ob-dot.el
-;;
-;; Example:
-;;
-;; #+begin_src mscgen :file example.png
-;; msc {
-;;  A,B;
-;;  A -> B [ label = "send message" ];
-;;  A <- B [ label = "get answer" ];
-;; }
-;; #+end_src
-;;
-;; Header for alternative file type:
-;;
-;; #+begin_src mscgen :file ex2.svg :filetype svg
-
-;; This differs from most standard languages in that
-;;
-;; 1) there is no such thing as a "session" in mscgen
-;; 2) we are generally only going to return results of type "file"
-;; 3) we are adding the "file" and "filetype" header arguments
-;; 4) there are no variables
-
-;;; Code:
-(require 'ob)
-
-(defvar org-babel-default-header-args:mscgen
-  '((:results . "file") (:exports . "results"))
-  "Default arguments to use when evaluating a mscgen source block.")
-
-(defun org-babel-execute:mscgen (body params)
-  "Execute a block of Mscgen code with Babel.
-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 (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)
-  "Raise an error because Mscgen doesn't support sessions."
-  (error "Mscgen does not support sessions"))
-
-(provide 'ob-mscgen)
-
-;;; ob-msc.el ends here
diff --git a/lisp/ob-ocaml.el b/lisp/ob-ocaml.el
index ea0ceb8..faf117c 100644
--- a/lisp/ob-ocaml.el
+++ b/lisp/ob-ocaml.el
@@ -112,8 +112,8 @@
                                             session
                                           tuareg-interactive-buffer-name)))
     (save-window-excursion (if (fboundp 'tuareg-run-process-if-needed)
-        (tuareg-run-process-if-needed org-babel-ocaml-command)
-       (tuareg-run-caml)))
+                              (tuareg-run-process-if-needed 
org-babel-ocaml-command)
+                             (tuareg-run-caml)))
     (get-buffer tuareg-interactive-buffer-name)))
 
 (defun org-babel-variable-assignments:ocaml (params)
diff --git a/lisp/ob-octave.el b/lisp/ob-octave.el
index 166cd59..bfe3e2a 100644
--- a/lisp/ob-octave.el
+++ b/lisp/ob-octave.el
@@ -45,8 +45,8 @@
 
 (defvar org-babel-matlab-with-emacs-link nil
   "If non-nil use matlab-shell-run-region for session evaluation.
-  This will use EmacsLink if (matlab-with-emacs-link) evaluates
-  to a non-nil value.")
+This will use EmacsLink if (matlab-with-emacs-link) evaluates
+to a non-nil value.")
 
 (defvar org-babel-matlab-emacs-link-wrapper-method
   "%s
@@ -164,7 +164,7 @@ create.  Return the initialized session."
          (current-buffer))))))
 
 (defun org-babel-octave-evaluate
-  (session body result-type &optional matlabp)
+    (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
@@ -181,12 +181,12 @@ value of the last statement in BODY, as elisp."
     (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
-                       (org-babel-process-file-name tmp-file 'noquote)
-                       (org-babel-process-file-name tmp-file 'noquote)))
-              (org-babel-octave-import-elisp-from-file tmp-file))))))
+               (org-babel-eval
+                cmd
+                (format org-babel-octave-wrapper-method body
+                        (org-babel-process-file-name tmp-file 'noquote)
+                        (org-babel-process-file-name tmp-file 'noquote)))
+               (org-babel-octave-import-elisp-from-file tmp-file))))))
 
 (defun org-babel-octave-evaluate-session
     (session body result-type &optional matlabp)
diff --git a/lisp/ob-perl.el b/lisp/ob-perl.el
index 0cfac85..4d405a8 100644
--- a/lisp/ob-perl.el
+++ b/lisp/ob-perl.el
@@ -4,6 +4,7 @@
 
 ;; Authors: Dan Davison
 ;;      Eric Schulte
+;; Maintainer: Corwin Brust
 ;; Keywords: literate programming, reproducible research
 ;; Homepage: https://orgmode.org
 
diff --git a/lisp/ob-picolisp.el b/lisp/ob-picolisp.el
deleted file mode 100644
index b1587f2..0000000
--- a/lisp/ob-picolisp.el
+++ /dev/null
@@ -1,185 +0,0 @@
-;;; ob-picolisp.el --- Babel Functions for Picolisp  -*- lexical-binding: t; 
-*-
-
-;; Copyright (C) 2010-2021 Free Software Foundation, Inc.
-
-;; Authors: Thorsten Jolitz
-;;      Eric Schulte
-;; Keywords: literate programming, reproducible research
-;; Homepage: https://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 <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; This library enables the use of PicoLisp in the multi-language
-;; programming framework Org-Babel.  PicoLisp is a minimal yet
-;; fascinating lisp dialect and a highly productive application
-;; framework for web-based client-server applications on top of
-;; object-oriented databases.  A good way to learn PicoLisp is to first
-;; read Paul Grahams essay "The hundred year language"
-;; (http://www.paulgraham.com/hundred.html) and then study the various
-;; documents and essays published in the PicoLisp wiki
-;; (http://picolisp.com/5000/-2.html). PicoLisp is included in some
-;; GNU/Linux Distributions, and can be downloaded here:
-;; http://software-lab.de/down.html.  It ships with a picolisp-mode and
-;; an inferior-picolisp-mode for Emacs (to be found in the /lib/el/
-;; directory).
-
-;; Although it might seem more natural to use Emacs Lisp for most
-;; Lisp-based programming tasks inside Org, an Emacs library written
-;; in Emacs Lisp, PicoLisp has at least two outstanding features that
-;; make it a valuable addition to Org Babel:
-
-;; PicoLisp _is_ an object-oriented database with a Prolog-based query
-;; language implemented in PicoLisp (Pilog). Database objects are
-;; first-class members of the language.
-
-;; PicoLisp is an extremely productive framework for the development
-;; of interactive web-applications (on top of a database).
-
-;;; Requirements:
-
-;;; Code:
-(require 'ob)
-(require 'comint)
-
-(declare-function run-picolisp "ext:inferior-picolisp" (cmd))
-(defvar org-babel-tangle-lang-exts) ;; Autoloaded
-
-;; optionally define a file extension for this language
-(add-to-list 'org-babel-tangle-lang-exts '("picolisp" . "l"))
-
-;;; interferes with settings in org-babel buffer?
-;; optionally declare default header arguments for this language
-;; (defvar org-babel-default-header-args:picolisp
-;;   '((:colnames . "no"))
-;;   "Default arguments for evaluating a picolisp source block.")
-
-(defvar org-babel-picolisp-eoe "org-babel-picolisp-eoe"
-  "String to indicate that evaluation has completed.")
-
-(defcustom org-babel-picolisp-cmd "pil"
-  "Name of command used to evaluate picolisp blocks."
-  :group 'org-babel
-  :version "24.1"
-  :type 'string)
-
-(defun org-babel-expand-body:picolisp (body params)
-  "Expand BODY according to PARAMS, return the expanded body."
-  (let ((vars (org-babel--get-vars params))
-        (print-level nil)
-       (print-length nil))
-    (if (> (length vars) 0)
-        (concat "(prog (let ("
-                (mapconcat
-                 (lambda (var)
-                   (format "%S '%S)"
-                           (print (car var))
-                           (print (cdr var))))
-                 vars "\n      ")
-                " \n" body ") )")
-      body)))
-
-(defun org-babel-execute:picolisp (body params)
-  "Execute a block of Picolisp code with org-babel.
-This function is called by `org-babel-execute-src-block'."
-  (message "executing Picolisp source code block")
-  (let* (
-        ;; Name of the session or "none".
-        (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-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.
-         (wrapped-body
-          (cond
-           ((or (member "code" result-params)
-                (member "pp" result-params))
-            (format "(pretty (out \"%s\" %s))" null-device full-body))
-           ((and (member "value" result-params) (not session))
-            (format "(print (out \"%s\" %s))" null-device full-body))
-           ((member "value" result-params)
-            (format "(out \"%s\" %s)" null-device full-body))
-           (t full-body)))
-         (result
-          (if (not (string= session-name "none"))
-              ;; Session based evaluation.
-              (mapconcat ;; <- joins the list back into a single string
-               #'identity
-               (butlast ;; <- remove the org-babel-picolisp-eoe line
-                (delq nil
-                      (mapcar
-                       (lambda (line)
-                         (org-babel-chomp      ;; Remove trailing newlines.
-                          (when (> (length line) 0) ;; Remove empty lines.
-                            (cond
-                             ;; Remove leading "-> " from return values.
-                             ((and (>= (length line) 3)
-                                   (string= "-> " (substring line 0 3)))
-                              (substring line 3))
-                             ;; Remove trailing "-> <<return-value>>" on the
-                             ;; last line of output.
-                             ((and (member "output" result-params)
-                                   (string-match-p "->" line))
-                              (substring line 0 (string-match "->" line)))
-                             (t line)
-                             )
-                            ;;(if (and (>= (length line) 3);Remove leading "<-"
-                            ;;         (string= "-> " (substring line 0 3)))
-                            ;;    (substring line 3)
-                            ;;  line)
-                            )))
-                       ;; Returns a list of the output of each evaluated exp.
-                       (org-babel-comint-with-output
-                           (session org-babel-picolisp-eoe)
-                         (insert wrapped-body) (comint-send-input)
-                         (insert "'" org-babel-picolisp-eoe)
-                         (comint-send-input)))))
-               "\n")
-            ;; external evaluation
-            (let ((script-file (org-babel-temp-file "picolisp-script-")))
-              (with-temp-file script-file
-                (insert (concat wrapped-body "(bye)")))
-              (org-babel-eval
-               (format "%s %s"
-                       org-babel-picolisp-cmd
-                       (org-babel-process-file-name script-file))
-               "")))))
-    (org-babel-result-cond result-params
-      result
-      (read result))))
-
-(defun org-babel-picolisp-initiate-session (&optional session-name)
-  "If there is not a current inferior-process-buffer in SESSION
-then create.  Return the initialized session."
-  (unless (string= session-name "none")
-    (require 'inferior-picolisp)
-    ;; provide a reasonable default session name
-    (let ((session (or session-name "*inferior-picolisp*")))
-      ;; check if we already have a live session by this name
-      (if (org-babel-comint-buffer-livep session)
-          (get-buffer session)
-        (save-window-excursion
-          (run-picolisp org-babel-picolisp-cmd)
-          (rename-buffer session-name)
-          (current-buffer))))))
-
-(provide 'ob-picolisp)
-
-;;; ob-picolisp.el ends here
diff --git a/lisp/ob-plantuml.el b/lisp/ob-plantuml.el
index 93c6538..fc62160 100644
--- a/lisp/ob-plantuml.el
+++ b/lisp/ob-plantuml.el
@@ -71,6 +71,12 @@ You can also configure extra arguments via 
`org-plantuml-executable-args'."
   :package-version '(Org . "9.4")
   :type '(repeat string))
 
+(defcustom org-babel-plantuml-svg-text-to-path nil
+  "When non-nil, export text in SVG images to paths using Inkscape."
+  :group 'org-babel
+  :package-version '(Org . "9.5")
+  :type 'boolean)
+
 (defun org-babel-variable-assignments:plantuml (params)
   "Return a list of PlantUML statements assigning the block's variables.
 PARAMS is a property list of source block parameters, which may
@@ -78,9 +84,9 @@ contain multiple entries for the key `:var'.  `:var' entries 
in PARAMS
 are expected to be scalar variables."
   (mapcar
    (lambda (pair)
-       (format "!define %s %s"
-              (car pair)
-              (replace-regexp-in-string "\"" "" (cdr pair))))
+     (format "!define %s %s"
+            (car pair)
+            (replace-regexp-in-string "\"" "" (cdr pair))))
    (org-babel--get-vars params)))
 
 (defun org-babel-plantuml-make-body (body params)
@@ -145,6 +151,9 @@ This function is called by `org-babel-execute-src-block'."
                         " ")))
     (with-temp-file in-file (insert full-body))
     (message "%s" cmd) (org-babel-eval cmd "")
+    (if (and (string= (file-name-extension out-file) "svg")
+             org-babel-plantuml-svg-text-to-path)
+        (org-babel-eval (format "inkscape %s -T -l %s" out-file out-file) ""))
     nil)) ;; signal that output has already been written to file
 
 (defun org-babel-prep-session:plantuml (_session _params)
diff --git a/lisp/ob-processing.el b/lisp/ob-processing.el
index 9e6572a..84fd6a2 100644
--- a/lisp/ob-processing.el
+++ b/lisp/ob-processing.el
@@ -47,7 +47,7 @@
 ;;; Requirements:
 
 ;; - processing2-emacs mode :: https://github.com/ptrv/processing2-emacs
-;; - Processing.js module :: http://processingjs.org/
+;; - Processing.js module :: https://processingjs.org/
 
 ;;; Code:
 (require 'ob)
diff --git a/lisp/ob-python.el b/lisp/ob-python.el
index 7911205..3c095ad 100644
--- a/lisp/ob-python.el
+++ b/lisp/ob-python.el
@@ -81,15 +81,20 @@ This function is called by `org-babel-execute-src-block'."
                   (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))
+        (return-val (when (eq result-type 'value)
                       (cdr (assq :return params))))
         (preamble (cdr (assq :preamble params)))
+        (async (org-babel-comint-use-async params))
          (full-body
-         (org-babel-expand-body:generic
-          (concat body (if return-val (format "\nreturn %s" return-val) ""))
-          params (org-babel-variable-assignments:python params)))
+         (concat
+          (org-babel-expand-body:generic
+           body params
+           (org-babel-variable-assignments:python params))
+          (when return-val
+            (format (if session "\n%s" "\nreturn %s") return-val))))
          (result (org-babel-python-evaluate
-                 session full-body result-type result-params preamble)))
+                 session full-body result-type
+                 result-params preamble async)))
     (org-babel-reassemble-table
      result
      (org-babel-pick-name (cdr (assq :colname-names params))
@@ -149,7 +154,7 @@ 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-python-None-to el))
+                                 org-babel-python-None-to el))
                 res)
       res)))
 
@@ -275,11 +280,14 @@ else:
          (if (member "pp" result-params) "True" "False")))
 
 (defun org-babel-python-evaluate
-  (session body &optional result-type result-params preamble)
+    (session body &optional result-type result-params preamble async)
   "Evaluate BODY as Python code."
   (if session
-      (org-babel-python-evaluate-session
-       session body result-type result-params)
+      (if async
+         (org-babel-python-async-evaluate-session
+          session body result-type result-params)
+       (org-babel-python-evaluate-session
+        session body result-type result-params))
     (org-babel-python-evaluate-external-process
      body result-type result-params preamble)))
 
@@ -388,6 +396,49 @@ last statement in BODY, as elisp."
       (substring string 1 -1)
     string))
 
+;; Async session eval
+
+(defconst org-babel-python-async-indicator "print 
('ob_comint_async_python_%s_%s')")
+
+(defun org-babel-python-async-value-callback (params tmp-file)
+  (let ((result-params (cdr (assq :result-params params)))
+       (results (org-babel-eval-read-file tmp-file)))
+    (org-babel-result-cond result-params
+      results
+      (org-babel-python-table-or-string results))))
+
+(defun org-babel-python-async-evaluate-session
+    (session body &optional result-type result-params)
+  "Asynchronously evaluate BODY in SESSION.
+Returns a placeholder string for insertion, to later be replaced
+by `org-babel-comint-async-filter'."
+  (org-babel-comint-async-register
+   session (current-buffer)
+   "ob_comint_async_python_\\(.+\\)_\\(.+\\)"
+   'org-babel-chomp 'org-babel-python-async-value-callback)
+  (let ((python-shell-buffer-name (org-babel-python-without-earmuffs session)))
+    (pcase result-type
+      (`output
+       (let ((uuid (md5 (number-to-string (random 100000000)))))
+         (with-temp-buffer
+           (insert (format org-babel-python-async-indicator "start" uuid))
+           (insert "\n")
+           (insert body)
+           (insert "\n")
+           (insert (format org-babel-python-async-indicator "end" uuid))
+           (python-shell-send-buffer))
+         uuid))
+      (`value
+       (let ((tmp-results-file (org-babel-temp-file "python-"))
+             (tmp-src-file (org-babel-temp-file "python-")))
+         (with-temp-file tmp-src-file (insert body))
+         (with-temp-buffer
+           (insert (org-babel-python-format-session-value tmp-src-file 
tmp-results-file result-params))
+           (insert "\n")
+           (insert (format org-babel-python-async-indicator "file" 
tmp-results-file))
+           (python-shell-send-buffer))
+         tmp-results-file)))))
+
 (provide 'ob-python)
 
 ;;; ob-python.el ends here
diff --git a/lisp/ob-ruby.el b/lisp/ob-ruby.el
index ccc746e..b2483f1 100644
--- a/lisp/ob-ruby.el
+++ b/lisp/ob-ruby.el
@@ -27,7 +27,7 @@
 
 ;;; Requirements:
 
-;; - ruby and irb executables :: http://www.ruby-lang.org/
+;; - ruby and irb executables :: https://www.ruby-lang.org/
 ;;
 ;; - ruby-mode :: Can be installed through ELPA, or from
 ;;   https://github.com/eschulte/rinari/raw/master/util/ruby-mode.el
diff --git a/lisp/ob-sass.el b/lisp/ob-sass.el
index 76cdfd8..c8762ca 100644
--- a/lisp/ob-sass.el
+++ b/lisp/ob-sass.el
@@ -23,7 +23,7 @@
 
 ;;; Commentary:
 
-;; For more information on sass see http://sass-lang.com/
+;; For more information on sass see https://sass-lang.com/
 ;;
 ;; This accepts a 'file' header argument which is the target of the
 ;; compiled sass.  The default output type for sass evaluation is
diff --git a/lisp/ob-scheme.el b/lisp/ob-scheme.el
index a18bfb5..f4836b2 100644
--- a/lisp/ob-scheme.el
+++ b/lisp/ob-scheme.el
@@ -110,7 +110,7 @@
     geiser-impl--implementation))
 
 (defun org-babel-scheme-get-repl (impl name)
-  "Switch to a scheme REPL, creating it if it doesn't exist:"
+  "Switch to a scheme REPL, creating it if it doesn't exist."
   (let ((buffer (org-babel-scheme-get-session-buffer name)))
     (or buffer
        (progn
diff --git a/lisp/ob-screen.el b/lisp/ob-screen.el
index a9bd422..7793825 100644
--- a/lisp/ob-screen.el
+++ b/lisp/ob-screen.el
@@ -3,6 +3,7 @@
 ;; Copyright (C) 2009-2021 Free Software Foundation, Inc.
 
 ;; Author: Benjamin Andresen
+;; Maintainer: Ken Mankoff
 ;; Keywords: literate programming, interactive shell
 ;; Homepage: https://orgmode.org
 
@@ -29,7 +30,7 @@
 ;; Adding :cmd and :terminal as header arguments
 ;; :terminal must support the -T (title) and -e (command) parameter
 ;;
-;; You can test the default setup. (xterm + sh) with
+;; You can test the default setup (xterm + sh) with
 ;; M-x org-babel-screen-test RET
 
 ;;; Code:
diff --git a/lisp/ob-sed.el b/lisp/ob-sed.el
index b95f411..4d3eeee 100644
--- a/lisp/ob-sed.el
+++ b/lisp/ob-sed.el
@@ -70,12 +70,12 @@ function is called by `org-babel-execute-src-block'."
                        (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))))
+                 (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
diff --git a/lisp/ob-shen.el b/lisp/ob-shen.el
deleted file mode 100644
index 6803b0b..0000000
--- a/lisp/ob-shen.el
+++ /dev/null
@@ -1,79 +0,0 @@
-;;; ob-shen.el --- Babel Functions for Shen          -*- lexical-binding: t; 
-*-
-
-;; Copyright (C) 2010-2021 Free Software Foundation, Inc.
-
-;; Author: Eric Schulte
-;; Keywords: literate programming, reproducible research, shen
-;; Homepage: https://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 <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; Currently this only works using session evaluation as there is no
-;; defined method for executing shen code outside of a session.
-
-;;; Requirements:
-
-;; - shen-mode and inf-shen will soon be available through the GNU
-;;   elpa, however in the interim they are available at
-;;   https://github.com/eschulte/shen-mode
-
-;;; Code:
-(require 'ob)
-
-(declare-function shen-eval-defun "ext:inf-shen" (&optional and-go))
-(declare-function org-babel-ruby-var-to-ruby "ob-ruby" (var))
-
-(defvar org-babel-default-header-args:shen '()
-  "Default header arguments for shen code blocks.")
-
-(defun org-babel-expand-body:shen (body params)
-  "Expand BODY according to PARAMS, return the expanded body."
-  (let ((vars (org-babel--get-vars params)))
-    (if (> (length vars) 0)
-        (concat "(let "
-                (mapconcat (lambda (var)
-                            (format "%s %s" (car var)
-                                    (org-babel-shen-var-to-shen (cdr var))))
-                          vars " ")
-               body ")")
-      body)))
-
-(defun org-babel-shen-var-to-shen (var)
-  "Convert VAR into a shen variable."
-  (if (listp var)
-      (concat "[" (mapconcat #'org-babel-ruby-var-to-ruby var " ") "]")
-    (format "%S" var)))
-
-(defun org-babel-execute:shen (body params)
-  "Execute a block of Shen code with org-babel.
-This function is called by `org-babel-execute-src-block'."
-  (require 'inf-shen)
-  (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
-        results
-        (condition-case nil (org-babel-script-escape results)
-          (error results))))))
-
-(provide 'ob-shen)
-
-;;; ob-shen.el ends here
diff --git a/lisp/ob-sql.el b/lisp/ob-sql.el
index ef8b9a4..f512d29 100644
--- a/lisp/ob-sql.el
+++ b/lisp/ob-sql.el
@@ -40,6 +40,7 @@
 ;; - dbuser
 ;; - dbpassword
 ;; - dbconnection (to reference connections in sql-connection-alist)
+;; - dbinstance (currently only used by SAP HANA)
 ;; - database
 ;; - colnames (default, nil, means "yes")
 ;; - result-params
@@ -58,6 +59,7 @@
 ;; - postgresql (postgres)
 ;; - oracle
 ;; - vertica
+;; - saphana
 ;;
 ;; TODO:
 ;;
@@ -85,13 +87,21 @@
     (dbport           . :any)
     (dbuser           . :any)
     (dbpassword               . :any)
+    (dbinstance               . :any)
     (database         . :any))
   "SQL-specific header arguments.")
 
 (defun org-babel-expand-body:sql (body params)
   "Expand BODY according to the values of PARAMS."
-  (org-babel-sql-expand-vars
-   body (org-babel--get-vars params)))
+  (let ((prologue (cdr (assq :prologue params)))
+       (epilogue (cdr (assq :epilogue params))))
+    (mapconcat 'identity
+               (list
+                prologue
+                (org-babel-sql-expand-vars
+                 body (org-babel--get-vars params))
+                epilogue)
+               "\n")))
 
 (defun org-babel-edit-prep:sql (info)
   "Set `sql-product' in Org edit buffer.
@@ -166,15 +176,30 @@ SQL Server on Windows and Linux platform."
              " "))
 
 (defun org-babel-sql-dbstring-vertica (host port user password database)
-  "Make Vertica command line args for database connection. Pass nil to omit 
that arg."
+  "Make Vertica command line args for database connection.
+Pass nil to omit that arg."
+  (mapconcat #'identity
+            (delq nil
+                  (list (when host     (format "-h %s" host))
+                        (when port     (format "-p %d" port))
+                        (when user     (format "-U %s" user))
+                        (when password (format "-w %s" (shell-quote-argument 
password) ))
+                        (when database (format "-d %s" database))))
+            " "))
+
+(defun org-babel-sql-dbstring-saphana (host port instance user password 
database)
+  "Make SAP HANA command line args for database connection.
+Pass nil to omit that arg."
   (mapconcat #'identity
-             (delq nil
-                   (list (when host     (format "-h %s" host))
-                         (when port     (format "-p %d" port))
-                         (when user     (format "-U %s" user))
-                         (when password (format "-w %s" (shell-quote-argument 
password) ))
-                         (when database (format "-d %s" database))))
-             " "))
+             (delq nil
+                   (list (and host port (format "-n %s:%s" host port))
+                         (and host (not port) (format "-n %s" host))
+                         (and instance (format "-i %d" instance))
+                         (and user (format "-u %s" user))
+                         (and password (format "-p %s"
+                                               (shell-quote-argument 
password)))
+                         (and database (format "-d %s" database))))
+             " "))
 
 (defun org-babel-sql-convert-standard-filename (file)
   "Convert FILE to OS standard file name.
@@ -190,8 +215,8 @@ Otherwise, use Emacs' standard conversion function."
   "Return database connection parameter NAME.
 Given a parameter NAME, if :dbconnection is defined in PARAMS
 then look for the parameter into the corresponding connection
-defined in `sql-connection-alist`, otherwise look into PARAMS.
-Look `sql-connection-alist` (part of SQL mode) for how to define
+defined in `sql-connection-alist', otherwise look into PARAMS.
+See `sql-connection-alist' (part of SQL mode) for how to define
 database connections."
   (if (assq :dbconnection params)
       (let* ((dbconnection (cdr (assq :dbconnection params)))
@@ -199,6 +224,7 @@ database connections."
                              (:dbport . sql-port)
                              (:dbuser . sql-user)
                              (:dbpassword . sql-password)
+                             (:dbinstance . sql-dbinstance)
                              (:database . sql-database)))
              (mapped-name (cdr (assq name name-mapping))))
         (cadr (assq mapped-name
@@ -214,6 +240,7 @@ This function is called by `org-babel-execute-src-block'."
          (dbport (org-babel-find-db-connection-param params :dbport))
          (dbuser (org-babel-find-db-connection-param params :dbuser))
          (dbpassword (org-babel-find-db-connection-param params :dbpassword))
+         (dbinstance (org-babel-find-db-connection-param params :dbinstance))
          (database (org-babel-find-db-connection-param params :database))
          (engine (cdr (assq :engine params)))
          (colnames-p (not (equal "no" (cdr (assq :colnames params)))))
@@ -281,6 +308,12 @@ footer=off -F \"\t\"  %s -f %s -o %s %s"
                              dbhost dbport dbuser dbpassword database)
                             (org-babel-process-file-name in-file)
                             (org-babel-process-file-name out-file)))
+                   (saphana (format "hdbsql %s -I %s -o %s %s"
+                                    (org-babel-sql-dbstring-saphana
+                                     dbhost dbport dbinstance dbuser 
dbpassword database)
+                                    (org-babel-process-file-name in-file)
+                                    (org-babel-process-file-name out-file)
+                                    (or cmdline "")))
                     (t (user-error "No support for the %s SQL engine" 
engine)))))
     (with-temp-file in-file
       (insert
@@ -314,7 +347,7 @@ SET COLSEP '|'
        (progn (insert-file-contents-literally out-file) (buffer-string)))
       (with-temp-buffer
        (cond
-        ((memq (intern engine) '(dbi mysql postgresql postgres sqsh vertica))
+        ((memq (intern engine) '(dbi mysql postgresql postgres saphana sqsh 
vertica))
          ;; Add header row delimiter after column-names header in first line
          (cond
           (colnames-p
@@ -351,8 +384,13 @@ SET COLSEP '|'
         (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."
+(defun org-babel-sql-expand-vars (body vars &optional sqlite)
+  "Expand the variables held in VARS in BODY.
+
+If SQLITE has been provided, prevent passing a format to
+`orgtbl-to-csv'.  This prevents overriding the default format, which if
+there were commas in the context of the table broke the table as an
+argument mechanism."
   (mapc
    (lambda (pair)
      (setq body
@@ -363,9 +401,11 @@ SET COLSEP '|'
                   (let ((data-file (org-babel-temp-file "sql-data-")))
                     (with-temp-file data-file
                       (insert (orgtbl-to-csv
-                               val '(:fmt (lambda (el) (if (stringp el)
-                                                      el
-                                                    (format "%S" el)))))))
+                               val (if sqlite
+                                       nil
+                                     '(:fmt (lambda (el) (if (stringp el)
+                                                             el
+                                                           (format "%S" 
el))))))))
                     data-file)
                 (if (stringp val) val (format "%S" val))))
            body)))
diff --git a/lisp/ob-sqlite.el b/lisp/ob-sqlite.el
index e23e278..7bfb66c 100644
--- a/lisp/ob-sqlite.el
+++ b/lisp/ob-sqlite.el
@@ -3,6 +3,7 @@
 ;; Copyright (C) 2010-2021 Free Software Foundation, Inc.
 
 ;; Author: Eric Schulte
+;; Maintainer: Nick Savage
 ;; Keywords: literate programming, reproducible research
 ;; Homepage: https://orgmode.org
 
@@ -27,6 +28,7 @@
 
 ;;; Code:
 (require 'ob)
+(require 'ob-sql)
 
 (declare-function org-table-convert-region "org-table"
                  (beg0 end0 &optional separator))
@@ -51,8 +53,8 @@
 
 (defun org-babel-expand-body:sqlite (body params)
   "Expand BODY according to the values of PARAMS."
-  (org-babel-sqlite-expand-vars
-   body (org-babel--get-vars params)))
+  (org-babel-sql-expand-vars
+   body (org-babel--get-vars params) t))
 
 (defvar org-babel-sqlite3-command "sqlite3")
 
@@ -112,22 +114,8 @@ This function is called by `org-babel-execute-src-block'."
 
 (defun org-babel-sqlite-expand-vars (body vars)
   "Expand the variables held in VARS in BODY."
-  ;; FIXME: Redundancy with org-babel-sql-expand-vars!
-  (mapc
-   (lambda (pair)
-     (setq body
-          (replace-regexp-in-string
-           (format "$%s" (car pair))
-           (let ((val (cdr pair)))
-              (if (listp val)
-                  (let ((data-file (org-babel-temp-file "sqlite-data-")))
-                    (with-temp-file data-file
-                      (insert (orgtbl-to-csv val nil)))
-                    data-file)
-                (if (stringp val) val (format "%S" val))))
-           body)))
-   vars)
-  body)
+  (declare (obsolete "use `org-babel-sql-expand-vars' instead." "9.5"))
+  (org-babel-sql-expand-vars body vars t))
 
 (defun org-babel-sqlite-table-or-scalar (result)
   "If RESULT looks like a trivial table, then unwrap it."
diff --git a/lisp/ob-stan.el b/lisp/ob-stan.el
deleted file mode 100644
index 1f2afde..0000000
--- a/lisp/ob-stan.el
+++ /dev/null
@@ -1,86 +0,0 @@
-;;; ob-stan.el --- Babel Functions for Stan          -*- lexical-binding: t; 
-*-
-
-;; Copyright (C) 2015-2021 Free Software Foundation, Inc.
-
-;; Author: Kyle Meyer
-;; Keywords: literate programming, reproducible research
-;; Homepage: https://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 <https://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
-;; https://orgmode.org/worg/org-contrib/babel/languages/ob-doc-stan.html
-;;
-;; [1] https://mc-stan.org/
-
-;;; Code:
-(require 'ob)
-(require 'org-compat)
-
-(defcustom org-babel-stan-cmdstan-directory nil
-  "CmdStan source directory.
-Call \"make\" from this directory to compile the Stan block.
-When nil, executing Stan blocks dumps the content to a file."
-  :group 'org-babel
-  :type '(choice
-         (directory :tag "Compilation directory")
-         (const :tag "Dump to a file" nil)))
-
-(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/ob-table.el b/lisp/ob-table.el
index 39a14a2..e081708 100644
--- a/lisp/ob-table.el
+++ b/lisp/ob-table.el
@@ -78,7 +78,8 @@ So this `org-sbe' construct
 
 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
+ #+begin_src emacs-lisp :var results=source-block(n=val_at_col_2, m=3) \\
+     :results silent
  results
  #+end_src
 
diff --git a/lisp/ob-tangle.el b/lisp/ob-tangle.el
index 3ee7179..2dd1d03 100644
--- a/lisp/ob-tangle.el
+++ b/lisp/ob-tangle.el
@@ -43,6 +43,7 @@
 (declare-function org-in-commented-heading-p "org" (&optional no-inheritance))
 (declare-function org-in-archived-heading-p "org" (&optional no-inheritance))
 (declare-function outline-previous-heading "outline" ())
+(defvar org-id-link-to-org-use-id nil) ; Dynamically scoped
 
 (defcustom org-babel-tangle-lang-exts
   '(("emacs-lisp" . "el")
@@ -150,7 +151,7 @@ represented in the file."
   "Open FILE into a temporary buffer execute BODY there like
 `progn', then kill the FILE buffer returning the result of
 evaluating BODY."
-  (declare (indent 1))
+  (declare (indent 1) (debug t))
   (let ((temp-path (make-symbol "temp-path"))
        (temp-result (make-symbol "temp-result"))
        (temp-file (make-symbol "temp-file"))
@@ -164,17 +165,19 @@ evaluating BODY."
         (setf ,temp-result (progn ,@body)))
        (unless ,visited-p (kill-buffer ,temp-file))
        ,temp-result)))
-(def-edebug-spec org-babel-with-temp-filebuffer (form body))
 
 ;;;###autoload
 (defun org-babel-tangle-file (file &optional target-file lang-re)
   "Extract the bodies of source code blocks in FILE.
 Source code blocks are extracted with `org-babel-tangle'.
+
 Optional argument TARGET-FILE can be used to specify a default
-export file for all source blocks.  Optional argument LANG-RE can
-be used to limit the exported source code blocks by languages
-matching a regular expression.  Return a list whose CAR is the
-tangled file name."
+export file for all source blocks.
+
+Optional argument LANG-RE can be used to limit the exported
+source code blocks by languages matching a regular expression.
+
+Return a list whose CAR is the tangled file name."
   (interactive "fFile to tangle: \nP")
   (let ((visited-p (find-buffer-visiting (expand-file-name file)))
        to-be-removed)
@@ -226,67 +229,55 @@ matching a regular expression."
               (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
-        (lambda (by-lang)
-          (let* ((lang (car by-lang))
-                 (specs (cdr by-lang))
-                 (ext (or (cdr (assoc lang org-babel-tangle-lang-exts)) lang))
-                 (lang-f (org-src-get-lang-mode lang))
-                 she-banged)
-            (mapc
-             (lambda (spec)
-               (let ((get-spec (lambda (name) (cdr (assoc name (nth 4 
spec))))))
-                 (let* ((tangle (funcall get-spec :tangle))
-                        (she-bang (let ((sheb (funcall get-spec :shebang)))
-                                     (when (> (length sheb) 0) sheb)))
-                        (tangle-mode (funcall get-spec :tangle-mode))
-                        (base-name (cond
-                                    ((string= "yes" tangle)
-                                     (file-name-sans-extension
-                                      (nth 1 spec)))
-                                    ((string= "no" tangle) nil)
-                                    ((> (length tangle) 0) tangle)))
-                        (file-name (when base-name
-                                     ;; decide if we want to add ext to 
base-name
-                                     (if (and ext (string= "yes" tangle))
-                                         (concat base-name "." ext) 
base-name))))
-                   (when file-name
-                     ;; Possibly create the parent directories for file.
-                     (let ((m (funcall get-spec :mkdirp))
-                           (fnd (file-name-directory file-name)))
-                       (and m fnd (not (string= m "no"))
-                            (make-directory fnd 'parents)))
-                     ;; delete any old versions of file
-                     (and (file-exists-p file-name)
-                          (not (member file-name (mapcar #'car 
path-collector)))
-                          (delete-file file-name))
-                     ;; drop source-block to file
-                     (with-temp-buffer
-                       (when (fboundp lang-f) (ignore-errors (funcall lang-f)))
-                       (when (and she-bang (not (member file-name she-banged)))
+       (mapc ;; map over file-names
+        (lambda (by-fn)
+          (let ((file-name (car by-fn)))
+            (when file-name
+               (let ((lspecs (cdr by-fn))
+                    (fnd (file-name-directory file-name))
+                    modes make-dir she-banged lang)
+                ;; drop source-blocks to file
+                ;; We avoid append-to-file as it does not work with tramp.
+                (with-temp-buffer
+                  (mapc
+                   (lambda (lspec)
+                     (let* ((block-lang (car lspec))
+                            (spec (cdr lspec))
+                            (get-spec (lambda (name) (cdr (assq name (nth 4 
spec)))))
+                            (she-bang (let ((sheb (funcall get-spec :shebang)))
+                                        (when (> (length sheb) 0) sheb)))
+                            (tangle-mode (funcall get-spec :tangle-mode)))
+                       (unless (string-equal block-lang lang)
+                         (setq lang block-lang)
+                         (let ((lang-f (org-src-get-lang-mode lang)))
+                           (when (fboundp lang-f) (ignore-errors (funcall 
lang-f)))))
+                       ;; if file contains she-bangs, then make it executable
+                       (when she-bang
+                         (unless tangle-mode (setq tangle-mode #o755)))
+                       (when tangle-mode
+                         (add-to-list 'modes tangle-mode))
+                       ;; Possibly create the parent directories for file.
+                       (let ((m (funcall get-spec :mkdirp)))
+                         (and m fnd (not (string= m "no"))
+                              (setq make-dir t)))
+                       ;; Handle :padlines unless first line in file
+                       (unless (or (string= "no" (funcall get-spec :padline))
+                                   (= (point) (point-min)))
+                         (insert "\n"))
+                       (when (and she-bang (not she-banged))
                          (insert (concat she-bang "\n"))
-                         (setq she-banged (cons file-name she-banged)))
-                       (org-babel-spec-to-string spec)
-                       ;; We avoid append-to-file as it does not work with 
tramp.
-                       (let ((content (buffer-string)))
-                         (with-temp-buffer
-                           (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
-                     (when she-bang
-                       (unless tangle-mode (setq tangle-mode #o755)))
-                     ;; update counter
-                     (setq block-counter (+ 1 block-counter))
-                     (unless (assoc file-name path-collector)
-                       (push (cons file-name tangle-mode) path-collector))))))
-             specs)))
+                         (setq she-banged t))
+                       (org-babel-spec-to-string spec)
+                       (setq block-counter (+ 1 block-counter))))
+                   lspecs)
+                  (when make-dir
+                    (make-directory fnd 'parents))
+                   ;; erase previous file
+                   (when (file-exists-p file-name)
+                     (delete-file file-name))
+                  (write-region nil nil file-name)
+                  (mapc (lambda (mode) (set-file-modes file-name mode)) modes)
+                   (push file-name path-collector))))))
         (if (equal arg '(4))
             (org-babel-tangle-single-block 1 t)
           (org-babel-tangle-collect-blocks lang-re tangle-file)))
@@ -294,19 +285,18 @@ matching a regular expression."
                 (if (= block-counter 1) "" "s")
                 (file-name-nondirectory
                  (buffer-file-name
-                  (or (buffer-base-buffer) (current-buffer)))))
+                  (or (buffer-base-buffer)
+                       (current-buffer)
+                       (and (org-src-edit-buffer-p)
+                            (org-src-source-buffer))))))
        ;; run `org-babel-post-tangle-hook' in all tangled files
        (when org-babel-post-tangle-hook
          (mapc
           (lambda (file)
             (org-babel-with-temp-filebuffer file
               (run-hooks 'org-babel-post-tangle-hook)))
-          (mapcar #'car path-collector)))
-       ;; set permissions on tangled files
-       (mapc (lambda (pair)
-               (when (cdr pair) (set-file-modes (car pair) (cdr pair))))
-             path-collector)
-       (mapcar #'car path-collector)))))
+          path-collector))
+       path-collector))))
 
 (defun org-babel-tangle-clean ()
   "Remove comments inserted by `org-babel-tangle'.
@@ -367,12 +357,32 @@ that the appropriate major-mode is set.  SPEC has the 
form:
               (org-fill-template
                org-babel-tangle-comment-format-end link-data)))))
 
+(defun org-babel-effective-tangled-filename (buffer-fn src-lang src-tfile)
+  "Return effective tangled filename of a source-code block.
+BUFFER-FN is the name of the buffer, SRC-LANG the language of the
+block and SRC-TFILE is the value of the :tangle header argument,
+as computed by `org-babel-tangle-single-block'."
+  (let ((base-name (cond
+                    ((string= "yes" src-tfile)
+                     ;; Use the buffer name
+                     (file-name-sans-extension buffer-fn))
+                    ((string= "no" src-tfile) nil)
+                    ((> (length src-tfile) 0) src-tfile)))
+        (ext (or (cdr (assoc src-lang org-babel-tangle-lang-exts)) src-lang)))
+    (when base-name
+      ;; decide if we want to add ext to base-name
+      (if (and ext (string= "yes" src-tfile))
+          (concat base-name "." ext) base-name))))
+
 (defun org-babel-tangle-collect-blocks (&optional lang-re tangle-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.
+Return an association list of language and source-code block
+specifications of the form used by `org-babel-spec-to-string'
+grouped by tangled file name.
+
 Optional argument LANG-RE can be used to limit the collected
 source code blocks by languages matching a regular expression.
+
 Optional argument TANGLE-FILE can be used to limit the collected
 code blocks by target file."
   (let ((counter 0) last-heading-pos blocks)
@@ -391,12 +401,15 @@ code blocks by target file."
          (unless (or (string= src-tfile "no")
                      (and tangle-file (not (equal tangle-file src-tfile)))
                      (and lang-re (not (string-match-p lang-re 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)))))))
+           ;; Add the spec for this block to blocks under its tangled
+           ;; file name.
+           (let* ((block (org-babel-tangle-single-block counter))
+                   (src-tfile (cdr (assq :tangle (nth 4 block))))
+                  (file-name (org-babel-effective-tangled-filename
+                               (nth 1 block) src-lang src-tfile))
+                  (by-fn (assoc file-name blocks)))
+             (if by-fn (setcdr by-fn (cons (cons src-lang block) (cdr by-fn)))
+               (push (cons file-name (list (cons src-lang block))) 
blocks)))))))
     ;; Ensure blocks are in the correct order.
     (mapcar (lambda (b) (cons (car b) (nreverse (cdr b))))
            (nreverse blocks))))
@@ -494,7 +507,10 @@ non-nil, return the full association list to be used by
                  (org-trim (org-remove-indentation body)))
                comment)))
     (if only-this-block
-       (list (cons src-lang (list result)))
+        (let* ((src-tfile (cdr (assq :tangle (nth 4 result))))
+               (file-name (org-babel-effective-tangled-filename
+                           (nth 1 result) src-lang src-tfile)))
+          (list (cons file-name (list (cons src-lang result)))))
       result)))
 
 (defun org-babel-tangle-comment-links (&optional info)
diff --git a/lisp/ob-vala.el b/lisp/ob-vala.el
deleted file mode 100644
index 6c3068a..0000000
--- a/lisp/ob-vala.el
+++ /dev/null
@@ -1,116 +0,0 @@
-;;; ob-vala.el --- Babel functions for Vala evaluation -*- lexical-binding: t; 
-*-
-
-;; Copyright (C) 2017-2021 Free Software Foundation, Inc.
-
-;; Author: Christian Garbs <mitch@cgarbs.de>
-;; Keywords: literate programming, reproducible research
-;; Homepage: https://orgmode.org
-
-;;; License:
-
-;; 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 <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; ob-vala.el provides Babel support for the Vala language
-;; (see https://live.gnome.org/Vala for details)
-
-;;; Requirements:
-
-;; - Vala compiler binary (valac)
-;; - Vala development environment (Vala libraries etc.)
-;;
-;; vala-mode.el is nice to have for code formatting, but is not needed
-;; for ob-vala.el
-
-;;; Code:
-
-(require 'ob)
-(require 'org-macs)
-
-;; File extension.
-(add-to-list 'org-babel-tangle-lang-exts '("vala" . "vala"))
-
-;; Header arguments empty by default.
-(defvar org-babel-default-header-args:vala '())
-
-(defcustom org-babel-vala-compiler "valac"
-  "Command used to compile a C source code file into an executable.
-May be either a command in the path, like \"valac\"
-or an absolute path name, like \"/usr/local/bin/valac\".
-Parameters may be used like this: \"valac -v\""
-  :group 'org-babel
-  :version "26.1"
-  :package-version '(Org . "9.1")
-  :type 'string)
-
-;; This is the main function which is called to evaluate a code
-;; block.
-;;
-;; - run Vala compiler and create a binary in a temporary file
-;;   - compiler/linker flags can be set via :flags header argument
-;; - if compilation succeeded, run the binary
-;;   - commandline parameters to the binary can be set via :cmdline
-;;     header argument
-;;   - stdout will be parsed as RESULT (control via :result-params
-;;     header argument)
-;;
-;; There is no session support because Vala is a compiled language.
-;;
-;; This function is heavily based on ob-C.el
-(defun org-babel-execute:vala (body params)
-  "Execute a block of Vala code with Babel.
-This function is called by `org-babel-execute-src-block'."
-  (message "executing Vala source code block")
-  (let* ((tmp-src-file (org-babel-temp-file
-                       "vala-src-"
-                       ".vala"))
-         (tmp-bin-file (org-babel-temp-file "vala-bin-" org-babel-exeext))
-         (cmdline (cdr (assq :cmdline params)))
-         (flags (cdr (assq :flags params))))
-    (with-temp-file tmp-src-file (insert body))
-    (org-babel-eval
-     (format "%s %s -o %s %s"
-            org-babel-vala-compiler
-            (mapconcat #'identity
-                       (if (listp flags) flags (list flags)) " ")
-            (org-babel-process-file-name tmp-bin-file)
-            (org-babel-process-file-name tmp-src-file)) "")
-    (when (file-executable-p tmp-bin-file)
-       (let ((results
-              (org-trim
-               (org-babel-eval
-                (concat tmp-bin-file (if cmdline (concat " " cmdline) "")) 
""))))
-         (org-babel-reassemble-table
-          (org-babel-result-cond (cdr (assq :result-params params))
-            (org-babel-read results)
-            (let ((tmp-file (org-babel-temp-file "vala-")))
-              (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-prep-session:vala (_session _params)
-  "Prepare a session.
-This function does nothing as Vala is a compiled language with no
-support for sessions."
-  (error "Vala is a compiled language -- no support for sessions"))
-
-(provide 'ob-vala)
-
-;;; ob-vala.el ends here
diff --git a/lisp/oc-basic.el b/lisp/oc-basic.el
new file mode 100644
index 0000000..3b58990
--- /dev/null
+++ b/lisp/oc-basic.el
@@ -0,0 +1,770 @@
+;;; oc-basic.el --- basic back-end for citations  -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021 Free Software Foundation, Inc.
+
+;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; The `basic' citation processor provides "activate", "follow", "export" and
+;; "insert" capabilities.
+
+;; "activate" capability re-uses default fontification, but provides additional
+;; features on both correct and wrong keys according to the bibliography
+;; defined in the document.
+
+;; When the mouse is over a known key, it displays the corresponding
+;; bibliography entry.  Any wrong key, however, is highlighted with `error'
+;; face.  Moreover, moving the mouse onto it displays a list of suggested 
correct
+;; keys, and pressing <mouse-1> on the faulty key will try to fix it according 
to
+;; those suggestions.
+
+;; On a citation key, "follow" capability moves point to the corresponding 
entry
+;; in the current bibliography.  Elsewhere on the citation, it asks the user to
+;; follow any of the keys cited there, with completion.
+
+;; "export" capability supports the following citation styles:
+;;
+;;   - author (a), including caps (c) variant,
+;;   - noauthor (na) including bare (b) variant,
+;;   - text (t), including bare (b), caps (c), and bare-caps (bc) variants,
+;;   - note (ft, including bare (b), caps (c), and bare-caps (bc) variants,
+;;   - nocite (n)
+;;   - numeric (nb),
+;;   - default, including bare (b), caps (c), and bare-caps (bc) variants.
+;;
+;; It also supports the following styles for bibliography:
+;;   - plain
+;;   - numeric
+;;   - author-year (default)
+
+;; "insert" capability inserts or edits (with completion) citation style or
+;; citation reference keys.  In an appropriate place, it offers to insert a new
+;; citation.  With a prefix argument, it removes the one at point.
+
+;; It supports bibliography files in BibTeX (".bibtex"), biblatex (".bib") and
+;; JSON (".json") format.
+
+;; Disclaimer: this citation processor is meant to be a proof of concept, and
+;; possibly a fall-back mechanism when nothing else is available.  It is too
+;; limited for any serious use case.
+
+;;; Code:
+
+(require 'bibtex)
+(require 'json)
+(require 'oc)
+(require 'org)
+(require 'seq)
+
+(declare-function org-open-at-point "org" (&optional arg))
+
+(declare-function org-element-interpret-data "org-element" (data))
+(declare-function org-element-property "org-element" (property element))
+(declare-function org-element-type "org-element" (element))
+
+(declare-function org-export-data "org-export" (data info))
+(declare-function org-export-derived-backend-p "org-export" (backend &rest 
backends))
+(declare-function org-export-raw-string "org-export" (contents))
+
+
+;;; Customization
+(defcustom org-cite-basic-sorting-field 'author
+  "Field used to sort bibliography items as a symbol, or nil."
+  :group 'org-cite
+  :package-version '(Org . "9.5")
+  :type 'symbol
+  :safe t)
+
+(defcustom org-cite-basic-author-year-separator ", "
+  "String used to separate cites in an author-year configuration."
+  :group 'org-cite
+  :package-version '(Org . "9.5")
+  :type 'string
+  :safe t)
+
+(defcustom org-cite-basic-max-key-distance 2
+  "Maximum (Levenshtein) distance between a wrong key and its suggestions."
+  :group 'org-cite
+  :package-version '(Org . "9.5")
+  :type 'integer
+  :safe t)
+
+(defcustom org-cite-basic-author-column-end 25
+  "Column where author field ends in completion table, as an integer."
+  :group 'org-cite
+  :package-version '(Org . "9.5")
+  :type 'integer
+  :safe t)
+
+(defcustom org-cite-basic-column-separator "  "
+  "Column separator in completion table, as a string."
+  :group 'org-cite
+  :package-version '(Org . "9.5")
+  :type 'string
+  :safe t)
+
+(defcustom org-cite-basic-mouse-over-key-face 'highlight
+  "Face used when mouse is over a citation key."
+  :group 'org-cite
+  :package-version '(Org . "9.5")
+  :type 'face
+  :safe t)
+
+
+;;; Internal variables
+(defvar org-cite-basic--bibliography-cache nil
+  "Cache for parsed bibliography files.
+
+This is an association list following the pattern:
+
+  (FILE-ID . ENTRIES)
+
+FILE-ID is a cons cell (FILE . HASH), with FILE being the absolute file name of
+the bibliography file, and HASH a hash of its contents.
+
+ENTRIES is a hash table with citation references as keys and fields alist as
+values.")
+
+(defvar org-cite-basic--completion-cache (make-hash-table :test #'equal)
+  "Cache for key completion table.
+
+This is an a hash-table.")
+
+
+;;; Internal functions
+(defun org-cite-basic--parse-json ()
+  "Parse JSON entries in the current buffer.
+Return a hash table with citation references as keys and fields alist as 
values."
+  (let ((entries (make-hash-table :test #'equal)))
+    (let ((json-array-type 'list)
+          (json-key-type 'symbol))
+      (dolist (item (json-read))
+        (puthash (cdr (assq 'id item))
+                 (mapcar (pcase-lambda (`(,field . ,value))
+                           (pcase field
+                             ('author
+                              ;; Author is an array of objects, each
+                              ;; of them designing a person.  These
+                              ;; objects may contain multiple
+                              ;; properties, but for this basic
+                              ;; processor, we'll focus on `given' and
+                              ;; `family'.
+                              ;;
+                              ;; For compatibility with BibTeX, add
+                              ;; "and" between authors.
+                              (cons 'author
+                                    (mapconcat
+                                     (lambda (alist)
+                                       (concat (alist-get 'family alist)
+                                               " "
+                                               (alist-get 'given alist)))
+                                     value
+                                     " and ")))
+                             ('issued
+                              ;; Date are expressed as an array
+                              ;; (`date-parts') or a "string (`raw').
+                              ;; In both cases, extract the year and
+                              ;; associate it to `year' field, for
+                              ;; compatibility with BibTeX format.
+                              (let ((date (or (alist-get 'date-parts value)
+                                              (alist-get 'raw value))))
+                                (cons 'year
+                                      (cond
+                                       ((consp date)
+                                        (caar date))
+                                       ((stringp date)
+                                        (car (split-string date "-")))
+                                       (t
+                                        (error "Unknown CSL-JSON date format: 
%S"
+                                               date))))))
+                             (_
+                              (cons field value))))
+                         item)
+                 entries))
+      entries)))
+
+(defun org-cite-basic--parse-bibtex (dialect)
+  "Parse BibTeX entries in the current buffer.
+DIALECT is the BibTeX dialect used.  See `bibtex-dialect'.
+Return a hash table with citation references as keys and fields alist as 
values."
+  (let ((entries (make-hash-table :test #'equal))
+        (bibtex-sort-ignore-string-entries t))
+    (bibtex-set-dialect dialect t)
+    (bibtex-map-entries
+     (lambda (key &rest _)
+       ;; Normalize entries: field names are turned into symbols
+       ;; including special "=key=" and "=type=", and consecutive
+       ;; white spaces are removed from values.
+       (puthash key
+                (mapcar
+                 (pcase-lambda (`(,field . ,value))
+                   (pcase field
+                     ("=key=" (cons 'id key))
+                     ("=type=" (cons 'type value))
+                     (_
+                      (cons
+                       (intern (downcase field))
+                       (replace-regexp-in-string "[ \t\n]+" " " value)))))
+                 (bibtex-parse-entry t))
+                entries)))
+    entries))
+
+(defun org-cite-basic--parse-bibliography (&optional info)
+  "List all entries available in the buffer.
+
+Each association follows the pattern
+
+  (FILE . ENTRIES)
+
+where FILE is the absolute file name of the BibTeX file, and ENTRIES is a hash
+table where keys are references and values are association lists between 
fields,
+as symbols, and values as strings or nil.
+
+Optional argument INFO is the export state, as a property list."
+  (if (plist-member info :cite-basic/bibliography)
+      (plist-get info :cite-basic/bibliography)
+    (let ((results nil))
+      (dolist (file (org-cite-list-bibliography-files))
+        (when (file-readable-p file)
+          (with-temp-buffer
+            (insert-file-contents file)
+           (let* ((file-id (cons file (org-buffer-hash)))
+                   (entries
+                    (or (cdr (assoc file-id 
org-cite-basic--bibliography-cache))
+                        (let ((table
+                               (pcase (file-name-extension file)
+                                 ("json" (org-cite-basic--parse-json))
+                                 ("bib" (org-cite-basic--parse-bibtex 
'biblatex))
+                                 ("bibtex" (org-cite-basic--parse-bibtex 
'BibTeX))
+                                 (ext
+                                  (user-error "Unknown bibliography extension: 
%S"
+                                              ext)))))
+                          (push (cons file-id table) 
org-cite-basic--bibliography-cache)
+                          table))))
+              (push (cons file entries) results)))))
+      (when info (plist-put info :cite-basic/bibliography results))
+      results)))
+
+(defun org-cite-basic--key-number (key info)
+  "Return number associated to cited KEY.
+INFO is the export state, as a property list."
+  (let ((predicate
+         (org-cite-basic--field-less-p org-cite-basic-sorting-field info)))
+    (org-cite-key-number key info predicate)))
+
+(defun org-cite-basic--all-keys ()
+  "List all keys available in current bibliography."
+  (seq-mapcat (pcase-lambda (`(,_ . ,entries))
+                (map-keys entries))
+              (org-cite-basic--parse-bibliography)))
+
+(defun org-cite-basic--get-entry (key &optional info)
+  "Return BibTeX entry for KEY, as an association list.
+When non-nil, INFO is the export state, as a property list."
+  (catch :found
+    (pcase-dolist (`(,_ . ,entries) (org-cite-basic--parse-bibliography info))
+      (let ((entry (gethash key entries)))
+        (when entry (throw :found entry))))
+    nil))
+
+(defun org-cite-basic--get-field (field entry-or-key &optional info raw)
+  "Return FIELD value for ENTRY-OR-KEY, or nil.
+
+FIELD is a symbol.  ENTRY-OR-KEY is either an association list, as returned by
+`org-cite-basic--get-entry', or a string representing a citation key.
+
+Optional argument INFO is the export state, as a property list.
+
+Return value may be nil or a string.  If current export back-end is derived
+from `latex', return a raw string instead, unless optional argument RAW is
+non-nil."
+  (let ((value
+         (cdr
+          (assq field
+                (pcase entry-or-key
+                  ((pred stringp)
+                   (org-cite-basic--get-entry entry-or-key info))
+                  ((pred consp)
+                   entry-or-key)
+                  (_
+                   (error "Wrong value for ENTRY-OR-KEY: %S" 
entry-or-key)))))))
+    (if (and value
+             (not raw)
+             (org-export-derived-backend-p (plist-get info :back-end) 'latex))
+        (org-export-raw-string value)
+      value)))
+
+(defun org-cite-basic--number-to-suffix (n)
+  "Compute suffix associated to number N.
+This is used for disambiguation."
+  (let ((result nil))
+    (apply #'string
+           (mapcar (lambda (n) (+ 97 n))
+                   (catch :complete
+                     (while t
+                       (push (% n 26) result)
+                       (setq n (/ n 26))
+                       (cond
+                        ((= n 0) (throw :complete result))
+                        ((< n 27) (throw :complete (cons (1- n) result)))
+                        ((= n 27) (throw :complete (cons 0 (cons 0 result))))
+                        (t nil))))))))
+
+(defun org-cite-basic--get-year (entry-or-key info)
+  "Return year associated to ENTRY-OR-KEY.
+
+ENTRY-OR-KEY is either an association list, as returned by
+`org-cite-basic--get-entry', or a string representing a citation key.  INFO is
+the export state, as a property list.
+
+Unlike `org-cite-basic--get-field', this function disambiguates author-year
+patterns."
+  ;; The cache is an association list with the following structure:
+  ;;
+  ;;    (AUTHOR-YEAR . KEY-SUFFIX-ALIST).
+  ;;
+  ;; AUTHOR-YEAR is the author year pair associated to current entry
+  ;; or key.
+  ;;
+  ;; KEY-SUFFIX-ALIST is an association (KEY . SUFFIX), where KEY is
+  ;; the cite key, as a string, and SUFFIX is the generated suffix
+  ;; string, or the empty string.
+  (let* ((author (org-cite-basic--get-field 'author entry-or-key info 'raw))
+         (year (org-cite-basic--get-field 'year entry-or-key info 'raw))
+         (cache-key (cons author year))
+         (key
+          (pcase entry-or-key
+            ((pred stringp) entry-or-key)
+            ((pred consp) (cdr (assq 'id entry-or-key)))
+            (_ (error "Wrong value for ENTRY-OR-KEY: %S" entry-or-key))))
+         (cache (plist-get info :cite-basic/author-date-cache)))
+    (pcase (assoc cache-key cache)
+      ('nil
+       (let ((value (cons cache-key (list (cons key "")))))
+         (plist-put info :cite-basic/author-date-cache (cons value cache))
+         year))
+      (`(,_ . ,alist)
+       (concat year
+               (or (cdr (assoc key alist))
+                   (let ((new (org-cite-basic--number-to-suffix (1- (length 
alist)))))
+                     (push (cons key new) alist)
+                     new)))))))
+
+(defun org-cite-basic--print-entry (entry style &optional info)
+  "Format ENTRY according to STYLE string.
+ENTRY is an alist, as returned by `org-cite-basic--get-entry'.
+Optional argument INFO is the export state, as a property list."
+  (let ((author (org-cite-basic--get-field 'author entry info))
+        (title (org-cite-basic--get-field 'title entry info))
+        (year (org-cite-basic--get-field 'year entry info))
+        (from
+         (or (org-cite-basic--get-field 'publisher entry info)
+             (org-cite-basic--get-field 'journal entry info)
+             (org-cite-basic--get-field 'institution entry info)
+             (org-cite-basic--get-field 'school entry info))))
+    (pcase style
+      ("plain"
+       (org-cite-concat
+        author ". " title (and from (list ", " from)) ", " year "."))
+      ("numeric"
+       (let ((n (org-cite-basic--key-number (cdr (assq 'id entry)) info)))
+         (org-cite-concat
+          (format "[%d] " n) author ", "
+          (org-cite-emphasize 'italic title)
+          (and from (list ", " from)) ", "
+          year ".")))
+      ;; Default to author-year.  Use year disambiguation there.
+      (_
+       (let ((year (org-cite-basic--get-year entry info)))
+         (org-cite-concat
+          author " (" year "). "
+          (org-cite-emphasize 'italic title)
+          (and from (list ", " from)) "."))))))
+
+
+;;; "Activate" capability
+(defun org-cite-basic--close-keys (key keys)
+  "List cite keys close to KEY in terms of string distance."
+  (seq-filter (lambda (k)
+                (>= org-cite-basic-max-key-distance
+                    (org-string-distance k key)))
+              keys))
+
+(defun org-cite-basic--set-keymap (beg end suggestions)
+  "Set keymap on citation key between BEG and END positions.
+
+When the key is know, SUGGESTIONS is nil.  Otherwise, it may be
+a list of replacement keys, as strings, which will be offered as
+substitutes for the unknown key.  Finally, it may be the symbol
+`all'."
+  (let ((km (make-sparse-keymap)))
+    (define-key km (kbd "<mouse-1>")
+      (pcase suggestions
+        ('nil #'org-open-at-point)
+        ('all #'org-cite-insert)
+        (_
+         (lambda ()
+           (interactive)
+           (setf (buffer-substring beg end)
+                 (concat "@"
+                         (if (= 1 (length suggestions))
+                             (car suggestions)
+                           (completing-read "Did you mean: "
+                                            suggestions nil t))))))))
+    (put-text-property beg end 'keymap km)))
+
+(defun org-cite-basic-activate (citation)
+  "Set various text properties on CITATION object.
+
+Fontify whole citation with `org-cite' face.  Fontify key with `error' face
+when it does not belong to known keys.  Otherwise, use `org-cite-key' face.
+
+Moreover, when mouse is on a known key, display the corresponding bibliography.
+On a wrong key, suggest a list of possible keys, and offer to substitute one of
+them with a mouse click."
+  (pcase-let ((`(,beg . ,end) (org-cite-boundaries citation))
+              (keys (org-cite-basic--all-keys)))
+    (put-text-property beg end 'font-lock-multiline t)
+    (add-face-text-property beg end 'org-cite)
+    (dolist (reference (org-cite-get-references citation))
+      (pcase-let* ((`(,beg . ,end) (org-cite-key-boundaries reference))
+                   (key (org-element-property :key reference)))
+        ;; Highlight key on mouse over.
+        (put-text-property beg end
+                           'mouse-face
+                           org-cite-basic-mouse-over-key-face)
+        (if (member key keys)
+            ;; Activate a correct key.  Face is `org-cite-key' and
+            ;; `help-echo' displays bibliography entry, for reference.
+            ;; <mouse-1> calls `org-open-at-point'.
+            (let* ((entry (org-cite-basic--get-entry key))
+                   (bibliography-entry
+                    (org-element-interpret-data
+                     (org-cite-basic--print-entry entry "plain"))))
+              (add-face-text-property beg end 'org-cite-key)
+              (put-text-property beg end 'help-echo bibliography-entry)
+              (org-cite-basic--set-keymap beg end nil))
+          ;; Activate a wrong key.  Face is `error', `help-echo'
+          ;; displays possible suggestions.
+          (add-face-text-property beg end 'error)
+          (let ((close-keys (org-cite-basic--close-keys key keys)))
+            (when close-keys
+              (put-text-property beg end 'help-echo
+                                 (concat "Suggestions (mouse-1 to substitute): 
"
+                                         (mapconcat #'identity close-keys " 
"))))
+            ;; When the are close know keys, <mouse-1> provides
+            ;; completion to fix the current one.  Otherwise, call
+            ;; `org-cite-insert'.
+            (org-cite-basic--set-keymap beg end (or close-keys 'all))))))))
+
+
+;;; "Export" capability
+(defun org-cite-basic--format-author-year (citation format-cite format-ref 
info)
+  "Format CITATION object according to author-year format.
+
+FORMAT-CITE is a function of three arguments: the global prefix, the contents,
+and the global suffix.  All arguments can be strings or secondary strings.
+
+FORMAT-REF is a function of four arguments: the reference prefix, as a string 
or
+secondary string, the author, the year, and the reference suffix, as a string 
or
+secondary string.
+
+INFO is the export state, as a property list."
+  (org-export-data
+   (funcall format-cite
+            (org-element-property :prefix citation)
+            (org-cite-mapconcat
+             (lambda (ref)
+               (let ((k (org-element-property :key ref))
+                     (prefix (org-element-property :prefix ref))
+                     (suffix (org-element-property :suffix ref)))
+                 (funcall format-ref
+                          prefix
+                          (org-cite-basic--get-field 'author k info)
+                          (org-cite-basic--get-year k info)
+                          suffix)))
+             (org-cite-get-references citation)
+             org-cite-basic-author-year-separator)
+            (org-element-property :suffix citation))
+   info))
+
+(defun org-cite-basic--citation-numbers (citation info)
+  "Return numbers associated to references in CITATION object.
+INFO is the export state as a property list."
+  (let* ((numbers
+          (sort (mapcar (lambda (k) (org-cite-basic--key-number k info))
+                        (org-cite-get-references citation t))
+                #'<))
+         (last (car numbers))
+         (result (list (number-to-string (pop numbers)))))
+    ;; Use compact number references, i.e., "1, 2, 3" becomes "1-3".
+    (while numbers
+      (let ((current (pop numbers))
+            (next (car numbers)))
+        (cond
+         ((and next
+               (= current (1+ last))
+               (= current (1- next)))
+          (unless (equal "-" (car result))
+            (push "-" result)))
+         ((equal "-" (car result))
+          (push (number-to-string current) result))
+         (t
+          (push (format ", %d" current) result)))
+        (setq last current)))
+    (apply #'concat (nreverse result))))
+
+(defun org-cite-basic--field-less-p (field info)
+  "Return a sort predicate comparing FIELD values for two citation keys.
+INFO is the export state, as a property list."
+  (and field
+       (lambda (a b)
+         (org-string-collate-lessp
+          (org-cite-basic--get-field field a info 'raw)
+          (org-cite-basic--get-field field b info 'raw)
+          nil t))))
+
+(defun org-cite-basic--sort-keys (keys info)
+  "Sort KEYS by author name.
+INFO is the export communication channel, as a property list."
+  (let ((predicate (org-cite-basic--field-less-p org-cite-basic-sorting-field 
info)))
+    (if predicate
+        (sort keys predicate)
+      keys)))
+
+(defun org-cite-basic-export-citation (citation style _ info)
+  "Export CITATION object.
+STYLE is the expected citation style, as a pair of strings or nil.  INFO is the
+export communication channel, as a property list."
+  (let ((has-variant-p
+         (lambda (variant type)
+           ;; Non-nil when style VARIANT has TYPE.  TYPE is either
+           ;; `bare' or `caps'.
+           (member variant
+                   (pcase type
+                     ('bare '("bare" "bare-caps" "b" "bc"))
+                     ('caps '("caps" "bare-caps" "c" "bc"))
+                     (_ (error "Invalid variant type: %S" type)))))))
+    (pcase style
+      ;; "author" style.
+      (`(,(or "author" "a") . ,variant)
+       (let ((caps (member variant '("caps" "c"))))
+         (org-export-data
+          (mapconcat
+           (lambda (key)
+             (let ((author (org-cite-basic--get-field 'author key info)))
+               (if caps (capitalize author) author)))
+           (org-cite-get-references citation t)
+           org-cite-basic-author-year-separator)
+          info)))
+      ;; "noauthor" style.
+      (`(,(or "noauthor" "na") . ,variant)
+       (format (if (funcall has-variant-p variant 'bare) "%s" "(%s)")
+               (mapconcat (lambda (key) (org-cite-basic--get-year key info))
+                          (org-cite-get-references citation t)
+                          org-cite-basic-author-year-separator)))
+      ;; "nocite" style.
+      (`(,(or "nocite" "n") . ,_) nil)
+      ;; "text" and "note" styles.
+      (`(,(and (or "text" "note" "t" "ft") style) . ,variant)
+       (when (and (member style '("note" "ft"))
+                  (not (org-cite-inside-footnote-p citation)))
+         (org-cite-adjust-note citation info)
+         (org-cite-wrap-citation citation info))
+       (let ((bare (funcall has-variant-p variant 'bare))
+             (caps (funcall has-variant-p variant 'caps)))
+         (org-cite-basic--format-author-year
+          citation
+          (lambda (p c s) (org-cite-concat p c s))
+          (lambda (p a y s)
+            (org-cite-concat p
+                             (if caps (capitalize a) a)
+                             (if bare " " " (")
+                             y s
+                             (and (not bare) ")")))
+          info)))
+      ;; "numeric" style.
+      ;;
+      ;; When using this style on citations with multiple references,
+      ;; use global affixes and ignore local ones.
+      (`(,(or "numeric" "nb") . ,_)
+       (let* ((references (org-cite-get-references citation))
+              (prefix
+               (or (org-element-property :prefix citation)
+                   (and (= 1 (length references))
+                        (org-element-property :prefix (car references)))))
+              (suffix
+               (or (org-element-property :suffix citation)
+                   (and (= 1 (length references))
+                        (org-element-property :suffix (car references))))))
+         (org-export-data
+          (org-cite-concat
+           "(" prefix (org-cite-basic--citation-numbers citation info) suffix 
")")
+          info)))
+      ;; Default ("nil") style.
+      (`(,_ . ,variant)
+       (let ((bare (funcall has-variant-p variant 'bare))
+             (caps (funcall has-variant-p variant 'caps)))
+         (org-cite-basic--format-author-year
+          citation
+          (lambda (p c s)
+            (org-cite-concat (and (not bare) "(") p c s (and (not bare) ")")))
+          (lambda (p a y s)
+            (org-cite-concat p (if caps (capitalize a) a) ", " y s))
+          info)))
+      ;; This should not happen.
+      (_ (error "Invalid style: %S" style)))))
+
+(defun org-cite-basic-export-bibliography (keys _files style _props backend 
info)
+  "Generate bibliography.
+KEYS is the list of cited keys, as strings.  STYLE is the expected bibliography
+style, as a string.  BACKEND is the export back-end, as a symbol.  INFO is the
+export state, as a property list."
+  (mapconcat
+   (lambda (k)
+     (let ((entry (org-cite-basic--get-entry k info)))
+       (org-export-data
+        (org-cite-make-paragraph
+         (and (org-export-derived-backend-p backend 'latex)
+              (org-export-raw-string "\\noindent\n"))
+         (org-cite-basic--print-entry entry style info))
+        info)))
+   (org-cite-basic--sort-keys keys info)
+   "\n"))
+
+
+;;; "Follow" capability
+(defun org-cite-basic-goto (datum _)
+  "Follow citation or citation reference DATUM.
+When DATUM is a citation reference, open bibliography entry referencing
+the citation key.  Otherwise, select which key to follow among all keys
+present in the citation."
+  (let* ((key
+          (if (eq 'citation-reference (org-element-type datum))
+              (org-element-property :key datum)
+            (pcase (org-cite-get-references datum t)
+              (`(,key) key)
+              (keys
+               (or (completing-read "Select citation key: " keys nil t)
+                   (user-error "Aborted"))))))
+         (file
+          (pcase (seq-find (pcase-lambda (`(,_ . ,entries))
+                             (gethash key entries))
+                           (org-cite-basic--parse-bibliography))
+            (`(,f . ,_) f)
+            (_  (user-error "Cannot find citation key: %S" key)))))
+    (org-open-file file '(4))
+    (pcase (file-name-extension file)
+      ("json"
+       ;; `rx' can not be used with Emacs <27.1 since `literal' form
+       ;; is not supported.
+       (let ((regexp (rx-to-string `(seq "\"id\":" (0+ (any "[ \t]")) "\"" 
,key "\"") t)))
+         (goto-char (point-min))
+         (re-search-forward regexp)
+         (search-backward "{")))
+      (_
+       (bibtex-set-dialect)
+       (bibtex-search-entry key)))))
+
+
+;;; "Insert" capability
+(defun org-cite-basic--complete-style (_)
+  "Offer completion for style.
+Return chosen style as a string."
+  (let* ((styles
+          (mapcar (pcase-lambda (`((,style . ,_) . ,_))
+                    style)
+                  (org-cite-supported-styles))))
+    (pcase styles
+      (`(,style) style)
+      (_ (completing-read "Style (\"\" for default): " styles nil t)))))
+
+(defun org-cite-basic--key-completion-table ()
+  "Return completion table for cite keys, as a hash table.
+In this hash table, keys are a strings with author, date, and title of the
+reference.  Values are the cite key."
+  (let ((cache-key (mapcar #'car org-cite-basic--bibliography-cache)))
+    (if (gethash cache-key org-cite-basic--completion-cache)
+        org-cite-basic--completion-cache
+      (clrhash org-cite-basic--completion-cache)
+      (dolist (key (org-cite-basic--all-keys))
+        (let ((completion
+               (concat
+                (let ((author (org-cite-basic--get-field 'author key nil t)))
+                  (if author
+                      (truncate-string-to-width
+                       (replace-regexp-in-string " and " "; " author)
+                       org-cite-basic-author-column-end nil ?\s)
+                    (make-string org-cite-basic-author-column-end ?\s)))
+                org-cite-basic-column-separator
+                (let ((date (org-cite-basic--get-field 'year key nil t)))
+                  (format "%4s" (or date "")))
+                org-cite-basic-column-separator
+                (org-cite-basic--get-field 'title key nil t))))
+          (puthash completion key org-cite-basic--completion-cache)))
+      (puthash cache-key t org-cite-basic--completion-cache)
+      org-cite-basic--completion-cache)))
+
+(defun org-cite-basic--complete-key (&optional multiple)
+  "Prompt for a reference key and return a citation reference string.
+
+When optional argument MULTIPLE is non-nil, prompt for multiple keys, until one
+of them is nil.  Then return the list of reference strings selected.
+
+Raise an error when no bibliography is set in the buffer."
+  (let* ((table
+          (or (org-cite-basic--key-completion-table)
+              (user-error "No bibliography set")))
+         (prompt
+          (lambda (text)
+            (completing-read text table nil t))))
+    (if (null multiple)
+        (let ((key (gethash (funcall prompt "Key: ") table)))
+          (org-string-nw-p key))
+      (let* ((keys nil)
+             (build-prompt
+              (lambda ()
+                (if keys
+                    (format "Key (\"\" to exit) %s: "
+                            (mapconcat #'identity (reverse keys) ";"))
+                  "Key (\"\" to exit): "))))
+        (let ((key (funcall prompt (funcall build-prompt))))
+          (while (org-string-nw-p key)
+            (push (gethash key table) keys)
+            (setq key (funcall prompt (funcall build-prompt)))))
+        keys))))
+
+
+;;; Register processor
+(org-cite-register-processor 'basic
+  :activate #'org-cite-basic-activate
+  :export-citation #'org-cite-basic-export-citation
+  :export-bibliography #'org-cite-basic-export-bibliography
+  :follow #'org-cite-basic-goto
+  :insert (org-cite-make-insert-processor #'org-cite-basic--complete-key
+                                          #'org-cite-basic--complete-style)
+  :cite-styles
+  '((("author" "a") ("caps" "c"))
+    (("noauthor" "na") ("bare" "b"))
+    (("nocite" "n"))
+    (("note" "ft") ("bare-caps" "bc") ("caps" "c"))
+    (("numeric" "nb"))
+    (("text" "t") ("bare-caps" "bc") ("caps" "c"))
+    (("nil") ("bare" "b") ("bare-caps" "bc") ("caps" "c"))))
+
+(provide 'oc-basic)
+;;; oc-basic.el ends here
diff --git a/lisp/oc-biblatex.el b/lisp/oc-biblatex.el
new file mode 100644
index 0000000..a27f9e9
--- /dev/null
+++ b/lisp/oc-biblatex.el
@@ -0,0 +1,319 @@
+;;; oc-biblatex.el --- biblatex citation processor for Org  -*- 
lexical-binding: t; -*-
+
+;; Copyright (C) 2021 Free Software Foundation, Inc.
+
+;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This library registers the `biblatex' citation processor, which provides
+;; the "export" capability for citations.
+
+;; The processor relies on "biblatex" LaTeX package.  As such it ensures that
+;; the package is properly required in the document's preamble.  More
+;; accurately, it will re-use any "\usepackage{biblatex}" already present in
+;; the document (e.g., through `org-latex-packages-alist'), or insert one using
+;; options defined in `org-cite-biblatex-options'.
+
+;; In any case, the library will override style-related options with those
+;; specified with the citation processor, in `org-cite-export-processors' or
+;; "cite_export" keyword.  If you need to use different styles for bibliography
+;; and citations, you can separate them with "bibstyle/citestyle" syntax.  
E.g.,
+;;
+;;   #+cite_export: biblatex authortitle/authortitle-ibid
+
+;; The library supports the following citation styles:
+;;
+;; - author (a), including caps (c), full (f) and caps-full (cf) variants,
+;; - locators (l), including bare (b), caps (c) and bare-caps (bc) variants,
+;; - noauthor (na),
+;; - nocite (n),
+;; - text (t), including caps (c) variant,
+;; - default style, including bare (b), caps (c) and bare-caps (bc) variants.
+
+;; When citation and style permit, the library automatically generates
+;; "multicite" versions of the commands above.
+
+;; Bibliography is printed using "\printbibliography" command.  Additional
+;; options may be passed to it through a property list attached to the
+;; "print_bibliography" keyword.  E.g.,
+;;
+;;    #+print_bibliography: :section 2 :heading subbibliography
+;;
+;; Values including spaces must be surrounded with double quotes.  If you need
+;; to use a key multiple times, you can separate its values with commas, but
+;; without any space in-between:
+;;
+;;    #+print_bibliography: :keyword abc,xyz :title "Primary Sources"
+
+;;; Code:
+(require 'org-macs)
+(require 'oc)
+
+(declare-function org-element-property "org-element" (property element))
+(declare-function org-export-data "org-export" (data info))
+(declare-function org-export-get-next-element "org-export" (blob info 
&optional n))
+
+
+;;; Customization
+(defcustom org-cite-biblatex-options nil
+  "Options added to \"biblatex\" package.
+If \"biblatex\" package is already required in the document, e.g., through
+`org-latex-packages-alist' variable, these options are ignored."
+  :group 'org-cite
+  :package-version '(Org . "9.5")
+  :type '(choice
+          (string :tag "Options (key=value,key2=value2...)")
+          (const :tag "No option" nil))
+  :safe t)
+
+
+;;; Internal functions
+(defun org-cite-biblatex--package-options (initial style)
+  "Return options string for \"biblatex\" package.
+
+INITIAL is an initial style of comma-separated options, as a string or nil.
+STYLE is the style definition as a string or nil.
+
+Return a string."
+  (let ((options-no-style
+         (and initial
+              (let ((re (rx string-start (or "bibstyle" "citestyle" "style"))))
+                (seq-filter
+                 (lambda (option) (not (string-match re option)))
+                 (split-string (org-unbracket-string "[" "]" initial)
+                               "," t " \t")))))
+        (style-options
+         (cond
+          ((null style) nil)
+          ((not (string-match "/" style)) (list (concat "style=" style)))
+          (t
+           (list (concat "bibstyle=" (substring style nil (match-beginning 0)))
+                 (concat "citestyle=" (substring style (match-end 0))))))))
+    (if (or options-no-style style-options)
+        (format "[%s]"
+                (mapconcat #'identity
+                           (append options-no-style style-options)
+                           ","))
+      "")))
+
+(defun org-cite-biblatex--multicite-p  (citation)
+  "Non-nil when citation could make use of a \"multicite\" command."
+  (let ((references (org-cite-get-references citation)))
+    (and (< 1 (length references))
+         (seq-some (lambda (r)
+                     (or (org-element-property :prefix r)
+                         (org-element-property :suffix r)))
+                   references))))
+
+(defun org-cite-biblatex--atomic-arguments (references info &optional no-opt)
+  "Build argument for the list of citation REFERENCES.
+When NO-OPT argument is non-nil, only provide mandatory arguments."
+  (let ((mandatory
+         (format "{%s}"
+                 (mapconcat (lambda (r) (org-element-property :key r))
+                            references
+                            ","))))
+    (if no-opt mandatory
+      (let* ((origin (pcase references
+                       (`(,reference) reference)
+                       (`(,reference . ,_)
+                        (org-element-property :parent reference))))
+             (suffix (org-element-property :suffix origin))
+             (prefix (org-element-property :prefix origin)))
+        (concat (and prefix
+                     (format "[%s]" (org-trim (org-export-data prefix info))))
+                (cond
+                 (suffix (format "[%s]"
+                                 (org-trim (org-export-data suffix info))))
+                 (prefix "[]")
+                 (t nil))
+                mandatory)))))
+
+(defun org-cite-biblatex--multi-arguments (citation info)
+  "Build \"multicite\" command arguments for CITATION object.
+INFO is the export state, as a property list."
+  (let ((global-prefix (org-element-property :prefix citation))
+        (global-suffix (org-element-property :suffix citation)))
+    (concat (and global-prefix
+                 (format "(%s)"
+                         (org-trim (org-export-data global-prefix info))))
+            (cond
+             ;; Global pre/post-notes.
+             (global-suffix
+              (format "(%s)"
+                      (org-trim (org-export-data global-suffix info))))
+             (global-prefix "()")
+             (t nil))
+            ;; All arguments.
+            (mapconcat (lambda (r)
+                         (org-cite-biblatex--atomic-arguments (list r) info))
+                       (org-cite-get-references citation)
+                       "")
+            ;; According to biblatex manual, left braces or brackets
+            ;; following a multicite command could be parsed as other
+            ;; arguments. So we look ahead and insert a \relax if
+            ;; needed.
+            (and (let ((next (org-export-get-next-element citation info)))
+                   (and next
+                        (string-match (rx string-start (or "{" "["))
+                                      (org-export-data next info))))
+                 "\\relax"))))
+
+(defun org-cite-biblatex--command (citation info base &optional multi no-opt)
+  "Return biblatex command using BASE name for CITATION object.
+
+INFO is the export state, as a property list.
+
+When optional argument MULTI is non-nil, generate a \"multicite\" command when
+appropriate.  When optional argument NO-OPT is non-nil, do not add optional
+arguments to the command."
+  (format "\\%s%s"
+          base
+          (if (and multi (org-cite-biblatex--multicite-p citation))
+              (concat "s" (org-cite-biblatex--multi-arguments citation info))
+            (org-cite-biblatex--atomic-arguments
+             (org-cite-get-references citation) info no-opt))))
+
+
+;;; Export capability
+(defun org-cite-biblatex-export-bibliography (_keys _files _style props &rest 
_)
+  "Print references from bibliography.
+PROPS is the local properties of the bibliography, as a property list."
+  (concat "\\printbibliography"
+          (and props
+               (let ((key nil)
+                     (results nil))
+                 (dolist (datum props)
+                   (cond
+                    ((keywordp datum)
+                     (when key (push key results))
+                     (setq key (substring (symbol-name datum) 1)))
+                    (t
+                     ;; Comma-separated values are associated to the
+                     ;; same keyword.
+                     (push (mapconcat (lambda (v) (concat key "=" v))
+                                      (split-string datum "," t)
+                                      ",")
+                           results)
+                     (setq key nil))))
+                 (format "[%s]"
+                         (mapconcat #'identity (nreverse results) ","))))))
+
+(defun org-cite-biblatex-export-citation (citation style _ info)
+  "Export CITATION object.
+STYLE is the citation style, as a string or nil.  INFO is the export state, as
+a property list."
+  (apply
+   #'org-cite-biblatex--command citation info
+   (pcase style
+     ;; "author" style.
+     (`(,(or "author" "a") . ,variant)
+      (pcase variant
+        ((or "caps" "c")            '("Citeauthor*"))
+        ((or "full" "f")            '("citeauthor"))
+        ((or "caps-full" "cf")      '("Citeauthor"))
+        (_                          '("citeauthor*"))))
+     ;; "locators" style.
+     (`(,(or "locators" "l") . ,variant)
+      (pcase variant
+        ((or "bare" "b")            '("notecite"))
+        ((or "caps" "c")            '("Pnotecite"))
+        ((or "bare-caps" "bc")      '("Notecite"))
+        (_                          '("pnotecite"))))
+     ;; "noauthor" style.
+     (`(,(or "noauthor" "na") . ,_) '("autocite*"))
+     ;; "nocite" style.
+     (`(,(or "nocite" "n") . ,_)    '("nocite" nil t))
+     ;; "text" style.
+     (`(,(or "text" "t") . ,variant)
+      (pcase variant
+        ((or "caps" "c")            '("Textcite" t))
+        (_                          '("textcite" t))))
+     ;; Default "nil" style.
+     (`(,_ . ,variant)
+      (pcase variant
+        ((or "bare" "b")            '("cite" t))
+        ((or "caps" "c")            '("Autocite" t))
+        ((or "bare-caps" "bc")      '("Cite" t))
+        (_                          '("autocite" t))))
+     ;; This should not happen.
+     (_ (error "Invalid style: %S" style)))))
+
+(defun org-cite-biblatex-prepare-preamble (output _keys files style &rest _)
+  "Prepare document preamble for \"biblatex\" usage.
+
+OUTPUT is the final output of the export process.  FILES is the list of file
+names used as the bibliography.
+
+This function ensures \"biblatex\" package is required.  It also adds resources
+to the document, and set styles."
+  (with-temp-buffer
+    (save-excursion (insert output))
+    (when (search-forward "\\begin{document}" nil t)
+      ;; Ensure there is a \usepackage{biblatex} somewhere or add one.
+      ;; Then set options.
+      (goto-char (match-beginning 0))
+      (let ((re (rx "\\usepackage"
+                    (opt (group "[" (*? anything) "]"))
+                    "{biblatex}")))
+        (cond
+         ;; No "biblatex" package loaded.  Insert "usepackage" command
+         ;; with appropriate options, including style.
+         ((not (re-search-backward re nil t))
+          (save-excursion
+            (insert
+             (format "\\usepackage%s{biblatex}\n"
+                     (org-cite-biblatex--package-options
+                      org-cite-biblatex-options style)))))
+         ;; "biblatex" package loaded, but without any option.
+         ;; Include style only.
+         ((not (match-beginning 1))
+          (search-forward "{" nil t)
+          (insert (org-cite-biblatex--package-options nil style)))
+         ;; "biblatex" package loaded with some options set.  Override
+         ;; style-related options with ours.
+         (t
+          (replace-match
+           (save-match-data
+             (org-cite-biblatex--package-options (match-string 1) style))
+           nil nil nil 1))))
+      ;; Insert resources below.
+      (forward-line)
+      (insert (mapconcat (lambda (f)
+                           (format "\\addbibresource%s{%s}"
+                                   (if (org-url-p f) "[location=remote]" "")
+                                   f))
+                         files
+                         "\n")
+              "\n"))
+    (buffer-string)))
+
+
+;;; Register `biblatex' processor
+(org-cite-register-processor 'biblatex
+  :export-bibliography #'org-cite-biblatex-export-bibliography
+  :export-citation #'org-cite-biblatex-export-citation
+  :export-finalizer #'org-cite-biblatex-prepare-preamble
+  :cite-styles
+  '((("author" "a") ("caps" "c") ("full" "f") ("caps-full" "cf"))
+    (("locators" "l") ("bare" "b") ("caps" "c") ("bare-caps" "bc"))
+    (("noauthor" "na"))
+    (("text" "t") ("caps" "c"))
+    (("nil") ("bare" "b") ("caps" "c") ("bare-caps" "bc"))))
+
+(provide 'oc-biblatex)
+;;; oc-biblatex.el ends here
diff --git a/lisp/oc-csl.el b/lisp/oc-csl.el
new file mode 100644
index 0000000..50df121
--- /dev/null
+++ b/lisp/oc-csl.el
@@ -0,0 +1,612 @@
+;;; oc-csl.el --- csl citation processor for Org -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021 Free Software Foundation, Inc.
+
+;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This library registers the `csl' citation processor, which provides
+;; the "export" capability for citations.
+
+;; The processor relies on the external Citeproc Emacs library, which must be
+;; available prior to loading this library.
+
+;; By default, citations are rendered in Chicago author-date CSL style.  You 
can
+;; use another style file by specifying it in `org-cite-export-processors' or
+;; from within the document by adding the file name to "cite_export" keyword
+;;
+;;    #+cite_export: csl /path/to/style-file.csl
+;;    #+cite_export: csl "/path/to/style-file.csl"
+;;
+;; With the variable `org-cite-csl-styles-dir' set appropriately, the
+;; above can even be shortened to
+;;
+;;     #+cite_export: csl style-file.csl
+;;
+;; Styles can be downloaded, for instance, from the Zotero Style Repository
+;; (<https://www.zotero.org/styles>).  Dependent styles (which are not "unique"
+;; in the Zotero Style Repository terminology) are not supported.
+
+;; The processor uses the "en-US" CSL locale file shipped with Org for 
rendering
+;; localized dates and terms in the references, independently of the language
+;; settings of the Org document.  Additional CSL locales can be made available
+;; by setting `org-cite-csl-locales-dir' to a directory containing the locale
+;; files in question (see <https://github.com/citation-style-language/locales>
+;; for such files).
+
+;; Bibliography is defined with the "bibliography" keyword.  It supports files
+;; with ".bib", ".bibtex", and ".json" extensions.  References are exported 
using
+;; the "print_bibliography" keyword.
+
+;; The library supports the following citation styles:
+;;
+;; - author (a), including caps (c), full (f), and caps-full (cf) variants,
+;; - noauthor (na), including bare (b), caps (c) and bare-caps (bc) variants,
+;; - year (y), including a bare (b) variant,
+;; - text (t). including caps (c), full (f), and caps-full (cf) variants,
+;; - default style, including bare (b), caps (c) and bare-caps (bc) variants.
+
+;; CSL styles recognize "locator" in citation references' suffix.  For example,
+;; in the citation
+;;
+;;     [cite:see @Tarski-1965 chapter 1, for an example]
+;;
+;; "chapter 1" is the locator.  The whole citation is rendered as
+;;
+;;     (see Tarski 1965, chap. 1 for an example)
+;;
+;; in the default CSL style.
+;;
+;; The locator starts with a locator term, among "bk.", "bks.", "book", 
"chap.",
+;; "chaps.", "chapter", "col.", "cols.", "column", "figure", "fig.", "figs.",
+;; "folio", "fol.", "fols.", "number", "no.", "nos.", "line", "l.", "ll.",
+;; "note", "n.", "nn.", "opus", "op.", "opp.", "page", "p.", "pp.", 
"paragraph",
+;; "para.", "paras.", "ยถ", "ยถยถ", "ยง", "ยงยง", "part", "pt.", "pts.", "section",
+;; "sec.", "secs.", "sub verbo", "s.v.", "s.vv.", "verse", "v.", "vv.",
+;; "volume", "vol.", and "vols.".  It ends with the last comma or digit in the
+;; suffix, whichever comes last, or runs till the end of the suffix.
+;;
+;; The part of the suffix before the locator is appended to reference's prefix.
+;; If no locator term is used, but a number is present, then "page" is assumed.
+
+;; This library was heavily inspired by and borrows from Andrรกs Simonyi's
+;; Citeproc Org (<https://github.com/andras-simonyi/citeproc-org>) library.
+;; Many thanks to him!
+
+;;; Code:
+(require 'bibtex)
+(require 'json)
+(require 'oc)
+
+(require 'citeproc nil t)
+(declare-function citeproc-style-cite-note "ext:citeproc")
+(declare-function citeproc-proc-style "ext:citeproc")
+(declare-function citeproc-bt-entry-to-csl "ext:citeproc")
+(declare-function citeproc-locale-getter-from-dir "ext:citeproc")
+(declare-function citeproc-create "ext:citeproc")
+(declare-function citeproc-citation-create "ext:citeproc")
+(declare-function citeproc-append-citations "ext:citeproc")
+(declare-function citeproc-render-citations "ext:citeproc")
+(declare-function citeproc-render-bib "ext:citeproc")
+(declare-function citeproc-hash-itemgetter-from-any "ext:citeproc")
+
+(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-property "org-element" (property element))
+(declare-function org-element-put-property "org-element" (element property 
value))
+
+(declare-function org-export-data "org-export" (data info))
+(declare-function org-export-derived-backend-p "org-export" (backend &rest 
backends))
+(declare-function org-export-get-footnote-number "org-export" (footnote info 
&optional data body-first))
+
+
+;;; Customization
+
+;;;; Location of CSL directories
+(defcustom org-cite-csl-locales-dir nil
+  "Directory of CSL locale files.
+If nil then only the fallback en-US locale will be available."
+  :group 'org-cite
+  :package-version '(Org . "9.5")
+  :type '(choice
+          (dir :tag "Locales directory")
+          (const :tag "Use en-US locale only" nil))
+  :safe t)
+
+(defcustom org-cite-csl-styles-dir nil
+  "Directory of CSL style files.
+When non-nil, relative style file names are expanded relatively to this
+directory.  This variable is ignored when style file is absolute."
+  :group 'org-cite
+  :package-version '(Org . "9.5")
+  :type '(choice
+          (dir :tag "Styles directory")
+          (const :tag "Use absolute file names" nil))
+  :safe t)
+
+;;;; Citelinks
+(defcustom org-cite-csl-link-cites t
+  "When non-nil, link cites to references."
+  :group 'org-cite
+  :package-version '(Org . "9.5")
+  :type 'boolean
+  :safe t)
+
+(defcustom org-cite-csl-no-citelinks-backends '(ascii)
+  "List of export back-ends for which cite linking is disabled.
+Cite linking for export back-ends derived from any of the back-ends listed 
here,
+is also disabled."
+  :group 'org-cite
+  :package-version '(Org . "9.5")
+  :type '(repeat symbol)
+  :safe t)
+
+;;;; Output-specific variables
+(defcustom org-cite-csl-html-hanging-indent "1.5em"
+  "Size of hanging-indent for HTML output in valid CSS units."
+  :group 'org-cite
+  :package-version '(Org . "9.5")
+  :type 'string
+  :safe t)
+
+(defcustom org-cite-csl-html-label-width-per-char "0.6em"
+  "Character width in CSS units for calculating entry label widths.
+Used only when `second-field-align' is activated by the used CSL style."
+  :group 'org-cite
+  :package-version '(Org . "9.5")
+  :type 'string
+  :safe t)
+
+(defcustom org-cite-csl-latex-hanging-indent "1.5em"
+  "Size of hanging-indent for LaTeX output in valid LaTeX units."
+  :group 'org-cite
+  :package-version '(Org . "9.5")
+  :type 'string
+  :safe t)
+
+
+;;; Internal variables
+(defconst org-cite-csl--etc-dir
+  (let* ((oc-root (file-name-directory (locate-library "oc")))
+         (oc-etc-dir-1 (expand-file-name "../etc/csl/" oc-root)))
+    ;; package.el and straight will put all of org-mode/lisp/ in org-mode/.
+    ;; This will cause .. to resolve to the directory above Org.
+    ;; To make life easier for people using package.el or straight, we can
+    ;; check to see if ../etc/csl exists, and if it doesn't try ./etc/csl.
+    (if (file-exists-p oc-etc-dir-1) oc-etc-dir-1
+      (expand-file-name "etc/csl/" oc-root)))
+  "Directory \"etc/\" from repository.")
+
+(defconst org-cite-csl--fallback-locales-dir org-cite-csl--etc-dir
+  "Fallback CSL locale files directory.")
+
+(defconst org-cite-csl--fallback-style-file
+  (expand-file-name "chicago-author-date.csl"
+                    org-cite-csl--etc-dir)
+  "Default CSL style file, or nil.
+If nil then the Chicago author-date style is used as a fallback.")
+
+(defconst org-cite-csl--label-alist
+  '(("bk."       . "book")
+    ("bks."      . "book")
+    ("book"      . "book")
+    ("chap."     . "chapter")
+    ("chaps."    . "chapter")
+    ("chapter"   . "chapter")
+    ("col."      . "column")
+    ("cols."     . "column")
+    ("column"    . "column")
+    ("figure"    . "figure")
+    ("fig."      . "figure")
+    ("figs."     . "figure")
+    ("folio"     . "folio")
+    ("fol."      . "folio")
+    ("fols."     . "folio")
+    ("number"    . "number")
+    ("no."       . "number")
+    ("nos."      . "number")
+    ("line"      . "line")
+    ("l."        . "line")
+    ("ll."       . "line")
+    ("note"      . "note")
+    ("n."        . "note")
+    ("nn."       . "note")
+    ("opus"      . "opus")
+    ("op."       . "opus")
+    ("opp."      . "opus")
+    ("page"      . "page")
+    ("p"         . "page")
+    ("p."        . "page")
+    ("pp."       . "page")
+    ("paragraph" . "paragraph")
+    ("para."     . "paragraph")
+    ("paras."    . "paragraph")
+    ("ยถ"         . "paragraph")
+    ("ยถยถ"        . "paragraph")
+    ("ยง"         . "paragraph")
+    ("ยงยง"        . "paragraph")
+    ("part"      . "part")
+    ("pt."       . "part")
+    ("pts."      . "part")
+    ("section"   . "section")
+    ("sec."      . "section")
+    ("secs."     . "section")
+    ("sub verbo" . "sub verbo")
+    ("s.v."      . "sub verbo")
+    ("s.vv."     . "sub verbo")
+    ("verse"     . "verse")
+    ("v."        . "verse")
+    ("vv."       . "verse")
+    ("volume"    . "volume")
+    ("vol."      . "volume")
+    ("vols."     . "volume"))
+  "Alist mapping locator names to locators.")
+
+(defconst org-cite-csl--label-regexp
+  ;; Prior to Emacs-27.1 argument of `regexp' form must be a string literal.
+  ;; It is the reason why `rx' is avoided here.
+  (rx-to-string `(seq word-start
+                      (regexp ,(regexp-opt (mapcar #'car 
org-cite-csl--label-alist) t))
+                      (0+ digit)
+                      (or word-start line-end (any ?\s ?\t)))
+                t)
+  "Regexp matching a label in a citation reference suffix.
+Label is in match group 1.")
+
+
+;;; Internal functions
+(defun org-cite-csl--barf-without-citeproc ()
+  "Raise an error if Citeproc library is not loaded."
+  (unless (featurep 'citeproc) "Citeproc library is not loaded"))
+
+(defun org-cite-csl--note-style-p (info)
+  "Non-nil when bibliography style implies wrapping citations in footnotes.
+INFO is the export state, as a property list."
+  (citeproc-style-cite-note
+   (citeproc-proc-style
+    (org-cite-csl--processor info))))
+
+(defun org-cite-csl--create-structure-params (citation info)
+  "Return citeproc structure creation params for CITATION object.
+STYLE is the citation style, as a string or nil. INFO is the export state, as
+a property list."
+  (let ((style (org-cite-citation-style citation info)))
+    (pcase style
+      ;; "author" style.
+      (`(,(or "author" "a") . ,variant)
+       (pcase variant
+        ((or "caps" "c") '(:mode author-only :capitalize-first t))
+        ((or "full" "f") '(:mode author-only :ignore-et-al t))
+        ((or "caps-full" "cf") '(:mode author-only :capitalize-first t 
:ignore-et-al t))
+        (_ '(:mode author-only))))
+      ;; "noauthor" style.
+      (`(,(or "noauthor" "na") . ,variant)
+       (pcase variant
+        ((or "bare" "b") '(:mode suppress-author :suppress-affixes t))
+        ((or "caps" "c") '(:mode suppress-author :capitalize-first t))
+        ((or "bare-caps" "bc")
+          '(:mode suppress-author :suppress-affixes t :capitalize-first t))
+        (_ '(:mode suppress-author))))
+      ;; "year" style.
+      (`(,(or "year" "y") . ,variant)
+       (pcase variant
+        ((or "bare" "b") '(:mode year-only :suppress-affixes t))
+        (_ '(:mode year-only))))
+      ;; "text" style.
+      (`(,(or "text" "t") . ,variant)
+       (pcase variant
+         ((or "caps" "c") '(:mode textual :capitalize-first t))
+         ((or "full" "f") '(:mode textual :ignore-et-al t))
+         ((or "caps-full" "cf") '(:mode textual :ignore-et-al t 
:capitalize-first t))
+         (_ '(:mode textual))))
+      ;; Default "nil" style.
+      (`(,_ . ,variant)
+       (pcase variant
+         ((or "caps" "c") '(:capitalize-first t))
+         ((or "bare" "b") '(:suppress-affixes t))
+         ((or "bare-caps" "bc") '(:suppress-affixes t :capitalize-first t))
+         (_  nil)))
+      ;; This should not happen.
+      (_ (error "Invalid style: %S" style)))))
+
+(defun org-cite-csl--no-citelinks-p (info)
+  "Non-nil when export BACKEND should not create cite-reference links."
+  (or (not org-cite-csl-link-cites)
+      (and org-cite-csl-no-citelinks-backends
+           (apply #'org-export-derived-backend-p
+                  (plist-get info :back-end)
+                  org-cite-csl-no-citelinks-backends))
+      ;; No references are being exported anyway.
+      (not (org-element-map (plist-get info :parse-tree) 'keyword
+             (lambda (k)
+               (equal "PRINT_BIBLIOGRAPHY" (org-element-property :key k)))
+             info t))))
+
+(defun org-cite-csl--output-format (info)
+  "Return expected Citeproc's output format.
+INFO is the export state, as a property list.  The return value is a symbol
+corresponding to one of the output formats supported by Citeproc: `html',
+`latex', or `org'."
+  (let ((backend (plist-get info :back-end)))
+    (cond
+     ((org-export-derived-backend-p backend 'html) 'html)
+     ((org-export-derived-backend-p backend 'latex) 'latex)
+     (t 'org))))
+
+(defun org-cite-csl--style-file (info)
+  "Return style file associated to current export process.
+
+INFO is the export state, as a property list.
+
+When file name is relative, expand it according to `org-cite-csl-styles-dir',
+or raise an error if the variable is unset."
+  (pcase (org-cite-bibliography-style info)
+    ('nil org-cite-csl--fallback-style-file)
+    ((and (pred file-name-absolute-p) file) file)
+    ((and (guard org-cite-csl-styles-dir) file)
+     (expand-file-name file org-cite-csl-styles-dir))
+    (other
+     (user-error "Cannot handle relative style file name" other))))
+
+(defun org-cite-csl--locale-getter ()
+  "Return a locale getter.
+The getter looks for locales in `org-cite-csl-locales-dir' directory.  If it
+cannot find them, it retrieves the default \"en_US\" from
+`org-cite-csl--fallback-locales-dir'."
+  (lambda (loc)
+    (or (and org-cite-csl-locales-dir
+             (ignore-errors
+               (funcall (citeproc-locale-getter-from-dir 
org-cite-csl-locales-dir)
+                        loc)))
+        (funcall (citeproc-locale-getter-from-dir
+                  org-cite-csl--fallback-locales-dir)
+                 loc))))
+
+(defun org-cite-csl--processor (info)
+  "Return Citeproc processor reading items from current bibliography.
+
+INFO is the export state, as a property list.
+
+Newly created processor is stored as the value of the 
`:cite-citeproc-processor'
+property in INFO."
+  (or (plist-get info :cite-citeproc-processor)
+      (let* ((bibliography (plist-get info :bibliography))
+             (locale (or (plist-get info :language) "en_US"))
+             (processor
+              (citeproc-create
+               (org-cite-csl--style-file info)
+               (citeproc-hash-itemgetter-from-any bibliography)
+               (org-cite-csl--locale-getter)
+               locale)))
+        (plist-put info :cite-citeproc-processor processor)
+        processor)))
+
+(defun org-cite-csl--parse-reference (reference info)
+  "Return Citeproc's structure associated to citation REFERENCE.
+
+INFO is the export state, as a property list.
+
+The result is a association list.  Keys are: `id', `prefix',`suffix',
+`location', `locator' and `label'."
+  (let (label location-start locator-start location locator prefix suffix)
+    ;; Parse suffix.  Insert it in a temporary buffer to find
+    ;; different parts: pre-label, label, locator, location (label +
+    ;; locator), and suffix.
+    (with-temp-buffer
+      (save-excursion
+        (insert (org-element-interpret-data
+                 (org-element-property :suffix reference))))
+      (cond
+       ((re-search-forward org-cite-csl--label-regexp nil t)
+        (setq location-start (match-beginning 0))
+        (setq label (cdr (assoc (match-string 1) org-cite-csl--label-alist)))
+        (setq locator-start (match-end 1)))
+       ((re-search-forward (rx digit) nil t)
+        (setq location-start (match-beginning 0))
+        (setq label "page")
+        (setq locator-start location-start))
+       (t
+        (setq suffix (org-element-property :suffix reference))))
+      ;; Find locator's end, and suffix, if any. To that effect, look
+      ;; for the last comma or digit after label, whichever comes
+      ;; last.
+      (unless suffix
+        (goto-char (point-max))
+        (let ((re (rx (or "," (group digit)))))
+          (when (re-search-backward re location-start t)
+            (goto-char (or (match-end 1) (match-beginning 0)))
+            (setq location (buffer-substring location-start (point)))
+            (setq locator (org-trim (buffer-substring locator-start (point))))
+            ;; Skip comma in suffix.
+            (setq suffix
+                  (org-cite-parse-objects
+                   (buffer-substring (match-end 0) (point-max))
+                   t)))))
+      (setq prefix
+            (org-cite-concat
+             (org-element-property :prefix reference)
+             (and location-start
+                  (org-cite-parse-objects
+                   (buffer-substring 1 location-start)
+                   t)))))
+    ;; Return value.
+    (let ((export
+           (lambda (data)
+             (org-string-nw-p
+              (org-trim
+               ;; When Citeproc exports to Org syntax, avoid mix and
+               ;; matching output formats by also generating Org
+               ;; syntax for prefix and suffix.
+               (if (eq 'org (org-cite-csl--output-format info))
+                   (org-element-interpret-data data)
+                 (org-export-data data info)))))))
+      `((id . ,(org-element-property :key reference))
+        (prefix . ,(funcall export prefix))
+        (suffix . ,(funcall export suffix))
+        (locator . ,locator)
+        (label . ,label)
+        (location . ,location)))))
+
+(defun org-cite-csl--create-structure (citation info)
+  "Create Citeproc structure for CITATION object.
+INFO is the export state, as a property list."
+  (let* ((cites (mapcar (lambda (r)
+                          (org-cite-csl--parse-reference r info))
+                        (org-cite-get-references citation)))
+         (footnote (org-cite-inside-footnote-p citation)))
+    ;; Global prefix is inserted in front of the prefix of the first
+    ;; reference.
+    (let ((global-prefix (org-element-property :prefix citation)))
+      (when global-prefix
+        (let* ((first (car cites))
+               (prefix (org-element-property :prefix first)))
+          (org-element-put-property
+           first :prefix (org-cite-concat global-prefix prefix)))))
+    ;; Global suffix is appended to the suffix of the last reference.
+    (let ((global-suffix (org-element-property :suffix citation)))
+      (when global-suffix
+        (let* ((last (org-last cites))
+               (suffix (org-element-property :suffix last)))
+          (org-element-put-property
+           last :suffix (org-cite-concat suffix global-suffix)))))
+    ;; Check if CITATION needs wrapping, i.e., it should be wrapped in
+    ;; a footnote, but isn't yet.
+    (when (and (not footnote) (org-cite-csl--note-style-p info))
+      (org-cite-adjust-note citation info)
+      (org-cite-wrap-citation citation info))
+    ;; Return structure.
+    (apply #'citeproc-citation-create
+           `(:note-index
+             ,(and footnote (org-export-get-footnote-number footnote info))
+             :cites ,cites
+             ,@(org-cite-csl--create-structure-params citation info)))))
+
+(defun org-cite-csl--rendered-citations (info)
+  "Return the rendered citations as an association list.
+
+INFO is the export state, as a property list.
+
+Return an alist (CITATION . OUTPUT) where CITATION object has been rendered as
+OUTPUT using Citeproc."
+  (or (plist-get info :cite-citeproc-rendered-citations)
+      (let* ((citations (org-cite-list-citations info))
+             (processor (org-cite-csl--processor info))
+             (structures
+              (mapcar (lambda (c) (org-cite-csl--create-structure c info))
+                      citations)))
+        (citeproc-append-citations structures processor)
+        (let* ((rendered
+                (citeproc-render-citations
+                 processor
+                 (org-cite-csl--output-format info)
+                 (org-cite-csl--no-citelinks-p info)))
+               (result (seq-mapn #'cons citations rendered)))
+          (plist-put info :cite-citeproc-rendered-citations result)
+          result))))
+
+
+;;; Export capability
+(defun org-cite-csl-render-citation (citation _style _backend info)
+  "Export CITATION object.
+INFO is the export state, as a property list."
+  (org-cite-csl--barf-without-citeproc)
+  (let ((output (cdr (assq citation (org-cite-csl--rendered-citations info)))))
+    (if (not (eq 'org (org-cite-csl--output-format info)))
+        output
+      ;; Parse Org output to re-export it during the regular export
+      ;; process.
+      (org-cite-parse-objects output))))
+
+(defun org-cite-csl-render-bibliography (_keys _files _style _props _backend 
info)
+  "Export bibliography.
+INFO is the export state, as a property list."
+  (org-cite-csl--barf-without-citeproc)
+  (pcase-let* ((format (org-cite-csl--output-format info))
+               (`(,output . ,parameters)
+                (citeproc-render-bib
+                 (org-cite-csl--processor info)
+                 format
+                 (org-cite-csl--no-citelinks-p info))))
+    (pcase format
+      ('html
+       (concat
+        (and (cdr (assq 'second-field-align parameters))
+             (let* ((max-offset (cdr (assq 'max-offset parameters)))
+                    (char-width
+                     (string-to-number org-cite-csl-html-label-width-per-char))
+                    (char-width-unit
+                     (progn
+                       (string-match (number-to-string char-width)
+                                     org-cite-csl-html-label-width-per-char)
+                       (substring org-cite-csl-html-label-width-per-char
+                                  (match-end 0)))))
+               (format
+                "<style>.csl-left-margin{float: left; padding-right: 0em;}
+ .csl-right-inline{margin: 0 0 0 %d%s;}</style>"
+                (* max-offset char-width)
+                char-width-unit)))
+        (and (cdr (assq 'hanging-indent parameters))
+             (format
+              "<style>.csl-entry{text-indent: -%s; margin-left: %s;}</style>"
+              org-cite-csl-html-hanging-indent
+              org-cite-csl-html-hanging-indent))
+        output))
+      ('latex
+       (if (cdr (assq 'hanging-indent parameters))
+           (format "\\begin{hangparas}{%s}{1}\n%s\n\\end{hangparas}"
+                   org-cite-csl-latex-hanging-indent
+                   output)
+         output))
+      (_
+       ;; Parse Org output to re-export it during the regular export
+       ;; process.
+       (org-cite-parse-elements output)))))
+
+(defun org-cite-csl-finalizer (output _keys _files _style _backend info)
+  "Add \"hanging\" package if missing from LaTeX output.
+OUTPUT is the export document, as a string.  INFO is the export state, as a
+property list."
+  (org-cite-csl--barf-without-citeproc)
+  (if (not (eq 'latex (org-cite-csl--output-format info)))
+      output
+    (with-temp-buffer
+      (save-excursion (insert output))
+      (when (search-forward "\\begin{document}" nil t)
+        ;; Ensure that \citeprocitem is defined for citeproc-el
+        (insert 
"\\makeatletter\n\\newcommand{\\citeprocitem}[2]{\\hyper@linkstart{cite}{citeproc_bib_item_#1}#2\\hyper@linkend}\n\\makeatother\n\n")
+        ;; Ensure there is a \usepackage{hanging} somewhere or add one.
+        (goto-char (match-beginning 0))
+        (let ((re (rx "\\usepackage" (opt "[" (*? nonl) "]") "{hanging}")))
+          (unless (re-search-backward re nil t)
+            (insert "\\usepackage[notquote]{hanging}\n"))))
+      (buffer-string))))
+
+
+;;; Register `csl' processor
+(org-cite-register-processor 'csl
+  :export-citation #'org-cite-csl-render-citation
+  :export-bibliography #'org-cite-csl-render-bibliography
+  :export-finalizer #'org-cite-csl-finalizer
+  :cite-styles
+  '((("author" "a") ("full" "f") ("caps" "c") ("caps-full" "cf"))
+    (("noauthor" "na") ("bare" "b") ("caps" "c") ("bare-caps" "bc"))
+    (("year" "y") ("bare" "b"))
+    (("text" "t") ("caps" "c") ("full" "f") ("caps-full" "cf"))
+    (("nil") ("bare" "b") ("caps" "c") ("bare-caps" "bc"))))
+
+(provide 'oc-csl)
+;;; oc-csl.el ends here
diff --git a/lisp/oc-natbib.el b/lisp/oc-natbib.el
new file mode 100644
index 0000000..7e2127b
--- /dev/null
+++ b/lisp/oc-natbib.el
@@ -0,0 +1,196 @@
+;;; oc-natbib.el --- Citation processor using natbib LaTeX package  -*- 
lexical-binding: t; -*-
+
+;; Copyright (C) 2021 Free Software Foundation, Inc.
+
+;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This library registers the `natbib' citation processor, which provides the
+;; "export" capability for citations.
+
+;; The processor relies on "natbib" LaTeX package.  As such it ensures that the
+;; package is properly required in the document's preamble.  More accurately, 
it
+;; will use any "\\usepackage{natbib}" command already present in the document
+;; (e.g., through `org-latex-packages-alist'), or insert one using options
+;; defined in `org-cite-natbib-options'.
+
+;; It supports the following citation styles:
+;;
+;; - author (a), including caps (c), and full (f) variants,
+;; - noauthor (na), including bare (b) variant,
+;; - text (t), including bare (b), caps (c), full (f), bare-caps (bc),
+;;   bare-full (bf), caps-full (cf), and bare-caps-full (bcf) variants,
+;; - default, including bare (b), caps (c), full (f), bare-caps (bc),
+;;   bare-full (bf), caps-full (cf), and bare-caps-full (bcf) variants.
+
+;; Bibliography accepts any style supported by "natbib" package.
+
+;;; Code:
+(require 'oc)
+
+(declare-function org-element-property "org-element" (property element))
+
+(declare-function org-export-data "org-export" (data info))
+
+
+;;; Customization
+(defcustom org-cite-natbib-options nil
+  "List of options added to \"natbib\" package.
+If \"natbib\" package is already required in the document, e.g., through
+`org-latex-packages-alist' variable, these options are ignored."
+  :group 'org-cite
+  :package-version '(Org . "9.5")
+  :type
+  '(set
+    (const :tag "use round parentheses (default)" round)
+    (const :tag "use square brackets" square)
+    (const :tag "use curly braces" curly)
+    (const :tag "use angle brackets" angle)
+    (const :tag "separate multiple citations with colons (default)" colon)
+    (const :tag "separate multiple citations with comas" comma)
+    (const :tag "generate author-year citations" authoryear)
+    (const :tag "generate numerical citations" numbers)
+    (const :tag "generate superscripted numerical citations" super)
+    (const :tag "order multiple citations according to the list of references" 
sort)
+    (const :tag "order as above, but numerical citations are compressed if 
possible" sort&compress)
+    (const :tag "display full author list on first citation, abbreviate the 
others" longnamesfirst)
+    (const :tag "redefine \\thebibliography to issue \\section* instead of 
\\chapter*" sectionbib)
+    (const :tag "keep all the authors' names in a citation on one line" 
nonamebreak))
+  :safe t)
+
+
+;;; Internal functions
+(defun org-cite-natbib--style-to-command (style)
+  "Return command name to use according to STYLE pair."
+  (pcase style
+    ;; "author" style.
+    (`(,(or "author" "a") . ,variant)
+     (pcase variant
+       ((or "caps" "c")             "\\Citeauthor")
+       ((or "full" "f")             "\\citeauthor*")
+       (_                           "\\citeauthor")))
+    ;; "noauthor" style.
+    (`(,(or "noauthor" "na") . ,variant)
+     (pcase variant
+       ((or "bare" "b")             "\\citeyear")
+       (_                           "\\citeyearpar")))
+    ;; "nocite" style.
+    (`(,(or "nocite" "n") . ,_)     "\\nocite")
+    ;; "text" style.
+    (`(,(or "text" "t") . ,variant)
+     (pcase variant
+       ((or "bare" "b")             "\\citealt")
+       ((or "caps" "c")             "\\Citet")
+       ((or "full" "f")             "\\citet*")
+       ((or "bare-caps" "bc")       "\\Citealt")
+       ((or "bare-full" "bf")       "\\citealt*")
+       ((or "caps-full" "cf")       "\\Citet*")
+       ((or "bare-caps-full" "bcf") "\\Citealt*")
+       (_ "\\citet")))
+    ;; Default ("nil") style.
+    (`(,_ . ,variant)
+     (pcase variant
+       ((or "bare" "b")             "\\citealp")
+       ((or "caps" "c")             "\\Citep")
+       ((or "full" "f")             "\\citep*")
+       ((or "bare-caps" "bc")       "\\Citealp")
+       ((or "bare-full" "bf")       "\\citealp*")
+       ((or "caps-full" "cf")       "\\Citep*")
+       ((or "bare-caps-full" "bcf") "\\Citealp*")
+       (_                           "\\citep")))
+    ;; This should not happen.
+    (_ (error "Invalid style: %S" style))))
+
+(defun org-cite-natbib--build-optional-arguments (citation info)
+  "Build optional arguments for citation command.
+CITATION is the citation object.  INFO is the export state, as a property 
list."
+  (let* ((origin (pcase (org-cite-get-references citation)
+                   (`(,reference) reference)
+                   (_ citation)))
+         (suffix (org-element-property :suffix origin))
+         (prefix (org-element-property :prefix origin)))
+    (concat (and prefix (format "[%s]" (org-trim (org-export-data prefix 
info))))
+            (cond
+             (suffix (format "[%s]" (org-trim (org-export-data suffix info))))
+             (prefix "[]")
+             (t nil)))))
+
+(defun org-cite-natbib--build-arguments (citation)
+  "Build arguments for citation command for CITATION object."
+  (format "{%s}"
+          (mapconcat #'identity
+                     (org-cite-get-references citation t)
+                     ",")))
+
+
+;;; Export capability
+(defun org-cite-natbib-export-bibliography (_keys files style &rest _)
+  "Print references from bibliography FILES.
+FILES is a list of absolute file names.  STYLE is the bibliography style, as
+a string or nil."
+  (concat (and style (format "\\bibliographystyle{%s}\n" style))
+          (format "\\bibliography{%s}"
+                  (mapconcat #'file-name-sans-extension
+                             files
+                             ","))))
+
+(defun org-cite-natbib-export-citation (citation style _ info)
+  "Export CITATION object.
+STYLE is the citation style, as a pair of strings or nil.  INFO is the export
+state, as a property list."
+  (concat (org-cite-natbib--style-to-command style)
+          (org-cite-natbib--build-optional-arguments citation info)
+          (org-cite-natbib--build-arguments citation)))
+
+(defun org-cite-natbib-use-package (output &rest _)
+  "Ensure output requires \"natbib\" package.
+OUTPUT is the final output of the export process."
+  (with-temp-buffer
+    (save-excursion (insert output))
+    (when (search-forward "\\begin{document}" nil t)
+      ;; Ensure there is a \usepackage{natbib} somewhere or add one.
+      (goto-char (match-beginning 0))
+      (let ((re (rx "\\usepackage" (opt "[" (*? nonl) "]") "{natbib}")))
+        (unless (re-search-backward re nil t)
+          (insert
+           (format "\\usepackage%s{natbib}\n"
+                   (if (null org-cite-natbib-options)
+                       ""
+                     (format "[%s]"
+                             (mapconcat #'symbol-name
+                                        org-cite-natbib-options
+                                        ","))))))))
+    (buffer-string)))
+
+
+;;; Register `natbib' processor
+(org-cite-register-processor 'natbib
+  :export-bibliography #'org-cite-natbib-export-bibliography
+  :export-citation #'org-cite-natbib-export-citation
+  :export-finalizer #'org-cite-natbib-use-package
+  :cite-styles
+  '((("author" "a") ("caps" "a") ("full" "f"))
+    (("noauthor" "na") ("bare" "b"))
+    (("text" "t")
+     ("bare" "b") ("caps" "c") ("full" "f") ("bare-caps" "bc")
+     ("bare-full" "bf") ("caps-full" "cf") ("bare-caps-full" "bcf"))
+    (("nil")
+     ("bare" "b") ("caps" "c") ("full" "f") ("bare-caps" "bc")
+     ("bare-full" "bf") ("caps-full" "cf") ("bare-caps-full" "bcf"))))
+
+(provide 'oc-natbib)
+;;; oc-natbib.el ends here
diff --git a/lisp/oc.el b/lisp/oc.el
new file mode 100644
index 0000000..eb2b7a1
--- /dev/null
+++ b/lisp/oc.el
@@ -0,0 +1,1608 @@
+;;; oc.el --- Org Cite library                  -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021 Free Software Foundation, Inc.
+
+;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This library provides tooling to handle citations in Org, e.g,
+;; activate, follow, insert, and export them, respectively called
+;; "activate", "follow", "insert" and "export" capabilities.
+;; Libraries responsible for providing some, or all, of these
+;; capabilities are called "citation processors".
+
+;; Such processors are defined using `org-cite-register-processor'.
+;; Using this function, it is possible, in addition to giving it a
+;; name, to attach functions associated to capabilities.  As such, a
+;; processor handling citation export must set the `:export-citation'
+;; property to an appropriate function.  Likewise, "activate"
+;; capability requires an appropriate `:activate' property, "insert"
+;; requires `:insert' property and, unsurprisingly, "follow"
+;; capability implies `:follow' property.
+
+;; As a user, the first thing to do is setting a bibliography, either
+;; globally with `org-cite-global-bibliography', or locally using one
+;; or more "bibliography" keywords.  Then one can select any
+;; registered processor for each capability by providing a processor
+;; name to the variables `org-cite-activate-processor' and
+;; `org-cite-follow-processor'.
+
+;; The "export" capability is slightly more involved as one need to
+;; select the processor providing it, but may also provide a default
+;; style for citations and bibliography.  Also, the choice of an
+;; export processor may depend of the current export back-end.  The
+;; association between export back-ends and triplets of parameters can
+;; be set in `org-cite-export-processors' variable, or in a document,
+;; through the "cite_export" keyword.
+
+;; Eventually, this library provides some tools, mainly targeted at
+;; processor implementors.  Most are export-specific and are located
+;; in the "Tools only available during export" and "Tools generating
+;; or operating on parsed data" sections.
+
+;; The few others can be used directly from an Org buffer, or operate
+;; on processors.  See "Generic tools" section.
+
+;;; Code:
+
+(require 'org-compat)
+(require 'org-macs)
+(require 'seq)
+
+(declare-function org-at-heading-p "org" (&optional _))
+(declare-function org-collect-keywords "org" (keywords &optional unique 
directory))
+
+(declare-function org-element-adopt-elements "org-element" (parent &rest 
children))
+(declare-function org-element-citation-parser "org-element" ())
+(declare-function org-element-citation-reference-parser "org-element" ())
+(declare-function org-element-class "org-element" (datum &optional parent))
+(declare-function org-element-contents "org-element" (element))
+(declare-function org-element-create "org-element" (type &optional props &rest 
children))
+(declare-function org-element-extract-element "org-element" (element))
+(declare-function org-element-insert-before "org-element" (element location))
+(declare-function org-element-lineage "org-element" (datum &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-normalize-string "org-element" (s))
+(declare-function org-element-parse-buffer "org-element" (&optional 
granularity visible-only))
+(declare-function org-element-parse-secondary-string "org-element" (string 
restriction &optional parent))
+(declare-function org-element-context "org-element" (&optional element))
+(declare-function org-element-property "org-element" (property element))
+(declare-function org-element-put-property "org-element" (element property 
value))
+(declare-function org-element-restriction "org-element" (element))
+(declare-function org-element-set-element "org-element" (old new))
+(declare-function org-element-type "org-element" (element))
+
+(declare-function org-export-derived-backend-p "org-export" (backend &rest 
backends))
+(declare-function org-export-get-footnote-definition "org-export" 
(footnote-reference info))
+(declare-function org-export-get-next-element "org-export" (blob info 
&optional n))
+(declare-function org-export-get-previous-element "org-export" (blob info 
&optional n))
+(declare-function org-export-raw-string "org-export" (s))
+
+(defvar org-complex-heading-regexp)
+(defvar org-element-all-objects)
+(defvar org-element-citation-key-re)
+(defvar org-element-citation-prefix-re)
+(defvar org-element-parsed-keywords)
+
+
+;;; Constants
+;; Borrowed from "citeproc.el" library.
+(defconst org-cite--default-region-alist
+  '(("af" . "za") ("ca" . "ad") ("cs" . "cz") ("cy" . "gb")
+    ("da" . "dk") ("el" . "gr") ("et" . "ee") ("fa" . "ir")
+    ("he" . "ir") ("ja" . "jp") ("km" . "kh") ("ko" . "kr")
+    ("nb" . "no") ("nn" . "no") ("sl" . "si") ("sr" . "rs")
+    ("sv" . "se") ("uk" . "ua") ("vi" . "vn") ("zh" . "cn"))
+  "Alist mapping those languages to their default region.
+Only those languages are given for which the default region is not simply the
+result of duplicating the language part.")
+
+
+;;; Configuration variables
+(defgroup org-cite nil
+  "Options concerning citations in Org mode."
+  :group 'org
+  :tag "Org Cite")
+
+(defcustom org-cite-global-bibliography nil
+  "List of bibliography files available in all documents.
+File names must be absolute."
+  :group 'org-cite
+  :package-version '(Org . "9.5")
+  :type '(choice (const :tag "No global bibliography" nil)
+                (repeat :tag "List of bibliography files"
+                         (file :tag "Bibliography")))
+  :safe t)
+
+(defcustom org-cite-activate-processor 'basic
+  "Processor used for activating citations, as a symbol."
+  :group 'org-cite
+  :package-version '(Org . "9.5")
+  :type '(choice (const :tag "Default fontification" nil)
+                 (symbol :tag "Citation processor"))
+  :safe nil)
+
+(defcustom org-cite-export-processors '((t basic))
+  "Processor used for exporting citations, as a triplet, or nil.
+
+When nil, citations and bibliography are not exported.
+
+When non-nil, the value is an association list between export back-ends and
+citation export processors:
+
+  (BACK-END . PROCESSOR)
+
+where BACK-END is the name of an export back-end or t, and PROCESSOR is a
+triplet following the pattern
+
+  (NAME BIBLIOGRAPHY-STYLE CITATION-STYLE)
+
+There, NAME is the name of a registered citation processor providing export
+functionality, as a symbol.  BIBLIOGRAPHY-STYLE (resp. CITATION-STYLE) is the
+desired default style to use when printing a bibliography (resp. exporting a
+citation), as a string or nil.  Both BIBLIOGRAPHY-STYLE and CITATION-STYLE are
+optional.  NAME is mandatory.
+
+The export process selects the citation processor associated to the current
+export back-end, or the most specific back-end the current one is derived from,
+or, if all are inadequate, to the processor associated to t.  For example, with
+the following value
+
+  ((beamer natbib)
+   (latex biblatex)
+   (t csl))
+
+exporting with `beamer' or any back-end derived from it will use `natbib',
+whereas exporting with `latex' or any back-end derived from it but different
+from `beamer' will use `biblatex' processor.  Any other back-end, such as
+`html', will use `csl' processor.
+
+CITATION-STYLE is overridden by adding a style to any citation object.  A nil
+style lets the export processor choose the default output.  Any style not
+recognized by the export processor is equivalent to nil.
+
+The citation triplet can also be set with the CITE_EXPORT keyword.
+E.g.,
+
+  #+CITE_EXPORT: basic note numeric
+
+or
+
+  #+CITE_EXPORT: basic
+
+In that case, `basic' processor is used on every export, independently on the
+back-end."
+  :group 'org-cite
+  :package-version '(Org . "9.5")
+  :type '(choice (const :tag "No export" nil)
+                 (alist :key-type symbol
+                        :value-type
+                        (list :tag "Citation processor"
+                              (symbol :tag "Processor name")
+                              (choice
+                               (const :tag "Default bibliography style" nil)
+                               (string :tag "Use specific bibliography style"))
+                              (choice
+                               (const :tag "Default citation style" nil)
+                               (string :tag "Use specific citation style")))))
+  :safe nil)
+
+(defcustom org-cite-follow-processor 'basic
+  "Processor used for following citations, as a symbol."
+  :group 'org-cite
+  :package-version '(Org . "9.5")
+  :type '(choice (const :tag "No following" nil)
+                 (symbol :tag "Citation processor"))
+  :safe nil)
+
+(defcustom org-cite-insert-processor 'basic
+  "Processor used for inserting citations, as a symbol."
+  :group 'org-cite
+  :package-version '(Org . "9.5")
+  :type '(choice (const :tag "No insertion" nil)
+                 (symbol :tag "Citation processor"))
+  :safe nil)
+
+(defcustom org-cite-adjust-note-numbers t
+  "When non-nil, allow process to modify location of note numbers.
+
+When this variable is non-nil, it is possible to swap between author-date and
+note style without modifying the document.  To that effect, citations should
+always be located as in an author-date style.  Prior to turning the citation
+into a footnote, the citation processor moves the citation (i.e., the future
+note number), and the surrounding punctuation, according to rules defined in
+`org-cite-note-rules'.
+
+When nil, the note number is not moved."
+  :group 'org-cite
+  :package-version '(Org . "9.5")
+  :type '(choice (const :tag "Automatic note number location" t)
+                 (const :tag "Place note numbers manually" nil))
+  :safe t)
+
+(defcustom org-cite-note-rules
+  '(("en-us" inside outside after)
+    ("fr" adaptive same before))
+  "Alist between languages and typographic rules for citations in note style.
+
+When `org-cite-adjust-note-numbers' is non-nil, and note style is requested,
+citation processor is allowed to move the note marker according to some 
specific
+rules, detailed here.  More accurately, a rule is a list following the pattern
+
+    (LANGUAGE-TAG . RULE)
+
+  LANGUAGE-TAG is a down-cased string representing a language tag as defined in
+  RFC 4646.  It may constituted of a language and a region separated with an
+  hyphen (e.g., \"en-us\"), or the language alone (e.g., \"fr\").  A language
+  without a region applies to all regions.
+
+  RULE is a triplet
+
+    (PUNCTUATION NUMBER ORDER)
+
+  PUNCTUATION is the desired location of the punctuation with regards to the
+  quotation, if any.  It may be `inside', `outside', or `adaptive'.  The latter
+  permits subtler control over the punctuation: when there is no space between
+  the quotation mark and the punctuation, it is equivalent to `inside'.
+  Otherwise, it means `outside', as illustrated in the following examples:
+
+      \"A quotation ending without punctuation\" [cite:@org21].
+      \"A quotation ending with a period\"[cite:@org21].
+
+  Notwithstanding the above, a space always appear before the citation when it
+  is to become anything else than a note.
+
+  NUMBER is the desired location of the note number with regards to the
+  quotation mark, if any.  It may be `inside', `outside', or `same'.  When set
+  to `same', the number appears on the same side as the punctuation, unless
+  there is punctuation on both sides or on none.
+
+  ORDER is the relative position of the citation with regards to the closest
+  punctuation.  It may be `after' or `before'.
+
+For example (adaptive same before) corresponds to French typography.
+
+When the locale is unknown to this variable, the default rule is:
+
+  (adaptive outside after)
+
+This roughly follows the Oxford Guide to Style recommendations."
+  :group 'org-cite
+  :package-version '(Org . "9.5")
+  :type
+  '(repeat
+    (list :tag "Typographic rule"
+          (string :tag "Language code")
+          (choice :tag "Location of punctuation"
+                  (const :tag "Punctuation inside quotation" inside)
+                  (const :tag "Punctuation outside quotation" outside)
+                  (const :tag "Location depends on spacing" adaptive))
+          (choice :tag "Location of citation"
+                  (const :tag "Citation inside quotation" inside)
+                  (const :tag "Citation outside quotation" outside)
+                  (const :tag "Citation next to punctuation" same))
+          (choice :tag "Order of citation and punctuation"
+                  (const :tag "Citation first" before)
+                  (const :tag "Citation last" after))))
+  :safe t)
+
+(defcustom org-cite-punctuation-marks '("." "," ";" ":" "!" "?")
+  "List of strings that can be moved around when placing note numbers.
+
+When `org-cite-adjust-note-numbers' is non-nil, the citation processor is
+allowed to shuffle punctuation marks specified in this list in order to
+place note numbers according to rules defined in `org-cite-note-rules'."
+  :group 'org-cite
+  :package-version '(Org . "9.5")
+  :type '(repeat string)
+  :safe t)
+
+
+;;; Citation processors
+(cl-defstruct (org-cite-processor (:constructor org-cite--make-processor)
+                                 (:copier nil))
+  (name nil :read-only t)
+  (activate nil :read-only t)
+  (cite-styles nil :read-only t)
+  (export-bibliography nil :read-only t)
+  (export-citation nil :read-only t)
+  (export-finalizer nil :read-only t)
+  (follow nil :read-only t)
+  (insert nil :read-only t))
+
+(defvar org-cite--processors nil
+  "List of registered citation processors.
+See `org-cite-register-processor' for more information about
+processors.")
+
+(defun org-cite--get-processor (name)
+  "Return citation processor named after symbol NAME.
+Return nil if no such processor is found."
+  (seq-find (lambda (p) (eq name (org-cite-processor-name p)))
+           org-cite--processors))
+
+(defun org-cite-register-processor (name &rest body)
+  "Mark citation processor NAME as available.
+
+NAME is a symbol.  BODY is a property list, where the following
+optional keys can be set:
+
+  `:activate'
+
+    Function activating a citation.  It is called with a single
+    argument: a citation object extracted from the current
+    buffer.  It may add text properties to the buffer.  If it is
+    not provided, `org-cite-fontify-default' is used.
+
+  `:export-bibliography'
+
+    Function rendering a bibliography.  It is called with six
+    arguments: the list of citation keys used in the document, as
+    strings, a list of bibliography files, the style, as a string
+    or nil, the local properties, as a property list, the export
+    back-end, as a symbol, and the communication channel, as a
+    property list.
+
+    It is called at each \"print_bibliography\" keyword in the
+    parse tree.  It may return a string, a parsed element, a list
+    of parsed elements, or nil.  When it returns nil, the keyword
+    is ignored.  Otherwise, the value it returns replaces the
+    keyword in the export output.
+
+  `:export-citation'    (mandatory for \"export\" capability)
+
+    Function rendering citations.  It is called with four
+    arguments: a citation object, the style, as a pair, the
+    export back-end, as a symbol, and the communication channel,
+    as a property list.
+
+    It is called on each citation object in the parse tree.  It
+    may return a string, a parsed object, a secondary string, or
+    nil.  When it returns nil, the citation is ignored.
+    Otherwise, the value it returns replaces the citation object
+    in the export output.
+
+  `:export-finalizer'
+
+    Function called at the end of export process.  It must accept
+    six arguments: the output, as a string, a list of citation
+    keys used in the document, a list of bibliography files, the
+    expected bibliography style, as a string or nil, the export
+    back-end, as a symbol, and the communication channel, as a
+    property list.
+
+    It must return a string, which will become the final output
+    from the export process, barring subsequent modifications
+    from export filters.
+
+  `:follow'
+
+    Function called to follow a citation.  It accepts two
+    arguments, the citation or citation reference object at
+    point, and any prefix argument received during interactive
+    call of `org-open-at-point'.
+
+  `:insert'
+
+    Function called to insert a citation.  It accepts two
+    arguments, the citation or citation reference object at point
+    or nil, and any prefix argument received.
+
+  `:cite-styles'
+
+    When the processor has export capability, the value can
+    specify what cite styles, variants, and their associated
+    shortcuts are supported.  It can be useful information for
+    completion or linting.
+
+    The expected format is
+
+      ((STYLE . SHORTCUTS) . VARIANTS))
+
+    where STYLE is a string, SHORTCUTS a list of strings or nil,
+    and VARIANTS is a list of pairs (VARIANT . SHORTCUTS),
+    VARIANT being a string and SHORTCUTS a list of strings or
+    nil.
+
+    The \"nil\" style denotes the processor fall-back style.  It
+    should have a corresponding entry in the value.
+
+Return a non-nil value on a successful operation."
+  (declare (indent 1))
+  (unless (and name (symbolp name))
+    (error "Invalid processor name: %S" name))
+  (when (org-cite--get-processor name)
+    (org-cite-unregister-processor name))
+  (push (apply #'org-cite--make-processor :name name body)
+       org-cite--processors))
+
+(defun org-cite-unregister-processor (name)
+  "Unregister citation processor NAME.
+NAME is a symbol.  Raise an error if processor is not registered.
+Return a non-nil value on a successful operation."
+  (unless (and name (symbolp name))
+    (error "Invalid processor name: %S" name))
+  (pcase (org-cite--get-processor name)
+    ('nil (error "Processor %S not registered" name))
+    (processor
+     (setq org-cite--processors (delete processor org-cite--processors))))
+  t)
+
+(defun org-cite-processor-has-capability-p (processor capability)
+  "Return non-nil if PROCESSOR is able to handle CAPABILITY.
+PROCESSOR is the name of a cite processor, as a symbol.  CAPABILITY is
+`activate', `export', `follow', or `insert'."
+  (let ((p (org-cite--get-processor processor)))
+    (pcase capability
+      ((guard (not p)) nil)             ;undefined processor
+      ('activate (functionp (org-cite-processor-activate p)))
+      ('export (functionp (org-cite-processor-export-citation p)))
+      ('follow (functionp (org-cite-processor-follow p)))
+      ('insert (functionp (org-cite-processor-insert p)))
+      (other (error "Invalid capability: %S" other)))))
+
+
+;;; Internal functions
+(defun org-cite--set-post-blank (datum blanks)
+  "Set `:post-blank' property from element or object before DATUM to BLANKS.
+DATUM is an element or object.  BLANKS is an integer.  DATUM is modified
+by side-effect."
+  (if (not (eq 'plain-text (org-element-type datum)))
+      (org-element-put-property datum :post-blank blanks)
+    ;; Remove any blank from string before DATUM so it is exported
+    ;; with exactly BLANKS white spaces.
+    (org-element-set-element
+     datum
+     (replace-regexp-in-string
+      "[ \t\n]*\\'" (make-string blanks ?\s) datum))))
+
+(defun org-cite--set-previous-post-blank (datum blanks info)
+  "Set `:post-blank' property from element or object before DATUM to BLANKS.
+DATUM is an element or object.  BLANKS is an integer.  INFO is the export
+state, as a property list.  Previous element or object, if any, is modified by
+side-effect."
+  (let ((previous (org-export-get-previous-element datum info)))
+    (when previous
+      (org-cite--set-post-blank previous blanks))))
+
+(defun org-cite--insert-at-split (s citation n regexp)
+  "Split string S and insert CITATION object between the two parts.
+S is split at beginning of match group N upon matching REGEXP against it.
+This function assumes S precedes CITATION."
+  ;; When extracting the citation, remove white spaces before it, but
+  ;; preserve those after it.
+  (let ((post-blank (org-element-property :post-blank citation)))
+    (when (and post-blank (> post-blank 0))
+      (org-element-insert-before (make-string post-blank ?\s) citation)))
+  (org-element-insert-before
+   (org-element-put-property (org-element-extract-element citation)
+                             :post-blank 0)
+   s)
+  (string-match regexp s)
+  (let* ((split (match-beginning n))
+         (first-part (substring s nil split))
+         ;; Remove trailing white spaces as they are before the
+         ;; citation.
+         (last-part
+          (replace-regexp-in-string (rx (1+ (any blank ?\n)) string-end)
+                                    ""
+                                    (substring s split))))
+    (when (org-string-nw-p first-part)
+      (org-element-insert-before first-part citation))
+    (org-element-set-element s last-part)))
+
+(defun org-cite--move-punct-before (punct citation s info)
+  "Move punctuation PUNCT before CITATION object.
+String S contains PUNCT.  The function assumes S follows CITATION.
+Parse tree is modified by side-effect."
+  (if (equal s punct)
+      (org-element-extract-element s)   ;it would be empty anyway
+    (org-element-set-element s (substring s (length punct))))
+  ;; Remove blanks before citation.
+  (org-cite--set-previous-post-blank citation 0 info)
+  (org-element-insert-before
+   ;; Blanks between citation and punct are now before punct and
+   ;; citation.
+   (concat (make-string (or (org-element-property :post-blank citation) 0) ?\s)
+           punct)
+   citation))
+
+(defun org-cite--parse-as-plist (s)
+  "Parse string S as a property list.
+Values are always strings.  Return nil if S is nil."
+  (cond
+   ((null s) nil)
+   ((stringp s)
+    (with-temp-buffer
+      (save-excursion (insert s))
+      (skip-chars-forward " \t")
+      (let ((results nil)
+            (value-flag nil))
+        (while (not (eobp))
+          (pcase (char-after)
+            (?:
+             (push (read (current-buffer)) results)
+             (setq value-flag t))
+            ((guard (not value-flag))
+             (skip-chars-forward "^ \t"))
+            (?\"
+             (let ((origin (point)))
+               (condition-case _
+                   (progn
+                     (read (current-buffer))
+                     (push (buffer-substring (1+ origin) (1- (point))) 
results))
+                 (end-of-file
+                  (goto-char origin)
+                  (skip-chars-forward "^ \t")
+                  (push (buffer-substring origin (point)) results)))
+               (setq value-flag nil)))
+            (_
+             (let ((origin (point)))
+               (skip-chars-forward "^ \t")
+               (push (buffer-substring origin (point)) results)
+               (setq value-flag nil))))
+          (skip-chars-forward " \t"))
+        (nreverse results))))
+   (t (error "Invalid argument type: %S" s))))
+
+(defun org-cite--get-note-rule (info)
+  "Return punctuation rule according to language used for export.
+
+INFO is the export state, as a property list.
+
+Rule is found according to the language used for export and
+`org-cite-note-rules', which see.
+
+If there is no rule matching current language, the rule defaults
+to (adaptive outside after)."
+  (let* ((language-tags
+          ;; Normalize language as a language-region tag, as described
+          ;; in RFC 4646.
+          (pcase (split-string (plist-get info :language) "[-_]")
+            (`(,language)
+             (list language
+                   (or (cdr (assoc language org-cite--default-region-alist))
+                       language)))
+            (`(,language ,region)
+             (list language region))
+            (other
+             (error "Invalid language identifier: %S" other))))
+         (language-region (mapconcat #'downcase language-tags "-"))
+         (language (car language-tags)))
+    (or (cdr (assoc language-region org-cite-note-rules))
+        (cdr (assoc language org-cite-note-rules))
+        '(adaptive outside after))))
+
+
+;;; Generic tools
+(defun org-cite-list-bibliography-files ()
+  "List all bibliography files defined in the buffer."
+  (delete-dups
+   (append (mapcar (lambda (value)
+                    (pcase value
+                      (`(,f . ,d)
+                        (expand-file-name (org-strip-quotes f) d))))
+                  (pcase (org-collect-keywords
+                           '("BIBLIOGRAPHY") nil '("BIBLIOGRAPHY"))
+                    (`(("BIBLIOGRAPHY" . ,pairs)) pairs)))
+          org-cite-global-bibliography)))
+
+(defun org-cite-get-references (citation &optional keys-only)
+  "Return citations references contained in CITATION object.
+
+When optional argument KEYS-ONLY is non-nil, return the references' keys, as a
+list of strings.
+
+Assume CITATION object comes from either a full parse tree, e.g., during 
export,
+or from the current buffer."
+  (let ((contents (org-element-contents citation)))
+    (cond
+     ((null contents)
+      (org-with-point-at (org-element-property :contents-begin citation)
+        (narrow-to-region (point) (org-element-property :contents-end 
citation))
+        (let ((references nil))
+          (while (not (eobp))
+            (let ((reference (org-element-citation-reference-parser)))
+              (goto-char (org-element-property :end reference))
+              (push (if keys-only
+                        (org-element-property :key reference)
+                      reference)
+                    references)))
+          (nreverse references))))
+     (keys-only (mapcar (lambda (r) (org-element-property :key r)) contents))
+     (t contents))))
+
+(defun org-cite-boundaries (citation)
+  "Return the beginning and end strict position of CITATION.
+Returns a (BEG . END) pair."
+  (let ((beg (org-element-property :begin citation))
+       (end (org-with-point-at (org-element-property :end citation)
+              (skip-chars-backward " \t")
+              (point))))
+    (cons beg end)))
+
+(defun org-cite-key-boundaries (reference)
+  "Return citation REFERENCE's key boundaries as buffer positions.
+The function returns a pair (START . END) where START and END denote positions
+in the current buffer.  Positions include leading \"@\" character."
+  (org-with-point-at (org-element-property :begin reference)
+    (let ((end (org-element-property :end reference)))
+      (re-search-forward org-element-citation-key-re end t)
+      (cons (match-beginning 0) (match-end 0)))))
+
+(defun org-cite-supported-styles (&optional processors)
+  "List of supported citation styles and variants.
+
+Supported styles are those handled by export processors from
+`org-cite-export-processors', or in PROCESSORS, as a list of symbols,
+when non-nil.
+
+Return value is a list with the following items:
+
+  ((STYLE . SHORTCUTS) . VARIANTS))
+
+where STYLE is a string, SHORTCUTS a list of strings, and VARIANTS is a list of
+pairs (VARIANT . SHORTCUTS), VARIANT being a string and SHORTCUTS a list of
+strings."
+  (let ((collection
+         (seq-mapcat
+          (lambda (name)
+            (org-cite-processor-cite-styles (org-cite--get-processor name)))
+          (or processors
+              (mapcar (pcase-lambda (`(,_ . (,name . ,_))) name)
+                      org-cite-export-processors))))
+        (result nil))
+    ;; Merge duplicate styles.  Each style full name is guaranteed to
+    ;; be unique, and associated to all shortcuts and all variants in
+    ;; the initial collection.
+    (pcase-dolist (`((,style . ,shortcuts) . ,variants) collection)
+      (let ((entry (assoc style result)))
+        (if (not entry)
+            (push (list style shortcuts variants) result)
+          (setf (nth 1 entry)
+                (seq-uniq (append shortcuts (nth 1 entry))))
+          (setf (nth 2 entry)
+                (append variants (nth 2 entry))))))
+    ;; Return value with the desired format.
+    (nreverse
+     (mapcar (pcase-lambda (`(,style ,shortcuts ,variants))
+               (cons (cons style (nreverse shortcuts))
+                     ;; Merge variant shortcuts.
+                     (let ((result nil))
+                       (pcase-dolist (`(,variant . ,shortcuts) variants)
+                         (let ((entry (assoc variant result)))
+                           (if (not entry)
+                               (push (cons variant shortcuts) result)
+                             (setf (cdr entry)
+                                   (seq-uniq (append shortcuts (cdr 
entry)))))))
+                       result)))
+             result))))
+
+(defun org-cite-delete-citation (datum)
+  "Delete citation or citation reference DATUM.
+When removing the last reference, also remove the whole citation."
+  (pcase (org-element-type datum)
+    ('citation
+     (pcase-let* ((`(,begin . ,end) (org-cite-boundaries datum))
+                  (pos-before-blank
+                   (org-with-point-at begin
+                     (skip-chars-backward " \t")
+                     (point)))
+                  (pos-after-blank (org-element-property :end datum))
+                  (first-on-line?
+                   (= pos-before-blank (line-beginning-position)))
+                  (last-on-line?
+                   (= pos-after-blank (line-end-position))))
+       (cond
+        ;; The citation is alone on its line.  Remove the whole line.
+        ;; Do not leave it blank as it might break a surrounding
+        ;; paragraph.
+        ((and first-on-line? last-on-line?)
+         (delete-region (line-beginning-position) (line-beginning-position 2)))
+        ;; When the citation starts the line, preserve indentation.
+        (first-on-line? (delete-region begin pos-after-blank))
+        ;; When the citation ends the line, remove any trailing space.
+        (last-on-line? (delete-region pos-before-blank (line-end-position)))
+        ;; Otherwise, delete blanks before the citation.
+        ;; Nevertheless, make sure there is at least one blank left,
+        ;; so as to not splice unrelated surroundings.
+        (t
+         (delete-region pos-before-blank end)
+         (when (= pos-after-blank end)
+           (org-with-point-at pos-before-blank (insert " ")))))))
+    ('citation-reference
+     (let* ((citation (org-element-property :parent datum))
+            (references (org-cite-get-references citation))
+            (begin (org-element-property :begin datum))
+            (end (org-element-property :end datum)))
+       (cond
+        ;; Single reference.
+        ((= 1 (length references))
+         (org-cite-delete-citation citation))
+        ;; First reference, no prefix.
+        ((and (= begin (org-element-property :contents-begin citation))
+              (not (org-element-property :prefix citation)))
+         (org-with-point-at (org-element-property :begin datum)
+           (skip-chars-backward " \t")
+           (delete-region (point) end)))
+        ;; Last reference, no suffix.
+        ((and (= end (org-element-property :contents-end citation))
+              (not (org-element-property :suffix citation)))
+         (delete-region (1- begin) (1- (cdr (org-cite-boundaries citation)))))
+        ;; Somewhere in-between.
+        (t
+         (delete-region begin end)))))
+    (other
+     (error "Invalid object type: %S" other))))
+
+
+;;; Tools only available during export
+(defun org-cite-citation-style (citation info)
+  "Return citation style used for CITATION object.
+
+Style is a pair (NAME . VARIANT) where NAME and VARIANT are strings or nil.
+A nil NAME means the default style for the current processor should be used.
+
+INFO is a plist used as a communication channel."
+  (let* ((separate
+          (lambda (s)
+            (cond
+             ((null s) (cons nil nil))
+             ((not (string-match "/" s)) (cons s nil))
+             (t (cons (substring s nil (match-beginning 0))
+                      (org-string-nw-p (substring s (match-end 0))))))))
+         (local (funcall separate (org-element-property :style citation)))
+         (global
+          (funcall separate (pcase (plist-get info :cite-export)
+                              (`(,_ ,_ ,style) style)
+                              (_ nil)))))
+    (cond
+     ((org-string-nw-p (car local))
+      (cons (org-not-nil (car local)) (cdr local)))
+     (t
+      (cons (org-not-nil (car global))
+            (or (cdr local) (cdr global)))))))
+
+(defun org-cite-bibliography-style (info)
+  "Return expected bibliography style.
+INFO is a plist used as a communication channel."
+  (pcase (plist-get info :cite-export)
+    (`(,_ ,style ,_) style)
+    (_ nil)))
+
+(defun org-cite-bibliography-properties (keyword)
+  "Return properties associated to \"print_bibliography\" KEYWORD object.
+Return value is a property list."
+  (org-cite--parse-as-plist (org-element-property :value keyword)))
+
+(defun org-cite-list-citations (info)
+  "List citations in the exported document.
+Citations are ordered by appearance in the document, when following footnotes.
+INFO is the export communication channel, as a property list."
+  (or (plist-get info :citations)
+      (letrec ((cites nil)
+               (search-cites
+                (lambda (data)
+                  (org-element-map data '(citation footnote-reference)
+                    (lambda (datum)
+                      (pcase (org-element-type datum)
+                        ('citation (push datum cites))
+                       ;; Do not force entering inline definitions, since
+                       ;; `org-element-map' is going to enter it anyway.
+                        ((guard (eq 'inline (org-element-property :type 
datum))))
+                        (_
+                         (funcall search-cites
+                                  (org-export-get-footnote-definition datum 
info)))))
+                    info nil 'footnote-definition t))))
+        (funcall search-cites (plist-get info :parse-tree))
+        (let ((result (nreverse cites)))
+          (plist-put info :citations result)
+          result))))
+
+(defun org-cite-list-keys (info)
+  "List citation keys in the exported document.
+Keys are ordered by first appearance in the document, when following footnotes.
+Duplicate keys are removed.  INFO is the export communication channel, as a
+property list."
+  (delete-dups
+   (org-element-map (org-cite-list-citations info) 'citation-reference
+     (lambda (r) (org-element-property :key r))
+     info)))
+
+(defun org-cite-key-number (key info &optional predicate)
+  "Return number associated to string KEY.
+
+INFO is the export communication channel, as a property list.
+
+Optional argument PREDICATE is called with two keys, and returns non-nil
+if the first reference should sort before the second.  When nil, references
+are sorted in order cited."
+  (let* ((keys (org-cite-list-keys info))
+         (sorted-keys (if (functionp predicate)
+                          (sort keys predicate)
+                        keys))
+         (position (seq-position sorted-keys key #'string-equal)))
+    (and (integerp position)
+         (1+ position))))
+
+(defun org-cite-inside-footnote-p (citation &optional strict)
+  "Non-nil when CITATION object is contained within a footnote.
+
+When optional argument STRICT is non-nil, return t only if CITATION represents
+the sole contents of the footnote, e.g., after calling 
`org-cite-wrap-citation'.
+
+When non-nil, the return value if the footnote container."
+  (let ((footnote
+         (org-element-lineage citation
+                              '(footnote-definition footnote-reference))))
+    (and footnote
+         (or (not strict)
+             (equal (org-element-contents (org-element-property :parent 
citation))
+                    (list citation)))
+         ;; Return value.
+         footnote)))
+
+(defun org-cite-wrap-citation (citation info)
+  "Wrap an anonymous inline footnote around CITATION object in the parse tree.
+
+INFO is the export state, as a property list.
+
+White space before the citation, if any, are removed.  The parse tree is
+modified by side-effect."
+  (let ((footnote
+         (list 'footnote-reference
+               (list :label nil
+                     :type 'inline
+                     :contents-begin (org-element-property :begin citation)
+                     :contents-end (org-element-property :end citation)
+                     :post-blank (org-element-property :post-blank 
citation)))))
+    ;; Remove any white space before citation.
+    (org-cite--set-previous-post-blank citation 0 info)
+    ;; Footnote swallows citation.
+    (org-element-insert-before footnote citation)
+    (org-element-adopt-elements footnote
+      (org-element-extract-element citation))))
+
+(defun org-cite-adjust-note (citation info &optional rule punct)
+  "Adjust note number location for CITATION object, and punctuation around it.
+
+INFO is the export state, as a property list.
+
+Optional argument PUNCT is a list of punctuation marks to be considered.
+When nil, it defaults to `org-cite-punctuation-marks'.
+
+Parse tree is modified by side-effect.
+
+Note: when calling both `org-cite-adjust-note' and `org-cite-wrap-citation' on
+the same object, call `org-cite-adjust-punctuation' first."
+  (when org-cite-adjust-note-numbers
+    (pcase-let* ((rule (or rule (org-cite--get-note-rule info)))
+                 (punct-re (regexp-opt (or punct org-cite-punctuation-marks)))
+                 ;; with Emacs <27.1. Argument of `regexp' form (PUNCT-RE this 
case)
+                 ;; must be a string literal.
+                 (previous-punct-re
+                  (rx-to-string `(seq (opt (group (regexp ,(rx (0+ (any blank 
?\n))))
+                                                  (regexp ,punct-re)))
+                                      (regexp ,(rx (opt (0+ (any blank ?\n)) 
(group ?\"))
+                                                   (opt (group (1+ (any blank 
?\n))))
+                                                   string-end)))
+                                t))
+                 (next-punct-re
+                  (rx-to-string `(seq string-start
+                                      (group (0+ (any blank ?\n)) (regexp 
,punct-re)))
+                                t))
+                 (next (org-export-get-next-element citation info))
+                 (final-punct
+                  (and (stringp next)
+                       (string-match next-punct-re next)
+                       (match-string 1 next)))
+                 (previous
+                  ;; Find the closest terminal object.  Consider
+                  ;; citation, subscript and superscript objects as
+                  ;; terminal.
+                  (org-last
+                   (org-element-map (org-export-get-previous-element citation 
info)
+                       '(citation code entity export-snippet footnote-reference
+                                  line-break latex-fragment link plain-text
+                                  radio-target statistics-cookie timestamp
+                                  verbatim)
+                     #'identity info nil '(citation subscript superscript))))
+                 (`(,punct ,quote ,spacing)
+                  (and (stringp previous)
+                       (string-match previous-punct-re previous)
+                       (list (match-string 1 previous)
+                             (match-string 2 previous)
+                             (match-string 3 previous)))))
+      ;; Bail you when there is no quote and either no punctuation, or
+      ;; punctuation on both sides.
+      (when (or quote (org-xor punct final-punct))
+        ;; Phase 1: handle punctuation rule.
+        (pcase rule
+          ((guard (not quote)) nil)
+          ;; Move punctuation inside.
+          (`(,(or `inside (and `adaptive (guard (not spacing)))) . ,_)
+           ;; This only makes sense if there is a quotation before the
+           ;; citation that does not end with some punctuation.
+           (when (and (not punct) final-punct)
+             ;; Quote guarantees there is a string object before
+             ;; citation.  Likewise, any final punctuation guarantees
+             ;; there is a string object following citation.
+             (let ((new-prev
+                    (replace-regexp-in-string
+                     previous-punct-re
+                     (concat final-punct "\"") previous nil nil 2))
+                   (new-next
+                    (replace-regexp-in-string
+                     ;; Before Emacs-27.1 `literal' `rx' form with a variable
+                     ;; as an argument is not available.
+                     (rx-to-string `(seq string-start ,final-punct) t)
+                     "" next)))
+               (org-element-set-element previous new-prev)
+               (org-element-set-element next new-next)
+               (setq previous new-prev)
+               (setq next new-next)
+               (setq punct final-punct)
+               (setq final-punct nil))))
+          ;; Move punctuation outside.
+          (`(,(or `outside (and `adaptive (guard spacing))) . ,_)
+           ;; This is only meaningful if there is some inner
+           ;; punctuation and no final punctuation already.
+           (when (and punct (not final-punct))
+             ;; Inner punctuation guarantees there is text object
+             ;; before the citation.  However, there is no information
+             ;; about the object following citation, if any.
+             ;; Therefore, we handle all the possible cases (string,
+             ;; other type, or none).
+             (let ((new-prev
+                    (replace-regexp-in-string
+                     previous-punct-re "" previous nil nil 1))
+                   (new-next (if (stringp next) (concat punct next) punct)))
+               (org-element-set-element previous new-prev)
+               (cond
+                ((stringp next)
+                 (org-element-set-element next new-next))
+                (next
+                 (org-element-insert-before new-next next))
+                (t
+                 (org-element-adopt-elements
+                     (org-element-property :parent citation)
+                   new-next)))
+               (setq previous new-prev)
+               (setq next new-next)
+               (setq final-punct punct)
+               (setq punct nil))))
+          (_
+           (error "Invalid punctuation rule: %S" rule))))
+      ;; Phase 2: move citation to its appropriate location.
+      ;;
+      ;; First transform relative citation location into a definitive
+      ;; location, according to the surrounding punctuation.
+      (pcase rule
+        (`(,punctuation same ,order)
+         (setf rule
+               (list punctuation
+                     (cond
+                      ;; When there is punctuation on both sides, the
+                      ;; citation is necessarily on the outside.
+                      ((and punct final-punct) 'outside)
+                      (punct 'inside)
+                      (final-punct 'outside)
+                      ;; No punctuation: bail out on next step.
+                      (t nil))
+                     order))))
+      (pcase rule
+        (`(,_ nil ,_) nil)
+        (`(,_ inside after)
+         ;; Citation has to be moved after punct, if there is
+         ;; a quotation mark, or after final punctuation.
+         (cond
+          (quote
+           (org-cite--insert-at-split previous citation 2 previous-punct-re))
+          (final-punct
+           (org-cite--move-punct-before final-punct citation next info))
+          ;; There is only punct, and we're already after it.
+          (t nil)))
+        (`(,_ inside before)
+         ;; Citation is already behind final-punct, so only consider
+         ;; other locations.
+         (when (or punct quote)
+           (org-cite--insert-at-split previous citation 0 previous-punct-re)))
+        (`(,_ outside after)
+         ;; Citation is already after any punct or quote.  It can only
+         ;; move past final punctuation, if there is one.
+         (when final-punct
+           (org-cite--move-punct-before final-punct citation next info)))
+        (`(,_ outside before)
+         ;; The only non-trivial case is when citation follows punct
+         ;; without a quote.
+         (when (and punct (not quote))
+           (org-cite--insert-at-split previous citation 0 previous-punct-re)))
+        (_
+         (error "Invalid punctuation rule: %S" rule))))))
+
+
+;;; Tools generating or operating on parsed data
+(defun org-cite-parse-elements (s)
+  "Parse string S as a list of Org elements.
+
+The return value is suitable as a replacement for a
+\"print_bibliography\" keyword.  As a consequence, the function
+raises an error if S contains a headline."
+  (with-temp-buffer
+    (insert s)
+    (pcase (org-element-contents (org-element-parse-buffer))
+      ('nil nil)
+      (`(,(and section (guard (eq 'section (org-element-type section)))))
+       (org-element-contents section))
+      (_
+       (error "Headlines cannot replace a keyword")))))
+
+(defun org-cite-parse-objects (s &optional affix)
+  "Parse string S as a secondary string.
+
+The return value is suitable as a replacement for a citation object.
+
+When optional argument AFFIX is non-nil, restrict the set of allowed object
+types to match the contents of a citation affix."
+  (org-element-parse-secondary-string
+   s (org-element-restriction (if affix 'citation-reference 'paragraph))))
+
+(defun org-cite-make-paragraph (&rest data)
+  "Return a paragraph element containing DATA.
+DATA are strings, objects or secondary strings."
+  (apply #'org-element-create 'paragraph nil (apply #'org-cite-concat data)))
+
+(defun org-cite-emphasize (type &rest data)
+  "Apply emphasis TYPE on DATA.
+TYPE is a symbol among `bold', `italic', `strike-through' and `underline'.
+DATA are strings, objects or secondary strings.  Return an object of type 
TYPE."
+  (declare (indent 1))
+  (unless (memq type '(bold italic strike-through underline))
+    (error "Wrong emphasis type: %S" type))
+  (apply #'org-element-create type nil (apply #'org-cite-concat data)))
+
+(defun org-cite-concat (&rest data)
+  "Concatenate all the DATA arguments and make the result a secondary string.
+Each argument may be a string, an object, or a secondary string."
+  (let ((results nil))
+    (dolist (datum (reverse data))
+      (pcase datum
+        ('nil nil)
+        ;; Element or object.
+        ((pred org-element-type) (push datum results))
+        ;; Secondary string.
+        ((pred consp) (setq results (append datum results)))
+        (_
+         (signal
+          'wrong-type-argument
+          (list (format "Argument is not a string or a secondary string: %S"
+                        datum))))))
+    results))
+
+(defun org-cite-mapconcat (function data separator)
+  "Apply FUNCTION to each element of DATA, and return a secondary string.
+
+In between each pair of results, stick SEPARATOR, which may be a string,
+an object, or a secondary string.  FUNCTION must be a function of one argument,
+and must return either a string, an object, or a secondary string."
+  (and data
+       (let ((result (list (funcall function (car data)))))
+         (dolist (datum (cdr data))
+           (setq result
+                 (org-cite-concat result separator (funcall function datum))))
+         result)))
+
+
+;;; Internal interface with fontification (activate capability)
+(defun org-cite-fontify-default (datum)
+  "Fontify DATUM with `org-cite' and `org-cite-key' face.
+DATUM is a citation object, or a citation reference.  In any case, apply
+`org-cite' face on the whole citation, and `org-cite-key' face on each key."
+  (let* ((cite (if (eq 'citation-reference (org-element-type datum))
+                   (org-element-property :parent datum)
+                 datum))
+         (beg (org-element-property :begin cite))
+         (end (org-with-point-at (org-element-property :end cite)
+                (skip-chars-backward " \t")
+                (point))))
+    (add-text-properties beg end '(font-lock-multiline t))
+    (add-face-text-property beg end 'org-cite)
+    (dolist (reference (org-cite-get-references cite))
+      (let ((boundaries (org-cite-key-boundaries reference)))
+        (add-face-text-property (car boundaries) (cdr boundaries)
+                                'org-cite-key)))))
+
+(defun org-cite-activate (limit)
+  "Activate citations from up to LIMIT buffer position.
+Each citation encountered is activated using the appropriate function
+from the processor set in `org-cite-activate-processor'."
+  (let ((name org-cite-activate-processor))
+    (let ((activate
+           (or (and name
+                    (org-cite-processor-has-capability-p name 'activate)
+                    (org-cite-processor-activate (org-cite--get-processor 
name)))
+               #'org-cite-fontify-default)))
+      (while (re-search-forward org-element-citation-prefix-re limit t)
+        (let ((cite (org-with-point-at (match-beginning 0)
+                      (org-element-citation-parser))))
+          (when cite (save-excursion (funcall activate cite))))))))
+
+
+;;; Internal interface with Org Export library (export capability)
+(defun org-cite-store-bibliography (info)
+  "Store bibliography in the communication channel.
+
+Bibliography is stored as a list of absolute file names in the `:bibliography'
+property.
+
+INFO is the communication channel, as a plist.  It is modified by side-effect."
+  (plist-put info :bibliography (org-cite-list-bibliography-files)))
+
+(defun org-cite-store-export-processor (info)
+  "Store export processor in the `:cite-export' property during export.
+
+Export processor is stored as a triplet, or nil.
+
+When non-nil, it is defined as (NAME BIBLIOGRAPHY-STYLE CITATION-STYLE) where
+NAME is a symbol, whereas BIBLIOGRAPHY-STYLE and CITATION-STYLE are strings,
+or nil.
+
+INFO is the communication channel, as a plist.  It is modified by side-effect."
+  (let* ((err
+          (lambda (s)
+            (user-error "Invalid cite export processor definition: %S" s)))
+         (processor
+          (pcase (plist-get info :cite-export)
+            ((or "" `nil) nil)
+            ;; Value is a string.  It comes from a "cite_export"
+            ;; keyword.  It may contain between 1 and 3 tokens, the
+            ;; first one being a symbol and the other (optional) two,
+            ;; strings.
+            ((and (pred stringp) s)
+             (with-temp-buffer
+               (save-excursion (insert s))
+               (let ((result (list (read (current-buffer)))))
+                 (dotimes (_ 2)
+                   (skip-chars-forward " \t")
+                   (cond
+                    ((eobp) (push nil result))
+                    ((char-equal ?\" (char-after))
+                     (condition-case _
+                         (push (org-not-nil (read (current-buffer))) result)
+                       (error (funcall err s))))
+                    (t
+                     (let ((origin (point)))
+                       (skip-chars-forward "^ \t")
+                       (push (org-not-nil (buffer-substring origin (point)))
+                             result)))))
+                 (unless (eobp) (funcall err s))
+                 (nreverse result))))
+            ;; Value is an alist.  It must come from
+            ;; `org-cite-export-processors' variable.  Find the most
+            ;; appropriate processor according to current export
+            ;; back-end.
+            ((and (pred consp) alist)
+             (let* ((backend (plist-get info :back-end))
+                    (candidates
+                     ;; Limit candidates to processors associated to
+                     ;; back-ends derived from or equal to the current
+                     ;; one.
+                     (sort (seq-filter
+                            (pcase-lambda (`(,key . ,_))
+                              (org-export-derived-backend-p backend key))
+                            alist)
+                           (lambda (a b)
+                             (org-export-derived-backend-p (car a) (car b))))))
+               ;; Select the closest candidate, or fallback to t.
+               (pcase (or (car candidates) (assq t alist))
+                 ('nil nil)
+                 (`(,_ . ,p)
+                  ;; Normalize value by turning it into a triplet.
+                  (pcase p
+                    (`(,(pred symbolp))
+                     (append p (list nil nil)))
+                    (`(,(pred symbolp) ,(pred string-or-null-p))
+                     (append p (list nil)))
+                    (`(,(pred symbolp)
+                       ,(pred string-or-null-p)
+                       ,(pred string-or-null-p))
+                     p)
+                    (_ (funcall err p))))
+                 (other (funcall err (cdr other))))))
+            (other (funcall err other)))))
+    (pcase processor
+      ('nil nil)
+      (`(,name . ,_)
+       (cond
+        ((not (org-cite--get-processor name))
+         (user-error "Unknown processor %S" name))
+        ((not (org-cite-processor-has-capability-p name 'export))
+         (user-error "Processor %S is unable to handle citation export" 
name)))))
+    (plist-put info :cite-export processor)))
+
+(defun org-cite-export-citation (citation _ info)
+  "Export CITATION object according to INFO property list.
+This function delegates the export of the current citation to the
+selected citation processor."
+  (pcase (plist-get info :cite-export)
+    ('nil nil)
+    (`(,p ,_ ,_)
+     (funcall (org-cite-processor-export-citation (org-cite--get-processor p))
+             citation
+              (org-cite-citation-style citation info)
+              (plist-get info :back-end)
+              info))
+    (other (error "Invalid `:cite-export' value: %S" other))))
+
+(defun org-cite-export-bibliography (keyword _ info)
+  "Return bibliography associated to \"print_bibliography\" KEYWORD.
+BACKEND is the export back-end, as a symbol.  INFO is a plist
+used as a communication channel."
+  (pcase (plist-get info :cite-export)
+    ('nil nil)
+    (`(,p ,_ ,_)
+     (let ((export-bibilography
+            (org-cite-processor-export-bibliography
+             (org-cite--get-processor p))))
+       (when export-bibilography
+         (funcall export-bibilography
+                 (org-cite-list-keys info)
+                  (plist-get info :bibliography)
+                  (org-cite-bibliography-style info)
+                  (org-cite-bibliography-properties keyword)
+                  (plist-get info :back-end)
+                  info))))
+    (other (error "Invalid `:cite-export' value: %S" other))))
+
+(defun org-cite-process-citations (info)
+  "Replace all citations in the parse tree.
+INFO is the communication channel, as a plist.  Parse tree is modified
+by side-effect."
+  (dolist (cite (org-cite-list-citations info))
+    (let ((replacement (org-cite-export-citation cite nil info))
+          (blanks (or (org-element-property :post-blank cite) 0)))
+      (if (null replacement)
+          ;; Before removing the citation, transfer its `:post-blank'
+          ;; property to the object before, if any.
+          (org-cite--set-previous-post-blank cite blanks info)
+        ;; We want to be sure any non-note citation is preceded by
+        ;; a space.  This is particularly important when using
+        ;; `adaptive' note rule.  See `org-cite-note-rules'.
+        (unless (org-cite-inside-footnote-p cite t)
+          (org-cite--set-previous-post-blank cite 1 info))
+        (pcase replacement
+          ;; String.
+          ((pred stringp)
+           ;; Handle `:post-blank' before replacing value.
+           (let ((output (concat (org-trim replacement)
+                                 (make-string blanks ?\s))))
+             (org-element-insert-before (org-export-raw-string output) cite)))
+          ;; Single element.
+          (`(,(pred symbolp) . ,_)
+           (org-cite--set-post-blank replacement blanks)
+           (org-element-insert-before replacement cite))
+          ;; Secondary string: splice objects at cite's place.
+          ;; Transfer `:post-blank' to the last object.
+          ((pred consp)
+           (let ((last nil))
+             (dolist (datum replacement)
+               (setq last datum)
+               (org-element-insert-before datum cite))
+             (org-cite--set-post-blank last blanks)))
+          (_
+           (error "Invalid return value from citation export processor: %S"
+                  replacement))))
+      (org-element-extract-element cite))))
+
+(defun org-cite-process-bibliography (info)
+  "Replace all \"print_bibliography\" keywords in the parse tree.
+
+INFO is the communication channel, as a plist.  Parse tree is modified
+by side effect."
+  (org-element-map (plist-get info :parse-tree) 'keyword
+    (lambda (keyword)
+      (when (equal "PRINT_BIBLIOGRAPHY" (org-element-property :key keyword))
+        (let ((replacement (org-cite-export-bibliography keyword nil info))
+              (blanks (or (org-element-property :post-blank keyword) 0)))
+          (pcase replacement
+            ;; Before removing the citation, transfer its
+            ;; `:post-blank' property to the element before, if any.
+            ('nil
+             (org-cite--set-previous-post-blank keyword blanks info)
+             (org-element-extract-element keyword))
+            ;; Handle `:post-blank' before replacing keyword with string.
+            ((pred stringp)
+             (let ((output (concat (org-element-normalize-string replacement)
+                                   (make-string blanks ?\n))))
+               (org-element-set-element keyword (org-export-raw-string 
output))))
+            ;; List of elements: splice contents before keyword and
+            ;; remove the latter.  Transfer `:post-blank' to last
+            ;; element.
+            ((and `(,(pred listp) . ,_) contents)
+             (let ((last nil))
+               (dolist (datum contents)
+                 (setq last datum)
+                 (org-element-insert-before datum keyword))
+               (org-cite--set-post-blank last blanks)
+               (org-element-extract-element keyword)))
+            ;; Single element: replace the keyword.
+            (`(,(pred symbolp) . ,_)
+             (org-cite--set-post-blank replacement blanks)
+             (org-element-set-element keyword replacement))
+            (_
+             (error "Invalid return value from citation export processor: %S"
+                    replacement))))))
+    info))
+
+(defun org-cite-finalize-export (output info)
+  "Finalizer for export process.
+OUTPUT is the full output of the export process.  INFO is the communication
+channel, as a property list."
+  (pcase (plist-get info :cite-export)
+    ('nil output)
+    (`(,p ,_ ,_)
+     (let ((finalizer
+            (org-cite-processor-export-finalizer (org-cite--get-processor p))))
+       (if (not finalizer)
+           output
+         (funcall finalizer
+                  output
+                  (org-cite-list-keys info)
+                  (plist-get info :bibliography)
+                  (org-cite-bibliography-style info)
+                  (plist-get info :back-end)
+                  info))))
+    (other (error "Invalid `:cite-export' value: %S" other))))
+
+
+;;; Internal interface with `org-open-at-point' (follow capability)
+(defun org-cite-follow (datum arg)
+  "Follow citation or citation-reference DATUM.
+Following is done according to the processor set in 
`org-cite-follow-processor'.
+ARG is the prefix argument received when calling `org-open-at-point', or nil."
+  (let ((name org-cite-follow-processor))
+    (cond
+     ((null name)
+      (user-error "No processor set to follow citations"))
+     ((not (org-cite--get-processor name))
+      (user-error "Unknown processor %S" name))
+     ((not (org-cite-processor-has-capability-p name 'follow))
+      (user-error "Processor %S cannot follow citations" name))
+     (t
+      (let ((follow (org-cite-processor-follow (org-cite--get-processor 
name))))
+        (funcall follow datum arg))))))
+
+
+;;; Meta-command for citation insertion (insert capability)
+(defun org-cite--allowed-p (context)
+  "Non-nil when a citation can be inserted at point."
+  (let ((type (org-element-type context)))
+    (cond
+     ;; No citation in attributes, except in parsed ones.
+     ;;
+     ;; XXX: Inserting citation in a secondary value is not allowed
+     ;; yet.  Is it useful?
+     ((let ((post (org-element-property :post-affiliated context)))
+       (and post (< (point) post)))
+      (let ((case-fold-search t))
+        (looking-back
+         (rx-to-string
+          `(seq line-start (0+ (any " \t"))
+                "#+"
+                (or ,@org-element-parsed-keywords)
+                ":"
+                (0+ nonl))
+          t)
+         (line-beginning-position))))
+     ;; 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)
+                           (line-beginning-position 2)))))
+     ;; At the start of a list item is fine, as long as the bullet is 
unaffected.
+     ((eq type 'item)
+      (> (point) (+ (org-element-property :begin context)
+                    (current-indentation)
+                    (if (org-element-property :checkbox context)
+                        5 1))))
+     ;; 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)
+     ((eq type 'table-cell)
+      ;; :contents-begin is not reliable on empty cells, so special
+      ;; case it.
+      (<= (save-excursion (skip-chars-backward " \t") (point))
+          (org-element-property :contents-end context)))
+     ((let ((cbeg (org-element-property :contents-begin context))
+           (cend (org-element-property :contents-end context)))
+       (and cbeg (>= (point) cbeg) (<= (point) cend)))))))
+
+(defun org-cite--insert-string-before (string reference)
+  "Insert STRING before citation REFERENCE object."
+  (org-with-point-at (org-element-property :begin reference)
+    (insert string ";")))
+
+(defun org-cite--insert-string-after (string reference)
+  "Insert STRING after citation REFERENCE object."
+  (org-with-point-at (org-element-property :end reference)
+    ;; Make sure to move forward when we're inserting at point, so the
+    ;; insertion can happen multiple times.
+    (if (char-equal ?\; (char-before))
+        (insert-before-markers  string ";")
+      (insert-before-markers ";" string))))
+
+(defun org-cite--keys-to-citation (keys)
+  "Build a citation object from a list of citation KEYS.
+Citation keys are strings without the leading \"@\"."
+  (apply #'org-element-create
+         'citation
+         nil
+         (mapcar (lambda (k)
+                   (org-element-create 'citation-reference (list :key k)))
+                 keys)))
+
+(defun org-cite-make-insert-processor (select-key select-style)
+  "Build a function appropriate as an insert processor.
+
+SELECT-KEY is a function called with one argument.  When it is nil, the 
function
+should return a citation key as a string, or nil.  Otherwise, the function
+should return a list of such keys, or nil.  The keys should not have any 
leading
+\"@\" character.
+
+SELECT-STYLE is a function called with one argument, the citation object being
+edited or constructed so far.  It should return a style string, or nil.
+
+The return value is a function of two arguments: CONTEXT and ARG.  CONTEXT is
+either a citation reference, a citation object, or nil.  ARG is a prefix
+argument.
+
+The generated function inserts or edit a citation at point.  More specifically,
+
+  On a citation reference:
+
+    - on the prefix or right before th \"@\" character, insert a new reference
+      before the current one,
+    - on the suffix, insert it after the reference,
+    - otherwise, update the cite key, preserving both affixes.
+
+    When ARG is non-nil, remove the reference, possibly removing the whole
+    citation if it contains a single reference.
+
+  On a citation object:
+
+    - on the style part, offer to update it,
+    - on the global prefix, add a new reference before the first one,
+    - on the global suffix, add a new reference after the last one,
+
+  Elsewhere, insert a citation at point.  When ARG is non-nil, offer to 
complete
+  style in addition to references."
+  (unless (and (functionp select-key) (functionp select-style))
+    (error "Wrong argument type(s)"))
+  (lambda (context arg)
+    (pcase (org-element-type context)
+      ;; When on a citation, check point is not on the blanks after it.
+      ;; Otherwise, consider we're after it.
+      ((and 'citation
+            (guard
+             (let ((boundaries (org-cite-boundaries context)))
+               (and (< (point) (cdr boundaries))
+                    (> (point) (car boundaries))))))
+       ;; When ARG is non-nil, delete the whole citation.  Otherwise,
+       ;; action depends on the point.
+       (if arg
+           (org-cite-delete-citation context)
+         (let* ((begin (org-element-property :begin context))
+                (style-end (1- (org-with-point-at begin (search-forward 
":")))))
+           (if (>= style-end (point))
+               ;; On style part, edit the style.
+               (let ((style-start (+ 5 begin))
+                     (style (funcall select-style)))
+                 (unless style (user-error "Aborted"))
+                 (org-with-point-at style-start
+                   (delete-region style-start style-end)
+                   (when (org-string-nw-p style) (insert "/" style))))
+             ;; On an affix, insert a new reference before or after
+             ;; point.
+             (let* ((references (org-cite-get-references context))
+                    (key (concat "@" (funcall select-key nil))))
+               (if (< (point) (org-element-property :contents-begin context))
+                   (org-cite--insert-string-before key (car references))
+                 (org-cite--insert-string-after key (org-last 
references))))))))
+      ;; On a citation reference.  If ARG is not nil, remove the
+      ;; reference.  Otherwise, action depends on the point.
+      ((and 'citation-reference (guard arg)) (org-cite-delete-citation 
context))
+      ('citation-reference
+       (pcase-let* ((`(,start . ,end) (org-cite-key-boundaries context))
+                    (key (concat "@"
+                                 (or (funcall select-key nil)
+                                     (user-error "Aborted")))))
+         ;; Right before the "@" character, do not replace the reference
+         ;; at point, but insert a new one before it.  It makes adding
+         ;; a new reference at the beginning easier in the following
+         ;; case: [cite:@key].
+         (cond
+          ((>= start (point)) (org-cite--insert-string-before key context))
+          ((<= end (point)) (org-cite--insert-string-after key context))
+          (t
+           (org-with-point-at start
+             (delete-region start end)
+             (insert key))))))
+      (_
+       (let ((keys (funcall select-key t)))
+         (unless keys (user-error "Aborted"))
+         (insert
+          (format "[cite%s:%s]"
+                  (if arg
+                      (let ((style (funcall select-style
+                                            (org-cite--keys-to-citation 
keys))))
+                        (if (org-string-nw-p style)
+                            (concat "/" style)
+                          ""))
+                    "")
+                  (mapconcat (lambda (k) (concat "@" k)) keys ";"))))))))
+
+(defun org-cite-insert (arg)
+  "Insert a citation at point.
+Insertion is done according to the processor set in 
`org-cite-insert-processor'.
+ARG is the prefix argument received when calling interactively the function."
+  (interactive "P")
+  (let ((name org-cite-insert-processor))
+    (cond
+     ((null name)
+      (user-error "No processor set to follow citations"))
+     ((not (org-cite--get-processor name))
+      (user-error "Unknown processor %S" name))
+     ((not (org-cite-processor-has-capability-p name 'insert))
+      (user-error "Processor %S cannot insert citations" name))
+     (t
+      (let ((context (org-element-context))
+            (insert (org-cite-processor-insert (org-cite--get-processor 
name))))
+        (cond
+         ((memq (org-element-type context) '(citation citation-reference))
+          (funcall insert context arg))
+         ((org-cite--allowed-p context)
+          (funcall insert nil arg))
+         (t
+          (user-error "Cannot insert a citation here"))))))))
+
+(provide 'oc)
+;;; oc.el ends here
diff --git a/lisp/ol-bbdb.el b/lisp/ol-bbdb.el
index 84537b1..f697f1f 100644
--- a/lisp/ol-bbdb.el
+++ b/lisp/ol-bbdb.el
@@ -2,7 +2,7 @@
 
 ;; Copyright (C) 2004-2021 Free Software Foundation, Inc.
 
-;; Authors: Carsten Dominik <carsten at orgmode dot org>
+;; Authors: Carsten Dominik <carsten.dominik@gmail.com>
 ;;       Thomas Baumann <thomas dot baumann at ch dot tum dot de>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: https://orgmode.org
@@ -60,7 +60,7 @@
 ;;
 ;; CLASS-OR-FORMAT-STRING is one of two things:
 ;;
-;;  - an identifier for a class of anniversaries (eg. birthday or
+;;  - an identifier for a class of anniversaries (e.g. birthday or
 ;;    wedding) from `org-bbdb-anniversary-format-alist' which then
 ;;    defines the format string for this class
 ;;  - the (format) string displayed in the diary.
@@ -431,7 +431,7 @@ variable to be globally bound."
 ;;; 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."
+  "Return 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)))))
diff --git a/lisp/ol-bibtex.el b/lisp/ol-bibtex.el
index 0c88de0..476095d 100644
--- a/lisp/ol-bibtex.el
+++ b/lisp/ol-bibtex.el
@@ -88,7 +88,7 @@
 ;;
 ;; - All Bibtex information is taken from the document compiled by
 ;;   Andrew Roberts from the Bibtex manual, available at
-;;   http://www.andy-roberts.net/res/writing/latex/bibentries.pdf
+;;   https://www.andy-roberts.net/res/writing/latex/bibentries.pdf
 ;;
 ;;; History:
 ;;
@@ -145,59 +145,59 @@
   '((:article
      (:description . "An article from a journal or magazine")
      (:required :author :title :journal :year)
-     (:optional :volume :number :pages :month :note))
+     (:optional :volume :number :pages :month :note :doi))
     (:book
      (:description . "A book with an explicit publisher")
      (:required (:editor :author) :title :publisher :year)
-     (:optional (:volume :number) :series :address :edition :month :note))
+     (:optional (:volume :number) :series :address :edition :month :note :doi))
     (:booklet
      (:description . "A work that is printed and bound, but without a named 
publisher or sponsoring institution.")
      (:required :title)
-     (:optional :author :howpublished :address :month :year :note))
+     (:optional :author :howpublished :address :month :year :note :doi :url))
     (:conference
      (:description . "")
      (:required :author :title :booktitle :year)
-     (:optional :editor :pages :organization :publisher :address :month :note))
+     (:optional :editor :pages :organization :publisher :address :month :note 
:doi :url))
     (:inbook
      (:description . "A part of a book, which may be a chapter (or section or 
whatever) and/or a range of pages.")
      (:required (:author :editor) :title (:chapter :pages) :publisher :year)
-     (:optional :crossref (:volume :number) :series :type :address :edition 
:month :note))
+     (:optional :crossref (:volume :number) :series :type :address :edition 
:month :note :doi))
     (:incollection
      (:description . "A part of a book having its own title.")
      (:required :author :title :booktitle :publisher :year)
-     (:optional :crossref :editor (:volume :number) :series :type :chapter 
:pages :address :edition :month :note))
+     (:optional :crossref :editor (:volume :number) :series :type :chapter 
:pages :address :edition :month :note :doi))
     (:inproceedings
      (:description . "An article in a conference proceedings")
      (:required :author :title :booktitle :year)
-     (:optional :crossref :editor (:volume :number) :series :pages :address 
:month :organization :publisher :note))
+     (:optional :crossref :editor (:volume :number) :series :pages :address 
:month :organization :publisher :note :doi))
     (:manual
      (:description . "Technical documentation.")
      (:required :title)
-     (:optional :author :organization :address :edition :month :year :note))
+     (:optional :author :organization :address :edition :month :year :note 
:doi :url))
     (:mastersthesis
      (:description . "A Masterโ€™s thesis.")
      (:required :author :title :school :year)
-     (:optional :type :address :month :note))
+     (:optional :type :address :month :note :doi :url))
     (:misc
      (:description . "Use this type when nothing else fits.")
      (:required)
-     (:optional :author :title :howpublished :month :year :note))
+     (:optional :author :title :howpublished :month :year :note :doi :url))
     (:phdthesis
      (:description . "A PhD thesis.")
      (:required :author :title :school :year)
-     (:optional :type :address :month :note))
+     (:optional :type :address :month :note :doi :url))
     (:proceedings
      (:description . "The proceedings of a conference.")
      (:required :title :year)
-     (:optional :editor (:volume :number) :series :address :month 
:organization :publisher :note))
+     (:optional :editor (:volume :number) :series :address :month 
:organization :publisher :note :doi))
     (:techreport
      (:description . "A report published by a school or other institution.")
      (:required :author :title :institution :year)
-     (:optional :type :address :month :note))
+     (:optional :type :address :month :note :doi :url))
     (:unpublished
      (:description . "A document having an author and title, but not formally 
published.")
      (:required :author :title :note)
-     (:optional :month :year)))
+     (:optional :month :year :doi :url)))
   "Bibtex entry types with required and optional parameters.")
 
 (defvar org-bibtex-fields
@@ -207,6 +207,7 @@
     (:booktitle    . "Title of a book, part of which is being cited.  See the 
LaTeX book for how to type titles.  For book entries, use the title field 
instead.")
     (:chapter      . "A chapter (or section or whatever) number.")
     (:crossref     . "The database key of the entry being cross referenced.")
+    (:doi          . "The digital object identifier.")
     (:edition      . "The edition of a book for example, 'Second'.  This 
should be an ordinal, and should have the first letter capitalized, as shown 
here; the standard styles convert to lower case when necessary.")
     (:editor       . "Name(s) of editor(s), typed as indicated in the LaTeX 
book.  If there is also an author field, then the editor field gives the editor 
of the book or collection in which the reference appears.")
     (:howpublished . "How something strange has been published.  The first 
word should be capitalized.")
@@ -223,6 +224,7 @@
     (:series       . "The name of a series or set of books.  When citing an 
entire book, the title field gives its title and an optional series field gives 
the name of a series or multi-volume set in which the book is published.")
     (:title        . "The workโ€™s title, typed as explained in the LaTeX book.")
     (:type         . "The type of a technical report for example, 'Research 
Note'.")
+    (:url          . "Uniform resource locator.")
     (:volume       . "The volume of a journal or multi-volume book.")
     (:year         . "The year of publication or, for an unpublished work, the 
year it was written.  Generally it should consist of four numerals, such as 
1984, although the standard styles can handle any year whose last four 
nonpunctuation characters are numerals, such as '(about 1984)'"))
   "Bibtex fields with descriptions.")
@@ -507,6 +509,7 @@ ARG, when non-nil, is a universal prefix argument.  See
       (org-link-store-props
        :key (cdr (assoc "=key=" entry))
        :author (or (cdr (assoc "author" entry)) "[no author]")
+       :doi (or (cdr (assoc "doi" entry)) "[no doi]")
        :editor (or (cdr (assoc "editor" entry)) "[no editor]")
        :title (or (cdr (assoc "title" entry)) "[no title]")
        :booktitle (or (cdr (assoc "booktitle" entry)) "[no booktitle]")
@@ -656,7 +659,7 @@ 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)))
diff --git a/lisp/ol-doi.el b/lisp/ol-doi.el
new file mode 100644
index 0000000..dfde380
--- /dev/null
+++ b/lisp/ol-doi.el
@@ -0,0 +1,70 @@
+;;; ol-doi.el --- DOI links support in Org           -*- lexical-binding: t; 
-*-
+
+;; Copyright (C) 2021  Free Software Foundation, Inc.
+
+;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This library introduces the "doi" link type in Org, and provides
+;; code for opening and exporting such links.
+
+;;; Code:
+
+(require 'ol)
+
+(defcustom org-link-doi-server-url "https://doi.org/";
+  "The URL of the DOI server."
+  :group 'org-link-follow
+  :version "24.3"
+  :type 'string
+  :safe #'stringp)
+
+(defun org-link-doi-open (path arg)
+  "Open a \"doi\" type link.
+PATH is a the path to search for, as a string."
+  (browse-url (url-encode-url (concat org-link-doi-server-url path)) arg))
+
+(defun org-link-doi-export (path desc backend info)
+  "Export a \"doi\" type link.
+PATH is the DOI name.  DESC is the description of the link, or
+nil.  BACKEND is a symbol representing the backend used for
+export.  INFO is a a plist containing the export parameters."
+  (let ((uri (concat org-link-doi-server-url path)))
+    (pcase backend
+      (`html
+       (format "<a href=\"%s\">%s</a>" uri (or desc uri)))
+      (`latex
+       (if desc (format "\\href{%s}{%s}" uri desc)
+        (format "\\url{%s}" uri)))
+      (`ascii
+       (if (not desc) (format "<%s>" uri)
+         (concat (format "[%s]" desc)
+                (and (not (plist-get info :ascii-links-to-notes))
+                     (format " (<%s>)" uri)))))
+      (`texinfo
+       (if (not desc) (format "@uref{%s}" uri)
+         (format "@uref{%s, %s}" uri desc)))
+      (_ uri))))
+
+(org-link-set-parameters "doi"
+                         :follow #'org-link-doi-open
+                         :export #'org-link-doi-export)
+
+
+(provide 'org-link-doi)
+(provide 'ol-doi)
+;;; ol-doi.el ends here
diff --git a/lisp/ol-eshell.el b/lisp/ol-eshell.el
index 769e7ee..a7550e3 100644
--- a/lisp/ol-eshell.el
+++ b/lisp/ol-eshell.el
@@ -1,4 +1,4 @@
-;;; ol-eshell.el - Links to Working Directories in Eshell -*- lexical-binding: 
t; -*-
+;;; ol-eshell.el --- Links to Working Directories in Eshell  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2011-2021 Free Software Foundation, Inc.
 
@@ -35,9 +35,9 @@
 
 (defun org-eshell-open (link _)
   "Switch to an eshell buffer and execute a command line.
-   The link can be just a command line (executed in the default
-   eshell buffer) or a command line prefixed by a buffer name
-   followed by a colon."
+The link can be just a command line (executed in the default
+eshell buffer) or a command line prefixed by a buffer name
+followed by a colon."
   (let* ((buffer-and-command
           (if (string-match "\\([A-Za-z0-9+*-]+\\):\\(.*\\)" link)
              (list (match-string 1 link)
@@ -55,7 +55,7 @@
 
 (defun org-eshell-store-link ()
   "Store a link that, when opened, switches back to the current eshell buffer
-   and the current working directory."
+and the current working directory."
   (when (eq major-mode 'eshell-mode)
     (let* ((command (concat "cd " (eshell/pwd)))
            (link  (concat (buffer-name) ":" command)))
diff --git a/lisp/ol-gnus.el b/lisp/ol-gnus.el
index 71051bc..72bdd73 100644
--- a/lisp/ol-gnus.el
+++ b/lisp/ol-gnus.el
@@ -2,7 +2,7 @@
 
 ;; Copyright (C) 2004-2021 Free Software Foundation, Inc.
 
-;; Author: Carsten Dominik <carsten at orgmode dot org>
+;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 ;;         Tassilo Horn <tassilo at member dot fsf dot org>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: https://orgmode.org
@@ -194,15 +194,15 @@ If `org-store-link' was called with a prefix arg the 
meaning of
                               (message-tokenize-header
                                (mail-fetch-field "gcc" nil t) " ,"))))
               (id (org-unbracket-string "<" ">"
-                                        (mail-fetch-field "Message-ID")))
+                    (mail-fetch-field "Message-ID")))
               (to (mail-fetch-field "To"))
               (from (mail-fetch-field "From"))
               (subject (mail-fetch-field "Subject"))
-              newsgroup xarchive)      ;those are always nil for gcc
+              ) ;; newsgroup xarchive  ;those are always nil for gcc
           (unless gcc (error "Can not create link: No Gcc header found"))
           (org-link-store-props :type "gnus" :from from :subject subject
                                 :message-id id :group gcc :to to)
-          (let ((link (org-gnus-article-link gcc newsgroup id xarchive))
+          (let ((link (org-gnus-article-link gcc nil id nil)) ;;newsgroup 
xarchive
                 (description (org-link-email-description)))
             (org-link-add-props :link link :description description)
             link)))))))
diff --git a/lisp/ol-info.el b/lisp/ol-info.el
index 824faf7..a535ea5 100644
--- a/lisp/ol-info.el
+++ b/lisp/ol-info.el
@@ -2,7 +2,7 @@
 
 ;; Copyright (C) 2004-2021 Free Software Foundation, Inc.
 
-;; Author: Carsten Dominik <carsten at orgmode dot org>
+;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: https://orgmode.org
 ;;
@@ -91,7 +91,7 @@
     "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.
+  "List of Emacs documents available.
 Taken from <https://www.gnu.org/software/emacs/manual/html_mono/.>")
 
 (defconst org-info-other-documents
diff --git a/lisp/ol-rmail.el b/lisp/ol-rmail.el
index a73060b..2593ebd 100644
--- a/lisp/ol-rmail.el
+++ b/lisp/ol-rmail.el
@@ -2,7 +2,7 @@
 
 ;; Copyright (C) 2004-2021 Free Software Foundation, Inc.
 
-;; Author: Carsten Dominik <carsten at orgmode dot org>
+;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: https://orgmode.org
 ;;
diff --git a/lisp/ol-w3m.el b/lisp/ol-w3m.el
index f1f3afd..9e03269 100644
--- a/lisp/ol-w3m.el
+++ b/lisp/ol-w3m.el
@@ -7,13 +7,13 @@
 ;; Homepage: https://orgmode.org
 ;;
 ;; This file is part of GNU Emacs.
-;;
-;; This program is free software: you can redistribute it and/or modify
+
+;; 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.
 
-;; This program is distributed in the hope that it will be useful,
+;; 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.
@@ -82,26 +82,41 @@ so that it can be yanked into an Org  buffer with links 
working correctly."
         (setq temp-position (point))
         ;; move to next anchor when current point is not at anchor
         (or (get-text-property (point) 'w3m-href-anchor) 
(org-w3m-get-next-link-start))
-        (if (<= (point) transform-end) ; if point is inside transform bound
-            (progn
-              ;; get content between two links.
-              (when (> (point) temp-position)
-                (setq return-content (concat return-content
-                                             (buffer-substring
-                                              temp-position (point)))))
-              ;; get link location at current point.
-              (setq link-location (get-text-property (point) 'w3m-href-anchor))
-              ;; get link title at current point.
-              (setq link-title (buffer-substring (point)
-                                                 (org-w3m-get-anchor-end)))
-              ;; concat Org style url to `return-content'.
-              (setq return-content
-                   (concat return-content
-                           (if (org-string-nw-p link-location)
-                               (org-link-make-string link-location link-title)
-                             link-title))))
+        (cond
+         ((<= (point) transform-end) ; point is inside transform bound
+          ;; get content between two links.
+          (when (> (point) temp-position)
+            (setq return-content (concat return-content
+                                         (buffer-substring
+                                          temp-position (point)))))
+          (cond
+           ((setq link-location (get-text-property (point) 'w3m-href-anchor))
+            ;; current point is a link
+            ;; (we thus also got link location at current point)
+            ;; get link title at current point.
+            (setq link-title (buffer-substring (point)
+                                               (org-w3m-get-anchor-end)))
+            ;; concat Org style url to `return-content'.
+            (setq return-content
+                  (concat return-content
+                          (if (org-string-nw-p link-location)
+                              (org-link-make-string link-location link-title)
+                            link-title))))
+           ((setq link-location (get-text-property (point) 'w3m-image))
+            ;; current point is an image
+            ;; (we thus also got image link location at current point)
+            ;; get link title at current point.
+            (setq link-title (buffer-substring (point) 
(org-w3m-get-image-end)))
+            ;; concat Org style url to `return-content'.
+            (setq return-content
+                  (concat return-content
+                          (if (org-string-nw-p link-location)
+                              (org-link-make-string link-location link-title)
+                            link-title))))
+           (t nil))); current point is neither a link nor an image
+         (t ; point is NOT inside transform bound
           (goto-char temp-position) ; reset point before jump next anchor
-          (setq out-bound t)))     ; for break out `while' loop
+          (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
@@ -114,6 +129,7 @@ so that it can be yanked into an Org  buffer with links 
working correctly."
 (defun org-w3m-get-anchor-start ()
   "Move cursor to the start of current anchor.  Return point."
   ;; get start position of anchor or current point
+  ;; NOTE: This function seems never to be used. Should it be removed?
   (goto-char (or (previous-single-property-change (point) 'w3m-anchor-sequence)
                  (point))))
 
@@ -123,26 +139,46 @@ so that it can be yanked into an Org  buffer with links 
working correctly."
   (goto-char (or (next-single-property-change (point) 'w3m-anchor-sequence)
                 (point))))
 
+(defun org-w3m-get-image-end ()
+  "Move cursor to the end of current image.  Return point."
+  ;; get end position of image or point
+  ;; NOTE: Function `org-w3m-get-image-start' was not created because
+  ;;       function `org-w3m-get-anchor-start' is never used.
+  (goto-char (or (next-single-property-change (point) 'w3m-image)
+                (point))))
+
 (defun org-w3m-get-next-link-start ()
-  "Move cursor to the start of next link.  Return point."
-  (catch 'reach
-    (while (next-single-property-change (point) 'w3m-anchor-sequence)
-      ;; jump to next anchor
-      (goto-char (next-single-property-change (point) 'w3m-anchor-sequence))
-      (when (get-text-property (point) 'w3m-href-anchor)
-        ;; return point when current is valid link
-        (throw 'reach nil))))
-  (point))
+  "Move cursor to the start of next link or image.  Return point."
+  (let (pos start-pos anchor-pos image-pos)
+    (setq pos (setq start-pos (point)))
+    (setq anchor-pos
+          (catch 'reach
+            (while (setq pos (next-single-property-change pos 
'w3m-anchor-sequence))
+              (when (get-text-property pos 'w3m-href-anchor)
+                (throw 'reach pos)))))
+    (setq pos start-pos)
+    (setq image-pos
+          (catch 'reach
+            (while (setq pos (next-single-property-change pos 'w3m-image))
+              (when (get-text-property pos 'w3m-image)
+                (throw 'reach pos)))))
+    (goto-char (min (or anchor-pos (point-max)) (or image-pos (point-max))))))
 
 (defun org-w3m-get-prev-link-start ()
   "Move cursor to the start of previous link.  Return point."
+  ;; NOTE: This function is only called by `org-w3m-no-prev-link-p',
+  ;;       which itself seems never to be used. Should it be removed?
+  ;;
+  ;; WARNING: This function has not been updated to account for
+  ;;      `w3m-image'. See `org-w3m-get-next-link-start'.
   (catch 'reach
-    (while (previous-single-property-change (point) 'w3m-anchor-sequence)
-      ;; jump to previous anchor
-      (goto-char (previous-single-property-change (point) 
'w3m-anchor-sequence))
-      (when (get-text-property (point) 'w3m-href-anchor)
-        ;; return point when current is valid link
-        (throw 'reach nil))))
+    (let ((pos (point)))
+      (while (setq pos (previous-single-property-change pos 
'w3m-anchor-sequence))
+        (when (get-text-property pos 'w3m-href-anchor)
+          ;; jump to previous anchor
+          (goto-char pos)
+          ;; return point when current is valid link
+          (throw 'reach nil)))))
   (point))
 
 (defun org-w3m-no-next-link-p ()
@@ -154,6 +190,7 @@ Return t if there is no next link; otherwise, return nil."
 (defun org-w3m-no-prev-link-p ()
   "Whether there is no previous link after the cursor.
 Return t if there is no previous link; otherwise, return nil."
+  ;; NOTE: This function seems never to be used. Should it be removed?
   (save-excursion
     (equal (point) (org-w3m-get-prev-link-start))))
 
diff --git a/lisp/ol.el b/lisp/ol.el
index de03c1b..e4a5a27 100644
--- a/lisp/ol.el
+++ b/lisp/ol.el
@@ -2,7 +2,7 @@
 
 ;; Copyright (C) 2018-2021 Free Software Foundation, Inc.
 
-;; Author: Carsten Dominik <carsten at orgmode dot org>
+;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 ;; Keywords: outlines, hypermedia, calendar, wp
 
 ;; This file is part of GNU Emacs.
@@ -214,13 +214,18 @@ relative  Relative to the current directory, i.e. the 
directory of the file
 absolute  Absolute path, if possible with ~ for home directory.
 noabbrev  Absolute path, no abbreviation of home directory.
 adaptive  Use relative path for files in the current directory and sub-
-          directories of it.  For other files, use an absolute path."
+          directories of it.  For other files, use an absolute path.
+
+Alternatively, users may supply a custom function that takes the
+full filename as an argument and returns the path."
   :group 'org-link
   :type '(choice
          (const relative)
          (const absolute)
          (const noabbrev)
-         (const adaptive))
+         (const adaptive)
+         (function))
+  :package-version '(Org . "9.5")
   :safe #'symbolp)
 
 (defcustom org-link-abbrev-alist nil
@@ -277,13 +282,6 @@ links created by planner."
   :type '(choice (const nil) (function))
   :safe #'null)
 
-(defcustom org-link-doi-server-url "https://doi.org/";
-  "The URL of the DOI server."
-  :group 'org-link-follow
-  :version "24.3"
-  :type 'string
-  :safe #'stringp)
-
 (defcustom org-link-frame-setup
   '((vm . vm-visit-folder-other-frame)
     (vm-imap . vm-visit-imap-folder-other-frame)
@@ -376,9 +374,9 @@ changes to the current buffer."
 
 Shell links can be dangerous: just think about a link
 
-     [[shell:rm -rf ~/*][Google Search]]
+     [[shell:rm -rf ~/*][Web Search]]
 
-This link would show up in your Org document as \"Google Search\",
+This link would show up in your Org document as \"Web 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
@@ -401,9 +399,9 @@ single keystroke rather than having to type \"yes\"."
   "Non-nil means ask for confirmation before executing Emacs Lisp links.
 Elisp links can be dangerous: just think about a link
 
-     [[elisp:(shell-command \"rm -rf ~/*\")][Google Search]]
+     [[elisp:(shell-command \"rm -rf ~/*\")][Web Search]]
 
-This link would show up in your Org document as \"Google Search\",
+This link would show up in your Org document as \"Web 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
@@ -444,7 +442,7 @@ negates this setting for the duration of the command."
   :safe (lambda (val) (or (booleanp val) (integerp val))))
 
 (defcustom org-link-email-description-format "Email %c: %s"
-  "Format of the description part of a link to an email or usenet message.
+  "Format of the description part of a link to an email or Usenet message.
 The following %-escapes will be replaced by corresponding information:
 
 %F   full \"From\" field
@@ -508,7 +506,7 @@ links more efficient."
   "Regular expression matching radio targets in plain text.")
 
 (defvar org-link-types-re nil
-  "Matches a link that has a url-like prefix like \"http:\"")
+  "Matches a link that has a url-like prefix like \"http:\".")
 
 (defvar org-link-angle-re nil
   "Matches link with angular brackets, spaces are allowed.")
@@ -594,7 +592,7 @@ 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 can continue with other options like
+nil to indicate that Org can continue with other options like
 exact and fuzzy text search.")
 
 
@@ -931,7 +929,7 @@ and dates."
 
 (defun org-link-encode (text table)
   "Return percent escaped representation of string TEXT.
-TEXT is a string with the text to escape. TABLE is a list of
+TEXT is a string with the text to escape.  TABLE is a list of
 characters that should be escaped."
   (mapconcat
    (lambda (c)
@@ -1322,14 +1320,6 @@ If there is no description, use the link target."
 
 ;;; Built-in link types
 
-;;;; "doi" link type
-(defun org-link--open-doi (path arg)
-  "Open a \"doi\" type link.
-PATH is a the path to search for, as a string."
-  (browse-url (url-encode-url (concat org-link-doi-server-url path)) arg))
-
-(org-link-set-parameters "doi" :follow #'org-link--open-doi)
-
 ;;;; "elisp" link type
 (defun org-link--open-elisp (path _)
   "Open a \"elisp\" type link.
@@ -1360,7 +1350,23 @@ PATH is a symbol name, as a string."
     ((and (pred boundp) variable) (describe-variable variable))
     (name (user-error "Unknown function or variable: %s" name))))
 
-(org-link-set-parameters "help" :follow #'org-link--open-help)
+(defun org-link--store-help ()
+  "Store \"help\" type link."
+  (when (eq major-mode 'help-mode)
+    (let ((symbol
+           (save-excursion
+            (goto-char (point-min))
+             ;; In case the help is about the key-binding, store the
+             ;; function instead.
+             (search-forward "runs the command " (line-end-position) t)
+             (read (current-buffer)))))
+      (org-link-store-props :type "help"
+                            :link (format "help:%s" symbol)
+                            :description nil))))
+
+(org-link-set-parameters "help"
+                         :follow #'org-link--open-help
+                         :store #'org-link--store-help)
 
 ;;;; "http", "https", "mailto", "ftp", and "news" link types
 (dolist (scheme '("ftp" "http" "https" "mailto" "news"))
@@ -1488,7 +1494,7 @@ non-nil."
            (move-beginning-of-line 2)
            (set-mark (point)))))
     (setq org-store-link-plist nil)
-    (let (link cpltxt desc description search custom-id agenda-link)
+    (let (link cpltxt desc search custom-id agenda-link) ;; description
       (cond
        ;; Store a link using an external link type, if any function is
        ;; available. If more than one can generate a link from current
@@ -1512,14 +1518,17 @@ non-nil."
                  (apply #'org-link-store-props
                         (cdr (assoc-string
                               (completing-read
-                               "Which function for creating the link? "
-                               (mapcar #'car results-alist)
-                               nil t (symbol-name name))
+                                (format "Store link with (default %s): " name)
+                                (mapcar #'car results-alist)
+                                nil t nil nil (symbol-name name))
                               results-alist)))
                  t))))
        (setq link (plist-get org-store-link-plist :link))
-       (setq desc (or (plist-get org-store-link-plist :description)
-                      link)))
+        ;; If store function actually set `:description' property, use
+        ;; it, even if it is nil.  Otherwise, fallback to link value.
+       (setq desc (if (plist-member org-store-link-plist :description)
+                       (plist-get org-store-link-plist :description)
+                    link)))
 
        ;; Store a link from a remote editing buffer.
        ((org-src-edit-buffer-p)
@@ -1577,19 +1586,6 @@ non-nil."
                              nil nil nil))))
          (org-link-store-props :type "calendar" :date cd)))
 
-       ((eq major-mode 'help-mode)
-       (let ((symbol (replace-regexp-in-string
-                      ;; Help mode escapes backquotes and backslashes
-                      ;; before displaying them.  E.g., "`" appears
-                      ;; as "\'" for reasons.  Work around this.
-                      (rx "\\" (group (or "`" "\\"))) "\\1"
-                      (save-excursion
-                        (goto-char (point-min))
-                        (looking-at "^[^ ]+")
-                        (match-string 0)))))
-         (setq link (concat "help:" symbol)))
-       (org-link-store-props :type "help"))
-
        ((eq major-mode 'w3-mode)
        (setq cpltxt (if (and (buffer-name)
                              (not (string-match "Untitled" (buffer-name))))
@@ -1619,7 +1615,7 @@ non-nil."
                      'org-create-file-search-functions))
        (setq link (concat "file:" (abbreviate-file-name buffer-file-name)
                           "::" search))
-       (setq cpltxt (or description link)))
+       (setq cpltxt (or link))) ;; description
 
        ((and (buffer-file-name (buffer-base-buffer)) (derived-mode-p 
'org-mode))
        (org-with-limited-levels
@@ -1724,7 +1720,7 @@ non-nil."
       (if (not (and interactive? link))
          (or agenda-link (and link (org-link-make-string link desc)))
        (if (member (list link desc) org-stored-links)
-           (message "This link already exists")
+           (message "This link has already been stored")
          (push (list link desc) org-stored-links)
          (message "Stored: %s" (or desc link))
          (when custom-id
@@ -1906,6 +1902,9 @@ Use TAB to complete link prefixes, then RET for 
type-specific completion support
            (setq path (expand-file-name path)))
           ((eq org-link-file-path-type 'relative)
            (setq path (file-relative-name path)))
+          ((functionp org-link-file-path-type)
+           (setq path (funcall org-link-file-path-type
+                               (expand-file-name path))))
           (t
            (save-match-data
              (if (string-match (concat "^" (regexp-quote
diff --git a/lisp/org-agenda.el b/lisp/org-agenda.el
index b196e14..354f408 100644
--- a/lisp/org-agenda.el
+++ b/lisp/org-agenda.el
@@ -1,8 +1,8 @@
-;;; org-agenda.el --- Dynamic task and appointment lists for Org
+;;; org-agenda.el --- Dynamic task and appointment lists for Org  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2004-2021 Free Software Foundation, Inc.
 
-;; Author: Carsten Dominik <carsten at orgmode dot org>
+;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: https://orgmode.org
 ;;
@@ -99,8 +99,8 @@
 (defvar org-agenda-buffer-name "*Org Agenda*")
 (defvar org-agenda-overriding-header nil)
 (defvar org-agenda-title-append nil)
-(with-no-warnings (defvar entry)) ;; unprefixed, from calendar.el
-(with-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
@@ -148,6 +148,8 @@ addresses the separator between the current and the 
previous block."
   :type 'boolean)
 
 (defcustom org-agenda-exporter-settings nil
+  ;; FIXME: Do we really want to evaluate those settings and thus force
+  ;; the user to use `quote' all the time?
   "Alist of variable/value pairs that should be active during agenda export.
 This is a good place to set options for ps-print and for htmlize.
 Note that the way this is implemented, the values will be evaluated
@@ -1188,11 +1190,11 @@ This function makes sure that dates are aligned for 
easy reading."
         (year (nth 2 date))
         (iso-week (org-days-to-iso-week
                    (calendar-absolute-from-gregorian date)))
-        (weekyear (cond ((and (= month 1) (>= iso-week 52))
-                         (1- year))
-                        ((and (= month 12) (<= iso-week 1))
-                         (1+ year))
-                        (t year)))
+        ;; (weekyear (cond ((and (= month 1) (>= iso-week 52))
+        ;;               (1- year))
+        ;;              ((and (= month 12) (<= iso-week 1))
+        ;;               (1+ year))
+        ;;              (t year)))
         (weekstring (if (= day-of-week 1)
                         (format " W%02d" iso-week)
                       "")))
@@ -1230,7 +1232,8 @@ For example, 9:30am would become 09:30 rather than  9:30."
      ":" minute ampm)))
 
 (defun org-agenda-time-of-day-to-ampm-maybe (time)
-  "Conditionally convert TIME to AM/PM format based on 
`org-agenda-timegrid-use-ampm'."
+  "Conditionally convert TIME to AM/PM format.
+This is based on `org-agenda-timegrid-use-ampm'."
   (if org-agenda-timegrid-use-ampm
       (org-agenda-time-of-day-to-ampm time)
     time))
@@ -2080,9 +2083,25 @@ For example, this value makes those two functions 
available:
 
 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 :key-type character :value-type (group function))
-  :version "24.1"
+Note that functions in this alist don't need to be quoted.
+
+You can also specify a function which collects arguments to be
+used for each call to your bulk custom function.  The argument
+collecting function will be run once and should return a list of
+arguments to pass to the bulk function.  For example:
+
+  \\='((?R set-category get-category))
+
+Now, `B R' will call the custom `get-category' which would prompt
+the user once for a category.  That category is then passed as an
+argument to `set-category' for each entry it's called against."
+  :type
+  '(alist :key-type character
+         :value-type
+          (group (function :tag "Bulk Custom Function")
+                (choice (function :tag "Bulk Custom Argument Function")
+                        (const :tag "No Bulk Custom Argument Function" nil))))
+  :package-version '(Org . "9.5")
   :group 'org-agenda)
 
 (defmacro org-agenda-with-point-at-orig-entry (string &rest body)
@@ -2090,6 +2109,7 @@ Note that functions in this alist don't need to be 
quoted."
 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."
+  (declare (debug t))
   (org-with-gensyms (marker)
     `(let ((,marker (get-text-property (if ,string 0 (point-at-bol))
                                       'org-hd-marker ,string)))
@@ -2097,7 +2117,6 @@ of the current line."
         (save-excursion
           (goto-char ,marker)
           ,@body)))))
-(def-edebug-spec org-agenda-with-point-at-orig-entry (form body))
 
 (defun org-add-agenda-custom-command (entry)
   "Replace or add a command in `org-agenda-custom-commands'.
@@ -2113,7 +2132,8 @@ works you probably want to add it to 
`org-agenda-custom-commands' for good."
 The inserted header depends on `org-agenda-overriding-header'.
 If the empty string, don't insert a header.  If any other string,
 insert it as a header.  If nil, insert DEFAULT, which should
-evaluate to a string."
+evaluate to a string.  If a function, call it and insert the
+string that it returns."
   (declare (debug (form)) (indent defun))
   `(cond
     ((not org-agenda-overriding-header) (insert ,default))
@@ -2122,6 +2142,8 @@ evaluate to a string."
      (insert (propertize org-agenda-overriding-header
                         'face 'org-agenda-structure)
             "\n"))
+    ((functionp org-agenda-overriding-header)
+     (insert (funcall org-agenda-overriding-header)))
     (t (user-error "Invalid value for `org-agenda-overriding-header': %S"
                   org-agenda-overriding-header))))
 
@@ -2238,26 +2260,26 @@ The following commands are available:
        (save (buffer-local-variables)))
     (kill-all-local-variables)
     (cl-flet ((reset-saved (var-set)
-                          "Reset variables in VAR-SET to possibly stored value 
in SAVE."
-                          (dolist (elem save)
-                            (pcase elem
-                              (`(,var . ,val)          ;ignore unbound 
variables
-                               (when (and val (memq var var-set))
-                                 (set var val)))))))
+               "Reset variables in VAR-SET to possibly stored value in SAVE."
+               (dolist (elem save)
+                 (pcase elem
+                   (`(,var . ,val)             ;ignore unbound variables
+                    (when (and val (memq var var-set))
+                      (set var val)))))))
       (cond (org-agenda-doing-sticky-redo
-            ;; Refreshing sticky agenda-buffer
-            ;;
-            ;; Preserve the value of `org-agenda-local-vars' variables.
-            (mapc #'make-local-variable org-agenda-local-vars)
-            (reset-saved org-agenda-local-vars)
-            (setq-local org-agenda-this-buffer-is-sticky t))
+             ;; Refreshing sticky agenda-buffer
+             ;;
+             ;; Preserve the value of `org-agenda-local-vars' variables.
+             (mapc #'make-local-variable org-agenda-local-vars)
+             (reset-saved org-agenda-local-vars)
+             (setq-local org-agenda-this-buffer-is-sticky t))
            (org-agenda-sticky
-            ;; Creating a sticky Agenda buffer for the first time
-            (mapc 'make-local-variable org-agenda-local-vars)
-            (setq-local org-agenda-this-buffer-is-sticky t))
+             ;; Creating a sticky Agenda buffer for the first time
+             (mapc #'make-local-variable org-agenda-local-vars)
+             (setq-local org-agenda-this-buffer-is-sticky t))
            (t
-            ;; Creating a non-sticky agenda buffer
-            (setq-local org-agenda-this-buffer-is-sticky nil)))
+             ;; Creating a non-sticky agenda buffer
+             (setq-local org-agenda-this-buffer-is-sticky nil)))
       (mapc #'make-local-variable agenda-local-vars-to-keep)
       (reset-saved agenda-local-vars-to-keep)))
   (setq org-agenda-undo-list nil
@@ -2271,8 +2293,8 @@ The following commands are available:
   (use-local-map org-agenda-mode-map)
   (when org-startup-truncated (setq truncate-lines t))
   (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)
+  (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
   (if (boundp 'filter-buffer-substring-functions)
       (add-hook 'filter-buffer-substring-functions
@@ -2300,11 +2322,9 @@ The following commands are available:
       '(org-edit-agenda-file-list)
       (not (get 'org-agenda-files 'org-restrict)))
      "--")
-    (mapcar 'org-file-menu-entry (org-agenda-files))))
+    (mapcar #'org-file-menu-entry (org-agenda-files))))
   (org-agenda-set-mode-name)
-  (apply
-   (if (fboundp 'run-mode-hooks) 'run-mode-hooks 'run-hooks)
-   (list 'org-agenda-mode-hook)))
+  (run-mode-hooks 'org-agenda-mode-hook))
 
 (substitute-key-definition #'undo #'org-agenda-undo
                           org-agenda-mode-map global-map)
@@ -2452,7 +2472,7 @@ The following commands are available:
 (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"
+(easy-menu-define org-agenda-menu org-agenda-mode-map "Agenda menu."
   '("Agenda"
     ("Agenda Files")
     "--"
@@ -2644,7 +2664,7 @@ that have been changed along."
       (while (bufferp (setq buf (pop entry)))
        (when (pop entry)
          (with-current-buffer buf
-           (let ((last-undo-buffer buf)
+           (let (;; (last-undo-buffer buf)
                   (inhibit-read-only t))
              (unless (memq buf org-agenda-undo-has-started-in)
                (push buf org-agenda-undo-has-started-in)
@@ -2796,7 +2816,7 @@ to limit entries to in this type."
 (defvar org-keys nil)
 (defvar org-match nil)
 ;;;###autoload
-(defun org-agenda (&optional arg org-keys restriction)
+(defun org-agenda (&optional arg keys restriction)
   "Dispatch agenda commands to collect entries to the agenda buffer.
 Prompts for a command to execute.  Any prefix arg will be passed
 on to the selected command.  The default selections are:
@@ -2831,7 +2851,8 @@ Pressing `<' twice means to restrict to the current 
subtree or region
 \(if active)."
   (interactive "P")
   (catch 'exit
-    (let* ((prefix-descriptions nil)
+    (let* ((org-keys keys)
+          (prefix-descriptions nil)
           (org-agenda-buffer-name org-agenda-buffer-name)
           (org-agenda-window-setup (if (equal (buffer-name)
                                               org-agenda-buffer-name)
@@ -2853,9 +2874,9 @@ Pressing `<' twice means to restrict to the current 
subtree or region
           (org-agenda-custom-commands
            (org-contextualize-keys
             org-agenda-custom-commands org-agenda-custom-commands-contexts))
-          (buf (current-buffer))
+          ;; (buf (current-buffer))
           (bfn (buffer-file-name (buffer-base-buffer)))
-          entry key type org-match lprops ans)
+          entry type org-match lprops ans) ;; key
       ;; Turn off restriction unless there is an overriding one,
       (unless org-agenda-overriding-restriction
        (unless org-agenda-keep-restricted-file-list
@@ -2907,47 +2928,51 @@ Pressing `<' twice means to restrict to the current 
subtree or region
        ((setq entry (assoc org-keys org-agenda-custom-commands))
        (if (or (symbolp (nth 2 entry)) (functionp (nth 2 entry)))
            (progn
-             (setq type (nth 2 entry) org-match (eval (nth 3 entry))
+             ;; FIXME: Is (nth 3 entry) supposed to have access (via dynvars)
+              ;; to some of the local variables?  There's no doc about
+              ;; that for `org-agenda-custom-commands'.
+             (setq type (nth 2 entry) org-match (eval (nth 3 entry) t)
                    lprops (nth 4 entry))
              (when org-agenda-sticky
                (setq org-agenda-buffer-name
                      (or (and (stringp org-match) (format "*Org 
Agenda(%s:%s)*" org-keys org-match))
                          (format "*Org Agenda(%s)*" org-keys))))
              (put 'org-agenda-redo-command 'org-lprops lprops)
-             (cond
-              ((eq type 'agenda)
-               (org-let lprops '(org-agenda-list current-prefix-arg)))
-              ((eq type 'agenda*)
-               (org-let lprops '(org-agenda-list current-prefix-arg nil nil 
t)))
-              ((eq type 'alltodo)
-               (org-let lprops '(org-todo-list current-prefix-arg)))
-              ((eq type 'search)
-               (org-let lprops '(org-search-view current-prefix-arg org-match 
nil)))
-              ((eq type 'stuck)
-               (org-let lprops '(org-agenda-list-stuck-projects
-                                 current-prefix-arg)))
-              ((eq type 'tags)
-               (org-let lprops '(org-tags-view current-prefix-arg org-match)))
-              ((eq type 'tags-todo)
-               (org-let lprops '(org-tags-view '(4) org-match)))
-              ((eq type 'todo)
-               (org-let lprops '(org-todo-list org-match)))
-              ((eq type 'tags-tree)
-               (org-check-for-org-mode)
-               (org-let lprops '(org-match-sparse-tree current-prefix-arg 
org-match)))
-              ((eq type 'todo-tree)
-               (org-check-for-org-mode)
-               (org-let lprops
-                 '(org-occur (concat "^" org-outline-regexp "[ \t]*"
-                                     (regexp-quote org-match) "\\>"))))
-              ((eq type 'occur-tree)
-               (org-check-for-org-mode)
-               (org-let lprops '(org-occur org-match)))
-              ((functionp type)
-               (org-let lprops '(funcall type org-match)))
-              ((fboundp type)
-               (org-let lprops '(funcall type org-match)))
-              (t (user-error "Invalid custom agenda command type %s" type))))
+             (cl-progv
+                 (mapcar #'car lprops)
+                 (mapcar (lambda (binding) (eval (cadr binding) t)) lprops)
+               (pcase type
+                 (`agenda
+                  (org-agenda-list current-prefix-arg))
+                 (`agenda*
+                  (org-agenda-list current-prefix-arg nil nil t))
+                 (`alltodo
+                  (org-todo-list current-prefix-arg))
+                 (`search
+                  (org-search-view current-prefix-arg org-match nil))
+                 (`stuck
+                  (org-agenda-list-stuck-projects current-prefix-arg))
+                 (`tags
+                  (org-tags-view current-prefix-arg org-match))
+                 (`tags-todo
+                  (org-tags-view '(4) org-match))
+                 (`todo
+                  (org-todo-list org-match))
+                 (`tags-tree
+                  (org-check-for-org-mode)
+                  (org-match-sparse-tree current-prefix-arg org-match))
+                 (`todo-tree
+                  (org-check-for-org-mode)
+                  (org-occur (concat "^" org-outline-regexp "[ \t]*"
+                                     (regexp-quote org-match) "\\>")))
+                 (`occur-tree
+                  (org-check-for-org-mode)
+                  (org-occur org-match))
+                 ((pred functionp)
+                  (funcall type org-match))
+                 ;; FIXME: Will signal an error since it's not `functionp'!
+                 ((pred fboundp) (funcall type org-match))
+                 (_ (user-error "Invalid custom agenda command type %s" 
type)))))
          (org-agenda-run-series (nth 1 entry) (cddr entry))))
        ((equal org-keys "C")
        (setq org-agenda-custom-commands org-agenda-custom-commands-orig)
@@ -3205,7 +3230,7 @@ s   Search for keywords                 M   Like m, but 
only TODO entries
             (delete-window)
             (org-agenda-get-restriction-and-command prefix-descriptions))
 
-          ((equal c ?q) (error "Abort"))
+          ((equal c ?q) (user-error "Abort"))
           (t (user-error "Invalid key %c" c))))))))
 
 (defun org-agenda-fit-window-to-buffer ()
@@ -3224,63 +3249,81 @@ s   Search for keywords                 M   Like m, but 
only TODO entries
 (defvar org-agenda-overriding-cmd nil)
 (defvar org-agenda-overriding-arguments nil)
 (defvar org-agenda-overriding-cmd-arguments nil)
+
+(defun org-let (list &rest body) ;FIXME: So many kittens are suffering here.
+  (declare (indent 1) (obsolete cl-progv "2021"))
+  (eval (cons 'let (cons list body))))
+
+(defun org-let2 (list1 list2 &rest body) ;FIXME: Where did our karma go?
+  (declare (indent 2) (obsolete cl-progv "2021"))
+  (eval (cons 'let (cons list1 (list (cons 'let (cons list2 body)))))))
+
 (defun org-agenda-run-series (name series)
   "Run agenda NAME as a SERIES of agenda commands."
-  (org-let (nth 1 series) '(org-agenda-prepare name))
-  ;; We need to reset agenda markers here, because when constructing a
-  ;; block agenda, the individual blocks do not do that.
-  (org-agenda-reset-markers)
-  (let* ((org-agenda-multi t)
-        (redo (list 'org-agenda-run-series name (list 'quote series)))
-        (cmds (car series))
-        (gprops (nth 1 series))
-        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))
-      (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
-                    org-agenda-overriding-cmd-arguments))))
-       (cond
-        ((eq type 'agenda)
-         (org-let2 gprops lprops
-           '(call-interactively 'org-agenda-list)))
-        ((eq type 'agenda*)
-         (org-let2 gprops lprops
-           '(funcall 'org-agenda-list nil nil t)))
-        ((eq type 'alltodo)
-         (org-let2 gprops lprops
-           '(call-interactively 'org-todo-list)))
-        ((eq type 'search)
-         (org-let2 gprops lprops
-           '(org-search-view current-prefix-arg match nil)))
-        ((eq type 'stuck)
-         (org-let2 gprops lprops
-           '(call-interactively 'org-agenda-list-stuck-projects)))
-        ((eq type 'tags)
-         (org-let2 gprops lprops
-           '(org-tags-view current-prefix-arg match)))
-        ((eq type 'tags-todo)
-         (org-let2 gprops lprops
-           '(org-tags-view '(4) match)))
-        ((eq type 'todo)
-         (org-let2 gprops lprops
-           '(org-todo-list match)))
-        ((fboundp type)
-         (org-let2 gprops lprops
-           '(funcall type match)))
-        (t (error "Invalid type in command series")))))
-    (widen)
-    (let ((inhibit-read-only t))
-      (add-text-properties (point-min) (point-max)
-                          `(org-series t org-series-redo-cmd ,redo)))
-    (setq org-agenda-redo-command redo)
-    (goto-char (point-min)))
-  (org-agenda-fit-window-to-buffer)
-  (org-let (nth 1 series) '(org-agenda-finalize)))
+  (let* ((gprops (nth 1 series))
+         (gvars (mapcar #'car gprops))
+         (gvals (mapcar (lambda (binding) (eval (cadr binding) t)) gprops)))
+    (cl-progv gvars gvals (org-agenda-prepare name))
+    ;; We need to reset agenda markers here, because when constructing a
+    ;; block agenda, the individual blocks do not do that.
+    (org-agenda-reset-markers)
+    (with-no-warnings
+      (defvar match))          ;Used via the `eval' below.
+    (let* ((org-agenda-multi t)
+          ;; FIXME: Redo should contain lists of (FUNS . ARGS) rather
+           ;; than expressions, so you don't need to `quote' the args
+           ;; and you just need to `apply' instead of `eval' when using it.
+          (redo (list 'org-agenda-run-series name (list 'quote series)))
+          (cmds (car series))
+          match
+          org-cmd type lprops)
+      (while (setq org-cmd (pop cmds))
+        (setq type (car org-cmd))
+        (setq match (eval (nth 1 org-cmd) t))
+        (setq lprops (nth 2 org-cmd))
+        (let ((org-agenda-overriding-arguments
+              (if (eq org-agenda-overriding-cmd org-cmd)
+                  (or org-agenda-overriding-arguments
+                      org-agenda-overriding-cmd-arguments)))
+              (lvars (mapcar #'car lprops))
+              (lvals (mapcar (lambda (binding) (eval (cadr binding) t)) 
lprops)))
+          (cl-progv (append gvars lvars) (append gvals lvals)
+           (pcase type
+             (`agenda
+              (call-interactively 'org-agenda-list))
+             (`agenda*
+              (funcall 'org-agenda-list nil nil t))
+             (`alltodo
+              (call-interactively 'org-todo-list))
+             (`search
+              (org-search-view current-prefix-arg match nil))
+             (`stuck
+              (call-interactively 'org-agenda-list-stuck-projects))
+             (`tags
+              (org-tags-view current-prefix-arg match))
+             (`tags-todo
+              (org-tags-view '(4) match))
+             (`todo
+              (org-todo-list match))
+             ((pred fboundp)
+              (funcall type match))
+             (_ (error "Invalid type in command series"))))))
+      (widen)
+      (let ((inhibit-read-only t))
+       (add-text-properties (point-min) (point-max)
+                            `(org-series t org-series-redo-cmd ,redo)))
+      (setq org-agenda-redo-command redo)
+      (goto-char (point-min)))
+    (org-agenda-fit-window-to-buffer)
+    (cl-progv gvars gvals (org-agenda-finalize))))
+
+(defun org-agenda--split-plist (plist)
+  ;; We could/should arguably use `map-keys' and `map-values'.
+  (let (keys vals)
+    (while plist
+      (push (pop plist) keys)
+      (push (pop plist) vals))
+    (cons (nreverse keys) (nreverse vals))))
 
 ;;;###autoload
 (defmacro org-batch-agenda (cmd-key &rest parameters)
@@ -3290,7 +3333,13 @@ If CMD-KEY is a string of length 1, it is used as a key 
in
 longer string it is used as a tags/todo match string.
 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)
+  (pcase-let ((`(,vars . ,exps) (org-agenda--split-plist parameters)))
+    `(org--batch-agenda ,cmd-key ',vars (list ,@exps))))
+
+(defun org--batch-agenda (cmd-key vars vals)
+  ;; `org-batch-agenda' is a macro because every other "parameter" is
+  ;; a variable name rather than an expression to evaluate.  Yuck!
+  (cl-progv vars vals
     (let (org-agenda-sticky)
       (if (> (length cmd-key) 1)
          (org-tags-view nil cmd-key)
@@ -3335,11 +3384,18 @@ extra        String with extra planning info
 priority-l   The priority letter if any was given
 priority-n   The computed numerical priority
 agenda-day   The day in the agenda where this is listed"
-  (org-eval-in-environment (append '((org-agenda-remove-tags t))
-                                  (org-make-parameter-alist parameters))
-    (if (> (length cmd-key) 2)
-       (org-tags-view nil cmd-key)
-      (org-agenda nil cmd-key)))
+  (pcase-let ((`(,vars . ,exps) (org-agenda--split-plist parameters)))
+    `(org--batch-agenda-csv ,cmd-key ',vars (list ,@exps))))
+
+(defun org--batch-agenda-csv (cmd-key vars vals)
+  ;; `org-batch-agenda-csv' is a macro because every other "parameter" is
+  ;; a variable name rather than an expression to evaluate.  Yuck!
+  (let ((org-agenda-remove-tags t))
+    (cl-progv vars vals
+      ;; FIXME: Shouldn't this be 1 (see commit 10173ad6d610b)?
+      (if (> (length cmd-key) 2)
+         (org-tags-view nil cmd-key)
+       (org-agenda nil cmd-key))))
   (set-buffer org-agenda-buffer-name)
   (let ((lines (org-split-string (buffer-string) "\n")))
     (dolist (line lines)
@@ -3347,9 +3403,9 @@ agenda-day   The day in the agenda where this is listed"
        (setq org-agenda-info
              (org-fix-agenda-info (text-properties-at 0 line)))
        (princ
-        (mapconcat 'org-agenda-export-csv-mapper
+        (mapconcat #'org-agenda-export-csv-mapper
                    '(org-category txt type todo tags date time extra
-                                  priority-letter priority agenda-day)
+                                  priority-letter priority agenda-day)
                    ","))
        (princ "\n")))))
 
@@ -3358,7 +3414,7 @@ agenda-day   The day in the agenda where this is listed"
 This ensures the export commands can easily use it."
   (let (tmp re)
     (when (setq tmp (plist-get props 'tags))
-      (setq props (plist-put props 'tags (mapconcat 'identity tmp ":"))))
+      (setq props (plist-put props 'tags (mapconcat #'identity tmp ":"))))
     (when (setq tmp (plist-get props 'date))
       (when (integerp tmp) (setq tmp (calendar-gregorian-from-absolute tmp)))
       (let ((calendar-date-display-form '(year "-" month "-" day)))
@@ -3394,19 +3450,22 @@ This ensures the export commands can easily use it."
     (org-trim (replace-regexp-in-string "," ";" res nil t))))
 
 ;;;###autoload
-(defun org-store-agenda-views (&rest parameters)
+(defun org-store-agenda-views (&rest _parameters)
   "Store agenda views."
   (interactive)
-  (eval (list 'org-batch-store-agenda-views)))
+  (org--batch-store-agenda-views nil nil))
 
 ;;;###autoload
 (defmacro org-batch-store-agenda-views (&rest parameters)
   "Run all custom agenda commands that have a file argument."
+  (pcase-let ((`(,vars . ,exps) (org-agenda--split-plist parameters)))
+    `(org--batch-store-agenda-views ',vars (list ,@exps))))
+
+(defun org--batch-store-agenda-views (vars vals)
   (let ((cmds (org-agenda-normalize-custom-commands 
org-agenda-custom-commands))
-       (pop-up-frames nil)
-       (dir default-directory)
-       (pars (org-make-parameter-alist parameters))
-       cmd thiscmdkey thiscmdcmd match files opts cmd-or-set bufname)
+        (pop-up-frames nil)
+        (dir default-directory)
+        cmd thiscmdkey thiscmdcmd match files opts cmd-or-set bufname)
     (save-window-excursion
       (while cmds
        (setq cmd (pop cmds)
@@ -3423,14 +3482,18 @@ This ensures the export commands can easily use it."
              files (nth (if (listp cmd-or-set) 4 5) cmd))
        (if (stringp files) (setq files (list files)))
        (when files
-         (org-eval-in-environment (append org-agenda-exporter-settings
-                                          opts pars)
-           (org-agenda nil thiscmdkey))
-         (set-buffer bufname)
-         (while files
-           (org-eval-in-environment (append org-agenda-exporter-settings
-                                            opts pars)
-             (org-agenda-write (expand-file-name (pop files) dir) nil t 
bufname)))
+         (let* ((opts (append org-agenda-exporter-settings opts))
+                (vars (append (mapcar #'car opts) vars))
+                (vals (append (mapcar (lambda (binding) (eval (cadr binding) 
t))
+                                      opts)
+                              vals)))
+           (cl-progv vars vals
+             (org-agenda nil thiscmdkey))
+           (set-buffer bufname)
+           (while files
+             (cl-progv vars vals
+               (org-agenda-write (expand-file-name (pop files) dir)
+                                 nil t bufname))))
          (and (get-buffer bufname)
               (kill-buffer bufname)))))))
 
@@ -3470,80 +3533,87 @@ the agenda to write."
               (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)))
-              (extension (file-name-extension file))
-              (default-directory (file-name-directory 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 'invisible 'org-filtered)
-            (run-hooks 'org-agenda-before-write-hook)
-            (cond
-             ((bound-and-true-p org-mobile-creating-agendas)
-              (org-mobile-write-agenda-for-mobile 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))
-                  (goto-char p)
-                  (setq m (get-text-property (point) 'org-hd-marker))
-                  (when m
-                    (push (save-excursion
-                            (set-buffer (marker-buffer m))
-                            (goto-char m)
-                            (org-copy-subtree 1 nil t t)
-                            org-subtree-clip)
-                          content)))
-                (find-file file)
-                (erase-buffer)
-                (dolist (s content) (org-paste-subtree 1 s))
-                (write-file file)
-                (kill-buffer (current-buffer))
-                (message "Org file written to %s" file)))
-             ((member extension '("html" "htm"))
-              (or (require 'htmlize nil t)
-                  (error "Please install htmlize from 
https://github.com/hniksic/emacs-htmlize";))
-              (set-buffer (htmlize-buffer (current-buffer)))
-              (when org-agenda-export-html-style
-                ;; replace <style> section with org-agenda-export-html-style
-                (goto-char (point-min))
-                (kill-region (- (search-forward "<style") 6)
-                             (search-forward "</style>"))
-                (insert org-agenda-export-html-style))
-              (write-file file)
-              (kill-buffer (current-buffer))
-              (message "HTML written to %s" file))
-             ((string= "ps" extension)
-              (require 'ps-print)
-              (ps-print-buffer-with-faces file)
-              (message "Postscript written to %s" file))
-             ((string= "pdf" extension)
-              (require 'ps-print)
-              (ps-print-buffer-with-faces
-               (concat (file-name-sans-extension file) ".ps"))
-              (call-process "ps2pdf" nil nil nil
-                            (expand-file-name
-                             (concat (file-name-sans-extension file) ".ps"))
-                            (expand-file-name file))
-              (delete-file (concat (file-name-sans-extension file) ".ps"))
-              (message "PDF written to %s" file))
-             ((string= "ics" extension)
-              (require 'ox-icalendar)
-              (org-icalendar-export-current-agenda (expand-file-name file)))
-             (t
-              (let ((bs (buffer-string)))
-                (find-file file)
-                (erase-buffer)
-                (insert bs)
-                (save-buffer 0)
-                (kill-buffer (current-buffer))
-                (message "Plain text written to %s" file))))))))
+  (cl-progv
+      (if nosettings nil (mapcar #'car org-agenda-exporter-settings))
+      (if nosettings nil (mapcar (lambda (binding) (eval (cadr binding) t))
+                                 org-agenda-exporter-settings))
+    (save-excursion
+      (save-window-excursion
+       (let ((bs (copy-sequence (buffer-string)))
+             (extension (file-name-extension file))
+             (default-directory (file-name-directory 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 'invisible 'org-filtered)
+           (run-hooks 'org-agenda-before-write-hook)
+           (cond
+            ((bound-and-true-p org-mobile-creating-agendas)
+             (org-mobile-write-agenda-for-mobile 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))
+                 (goto-char p)
+                 (setq m (get-text-property (point) 'org-hd-marker))
+                 (when m
+                   (push (with-current-buffer (marker-buffer m)
+                           (goto-char m)
+                           (org-copy-subtree 1 nil t t)
+                           org-subtree-clip)
+                         content)))
+               (find-file file)
+               (erase-buffer)
+               (dolist (s content) (org-paste-subtree 1 s))
+               (write-file file)
+               (kill-buffer (current-buffer))
+               (message "Org file written to %s" file)))
+            ((member extension '("html" "htm"))
+             (or (require 'htmlize nil t)
+                 (error "Please install htmlize from 
https://github.com/hniksic/emacs-htmlize";))
+             (declare-function htmlize-buffer "htmlize" (&optional buffer))
+             (set-buffer (htmlize-buffer (current-buffer)))
+             (when org-agenda-export-html-style
+               ;; replace <style> section with org-agenda-export-html-style
+               (goto-char (point-min))
+               (kill-region (- (search-forward "<style") 6)
+                            (search-forward "</style>"))
+               (insert org-agenda-export-html-style))
+             (write-file file)
+             (kill-buffer (current-buffer))
+             (message "HTML written to %s" file))
+            ((string= "ps" extension)
+             (require 'ps-print)
+             (ps-print-buffer-with-faces file)
+             (message "Postscript written to %s" file))
+            ((string= "pdf" extension)
+             (require 'ps-print)
+             (ps-print-buffer-with-faces
+              (concat (file-name-sans-extension file) ".ps"))
+             (call-process "ps2pdf" nil nil nil
+                           (expand-file-name
+                            (concat (file-name-sans-extension file) ".ps"))
+                           (expand-file-name file))
+             (delete-file (concat (file-name-sans-extension file) ".ps"))
+             (message "PDF written to %s" file))
+            ((string= "ics" extension)
+             (require 'ox-icalendar)
+             (declare-function org-icalendar-export-current-agenda
+                               "ox-icalendar" (file))
+             (org-icalendar-export-current-agenda (expand-file-name file)))
+            (t
+             (let ((bs (buffer-string)))
+               (find-file file)
+               (erase-buffer)
+               (insert bs)
+               (save-buffer 0)
+               (kill-buffer (current-buffer))
+               (message "Plain text written to %s" file))))))))
     (set-buffer (or agenda-bufname
+                   ;; FIXME: I'm pretty sure called-interactively-p
+                    ;; doesn't do what we want here!
                    (and (called-interactively-p 'any) (buffer-name))
                    org-agenda-buffer-name)))
   (when open (org-open-file file)))
@@ -3699,15 +3769,14 @@ the global options and expect it to be applied to the 
entire view.")
     (tag . org-agenda-tag-filter)
     (effort . org-agenda-effort-filter)
     (regexp . org-agenda-regexp-filter))
-  "Alist of filter types and associated variables")
+  "Alist of filter types and associated variables.")
 (defun org-agenda-filter-any ()
   "Is any filter active?"
-  (let ((form (cons 'or (mapcar (lambda (x)
-                                 (if (or (symbol-value (cdr x))
-                                         (get :preset-filter x))
-                                     t nil))
-                               org-agenda-filter-variables))))
-    (eval form)))
+  (cl-some (lambda (x)
+            (or (symbol-value (cdr x))
+                (get :preset-filter x)))
+          org-agenda-filter-variables))
+
 (defvar org-agenda-category-filter-preset nil
   "A preset of the category filter used for secondary agenda filtering.
 This must be a list of strings, each string must be a single category
@@ -3945,7 +4014,7 @@ agenda display, configure `org-agenda-finalize-hook'."
        (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))
+       (add-hook 'kill-buffer-hook #'org-agenda-reset-markers 'append 'local))
       (run-hooks 'org-agenda-finalize-hook))))
 
 (defun org-agenda-mark-clocking-task ()
@@ -4014,10 +4083,10 @@ agenda display, configure `org-agenda-finalize-hook'."
 
 (defvar org-depend-tag-blocked)
 
-(defun org-agenda-dim-blocked-tasks (&optional invisible)
+(defun org-agenda-dim-blocked-tasks (&optional _invisible)
   "Dim currently blocked TODOs in the agenda display.
 When INVISIBLE is non-nil, hide currently blocked TODO instead of
-dimming them."
+dimming them."                   ;FIXME: The arg isn't used, actually!
   (interactive "P")
   (when (called-interactively-p 'interactive)
     (message "Dim or hide blocked tasks..."))
@@ -4127,7 +4196,7 @@ functions do."
           (save-match-data
             (if fp
                 (funcall form)
-              (eval form)))))))
+              (eval form t)))))))
 
 (defvar org-agenda-markers nil
   "List of all currently active markers created by `org-agenda'.")
@@ -4201,6 +4270,9 @@ This check for agenda markers in all agenda buffers 
currently active."
   "Return the face DATE should be displayed with."
   (cond ((and (functionp org-agenda-day-face-function)
              (funcall org-agenda-day-face-function date)))
+       ((and (org-agenda-today-p date)
+              (memq (calendar-day-of-week date) org-agenda-weekend-days))
+         'org-agenda-date-weekend-today)
        ((org-agenda-today-p date) 'org-agenda-date-today)
        ((memq (calendar-day-of-week date) org-agenda-weekend-days)
         'org-agenda-date-weekend)
@@ -4243,7 +4315,7 @@ items if they have an hour specification like [h]h:mm."
     (setq span arg arg nil))
   (when (numberp span)
     (unless (< 0 span)
-      (user-error "Agenda creation impossible for this span(=%d days)." span)))
+      (user-error "Agenda creation impossible for this span(=%d days)" span)))
   (catch 'exit
     (setq org-agenda-buffer-name
          (org-agenda--get-buffer-name
@@ -4281,11 +4353,11 @@ items if they have an hour specification like [h]h:mm."
           (day-cnt 0)
           (inhibit-redisplay (not debug-on-error))
           (org-agenda-show-log-scoped org-agenda-show-log)
-          s e rtn rtnall file date d start-pos end-pos todayp
-          clocktable-start clocktable-end filter)
+          s rtn rtnall file date d start-pos end-pos todayp ;; e
+          clocktable-start clocktable-end) ;; filter
       (setq org-agenda-redo-command
            (list 'org-agenda-list (list 'quote arg) start-day (list 'quote 
span) with-hour))
-      (dotimes (n (1- ndays))
+      (dotimes (_ (1- ndays))
        (push (1+ (car day-numbers)) day-numbers))
       (setq day-numbers (nreverse day-numbers))
       (setq clocktable-start (car day-numbers)
@@ -4351,11 +4423,11 @@ items if they have an hour specification like [h]h:mm."
                (setq rtn (org-agenda-get-day-entries
                           file date :closed)))
               (org-agenda-show-log-scoped
-               (setq rtn (apply 'org-agenda-get-day-entries
+               (setq rtn (apply #'org-agenda-get-day-entries
                                 file date
                                 (append '(:closed) org-agenda-entry-types))))
               (t
-               (setq rtn (apply 'org-agenda-get-day-entries
+               (setq rtn (apply #'org-agenda-get-day-entries
                                 file date
                                 org-agenda-entry-types)))))
            (setq rtnall (append rtnall rtn)))) ;; all entries
@@ -4395,7 +4467,7 @@ items if they have an hour specification like [h]h:mm."
          (setq p (plist-put p :tstart clocktable-start))
          (setq p (plist-put p :tend clocktable-end))
          (setq p (plist-put p :scope 'agenda))
-         (setq tbl (apply 'org-clock-get-clocktable p))
+         (setq tbl (apply #'org-clock-get-clocktable p))
          (insert tbl)))
       (goto-char (point-min))
       (or org-agenda-multi (org-agenda-fit-window-to-buffer))
@@ -4524,7 +4596,7 @@ is active."
                      '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 location")))
+                     'help-echo "mouse-2 or RET jump to location"))
         (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
@@ -4616,7 +4688,7 @@ is active."
                      (setq re (regexp-quote (downcase w)))))
                  (if neg (push re regexps-) (push re regexps+)))
                words)
-       (push (mapconcat (lambda (w) (regexp-quote w)) words "\\s-+")
+       (push (mapconcat #'regexp-quote words "\\s-+")
              regexps+))
       (setq regexps+ (sort regexps+ (lambda (a b) (> (length a) (length b)))))
       (if (not regexps+)
@@ -4739,7 +4811,7 @@ is active."
                               (list 'face 'org-agenda-structure))
          (setq pos (point))
          (insert string "\n")
-         (add-text-properties pos (1- (point)) (list 'face 'org-warning))
+         (add-text-properties pos (1- (point)) (list 'face 
'org-agenda-structure-filter))
          (setq pos (point))
          (unless org-agenda-multi
            (insert (substitute-command-keys "\\<org-agenda-mode-map>\
@@ -4749,7 +4821,7 @@ Press `\\[org-agenda-manipulate-query-add]', \
 `\\[org-agenda-manipulate-query-subtract-re]' to add/sub regexp, \
 `\\[universal-argument] \\[org-agenda-redo]' for a fresh search\n"))
            (add-text-properties pos (1- (point))
-                                (list 'face 'org-agenda-structure)))
+                                (list 'face 'org-agenda-structure-secondary)))
          (buffer-string)))
       (org-agenda-mark-header-line (point-min))
       (when rtnall
@@ -4770,10 +4842,10 @@ Press `\\[org-agenda-manipulate-query-add]', \
   "Use `org-todo-keyword-faces' for the selected todo KEYWORDS."
   (concat
    (if (or (equal keywords "ALL") (not keywords))
-       (propertize "ALL" 'face 'warning)
+       (propertize "ALL" 'face 'org-agenda-structure-filter)
      (mapconcat
       (lambda (kw)
-        (propertize kw 'face (org-get-todo-face kw)))
+        (propertize kw 'face (list (org-get-todo-face kw) 
'org-agenda-structure)))
       (org-split-string keywords "|")
       "|"))
    "\n"))
@@ -4781,6 +4853,8 @@ Press `\\[org-agenda-manipulate-query-add]', \
 (defvar org-select-this-todo-keyword nil)
 (defvar org-last-arg nil)
 
+(defvar crm-separator)
+
 ;;;###autoload
 (defun org-todo-list (&optional arg)
   "Show all (not done) TODO entries from all agenda file in a single list.
@@ -4856,7 +4930,7 @@ to search again: (0)[ALL]"))
                     (insert "\n                     "))
                   (insert " " s))))
            (insert "\n"))
-         (add-text-properties pos (1- (point)) (list 'face 
'org-agenda-structure))
+         (add-text-properties pos (1- (point)) (list 'face 
'org-agenda-structure-secondary))
          (buffer-string)))
       (org-agenda-mark-header-line (point-min))
       (when rtnall
@@ -4947,7 +5021,7 @@ The prefix arg TODO-ONLY limits the search to TODO 
entries."
                                     (concat "Match: " match)))
          (setq pos (point))
          (insert match "\n")
-         (add-text-properties pos (1- (point)) (list 'face 'org-warning))
+         (add-text-properties pos (1- (point)) (list 'face 
'org-agenda-structure-filter))
          (setq pos (point))
          (unless org-agenda-multi
            (insert (substitute-command-keys
@@ -4955,7 +5029,7 @@ The prefix arg TODO-ONLY limits the search to TODO 
entries."
 \\<org-agenda-mode-map>`\\[universal-argument] \\[org-agenda-redo]' \
 to search again\n")))
          (add-text-properties pos (1- (point))
-                              (list 'face 'org-agenda-structure))
+                              (list 'face 'org-agenda-structure-secondary))
          (buffer-string)))
       (org-agenda-mark-header-line (point-min))
       (when rtnall
@@ -4981,10 +5055,11 @@ used by user-defined selections using 
`org-agenda-skip-function'.")
 (defvar org-agenda-overriding-header nil
   "When set during agenda, todo and tags searches it replaces the header.
 If an empty string, no header will be inserted.  If any other
-string, it will be inserted as a header.  If nil, a header will
-be generated automatically according to the command.  This
-variable should not be set directly, but custom commands can bind
-it in the options section.")
+string, it will be inserted as a header.  If a function, insert
+the string returned by the function as a header.  If nil, a
+header will be generated automatically according to the command.
+This variable should not be set directly, but custom commands can
+bind it in the options section.")
 
 (defun org-agenda-skip-entry-if (&rest conditions)
   "Skip entry if any of CONDITIONS is true.
@@ -4997,7 +5072,7 @@ See `org-agenda-skip-if' for details."
   (org-agenda-skip-if t conditions))
 
 (defun org-agenda-skip-if (subtree conditions)
-  "Checks current entity for CONDITIONS.
+  "Check current entity for CONDITIONS.
 If SUBTREE is non-nil, the entire subtree is checked.  Otherwise, only
 the entry (i.e. the text before the next heading) is checked.
 
@@ -5036,7 +5111,7 @@ If any of these conditions is met, this function returns 
the end point of
 the entity, causing the search to continue from there.  This is a function
 that can be put into `org-agenda-skip-function' for the duration of a command."
   (org-back-to-heading t)
-  (let* ((beg (point))
+  (let* (;; (beg (point))
         (end (if subtree (save-excursion (org-end-of-subtree t) (point))
                (org-entry-end-position)))
         (planning-end (if subtree end (line-end-position 2)))
@@ -5110,7 +5185,7 @@ a list of TODO keywords, or a state symbol `todo' or 
`done' or
       (`(,type . ,_) (error "Unknown TODO skip type: %S" type)))))
 
 ;;;###autoload
-(defun org-agenda-list-stuck-projects (&rest ignore)
+(defun org-agenda-list-stuck-projects (&rest _ignore)
   "Create agenda view for projects that are stuck.
 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
@@ -5148,12 +5223,12 @@ of what a project is and how to check if it stuck, 
customize the variable
         (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))))))
+         (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
@@ -5169,24 +5244,28 @@ of what a project is and how to check if it stuck, 
customize the variable
 (defvar org-disable-agenda-to-diary nil)          ;Dynamically-scoped param.
 (defvar diary-list-entries-hook)
 (defvar diary-time-regexp)
+(defvar diary-modify-entry-list-string-function)
+(defvar diary-file-name-prefix)
+(defvar diary-display-function)
+
 (defun org-get-entries-from-diary (date)
   "Get the (Emacs Calendar) diary entries for DATE."
   (require 'diary-lib)
+  (declare-function diary-fancy-display "diary-lib" ())
   (let* ((diary-fancy-buffer "*temporary-fancy-diary-buffer*")
-        (diary-display-function 'diary-fancy-display)
+        (diary-display-function #'diary-fancy-display)
         (pop-up-frames nil)
         (diary-list-entries-hook
          (cons 'org-diary-default-entry diary-list-entries-hook))
         (diary-file-name-prefix nil) ; turn this feature off
-        (diary-modify-entry-list-string-function 
'org-modify-diary-entry-string)
+        (diary-modify-entry-list-string-function
+         #'org-modify-diary-entry-string)
         (diary-time-regexp (concat "^" diary-time-regexp))
         entries
         (org-disable-agenda-to-diary t))
     (save-excursion
       (save-window-excursion
-       (funcall (if (fboundp 'diary-list-entries)
-                    'diary-list-entries 'list-diary-entries)
-                date 1)))
+        (diary-list-entries date 1)))
     (if (not (get-buffer diary-fancy-buffer))
        (setq entries nil)
       (with-current-buffer diary-fancy-buffer
@@ -5261,15 +5340,7 @@ each date.  It also removes lines that contain only 
whitespace."
 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" "")
-      (error
-       (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)
-      (apply 'diary-add-to-list args)
-    (apply 'add-to-diary-list args)))
+    (diary-add-to-list original-date "Org mode dummy" "")))
 
 (defvar org-diary-last-run-time nil)
 
@@ -5300,6 +5371,7 @@ So the example above may also be written as
 The function expects the lisp variables `entry' and `date' to be provided
 by the caller, because this is how the calendar works.  Don't use this
 function from a program - use `org-agenda-get-day-entries' instead."
+  (with-no-warnings (defvar date) (defvar entry))
   (when (> (- (float-time)
              org-agenda-last-marker-time)
           5)
@@ -5324,7 +5396,7 @@ function from a program - use 
`org-agenda-get-day-entries' instead."
     ;; the calendar.  Org Agenda will list these entries itself.
     (when org-disable-agenda-to-diary (setq files nil))
     (while (setq file (pop files))
-      (setq rtn (apply 'org-agenda-get-day-entries file date args))
+      (setq rtn (apply #'org-agenda-get-day-entries file date args))
       (setq results (append results rtn)))
     (when results
       (setq results
@@ -5385,27 +5457,29 @@ the documentation of `org-diary'."
              (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)))))))))))
+              (org-dlet
+                  ((date date))
+               (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?"
@@ -5467,11 +5541,12 @@ and the timestamp type relevant for the sorting 
strategy in
                           org-todo-regexp)
                          (org-select-this-todo-keyword
                           (concat "\\("
-                                  (mapconcat 'identity
+                                  (mapconcat #'identity
                                              (org-split-string
                                               org-select-this-todo-keyword
                                               "|")
-                                             "\\|") "\\)"))
+                                             "\\|")
+                                  "\\)"))
                          (t org-not-done-regexp))))
         marker priority category level tags todo-state
         ts-date ts-date-type ts-date-pair
@@ -5611,6 +5686,7 @@ This function is invoked if 
`org-agenda-todo-ignore-deadlines',
   "Return the date stamp information for agenda display.
 Optional argument DEADLINES is a list of deadline items to be
 displayed in agenda view."
+  (with-no-warnings (defvar date))
   (let* ((props (list 'face 'org-agenda-calendar-event
                      'org-not-done-regexp org-not-done-regexp
                      'org-todo-regexp org-todo-regexp
@@ -5753,12 +5829,15 @@ displayed in agenda view."
 (defun org-agenda-get-sexps ()
   "Return the sexp information for agenda display."
   (require 'diary-lib)
+  (with-no-warnings (defvar date) (defvar entry))
   (let* ((props (list 'face 'org-agenda-calendar-sexp
                      'mouse-face 'highlight
                      'help-echo
                      (format "mouse-2 or RET jump to org file %s"
                              (abbreviate-file-name buffer-file-name))))
         (regexp "^&?%%(")
+        ;; FIXME: Is this `entry' binding intended to be dynamic,
+         ;; so as to "hide" any current binding for it?
         marker category extra level ee txt tags entry
         result beg b sexp sexp-entry todo-state warntime inherited-tags)
     (goto-char (point-min))
@@ -5839,6 +5918,7 @@ item should be skipped.  If any of the SKIP-WEEKS 
arguments is the symbol
 `holidays', then any date that is known by the Emacs calendar to be a
 holiday will also be skipped.  If SKIP-WEEKS arguments are holiday strings,
 then those holidays will be skipped."
+  (with-no-warnings (defvar date) (defvar entry))
   (let* ((date1 (calendar-absolute-from-gregorian (list m1 d1 y1)))
         (date2 (calendar-absolute-from-gregorian (list m2 d2 y2)))
         (d (calendar-absolute-from-gregorian date))
@@ -5855,9 +5935,10 @@ then those holidays will be skipped."
              (delq nil (mapcar (lambda(g) (member g skip-weeks)) h))))
      entry)))
 
-(defalias 'org-get-closed 'org-agenda-get-progress)
+(defalias 'org-get-closed #'org-agenda-get-progress)
 (defun org-agenda-get-progress ()
   "Return the logged TODO entries for agenda display."
+  (with-no-warnings (defvar date))
   (let* ((props (list 'mouse-face 'highlight
                      'org-not-done-regexp org-not-done-regexp
                      'org-todo-regexp org-todo-regexp
@@ -5877,7 +5958,7 @@ then those holidays will be skipped."
                 (when (memq 'clock items) (concat "\\<" org-clock-string))
                 (when (memq 'state items)
                   (format "- +State \"%s\".*?" org-todo-regexp)))))
-        (parts-re (if parts (mapconcat 'identity parts "\\|")
+        (parts-re (if parts (mapconcat #'identity parts "\\|")
                     (error "`org-agenda-log-mode-items' is empty")))
         (regexp (concat
                  "\\(" parts-re "\\)"
@@ -6089,6 +6170,7 @@ See also the user option 
`org-agenda-clock-consistency-checks'."
   "Return the deadline information for agenda display.
 When WITH-HOUR is non-nil, only return deadlines with an hour
 specification like [h]h:mm."
+  (with-no-warnings (defvar date))
   (let* ((props (list 'mouse-face 'highlight
                      'org-not-done-regexp org-not-done-regexp
                      'org-todo-regexp org-todo-regexp
@@ -6247,6 +6329,7 @@ FRACTION is what fraction of the head-warning time has 
passed."
 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."
+  (with-no-warnings (defvar date))
   (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
@@ -6447,6 +6530,7 @@ scheduled items with an hour specification like [h]h:mm."
 
 (defun org-agenda-get-blocks ()
   "Return the date-range information for agenda display."
+  (with-no-warnings (defvar date))
   (let* ((props (list 'face nil
                      'org-not-done-regexp org-not-done-regexp
                      'org-todo-regexp org-todo-regexp
@@ -6578,14 +6662,14 @@ The flag is set if the currently compiled format 
contains a `%b'.")
          (cl-return (cadr entry))
        (cl-return (apply #'create-image (cdr entry)))))))
 
-(defun org-agenda-format-item (extra txt &optional level category tags dotime
+(defun org-agenda-format-item (extra txt &optional with-level with-category 
tags dotime
                                     remove-re habitp)
   "Format TXT to be inserted into the agenda buffer.
 In particular, add the prefix and corresponding text properties.
 
 EXTRA must be a string to replace the `%s' specifier in the prefix format.
-LEVEL may be a string to replace the `%l' specifier.
-CATEGORY (a string, a symbol or nil) may be used to overrule the default
+WITH-LEVEL may be a string to replace the `%l' specifier.
+WITH-CATEGORY (a string, a symbol or nil) may be used to overrule the default
 category taken from local variable or file name.  It will replace the `%c'
 specifier in the format.
 DOTIME, when non-nil, indicates that a time-of-day should be extracted from
@@ -6615,7 +6699,14 @@ Any match of REMOVE-RE will be removed from TXT."
                 org-agenda-show-inherited-tags
                 org-agenda-hide-tags-regexp))
 
-      (let* ((category (or category
+      (with-no-warnings
+       ;; `time', `tag', `effort' are needed for the eval of the prefix format.
+       ;; Based on what I see in `org-compile-prefix-format', I added
+       ;; a few more.
+        (defvar breadcrumbs) (defvar category) (defvar category-icon)
+        (defvar effort) (defvar extra)
+        (defvar level) (defvar tag) (defvar time))
+      (let* ((category (or with-category
                           (if buffer-file-name
                               (file-name-sans-extension
                                (file-name-nondirectory buffer-file-name))
@@ -6626,9 +6717,9 @@ Any match of REMOVE-RE will be removed from TXT."
                              ""))
             (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-grid-trailing-characters (nth 2 org-agenda-time-grid))
+            (extra (or (and (not habitp) extra) ""))
             time
             (ts (when dotime (concat
                               (if (stringp dotime) dotime "")
@@ -6712,9 +6803,8 @@ Any match of REMOVE-RE will be removed from TXT."
                                   (concat time-grid-trailing-characters " ")
                                 time-grid-trailing-characters)))
                         (t ""))
-             extra (or (and (not habitp) extra) "")
              category (if (symbolp category) (symbol-name category) category)
-             level (or level ""))
+             level (or with-level ""))
        (if (string-match org-link-bracket-re category)
            (progn
              (setq l (string-width (or (match-string 2) (match-string 1))))
@@ -6727,14 +6817,14 @@ Any match of REMOVE-RE will be removed from TXT."
                     (>= (length category) org-prefix-category-max-length))
            (setq category (substring category 0 (1- 
org-prefix-category-max-length)))))
        ;; Evaluate the compiled format
-       (setq rtn (concat (eval formatter) txt))
+       (setq rtn (concat (eval formatter t) 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 category
-         'tags tags
-         'org-priority-highest org-priority-highest
+          'tags tags
+          'org-priority-highest org-priority-highest
          'org-priority-lowest org-priority-lowest
          'time-of-day time-of-day
          'duration duration
@@ -6840,8 +6930,8 @@ and stored in the variable `org-prefix-format-compiled'."
             (cdr (assq key org-agenda-prefix-format)))
            (t "  %-12:c%?-12t% s")))
        (start 0)
-       varform vars var e c f opt)
-    (while (string-match "%\\(\\?\\)?\\([-+]?[0-9.]*\\)\\([ 
.;,:!?=|/<>]?\\)\\([cltseib]\\|(.+)\\)"
+       varform vars var c f opt) ;; e
+    (while (string-match "%\\(\\?\\)?\\([-+]?[0-9.]*\\)\\([ 
.;,:!?=|/<>]?\\)\\([cltseib]\\|(.+?)\\)"
                         s start)
       (setq var (or (cdr (assoc (match-string 4 s)
                                '(("c" . category) ("t" . time) ("l" . level) 
("s" . extra)
@@ -6865,17 +6955,21 @@ and stored in the variable 
`org-prefix-format-compiled'."
                  (and (string-match "\\.[0-9]+" x)
                       (string-to-number (substring (match-string 0 x) 1)))))))
       (if (eq var 'eval)
-         (setq varform `(format ,f (org-eval ,(read (match-string 4 s)))))
+         (setq varform `(format ,f (org-eval ,(read (substring s 
(match-beginning 4))))))
        (if opt
            (setq varform
-                 `(if (or (equal "" ,var) (equal nil ,var))
+                 `(if (member ,var '("" nil))
                       ""
                     (format ,f (concat ,var ,c))))
          (setq varform
-               `(format ,f (if (or (equal ,var "")
-                                   (equal ,var nil)) ""
+               `(format ,f (if (member ,var '("" nil)) ""
                              (concat ,var ,c (get-text-property 0 'extra-space 
,var)))))))
-      (setq s (replace-match "%s" t nil s))
+      (if (eq var 'eval)
+          (setf (substring s (match-beginning 0)
+                           (+ (match-beginning 4)
+                              (length (format "%S" (read (substring s 
(match-beginning 4)))))))
+                "%s")
+        (setq s (replace-match "%s" t nil s)))
       (push varform vars))
     (setq vars (nreverse vars))
     (with-current-buffer (or org-agenda-buffer (current-buffer))
@@ -6889,10 +6983,10 @@ and stored in the variable 
`org-prefix-format-compiled'."
             `(format ,s ,@vars))))))
 
 (defun org-set-sorting-strategy (key)
-  (if (symbolp (car org-agenda-sorting-strategy))
-      ;; the old format
-      (setq org-agenda-sorting-strategy-selected org-agenda-sorting-strategy)
-    (setq org-agenda-sorting-strategy-selected
+  (setq org-agenda-sorting-strategy-selected
+        (if (symbolp (car org-agenda-sorting-strategy))
+            ;; the old format
+            org-agenda-sorting-strategy
          (or (cdr (assq key org-agenda-sorting-strategy))
              (cdr (assq 'agenda org-agenda-sorting-strategy))
              '(time-up category-keep priority-down)))))
@@ -6981,8 +7075,8 @@ The optional argument TYPE tells the agenda type."
            (delq nil
                  (mapcar
                   org-agenda-before-sorting-filter-function list))))
-    (setq list (mapcar 'org-agenda-highlight-todo list)
-         list (mapcar 'identity (sort list 'org-entries-lessp)))
+    (setq list (mapcar #'org-agenda-highlight-todo list)
+         list (mapcar #'identity (sort list #'org-entries-lessp)))
     (when max-effort
       (setq list (org-agenda-limit-entries
                  list 'effort-minutes max-effort
@@ -6996,7 +7090,7 @@ The optional argument TYPE tells the agenda type."
       (setq list (org-agenda-limit-entries list 'org-hd-marker max-entries)))
     (when (and org-agenda-dim-blocked-tasks org-blocker-hook)
       (setq list (mapcar #'org-agenda--mark-blocked-entry list)))
-    (mapconcat 'identity list "\n")))
+    (mapconcat #'identity list "\n")))
 
 (defun org-agenda-limit-entries (list prop limit &optional fn)
   "Limit the number of agenda entries."
@@ -7088,7 +7182,7 @@ The optional argument TYPE tells the agenda type."
                    ;; Remove `display' property as the icon could leak
                   ;; on the white space.
                   (org-add-props " " (org-plist-delete (text-properties-at 0 x)
-                                                       'display))
+                                                        'display))
                    (substring x (match-end 3)))))))
       x)))
 
@@ -7212,8 +7306,9 @@ their type."
   "Predicate for sorting agenda entries."
   ;; The following variables will be used when the form is evaluated.
   ;; So even though the compiler complains, keep them.
-  (let* ((ss org-agenda-sorting-strategy-selected)
-        (timestamp-up    (and (org-em 'timestamp-up 'timestamp-down ss)
+  (let ((ss org-agenda-sorting-strategy-selected))
+    (org-dlet
+       ((timestamp-up    (and (org-em 'timestamp-up 'timestamp-down ss)
                               (org-cmp-ts a b "")))
         (timestamp-down  (if timestamp-up (- timestamp-up) nil))
         (scheduled-up    (and (org-em 'scheduled-up 'scheduled-down ss)
@@ -7259,14 +7354,14 @@ their type."
         (alpha-down      (if alpha-up (- alpha-up) nil))
         (need-user-cmp   (org-em 'user-defined-up 'user-defined-down ss))
         user-defined-up user-defined-down)
-    (when (and need-user-cmp org-agenda-cmp-user-defined
-              (functionp org-agenda-cmp-user-defined))
-      (setq user-defined-up
-           (funcall org-agenda-cmp-user-defined a b)
-           user-defined-down (if user-defined-up (- user-defined-up) nil)))
-    (cdr (assoc
-         (eval (cons 'or org-agenda-sorting-strategy-selected))
-         '((-1 . t) (1 . nil) (nil . nil))))))
+      (when (and need-user-cmp org-agenda-cmp-user-defined
+                (functionp org-agenda-cmp-user-defined))
+       (setq user-defined-up
+             (funcall org-agenda-cmp-user-defined a b)
+             user-defined-down (if user-defined-up (- user-defined-up) nil)))
+      (cdr (assoc
+           (eval (cons 'or org-agenda-sorting-strategy-selected) t)
+           '((-1 . t) (1 . nil) (nil . nil)))))))
 
 ;;; Agenda restriction lock
 
@@ -7301,7 +7396,7 @@ When in a restricted subtree, remove it.
 
 The restriction will span over the entire file if TYPE is `file',
 or if type is '(4), or if the cursor is before the first headline
-in the file. Otherwise, only apply the restriction to the current
+in the file.  Otherwise, only apply the restriction to the current
 subtree."
   (interactive "P")
   (if (and org-agenda-overriding-restriction
@@ -7468,7 +7563,7 @@ This is used when toggling sticky agendas."
     (dolist (buf (buffer-list))
       (when (with-current-buffer buf (eq major-mode 'org-agenda-mode))
        (push buf blist)))
-    (mapc 'kill-buffer blist)))
+    (mapc #'kill-buffer blist)))
 
 (defun org-agenda-execute (arg)
   "Execute another agenda command, keeping same window.
@@ -7481,6 +7576,7 @@ in the agenda."
 (defun org-agenda-redo (&optional all)
   "Rebuild possibly ALL agenda view(s) in the current buffer."
   (interactive "P")
+  (defvar org-agenda-tag-filter-while-redo) ;FIXME: Where is this var used?
   (let* ((p (or (and (looking-at "\\'") (1- (point))) (point)))
         (cpa (unless (eq all t) current-prefix-arg))
         (org-agenda-doing-sticky-redo org-agenda-sticky)
@@ -7519,8 +7615,11 @@ in the agenda."
     (and cols (org-columns-quit))
     (message "Rebuilding agenda buffer...")
     (if series-redo-cmd
-       (eval series-redo-cmd)
-      (org-let lprops redo-cmd))
+       (eval series-redo-cmd t)
+      (cl-progv
+         (mapcar #'car lprops)
+         (mapcar (lambda (binding) (eval (cadr binding) t)) lprops)
+       (eval redo-cmd t)))
     (setq org-agenda-undo-list nil
          org-agenda-pending-undo-list nil
          org-agenda-tag-filter tag-filter
@@ -7569,7 +7668,8 @@ With a prefix argument, do so in all agenda buffers."
   "Filter lines in the agenda buffer that have a specific category.
 The category is that of the current line.
 With a `\\[universal-argument]' prefix argument, exclude the lines of that 
category.
-When there is already a category filter in place, this command removes the 
filter."
+When there is already a category filter in place, this command removes the
+filter."
   (interactive "P")
   (if (and org-agenda-filtered-by-category
           org-agenda-category-filter)
@@ -7721,7 +7821,7 @@ A single `\\[universal-argument]' prefix arg 
STRIP-OR-ACCUMULATE will negate the
 entire filter, which can be useful in connection with the prompt history.
 
 A double `\\[universal-argument] \\[universal-argument]' prefix arg will add 
the new filter elements to the
-existing ones. A shortcut for this is to add an additional `+' at the
+existing ones.  A shortcut for this is to add an additional `+' at the
 beginning of the string, like `+-John'.
 
 With a triple prefix argument, execute the computed filtering defined in
@@ -7745,15 +7845,15 @@ the variable `org-agenda-auto-exclude-function'."
           (negate (equal strip-or-accumulate '(4)))
           (cf (mapconcat #'identity org-agenda-category-filter ""))
           (tf (mapconcat #'identity org-agenda-tag-filter ""))
-          (rpl-fn (lambda (c) (replace-regexp-in-string "^\+" "" (or (car c) 
""))))
-          (ef (replace-regexp-in-string "^\+" "" (or (car 
org-agenda-effort-filter) "")))
-          (rf (replace-regexp-in-string "^\+" "" (or (car 
org-agenda-regexp-filter) "")))
+          ;; (rpl-fn (lambda (c) (replace-regexp-in-string "^\\+" "" (or (car 
c) ""))))
+          (ef (replace-regexp-in-string "^\\+" "" (or (car 
org-agenda-effort-filter) "")))
+          (rf (replace-regexp-in-string "^\\+" "" (or (car 
org-agenda-regexp-filter) "")))
           (ff (concat cf tf ef (when (not (equal rf "")) (concat "/" rf "/"))))
           (f-string (completing-read
                      (concat
                       (if negate "Negative filter" "Filter")
                       " [+cat-tag<0:10-/regexp/]: ")
-                     'org-agenda-filter-completion-function
+                     #'org-agenda-filter-completion-function
                      nil nil ff))
           (keep (or (if (string-match "^\\+[+-]" f-string)
                         (progn (setq f-string (substring f-string 1)) t))
@@ -7779,20 +7879,20 @@ the variable `org-agenda-auto-exclude-function'."
                   "~~~" "-" (match-string 3 f-string)))
          (cond
           ((member s tag-list)
-           (add-to-list 'ft (concat pm s) 'append 'equal))
+           (org-pushnew-to-end (concat pm s) ft))
           ((member s category-list)
-           (add-to-list 'fc (concat pm ; Remove temporary double quotes.
-                                    (replace-regexp-in-string "\"\\(.*\\)\"" 
"\\1" s))
-                        'append 'equal))
+           (org-pushnew-to-end (concat pm ; Remove temporary double quotes.
+                                       (replace-regexp-in-string 
"\"\\(.*\\)\"" "\\1" s))
+                               fc))
           (t (message
               "`%s%s' filter ignored because tag/category is not represented"
               pm s))))
         ((match-beginning 4)
          ;; effort
-         (add-to-list 'fe (concat pm (match-string 4 f-string)) t 'equal))
+         (org-pushnew-to-end (concat pm (match-string 4 f-string)) fe))
         ((match-beginning 5)
          ;; regexp
-         (add-to-list 'fr (concat pm (match-string 6 f-string)) t 'equal)))
+         (org-pushnew-to-end (concat pm (match-string 6 f-string)) fr)))
        (setq f-string (substring f-string (match-end 0))))
       (org-agenda-filter-remove-all)
       (and fc (org-agenda-filter-apply
@@ -7872,7 +7972,7 @@ With a `\\[universal-argument] \\[universal-argument] 
\\[universal-argument]' pr
 i.e. don't
 filter on all its group members.
 
-A lisp caller can specify CHAR.  EXCLUDE means that the new tag
+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")
@@ -7894,7 +7994,7 @@ also press `-' or `+' to switch between filtering and 
excluding."
         (expand (not (equal strip-or-accumulate '(64))))
         (inhibit-read-only t)
         (current org-agenda-tag-filter)
-        a n tag)
+        a tag) ;; n
     (unless char
       (while (not (memq char valid-char-list))
        (org-unlogged-message
@@ -7975,7 +8075,7 @@ These will be lower-case, for filtering."
            (if tt (push tt tags-lists)))
          (setq tags-lists
                (nreverse (org-uniquify
-                          (delq nil (apply 'append tags-lists)))))
+                          (delq nil (apply #'append tags-lists)))))
          (dolist (tag tags-lists)
            (mapc
             (lambda (group)
@@ -7985,9 +8085,10 @@ These will be lower-case, for filtering."
          (setq org-agenda-represented-tags tags-lists)))))
 
 (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."
+  "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 ((multi-pos-cats
         (and (eq type 'category)
              (string-match-p "\\+.*\\+"
@@ -8119,10 +8220,11 @@ grouptags."
     (while (not (eobp))
       (when (or (org-get-at-bol 'org-hd-marker)
                (org-get-at-bol 'org-marker))
-       (let ((tags (org-get-at-bol 'tags))
-             (cat (org-agenda-get-category))
-             (txt (or (org-get-at-bol 'txt) "")))
-         (unless (eval org-agenda-filter-form)
+       (org-dlet
+           ((tags (org-get-at-bol 'tags))
+            (cat (org-agenda-get-category))
+            (txt (or (org-get-at-bol 'txt) "")))
+         (unless (eval org-agenda-filter-form t)
            (org-agenda-filter-hide-line type))))
       (beginning-of-line 2)))
   (when (get-char-property (point) 'invisible)
@@ -8305,12 +8407,12 @@ When optional argument BACKWARD is set, go backward."
          "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)))))
+       (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))
+                       #'previous-single-property-change
+                     #'next-single-property-change))
                 moved dest)
             (while (and (setq dest (funcall
                                     f (point) 'org-agenda-structural-header))
@@ -8483,7 +8585,7 @@ SPAN may be `day', `week', `fortnight', `month', `year'.  
The return value
 is a cons cell with the starting date and the number of days,
 so that the date SD will be in that range."
   (let* ((greg (calendar-gregorian-from-absolute sd))
-        (dg (nth 1 greg))
+        ;; (dg (nth 1 greg))
         (mg (car greg))
         (yg (nth 2 greg)))
     (cond
@@ -8555,7 +8657,7 @@ so that the date SD will be in that range."
 
 (defun org-unhighlight-once ()
   "Remove the highlight from its position, and this function from the hook."
-  (remove-hook 'pre-command-hook 'org-unhighlight-once)
+  (remove-hook 'pre-command-hook #'org-unhighlight-once)
   (org-unhighlight))
 
 (defvar org-agenda-pre-follow-window-conf nil)
@@ -8692,7 +8794,8 @@ When called with a prefix argument, include all archive 
files as well."
              (if org-agenda-include-deadlines " Ddl"  "")
              (if org-agenda-use-time-grid   " Grid"   "")
              (if (and (boundp 'org-habit-show-habits)
-                      org-habit-show-habits) " Habit"   "")
+                      org-habit-show-habits)
+                 " Habit"   "")
              (cond
               ((consp org-agenda-show-log) " LogAll")
               ((eq org-agenda-show-log 'clockcheck) " ClkCk")
@@ -8704,36 +8807,39 @@ When called with a prefix argument, include all archive 
files as well."
                  '(:eval (propertize
                           (concat "["
                                   (mapconcat
-                                   'identity
+                                    #'identity
                                    (append
                                     (get 'org-agenda-category-filter 
:preset-filter)
                                     org-agenda-category-filter)
                                    "")
                                   "]")
                           'face 'org-agenda-filter-category
-                          'help-echo "Category used in filtering")) "")
+                           'help-echo "Category used in filtering"))
+                "")
              (if (or org-agenda-tag-filter
                      (get 'org-agenda-tag-filter :preset-filter))
                  '(:eval (propertize
                           (concat (mapconcat
-                                   'identity
+                                   #'identity
                                    (append
                                     (get 'org-agenda-tag-filter :preset-filter)
                                     org-agenda-tag-filter)
                                    ""))
                           'face 'org-agenda-filter-tags
-                          'help-echo "Tags used in filtering")) "")
+                          'help-echo "Tags used in filtering"))
+               "")
              (if (or org-agenda-effort-filter
                      (get 'org-agenda-effort-filter :preset-filter))
                  '(:eval (propertize
                           (concat (mapconcat
-                                   'identity
+                                   #'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")) 
"")
+                          'help-echo "Effort conditions used in filtering"))
+               "")
              (if (or org-agenda-regexp-filter
                      (get 'org-agenda-regexp-filter :preset-filter))
                  '(:eval (propertize
@@ -8744,7 +8850,8 @@ When called with a prefix argument, include all archive 
files as well."
                                     org-agenda-regexp-filter)
                                    ""))
                           'face 'org-agenda-filter-regexp
-                          'help-echo "Regexp used in filtering")) "")
+                          'help-echo "Regexp used in filtering"))
+               "")
              (if org-agenda-archives-mode
                  (if (eq org-agenda-archives-mode t)
                      " Archives"
@@ -8775,7 +8882,7 @@ When called with a prefix argument, include all archive 
files as well."
   "Move cursor to next agenda item."
   (interactive "p")
   (let ((col (current-column)))
-    (dotimes (c n)
+    (dotimes (_ n)
       (when (next-single-property-change (point-at-eol) 'org-marker)
        (move-end-of-line 1)
        (goto-char (next-single-property-change (point) 'org-marker))))
@@ -8785,7 +8892,7 @@ When called with a prefix argument, include all archive 
files as well."
 (defun org-agenda-previous-item (n)
   "Move cursor to next agenda item."
   (interactive "p")
-  (dotimes (c n)
+  (dotimes (_ n)
     (let ((col (current-column))
          (goto (save-excursion
                  (move-end-of-line 0)
@@ -8811,7 +8918,7 @@ When called with a prefix argument, include all archive 
files as well."
   (let* ((tags (org-get-at-bol 'tags)))
     (if tags
        (message "Tags are :%s:"
-                (org-no-properties (mapconcat 'identity tags ":")))
+                (org-no-properties (mapconcat #'identity tags ":")))
       (message "No tags associated with this line"))))
 
 (defun org-agenda-goto (&optional highlight)
@@ -8845,7 +8952,7 @@ Point is in the buffer where the item originated.")
 
 (defun org-agenda-do-in-region (beg end cmd &optional arg force-arg delete)
   "Between region BEG and END, call agenda command CMD.
-When optional argument ARG is non-nil or FORCE-ARG is `t', pass
+When optional argument ARG is non-nil or FORCE-ARG is t, pass
 ARG to CMD.  When optional argument DELETE is non-nil, assume CMD
 deletes the agenda entry and don't move to the next entry."
   (save-excursion
@@ -8952,6 +9059,8 @@ Pass ARG, FORCE-ARG, DELETE and BODY to 
`org-agenda-do-in-region'."
   (funcall-interactively
    #'org-agenda-archive-with 'org-archive-to-archive-sibling))
 
+(defvar org-archive-from-agenda)
+
 (defun org-agenda-archive-with (cmd &optional confirm)
   "Move the entry to the archive sibling."
   (interactive)
@@ -9028,7 +9137,7 @@ When NO-UPDATE is non-nil, don't redo the agenda buffer."
           (marker (or (org-get-at-bol 'org-hd-marker)
                       (org-agenda-error)))
           (buffer (marker-buffer marker))
-          (pos (marker-position marker))
+          ;; (pos (marker-position marker))
           (rfloc (or rfloc
                      (org-refile-get-location
                       (if goto "Goto" "Refile to") buffer
@@ -9314,6 +9423,8 @@ by a remote command from the agenda.")
   (interactive)
   (org-agenda-todo 'previousset))
 
+(defvar org-agenda-headline-snapshot-before-repeat)
+
 (defun org-agenda-todo (&optional arg)
   "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
@@ -9338,11 +9449,14 @@ the same tree node, and the headline of the tree node 
in the Org file."
         (goto-char pos)
         (org-show-context 'agenda)
         (let ((current-prefix-arg arg))
-          (call-interactively 'org-todo))
+          (call-interactively 'org-todo)
+           ;; Make sure that log is recorded in current undo.
+           (when (and org-log-setup
+                      (not (eq org-log-note-how 'note)))
+             (org-add-log-note)))
         (and (bolp) (forward-char 1))
         (setq newhead (org-get-heading))
-        (when (and (bound-and-true-p
-                    org-agenda-headline-snapshot-before-repeat)
+        (when (and org-agenda-headline-snapshot-before-repeat
                    (not (equal org-agenda-headline-snapshot-before-repeat
                                newhead))
                    todayp)
@@ -9361,15 +9475,15 @@ the same tree node, and the headline of the tree node 
in the Org file."
        (org-move-to-column col)
        (org-agenda-mark-clocking-task)))))
 
-(defun org-agenda-add-note (&optional arg)
+(defun org-agenda-add-note (&optional _arg)
   "Add a time-stamped note to the entry at point."
-  (interactive "P")
+  (interactive) ;; "P"
   (org-agenda-check-no-diary)
   (let* ((marker (or (org-get-at-bol 'org-marker)
                     (org-agenda-error)))
         (buffer (marker-buffer marker))
         (pos (marker-position marker))
-        (hdmarker (org-get-at-bol 'org-hd-marker))
+        (_hdmarker (org-get-at-bol 'org-hd-marker))
         (inhibit-read-only t))
     (with-current-buffer buffer
       (widen)
@@ -9392,7 +9506,7 @@ If FORCE-TAGS is non-nil, the car of it returns the new 
tags."
         (org-agenda-buffer (current-buffer))
         (thetags (with-current-buffer (marker-buffer hdmarker)
                    (org-get-tags hdmarker)))
-        props m pl undone-face done-face finish new dotime level cat tags)
+        props m undone-face done-face finish new dotime level cat tags) ;; pl
     (save-excursion
       (goto-char (point-max))
       (beginning-of-line 1)
@@ -9414,7 +9528,7 @@ If FORCE-TAGS is non-nil, the car of it returns the new 
tags."
                  (with-current-buffer (marker-buffer hdmarker)
                    (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)
+               ;; 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)
@@ -9493,33 +9607,35 @@ current line."
 
 (defun org-agenda-priority (&optional force-direction)
   "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 file.
-Called with a universal prefix arg, show the priority instead of setting it."
+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 file.
+
+Called with one universal prefix arg, show the priority instead
+of setting it.
+
+When called programmatically, FORCE-DIRECTION can be `set', `up',
+`down', or a character."
   (interactive "P")
-  (if (equal force-direction '(4))
-      (org-priority-show)
-    (unless org-priority-enable-commands
-      (user-error "Priority commands are disabled"))
-    (org-agenda-check-no-diary)
-    (let* ((col (current-column))
-          (marker (or (org-get-at-bol 'org-marker)
-                      (org-agenda-error)))
-          (hdmarker (org-get-at-bol 'org-hd-marker))
-          (buffer (marker-buffer hdmarker))
-          (pos (marker-position hdmarker))
-          (inhibit-read-only t)
-          newhead)
-      (org-with-remote-undo buffer
-       (with-current-buffer buffer
-         (widen)
-         (goto-char pos)
-         (org-show-context 'agenda)
-         (org-priority force-direction)
-         (end-of-line 1)
-         (setq newhead (org-get-heading)))
-       (org-agenda-change-all-lines newhead hdmarker)
-       (org-move-to-column col)))))
+  (unless org-priority-enable-commands
+    (user-error "Priority commands are disabled"))
+  (org-agenda-check-no-diary)
+  (let* ((col (current-column))
+        (hdmarker (org-get-at-bol 'org-hd-marker))
+        (buffer (marker-buffer hdmarker))
+        (pos (marker-position hdmarker))
+        (inhibit-read-only t)
+        newhead)
+    (org-with-remote-undo buffer
+      (with-current-buffer buffer
+       (widen)
+       (goto-char pos)
+       (org-show-context 'agenda)
+       (org-priority force-direction)
+       (end-of-line 1)
+       (setq newhead (org-get-heading)))
+      (org-agenda-change-all-lines newhead hdmarker)
+      (org-move-to-column col))))
 
 ;; FIXME: should fix the tags property of the agenda line.
 (defun org-agenda-set-tags (&optional tag onoff)
@@ -9558,7 +9674,7 @@ Called with a universal prefix arg, show the priority 
instead of setting it."
          (buffer (marker-buffer hdmarker))
          (pos (marker-position hdmarker))
          (inhibit-read-only t)
-         newhead)
+         ) ;; newhead
      (org-with-remote-undo buffer
        (with-current-buffer buffer
         (widen)
@@ -9764,7 +9880,7 @@ ARG is passed through to `org-schedule'."
    #'org-agenda-schedule arg t nil
    (let* ((marker (or (org-get-at-bol 'org-marker)
                      (org-agenda-error)))
-         (type (marker-insertion-type marker))
+         ;; (type (marker-insertion-type marker))
          (buffer (marker-buffer marker))
          (pos (marker-position marker))
          ts)
@@ -9839,9 +9955,9 @@ ARG is passed through to `org-deadline'."
     (org-move-to-column col)
     (org-agenda-unmark-clocking-task)))
 
-(defun org-agenda-clock-cancel (&optional arg)
+(defun org-agenda-clock-cancel (&optional _arg)
   "Cancel the currently running clock."
-  (interactive "P")
+  (interactive) ;; "P"
   (unless (marker-buffer org-clock-marker)
     (user-error "No running clock"))
   (org-with-remote-undo (marker-buffer org-clock-marker)
@@ -10085,7 +10201,7 @@ entries in that Org file."
        (unwind-protect
            (progn
              (fset 'calendar-cursor-to-date
-                   (lambda (&optional error dummy)
+                   (lambda (&optional _error _dummy)
                      (calendar-gregorian-from-absolute
                       (get-text-property point 'day))))
              (call-interactively cmd))
@@ -10100,18 +10216,19 @@ entries in that Org file."
   (let* ((oldf (symbol-function 'calendar-cursor-to-date))
         (point (point))
         (date (calendar-gregorian-from-absolute
-               (get-text-property point 'day)))
-         ;; the following 2 vars are needed in the calendar
-        (displayed-month (car date))
+               (get-text-property point 'day))))
+    ;; the following 2 vars are needed in the calendar
+    (org-dlet
+       ((displayed-month (car date))
         (displayed-year (nth 2 date)))
-    (unwind-protect
-       (progn
-         (fset 'calendar-cursor-to-date
-               (lambda (&optional error dummy)
-                 (calendar-gregorian-from-absolute
-                  (get-text-property point 'day))))
-         (call-interactively cmd))
-      (fset 'calendar-cursor-to-date oldf))))
+      (unwind-protect
+         (progn
+           (fset 'calendar-cursor-to-date
+                 (lambda (&optional _error _dummy)
+                   (calendar-gregorian-from-absolute
+                    (get-text-property point 'day))))
+           (call-interactively cmd))
+       (fset 'calendar-cursor-to-date oldf)))))
 
 (defun org-agenda-phases-of-moon ()
   "Display the phases of the moon for the 3 months around the cursor date."
@@ -10216,7 +10333,7 @@ When ARG is greater than one mark ARG lines."
     (setq arg (count-lines (region-beginning) (region-end)))
     (goto-char (region-beginning))
     (deactivate-mark))
-  (dotimes (i (or arg 1))
+  (dotimes (_ (or arg 1))
     (unless (org-get-at-bol 'org-agenda-diary-link)
       (let* ((m (org-get-at-bol 'org-hd-marker))
             ov)
@@ -10413,7 +10530,7 @@ The prefix arg is passed through to the command if 
possible."
                          (find-buffer-visiting (nth 1 refile-location))
                          (error "This should not happen")))))
 
-          (setq cmd `(lambda () (org-agenda-refile nil ',refile-location t)))
+          (setq cmd (lambda () (org-agenda-refile nil refile-location t)))
           (setq redo-at-end t)))
 
        (?t
@@ -10421,10 +10538,10 @@ The prefix arg is passed through to the command if 
possible."
                       "Todo state: "
                       (with-current-buffer (marker-buffer (car entries))
                         (mapcar #'list org-todo-keywords-1)))))
-          (setq cmd `(lambda ()
-                       (let ((org-inhibit-blocking t)
-                             (org-inhibit-logging 'note))
-                         (org-agenda-todo ,state))))))
+          (setq cmd (lambda ()
+                      (let ((org-inhibit-blocking t)
+                            (org-inhibit-logging 'note))
+                        (org-agenda-todo state))))))
 
        ((and (or ?- ?+) action)
         (let ((tag (completing-read
@@ -10434,9 +10551,9 @@ The prefix arg is passed through to the command if 
possible."
                             (mapcar (lambda (x) (and (stringp (car x)) x))
                                     org-current-tag-alist))))))
           (setq cmd
-                `(lambda ()
-                   (org-agenda-set-tags ,tag
-                                        ,(if (eq action ?+) ''on ''off))))))
+                (lambda ()
+                  (org-agenda-set-tags tag
+                                       (if (eq action ?+) 'on 'off))))))
 
        ((and (or ?s ?d) c)
         (let* ((schedule? (eq c ?s))
@@ -10458,13 +10575,13 @@ The prefix arg is passed through to the command if 
possible."
           ;; depending on the number of marked items.
           (setq cmd
                 (if schedule?
-                    `(lambda ()
-                       (let ((org-log-reschedule
-                              (and org-log-reschedule 'time)))
-                         (org-agenda-schedule arg ,time)))
-                  `(lambda ()
-                     (let ((org-log-redeadline (and org-log-redeadline 'time)))
-                       (org-agenda-deadline arg ,time)))))))
+                    (lambda ()
+                      (let ((org-log-reschedule
+                             (and org-log-reschedule 'time)))
+                        (org-agenda-schedule arg time)))
+                  (lambda ()
+                    (let ((org-log-redeadline (and org-log-redeadline 'time)))
+                      (org-agenda-deadline arg time)))))))
 
        (?S
         (unless (org-agenda-check-type nil 'agenda 'todo)
@@ -10474,29 +10591,29 @@ The prefix arg is passed through to the command if 
possible."
                              (if arg "week" ""))
                      7)))
           (setq cmd
-                `(lambda ()
-                   (let ((distance (1+ (random ,days))))
-                     (when arg
-                       (let ((dist distance)
-                             (day-of-week
-                              (calendar-day-of-week
-                               (calendar-gregorian-from-absolute 
(org-today)))))
-                         (dotimes (i (1+ dist))
-                           (while (member day-of-week org-agenda-weekend-days)
-                             (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.
-                     (ignore-errors
-                       (let* ((date (calendar-gregorian-from-absolute
-                                     (+ (org-today) distance)))
-                              (time (encode-time 0 0 0 (nth 1 date) (nth 0 
date)
-                                                 (nth 2 date))))
-                         (org-agenda-schedule nil time))))))))
+                (lambda ()
+                  (let ((distance (1+ (random days))))
+                    (when arg
+                      (let ((dist distance)
+                            (day-of-week
+                             (calendar-day-of-week
+                              (calendar-gregorian-from-absolute (org-today)))))
+                        (dotimes (_ (1+ dist))
+                          (while (member day-of-week org-agenda-weekend-days)
+                            (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.
+                    (ignore-errors
+                      (let* ((date (calendar-gregorian-from-absolute
+                                    (+ (org-today) distance)))
+                             (time (encode-time 0 0 0 (nth 1 date) (nth 0 date)
+                                                (nth 2 date))))
+                        (org-agenda-schedule nil time))))))))
 
        (?f
         (setq cmd
@@ -10504,10 +10621,15 @@ The prefix arg is passed through to the command if 
possible."
                (completing-read "Function: " obarray #'fboundp t nil nil))))
 
        (action
-        (pcase (assoc action org-agenda-bulk-custom-functions)
-          (`(,_ ,f) (setq cmd f) (setq redo-at-end t))
-          (_ (user-error "Invalid bulk action: %c" action)))))
-
+         (setq cmd
+               (pcase (assoc action org-agenda-bulk-custom-functions)
+                 (`(,_ ,fn)
+                  fn)
+                 (`(,_ ,fn ,arg-fn)
+                  (apply #'apply-partially fn (funcall arg-fn)))
+                 (_
+                  (user-error "Invalid bulk action: %c" action))))
+         (setq redo-at-end t)))
       ;; Sort the markers, to make sure that parents are handled
       ;; before children.
       (setq entries (sort entries
@@ -10576,7 +10698,7 @@ When the optional argument `backward' is non-nil, move 
backward."
   (let ((inhibit-read-only t) lst line)
     (if (or (not (get-text-property (point) 'txt))
            (save-excursion
-             (dotimes (n arg)
+             (dotimes (_ arg)
                (move-beginning-of-line (if backward 0 2))
                (push (not (get-text-property (point) 'txt)) lst))
              (delq nil lst)))
@@ -10605,7 +10727,7 @@ tag and (if present) the flagging note."
   (interactive)
   (let ((hdmarker (org-get-at-bol 'org-hd-marker))
        (win (selected-window))
-       note heading newhead)
+       note) ;; heading newhead
     (unless hdmarker
       (user-error "No linked entry at point"))
     (if (and (eq this-command last-command)
@@ -10633,11 +10755,11 @@ tag and note")))))
 
 (defun org-agenda-remove-flag (marker)
   "Remove the FLAGGED tag and any flagging note in the entry."
-  (let (newhead)
-    (org-with-point-at marker
-      (org-toggle-tag "FLAGGED" 'off)
-      (org-entry-delete nil "THEFLAGGINGNOTE")
-      (setq newhead (org-get-heading)))
+  (let ((newhead
+         (org-with-point-at marker
+           (org-toggle-tag "FLAGGED" 'off)
+           (org-entry-delete nil "THEFLAGGINGNOTE")
+           (org-get-heading))))
     (org-agenda-change-all-lines newhead marker)
     (message "Entry unflagged")))
 
@@ -10705,7 +10827,7 @@ to override `appt-message-warning-time'."
       (setq entries
             (delq nil
                   (append entries
-                          (apply 'org-agenda-get-day-entries
+                          (apply #'org-agenda-get-day-entries
                                  file today scope)))))
     ;; Map through entries and find if we should filter them out
     (mapc
diff --git a/lisp/org-archive.el b/lisp/org-archive.el
index 73cd83e..0943869 100644
--- a/lisp/org-archive.el
+++ b/lisp/org-archive.el
@@ -2,7 +2,7 @@
 
 ;; Copyright (C) 2004-2021 Free Software Foundation, Inc.
 
-;; Author: Carsten Dominik <carsten at orgmode dot org>
+;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: https://orgmode.org
 ;;
diff --git a/lisp/org-attach-git.el b/lisp/org-attach-git.el
index 2091cbc..4c6bdc9 100644
--- a/lisp/org-attach-git.el
+++ b/lisp/org-attach-git.el
@@ -24,7 +24,7 @@
 ;;; Commentary:
 
 ;; An extension to org-attach.  If `org-attach-id-dir' is initialized
-;; as a Git repository, then org-attach-git will automatically commit
+;; as a Git repository, then `org-attach-git' will automatically commit
 ;; changes when it sees them.  Requires git-annex.
 
 ;;; Code:
@@ -52,9 +52,25 @@ If \\='ask, prompt using `y-or-n-p'.  If t, always get.  If 
nil, never get."
          (const :tag "always get from annex if necessary" t)
          (const :tag "never get from annex" nil)))
 
+(defcustom org-attach-git-dir 'default
+  "Attachment directory with the Git repository to use.
+The default value is to use `org-attach-id-dir'.  When set to
+`individual-repository', then the directory attached to the
+current node, if correctly initialized as a Git repository, will
+be used instead."
+  :group 'org-attach
+  :package-version '(Org . "9.5")
+  :type '(choice
+          (const :tag "Default" default)
+          (const :tag "Individual repository" individual-repository)))
+
 (defun org-attach-git-use-annex ()
   "Return non-nil if git annex can be used."
-  (let ((git-dir (vc-git-root (expand-file-name org-attach-id-dir))))
+  (let ((git-dir (vc-git-root
+                  (cond ((eq org-attach-git-dir 'default)
+                         (expand-file-name org-attach-id-dir))
+                        ((eq org-attach-git-dir 'individual-repository)
+                         (org-attach-dir))))))
     (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))))))
@@ -62,7 +78,11 @@ If \\='ask, prompt using `y-or-n-p'.  If t, always get.  If 
nil, never get."
 (defun org-attach-git-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* ((default-directory (expand-file-name org-attach-id-dir))
+  (let* ((default-directory
+           (cond ((eq org-attach-git-dir 'default)
+                  (expand-file-name org-attach-id-dir))
+                 ((eq org-attach-git-dir 'individual-repository)
+                  (org-attach-dir))))
         (path-relative (file-relative-name path)))
     (when (and (org-attach-git-use-annex)
               (not
@@ -86,7 +106,10 @@ This checks for the existence of a \".git\" directory in 
that directory.
 
 Takes an unused optional argument for the sake of being compatible
 with hook `org-attach-after-change-hook'."
-  (let* ((dir (expand-file-name org-attach-id-dir))
+  (let* ((dir (cond ((eq org-attach-git-dir 'default)
+                     (expand-file-name org-attach-id-dir))
+                    ((eq org-attach-git-dir 'individual-repository)
+                     (org-attach-dir))))
         (git-dir (vc-git-root dir))
         (use-annex (org-attach-git-use-annex))
         (changes 0))
@@ -102,7 +125,7 @@ with hook `org-attach-after-change-hook'."
                        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))
+         (cl-incf changes))
        (dolist (deleted
                 (split-string
                  (shell-command-to-string "git ls-files -z --deleted") "\0" t))
diff --git a/lisp/org-attach.el b/lisp/org-attach.el
index 5eb5b74..75db69c 100644
--- a/lisp/org-attach.el
+++ b/lisp/org-attach.el
@@ -40,8 +40,11 @@
 (require 'org-id)
 
 (declare-function dired-dwim-target-directory "dired-aux")
+(declare-function dired-get-marked-files "dired" (&optional localp arg filter 
distinguish-one-marked error))
 (declare-function org-element-property "org-element" (property element))
 (declare-function org-element-type "org-element" (element))
+(declare-function org-inlinetask-goto-beginning "org-inlinetask" ())
+(declare-function org-inlinetask-in-task-p "org-inlinetask" ())
 
 (defgroup org-attach nil
   "Options concerning attachments in Org mode."
@@ -118,7 +121,7 @@ lns   create a symbol link.  Note that this is not supported
 (defcustom org-attach-use-inheritance 'selective
   "Attachment inheritance for the outline.
 
-Enabling inheritance for org-attach implies two things.  First,
+Enabling inheritance for `org-attach' implies two things.  First,
 that attachment links will look through all parent headings until
 it finds the linked attachment.  Second, that running org-attach
 inside a node without attachments will make org-attach operate on
@@ -182,7 +185,7 @@ attachment folders based on ID."
   :type '(repeat (function :tag "Function with ID as input")))
 
 (defvar org-attach-after-change-hook nil
-  "Hook to be called when files have been added or removed to the attachment 
folder.")
+  "Hook called when files have been added or removed to the attachment 
folder.")
 
 (defvar org-attach-open-hook nil
   "Hook that is invoked by `org-attach-open'.
@@ -243,6 +246,17 @@ Each entry in this list is a list of three elements:
                       (function :tag "Command")
                       (string :tag "Docstring"))))
 
+(defcustom org-attach-sync-delete-empty-dir 'query
+  "Determine what to do with an empty attachment directory on sync.
+When set to nil, don't touch the directory.  When set to `query',
+ask the user instead, else remove without asking."
+  :group 'org-attach
+  :package-version '(Org . "9.5")
+  :type '(choice
+         (const :tag "Never delete" nil)
+         (const :tag "Always delete" t)
+         (const :tag "Query the user" query)))
+
 ;;;###autoload
 (defun org-attach ()
   "The dispatcher for attachment commands.
@@ -256,38 +270,45 @@ Shows a list of commands and prompts for another key to 
execute a command."
       (unless marker
        (error "No item in current line")))
     (org-with-point-at marker
-      (org-back-to-heading-or-point-min t)
+      (if (and (featurep 'org-inlinetask)
+              (not (org-inlinetask-in-task-p)))
+         (org-with-limited-levels
+          (org-back-to-heading-or-point-min t))
+        (if (and (featurep 'org-inlinetask)
+                (org-inlinetask-in-task-p))
+            (org-inlinetask-goto-beginning)
+          (org-back-to-heading-or-point-min t)))
       (save-excursion
        (save-window-excursion
          (unless org-attach-expert
            (org-switch-to-buffer-other-window "*Org Attach*")
            (erase-buffer)
            (setq cursor-type nil
-             header-line-format "Use C-v, M-v, C-n or C-p to navigate.")
+                 header-line-format "Use C-v, M-v, C-n or C-p to navigate.")
            (insert
-               (concat "Attachment folder:\n"
-                      (or dir
-                          "Can't find an existing attachment-folder")
-                      (unless (and dir (file-directory-p dir))
-                        "\n(Not yet created)")
-                      "\n\n"
-                      (format "Select an Attachment Command:\n\n%s"
-                              (mapconcat
-                               (lambda (entry)
-                                 (pcase entry
-                                   (`((,key . ,_) ,_ ,docstring)
-                                    (format "%c       %s"
-                                            key
-                                            (replace-regexp-in-string 
"\n\\([\t ]*\\)"
-                                                                      "        
"
-                                                                      docstring
-                                                                      nil nil 
1)))
-                                   (_
-                                    (user-error
-                                     "Invalid `org-attach-commands' item: %S"
-                                     entry))))
-                               org-attach-commands
-                               "\n")))))
+             (concat "Attachment folder:\n"
+                    (or dir
+                        "Can't find an existing attachment-folder")
+                    (unless (and dir (file-directory-p dir))
+                      "\n(Not yet created)")
+                    "\n\n"
+                    (format "Select an Attachment Command:\n\n%s"
+                            (mapconcat
+                             (lambda (entry)
+                               (pcase entry
+                                 (`((,key . ,_) ,_ ,docstring)
+                                  (format "%c       %s"
+                                          key
+                                          (replace-regexp-in-string "\n\\([\t 
]*\\)"
+                                                                    "        "
+                                                                    docstring
+                                                                    nil nil 
1)))
+                                 (_
+                                  (user-error
+                                   "Invalid `org-attach-commands' item: %S"
+                                   entry))))
+                             org-attach-commands
+                             "\n")))))
          (org-fit-window-to-buffer (get-buffer-window "*Org Attach*"))
          (let ((msg (format "Select command: [%s]"
                             (concat (mapcar #'caar org-attach-commands)))))
@@ -365,7 +386,7 @@ If the attachment by some reason cannot be created an error 
will be raised."
     attach-dir))
 
 (defun org-attach-dir-from-id (id  &optional try-all)
-  "Returns a folder path based on `org-attach-id-dir' and ID.
+  "Return a folder path based on `org-attach-id-dir' and ID.
 If TRY-ALL is non-nil, try all id-to-path functions in
 `org-attach-id-to-path-function-list' and return the first path
 that exist in the filesystem, or the first one if none exist.
@@ -426,7 +447,7 @@ Return the directory."
     new))
 
 (defun org-attach-unset-directory ()
-  "Removes DIR node property.
+  "Remove DIR node property.
 If attachment folder is changed due to removal of DIR-property
 ask to move attachments to new location and ask to delete old
 attachment-folder.
@@ -591,14 +612,22 @@ with no prompts."
 
 (defun org-attach-sync ()
   "Synchronize the current outline node with its attachments.
-This can be used after files have been added externally."
+Useful after files have been added/removed externally.  Option
+`org-attach-sync-delete-empty-dir' controls the behavior for
+empty attachment directories."
   (interactive)
   (let ((attach-dir (org-attach-dir)))
-    (when attach-dir
+    (if (not attach-dir)
+        (org-attach-tag 'off)
       (run-hook-with-args 'org-attach-after-change-hook attach-dir)
       (let ((files (org-attach-file-list attach-dir)))
-       (org-attach-tag (not files))))
-    (unless attach-dir (org-attach-tag t))))
+       (org-attach-tag (not files)))
+      (when org-attach-sync-delete-empty-dir
+        (when (and (org-directory-empty-p attach-dir)
+                   (if (eq 'query org-attach-sync-delete-empty-dir)
+                       (yes-or-no-p "Attachment directory is empty.  Delete?")
+                     t))
+          (delete-directory attach-dir))))))
 
 (defun org-attach-file-list (dir)
   "Return a list of files in the attachment directory.
diff --git a/lisp/org-capture.el b/lisp/org-capture.el
index 831c3e1..a9350c5 100644
--- a/lisp/org-capture.el
+++ b/lisp/org-capture.el
@@ -2,7 +2,7 @@
 
 ;; Copyright (C) 2010-2021 Free Software Foundation, Inc.
 
-;; Author: Carsten Dominik <carsten at orgmode dot org>
+;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: https://orgmode.org
 ;;
@@ -69,6 +69,7 @@
 (declare-function org-table-goto-line "org-table" (N))
 
 (defvar dired-buffers)
+(defvar crm-separator)
 (defvar org-end-time-was-given)
 (defvar org-keyword-properties)
 (defvar org-remember-default-headline)
@@ -107,7 +108,7 @@
 
 (defun org-capture-upgrade-templates (templates)
   "Update the template list to the new format.
-TEMPLATES is a template list, as in `org-capture-templates'. The
+TEMPLATES is a template list, as in `org-capture-templates'.  The
 new format unifies all the date/week tree targets into one that
 also allows for an optional outline path to specify a target."
   (let ((modified-templates
@@ -246,6 +247,10 @@ properties are:
 
  :jump-to-captured   When set, jump to the captured entry when finished.
 
+ :refile-targets     When exiting capture mode via `org-capture-refile', the
+                     variable `org-refile-targets' will be temporarily bound
+                     to the value of this property.
+
  :empty-lines        Set this to the number of lines that should be inserted
                      before and after the new item.  Default 0, only common
                      other value is 1.
@@ -301,13 +306,15 @@ be replaced with content and expanded:
               current template.
   %(sexp)     Evaluate elisp `(sexp)' and replace it with the results.
               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.  The time stamp is the current time,
-              except when called from agendas with `\\[org-agenda-capture]' or
-              with `org-capture-use-agenda-date' set.
+              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.  The time stamp is the current
+              time, except when called from agendas with
+              `\\[org-agenda-capture]' or with
+              `org-capture-use-agenda-date' set.
   %T          Time stamp as above, with date and time.
   %u, %U      Like the above, but inactive time stamps.
   %i          Initial content, copied from the active region.  If
@@ -317,12 +324,13 @@ be replaced with content and expanded:
   %a          Annotation, normally the link created with `org-store-link'.
   %A          Like %a, but prompt for the description part.
   %l          Like %a, but only insert the literal link.
+  %L          Like %l, but without brackets (the link content itself).
   %c          Current kill ring head.
   %x          Content of the X clipboard.
   %k          Title of currently clocked task.
   %K          Link to currently clocked task.
   %n          User name (taken from the variable `user-full-name').
-  %f          File visited by current buffer when org-capture was called.
+  %f          File visited by current buffer when `org-capture' was called.
   %F          Full path of the file or directory visited by current buffer.
   %:keyword   Specific information for certain link types, see below.
   %^g         Prompt for tags, with completion on tags in target file.
@@ -333,6 +341,8 @@ be replaced with content and expanded:
   %^C         Interactive selection of which kill or clip to use.
   %^L         Like %^C, but insert as link.
   %^{prop}p   Prompt the user for a value for property `prop'.
+              A default value can be specified like this:
+              %^{prop|default}p.
   %^{prompt}  Prompt the user for a string and replace this sequence with it.
               A default value and a completion table can be specified like 
this:
               %^{prompt|default|completion2|completion3|...}.
@@ -363,7 +373,7 @@ 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"
+  :package-version '(Org . "9.5")
   :set (lambda (s v) (set s (org-capture-upgrade-templates v)))
   :type
   (let ((file-variants '(choice :tag "Filename       "
@@ -371,78 +381,78 @@ you can escape ambiguous cases with a backward slash, 
e.g., \\%i."
                                (function :tag "Function")
                                (variable :tag "Variable")
                                (sexp :tag "Form"))))
-  `(repeat
-    (choice :value ("" "" entry (file "~/org/notes.org") "")
-           (list :tag "Multikey description"
-                 (string :tag "Keys       ")
-                 (string :tag "Description"))
-           (list :tag "Template entry"
-                 (string :tag "Keys           ")
-                 (string :tag "Description    ")
-                 (choice :tag "Capture Type   " :value entry
-                         (const :tag "Org entry" entry)
-                         (const :tag "Plain list item" item)
-                         (const :tag "Checkbox item" checkitem)
-                         (const :tag "Plain text" plain)
-                         (const :tag "Table line" table-line))
-                 (choice :tag "Target location"
-                         (list :tag "File"
-                               (const :format "" file)
-                               ,file-variants)
-                         (list :tag "ID"
-                               (const :format "" id)
-                               (string :tag "  ID"))
-                         (list :tag "File & Headline"
-                               (const :format "" file+headline)
-                               ,file-variants
-                               (string :tag "  Headline"))
-                         (list :tag "File & Outline path"
-                               (const :format "" file+olp)
-                               ,file-variants
-                               (repeat :tag "Outline path" :inline t
-                                       (string :tag "Headline")))
-                         (list :tag "File & Regexp"
-                               (const :format "" file+regexp)
-                               ,file-variants
-                               (regexp :tag "  Regexp"))
-                         (list :tag "File [ & Outline path ] & Date tree"
-                               (const :format "" file+olp+datetree)
-                               ,file-variants
-                               (option (repeat :tag "Outline path" :inline t
-                                               (string :tag "Headline"))))
-                         (list :tag "File & function"
-                               (const :format "" file+function)
-                               ,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       "
-                         (string)
-                         (list :tag "File"
-                               (const :format "" file)
-                               (file :tag "Template file"))
-                         (list :tag "Function"
-                               (const :format "" function)
-                               (function :tag "Template function")))
-                 (plist :inline t
-                        ;; Give the most common options as checkboxes
-                        :options (((const :format "%v " :prepend) (const t))
-                                  ((const :format "%v " :immediate-finish) 
(const t))
-                                  ((const :format "%v " :jump-to-captured) 
(const t))
-                                  ((const :format "%v " :empty-lines) (const 
1))
-                                  ((const :format "%v " :empty-lines-before) 
(const 1))
-                                  ((const :format "%v " :empty-lines-after) 
(const 1))
-                                  ((const :format "%v " :clock-in) (const t))
-                                  ((const :format "%v " :clock-keep) (const t))
-                                  ((const :format "%v " :clock-resume) (const 
t))
-                                  ((const :format "%v " :time-prompt) (const 
t))
-                                  ((const :format "%v " :tree-type) (const 
week))
-                                  ((const :format "%v " :unnarrowed) (const t))
-                                  ((const :format "%v " :table-line-pos) 
(string))
-                                  ((const :format "%v " :kill-buffer) (const 
t)))))))))
+    `(repeat
+      (choice :value ("" "" entry (file "~/org/notes.org") "")
+             (list :tag "Multikey description"
+                   (string :tag "Keys       ")
+                   (string :tag "Description"))
+             (list :tag "Template entry"
+                   (string :tag "Keys           ")
+                   (string :tag "Description    ")
+                   (choice :tag "Capture Type   " :value entry
+                           (const :tag "Org entry" entry)
+                           (const :tag "Plain list item" item)
+                           (const :tag "Checkbox item" checkitem)
+                           (const :tag "Plain text" plain)
+                           (const :tag "Table line" table-line))
+                   (choice :tag "Target location"
+                           (list :tag "File"
+                                 (const :format "" file)
+                                 ,file-variants)
+                           (list :tag "ID"
+                                 (const :format "" id)
+                                 (string :tag "  ID"))
+                           (list :tag "File & Headline"
+                                 (const :format "" file+headline)
+                                 ,file-variants
+                                 (string :tag "  Headline"))
+                           (list :tag "File & Outline path"
+                                 (const :format "" file+olp)
+                                 ,file-variants
+                                 (repeat :tag "Outline path" :inline t
+                                         (string :tag "Headline")))
+                           (list :tag "File & Regexp"
+                                 (const :format "" file+regexp)
+                                 ,file-variants
+                                 (regexp :tag "  Regexp"))
+                           (list :tag "File [ & Outline path ] & Date tree"
+                                 (const :format "" file+olp+datetree)
+                                 ,file-variants
+                                 (option (repeat :tag "Outline path" :inline t
+                                                 (string :tag "Headline"))))
+                           (list :tag "File & function"
+                                 (const :format "" file+function)
+                                 ,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       "
+                           (string)
+                           (list :tag "File"
+                                 (const :format "" file)
+                                 (file :tag "Template file"))
+                           (list :tag "Function"
+                                 (const :format "" function)
+                                 (function :tag "Template function")))
+                   (plist :inline t
+                          ;; Give the most common options as checkboxes
+                          :options (((const :format "%v " :prepend) (const t))
+                                    ((const :format "%v " :immediate-finish) 
(const t))
+                                    ((const :format "%v " :jump-to-captured) 
(const t))
+                                    ((const :format "%v " :empty-lines) (const 
1))
+                                    ((const :format "%v " :empty-lines-before) 
(const 1))
+                                    ((const :format "%v " :empty-lines-after) 
(const 1))
+                                    ((const :format "%v " :clock-in) (const t))
+                                    ((const :format "%v " :clock-keep) (const 
t))
+                                    ((const :format "%v " :clock-resume) 
(const t))
+                                    ((const :format "%v " :time-prompt) (const 
t))
+                                    ((const :format "%v " :tree-type) (const 
week))
+                                    ((const :format "%v " :unnarrowed) (const 
t))
+                                    ((const :format "%v " :table-line-pos) 
(string))
+                                    ((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.
@@ -467,8 +477,7 @@ The capture buffer is current and still narrowed."
   :type 'hook)
 
 (defcustom org-capture-bookmark t
-  "When non-nil, add a bookmark pointing at the last stored
-position when capturing."
+  "When non-nil, add bookmark pointing at the last stored position when 
capturing."
   :group 'org-capture
   :version "24.3"
   :type 'boolean)
@@ -488,19 +497,19 @@ is copied to this variable, which is local in the 
indirect buffer.")
 
 (defvar org-capture-clock-keep nil
   "Local variable to store the value of the :clock-keep parameter.
-This is needed in case org-capture-finalize is called interactively.")
+This is needed in case `org-capture-finalize' is called interactively.")
 
-(defun org-capture-put (&rest stuff)
-  "Add properties to the capture property list `org-capture-plist'."
-  (while stuff
+(defun org-capture-put (&rest elements)
+  "Add ELEMENTS to the capture property list `org-capture-plist'."
+  (while elements
     (setq org-capture-plist (plist-put org-capture-plist
-                                      (pop stuff) (pop stuff)))))
-(defun org-capture-get (prop &optional local)
-  "Get properties from the capture property list `org-capture-plist'.
+                                      (pop elements) (pop elements)))))
+(defun org-capture-get (property &optional local)
+  "Get PROPERTY from the capture property list `org-capture-plist'.
 When LOCAL is set, use the local variable `org-capture-current-plist',
 this is necessary after initialization of the capture process,
 to avoid conflicts with other active capture processes."
-  (plist-get (if local org-capture-current-plist org-capture-plist) prop))
+  (plist-get (if local org-capture-current-plist org-capture-plist) property))
 
 ;;; The minor mode
 
@@ -521,7 +530,7 @@ for a capture buffer.")
   "Minor mode for special key bindings in a capture buffer.
 
 Turning on this mode runs the normal hook `org-capture-mode-hook'."
-  nil " Cap" org-capture-mode-map
+  :lighter " Cap"
   (setq-local
    header-line-format
    (substitute-command-keys
@@ -579,17 +588,17 @@ to avoid duplicates.)"
                       (string :tag "        Capture key")
                       (string :tag "Replace by template")
                       (repeat :tag "Available when"
-                             (choice
-                              (cons :tag "Condition"
-                                    (choice
-                                     (const :tag "In file" in-file)
-                                     (const :tag "Not in file" not-in-file)
-                                     (const :tag "In buffer" in-buffer)
-                                     (const :tag "Not in buffer" not-in-buffer)
-                                     (const :tag "In mode" in-mode)
-                                     (const :tag "Not in mode" not-in-mode))
-                                    (regexp))
-                              (function :tag "Custom function"))))))
+                              (choice
+                               (cons :tag "Condition"
+                                     (choice
+                                      (const :tag "In file" in-file)
+                                      (const :tag "Not in file" not-in-file)
+                                      (const :tag "In buffer" in-buffer)
+                                      (const :tag "Not in buffer" 
not-in-buffer)
+                                      (const :tag "In mode" in-mode)
+                                      (const :tag "Not in mode" not-in-mode))
+                                     (regexp))
+                               (function :tag "Custom function"))))))
 
 (defcustom org-capture-use-agenda-date nil
   "Non-nil means use the date at point when capturing from agendas.
@@ -882,7 +891,8 @@ for `entry'-type templates"))
         (pos (make-marker))
         (org-capture-is-refiling t)
         (kill-buffer (org-capture-get :kill-buffer 'local))
-        (jump-to-captured (org-capture-get :jump-to-captured 'local)))
+        (jump-to-captured (org-capture-get :jump-to-captured 'local))
+        (refile-targets (org-capture-get :refile-targets '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,
@@ -892,11 +902,12 @@ for `entry'-type templates"))
     ;; early.  We want to wait for the refiling to be over, so we
     ;; control when the latter function is called.
     (org-capture-put :kill-buffer nil :jump-to-captured nil)
-    (org-capture-finalize)
-    (save-window-excursion
-      (with-current-buffer base
-       (org-with-point-at pos
-         (call-interactively 'org-refile))))
+    (let ((org-refile-targets (or refile-targets org-refile-targets)))
+      (org-capture-finalize)
+      (save-window-excursion
+        (with-current-buffer base
+         (org-with-point-at pos
+           (call-interactively 'org-refile)))))
     (when kill-buffer
       (with-current-buffer base (save-buffer))
       (kill-buffer base))
@@ -916,7 +927,7 @@ for `entry'-type templates"))
   (interactive)
   (org-goto-marker-or-bmk org-capture-last-stored-marker
                          (plist-get org-bookmark-names-plist
-                                :last-capture))
+                                    :last-capture))
   (message "This is the last note stored by a capture process"))
 
 ;;; Supporting functions for handling the process
@@ -1110,7 +1121,7 @@ FILE is a generalized file location, as handled by
 
 (defun org-capture-place-template (&optional inhibit-wconf-store)
   "Insert the template at the target location, and display the buffer.
-When `inhibit-wconf-store', don't store the window configuration, as it
+When INHIBIT-WCONF-STORE is non-nil, don't store the window configuration, as 
it
 may have been stored before."
   (unless inhibit-wconf-store
     (org-capture-put :return-to-wconf (current-window-configuration)))
@@ -1405,21 +1416,21 @@ Of course, if exact position has been required, just 
put it there."
        (org-capture--position-cursor beg end)))))
 
 (defun org-capture-mark-kill-region (beg end)
-  "Mark the region that will have to be killed when aborting capture."
+  "Mark region between BEG and END to be killed on aborted capture."
   (let ((m1 (copy-marker beg))
        (m2 (copy-marker end t)))
     (org-capture-put :begin-marker m1)
     (org-capture-put :end-marker m2)))
 
-(defun org-capture-position-for-last-stored (where)
-  "Memorize the position that should later become the position of last 
capture."
+(defun org-capture-position-for-last-stored (position)
+  "Put POSITION on `org-capture-plist' for future use as `last capture`."
   (cond
-   ((integerp where)
+   ((integerp position)
     (org-capture-put :position-for-last-stored
-                    (move-marker (make-marker) where
+                    (move-marker (make-marker) position
                                  (or (buffer-base-buffer (current-buffer))
                                      (current-buffer)))))
-   ((eq where 'table-line)
+   ((eq position 'table-line)
     (org-capture-put :position-for-last-stored
                     (list 'table-line
                           (org-table-current-dline))))
@@ -1446,7 +1457,8 @@ Of course, if exact position has been required, just put 
it there."
        (move-marker org-capture-last-stored-marker (point))))))
 
 (defun org-capture-narrow (beg end)
-  "Narrow, unless configuration says not to narrow."
+  "Possibly narrow to region between BEG and END.
+If configuration contains non-nil :unnarrowed property, do not narrow."
   (unless (org-capture-get :unnarrowed)
     (narrow-to-region beg end)))
 
@@ -1459,8 +1471,9 @@ of the template."
     (replace-match "")))
 
 (defun org-capture-empty-lines-before (&optional n)
-  "Set the correct number of empty lines before the insertion point.
-Point will be after the empty lines, so insertion can directly be done."
+  "Insert N empty lines before the insertion point.
+Point will be after the empty lines, so insertion can directly be done.
+If N is nil, :empty-lines-before or :empty-lines are considered."
   (setq n (or n (org-capture-get :empty-lines-before)
              (org-capture-get :empty-lines) 0))
   (let ((pos (point)))
@@ -1470,7 +1483,8 @@ Point will be after the empty lines, so insertion can 
directly be done."
 
 (defun org-capture-empty-lines-after (&optional n)
   "Set the correct number of empty lines after the inserted string.
-Point will remain at the first line after the inserted text."
+Point will remain at the first line after the inserted text.
+If N is nil, :empty-lines-after or :empty-lines are considered."
   (setq n (or n (org-capture-get :empty-lines-after)
              (org-capture-get :empty-lines) 0))
   (org-back-over-empty-lines)
@@ -1482,7 +1496,7 @@ Point will remain at the first line after the inserted 
text."
 (defvar org-clock-marker) ; Defined in org.el
 
 (defun org-capture-set-plist (entry)
-  "Initialize the property list from the template definition."
+  "Initialize the property list for ENTRY from the template definition."
   (setq org-capture-plist (copy-sequence (nthcdr 5 entry)))
   (org-capture-put :key (car entry) :description (nth 1 entry)
                   :target (nth 3 entry))
@@ -1499,7 +1513,7 @@ Point will remain at the first line after the inserted 
text."
 
 (defun org-capture-goto-target (&optional template-key)
   "Go to the target location of a capture template.
-The user is queried for the template."
+If TEMPLATE-KEY is nil, the user is queried for the template."
   (interactive)
   (let ((entry (org-capture-select-template template-key)))
     (unless entry (error "No capture template selected"))
@@ -1509,7 +1523,7 @@ The user is queried for the template."
     (goto-char (org-capture-get :pos))))
 
 (defun org-capture-get-indirect-buffer (&optional buffer prefix)
-  "Make an indirect buffer for a capture process.
+  "Make an indirect BUFFER for a capture process.
 Use PREFIX as a prefix for the name of the indirect buffer."
   (setq buffer (or buffer (current-buffer)))
   (let ((n 1) (base (buffer-name buffer)) bname)
@@ -1551,8 +1565,10 @@ Lisp programs can force the template by setting KEYS to 
a string."
   "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."
+  "Fill a TEMPLATE and return the filled template as a string.
+The template may still contain \"%?\" for cursor positioning.
+INITIAL content and/or ANNOTATION may be specified, but will be overridden
+by their respective `org-store-link-plist' properties if present."
   (let* ((template (or template (org-capture-get :template)))
         (buffer (org-capture-get :buffer))
         (file (buffer-file-name (or (buffer-base-buffer buffer) buffer)))
@@ -1590,6 +1606,9 @@ The template may still contain \"%?\" for cursor 
positioning."
         (v-l (if (and v-a (string-match l-re v-a))
                  (replace-match "[[\\1]]" nil nil v-a)
                v-a))
+        (v-L (if (and v-a (string-match l-re v-a))
+                 (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)
@@ -1642,7 +1661,7 @@ The template may still contain \"%?\" for cursor 
positioning."
       ;; Mark %() embedded elisp for later evaluation.
       (org-capture-expand-embedded-elisp 'mark)
       ;; Expand non-interactive templates.
-      (let ((regexp 
"%\\(:[-A-Za-z]+\\|<\\([^>\n]+\\)>\\|[aAcfFikKlntTuUx]\\)"))
+      (let ((regexp 
"%\\(:[-A-Za-z]+\\|<\\([^>\n]+\\)>\\|[aAcfFikKlLntTuUx]\\)"))
        (save-excursion
          (while (re-search-forward regexp nil t)
            ;; `org-capture-escaped-%' may modify buffer and cripple
@@ -1679,6 +1698,7 @@ The template may still contain \"%?\" for cursor 
positioning."
                          (?k v-k)
                          (?K v-K)
                          (?l v-l)
+                         (?L v-L)
                          (?n v-n)
                          (?t v-t)
                          (?T v-T)
@@ -1726,12 +1746,11 @@ The template may still contain \"%?\" for cursor 
positioning."
                            (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:]_@#%]+")
+                                 (let ((crm-separator "[ \t]*:[ \t]*"))
+                                    (completing-read-multiple
+                                    (if prompt (concat prompt ": ") "Tags: ")
+                                    org-last-tags-completion-table nil nil nil
+                                    'org-tags-history))
                                  ":")))
                       (when (org-string-nw-p ins)
                         (unless (eq (char-before) ?:) (insert ":"))
@@ -1780,7 +1799,8 @@ The template may still contain \"%?\" for cursor 
positioning."
                                           (setq l (org-up-heading-safe)))
                                         (if l (point-marker)
                                           (point-min-marker)))))))
-                           (value (org-read-property-value prompt pom)))
+                           (value
+                            (org-read-property-value prompt pom default)))
                       (org-set-property prompt value)))
                    ((or "t" "T" "u" "U")
                     ;; These are the date/time related ones.
@@ -1835,7 +1855,7 @@ The template may still contain \"%?\" for cursor 
positioning."
 
 (defun org-capture-escaped-% ()
   "Non-nil if % was escaped.
-If yes, unescape it now.  Assume match-data contains the
+If yes, unescape it now.  Assume `match-data' contains the
 placeholder to check."
   (save-excursion
     (goto-char (match-beginning 0))
diff --git a/lisp/org-clock.el b/lisp/org-clock.el
index aec5bc7..143ed4f 100644
--- a/lisp/org-clock.el
+++ b/lisp/org-clock.el
@@ -2,7 +2,7 @@
 
 ;; Copyright (C) 2004-2021 Free Software Foundation, Inc.
 
-;; Author: Carsten Dominik <carsten at orgmode dot org>
+;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: https://orgmode.org
 ;;
@@ -85,7 +85,7 @@ function `org-clock-into-drawer' instead."
          (string :tag "Into Drawer named...")))
 
 (defun org-clock-into-drawer ()
-  "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.
@@ -438,12 +438,11 @@ specifications than `frame-title-format', which see."
 (defcustom org-clock-x11idle-program-name "x11idle"
   "Name of the program which prints X11 idle time in milliseconds.
 
-You can find x11idle.c in the contrib/scripts directory of the
-Org git distribution. Or, you can do:
+you can do \"~$ sudo apt-get install xprintidle\" if you are using
+a Debian-based distribution.
 
-    sudo apt-get install xprintidle
-
-if you are using Debian."
+Alternatively, can find x11idle.c in the org-contrib repository at
+https://git.sr.ht/~bzg/org-contrib";
   :group 'org-clock
   :version "24.4"
   :package-version '(Org . "8.0")
@@ -485,6 +484,17 @@ is added to the user configuration."
          (integer :tag "Clock out after Emacs is idle for X seconds")
          (const :tag "Never auto clock out" nil)))
 
+(defcustom org-clock-ask-before-exiting t
+  "If non-nil, ask if the user wants to clock out before exiting Emacs.
+This variable only has effect if set with \\[customize]."
+  :set (lambda (symbol value)
+         (if value
+             (add-hook 'kill-emacs-query-functions 
#'org-clock-kill-emacs-query)
+           (remove-hook 'kill-emacs-query-functions 
#'org-clock-kill-emacs-query))
+         (set symbol value))
+  :type 'boolean
+  :package-version '(Org . "9.5"))
+
 (defvar org-clock-in-prepare-hook nil
   "Hook run when preparing the clock.
 This hook is run before anything happens to the task that
@@ -503,9 +513,9 @@ to add an effort property.")
   "Has the clock been used during the current Emacs session?")
 
 (defvar org-clock-stored-history nil
-  "Clock history, populated by `org-clock-load'")
+  "Clock history, populated by `org-clock-load'.")
 (defvar org-clock-stored-resume-clock nil
-  "Clock to resume, saved by `org-clock-load'")
+  "Clock to resume, saved by `org-clock-load'.")
 
 ;;; The clock for measuring work time.
 
@@ -539,8 +549,8 @@ of a different task.")
   "Marker pointing to the task that has been interrupted by the current 
clock.")
 
 (defvar org-clock-mode-line-map (make-sparse-keymap))
-(define-key org-clock-mode-line-map [mode-line mouse-2] 'org-clock-goto)
-(define-key org-clock-mode-line-map [mode-line mouse-1] 'org-clock-menu)
+(define-key org-clock-mode-line-map [mode-line mouse-2] #'org-clock-goto)
+(define-key org-clock-mode-line-map [mode-line mouse-1] #'org-clock-menu)
 
 (defun org-clock--translate (s language)
   "Translate string S into using string LANGUAGE.
@@ -607,10 +617,6 @@ cannot be translated."
          ((stringp drawer) drawer)
          (t nil))))
 
-(defun org-clocking-buffer ()
-  "Return the clocking buffer if we are currently clocking a task or nil."
-  (marker-buffer org-clock-marker))
-
 (defun org-clocking-p ()
   "Return t when clocking a task."
   (not (equal (org-clocking-buffer) nil)))
@@ -677,19 +683,19 @@ pointing to it."
     (let (cat task heading prefix)
       (with-current-buffer (org-base-buffer (marker-buffer marker))
        (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))))))
+        (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)))))
@@ -853,6 +859,10 @@ use libnotify if available, or fall back on a message."
            org-show-notification-timeout
            nil
            (lambda () (w32-notification-close id)))))
+        ((fboundp 'ns-do-applescript)
+         (ns-do-applescript
+          (format "display notification \"%s\" with title \"Org mode 
notification\""
+                  (replace-regexp-in-string "\"" "#" notification))))
        ((fboundp 'notifications-notify)
         (notifications-notify
          :title "Org mode message"
@@ -911,17 +921,17 @@ 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."
+  (declare (indent 1) (debug t))
   `(with-current-buffer (marker-buffer (car ,clock))
      (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)
 
 (defmacro org-with-clock (clock &rest forms)
   "Evaluate FORMS with CLOCK as the current active clock.
 This macro also protects the current active clock from being altered."
+  (declare (indent 1) (debug t))
   `(org-with-clock-position ,clock
      (let ((org-clock-start-time (cdr ,clock))
           (org-clock-total-time)
@@ -932,8 +942,6 @@ This macro also protects the current active clock from 
being altered."
                                  (org-back-to-heading t)
                                  (point-marker))))
        ,@forms)))
-(def-edebug-spec org-with-clock (form body))
-(put 'org-with-clock 'lisp-indent-function 1)
 
 (defsubst org-clock-clock-in (clock &optional resume start-time)
   "Clock in to the clock located by CLOCK.
@@ -1164,13 +1172,12 @@ If `only-dangling-p' is non-nil, only ask to resolve 
dangling
                  (org-clock-resolve
                   clock
                   (or prompt-fn
-                      (function
-                       (lambda (clock)
-                         (format
-                          "Dangling clock started %d mins ago"
-                          (floor (org-time-convert-to-integer
-                                   (org-time-since (cdr clock)))
-                                  60)))))
+                      (lambda (clock)
+                        (format
+                         "Dangling clock started %d mins ago"
+                         (floor (org-time-convert-to-integer
+                                 (org-time-since (cdr clock)))
+                                60))))
                   (or last-valid
                       (cdr clock)))))))))))
 
@@ -1416,12 +1423,12 @@ the default behavior."
           (setq org-clock-mode-line-timer
                 (run-with-timer org-clock-update-period
                                 org-clock-update-period
-                                'org-clock-update-mode-line)))
+                                #'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))
+              (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))))))
 
@@ -1673,17 +1680,13 @@ to, overriding the existing value of 
`org-clock-out-switch-to-state'."
          (insert " => " (format "%2d:%02d" h m))
          (move-marker org-clock-marker nil)
          (move-marker org-clock-hd-marker nil)
-         ;; 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
-                     (= 0 h m))
-                (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 'note
-                 (concat "# Task: " (org-get-heading t) "\n\n"))))
+         ;; Possibly remove zero time clocks.
+          (when (and org-clock-out-remove-zero-time-clocks
+                    (= 0 h m))
+            (setq remove t)
+           (delete-region (line-beginning-position)
+                          (line-beginning-position 2)))
+          (org-clock-remove-empty-clock-drawer)
          (when org-clock-mode-line-timer
            (cancel-timer org-clock-mode-line-timer)
            (setq org-clock-mode-line-timer nil))
@@ -1714,11 +1717,14 @@ to, overriding the existing value of 
`org-clock-out-switch-to-state'."
                       "Clock stopped at %s after %s => LINE REMOVED"
                     "Clock stopped at %s after %s")
                   te (org-duration-from-minutes (+ (* 60 h) m)))
-         (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)
+          (unless (org-clocking-p)
+           (setq org-clock-current-task nil))
+          (run-hooks 'org-clock-out-hook)
+          ;; Add a note, but only if we didn't remove the clock line.
+          (when (and org-log-note-clock-out (not remove))
+            (org-add-log-setup
+            'clock-out nil nil nil
+            (concat "# Task: " (org-get-heading t) "\n\n"))))))))
 
 (defun org-clock-remove-empty-clock-drawer ()
   "Remove empty clock drawers in current subtree."
@@ -2014,7 +2020,7 @@ Use `\\[org-clock-remove-overlays]' to remove the subtree 
times."
              (when time (org-clock-put-overlay time)))))
        ;; Arrange to remove the overlays upon next change.
        (when org-remove-highlights-with-change
-         (add-hook 'before-change-functions 'org-clock-remove-overlays
+         (add-hook 'before-change-functions #'org-clock-remove-overlays
                    nil 'local))))
     (let* ((h (/ org-clock-file-total-minutes 60))
           (m (- org-clock-file-total-minutes (* 60 h))))
@@ -2065,7 +2071,7 @@ If NOREMOVE is nil, remove this function from the
     (setq org-clock-overlays nil)
     (unless noremove
       (remove-hook 'before-change-functions
-                  'org-clock-remove-overlays 'local))))
+                  #'org-clock-remove-overlays 'local))))
 
 ;;;###autoload
 (defun org-clock-out-if-current ()
@@ -2241,7 +2247,7 @@ have priority."
                  ((>= month 7) 3)
                  ((>= month 4) 2)
                  (t 1)))
-        m1 h1 d1 month1 y1 shiftedy shiftedm shiftedq)
+        h1 d1 month1 y1 shiftedy shiftedm shiftedq) ;; m1
     (cond
      ((string-match "\\`[0-9]+\\'" skey)
       (setq y (string-to-number skey) month 1 d 1 key 'year))
@@ -2344,7 +2350,7 @@ have priority."
                  (`interactive (org-read-date nil t nil "Range end? "))
                  (`untilnow (current-time))
                  (_ (encode-time 0
-                                 (or m1 m)
+                                 m ;; (or m1 m)
                                  (or h1 h)
                                  (or d1 d)
                                  (or month1 month)
@@ -2391,7 +2397,7 @@ the currently selected interval size."
        (user-error "Line needs a :block definition before this command works")
       (let* ((b (match-beginning 1)) (e (match-end 1))
             (s (match-string 1))
-            block shift ins y mw d date wp m)
+            block shift ins y mw d date wp) ;; m
        (cond
         ((equal s "yesterday") (setq s "today-1"))
         ((equal s "lastweek") (setq s "thisweek-1"))
@@ -2416,7 +2422,7 @@ the currently selected interval size."
          (cond
           (d (setq ins (format-time-string
                         "%Y-%m-%d"
-                        (encode-time 0 0 0 (+ d n) m y))))
+                        (encode-time 0 0 0 (+ d n) nil y)))) ;; m
           ((and wp (string-match "w\\|W" wp) mw (> (length wp) 0))
            (require 'cal-iso)
            (setq date (calendar-gregorian-from-absolute
@@ -2698,7 +2704,18 @@ from the dynamic block definition."
             (format (concat "| %s %s | %s%s%s"
                             (format org-clock-file-time-cell-format
                                     (org-clock--translate "File time" lang))
-                            " | *%s*|\n")
+
+                            ;; The file-time rollup value goes in the first 
time
+                            ;; column (of which there is always at least 
one)...
+                            " | *%s*|"
+                            ;; ...and the remaining file time cols (if any) 
are blank.
+                            (make-string (max 0 (1- time-columns)) ?|)
+
+                            ;; Optionally show the percentage contribution of 
"this"
+                            ;; file time to the total time.
+                            (if (eq formula '%) " %s |" "")
+                            "\n")
+
                     (file-name-nondirectory file-name)
                     (if level?    "| " "") ;level column, maybe
                     (if timestamp "| " "") ;timestamp column, maybe
@@ -2706,7 +2723,12 @@ from the dynamic block definition."
                     (if properties         ;properties columns, maybe
                         (make-string (length properties) ?|)
                       "")
-                    (org-duration-from-minutes file-time)))) ;time
+                    (org-duration-from-minutes file-time) ;time
+
+                    (cond ((not (eq formula '%)) "")      ;time percentage, 
maybe
+                          ((or (not total-time) (= total-time 0)) "0.0")
+                          (t
+                           (format "%.1f" (* 100 (/ file-time (float 
total-time)))))))))
 
          ;; Get the list of node entries and iterate over it
          (when (> maxlevel 0)
@@ -2734,13 +2756,13 @@ from the dynamic block definition."
                 (if timestamp (concat ts "|") "")   ;timestamp, maybe
                 (if tags (concat (mapconcat #'identity tgs ", ") "|") "")   
;tags, maybe
                 (if properties         ;properties columns, maybe
-                    (concat (mapconcat (lambda (p) (or (cdr (assoc p props)) 
""))
-                                       properties
-                                       "|")
-                            "|")
+                  (concat (mapconcat (lambda (p) (or (cdr (assoc p props)) ""))
+                                     properties
+                                     "|")
+                          "|")
                   "")
                 (if indent             ;indentation
-                    (org-clocktable-indent-string level)
+                  (org-clocktable-indent-string level)
                   "")
                 (format-field headline)
                 ;; Empty fields for higher levels.
@@ -2748,7 +2770,7 @@ from the dynamic block definition."
                 (format-field (org-duration-from-minutes time))
                 (make-string (max 0 (- time-columns level)) ?|)
                 (if (eq formula '%)
-                    (format "%.1f |" (* 100 (/ time (float total-time))))
+                  (format "%.1f |" (* 100 (/ time (float total-time))))
                   "")
                 "\n")))))))
     (delete-char -1)
@@ -2934,12 +2956,12 @@ PROPERTIES: The list properties specified in the 
`:properties' parameter
     (save-excursion
       (org-clock-sum ts te
                     (when matcher
-                      `(lambda ()
-                         (let* ((todo (org-get-todo-state))
-                                (tags-list (org-get-tags))
-                                (org-scanner-tags tags-list)
-                                (org-trust-scanner-tags t))
-                           (funcall ,matcher todo tags-list nil)))))
+                      (lambda ()
+                        (let* ((todo (org-get-todo-state))
+                               (tags-list (org-get-tags))
+                               (org-scanner-tags tags-list)
+                               (org-trust-scanner-tags t))
+                          (funcall matcher todo tags-list nil)))))
       (goto-char (point-min))
       (setq st t)
       (while (or (and (bobp) (prog1 st (setq st nil))
@@ -3103,6 +3125,17 @@ The details of what will be saved are regulated by the 
variable
               (when (org-invisible-p) (org-show-context))))))
        (_ nil)))))
 
+(defun org-clock-kill-emacs-query ()
+  "Query user when killing Emacs.
+This function is added to `kill-emacs-query-functions'."
+  (let ((buf (org-clocking-buffer)))
+    (when (and buf (yes-or-no-p "Clock out and save? "))
+      (with-current-buffer buf
+        (org-clock-out)
+        (save-buffer))))
+  ;; Unconditionally return t for `kill-emacs-query-functions'.
+  t)
+
 ;; Suggested bindings
 (org-defkey org-mode-map "\C-c\C-x\C-e" 'org-clock-modify-effort-estimate)
 
diff --git a/lisp/org-colview.el b/lisp/org-colview.el
index 8226a94..9794382 100644
--- a/lisp/org-colview.el
+++ b/lisp/org-colview.el
@@ -2,7 +2,7 @@
 
 ;; Copyright (C) 2004-2021 Free Software Foundation, Inc.
 
-;; Author: Carsten Dominik <carsten at orgmode dot org>
+;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: https://orgmode.org
 ;;
@@ -162,20 +162,20 @@ See `org-columns-summary-types' for details.")
   (org-overview)
   (org-content))
 
-(org-defkey org-columns-map "c" 'org-columns-content)
-(org-defkey org-columns-map "o" 'org-overview)
-(org-defkey org-columns-map "e" 'org-columns-edit-value)
-(org-defkey org-columns-map "\C-c\C-t" 'org-columns-todo)
-(org-defkey org-columns-map "\C-c\C-c" 'org-columns-toggle-or-columns-quit)
-(org-defkey org-columns-map "\C-c\C-o" 'org-columns-open-link)
-(org-defkey org-columns-map "v" 'org-columns-show-value)
-(org-defkey org-columns-map "q" 'org-columns-quit)
-(org-defkey org-columns-map "r" 'org-columns-redo)
-(org-defkey org-columns-map "g" 'org-columns-redo)
-(org-defkey org-columns-map [left] 'backward-char)
-(org-defkey org-columns-map "\M-b" 'backward-char)
-(org-defkey org-columns-map "a" 'org-columns-edit-allowed)
-(org-defkey org-columns-map "s" 'org-columns-edit-attributes)
+(org-defkey org-columns-map "c"        #'org-columns-content)
+(org-defkey org-columns-map "o"        #'org-overview)
+(org-defkey org-columns-map "e"        #'org-columns-edit-value)
+(org-defkey org-columns-map "\C-c\C-t" #'org-columns-todo)
+(org-defkey org-columns-map "\C-c\C-c" #'org-columns-toggle-or-columns-quit)
+(org-defkey org-columns-map "\C-c\C-o" #'org-columns-open-link)
+(org-defkey org-columns-map "v"        #'org-columns-show-value)
+(org-defkey org-columns-map "q"        #'org-columns-quit)
+(org-defkey org-columns-map "r"        #'org-columns-redo)
+(org-defkey org-columns-map "g"        #'org-columns-redo)
+(org-defkey org-columns-map [left]     #'backward-char)
+(org-defkey org-columns-map "\M-b"     #'backward-char)
+(org-defkey org-columns-map "a"        #'org-columns-edit-allowed)
+(org-defkey org-columns-map "s"        #'org-columns-edit-attributes)
 (org-defkey org-columns-map "\M-f"
            (lambda () (interactive) (goto-char (1+ (point)))))
 (org-defkey org-columns-map [right]
@@ -187,7 +187,7 @@ See `org-columns-summary-types' for details.")
                (while (and (org-invisible-p2) (not (eobp)))
                  (beginning-of-line 2))
                (move-to-column col)
-               (if (eq major-mode 'org-agenda-mode)
+               (if (derived-mode-p 'org-agenda-mode)
                    (org-agenda-do-context-action)))))
 (org-defkey org-columns-map [up]
            (lambda () (interactive)
@@ -198,22 +198,22 @@ See `org-columns-summary-types' for details.")
                (move-to-column col)
                (if (eq major-mode 'org-agenda-mode)
                    (org-agenda-do-context-action)))))
-(org-defkey org-columns-map [(shift right)] 'org-columns-next-allowed-value)
-(org-defkey org-columns-map "n" 'org-columns-next-allowed-value)
-(org-defkey org-columns-map [(shift left)] 'org-columns-previous-allowed-value)
-(org-defkey org-columns-map "p" 'org-columns-previous-allowed-value)
-(org-defkey org-columns-map "<" 'org-columns-narrow)
-(org-defkey org-columns-map ">" 'org-columns-widen)
-(org-defkey org-columns-map [(meta right)] 'org-columns-move-right)
-(org-defkey org-columns-map [(meta left)] 'org-columns-move-left)
-(org-defkey org-columns-map [(shift meta right)] 'org-columns-new)
-(org-defkey org-columns-map [(shift meta left)] 'org-columns-delete)
+(org-defkey org-columns-map [(shift right)] #'org-columns-next-allowed-value)
+(org-defkey org-columns-map "n" #'org-columns-next-allowed-value)
+(org-defkey org-columns-map [(shift left)] 
#'org-columns-previous-allowed-value)
+(org-defkey org-columns-map "p" #'org-columns-previous-allowed-value)
+(org-defkey org-columns-map "<" #'org-columns-narrow)
+(org-defkey org-columns-map ">" #'org-columns-widen)
+(org-defkey org-columns-map [(meta right)] #'org-columns-move-right)
+(org-defkey org-columns-map [(meta left)]  #'org-columns-move-left)
+(org-defkey org-columns-map [(shift meta right)] #'org-columns-new)
+(org-defkey org-columns-map [(shift meta left)]  #'org-columns-delete)
 (dotimes (i 10)
   (org-defkey org-columns-map (number-to-string i)
-             `(lambda () (interactive)
-                (org-columns-next-allowed-value nil ,i))))
+             (lambda () (interactive)
+               (org-columns-next-allowed-value nil i))))
 
-(easy-menu-define org-columns-menu org-columns-map "Org Column Menu"
+(easy-menu-define org-columns-menu org-columns-map "Org Column Menu."
   '("Column"
     ["Edit property" org-columns-edit-value t]
     ["Next allowed value" org-columns-next-allowed-value t]
@@ -490,7 +490,7 @@ for the duration of the command.")
           (org-add-props " " nil 'display `(space :align-to ,linum-offset))
           (org-add-props (substring title 0 -1) nil 'face 'org-column-title)))
     (setq org-columns-previous-hscroll -1)
-    (add-hook 'post-command-hook 'org-columns-hscroll-title nil 'local)))
+    (add-hook 'post-command-hook #'org-columns-hscroll-title nil 'local)))
 
 (defun org-columns-hscroll-title ()
   "Set the `header-line-format' so that it scrolls along with the table."
@@ -519,7 +519,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-hscroll-title 'local))
+      (remove-hook 'post-command-hook #'org-columns-hscroll-title 'local))
     (set-marker org-columns-begin-marker nil)
     (when (markerp org-columns-top-level-marker)
       (set-marker org-columns-top-level-marker nil))
@@ -782,7 +782,7 @@ around it."
       (setq time-after (copy-sequence time))
       (setf (nth 3 time-before) (1- (nth 3 time)))
       (setf (nth 3 time-after) (1+ (nth 3 time)))
-      (mapcar (lambda (x) (format-time-string fmt (apply 'encode-time x)))
+      (mapcar (lambda (x) (format-time-string fmt (apply #'encode-time x)))
              (list time-before time time-after)))))
 
 (defun org-columns-open-link (&optional arg)
@@ -878,7 +878,7 @@ When COLUMNS-FMT-STRING is non-nil, use it as the column 
format."
              (setq-local org-colview-initial-truncate-line-value
                          truncate-lines))
             (if (not global-visual-line-mode)
-              (setq truncate-lines t))
+                (setq truncate-lines t))
            (dolist (entry cache)
              (goto-char (car entry))
              (org-columns--display-here (cdr entry)))))))))
@@ -1272,7 +1272,7 @@ When PRINTF is non-nil, use it to format the result."
   "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)))
+                                      (string-match-p "\\[\\([1-9]\\)/\\1\\]" 
b)))
                       check-boxes)
          (length check-boxes)))
 
@@ -1398,8 +1398,9 @@ other rows.  Each row is a list of fields, as strings, or
                                  (org-get-tags))))
             (push (cons (org-reduced-level (org-current-level)) (nreverse row))
                   table)))))
-     (or (and maxlevel (format "LEVEL<=%d" maxlevel))
-        (and match match))
+     (if match
+         (concat match (and maxlevel (format "+LEVEL<=%d" maxlevel)))
+       (and maxlevel (format "LEVEL<=%d" maxlevel)))
      (and local 'tree)
      'archive 'comment)
     (org-columns-quit)
@@ -1694,7 +1695,7 @@ This will add overlays to the date lines, to show the 
summary for each day."
                               (delq nil
                                     (mapcar
                                      (lambda (e) (org-string-nw-p
-                                             (nth 1 (assoc spec e))))
+                                                  (nth 1 (assoc spec e))))
                                      entries)))
                              (final (if values
                                         (funcall summarize values printf)
diff --git a/lisp/org-compat.el b/lisp/org-compat.el
index 8a28154..d230ee2 100644
--- a/lisp/org-compat.el
+++ b/lisp/org-compat.el
@@ -2,7 +2,7 @@
 
 ;; Copyright (C) 2004-2021 Free Software Foundation, Inc.
 
-;; Author: Carsten Dominik <carsten at orgmode dot org>
+;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: https://orgmode.org
 ;;
@@ -72,6 +72,16 @@
 (defvar org-table1-hline-regexp)
 
 
+;;; Emacs < 28.1 compatibility
+
+(if (fboundp 'directory-empty-p)
+    (defalias 'org-directory-empty-p #'directory-empty-p)
+  (defun org-directory-empty-p (dir)
+    "Return t if DIR names an existing directory containing no other files."
+    (and (file-directory-p dir)
+         (null (directory-files dir nil directory-files-no-dot-files-regexp 
t)))))
+
+
 ;;; Emacs < 27.1 compatibility
 
 (unless (fboundp 'proper-list-p)
@@ -119,6 +129,32 @@ extension beyond end of line was not controllable."
   (when (fboundp 'set-face-extend)
     (mapc (lambda (f) (set-face-extend f extend-p)) faces)))
 
+(if (fboundp 'string-distance)
+    (defalias 'org-string-distance 'string-distance)
+  (defun org-string-distance (s1 s2)
+    "Return the edit (levenshtein) distance between strings S1 S2."
+    (let* ((l1 (length s1))
+          (l2 (length s2))
+          (dist (vconcat (mapcar (lambda (_) (make-vector (1+ l2) nil))
+                                 (number-sequence 1 (1+ l1)))))
+          (in (lambda (i j) (aref (aref dist i) j))))
+      (setf (aref (aref dist 0) 0) 0)
+      (dolist (j (number-sequence 1 l2))
+        (setf (aref (aref dist 0) j) j))
+      (dolist (i (number-sequence 1 l1))
+        (setf (aref (aref dist i) 0) i)
+        (dolist (j (number-sequence 1 l2))
+         (setf (aref (aref dist i) j)
+               (min
+                (1+ (funcall in (1- i) j))
+                (1+ (funcall in i (1- j)))
+                (+ (if (equal (aref s1 (1- i)) (aref s2 (1- j))) 0 1)
+                   (funcall in (1- i) (1- j)))))))
+      (funcall in l1 l2))))
+
+(define-obsolete-function-alias 'org-babel-edit-distance 'org-string-distance
+  "9.5")
+
 
 ;;; Emacs < 26.1 compatibility
 
@@ -179,9 +215,9 @@ This is a floating point number if the size is too large 
for an integer."
 Case is significant."
     (string< s1 s2)))
 
-;; The time- functions below translate nil to `current-time` and
-;; accept an integer as of Emacs 25.  `decode-time` and
-;; `format-time-string` accept nil on Emacs 24 but don't accept an
+;; The time- functions below translate nil to 'current-time' and
+;; accept an integer as of Emacs 25.  'decode-time' and
+;; 'format-time-string' accept nil on Emacs 24 but don't accept an
 ;; integer until Emacs 25.
 (if (< emacs-major-version 25)
     (let ((convert
@@ -212,38 +248,38 @@ Case is significant."
 ;;; Obsolete aliases (remove them after the next major release).
 
 ;;;; XEmacs compatibility, now removed.
-(define-obsolete-function-alias 'org-activate-mark 'activate-mark "Org 9.0")
-(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")
-(define-obsolete-function-alias 'org-file-remote-p 'file-remote-p "Org 9.2")
+(define-obsolete-function-alias 'org-activate-mark 'activate-mark "9.0")
+(define-obsolete-function-alias 'org-add-hook 'add-hook "9.0")
+(define-obsolete-function-alias 'org-bound-and-true-p 'bound-and-true-p "9.0")
+(define-obsolete-function-alias 'org-decompose-region 'decompose-region "9.0")
+(define-obsolete-function-alias 'org-defvaralias 'defvaralias "9.0")
+(define-obsolete-function-alias 'org-detach-overlay 'delete-overlay "9.0")
+(define-obsolete-function-alias 'org-file-equal-p 'file-equal-p "9.0")
+(define-obsolete-function-alias 'org-float-time 'float-time "9.0")
+(define-obsolete-function-alias 'org-indent-line-to 'indent-line-to "9.0")
+(define-obsolete-function-alias 'org-indent-to-column 'indent-to-column "9.0")
+(define-obsolete-function-alias 'org-looking-at-p 'looking-at-p "9.0")
+(define-obsolete-function-alias 'org-looking-back 'looking-back "9.0")
+(define-obsolete-function-alias 'org-match-string-no-properties 
'match-string-no-properties "9.0")
+(define-obsolete-function-alias 'org-propertize 'propertize "9.0")
+(define-obsolete-function-alias 'org-select-frame-set-input-focus 
'select-frame-set-input-focus "9.0")
+(define-obsolete-function-alias 'org-file-remote-p 'file-remote-p "9.2")
 
 (defmacro org-re (s)
   "Replace posix classes in regular expression S."
   (declare (debug (form))
-           (obsolete "you can safely remove it." "Org 9.0"))
+           (obsolete "you can safely remove it." "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")
+(define-obsolete-function-alias 'org-count 'cl-count "9.0")
+(define-obsolete-function-alias 'org-every 'cl-every "9.0")
+(define-obsolete-function-alias 'org-find-if 'cl-find-if "9.0")
+(define-obsolete-function-alias 'org-reduce 'cl-reduce "9.0")
+(define-obsolete-function-alias 'org-remove-if 'cl-remove-if "9.0")
+(define-obsolete-function-alias 'org-remove-if-not 'cl-remove-if-not "9.0")
+(define-obsolete-function-alias 'org-some 'cl-some "9.0")
+(define-obsolete-function-alias 'org-floor* 'cl-floor "9.0")
 
 (defun org-sublist (list start end)
   "Return a section of LIST, from START to END.
@@ -251,89 +287,91 @@ 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")
+               "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")
+(define-obsolete-function-alias 'org-buffer-narrowed-p 'buffer-narrowed-p 
"9.0")
+(define-obsolete-function-alias 'org-called-interactively-p 
'called-interactively-p "9.0")
+(define-obsolete-function-alias 'org-char-to-string 'char-to-string "9.0")
+(define-obsolete-function-alias 'org-delete-directory 'delete-directory "9.0")
+(define-obsolete-function-alias 'org-format-seconds 'format-seconds "9.0")
+(define-obsolete-function-alias 'org-link-escape-browser 'url-encode-url "9.0")
+(define-obsolete-function-alias 'org-no-warnings 'with-no-warnings "9.0")
+(define-obsolete-function-alias 'org-number-sequence 'number-sequence "9.0")
+(define-obsolete-function-alias 'org-pop-to-buffer-same-window 
'pop-to-buffer-same-window "9.0")
+(define-obsolete-function-alias 'org-string-match-p 'string-match-p "9.0")
 
 ;;;; Functions and variables from previous releases now obsolete.
 (define-obsolete-function-alias 'org-element-remove-indentation
-  'org-remove-indentation "Org 9.0")
+  'org-remove-indentation "9.0")
 (define-obsolete-variable-alias 'org-latex-create-formula-image-program
-  'org-preview-latex-default-process "Org 9.0")
+  'org-preview-latex-default-process "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")
+  'org-preview-latex-image-directory "9.0")
+(define-obsolete-function-alias 'org-table-p 'org-at-table-p "9.0")
+(define-obsolete-function-alias 'org-on-heading-p 'org-at-heading-p "9.0")
+(define-obsolete-function-alias 'org-at-regexp-p 'org-in-regexp "8.3")
 (define-obsolete-function-alias 'org-image-file-name-regexp
-  'image-file-name-regexp "Org 9.0")
+  'image-file-name-regexp "9.0")
 (define-obsolete-function-alias 'org-completing-read-no-i
-  'completing-read "Org 9.0")
+  'completing-read "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")
+  'completing-read "9.0")
+(define-obsolete-function-alias 'org-iread-file-name 'read-file-name "9.0")
 (define-obsolete-function-alias 'org-days-to-time
-  'org-time-stamp-to-now "Org 8.2")
+  'org-time-stamp-to-now "8.2")
 (define-obsolete-variable-alias 'org-agenda-ignore-drawer-properties
-  'org-agenda-ignore-properties "Org 9.0")
+  'org-agenda-ignore-properties "9.0")
 (define-obsolete-function-alias 'org-preview-latex-fragment
-  'org-toggle-latex-fragment "Org 8.3")
+  'org-toggle-latex-fragment "8.3")
 (define-obsolete-function-alias 'org-export-get-genealogy
-  'org-element-lineage "Org 9.0")
+  'org-element-lineage "9.0")
 (define-obsolete-variable-alias 'org-latex-with-hyperref
-  'org-latex-hyperref-template "Org 9.0")
-(define-obsolete-variable-alias 'hfy-optimisations 'hfy-optimizations "Org 
9.0")
+  'org-latex-hyperref-template "9.0")
+(define-obsolete-variable-alias 'hfy-optimisations 'hfy-optimizations "9.0")
 (define-obsolete-variable-alias 'org-export-htmlized-org-css-url
-  'org-org-htmlized-css-url "Org 8.2")
-(define-obsolete-function-alias 'org-list-parse-list 'org-list-to-lisp "Org 
9.0")
+  'org-org-htmlized-css-url "8.2")
+(define-obsolete-function-alias 'org-list-parse-list 'org-list-to-lisp "9.0")
 (define-obsolete-function-alias 'org-agenda-todayp
-  'org-agenda-today-p "Org 9.0")
+  'org-agenda-today-p "9.0")
 (define-obsolete-function-alias 'org-babel-examplize-region
-  'org-babel-examplify-region "Org 9.0")
+  'org-babel-examplify-region "9.0")
 (define-obsolete-variable-alias 'org-babel-capitalize-example-region-markers
-  'org-babel-uppercase-example-markers "Org 9.1")
+  'org-babel-uppercase-example-markers "9.1")
 
-(define-obsolete-function-alias 'org-babel-trim 'org-trim "Org 9.0")
+(define-obsolete-function-alias 'org-babel-trim 'org-trim "9.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")
+  'org-columns-insert-dblock "9.0")
 (define-obsolete-variable-alias 'org-export-babel-evaluate
-  'org-export-use-babel "Org 9.1")
+  'org-export-use-babel "9.1")
 (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")
-(define-obsolete-function-alias 'org-remove-double-quotes 'org-strip-quotes 
"Org 9.0")
+  'org-activate-links "9.0")
+(define-obsolete-function-alias 'org-activate-plain-links 'ignore "9.0")
+(define-obsolete-function-alias 'org-activate-angle-links 'ignore "9.0")
+(define-obsolete-function-alias 'org-remove-double-quotes 'org-strip-quotes 
"9.0")
 (define-obsolete-function-alias 'org-get-indentation
-  'current-indentation "Org 9.2")
-(define-obsolete-function-alias 'org-capture-member 'org-capture-get "Org 9.2")
+  'current-indentation "9.2")
+(define-obsolete-function-alias 'org-capture-member 'org-capture-get "9.2")
 (define-obsolete-function-alias 'org-remove-from-invisibility-spec
-  'remove-from-invisibility-spec "Org 9.2")
+  'remove-from-invisibility-spec "9.2")
 
 (define-obsolete-variable-alias 'org-effort-durations 'org-duration-units
-  "Org 9.2")
+  "9.2")
 
 (define-obsolete-function-alias 'org-toggle-latex-fragment 'org-latex-preview
-  "Org 9.3")
+  "9.3")
 
 (define-obsolete-function-alias 'org-remove-latex-fragment-image-overlays
-  'org-clear-latex-preview "Org 9.3")
+  'org-clear-latex-preview "9.3")
 
 (define-obsolete-variable-alias 'org-attach-directory
-  'org-attach-id-dir "Org 9.3")
-(make-obsolete 'org-attach-store-link "No longer used" "Org 9.4")
-(make-obsolete 'org-attach-expand-link "No longer used" "Org 9.4")
+  'org-attach-id-dir "9.3")
+(make-obsolete 'org-attach-store-link "No longer used" "9.4")
+(make-obsolete 'org-attach-expand-link "No longer used" "9.4")
+
+(define-obsolete-function-alias 'org-file-url-p 'org-url-p "9.5")
 
 (defun org-in-fixed-width-region-p ()
   "Non-nil if point in a fixed-width region."
@@ -341,7 +379,7 @@ Counting starts at 1."
     (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")
+               "9.0")
 
 (defun org-compatible-face (inherits specs)
   "Make a compatible face specification.
@@ -352,7 +390,7 @@ is, use SPECS to define the face."
   (if (facep inherits)
       (list (list t :inherit inherits))
     specs))
-(make-obsolete 'org-compatible-face "you can remove it." "Org 9.0")
+(make-obsolete 'org-compatible-face "you can remove it." "9.0")
 
 (defun org-add-link-type (type &optional follow export)
   "Add a new TYPE link.
@@ -383,7 +421,7 @@ 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")
+(make-obsolete 'org-add-link-type "use `org-link-set-parameters' instead." 
"9.0")
 
 ;;;; Functions unused in Org core.
 (defun org-table-recognize-table.el ()
@@ -407,12 +445,12 @@ See `org-link-parameters' for documentation on the other 
parameters."
 ;; Not used since commit 6d1e3082, Feb 2010.
 (make-obsolete 'org-table-recognize-table.el
                "please notify Org mailing list if you use this function."
-               "Org 9.0")
+               "9.0")
 
 (defmacro org-preserve-lc (&rest body)
   (declare (debug (body))
           (obsolete "please notify Org mailing list if you use this function."
-                    "Org 9.2"))
+                    "9.2"))
   (org-with-gensyms (line col)
     `(let ((,line (org-current-line))
           (,col (current-column)))
@@ -424,12 +462,12 @@ See `org-link-parameters' for documentation on the other 
parameters."
 (defun org-version-check (version &rest _)
   "Non-nil if VERSION is lower (older) than `emacs-version'."
   (declare (obsolete "use `version<' or `fboundp' instead."
-                    "Org 9.2"))
+                    "9.2"))
   (version< version emacs-version))
 
 (defun org-remove-angle-brackets (s)
   (org-unbracket-string "<" ">" s))
-(make-obsolete 'org-remove-angle-brackets 'org-unbracket-string "Org 9.0")
+(make-obsolete 'org-remove-angle-brackets 'org-unbracket-string "9.0")
 
 (defcustom org-publish-sitemap-file-entry-format "%t"
   "Format string for site-map file entry.
@@ -443,7 +481,7 @@ You could use brackets to delimit on what part the link 
will be.
 (make-obsolete-variable
  'org-publish-sitemap-file-entry-format
  "set `:sitemap-format-entry' in `org-publish-project-alist' instead."
- "Org 9.1")
+ "9.1")
 
 (defvar org-agenda-skip-regexp)
 (defun org-agenda-skip-entry-when-regexp-matches ()
@@ -452,7 +490,7 @@ If yes, it returns the end position of this entry, causing 
agenda commands
 to skip the entry but continuing the search in the subtree.  This is a
 function that can be put into `org-agenda-skip-function' for the duration
 of a command."
-  (declare (obsolete "use `org-agenda-skip-if' instead." "Org 9.1"))
+  (declare (obsolete "use `org-agenda-skip-if' instead." "9.1"))
   (let ((end (save-excursion (org-end-of-subtree t)))
        skip)
     (save-excursion
@@ -464,7 +502,7 @@ of a command."
 If yes, it returns the end position of this tree, causing agenda commands
 to skip this subtree.  This is a function that can be put into
 `org-agenda-skip-function' for the duration of a command."
-  (declare (obsolete "use `org-agenda-skip-if' instead." "Org 9.1"))
+  (declare (obsolete "use `org-agenda-skip-if' instead." "9.1"))
   (let ((end (save-excursion (org-end-of-subtree t)))
        skip)
     (save-excursion
@@ -478,7 +516,7 @@ causing agenda commands to skip the entry but continuing 
the search in
 the subtree.  This is a function that can be put into
 `org-agenda-skip-function' for the duration of a command.  An important
 use of this function is for the stuck project list."
-  (declare (obsolete "use `org-agenda-skip-if' instead." "Org 9.1"))
+  (declare (obsolete "use `org-agenda-skip-if' instead." "9.1"))
   (let ((end (save-excursion (org-end-of-subtree t)))
        (entry-end (save-excursion (outline-next-heading) (1- (point))))
        skip)
@@ -487,126 +525,126 @@ use of this function is for the stuck project list."
     (and skip entry-end)))
 
 (define-obsolete-function-alias 'org-minutes-to-clocksum-string
-  'org-duration-from-minutes "Org 9.1")
+  'org-duration-from-minutes "9.1")
 
 (define-obsolete-function-alias 'org-hh:mm-string-to-minutes
-  'org-duration-to-minutes "Org 9.1")
+  'org-duration-to-minutes "9.1")
 
 (define-obsolete-function-alias 'org-duration-string-to-minutes
-  'org-duration-to-minutes "Org 9.1")
+  'org-duration-to-minutes "9.1")
 
 (make-obsolete-variable 'org-time-clocksum-format
-  "set `org-duration-format' instead." "Org 9.1")
+                        "set `org-duration-format' instead." "9.1")
 
 (make-obsolete-variable 'org-time-clocksum-use-fractional
-  "set `org-duration-format' instead." "Org 9.1")
+                        "set `org-duration-format' instead." "9.1")
 
 (make-obsolete-variable 'org-time-clocksum-fractional-format
-  "set `org-duration-format' instead." "Org 9.1")
+                        "set `org-duration-format' instead." "9.1")
 
 (make-obsolete-variable 'org-time-clocksum-use-effort-durations
-  "set `org-duration-units' instead." "Org 9.1")
+                        "set `org-duration-units' instead." "9.1")
 
 (define-obsolete-function-alias 'org-babel-number-p
-  'org-babel--string-to-number "Org 9.0")
+  'org-babel--string-to-number "9.0")
 
 (define-obsolete-variable-alias 'org-usenet-links-prefer-google
-  'org-gnus-prefer-web-links "Org 9.1")
+  'org-gnus-prefer-web-links "9.1")
 
 (define-obsolete-variable-alias 'org-texinfo-def-table-markup
-  'org-texinfo-table-default-markup "Org 9.1")
+  'org-texinfo-table-default-markup "9.1")
 
 (define-obsolete-variable-alias 'org-agenda-overriding-columns-format
-  'org-overriding-columns-format "Org 9.2.2")
+  'org-overriding-columns-format "9.2.2")
 
 (define-obsolete-variable-alias 'org-doi-server-url
-  'org-link-doi-server-url "Org 9.3")
+  'org-link-doi-server-url "9.3")
 
 (define-obsolete-variable-alias 'org-email-link-description-format
-  'org-link-email-description-format "Org 9.3")
+  'org-link-email-description-format "9.3")
 
 (define-obsolete-variable-alias 'org-make-link-description-function
-  'org-link-make-description-function "Org 9.3")
+  'org-link-make-description-function "9.3")
 
 (define-obsolete-variable-alias 'org-from-is-user-regexp
-  'org-link-from-user-regexp "Org 9.3")
+  'org-link-from-user-regexp "9.3")
 
 (define-obsolete-variable-alias 'org-descriptive-links
-  'org-link-descriptive "Org 9.3")
+  'org-link-descriptive "9.3")
 
 (define-obsolete-variable-alias 'org-context-in-file-links
-  'org-link-context-for-files "Org 9.3")
+  'org-link-context-for-files "9.3")
 
 (define-obsolete-variable-alias 'org-keep-stored-link-after-insertion
-  'org-link-keep-stored-after-insertion "Org 9.3")
+  'org-link-keep-stored-after-insertion "9.3")
 
 (define-obsolete-variable-alias 'org-display-internal-link-with-indirect-buffer
-  'org-link-use-indirect-buffer-for-internals "Org 9.3")
+  'org-link-use-indirect-buffer-for-internals "9.3")
 
 (define-obsolete-variable-alias 'org-confirm-shell-link-function
-  'org-link-shell-confirm-function "Org 9.3")
+  'org-link-shell-confirm-function "9.3")
 
 (define-obsolete-variable-alias 'org-confirm-shell-link-not-regexp
-  'org-link-shell-skip-confirm-regexp "Org 9.3")
+  'org-link-shell-skip-confirm-regexp "9.3")
 
 (define-obsolete-variable-alias 'org-confirm-elisp-link-function
-  'org-link-elisp-confirm-function "Org 9.3")
+  'org-link-elisp-confirm-function "9.3")
 
 (define-obsolete-variable-alias 'org-confirm-elisp-link-not-regexp
-  'org-link-elisp-skip-confirm-regexp "Org 9.3")
+  'org-link-elisp-skip-confirm-regexp "9.3")
 
 (define-obsolete-function-alias 'org-file-complete-link
-  'org-link-complete-file "Org 9.3")
+  'org-link-complete-file "9.3")
 
 (define-obsolete-function-alias 'org-email-link-description
-  'org-link-email-description "Org 9.3")
+  'org-link-email-description "9.3")
 
 (define-obsolete-function-alias 'org-make-link-string
-  'org-link-make-string "Org 9.3")
+  'org-link-make-string "9.3")
 
 (define-obsolete-function-alias 'org-store-link-props
-  'org-link-store-props "Org 9.3")
+  'org-link-store-props "9.3")
 
 (define-obsolete-function-alias 'org-add-link-props
-  'org-link-add-props "Org 9.3")
+  'org-link-add-props "9.3")
 
 (define-obsolete-function-alias 'org-make-org-heading-search-string
-  'org-link-heading-search-string "Org 9.3")
+  'org-link-heading-search-string "9.3")
 
 (define-obsolete-function-alias 'org-make-link-regexps
-  'org-link-make-regexps "Org 9.3")
+  'org-link-make-regexps "9.3")
 
 (define-obsolete-function-alias 'org-property-global-value
-  'org-property-global-or-keyword-value "Org 9.3")
+  'org-property-global-or-keyword-value "9.3")
 
-(make-obsolete-variable 'org-file-properties 'org-keyword-properties "Org 9.3")
+(make-obsolete-variable 'org-file-properties 'org-keyword-properties "9.3")
 
 (define-obsolete-variable-alias 'org-angle-link-re
-  'org-link-angle-re "Org 9.3")
+  'org-link-angle-re "9.3")
 
 (define-obsolete-variable-alias 'org-plain-link-re
-  'org-link-plain-re "Org 9.3")
+  'org-link-plain-re "9.3")
 
 (define-obsolete-variable-alias 'org-bracket-link-regexp
-  'org-link-bracket-re "Org 9.3")
+  'org-link-bracket-re "9.3")
 
 (define-obsolete-variable-alias 'org-bracket-link-analytic-regexp
-  'org-link-bracket-re "Org 9.3")
+  'org-link-bracket-re "9.3")
 
 (define-obsolete-variable-alias 'org-any-link-re
-  'org-link-any-re "Org 9.3")
+  'org-link-any-re "9.3")
 
 (define-obsolete-function-alias 'org-open-link-from-string
-  'org-link-open-from-string "Org 9.3")
+  'org-link-open-from-string "9.3")
 
 (define-obsolete-function-alias 'org-add-angle-brackets
-  'org-link-add-angle-brackets "Org 9.3")
+  'org-link-add-angle-brackets "9.3")
 
 ;; 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")
+              "9.0")
 
 (defun org-show-block-all ()
   "Unfold all blocks in the current buffer."
@@ -615,34 +653,34 @@ use of this function is for the stuck project list."
 
 (make-obsolete 'org-show-block-all
               "use `org-show-all' instead."
-              "Org 9.2")
+              "9.2")
 
-(define-obsolete-function-alias 'org-get-tags-at 'org-get-tags "Org 9.2")
+(define-obsolete-function-alias 'org-get-tags-at 'org-get-tags "9.2")
 
 (defun org-get-local-tags ()
   "Get a list of tags defined in the current headline."
-  (declare (obsolete "use `org-get-tags' instead." "Org 9.2"))
+  (declare (obsolete "use `org-get-tags' instead." "9.2"))
   (org-get-tags nil 'local))
 
 (defun org-get-local-tags-at (&optional pos)
   "Get a list of tags defined in the current headline."
-  (declare (obsolete "use `org-get-tags' instead." "Org 9.2"))
+  (declare (obsolete "use `org-get-tags' instead." "9.2"))
   (org-get-tags pos 'local))
 
 (defun org-get-tags-string ()
   "Get the TAGS string in the current headline."
-  (declare (obsolete "use `org-make-tag-string' instead." "Org 9.2"))
+  (declare (obsolete "use `org-make-tag-string' instead." "9.2"))
   (org-make-tag-string (org-get-tags nil t)))
 
-(define-obsolete-function-alias 'org-set-tags-to 'org-set-tags "Org 9.2")
+(define-obsolete-function-alias 'org-set-tags-to 'org-set-tags "9.2")
 
 (defun org-align-all-tags ()
   "Align the tags in all headings."
-  (declare (obsolete "use `org-align-tags' instead." "Org 9.2"))
+  (declare (obsolete "use `org-align-tags' instead." "9.2"))
   (org-align-tags t))
 
 (define-obsolete-function-alias
-  'org-at-property-block-p 'org-at-property-drawer-p "Org 9.4")
+  'org-at-property-block-p 'org-at-property-drawer-p "9.4")
 
 (defun org-flag-drawer (flag &optional element beg end)
   "When FLAG is non-nil, hide the drawer we are at.
@@ -653,7 +691,7 @@ When optional argument ELEMENT is a parsed drawer, as 
returned by
 
 When buffer positions BEG and END are provided, hide or show that
 region as a drawer without further ado."
-  (declare (obsolete "use `org-hide-drawer-toggle' instead." "Org 9.4"))
+  (declare (obsolete "use `org-hide-drawer-toggle' instead." "9.4"))
   (if (and beg end) (org-flag-region beg end flag 'outline)
     (let ((drawer
           (or element
@@ -678,14 +716,14 @@ region as a drawer without further ado."
   "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."
-  (declare (obsolete "use `org-hide-block-toggle' instead." "Org 9.4"))
+  (declare (obsolete "use `org-hide-block-toggle' instead." "9.4"))
   (interactive)
   (org-hide-block-toggle nil t))
 
 (defun org-hide-block-toggle-all ()
   "Toggle the visibility of all blocks in the current buffer."
   (declare (obsolete "please notify Org mailing list if you use this function."
-                    "Org 9.4"))
+                    "9.4"))
   (let ((start (point-min))
         (end (point-max)))
     (save-excursion
@@ -703,17 +741,17 @@ an error.  Return a non-nil value when toggling is 
successful."
 Calls `org-table-next-row' or `newline-and-indent', depending on
 context.  See the individual commands for more information."
   (declare (obsolete "use `org-return' with INDENT set to t instead."
-                    "Org 9.4"))
+                    "9.4"))
   (interactive)
   (org-return t))
 
 (defmacro org-with-silent-modifications (&rest body)
-  (declare (obsolete "use `with-silent-modifications' instead." "Org 9.2")
+  (declare (obsolete "use `with-silent-modifications' instead." "9.2")
           (debug (body)))
   `(with-silent-modifications ,@body))
 
 (define-obsolete-function-alias 'org-babel-strip-quotes
-  'org-strip-quotes "Org 9.2")
+  'org-strip-quotes "9.2")
 
 (define-obsolete-variable-alias 'org-sort-agenda-notime-is-late
   'org-agenda-sort-notime-is-late "9.4")
@@ -730,9 +768,11 @@ context.  See the individual commands for more 
information."
 (make-obsolete-variable
  'org-maybe-keyword-time-regexp
  "use `org-planning-line-re', followed by `org-ts-regexp-both' instead."
- "Org 9.4")
+ "9.4")
+
+(define-obsolete-function-alias 'org-copy 'org-refile-copy "9.4")
 
-(define-obsolete-function-alias 'org-copy 'org-refile-copy "Org 9.4")
+(define-obsolete-function-alias 'org-get-last-sibling 
'org-get-previous-sibling "9.4")
 
 ;;;; Obsolete link types
 
@@ -1025,8 +1065,7 @@ ELEMENT is the element at point."
 (defun org-mode-flyspell-verify ()
   "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'.
+      ;; At a headline or an inlinetask, check title only.
       (and (save-excursion (beginning-of-line)
                           (and (let ((case-fold-search t))
                                  (not (looking-at-p "\\*+ END[ \t]*$")))
@@ -1035,7 +1074,9 @@ ELEMENT is the element at point."
           (match-beginning 4)
           (>= (point) (match-beginning 4))
           (or (not (match-beginning 5))
-              (< (point) (match-beginning 5))))
+              (< (point) (match-beginning 5)))
+           ;; Ignore checks in code, verbatim and others.
+           (org--flyspell-object-check-p (org-element-at-point)))
     (let* ((element (org-element-at-point))
           (post-affiliated (org-element-property :post-affiliated element)))
       (cond
@@ -1146,8 +1187,8 @@ key."
     ((guard (not (lookup-key calendar-mode-map "c")))
      (local-set-key "c" #'org-calendar-goto-agenda))
     (_ nil))
-  (unless (and (boundp 'org-agenda-diary-file)
-              (eq org-agenda-diary-file 'diary-file))
+  (when (and (boundp 'org-agenda-diary-file)
+            (not (eq org-agenda-diary-file 'diary-file)))
     (local-set-key org-calendar-insert-diary-entry-key
                   #'org-agenda-diary-entry)))
 
@@ -1201,6 +1242,11 @@ key."
 (eval-after-load 'session
   '(add-to-list 'session-globals-exclude 'org-mark-ring))
 
+;;;; Speed commands
+
+(make-obsolete-variable 'org-speed-commands-user
+                        "configure `org-speed-commands' instead." "9.5")
+
 (provide 'org-compat)
 
 ;; Local variables:
diff --git a/lisp/org-crypt.el b/lisp/org-crypt.el
index caf9de9..48f76b7 100644
--- a/lisp/org-crypt.el
+++ b/lisp/org-crypt.el
@@ -185,10 +185,10 @@ See `org-crypt-disable-auto-save'."
      ((eq org-crypt-disable-auto-save 'encrypt)
       (message "org-decrypt: Enabling re-encryption on auto-save.")
       (add-hook 'auto-save-hook
-                   (lambda ()
-                     (message "org-crypt: Re-encrypting all decrypted entries 
due to auto-save.")
-                     (org-encrypt-entries))
-                   nil t))
+               (lambda ()
+                 (message "org-crypt: Re-encrypting all decrypted entries due 
to auto-save.")
+                 (org-encrypt-entries))
+               nil t))
      (t nil))))
 
 (defun org-crypt-key-for-heading ()
@@ -284,6 +284,8 @@ Assume `epg-context' is set."
         nil)))
     (_ nil)))
 
+(defvar org--matcher-tags-todo-only)
+
 ;;;###autoload
 (defun org-encrypt-entries ()
   "Encrypt all top-level entries in the current buffer."
diff --git a/lisp/org-ctags.el b/lisp/org-ctags.el
index 8dc177d..7876c6e 100644
--- a/lisp/org-ctags.el
+++ b/lisp/org-ctags.el
@@ -1,12 +1,10 @@
-;;; org-ctags.el - Integrate Emacs "tags" Facility with Org -*- 
lexical-binding: t; -*-
-;;
+;;; org-ctags.el --- Integrate Emacs "tags" Facility with Org -*- 
lexical-binding: t; -*-
+
 ;; Copyright (C) 2007-2021 Free Software Foundation, Inc.
 
 ;; Author: Paul Sexton <eeeickythump@gmail.com>
-
-
 ;; Keywords: org, wp
-;;
+
 ;; This file is part of GNU Emacs.
 ;;
 ;; GNU Emacs is free software: you can redistribute it and/or modify
@@ -22,6 +20,8 @@
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
 
+;;; Commentary:
+
 ;;
 ;; Synopsis
 ;; ========
@@ -165,7 +165,7 @@ See the ctags documentation for more information.")
   '(org-ctags-find-tag
     org-ctags-ask-rebuild-tags-file-then-find-tag
     org-ctags-ask-append-topic)
-  "List of functions to be prepended to ORG-OPEN-LINK-FUNCTIONS when ORG-CTAGS 
is active."
+  "List of functions to be prepended to ORG-OPEN-LINK-FUNCTIONS by ORG-CTAGS."
   :group 'org-ctags
   :version "24.1"
   :type 'hook
diff --git a/lisp/org-datetree.el b/lisp/org-datetree.el
index 62bd46e..74442b0 100644
--- a/lisp/org-datetree.el
+++ b/lisp/org-datetree.el
@@ -2,7 +2,7 @@
 
 ;; Copyright (C) 2009-2021 Free Software Foundation, Inc.
 
-;; Author: Carsten Dominik <carsten at orgmode dot org>
+;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: https://orgmode.org
 ;;
@@ -72,8 +72,8 @@ will be built under the headline at point."
 (defun org-datetree--find-create-group
     (d time-grouping &optional keep-restriction)
   "Find or create an entry for date D.
-If time-period is day, group entries by day. If time-period is
-month, then group entries by month."
+If time-period is day, group entries by day.
+If time-period is month, then group entries by month."
   (setq-local org-datetree-base-level 1)
   (save-restriction
     (if (eq keep-restriction 'subtree-at-point)
diff --git a/lisp/org-element.el b/lisp/org-element.el
index 0e01a0a..1c971b2 100644
--- a/lisp/org-element.el
+++ b/lisp/org-element.el
@@ -117,6 +117,19 @@
 ;; `org-element-update-syntax' builds proper syntax regexps according
 ;; to current setup.
 
+(defconst org-element-citation-key-re
+  (rx "@" (group (one-or-more (any word "-.:?!`'/*@+|(){}<>&_^$#%&~"))))
+  "Regexp matching a citation key.
+Key is located in match group 1.")
+
+(defconst org-element-citation-prefix-re
+  (rx "[cite"
+      (opt "/" (group (one-or-more (any "/_-" alnum)))) ;style
+      ":"
+      (zero-or-more (any "\t\n ")))
+  "Regexp matching a citation prefix.
+Style, if any, is located in match group 1.")
+
 (defvar org-element-paragraph-separate nil
   "Regexp to separate paragraphs in an Org buffer.
 In the case of lines starting with \"#\" and \":\", this regexp
@@ -182,15 +195,17 @@ specially in `org-element--object-lex'.")
                                      (nth 2 org-emphasis-regexp-components)))
                      ;; Plain links.
                      (concat "\\<" link-types ":")
-                     ;; Objects starting with "[": regular link,
+                     ;; Objects starting with "[": citations,
                      ;; footnote reference, statistics cookie,
-                     ;; timestamp (inactive).
-                     (concat "\\[\\(?:"
-                             "fn:" "\\|"
-                             "\\[" "\\|"
-                             "[0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}" "\\|"
-                             "[0-9]*\\(?:%\\|/[0-9]*\\)\\]"
-                             "\\)")
+                     ;; timestamp (inactive) and regular link.
+                     (format "\\[\\(?:%s\\)"
+                             (mapconcat
+                              #'identity
+                              (list "cite[:/]"
+                                    "fn:"
+                                    "\\(?:[0-9]\\|\\(?:%\\|/[0-9]*\\)\\]\\)"
+                                    "\\[")
+                              "\\|"))
                      ;; Objects starting with "@": export snippets.
                      "@@"
                      ;; Objects starting with "{": macro.
@@ -234,15 +249,15 @@ specially in `org-element--object-lex'.")
   "List of recursive element types aka Greater Elements.")
 
 (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
-        radio-target statistics-cookie strike-through subscript superscript
-        table-cell target timestamp underline verbatim)
+  '(bold citation citation-reference code entity export-snippet
+        footnote-reference inline-babel-call inline-src-block italic line-break
+        latex-fragment link macro radio-target statistics-cookie strike-through
+        subscript superscript table-cell target timestamp underline verbatim)
   "Complete list of object types.")
 
 (defconst org-element-recursive-objects
-  '(bold footnote-reference italic link subscript radio-target strike-through
-        superscript table-cell underline)
+  '(bold citation footnote-reference italic link subscript radio-target
+        strike-through superscript table-cell underline)
   "List of recursive object types.")
 
 (defconst org-element-object-containers
@@ -331,9 +346,12 @@ Don't modify it, set `org-element-affiliated-keywords' 
instead.")
 (defconst org-element-object-restrictions
   (let* ((minimal-set '(bold code entity italic latex-fragment strike-through
                             subscript superscript underline verbatim))
-        (standard-set (remq 'table-cell org-element-all-objects))
+        (standard-set
+         (remq 'citation-reference (remq 'table-cell org-element-all-objects)))
         (standard-set-no-line-break (remq 'line-break standard-set)))
     `((bold ,@standard-set)
+      (citation citation-reference)
+      (citation-reference ,@minimal-set)
       (footnote-reference ,@standard-set)
       (headline ,@standard-set-no-line-break)
       (inlinetask ,@standard-set-no-line-break)
@@ -354,8 +372,8 @@ Don't modify it, set `org-element-affiliated-keywords' 
instead.")
       ;; Ignore inline babel call and inline source block as formulas
       ;; are possible.  Also ignore line breaks and statistics
       ;; cookies.
-      (table-cell export-snippet footnote-reference link macro radio-target
-                 target timestamp ,@minimal-set)
+      (table-cell citation export-snippet footnote-reference link macro
+                  radio-target target timestamp ,@minimal-set)
       (table-row table-cell)
       (underline ,@standard-set)
       (verse-block ,@standard-set)))
@@ -370,9 +388,11 @@ 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)
+  '((citation :prefix :suffix)
+    (headline :title)
     (inlinetask :title)
-    (item :tag))
+    (item :tag)
+    (citation-reference :prefix :suffix))
   "Alist between element types and locations of secondary values.")
 
 (defconst org-element--pair-round-table
@@ -1001,7 +1021,10 @@ Assume point is at beginning of the headline."
           (commentedp
            (and (let (case-fold-search) (looking-at org-comment-string))
                 (goto-char (match-end 0))))
-          (title-start (point))
+          (title-start (prog1 (point)
+                          (unless (or todo priority commentedp)
+                            ;; Headline like "* :tag:"
+                            (skip-syntax-backward " \t"))))
           (tags (when (re-search-forward
                        "[ \t]+\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$"
                        (line-end-position)
@@ -2753,6 +2776,129 @@ CONTENTS is the contents of the object."
   (format "*%s*" contents))
 
 
+;;;; Citation
+
+(defun org-element-citation-parser ()
+  "Parse citation object at point, if any.
+
+When at a citation object, return a list whose car is `citation'
+and cdr is a plist with `:style', `:prefix', `:suffix', `:begin',
+`:end', `:contents-begin', `:contents-end', and `:post-blank'
+keywords.  Otherwise, return nil.
+
+Assume point is at the beginning of the citation."
+  (when (looking-at org-element-citation-prefix-re)
+    (let* ((begin (point))
+          (style (and (match-end 1)
+                      (match-string-no-properties 1)))
+          ;; Ignore blanks between cite type and prefix or key.
+          (start (match-end 0))
+          (closing (with-syntax-table org-element--pair-square-table
+                     (ignore-errors (scan-lists begin 1 0)))))
+      (save-excursion
+       (when (and closing
+                  (re-search-forward org-element-citation-key-re closing t))
+         ;; Find prefix, if any.
+         (let ((first-key-end (match-end 0))
+               (types (org-element-restriction 'citation-reference))
+                (cite
+                (list 'citation
+                      (list :style style
+                            :begin begin
+                            :post-blank (progn
+                                          (goto-char closing)
+                                          (skip-chars-forward " \t"))
+                            :end (point)))))
+           ;; `:contents-begin' depends on the presence of
+           ;; a non-empty common prefix.
+           (goto-char first-key-end)
+           (if (not (search-backward ";" start t))
+               (org-element-put-property cite :contents-begin start)
+             (when (< start (point))
+               (org-element-put-property
+                 cite :prefix
+                 (org-element--parse-objects start (point) nil types cite)))
+             (forward-char)
+             (org-element-put-property cite :contents-begin (point)))
+           ;; `:contents-end' depends on the presence of a non-empty
+           ;; common suffix.
+           (goto-char (1- closing))
+           (skip-chars-backward " \r\t\n")
+           (let ((end (point)))
+             (if (or (not (search-backward ";" first-key-end t))
+                     (re-search-forward org-element-citation-key-re end t))
+                 (org-element-put-property cite :contents-end end)
+                (forward-char)
+               (when (< (point) end)
+                 (org-element-put-property
+                   cite :suffix
+                   (org-element--parse-objects (point) end nil types cite)))
+               (org-element-put-property cite :contents-end (point))))
+           cite))))))
+
+(defun org-element-citation-interpreter (citation contents)
+  "Interpret CITATION object as Org syntax.
+CONTENTS is the contents of the object, as a string."
+  (let ((prefix (org-element-property :prefix citation))
+        (suffix (org-element-property :suffix citation))
+        (style (org-element-property :style citation)))
+    (concat "[cite"
+            (and style (concat "/" style))
+            ":"
+            (and prefix (concat (org-element-interpret-data prefix) ";"))
+            (if suffix
+                (concat contents (org-element-interpret-data suffix))
+              ;; Remove spurious semicolon.
+              (substring contents nil -1))
+            "]")))
+
+
+;;;; Citation Reference
+
+(defun org-element-citation-reference-parser ()
+  "Parse citation reference object at point, if any.
+
+When at a reference, return a list whose car is
+`citation-reference', and cdr is a plist with `:key',
+`:prefix', `:suffix', `:begin', `:end', and `:post-blank' keywords.
+
+Assume point is at the beginning of the reference."
+  (save-excursion
+    (let ((begin (point)))
+      (when (re-search-forward org-element-citation-key-re nil t)
+        (let* ((key (match-string-no-properties 1))
+              (key-start (match-beginning 0))
+              (key-end (match-end 0))
+              (separator (search-forward ";" nil t))
+               (end (or separator (point-max)))
+               (suffix-end (if separator (1- end) end))
+               (types (org-element-restriction 'citation-reference))
+              (reference
+               (list 'citation-reference
+                     (list :key key
+                           :begin begin
+                           :end end
+                           :post-blank 0))))
+         (when (< begin key-start)
+           (org-element-put-property
+            reference :prefix
+             (org-element--parse-objects begin key-start nil types reference)))
+         (when (< key-end suffix-end)
+           (org-element-put-property
+            reference :suffix
+             (org-element--parse-objects key-end suffix-end nil types 
reference)))
+         reference)))))
+
+(defun org-element-citation-reference-interpreter (citation-reference _)
+  "Interpret CITATION-REFERENCE object as Org syntax."
+  (concat (org-element-interpret-data
+           (org-element-property :prefix citation-reference))
+         "@" (org-element-property :key citation-reference)
+         (org-element-interpret-data
+           (org-element-property :suffix citation-reference))
+          ";"))
+
+
 ;;;; Code
 
 (defun org-element-code-parser ()
@@ -4230,6 +4376,7 @@ looking into captions:
    (lambda (b)
      (and (org-element-map b \\='latex-snippet #\\='identity nil t) b))
    nil nil nil t)"
+  (declare (indent 2))
   ;; Ensure TYPES and NO-RECURSION are a list, even of one element.
   (let* ((types (if (listp types) types (list types)))
         (no-recursion (if (listp no-recursion) no-recursion
@@ -4323,7 +4470,6 @@ looking into captions:
        (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.
 ;;
@@ -4346,7 +4492,7 @@ element or object.  Meaningful values are `first-section',
 TYPE is the type of the current element or object.
 
 If PARENT? is non-nil, assume the next element or object will be
-located inside the current one.  "
+located inside the current one."
   (if parent?
       (pcase type
        (`headline 'section)
@@ -4437,7 +4583,11 @@ Elements are accumulated into ACC."
 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)
+  (cond
+   ((memq 'table-cell restriction) (org-element-table-cell-parser))
+   ((memq 'citation-reference restriction)
+    (org-element-citation-reference-parser))
+   (t
     (let* ((start (point))
           (limit
            ;; Object regexp sometimes needs to have a peek at
@@ -4525,6 +4675,9 @@ to an appropriate container (e.g., a paragraph)."
                         ((and ?f
                               (guard (memq 'footnote-reference restriction)))
                          (org-element-footnote-reference-parser))
+                        ((and ?c
+                              (guard (memq 'citation restriction)))
+                         (org-element-citation-parser))
                         ((and (or ?% ?/)
                               (guard (memq 'statistics-cookie restriction)))
                          (org-element-statistics-cookie-parser))
@@ -4539,8 +4692,8 @@ to an appropriate container (e.g., a paragraph)."
            (or (eobp) (forward-char))))
        (cond (found)
              (limit (forward-char -1)
-                    (org-element-link-parser)) ;radio link
-             (t nil))))))
+                    (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.
@@ -4679,19 +4832,18 @@ to interpret.  Return Org syntax as a string."
   "Return ELEMENT's affiliated keywords as Org syntax.
 If there is no affiliated keyword, return the empty string."
   (let ((keyword-to-org
-        (function
-         (lambda (key value)
-           (let (dual)
-             (when (member key org-element-dual-keywords)
-               (setq dual (cdr value) value (car value)))
-             (concat "#+" (downcase key)
-                     (and dual
-                          (format "[%s]" (org-element-interpret-data dual)))
-                     ": "
-                     (if (member key org-element-parsed-keywords)
-                         (org-element-interpret-data value)
-                       value)
-                     "\n"))))))
+        (lambda (key value)
+          (let (dual)
+            (when (member key org-element-dual-keywords)
+              (setq dual (cdr value) value (car value)))
+            (concat "#+" (downcase key)
+                    (and dual
+                         (format "[%s]" (org-element-interpret-data dual)))
+                    ": "
+                    (if (member key org-element-parsed-keywords)
+                        (org-element-interpret-data value)
+                      value)
+                    "\n")))))
     (mapconcat
      (lambda (prop)
        (let ((value (org-element-property prop element))
diff --git a/lisp/org-entities.el b/lisp/org-entities.el
index eb09899..9c5f626 100644
--- a/lisp/org-entities.el
+++ b/lisp/org-entities.el
@@ -2,7 +2,7 @@
 
 ;; Copyright (C) 2010-2021 Free Software Foundation, Inc.
 
-;; Author: Carsten Dominik <carsten at orgmode dot org>,
+;; Author: Carsten Dominik <carsten.dominik@gmail.com>,
 ;;         Ulf Stegemann <ulf at zeitform dot de>
 ;; Keywords: outlines, calendar, wp
 ;; Homepage: https://orgmode.org
@@ -114,6 +114,8 @@ packages to be loaded, add these packages to 
`org-latex-packages-alist'."
      ("igrave" "\\`{i}" nil "&igrave;" "i" "รฌ" "รฌ")
      ("Iacute" "\\'{I}" nil "&Iacute;" "I" "ร" "ร")
      ("iacute" "\\'{i}" nil "&iacute;" "i" "รญ" "รญ")
+     ("Idot" "\\.{I}" nil "&idot;" "I" "ฤฐ" "ฤฐ")
+     ("inodot" "\\i" nil "&inodot;" "i" "ฤฑ" "ฤฑ")
      ("Icirc" "\\^{I}" nil "&Icirc;" "I" "รŽ" "รŽ")
      ("icirc" "\\^{i}" nil "&icirc;" "i" "รฎ" "รฎ")
      ("Iuml" "\\\"{I}" nil "&Iuml;" "I" "ร" "ร")
diff --git a/lisp/org-faces.el b/lisp/org-faces.el
index c56873b..b151045 100644
--- a/lisp/org-faces.el
+++ b/lisp/org-faces.el
@@ -2,7 +2,7 @@
 
 ;; Copyright (C) 2004-2021 Free Software Foundation, Inc.
 
-;; Author: Carsten Dominik <carsten at orgmode dot org>
+;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: https://orgmode.org
 ;;
@@ -38,13 +38,28 @@
   :group 'org-faces)
 
 (defface org-hide
-  '((((background light)) (:foreground "white"))
+  '((default :inherit fixed-pitch)
+    (((background light)) (:foreground "white"))
     (((background dark)) (:foreground "black")))
   "Face used to hide leading stars in headlines.
 The foreground color of this face should be equal to the background
 color of the frame."
   :group 'org-faces)
 
+(defface org-dispatcher-highlight
+  '((default :weight bold)
+    (((class color) (min-colors 88) (background dark))
+     :background "gray20" :foreground "gold1")
+    (((class color) (min-colors 88) (background light))
+     :background "SlateGray1" :foreground "DarkBlue")
+    (((class color) (min-colors 16) (background dark))
+     :foreground "yellow")
+    (((class color) (min-colors 16) (background light))
+     :foreground "blue")
+    (t :inverse-video t))
+  "Face for highlighted keys in the dispatcher."
+  :group 'org-faces)
+
 (defface org-level-1 '((t :inherit outline-1))
   "Face used for level 1 headlines."
   :group 'org-faces)
@@ -153,6 +168,14 @@ set the properties in the `org-column' face.  For example, 
set
   "Face for headline with the ARCHIVE tag."
   :group 'org-faces)
 
+(defface org-cite '((t :inherit link))
+  "Face for citations."
+  :group 'org-faces)
+
+(defface org-cite-key '((t :inherit link))
+  "Face for citation keys."
+  :group 'org-faces)
+
 (defface org-link '((t :inherit link))
   "Face for links."
   :group 'org-faces)
@@ -179,7 +202,8 @@ set the properties in the `org-column' face.  For example, 
set
   :group 'org-faces)
 
 (defface org-date
-  '((((class color) (background light)) (:foreground "Purple" :underline t))
+  '((default :inherit fixed-pitch)
+    (((class color) (background light)) (:foreground "Purple" :underline t))
     (((class color) (background dark)) (:foreground "Cyan" :underline t))
     (t (:underline t)))
   "Face for date/time stamps."
@@ -355,7 +379,8 @@ changes."
                   (sexp :tag "Face")))))
 
 (defface org-table        ;Copied from `font-lock-function-name-face'
-  '((((class color) (min-colors 88) (background light)) (:foreground "Blue1"))
+  '((default :inherit fixed-pitch)
+    (((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"))
@@ -371,7 +396,8 @@ changes."
   :group 'org-faces)
 
 (defface org-formula
-  '((((class color) (min-colors 88) (background light)) (:foreground 
"Firebrick"))
+  '((default :inherit fixed-pitch)
+    (((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"))
@@ -379,12 +405,12 @@ changes."
   "Face for formulas."
   :group 'org-faces)
 
-(defface org-code '((t :inherit shadow))
+(defface org-code '((t :inherit (fixed-pitch shadow)))
   "Face for fixed-width text like code snippets."
   :group 'org-faces
   :version "22.1")
 
-(defface org-meta-line '((t :inherit font-lock-comment-face))
+(defface org-meta-line '((t :inherit (fixed-pitch font-lock-comment-face)))
   "Face for meta lines starting with \"#+\"."
   :group 'org-faces
   :version "22.1")
@@ -400,15 +426,18 @@ changes."
   '((((class color) (background light)) (:foreground "midnight blue"))
     (((class color) (background dark)) (:foreground "pale turquoise"))
     (t nil))
-  "Face for document date, author and email; i.e. that which
-follows a #+DATE:, #+AUTHOR: or #+EMAIL: keyword."
+  "Face for document information such as the author and date.
+This applies to the text that follows a #+SUBTITLE:, #+DATE:,
+#+AUTHOR: or #+EMAIL: keyword."
   :group 'org-faces)
 
 (defface org-document-info-keyword '((t :inherit shadow))
-  "Face for #+TITLE:, #+AUTHOR:, #+EMAIL: and #+DATE: keywords."
+  "Face for document information keywords.
+This face applies to the #+TITLE:, #+SUBTITLE:, #+AUTHOR:,
+#+EMAIL: and #+DATE: keywords."
   :group 'org-faces)
 
-(defface org-block `((t :inherit shadow
+(defface org-block `((t :inherit (fixed-pitch shadow)
                        ,@(and (>= emacs-major-version 27) '(:extend t))))
   "Face used for text inside various blocks.
 
@@ -430,7 +459,7 @@ verse and quote blocks are fontified using the `org-verse' 
and
   "Face used for the line delimiting the end of source blocks."
   :group 'org-faces)
 
-(defface org-verbatim '((t (:inherit shadow)))
+(defface org-verbatim '((t (:inherit (fixed-pitch shadow))))
   "Face for fixed-with text like code snippets."
   :group 'org-faces
   :version "22.1")
@@ -478,6 +507,16 @@ content of these blocks will still be treated as Org 
syntax."
   "Face used in agenda for captions and dates."
   :group 'org-faces)
 
+(defface org-agenda-structure-secondary '((t (:inherit org-agenda-structure)))
+  "Face used for secondary information in agenda block headers."
+  :group 'org-faces)
+
+(defface org-agenda-structure-filter '((t (:inherit (org-warning 
org-agenda-structure))))
+  "Face used for the current type of task filter in the agenda.
+It inherits from `org-agenda-structure' so it can adapt to
+it (e.g. if that is assigned a diffent font height or family)."
+  :group 'org-faces)
+
 (defface org-agenda-date '((t (:inherit org-agenda-structure)))
   "Face used in agenda for normal days."
   :group 'org-faces)
@@ -487,6 +526,10 @@ content of these blocks will still be treated as Org 
syntax."
   "Face used in agenda for today."
   :group 'org-faces)
 
+(defface org-agenda-date-weekend-today '((t (:inherit org-agenda-date-today)))
+  "Face used in agenda for today during weekends."
+  :group 'org-faces)
+
 (defface org-agenda-clocking '((t (:inherit secondary-selection)))
   "Face marking the current clock item in the agenda."
   :group 'org-faces)
@@ -529,6 +572,11 @@ which days belong to the weekend."
   "Face for items scheduled previously, and not yet done."
   :group 'org-faces)
 
+(defface org-imminent-deadline '((t :inherit org-warning))
+  "Face for current deadlines in the agenda.
+See also `org-agenda-deadline-faces'."
+  :group 'org-faces)
+
 (defface org-upcoming-deadline
   '((((class color) (min-colors 88) (background light)) (:foreground 
"Firebrick"))
     (((class color) (min-colors 88) (background dark)) (:foreground 
"chocolate1"))
@@ -544,7 +592,7 @@ See also `org-agenda-deadline-faces'."
 See also `org-agenda-deadline-faces'.")
 
 (defcustom org-agenda-deadline-faces
-  '((1.0 . org-warning)
+  '((1.0 . org-imminent-deadline)
     (0.5 . org-upcoming-deadline)
     (0.0 . org-upcoming-distant-deadline))
   "Faces for showing deadlines in the agenda.
diff --git a/lisp/org-feed.el b/lisp/org-feed.el
index 5dbd887..5df3b69 100644
--- a/lisp/org-feed.el
+++ b/lisp/org-feed.el
@@ -2,7 +2,7 @@
 ;;
 ;; Copyright (C) 2009-2021 Free Software Foundation, Inc.
 ;;
-;; Author: Carsten Dominik <carsten at orgmode dot org>
+;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: https://orgmode.org
 ;;
diff --git a/lisp/org-footnote.el b/lisp/org-footnote.el
index fdf4b3c..c8c4dae 100644
--- a/lisp/org-footnote.el
+++ b/lisp/org-footnote.el
@@ -2,7 +2,7 @@
 ;;
 ;; Copyright (C) 2009-2021 Free Software Foundation, Inc.
 ;;
-;; Author: Carsten Dominik <carsten at orgmode dot org>
+;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: https://orgmode.org
 ;;
@@ -291,7 +291,8 @@ otherwise."
        ((eq type 'table-cell)
         ;; :contents-begin is not reliable on empty cells, so special
         ;; case it.
-        (<= (point) (org-element-property :contents-end context)))
+        (<= (save-excursion (skip-chars-backward " \t") (point))
+            (org-element-property :contents-end context)))
        ((let ((cbeg (org-element-property :contents-begin context))
              (cend (org-element-property :contents-end context)))
          (and cbeg (>= (point) cbeg) (<= (point) cend))))))))
diff --git a/lisp/org-goto.el b/lisp/org-goto.el
index 163aa58..0a3470f 100644
--- a/lisp/org-goto.el
+++ b/lisp/org-goto.el
@@ -2,7 +2,7 @@
 
 ;; Copyright (C) 2012-2021 Free Software Foundation, Inc.
 
-;; Author: Carsten Dominik <carsten at orgmode dot org>
+;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 ;; Keywords: outlines, hypermedia, calendar, wp
 
 ;; This file is part of GNU Emacs.
@@ -219,9 +219,9 @@ position or nil."
            (error (make-indirect-buffer (current-buffer) "*org-goto*" t))))
         (let (temp-buffer-show-function temp-buffer-show-hook)
           (with-output-to-temp-buffer "*Org Help*"
-          (princ (format help (if org-goto-auto-isearch
-                                  "  Just type for auto-isearch."
-                                "  n/p/f/b/u to navigate, q to quit.")))))
+            (princ (format help (if org-goto-auto-isearch
+                                    "  Just type for auto-isearch."
+                                  "  n/p/f/b/u to navigate, q to quit.")))))
         (org-fit-window-to-buffer (get-buffer-window "*Org Help*"))
         (org-overview)
         (setq buffer-read-only t)
@@ -250,7 +250,7 @@ want.
 
 This command works around this by showing a copy of the current
 buffer in an indirect buffer, in overview mode.  You can dive
-into the tree in that copy, use org-occur and incremental search
+into the tree in that copy, use `org-occur' and incremental search
 to find a location.  When pressing RET or `Q', the command
 returns to the original buffer in which the visibility is still
 unchanged.  After RET it will also jump to the location selected
diff --git a/lisp/org-habit.el b/lisp/org-habit.el
index 231c08b..a355d8e 100644
--- a/lisp/org-habit.el
+++ b/lisp/org-habit.el
@@ -90,7 +90,7 @@ It will be green even if it was done after the deadline."
   :type 'boolean)
 
 (defcustom org-habit-scheduled-past-days nil
-"Value to use instead of `org-scheduled-past-days', for habits only.
+  "Value to use instead of `org-scheduled-past-days', for habits only.
 
 If nil, `org-scheduled-past-days' is used.
 
diff --git a/lisp/org-id.el b/lisp/org-id.el
index b3b98c6..56783d1 100644
--- a/lisp/org-id.el
+++ b/lisp/org-id.el
@@ -2,7 +2,7 @@
 ;;
 ;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
 ;;
-;; Author: Carsten Dominik <carsten at orgmode dot org>
+;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: https://orgmode.org
 ;;
@@ -128,6 +128,15 @@ nil   Never use an ID to make a link, instead link using a 
text search for
   :group 'org-id
   :type 'string)
 
+(defcustom org-id-ts-format "%Y%m%dT%H%M%S.%6N"
+  "Timestamp format for IDs generated using `ts' `org-id-method'.
+The format should be suitable to pass as an argument to `format-time-string'.
+
+Defaults to ISO8601 timestamps without separators and without
+timezone, local time and precision down to 1e-6 seconds."
+  :type 'string
+  :package-version '(Org . "9.5"))
+
 (defcustom org-id-method 'uuid
   "The method that should be used to create new IDs.
 
@@ -144,13 +153,12 @@ uuid       Create random (version 4) UUIDs.  If the 
program defined in
            `org-id-uuid-program' is available it is used to create the ID.
            Otherwise an internal functions is used.
 
-ts         Create ID's based on ISO8601 timestamps (without separators
-           and without timezone, local time).  Precision down to seconds."
+ts         Create ID's based on timestamps as specified in `org-id-ts-format'."
   :group 'org-id
   :type '(choice
          (const :tag "Org's internal method" org)
          (const :tag "external: uuidgen" uuid)
-         (const :tag "ISO8601 timestamp" ts)))
+         (const :tag "Timestamp with format `org-id-ts-format'" ts)))
 
 (defcustom org-id-prefix nil
   "The prefix for IDs.
@@ -196,7 +204,7 @@ This variable is only relevant when `org-id-track-globally' 
is set."
   :type 'file)
 
 (defcustom org-id-locations-file-relative nil
-  "Determines if org-id-locations should be stored as relative links.
+  "Determine if `org-id-locations' should be stored as relative links.
 Non-nil means that links to locations are stored as links
 relative to the location of where `org-id-locations-file' is
 stored.
@@ -297,7 +305,7 @@ If necessary, the ID is created."
          (if (caar org-refile-targets) 'file t))
         (org-refile-target-verify-function nil)
         (spos (org-refile-get-location "Entry"))
-        (pom (and spos (move-marker (make-marker) (nth 3 spos)
+        (pom (and spos (move-marker (make-marker) (or (nth 3 spos) 1)
                                     (get-file-buffer (nth 1 spos))))))
     (prog1 (org-id-get pom 'create)
       (move-marker pom nil))))
@@ -374,17 +382,15 @@ So a typical ID could look like \"Org:4nd91V40HI\"."
        (setq unique (org-id-uuid))))
      ((eq org-id-method 'org)
       (let* ((etime (org-reverse-string (org-id-time-to-b36)))
-            (postfix (if org-id-include-domain
-                         (progn
-                           (require 'message)
-                           (concat "@" (message-make-fqdn))))))
+            (postfix (when org-id-include-domain
+                       (require 'message)
+                       (concat "@" (message-make-fqdn)))))
        (setq unique (concat etime postfix))))
      ((eq org-id-method 'ts)
-      (let ((ts (format-time-string "%Y%m%dT%H%M%S.%6N"))
-           (postfix (if org-id-include-domain
-                        (progn
-                          (require 'message)
-                          (concat "@" (message-make-fqdn))))))
+      (let ((ts (format-time-string org-id-ts-format))
+           (postfix (when org-id-include-domain
+                      (require 'message)
+                      (concat "@" (message-make-fqdn)))))
        (setq unique (concat ts postfix))))
      (t (error "Invalid `org-id-method'")))
     (concat prefix unique)))
@@ -413,15 +419,15 @@ So a typical ID could look like \"Org:4nd91V40HI\"."
            (substring rnd 18 20)
            (substring rnd 20 32))))
 
-(defun org-id-int-to-b36-one-digit (i)
-  "Turn an integer between 0 and 61 into a single character 0..9, A..Z, a..z."
+(defun org-id-int-to-b36-one-digit (integer)
+  "Convert INTEGER between 0 and 61 into a single character 0..9, A..Z, a..z."
   (cond
-   ((< i 10) (+ ?0 i))
-   ((< i 36) (+ ?a i -10))
+   ((< integer 10) (+ ?0 integer))
+   ((< integer 36) (+ ?a integer -10))
    (t (error "Larger that 35"))))
 
 (defun org-id-b36-to-int-one-digit (i)
-  "Turn a character 0..9, A..Z, a..z into a number 0..61.
+  "Convert character 0..9, A..Z, a..z into a number 0..61.
 The input I may be a character, or a single-letter string."
   (and (stringp i) (setq i (string-to-char i)))
   (cond
@@ -429,9 +435,11 @@ The input I may be a character, or a single-letter string."
    ((and (>= i ?a) (<= i ?z)) (+ (- i ?a) 10))
    (t (error "Invalid b36 letter"))))
 
-(defun org-id-int-to-b36 (i &optional length)
-  "Convert an integer to a base-36 number represented as a string."
-  (let ((s ""))
+(defun org-id-int-to-b36 (integer &optional length)
+  "Convert an INTEGER to a base-36 number represented as a string.
+The returned string is padded with leading zeros to LENGTH if necessary."
+  (let ((s "")
+        (i integer))
     (while (> i 0)
       (setq s (concat (char-to-string
                       (org-id-int-to-b36-one-digit (mod i 36))) s)
@@ -441,11 +449,11 @@ The input I may be a character, or a single-letter 
string."
        (setq s (concat (make-string (- length (length s)) ?0) s)))
     s))
 
-(defun org-id-b36-to-int (s)
-  "Convert a base-36 string into the corresponding integer."
+(defun org-id-b36-to-int (string)
+  "Convert a base-36 STRING into the corresponding integer."
   (let ((r 0))
     (mapc (lambda (i) (setq r (+ (* r 36) (org-id-b36-to-int-one-digit i))))
-         s)
+         string)
     r))
 
 (defun org-id-time-to-b36 (&optional time)
@@ -483,7 +491,8 @@ and TIME is a Lisp time value (HI LO USEC)."
 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 also these files."
+When FILES is given, scan also these files.
+If SILENT is non-nil, messages are suppressed."
   (interactive)
   (unless org-id-track-globally
     (error "Please turn on `org-id-track-globally' if you want to track IDs"))
@@ -512,28 +521,31 @@ When FILES is given, scan also these files."
          (seen-ids nil)
          (ndup 0)
          (i 0))
-    (dolist (file files)
-      (when (file-exists-p file)
-        (unless silent
-          (cl-incf i)
-          (message "Finding ID locations (%d/%d files): %s" i nfiles file))
-        (with-current-buffer (find-file-noselect file t)
-          (let ((ids nil)
-                (case-fold-search t))
-            (org-with-point-at 1
-              (while (re-search-forward id-regexp nil t)
-                (when (org-at-property-p)
-                  (push (org-entry-get (point) "ID") ids)))
-              (when ids
-                (push (cons (abbreviate-file-name file) ids)
-                      org-id-locations)
-                (dolist (id ids)
-                  (cond
-                   ((not (member id seen-ids)) (push id seen-ids))
-                   (silent nil)
-                   (t
-                    (message "Duplicate ID %S" id)
-                    (cl-incf ndup))))))))))
+    (with-temp-buffer
+      (delay-mode-hooks
+       (org-mode)
+       (dolist (file files)
+         (when (file-exists-p file)
+            (unless silent
+              (cl-incf i)
+              (message "Finding ID locations (%d/%d files): %s" i nfiles file))
+           (insert-file-contents file nil nil nil 'replace)
+            (let ((ids nil)
+                 (case-fold-search t))
+              (org-with-point-at 1
+               (while (re-search-forward id-regexp nil t)
+                 (when (org-at-property-p)
+                    (push (org-entry-get (point) "ID") ids)))
+               (when ids
+                 (push (cons (abbreviate-file-name file) ids)
+                       org-id-locations)
+                 (dolist (id ids)
+                    (cond
+                     ((not (member id seen-ids)) (push id seen-ids))
+                     (silent nil)
+                     (t
+                      (message "Duplicate ID %S" id)
+                      (cl-incf ndup)))))))))))
     (setq org-id-files (mapcar #'car org-id-locations))
     (org-id-locations-save)
     ;; Now convert to a hash table.
@@ -580,7 +592,7 @@ When FILES is given, scan also these files."
                        (setf (car item) (expand-file-name (car item) loc))))
                    org-id-locations)))
        (error
-        (message "Could not read org-id-values from %s.  Setting it to nil."
+        (message "Could not read `org-id-values' from %s, setting it to nil"
                  org-id-locations-file))))
     (setq org-id-files (mapcar 'car org-id-locations))
     (setq org-id-locations (org-id-alist-to-hash org-id-locations))))
@@ -589,7 +601,7 @@ When FILES is given, scan also these files."
   "Add the ID with location FILE to the database of ID locations."
   ;; Only if global tracking is on, and when the buffer has a file
   (unless file
-    (error "bug: org-id-get expects a file-visiting buffer"))
+    (error "`org-id-get' expects a file-visiting buffer"))
   (let ((afile (abbreviate-file-name file)))
     (when (and org-id-track-globally id)
       (unless org-id-locations (org-id-locations-load))
@@ -601,7 +613,8 @@ When FILES is given, scan also these files."
   (add-hook 'kill-emacs-hook 'org-id-locations-save))
 
 (defun org-id-hash-to-alist (hash)
-  "Turn an org-id hash into an alist, so that it can be written to a file."
+  "Turn an org-id HASH into an alist.
+This is to be able to write it to a file."
   (let (res x)
     (maphash
      (lambda (k v)
@@ -612,7 +625,7 @@ When FILES is given, scan also these files."
     res))
 
 (defun org-id-alist-to-hash (list)
-  "Turn an org-id location list into a hash table."
+  "Turn an org-id location LIST into a hash table."
   (let ((res (make-hash-table
              :test 'equal
              :size (apply '+ (mapcar 'length list))))
@@ -625,7 +638,7 @@ When FILES is given, scan also these files."
     res))
 
 (defun org-id-paste-tracker (txt &optional buffer-or-file)
-  "Update any IDs in TXT and assign BUFFER-OR-FILE to them."
+  "Update any ids in TXT and assign BUFFER-OR-FILE to them."
   (when org-id-track-globally
     (save-match-data
       (setq buffer-or-file (or buffer-or-file (current-buffer)))
@@ -644,7 +657,7 @@ When FILES is given, scan also these files."
 
 ;;;###autoload
 (defun org-id-find-id-file (id)
-  "Query the id database for the file in which this ID is located."
+  "Query the id database for the file in which ID is located."
   (unless org-id-locations (org-id-locations-load))
   (or (and org-id-locations
           (hash-table-p org-id-locations)
@@ -655,20 +668,27 @@ When FILES is given, scan also these files."
 
 (defun org-id-find-id-in-file (id file &optional markerp)
   "Return the position of the entry ID in FILE.
+
 If that files does not exist, or if it does not contain this ID,
 return nil.
+
 The position is returned as a cons cell (file-name . position).  With
 optional argument MARKERP, return the position as a new marker."
-  (let (org-agenda-new-buffers buf pos)
-    (cond
-     ((not file) nil)
-     ((not (file-exists-p file)) nil)
-     (t (with-current-buffer (setq buf (org-get-agenda-file-buffer file))
-         (setq pos (org-find-entry-with-id id))
-         (when pos
-           (if markerp
-               (move-marker (make-marker) pos buf)
-             (cons file pos))))))))
+  (cond
+   ((not file) nil)
+   ((not (file-exists-p file)) nil)
+   (t
+    (let* ((visiting (find-buffer-visiting file))
+          (buffer (or visiting (find-file-noselect file))))
+      (unwind-protect
+         (with-current-buffer buffer
+           (let ((pos (org-find-entry-with-id id)))
+             (cond
+              ((null pos) nil)
+              (markerp (move-marker (make-marker) pos buffer))
+              (t (cons file pos)))))
+       ;; Remove opened buffer in the process.
+       (unless (or visiting markerp) (kill-buffer buffer)))))))
 
 ;; id link type
 
@@ -677,21 +697,27 @@ optional argument MARKERP, return the position as a new 
marker."
 
 ;;;###autoload
 (defun org-id-store-link ()
-  "Store a link to the current entry, using its ID."
+  "Store a link to the current entry, using its ID.
+
+If before first heading store first title-keyword as description
+or filename if no title."
   (interactive)
   (when (and (buffer-file-name (buffer-base-buffer)) (derived-mode-p 
'org-mode))
     (let* ((link (concat "id:" (org-id-get-create)))
           (case-fold-search nil)
           (desc (save-excursion
                   (org-back-to-heading-or-point-min t)
-                  (or (and (org-before-first-heading-p)
-                           (file-name-nondirectory
-                            (buffer-file-name (buffer-base-buffer))))
-                      (and (looking-at org-complex-heading-regexp)
-                           (if (match-end 4)
-                               (match-string 4)
-                             (match-string 0)))
-                      link))))
+                   (cond ((org-before-first-heading-p)
+                          (let ((keywords (org-collect-keywords '("TITLE"))))
+                            (if keywords
+                                (cadr (assoc "TITLE" keywords))
+                              (file-name-nondirectory
+                              (buffer-file-name (buffer-base-buffer))))))
+                        ((looking-at org-complex-heading-regexp)
+                         (if (match-end 4)
+                             (match-string 4)
+                           (match-string 0)))
+                         (t link)))))
       (org-link-store-props :link link :description desc :type "id")
       link)))
 
diff --git a/lisp/org-indent.el b/lisp/org-indent.el
index af2485c..e0cb697 100644
--- a/lisp/org-indent.el
+++ b/lisp/org-indent.el
@@ -2,7 +2,7 @@
 
 ;; Copyright (C) 2009-2021 Free Software Foundation, Inc.
 ;;
-;; Author: Carsten Dominik <carsten at orgmode dot org>
+;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: https://orgmode.org
 ;;
@@ -85,15 +85,13 @@ it may be prettier to customize the `org-indent' face."
   :type 'character)
 
 (defcustom org-indent-mode-turns-off-org-adapt-indentation t
-  "Non-nil means setting the variable `org-indent-mode' will \
-turn off indentation adaptation.
+  "Non-nil means setting `org-indent-mode' will turn off indentation 
adaptation.
 For details see the variable `org-adapt-indentation'."
   :group 'org-indent
   :type 'boolean)
 
 (defcustom org-indent-mode-turns-on-hiding-stars t
-  "Non-nil means setting the variable `org-indent-mode' will \
-turn on `org-hide-leading-stars'."
+  "Non-nil means setting `org-indent-mode' will turn on 
`org-hide-leading-stars'."
   :group 'org-indent
   :type 'boolean)
 
@@ -128,31 +126,32 @@ useful to make it ever so slightly different."
        (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
+  (when (> org-indent-indentation-per-level 0)
+    (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
+               (cond ((<= n 1) "")
+                     ((bound-and-true-p org-inlinetask-show-first-star)
+                      (concat org-indent-inlinetask-first-star
+                              (substring heading-prefix 1)))
+                     (t (org-add-props heading-prefix nil 'face 
'org-indent)))))
+        ;; Text line prefixes.
+        (aset org-indent--text-line-prefixes
              n
-             (org-add-props heading-prefix nil 'face 'org-indent))
-       ;; Inline tasks line prefixes
-       (aset org-indent--inlinetask-line-prefixes
-             n
-             (cond ((<= n 1) "")
-                   ((bound-and-true-p org-inlinetask-show-first-star)
-                    (concat org-indent-inlinetask-first-star
-                            (substring heading-prefix 1)))
-                   (t (org-add-props heading-prefix nil 'face 'org-indent)))))
-      ;; Text line prefixes.
-      (aset org-indent--text-line-prefixes
-           n
-           (org-add-props
-               (concat (make-string (+ n indentation) ?\s)
-                       (and (> n 0)
-                            (char-to-string org-indent-boundary-char)))
-               nil 'face 'org-indent)))))
+             (org-add-props
+                 (concat (make-string (+ n indentation) ?\s)
+                         (and (> n 0)
+                              (char-to-string org-indent-boundary-char)))
+                 nil 'face 'org-indent))))))
 
 (defsubst org-indent-remove-properties (beg end)
   "Remove indentations between BEG and END."
@@ -169,7 +168,7 @@ properties, after each buffer modification, on the modified 
zone.
 The process is synchronous.  Though, initial indentation of
 buffer, which can take a few seconds on large buffers, is done
 during idle time."
-  nil " Ind" nil
+  :lighter " Ind"
   (cond
    (org-indent-mode
     ;; mode was turned on.
diff --git a/lisp/org-inlinetask.el b/lisp/org-inlinetask.el
index d5e01fe..3379a2e 100644
--- a/lisp/org-inlinetask.el
+++ b/lisp/org-inlinetask.el
@@ -2,7 +2,7 @@
 
 ;; Copyright (C) 2009-2021 Free Software Foundation, Inc.
 ;;
-;; Author: Carsten Dominik <carsten at orgmode dot org>
+;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: https://orgmode.org
 
@@ -189,7 +189,7 @@ The number of levels is controlled by 
`org-inlinetask-min-level'."
 
 (defun org-inlinetask-goto-end ()
   "Go to the end of the inline task at point.
-    Return point."
+Return point."
   (save-match-data
     (beginning-of-line)
     (let ((case-fold-search t)
@@ -265,8 +265,8 @@ If the task has an end part, also demote it."
        (replace-match down-task nil t nil 1)
        (org-inlinetask-goto-end)
         (if (and (eobp) (looking-back "END\\s-*" (point-at-bol)))
-              (beginning-of-line)
-            (forward-line -1))
+            (beginning-of-line)
+          (forward-line -1))
        (unless (= (point) beg)
           (looking-at (org-inlinetask-outline-regexp))
          (replace-match down-task nil t nil 1)
diff --git a/lisp/org-keys.el b/lisp/org-keys.el
index 1c1785c..2984a4f 100644
--- a/lisp/org-keys.el
+++ b/lisp/org-keys.el
@@ -31,6 +31,8 @@
 
 (defvar org-outline-regexp)
 
+(require 'oc)
+
 (declare-function org-add-note "org" ())
 (declare-function org-agenda "org" (&optional arg org-keys restriction))
 (declare-function org-agenda-file-to-front "org" (&optional to-end))
@@ -175,7 +177,6 @@
 (declare-function org-show-subtree "org" ())
 (declare-function org-sort "org" (&optional with-case))
 (declare-function org-sparse-tree "org" (&optional arg type))
-(declare-function org-table-blank-field "org" ())
 (declare-function org-table-copy-down "org" (n))
 (declare-function org-table-create-or-convert-from-region "org" (arg))
 (declare-function org-table-create-with-table\.el "org-table" ())
@@ -572,6 +573,7 @@ COMMANDS is a list of alternating OLDDEF NEWDEF command 
names."
 (org-defkey org-mode-map (kbd "C-c ;") #'org-toggle-comment)
 (org-defkey org-mode-map (kbd "C-c C-w") #'org-refile)
 (org-defkey org-mode-map (kbd "C-c M-w") #'org-refile-copy)
+(org-defkey org-mode-map (kbd "C-c C-M-w") #'org-refile-reverse)
 (org-defkey org-mode-map (kbd "C-c /") #'org-sparse-tree) ;minor-mode reserved
 (org-defkey org-mode-map (kbd "C-c \\") #'org-match-sparse-tree) ;minor-mode r.
 (org-defkey org-mode-map (kbd "C-c RET") #'org-ctrl-c-ret)
@@ -610,7 +612,6 @@ COMMANDS is a list of alternating OLDDEF NEWDEF command 
names."
 (org-defkey org-mode-map (kbd "RET") #'org-return)
 (org-defkey org-mode-map (kbd "C-j") #'org-return-and-maybe-indent)
 (org-defkey org-mode-map (kbd "C-c ?") #'org-table-field-info)
-(org-defkey org-mode-map (kbd "C-c SPC") #'org-table-blank-field)
 (org-defkey org-mode-map (kbd "C-c +") #'org-table-sum)
 (org-defkey org-mode-map (kbd "C-c =") #'org-table-eval-formula)
 (org-defkey org-mode-map (kbd "C-c '") #'org-edit-special)
@@ -666,6 +667,7 @@ COMMANDS is a list of alternating OLDDEF NEWDEF command 
names."
 (org-defkey org-mode-map (kbd "C-c C-x !") #'org-reload)
 (org-defkey org-mode-map (kbd "C-c C-x g") #'org-feed-update-all)
 (org-defkey org-mode-map (kbd "C-c C-x G") #'org-feed-goto-inbox)
+(org-defkey org-mode-map (kbd "C-c C-x @") #'org-cite-insert)
 (org-defkey org-mode-map (kbd "C-c C-x [") #'org-reftex-citation)
 (org-defkey org-mode-map (kbd "C-c C-x I") #'org-info-find-node)
 
@@ -688,28 +690,6 @@ star at the beginning of the headline, you can do this:
          (const :tag "At beginning of headline stars" t)
          (function)))
 
-(defcustom org-speed-commands-user nil
-  "Alist of additional speed commands.
-This list will be checked before `org-speed-commands-default'
-when the variable `org-use-speed-commands' is non-nil
-and when the cursor is at the beginning of a headline.
-The car of each entry is a string with a single letter, which must
-be assigned to `self-insert-command' in the global map.
-The cdr is either a command to be called interactively, a function
-to be called, or a form to be evaluated.
-An entry that is just a list with a single string will be interpreted
-as a descriptive headline that will be added when listing the speed
-commands in the Help buffer using the `?' speed command."
-  :group 'org-structure
-  :type '(repeat :value ("k" . ignore)
-                (choice :value ("k" . ignore)
-                        (list :tag "Descriptive Headline" (string :tag 
"Headline"))
-                        (cons :tag "Letter and Command"
-                              (string :tag "Command letter")
-                              (choice
-                               (function)
-                               (sexp))))))
-
 (defcustom org-speed-command-hook
   '(org-speed-command-activate org-babel-speed-command-activate)
   "Hook for activating speed commands at strategic locations.
@@ -729,7 +709,7 @@ hook.  The default setting is `org-speed-command-activate'."
   :version "24.1"
   :type 'hook)
 
-(defconst org-speed-commands-default
+(defcustom org-speed-commands
   '(("Outline Navigation")
     ("n" . (org-speed-move-safe 'org-next-visible-heading))
     ("p" . (org-speed-move-safe 'org-previous-visible-heading))
@@ -739,7 +719,7 @@ hook.  The default setting is `org-speed-command-activate'."
     ("B" . org-previous-block)
     ("u" . (org-speed-move-safe 'outline-up-heading))
     ("j" . org-goto)
-    ("g" . (org-refile t))
+    ("g" . (org-refile '(4)))
     ("Outline Visibility")
     ("c" . org-cycle)
     ("C" . org-shifttab)
@@ -754,8 +734,7 @@ hook.  The default setting is `org-speed-command-activate'."
     ("l" . org-metaleft)
     ("R" . org-shiftmetaright)
     ("L" . org-shiftmetaleft)
-    ("i" . (progn (forward-char 1) (call-interactively
-                                   'org-insert-heading-respect-content)))
+    ("i" . (progn (forward-char 1) (call-interactively 
'org-insert-heading-respect-content)))
     ("^" . org-sort)
     ("w" . org-refile)
     ("a" . org-archive-subtree-default-with-confirmation)
@@ -774,8 +753,7 @@ hook.  The default setting is `org-speed-command-activate'."
     (":" . org-set-tags-command)
     ("e" . org-set-effort)
     ("E" . org-inc-effort)
-    ("W" . (lambda(m) (interactive "sMinutes before warning: ")
-            (org-entry-put (point) "APPT_WARNTIME" m)))
+    ("W" . (lambda (m) (interactive "sMinutes before warning: ") 
(org-entry-put (point) "APPT_WARNTIME" m)))
     ("Agenda Views etc")
     ("v" . org-agenda)
     ("/" . org-sparse-tree)
@@ -784,7 +762,28 @@ hook.  The default setting is 
`org-speed-command-activate'."
     ("?" . org-speed-command-help)
     ("<" . (org-agenda-set-restriction-lock 'subtree))
     (">" . (org-agenda-remove-restriction-lock)))
-  "The default speed commands.")
+  "Alist of speed commands.
+
+The car of each entry is a string with a single letter, which
+must be assigned to `self-insert-command' in the global map.
+
+The cdr is either a command to be called interactively, a
+function to be called, or a form to be evaluated.
+
+An entry that is just a list with a single string will be
+interpreted as a descriptive headline that will be added when
+listing the speed commands in the Help buffer using the `?' speed
+command."
+  :group 'org-structure
+  :package-version '(Org . "9.5")
+  :type '(repeat :value ("k" . ignore)
+                (choice :value ("k" . ignore)
+                        (list :tag "Descriptive Headline" (string :tag 
"Headline"))
+                        (cons :tag "Letter and Command"
+                              (string :tag "Command letter")
+                              (choice
+                               (function)
+                               (sexp))))))
 
 (defun org-print-speed-command (e)
   (if (> (length (car e)) 1)
@@ -806,12 +805,18 @@ hook.  The default setting is 
`org-speed-command-activate'."
   (interactive)
   (unless org-use-speed-commands
     (user-error "Speed commands are not activated, customize 
`org-use-speed-commands'"))
+  ;; FIXME: remove this warning for 9.6
+  (when (boundp 'org-speed-commands-user)
+    (message "`org-speed-command-user' is obsolete, please use 
`org-speed-commands'")
+    (sit-for 3))
   (with-output-to-temp-buffer "*Help*"
-    (princ "User-defined Speed commands\n===========================\n")
-    (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))
+    (princ "Speed commands\n==============\n")
+    (mapc #'org-print-speed-command
+          ;; FIXME: don't check `org-speed-commands-user' past 9.6
+          (if (boundp 'org-speed-commands-user)
+              (append org-speed-commands
+                      org-speed-commands-user)
+            org-speed-commands)))
   (with-current-buffer "*Help*"
     (setq truncate-lines t)))
 
@@ -827,13 +832,16 @@ If not, return to the original position and throw an 
error."
 
 (defun org-speed-command-activate (keys)
   "Hook for activating single-letter speed commands.
-`org-speed-commands-default' specifies a minimal command set.
-Use `org-speed-commands-user' for further customization."
+See `org-speed-commands' for configuring them."
   (when (or (and (bolp) (looking-at org-outline-regexp))
            (and (functionp org-use-speed-commands)
                 (funcall org-use-speed-commands)))
-    (cdr (assoc keys (append org-speed-commands-user
-                            org-speed-commands-default)))))
+    (cdr (assoc keys
+                ;; FIXME: don't check `org-speed-commands-user' past 9.6
+                (if (boundp 'org-speed-commands-user)
+                    (append org-speed-commands
+                            org-speed-commands-user)
+                  org-speed-commands)))))
 
 
 ;;; Babel speed keys
diff --git a/lisp/org-lint.el b/lisp/org-lint.el
index ffeb9b2..5c64c5a 100644
--- a/lisp/org-lint.el
+++ b/lisp/org-lint.el
@@ -593,7 +593,7 @@ in description"
        (let ((file (org-unbracket-string
                        "\"" "\""
                      (org-element-property :value k))))
-         (and (not (org-file-url-p file))
+         (and (not (org-url-p file))
               (not (file-remote-p file))
               (not (file-exists-p file))
               (list (org-element-property :begin k)
@@ -687,15 +687,42 @@ Use \"export %s\" instead"
     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)
+  (let* ((reports nil)
+         (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) #'<))))
+         (check-arity
+          (lambda (arity macro)
+            (let* ((name (org-element-property :key macro))
+                   (pos (org-element-property :begin macro))
+                   (args (org-element-property :args macro))
+                   (l (length args)))
+              (cond
+               ((< l (1- (car arity)))
+                (push (list pos (format "Missing arguments in macro %S" name))
+                      reports))
+               ((< l (car arity))
+                (push (list pos (format "Missing argument in macro %S" name))
+                      reports))
+               ((> l (1+ (cdr arity)))
+                (push (let ((spurious-args (nthcdr (cdr arity) args)))
+                        (list pos
+                              (format "Spurious arguments in macro %S: %s"
+                                      name
+                                      (mapconcat #'org-trim spurious-args ", 
"))))
+                      reports))
+               ((> l (cdr arity))
+                (push (list pos
+                            (format "Spurious argument in macro %S: %s"
+                                    name
+                                    (org-last args)))
+                      reports))
+               (t nil))))))
     ;; Check arguments for macro templates.
     (org-element-map ast 'keyword
       (lambda (k)
@@ -731,25 +758,29 @@ Use \"export %s\" instead"
        (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))))))))))
+            (pcase template
+              (`nil
+               (push (list (org-element-property :begin macro)
+                          (format "Undefined macro %S" name))
+                    reports))
+              ((guard (string= name "keyword"))
+               (funcall check-arity '(1 . 1) macro))
+              ((guard (string= name "modification-time"))
+               (funcall check-arity '(1 . 2) macro))
+              ((guard (string= name "n"))
+               (funcall check-arity '(0 . 2) macro))
+              ((guard (string= name "property"))
+               (funcall check-arity '(1 . 2) macro))
+              ((guard (string= name "time"))
+               (funcall check-arity '(1 . 1) macro))
+              ((pred functionp))        ;ignore (eval ...) templates
+              (_
+               (let* ((arg-numbers (funcall extract-placeholders template))
+                      (arity (if (null arg-numbers)
+                                 '(0 . 0)
+                               (let ((m (apply #'max arg-numbers)))
+                                 (cons m m)))))
+                 (funcall check-arity arity macro))))))))
     reports))
 
 (defun org-lint-undefined-footnote-reference (ast)
@@ -1195,7 +1226,6 @@ CHECKERS is the list of checkers used."
       (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)))
 
@@ -1221,7 +1251,7 @@ CHECKERS is the list of checkers used."
   (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-entries))
     (tabulated-list-print)))
 
 (defun org-lint--ignore-checker ()
@@ -1275,7 +1305,7 @@ ARG can also be a list of checker names, as symbols, to 
run."
                     (throw 'exit c)))))))
           ((pred consp)
            (cl-remove-if-not (lambda (c) (memq (org-lint-checker-name c) arg))
-                              org-lint--checkers))
+                             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)
diff --git a/lisp/org-list.el b/lisp/org-list.el
index 3a31ae3..2bd9dc4 100644
--- a/lisp/org-list.el
+++ b/lisp/org-list.el
@@ -2,7 +2,7 @@
 ;;
 ;; Copyright (C) 2004-2021 Free Software Foundation, Inc.
 ;;
-;; Author: Carsten Dominik <carsten at orgmode dot org>
+;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 ;;        Bastien Guerry <bzg@gnu.org>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: https://orgmode.org
@@ -601,25 +601,23 @@ Assume point is at an item."
           (beg-cell (cons (point) (current-indentation)))
            itm-lst itm-lst-2 end-lst end-lst-2 struct
           (assoc-at-point
-           (function
-            ;; Return association at point.
-            (lambda (ind)
-              (looking-at org-list-full-item-re)
-              (let ((bullet (match-string-no-properties 1)))
-                (list (point)
-                      ind
-                      bullet
-                      (match-string-no-properties 2) ; counter
-                      (match-string-no-properties 3) ; checkbox
-                      ;; Description tag.
-                      (and (string-match-p "[-+*]" bullet)
-                           (match-string-no-properties 4)))))))
+           ;; Return association at point.
+           (lambda (ind)
+             (looking-at org-list-full-item-re)
+             (let ((bullet (match-string-no-properties 1)))
+               (list (point)
+                     ind
+                     bullet
+                     (match-string-no-properties 2) ; counter
+                     (match-string-no-properties 3) ; checkbox
+                     ;; Description tag.
+                     (and (string-match-p "[-+*]" bullet)
+                          (match-string-no-properties 4))))))
           (end-before-blank
-           (function
-            ;; Ensure list ends at the first blank line.
-            (lambda ()
-              (skip-chars-backward " \r\t\n")
-              (min (1+ (point-at-eol)) lim-down)))))
+           ;; Ensure list ends at the first blank line.
+           (lambda ()
+             (skip-chars-backward " \r\t\n")
+             (min (1+ (point-at-eol)) lim-down))))
       ;; 1. Read list from starting item to its beginning, and save
       ;;    top item position and indentation in BEG-CELL.  Also store
       ;;    ending position of items in END-LST.
@@ -1004,23 +1002,22 @@ alist of ancestors, as returned by 
`org-list-parents-alist'.
 Return value is a list of integers.  Counters have an impact on
 that value."
   (let ((get-relative-number
-        (function
-         (lambda (item struct prevs)
-           ;; Return relative sequence number of ITEM in the sub-list
-           ;; it belongs.  STRUCT is the list structure.  PREVS is
-           ;; the alist of previous items.
-           (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)))
-               (cl-incf seq))
-             (if (not counter) (1+ seq)
-               (cond
-                ((string-match "[A-Za-z]" counter)
-                 (+ (- (string-to-char (upcase (match-string 0 counter))) 64)
-                    seq))
-                ((string-match "[0-9]+" counter)
-                 (+ (string-to-number (match-string 0 counter)) seq))
-                (t (1+ seq)))))))))
+        (lambda (item struct prevs)
+          ;; Return relative sequence number of ITEM in the sub-list
+          ;; it belongs.  STRUCT is the list structure.  PREVS is
+          ;; the alist of previous items.
+          (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)))
+              (cl-incf seq))
+            (if (not counter) (1+ seq)
+              (cond
+               ((string-match "[A-Za-z]" counter)
+                (+ (- (string-to-char (upcase (match-string 0 counter))) 64)
+                   seq))
+               ((string-match "[0-9]+" counter)
+                (+ (string-to-number (match-string 0 counter)) seq))
+               (t (1+ seq))))))))
     ;; Cons each parent relative number into return value (OUT).
     (let ((out (list (funcall get-relative-number item struct prevs)))
          (parent item))
@@ -1182,14 +1179,13 @@ some heuristics to guess the result."
           (cdr (assq 'plain-list-item org-blank-before-new-entry)))
          usr-blank
          (count-blanks
-          (function
-           (lambda ()
-             ;; Count blank lines above beginning of line.
-             (save-excursion
-               (count-lines (goto-char (point-at-bol))
-                            (progn (skip-chars-backward " \r\t\n")
-                                   (forward-line)
-                                   (point))))))))
+          (lambda ()
+            ;; Count blank lines above beginning of line.
+            (save-excursion
+              (count-lines (goto-char (point-at-bol))
+                           (progn (skip-chars-backward " \r\t\n")
+                                  (forward-line)
+                                  (point)))))))
       (cond
        ;; Trivial cases where there should be none.
        ((not insert-blank-p) 0)
@@ -1652,65 +1648,64 @@ PREVS is the alist of previous items, as returned by
 This function modifies STRUCT."
   (let ((case-fold-search nil)
        (fix-bul
-        (function
-         ;; Set bullet of ITEM in STRUCT, depending on the type of
-         ;; first item of the list, the previous bullet and counter
-         ;; if any.
-         (lambda (item)
-           (let* ((prev (org-list-get-prev-item item struct prevs))
-                  (prev-bul (and prev (org-list-get-bullet prev struct)))
-                  (counter (org-list-get-counter item struct))
-                  (bullet (org-list-get-bullet item struct))
-                  (alphap (and (not prev)
-                               (org-list-use-alpha-bul-p item struct prevs))))
-             (org-list-set-bullet
-              item struct
-              (org-list-bullet-string
-               (cond
-                ;; Alpha counter in alpha list: use counter.
-                ((and prev counter
-                      (string-match "[a-zA-Z]" counter)
-                      (string-match "[a-zA-Z]" prev-bul))
-                 ;; Use cond to be sure `string-match' is used in
-                 ;; both cases.
-                 (let ((real-count
-                        (cond
-                         ((string-match "[a-z]" prev-bul) (downcase counter))
-                         ((string-match "[A-Z]" prev-bul) (upcase counter)))))
-                   (replace-match real-count nil nil prev-bul)))
-                ;; Num counter in a num list: use counter.
-                ((and prev counter
-                      (string-match "[0-9]+" counter)
-                      (string-match "[0-9]+" prev-bul))
-                 (replace-match counter nil nil prev-bul))
-                ;; No counter: increase, if needed, previous bullet.
-                (prev
-                 (org-list-inc-bullet-maybe (org-list-get-bullet prev struct)))
-                ;; Alpha counter at first item: use counter.
-                ((and counter (org-list-use-alpha-bul-p item struct prevs)
-                      (string-match "[A-Za-z]" counter)
-                      (string-match "[A-Za-z]" bullet))
-                 (let ((real-count
-                        (cond
-                         ((string-match "[a-z]" bullet) (downcase counter))
-                         ((string-match "[A-Z]" bullet) (upcase counter)))))
-                   (replace-match real-count nil nil bullet)))
-                ;; Num counter at first item: use counter.
-                ((and counter
-                      (string-match "[0-9]+" counter)
-                      (string-match "[0-9]+" bullet))
-                 (replace-match counter nil nil bullet))
-                ;; First bullet is alpha uppercase: use "A".
-                ((and alphap (string-match "[A-Z]" bullet))
-                 (replace-match "A" nil nil bullet))
-                ;; First bullet is alpha lowercase: use "a".
-                ((and alphap (string-match "[a-z]" bullet))
-                 (replace-match "a" nil nil bullet))
-                ;; First bullet is num: use "1".
-                ((string-match "\\([0-9]+\\|[A-Za-z]\\)" bullet)
-                 (replace-match "1" nil nil bullet))
-                ;; Not an ordered list: keep bullet.
-                (t bullet)))))))))
+        ;; Set bullet of ITEM in STRUCT, depending on the type of
+        ;; first item of the list, the previous bullet and counter
+        ;; if any.
+        (lambda (item)
+          (let* ((prev (org-list-get-prev-item item struct prevs))
+                 (prev-bul (and prev (org-list-get-bullet prev struct)))
+                 (counter (org-list-get-counter item struct))
+                 (bullet (org-list-get-bullet item struct))
+                 (alphap (and (not prev)
+                              (org-list-use-alpha-bul-p item struct prevs))))
+            (org-list-set-bullet
+             item struct
+             (org-list-bullet-string
+              (cond
+               ;; Alpha counter in alpha list: use counter.
+               ((and prev counter
+                     (string-match "[a-zA-Z]" counter)
+                     (string-match "[a-zA-Z]" prev-bul))
+                ;; Use cond to be sure `string-match' is used in
+                ;; both cases.
+                (let ((real-count
+                       (cond
+                        ((string-match "[a-z]" prev-bul) (downcase counter))
+                        ((string-match "[A-Z]" prev-bul) (upcase counter)))))
+                  (replace-match real-count nil nil prev-bul)))
+               ;; Num counter in a num list: use counter.
+               ((and prev counter
+                     (string-match "[0-9]+" counter)
+                     (string-match "[0-9]+" prev-bul))
+                (replace-match counter nil nil prev-bul))
+               ;; No counter: increase, if needed, previous bullet.
+               (prev
+                (org-list-inc-bullet-maybe (org-list-get-bullet prev struct)))
+               ;; Alpha counter at first item: use counter.
+               ((and counter (org-list-use-alpha-bul-p item struct prevs)
+                     (string-match "[A-Za-z]" counter)
+                     (string-match "[A-Za-z]" bullet))
+                (let ((real-count
+                       (cond
+                        ((string-match "[a-z]" bullet) (downcase counter))
+                        ((string-match "[A-Z]" bullet) (upcase counter)))))
+                  (replace-match real-count nil nil bullet)))
+               ;; Num counter at first item: use counter.
+               ((and counter
+                     (string-match "[0-9]+" counter)
+                     (string-match "[0-9]+" bullet))
+                (replace-match counter nil nil bullet))
+               ;; First bullet is alpha uppercase: use "A".
+               ((and alphap (string-match "[A-Z]" bullet))
+                (replace-match "A" nil nil bullet))
+               ;; First bullet is alpha lowercase: use "a".
+               ((and alphap (string-match "[a-z]" bullet))
+                (replace-match "a" nil nil bullet))
+               ;; First bullet is num: use "1".
+               ((string-match "\\([0-9]+\\|[A-Za-z]\\)" bullet)
+                (replace-match "1" nil nil bullet))
+               ;; Not an ordered list: keep bullet.
+               (t bullet))))))))
     (mapc fix-bul (mapcar #'car struct))))
 
 (defun org-list-struct-fix-ind (struct parents &optional bullet-size)
@@ -1756,21 +1751,20 @@ all others cases, the return value will be nil.
 This function modifies STRUCT."
   (let ((all-items (mapcar #'car struct))
        (set-parent-box
-        (function
-         (lambda (item)
-           (let* ((box-list
-                   (mapcar (lambda (child)
-                             (org-list-get-checkbox child struct))
-                           (org-list-get-children item struct parents))))
-             (org-list-set-checkbox
-              item struct
-              (cond
-               ((and (member "[ ]" box-list) (member "[X]" box-list)) "[-]")
-               ((member "[-]" box-list) "[-]")
-               ((member "[X]" box-list) "[X]")
-               ((member "[ ]" box-list) "[ ]")
-               ;; Parent has no boxed child: leave box as-is.
-               (t (org-list-get-checkbox item struct))))))))
+        (lambda (item)
+          (let* ((box-list
+                  (mapcar (lambda (child)
+                            (org-list-get-checkbox child struct))
+                          (org-list-get-children item struct parents))))
+            (org-list-set-checkbox
+             item struct
+             (cond
+              ((and (member "[ ]" box-list) (member "[X]" box-list)) "[-]")
+              ((member "[-]" box-list) "[-]")
+              ((member "[X]" box-list) "[X]")
+              ((member "[ ]" box-list) "[ ]")
+              ;; Parent has no boxed child: leave box as-is.
+              (t (org-list-get-checkbox item struct)))))))
        parent-list)
     ;; 1. List all parents with a checkbox.
     (mapc
@@ -1841,56 +1835,54 @@ Initial position of cursor is restored after the 
changes."
                             (org-inlinetask-outline-regexp)))
         (item-re (org-item-re))
         (shift-body-ind
-         (function
-          ;; 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)
-            (while (or (> (point) beg)
-                       (and (= (point) beg)
-                            (not (looking-at item-re))))
-              (cond
-               ;; Skip inline tasks.
-               ((and inlinetask-re (looking-at inlinetask-re))
-                (org-inlinetask-goto-beginning))
-               ;; Shift only non-empty lines.
-               ((looking-at-p "^[ \t]*\\S-")
-                (indent-line-to (+ (current-indentation) delta))))
-              (forward-line -1)))))
-         (modify-item
-          (function
-          ;; Replace ITEM first line elements with new elements from
-          ;; STRUCT, if appropriate.
-          (lambda (item)
-            (goto-char item)
-            (let* ((new-ind (org-list-get-ind item struct))
-                   (old-ind (current-indentation))
-                   (new-bul (org-list-bullet-string
-                             (org-list-get-bullet item struct)))
-                   (old-bul (org-list-get-bullet item old-struct))
-                   (new-box (org-list-get-checkbox item struct)))
-              (looking-at org-list-full-item-re)
-              ;; a.  Replace bullet
-              (unless (equal old-bul new-bul)
-                (replace-match new-bul nil nil nil 1))
-              ;; b.  Replace checkbox.
-              (cond
-               ((equal (match-string 3) new-box))
-               ((and (match-string 3) new-box)
-                (replace-match new-box nil nil nil 3))
-               ((match-string 3)
-                (looking-at ".*?\\([ \t]*\\[[ X-]\\]\\)")
-                (replace-match "" nil nil nil 1))
-               (t (let ((counterp (match-end 2)))
-                    (goto-char (if counterp (1+ counterp) (match-end 1)))
-                    (insert (concat new-box (unless counterp " "))))))
-              ;; c.  Indent item to appropriate column.
-              (unless (= new-ind old-ind)
-                (delete-region (goto-char (point-at-bol))
-                               (progn (skip-chars-forward " \t") (point)))
-                (indent-to new-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)
+           (while (or (> (point) beg)
+                      (and (= (point) beg)
+                           (not (looking-at item-re))))
+             (cond
+              ;; Skip inline tasks.
+              ((and inlinetask-re (looking-at inlinetask-re))
+               (org-inlinetask-goto-beginning))
+              ;; Shift only non-empty lines.
+              ((looking-at-p "^[ \t]*\\S-")
+               (indent-line-to (+ (current-indentation) delta))))
+             (forward-line -1))))
+        (modify-item
+         ;; Replace ITEM first line elements with new elements from
+         ;; STRUCT, if appropriate.
+         (lambda (item)
+           (goto-char item)
+           (let* ((new-ind (org-list-get-ind item struct))
+                  (old-ind (current-indentation))
+                  (new-bul (org-list-bullet-string
+                            (org-list-get-bullet item struct)))
+                  (old-bul (org-list-get-bullet item old-struct))
+                  (new-box (org-list-get-checkbox item struct)))
+             (looking-at org-list-full-item-re)
+             ;; a.  Replace bullet
+             (unless (equal old-bul new-bul)
+               (replace-match new-bul nil nil nil 1))
+             ;; b.  Replace checkbox.
+             (cond
+              ((equal (match-string 3) new-box))
+              ((and (match-string 3) new-box)
+               (replace-match new-box nil nil nil 3))
+              ((match-string 3)
+               (looking-at ".*?\\([ \t]*\\[[ X-]\\]\\)")
+               (replace-match "" nil nil nil 1))
+              (t (let ((counterp (match-end 2)))
+                   (goto-char (if counterp (1+ counterp) (match-end 1)))
+                   (insert (concat new-box (unless counterp " "))))))
+             ;; c.  Indent item to appropriate column.
+             (unless (= new-ind old-ind)
+               (delete-region (goto-char (point-at-bol))
+                              (progn (skip-chars-forward " \t") (point)))
+               (indent-to new-ind))))))
     ;; 1. First get list of items and position endings.  We maintain
     ;;    two alists: ITM-SHIFT, determining indentation shift needed
     ;;    at item, and END-LIST, a pseudo-alist where key is ending
@@ -2304,7 +2296,7 @@ is an integer, 0 means `-', 1 means `+' etc.  If WHICH is
 ;;;###autoload
 (define-minor-mode org-list-checkbox-radio-mode
   "When turned on, use list checkboxes as radio buttons."
-  nil " CheckBoxRadio" nil
+  :lighter " CheckBoxRadio"
   (unless (eq major-mode 'org-mode)
     (user-error "Cannot turn this mode outside org-mode buffers")))
 
@@ -3356,7 +3348,7 @@ Valid parameters are:
     (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
+    ;; 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
diff --git a/lisp/org-macro.el b/lisp/org-macro.el
index f914a33..b8d3373 100644
--- a/lisp/org-macro.el
+++ b/lisp/org-macro.el
@@ -30,7 +30,7 @@
 ;; `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
+;; 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'.
 
@@ -61,7 +61,6 @@
 (declare-function org-element-type "org-element" (element))
 (declare-function org-entry-get "org" (pom property &optional inherit 
literal-nil))
 (declare-function org-file-contents "org" (file &optional noerror nocache))
-(declare-function org-file-url-p "org" (file))
 (declare-function org-in-commented-heading-p "org" (&optional no-inheritance))
 (declare-function org-link-search "ol" (s &optional avoid-pos stealth))
 (declare-function org-mode "org" ())
@@ -84,42 +83,67 @@ directly, use instead:
 
 ;;; Functions
 
-(defun org-macro--set-template (name value templates)
+(defun org-macro--makeargs (template)
+  "Compute the formal arglist to use for TEMPLATE."
+  (let ((max 0) (i 0))
+    (while (string-match "\\$\\([0-9]+\\)" template i)
+      (setq i (match-end 0))
+      (setq max (max max (string-to-number (match-string 1 template)))))
+    (let ((args '(&rest _)))
+      (if (< max 1) args ;Avoid `&optional &rest', refused by Emacs-26!
+        (while (> max 0)
+          (push (intern (format "$%d" max)) args)
+          (setq max (1- max)))
+        (cons '&optional args)))))
+
+(defun org-macro--set-templates (templates)
   "Set template for the macro NAME.
 VALUE is the template of the macro.  The new value override the
-previous one, unless VALUE is nil.  TEMPLATES is the list of
-templates.  Return the updated list."
-  (let ((old-definition (assoc name templates)))
-    (cond ((and value old-definition) (setcdr old-definition value))
-         (old-definition)
-         (t (push (cons name (or value "")) templates))))
-  templates)
+previous one, unless VALUE is nil.  Return the updated list."
+  (let ((new-templates nil))
+    (pcase-dolist (`(,name . ,value) templates)
+      (let ((old-definition (assoc name new-templates)))
+        (when (and (stringp value) (string-match-p "\\`(eval\\>" value))
+          ;; Pre-process the evaluation form for faster macro expansion.
+          (let* ((args (org-macro--makeargs value))
+                 (body
+                  (condition-case nil
+                      ;; `value' is of the form "(eval ...)" but we
+                      ;; don't want this to mean to pass the result to
+                      ;; `eval' (which would cause double evaluation),
+                      ;; so we strip the `eval' away with `cadr'.
+                     (cadr (read value))
+                   (error
+                     (user-error "Invalid definition for macro %S" name)))))
+           (setq value (eval (macroexpand-all `(lambda ,args ,body)) t))))
+        (cond ((and value old-definition) (setcdr old-definition value))
+             (old-definition)
+             (t (push (cons name (or value "")) new-templates)))))
+    new-templates))
 
 (defun org-macro--collect-macros ()
   "Collect macro definitions in current buffer and setup files.
 Return an alist containing all macro templates found."
-  (let ((templates nil))
+  (let ((templates
+         `(("author" . ,(org-macro--find-keyword-value "AUTHOR"))
+          ("email" . ,(org-macro--find-keyword-value "EMAIL"))
+          ("title" . ,(org-macro--find-keyword-value "TITLE" t))
+          ("date" . ,(org-macro--find-date)))))
     (pcase (org-collect-keywords '("MACRO"))
       (`(("MACRO" . ,values))
        (dolist (value values)
         (when (string-match "^\\(\\S-+\\)[ \t]*" value)
           (let ((name (match-string 1 value))
                 (definition (substring value (match-end 0))))
-            (setq templates
-                  (org-macro--set-template name definition templates)))))))
-    (let ((macros `(("author" . ,(org-macro--find-keyword-value "AUTHOR"))
-                   ("email" . ,(org-macro--find-keyword-value "EMAIL"))
-                   ("title" . ,(org-macro--find-keyword-value "TITLE" t))
-                   ("date" . ,(org-macro--find-date)))))
-      (pcase-dolist (`(,name . ,value) macros)
-       (setq templates (org-macro--set-template name value templates))))
+             (push (cons name definition) templates))))))
     templates))
 
-(defun org-macro-initialize-templates ()
+(defun org-macro-initialize-templates (&optional default)
   "Collect macro templates defined in current buffer.
 
-Templates are stored in buffer-local variable
-`org-macro-templates'.
+DEFAULT is a list of globally available templates.
+
+Templates are stored in buffer-local variable `org-macro-templates'.
 
 In addition to buffer-defined macros, the function installs the
 following ones: \"n\", \"author\", \"email\", \"keyword\",
@@ -129,8 +153,9 @@ a file, \"input-file\" and \"modification-time\"."
   (org-macro--counter-initialize)      ;for "n" macro
   (setq org-macro-templates
        (nconc
-        ;; Install user-defined macros.
-        (org-macro--collect-macros)
+        ;; Install user-defined macros.  Local macros have higher
+         ;; precedence than global ones.
+         (org-macro--set-templates (append default 
(org-macro--collect-macros)))
         ;; Install file-specific macros.
         (let ((visited-file (buffer-file-name (buffer-base-buffer))))
           (and visited-file
@@ -138,21 +163,23 @@ a file, \"input-file\" and \"modification-time\"."
                (list
                 `("input-file" . ,(file-name-nondirectory visited-file))
                 `("modification-time" .
-                  ,(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
-                            (file-attribute-modification-time
-                             (file-attributes visited-file))))))))
+                  ,(let ((modtime (file-attribute-modification-time
+                                   (file-attributes visited-file))))
+                     (lambda (arg1 &optional arg2 &rest _)
+                       (format-time-string
+                         arg1
+                         (or (and (org-string-nw-p arg2)
+                                  (org-macro--vc-modified-time visited-file))
+                             modtime))))))))
         ;; Install generic macros.
-        (list
-         '("n" . "(eval (org-macro--counter-increment $1 $2))")
-         '("keyword" . "(eval (org-macro--find-keyword-value $1))")
-         '("time" . "(eval (format-time-string $1))")
-         '("property" . "(eval (org-macro--get-property $1 $2))")))))
+        '(("keyword" . (lambda (arg1 &rest _)
+                          (org-macro--find-keyword-value arg1)))
+          ("n" . (lambda (&optional arg1 arg2 &rest _)
+                    (org-macro--counter-increment arg1 arg2)))
+           ("property" . (lambda (arg1 &optional arg2 &rest _)
+                           (org-macro--get-property arg1 arg2)))
+          ("time" . (lambda (arg1 &rest _)
+                       (format-time-string arg1)))))))
 
 (defun org-macro-expand (macro templates)
   "Return expanded MACRO, as a string.
@@ -164,21 +191,17 @@ default value.  Return nil if no template was found."
         ;; Macro names are case-insensitive.
         (cdr (assoc-string (org-element-property :key macro) templates t))))
     (when template
-      (let* ((eval? (string-match-p "\\`(eval\\>" template))
-            (value
-             (replace-regexp-in-string
-              "\\$[0-9]+"
-              (lambda (m)
-                (let ((arg (or (nth (1- (string-to-number (substring m 1)))
-                                    (org-element-property :args macro))
-                               ;; No argument: remove place-holder.
-                               "")))
-                  ;; `eval' implies arguments are strings.
-                  (if eval? (format "%S" arg) arg)))
-              template nil 'literal)))
-        (when eval?
-          (setq value (eval (condition-case nil (read value)
-                             (error (debug))))))
+      (let* ((value
+             (if (functionp template)
+                 (apply template (org-element-property :args macro))
+               (replace-regexp-in-string
+                "\\$[0-9]+"
+                (lambda (m)
+                  (or (nth (1- (string-to-number (substring m 1)))
+                           (org-element-property :args macro))
+                      ;; No argument: remove place-holder.
+                      ""))
+                template nil 'literal))))
         ;; Force return value to be a string.
         (format "%s" (or value ""))))))
 
@@ -380,7 +403,7 @@ value, i.e. do not increment.
 If the string represents an integer, set the counter to this number.
 
 Any other non-empty string resets the counter to 1."
-  (let ((name-trimmed (org-trim name))
+  (let ((name-trimmed (if (stringp name) (org-trim name) ""))
         (action-trimmed (when (org-string-nw-p action)
                           (org-trim action))))
     (puthash name-trimmed
diff --git a/lisp/org-macs.el b/lisp/org-macs.el
index 42935b3..a8fb79e 100644
--- a/lisp/org-macs.el
+++ b/lisp/org-macs.el
@@ -2,7 +2,7 @@
 
 ;; Copyright (C) 2004-2021 Free Software Foundation, Inc.
 
-;; Author: Carsten Dominik <carsten at orgmode dot org>
+;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: https://orgmode.org
 ;;
@@ -39,6 +39,7 @@
 (declare-function org-string-collate-lessp "org-compat" (s1 s2 &optional 
locale ignore-case))
 
 (defvar org-ts-regexp0)
+(defvar ffap-url-regexp)
 
 
 ;;; Macros
@@ -172,7 +173,7 @@ because otherwise all these markers will point to nowhere."
        ,@body)))
 
 (defmacro org-eval-in-environment (environment form)
-  (declare (debug (form form)) (indent 1))
+  (declare (debug (form form)) (indent 1) (obsolete cl-progv "2021"))
   `(eval (list 'let ,environment ',form)))
 
 ;;;###autoload
@@ -366,15 +367,17 @@ error when the user input is empty."
          (allow-empty? nil)
          (t (user-error "Empty input is not valid")))))
 
+(declare-function org-time-stamp-inactive "org" (&optional arg))
+
 (defun org-completing-read (&rest args)
   "Completing-read with SPACE being a normal character."
   (let ((enable-recursive-minibuffers t)
        (minibuffer-local-completion-map
         (copy-keymap minibuffer-local-completion-map)))
-    (define-key minibuffer-local-completion-map " " 'self-insert-command)
-    (define-key minibuffer-local-completion-map "?" 'self-insert-command)
+    (define-key minibuffer-local-completion-map " " #'self-insert-command)
+    (define-key minibuffer-local-completion-map "?" #'self-insert-command)
     (define-key minibuffer-local-completion-map (kbd "C-c !")
-      'org-time-stamp-inactive)
+      #'org-time-stamp-inactive)
     (apply #'completing-read args)))
 
 (defun org--mks-read-key (allowed-keys prompt navigation-keys)
@@ -470,8 +473,8 @@ is selected, only the bare key is returned."
                (goto-char (point-min))
                (org-fit-window-to-buffer)
                (message "") ; With this line the prompt appears in
-                            ; the minibuffer. Else keystrokes may
-                            ; appear, which is spurious.
+                                        ; the minibuffer. Else keystrokes may
+                                        ; appear, which is spurious.
                (let ((pressed (org--mks-read-key
                                allowed-keys prompt
                                (not (pos-visible-in-window-p (1- 
(point-max)))))))
@@ -535,6 +538,11 @@ that may remove elements by altering the list structure."
     (setq list (delete (pop elts) list)))
   list)
 
+(defun org-plist-delete-all (plist props)
+  "Delete all elements in PROPS from PLIST."
+  (dolist (e props plist)
+    (setq plist (org-plist-delete plist e))))
+
 (defun org-plist-delete (plist property)
   "Delete PROPERTY from PLIST.
 This is in contrast to merely setting it to 0."
@@ -627,18 +635,34 @@ program is needed for, so that the error message can be 
more informative."
   (let ((message-log-max nil))
     (apply #'message args)))
 
-(defun org-let (list &rest body)
-  (eval (cons 'let (cons list body))))
-(put 'org-let 'lisp-indent-function 1)
-
-(defun org-let2 (list1 list2 &rest body)
-  (eval (cons 'let (cons list1 (list (cons 'let (cons list2 body)))))))
-(put 'org-let2 'lisp-indent-function 2)
+(defmacro org-dlet (binders &rest body)
+  "Like `let*' but using dynamic scoping."
+  (declare (indent 1) (debug let))
+  (let ((vars (mapcar (lambda (binder)
+                        (if (consp binder) (car binder) binder))
+                      binders)))
+    `(progn
+       (with-no-warnings
+         ,@(mapcar (lambda (var) `(defvar ,var)) vars))
+       (let* ,binders ,@body))))
+
+(defmacro org-pushnew-to-end (val var)
+  "Like `cl-pushnew' but pushes to the end of the list.
+Uses `equal' for comparisons.
+
+Beware: this performs O(N) memory allocations, so if you use it in a loop, you
+get an unnecessary O(Nยฒ) space complexity, so you're usually better off using
+`cl-pushnew' (with a final `reverse' if you care about the order of elements)."
+  (declare (debug (form gv-place)))
+  (let ((v (make-symbol "v")))
+    `(let ((,v ,val))
+       (unless (member ,v ,var)
+         (setf ,var (append ,var (list ,v)))))))
 
 (defun org-eval (form)
   "Eval FORM and return result."
   (condition-case error
-      (eval form)
+      (eval form t)
     (error (format "%%![Error: %s]" error))))
 
 (defvar org-outline-regexp) ; defined in org.el
@@ -789,6 +813,10 @@ return nil."
           (list context (match-beginning group) (match-end group))
         t)))
 
+(defun org-url-p (s)
+  "Non-nil if string S is a URL."
+  (require 'ffap)
+  (and ffap-url-regexp (string-match-p ffap-url-regexp s)))
 
 
 ;;; String manipulation
@@ -877,7 +905,8 @@ delimiting S."
                    (let ((width (plist-get props :width)))
                      (and (wholenump width) width)))
                   (`(image . ,_)
-                   (ceiling (car (image-size spec))))
+                    (and (fboundp 'image-size)
+                         (ceiling (car (image-size spec)))))
                   ((pred stringp)
                    ;; Displayed string could contain invisible parts,
                    ;; but no nested display.
@@ -982,7 +1011,7 @@ IF WIDTH is nil and LINES is non-nil, the string is forced 
into at most that
 many lines, whatever width that takes.
 The return value is a list of lines, without newlines at the end."
   (let* ((words (split-string string))
-        (maxword (apply 'max (mapcar 'org-string-width words)))
+        (maxword (apply #'max (mapcar #'org-string-width words)))
         w ll)
     (cond (width
           (org--do-wrap words (max maxword width)))
@@ -1079,10 +1108,11 @@ that will be added to PLIST.  Returns the string that 
was modified."
   string)
 
 (defun org-make-parameter-alist (flat)
+  ;; FIXME: "flat" is called a "plist"!
   "Return alist based on FLAT.
 FLAT is a list with alternating symbol names and values.  The
 returned alist is a list of lists with the symbol name in car and
-the value in cdr."
+the value in cadr."
   (when flat
     (cons (list (car flat) (cadr flat))
          (org-make-parameter-alist (cddr flat)))))
@@ -1129,13 +1159,13 @@ move it back by one char before doing this check."
     (org-invisible-p)))
 
 (defun org-find-visible ()
-  "Return closest visible buffer position, or `point-max'"
+  "Return closest visible buffer position, or `point-max'."
   (if (org-invisible-p)
       (next-single-char-property-change (point) 'invisible)
     (point)))
 
 (defun org-find-invisible ()
-  "Return closest invisible buffer position, or `point-max'"
+  "Return closest invisible buffer position, or `point-max'."
   (if (org-invisible-p)
       (point)
     (next-single-char-property-change (point) 'invisible)))
@@ -1242,31 +1272,29 @@ Return 0. if S is not recognized as a valid value."
 When ADDITIONAL-KEYS is not nil, also include SPC and DEL in the
 allowed keys for scrolling, as expected in the export dispatch
 window."
-  (let ((scrlup (if additional-keys '(?\s 22) 22))
-       (scrldn (if additional-keys `(?\d 134217846) 134217846)))
-    (eval
-     `(cl-case ,key
-       ;; C-n
-       (14 (if (not (pos-visible-in-window-p (point-max)))
-               (ignore-errors (scroll-up 1))
-             (message "End of buffer")
-             (sit-for 1)))
-       ;; C-p
-       (16 (if (not (pos-visible-in-window-p (point-min)))
-               (ignore-errors (scroll-down 1))
-             (message "Beginning of buffer")
-             (sit-for 1)))
-       ;; SPC or
-       (,scrlup
-        (if (not (pos-visible-in-window-p (point-max)))
-            (scroll-up nil)
-          (message "End of buffer")
-          (sit-for 1)))
-       ;; DEL
-       (,scrldn (if (not (pos-visible-in-window-p (point-min)))
-                    (scroll-down nil)
-                  (message "Beginning of buffer")
-                  (sit-for 1)))))))
+  (let ((scrlup (if additional-keys '(?\s ?\C-v) ?\C-v))
+       (scrldn (if additional-keys `(?\d ?\M-v) ?\M-v)))
+    (pcase key
+      (?\C-n (if (not (pos-visible-in-window-p (point-max)))
+                (ignore-errors (scroll-up 1))
+              (message "End of buffer")
+              (sit-for 1)))
+      (?\C-p (if (not (pos-visible-in-window-p (point-min)))
+                (ignore-errors (scroll-down 1))
+              (message "Beginning of buffer")
+              (sit-for 1)))
+      ;; SPC or
+      ((guard (memq key scrlup))
+       (if (not (pos-visible-in-window-p (point-max)))
+          (scroll-up nil)
+        (message "End of buffer")
+        (sit-for 1)))
+      ;; DEL
+      ((guard (memq key scrldn))
+       (if (not (pos-visible-in-window-p (point-min)))
+          (scroll-down nil)
+        (message "Beginning of buffer")
+        (sit-for 1))))))
 
 (provide 'org-macs)
 
diff --git a/lisp/org-mobile.el b/lisp/org-mobile.el
index a64e0a2..e51258a 100644
--- a/lisp/org-mobile.el
+++ b/lisp/org-mobile.el
@@ -1,7 +1,7 @@
 ;;; org-mobile.el --- Code for Asymmetric Sync With a Mobile Device -*- 
lexical-binding: t; -*-
 ;; Copyright (C) 2009-2021 Free Software Foundation, Inc.
 ;;
-;; Author: Carsten Dominik <carsten at orgmode dot org>
+;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: https://orgmode.org
 ;;
diff --git a/lisp/org-mouse.el b/lisp/org-mouse.el
index d3ad73b..a35a19b 100644
--- a/lisp/org-mouse.el
+++ b/lisp/org-mouse.el
@@ -3,7 +3,7 @@
 ;; Copyright (C) 2006-2021 Free Software Foundation, Inc.
 
 ;; Author: Piotr Zielinski <piotr dot zielinski at gmail dot com>
-;; Maintainer: Carsten Dominik <carsten at orgmode dot org>
+;; Maintainer: Carsten Dominik <carsten.dominik@gmail.com>
 
 ;; This file is part of GNU Emacs.
 
@@ -161,20 +161,18 @@ it is intended to operate on.  If nil, then the action 
has been invoked
 indirectly, for example, through the agenda buffer.")
 
 (defgroup org-mouse nil
-  "Mouse support for org-mode."
+  "Mouse support for `org-mode'."
   :tag "Org Mouse"
   :group 'org)
 
 (defcustom org-mouse-punctuation ":"
   "Punctuation used when inserting text by drag and drop."
-  :group 'org-mouse
   :type 'string)
 
 (defcustom org-mouse-features
   '(context-menu yank-link activate-stars activate-bullets activate-checkboxes)
   "The features of org-mouse that should be activated.
 Changing this variable requires a restart of Emacs to get activated."
-  :group 'org-mouse
   :type '(set :greedy t
              (const :tag "Mouse-3 shows context menu" context-menu)
              (const :tag "C-mouse-1 and mouse-3 move trees" move-tree)
@@ -222,7 +220,7 @@ this function is called.  Otherwise, the current major mode 
menu is used."
          (if (fboundp 'mouse-menu-major-mode-map)
              (popup-menu (mouse-menu-major-mode-map) event prefix)
            (with-no-warnings ; don't warn about fallback, obsolete since 23.1
-            (mouse-major-mode-menu event prefix)))))
+             (mouse-major-mode-menu event prefix)))))
     (setq this-command 'mouse-save-then-kill)
     (mouse-save-then-kill event)))
 
@@ -292,19 +290,19 @@ argument.  If it is a string, it is interpreted as the 
format
 string to (format ITEMFORMAT keyword).  If it is neither a string
 nor a function, elements of KEYWORDS are used directly."
   (mapcar
-   `(lambda (keyword)
-      (vector (cond
-              ((functionp ,itemformat) (funcall ,itemformat keyword))
-              ((stringp ,itemformat) (format ,itemformat keyword))
-              (t keyword))
-             (list 'funcall ,function keyword)
-             :style (cond
-                     ((null ,selected) t)
-                     ((functionp ,selected) 'toggle)
-                     (t 'radio))
-             :selected (if (functionp ,selected)
-                           (and (funcall ,selected keyword) t)
-                         (equal ,selected keyword))))
+   (lambda (keyword)
+     (vector (cond
+             ((functionp itemformat) (funcall itemformat keyword))
+             ((stringp itemformat) (format itemformat keyword))
+             (t keyword))
+            (list 'funcall function keyword)
+            :style (cond
+                    ((null selected) t)
+                    ((functionp selected) 'toggle)
+                    (t 'radio))
+            :selected (if (functionp selected)
+                          (and (funcall selected keyword) t)
+                        (equal selected keyword))))
    keywords))
 
 (defun org-mouse-remove-match-and-spaces ()
@@ -344,12 +342,12 @@ string to (format ITEMFORMAT keyword).  If it is neither 
a string
 nor a function, elements of KEYWORDS are used directly."
   (setq group (or group 0))
   (let ((replace (org-mouse-match-closure
-                 (if nosurround 'replace-match
-                   'org-mouse-replace-match-and-surround))))
+                 (if nosurround #'replace-match
+                   #'org-mouse-replace-match-and-surround))))
     (append
      (org-mouse-keyword-menu
       keywords
-      `(lambda (keyword) (funcall ,replace keyword t t nil ,group))
+      (lambda (keyword) (funcall replace keyword t t nil group))
       (match-string group)
       itemformat)
      `(["None" org-mouse-remove-match-and-spaces
@@ -416,7 +414,7 @@ SCHEDULED: or DEADLINE: or ANYTHINGLIKETHIS:"
    (let ((kwds org-todo-keywords-1))
      (org-mouse-keyword-menu
       kwds
-      `(lambda (kwd) (org-todo kwd))
+      #'org-todo
       (lambda (kwd) (equal state kwd))))))
 
 (defun org-mouse-tag-menu ()           ;todo
@@ -424,14 +422,14 @@ SCHEDULED: or DEADLINE: or ANYTHINGLIKETHIS:"
   (append
    (let ((tags (org-get-tags nil t)))
      (org-mouse-keyword-menu
-      (sort (mapcar 'car (org-get-buffer-tags)) 'string-lessp)
-      `(lambda (tag)
-        (org-mouse-set-tags
-         (sort (if (member tag (quote ,tags))
-                   (delete tag (quote ,tags))
-                 (cons tag (quote ,tags)))
-               'string-lessp)))
-      `(lambda (tag) (member tag (quote ,tags)))
+      (sort (mapcar #'car (org-get-buffer-tags)) #'string-lessp)
+      (lambda (tag)
+       (org-mouse-set-tags
+        (sort (if (member tag tags)
+                  (delete tag tags)
+                (cons tag tags))
+              #'string-lessp)))
+      (lambda (tag) (member tag tags))
       ))
    '("--"
      ["Align Tags Here" (org-align-tags) t]
@@ -500,8 +498,8 @@ SCHEDULED: or DEADLINE: or ANYTHINGLIKETHIS:"
      ["Check TODOs" org-show-todo-tree t]
      ("Check Tags"
       ,@(org-mouse-keyword-menu
-        (sort (mapcar 'car (org-get-buffer-tags)) 'string-lessp)
-        #'(lambda (tag) (org-tags-sparse-tree nil tag)))
+        (sort (mapcar #'car (org-get-buffer-tags)) #'string-lessp)
+         (lambda (tag) (org-tags-sparse-tree nil tag)))
       "--"
       ["Custom Tag ..." org-tags-sparse-tree t])
      ["Check Phrase ..." org-occur]
@@ -510,27 +508,27 @@ SCHEDULED: or DEADLINE: or ANYTHINGLIKETHIS:"
      ["Display TODO List" org-todo-list t]
      ("Display Tags"
       ,@(org-mouse-keyword-menu
-        (sort (mapcar 'car (org-get-buffer-tags)) 'string-lessp)
-        #'(lambda (tag) (org-tags-view nil tag)))
+        (sort (mapcar #'car (org-get-buffer-tags)) #'string-lessp)
+         (lambda (tag) (org-tags-view nil tag)))
       "--"
       ["Custom Tag ..." org-tags-view t])
      ["Display Calendar" org-goto-calendar t]
      "--"
      ,@(org-mouse-keyword-menu
-       (mapcar 'car org-agenda-custom-commands)
-       #'(lambda (key)
-           (eval `(org-agenda nil (string-to-char ,key))))
+       (mapcar #'car org-agenda-custom-commands)
+        (lambda (key)
+         (org-agenda nil (string-to-char key)))
        nil
-       #'(lambda (key)
-           (let ((entry (assoc key org-agenda-custom-commands)))
-             (org-mouse-clip-text
-              (cond
-               ((stringp (nth 1 entry)) (nth 1 entry))
-               ((stringp (nth 2 entry))
-                (concat (org-mouse-agenda-type (nth 1 entry))
-                        (nth 2 entry)))
-               (t "Agenda Command `%s'"))
-              30))))
+        (lambda (key)
+          (let ((entry (assoc key org-agenda-custom-commands)))
+            (org-mouse-clip-text
+             (cond
+              ((stringp (nth 1 entry)) (nth 1 entry))
+              ((stringp (nth 2 entry))
+               (concat (org-mouse-agenda-type (nth 1 entry))
+                       (nth 2 entry)))
+              (t "Agenda Command `%s'"))
+             30))))
      "--"
      ["Delete Blank Lines" delete-blank-lines
       :visible (org-mouse-empty-line)]
@@ -594,10 +592,10 @@ This means, between the beginning of line and the point."
 
 (defun org-mouse-match-closure (function)
   (let ((match (match-data t)))
-    `(lambda (&rest rest)
-       (save-match-data
-        (set-match-data ',match)
-        (apply ',function rest)))))
+    (lambda (&rest rest)
+      (save-match-data
+       (set-match-data match)
+       (apply function rest)))))
 
 (defun org-mouse-yank-link (click)
   (interactive "e")
@@ -631,7 +629,7 @@ This means, between the beginning of line and the point."
      ((save-excursion (beginning-of-line) (looking-at "[ \t]*#\\+STARTUP: 
\\(.*\\)"))
       (popup-menu
        `(nil
-        ,@(org-mouse-list-options-menu (mapcar 'car org-startup-options)
+        ,@(org-mouse-list-options-menu (mapcar #'car org-startup-options)
                                        'org-mode-restart))))
      ((or (eolp)
          (and (looking-at "\\(  \\|\t\\)\\(\\+:[0-9a-zA-Z_:]+\\)?\\(  
\\|\t\\)+$")
@@ -795,8 +793,8 @@ This means, between the beginning of line and the point."
           ("Tags and Priorities"
            ,@(org-mouse-keyword-menu
               (org-mouse-priority-list)
-              #'(lambda (keyword)
-                  (org-mouse-set-priority (string-to-char keyword)))
+               (lambda (keyword)
+                 (org-mouse-set-priority (string-to-char keyword)))
               priority "Priority %s")
            "--"
            ,@(org-mouse-tag-menu))
@@ -856,55 +854,55 @@ This means, between the beginning of line and the point."
     (mouse-drag-region event)))
 
 (add-hook 'org-mode-hook
-         #'(lambda ()
-             (setq org-mouse-context-menu-function 'org-mouse-context-menu)
-
-             (when (memq 'context-menu org-mouse-features)
-               (org-defkey org-mouse-map [mouse-3] nil)
-               (org-defkey org-mode-map [mouse-3] 
'org-mouse-show-context-menu))
-             (org-defkey org-mode-map [down-mouse-1] 'org-mouse-down-mouse)
-             (when (memq 'context-menu org-mouse-features)
-               (org-defkey org-mouse-map [C-drag-mouse-1] 'org-mouse-move-tree)
-               (org-defkey org-mouse-map [C-down-mouse-1] 
'org-mouse-move-tree-start))
-             (when (memq 'yank-link org-mouse-features)
-               (org-defkey org-mode-map [S-mouse-2] 'org-mouse-yank-link)
-               (org-defkey org-mode-map [drag-mouse-3] 'org-mouse-yank-link))
-             (when (memq 'move-tree org-mouse-features)
-               (org-defkey org-mouse-map [drag-mouse-3] 'org-mouse-move-tree)
-               (org-defkey org-mouse-map [down-mouse-3] 
'org-mouse-move-tree-start))
-
-             (when (memq 'activate-stars org-mouse-features)
-               (font-lock-add-keywords
-                nil
-                `((,org-outline-regexp
-                   0 `(face org-link mouse-face highlight keymap 
,org-mouse-map)
-                   'prepend))
-                t))
-
-             (when (memq 'activate-bullets org-mouse-features)
-               (font-lock-add-keywords
-                nil
-                `(("^[ \t]*\\([-+*]\\|[0-9]+[.)]\\) +"
-                   (1 `(face org-link keymap ,org-mouse-map mouse-face 
highlight)
-                      'prepend)))
-                t))
-
-             (when (memq 'activate-checkboxes org-mouse-features)
-               (font-lock-add-keywords
-                nil
-                `(("^[ \t]*\\([-+*]\\|[0-9]+[.)]\\) +\\(\\[[ X]\\]\\)"
-                   (2 `(face org-checkbox keymap ,org-mouse-map mouse-face 
highlight) t)))
-                t))
-
-             (defadvice org-open-at-point (around org-mouse-open-at-point 
activate)
-               (let ((context (org-context)))
-                 (cond
-                  ((assq :headline-stars context) (org-cycle))
-                  ((assq :checkbox context) (org-toggle-checkbox))
-                  ((assq :item-bullet context)
-                   (let ((org-cycle-include-plain-lists t)) (org-cycle)))
-                  ((org-footnote-at-reference-p) nil)
-                  (t ad-do-it))))))
+          (lambda ()
+            (setq org-mouse-context-menu-function #'org-mouse-context-menu)
+
+            (when (memq 'context-menu org-mouse-features)
+              (org-defkey org-mouse-map [mouse-3] nil)
+              (org-defkey org-mode-map [mouse-3] 
#'org-mouse-show-context-menu))
+            (org-defkey org-mode-map [down-mouse-1] #'org-mouse-down-mouse)
+            (when (memq 'context-menu org-mouse-features)
+              (org-defkey org-mouse-map [C-drag-mouse-1] #'org-mouse-move-tree)
+              (org-defkey org-mouse-map [C-down-mouse-1] 
#'org-mouse-move-tree-start))
+            (when (memq 'yank-link org-mouse-features)
+              (org-defkey org-mode-map [S-mouse-2] #'org-mouse-yank-link)
+              (org-defkey org-mode-map [drag-mouse-3] #'org-mouse-yank-link))
+            (when (memq 'move-tree org-mouse-features)
+              (org-defkey org-mouse-map [drag-mouse-3] #'org-mouse-move-tree)
+              (org-defkey org-mouse-map [down-mouse-3] 
#'org-mouse-move-tree-start))
+
+            (when (memq 'activate-stars org-mouse-features)
+              (font-lock-add-keywords
+               nil
+               `((,org-outline-regexp
+                  0 `(face org-link mouse-face highlight keymap ,org-mouse-map)
+                  'prepend))
+               t))
+
+            (when (memq 'activate-bullets org-mouse-features)
+              (font-lock-add-keywords
+               nil
+               `(("^[ \t]*\\([-+*]\\|[0-9]+[.)]\\) +"
+                  (1 `(face org-link keymap ,org-mouse-map mouse-face 
highlight)
+                     'prepend)))
+               t))
+
+            (when (memq 'activate-checkboxes org-mouse-features)
+              (font-lock-add-keywords
+               nil
+               `(("^[ \t]*\\(?:[-+*]\\|[0-9]+[.)]\\)[ 
\t]+\\(?:\\[@\\(?:start:\\)?[0-9]+\\][ \t]*\\)?\\(\\[[- X]\\]\\)"
+                  (1 `(face nil keymap ,org-mouse-map mouse-face highlight) 
prepend)))
+               t))
+
+            (defadvice org-open-at-point (around org-mouse-open-at-point 
activate)
+              (let ((context (org-context)))
+                (cond
+                 ((assq :headline-stars context) (org-cycle))
+                 ((assq :checkbox context) (org-toggle-checkbox))
+                 ((assq :item-bullet context)
+                  (let ((org-cycle-include-plain-lists t)) (org-cycle)))
+                 ((org-footnote-at-reference-p) nil)
+                 (t ad-do-it))))))
 
 (defun org-mouse-move-tree-start (_event)
   (interactive "e")
@@ -1086,11 +1084,11 @@ This means, between the beginning of line and the 
point."
 (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)
+           (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)
diff --git a/lisp/org-num.el b/lisp/org-num.el
index ebddaa3..408b86f 100644
--- a/lisp/org-num.el
+++ b/lisp/org-num.el
@@ -29,8 +29,8 @@
 ;; to toggle it.
 ;;
 ;; You can select what is numbered according to level, tags, COMMENT
-;; keyword, or UNNUMBERED property. You can also skip footnotes
-;; sections. See `org-num-max-level', `org-num-skip-tags',
+;; keyword, or UNNUMBERED property.  You can also skip footnotes
+;; sections.  See `org-num-max-level', `org-num-skip-tags',
 ;; `org-num-skip-commented', `org-num-skip-unnumbered', and
 ;; `org-num-skip-footnotes' for details.
 ;;
@@ -63,6 +63,7 @@
 
 (require 'cl-lib)
 (require 'org-macs)
+(require 'org) ;Otherwise `org-num--comment-re' burps on `org-comment-string'
 
 (defvar org-comment-string)
 (defvar org-complex-heading-regexp)
@@ -90,7 +91,7 @@ output."
                  (face :tag "Use face"))
   :safe (lambda (val) (or (null val) (facep val))))
 
-(defcustom org-num-format-function 'org-num-default-format
+(defcustom org-num-format-function #'org-num-default-format
   "Function used to display numbering.
 It is called with one argument, a list of numbers, and should
 return a string, or nil.  When nil, no numbering is displayed.
diff --git a/lisp/org-pcomplete.el b/lisp/org-pcomplete.el
index 29d9d58..b31dc33 100644
--- a/lisp/org-pcomplete.el
+++ b/lisp/org-pcomplete.el
@@ -2,7 +2,7 @@
 
 ;; Copyright (C) 2004-2021 Free Software Foundation, Inc.
 ;;
-;; Author: Carsten Dominik <carsten at orgmode dot org>
+;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 ;;         John Wiegley <johnw at gnu dot org>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: https://orgmode.org
@@ -21,8 +21,7 @@
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
+
 ;;; Code:
 
 ;;;; Require other packages
@@ -186,7 +185,7 @@ When completing for #+STARTUP, for example, this function 
returns
        (cons (reverse args) (reverse begins))))))
 
 (defun org-pcomplete-initial ()
-  "Calls the right completion function for first argument completions."
+  "Call the right completion function for first argument completions."
   (ignore
    (funcall (or (pcomplete-find-completion-function
                 (car (org-thing-at-point)))
@@ -239,11 +238,11 @@ When completing for #+STARTUP, for example, this function 
returns
   (require 'ox)
   (pcomplete-here
    (and org-export-exclude-tags
-       (list (mapconcat 'identity org-export-exclude-tags " ")))))
+       (list (mapconcat #'identity org-export-exclude-tags " ")))))
 
 (defun pcomplete/org-mode/file-option/filetags ()
   "Complete arguments for the #+FILETAGS file option."
-  (pcomplete-here (and org-file-tags (mapconcat 'identity org-file-tags " "))))
+  (pcomplete-here (and org-file-tags (mapconcat #'identity org-file-tags " 
"))))
 
 (defun pcomplete/org-mode/file-option/language ()
   "Complete arguments for the #+LANGUAGE file option."
@@ -264,13 +263,13 @@ When completing for #+STARTUP, for example, this function 
returns
   (require 'ox)
   (pcomplete-here
    (and org-export-select-tags
-       (list (mapconcat 'identity org-export-select-tags " ")))))
+       (list (mapconcat #'identity org-export-select-tags " ")))))
 
 (defun pcomplete/org-mode/file-option/startup ()
   "Complete arguments for the #+STARTUP file option."
   (while (pcomplete-here
          (let ((opts (pcomplete-uniquify-list
-                      (mapcar 'car org-startup-options))))
+                      (mapcar #'car org-startup-options))))
            ;; Some options are mutually exclusive, and shouldn't be completed
            ;; against if certain other options have already been seen.
            (dolist (arg pcomplete-args)
@@ -340,7 +339,8 @@ When completing for #+STARTUP, for example, this function 
returns
   "Complete against TeX-style HTML entity names."
   (require 'org-entities)
   (while (pcomplete-here
-         (pcomplete-uniquify-list (remove nil (mapcar 'car-safe org-entities)))
+         (pcomplete-uniquify-list
+          (remove nil (mapcar #'car-safe org-entities)))
          (substring pcomplete-stub 1))))
 
 (defun pcomplete/org-mode/todo ()
diff --git a/lisp/org-plot.el b/lisp/org-plot.el
index 4ac15b3..63176fc 100644
--- a/lisp/org-plot.el
+++ b/lisp/org-plot.el
@@ -51,19 +51,28 @@
   "Parse an OPTIONS line and set values in the property list P.
 Returns the resulting property list."
   (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)))
+    (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)
+               ("min"       . :ymin)
+               ("ymin"      . :ymin)
+               ("max"       . :ymax)
+               ("ymax"      . :ymax)
+               ("xmin"      . :xmin)
+               ("xmax"      . :xmax)
+               ("ticks"     . :ticks)
+               ("trans"     . :transpose)
+               ("transpose" . :transpose)))
          (multiples '("set" "line"))
          (regexp ":\\([\"][^\"]+?[\"]\\|[(][^)]+?[)]\\|[^ \t\n\r;,.]*\\)")
          (start 0))
@@ -180,94 +189,440 @@ and dependent variables."
          (setf back-edge "") (setf front-edge ""))))
     row-vals))
 
-(defun org-plot/gnuplot-script (data-file num-cols params &optional preface)
-  "Write a gnuplot script to DATA-FILE respecting the options set in PARAMS.
+(defun org--plot/values-stats (nums &optional hard-min hard-max)
+  "Rudimentary statistics about NUMS, useful for guessing axis ticks.
+If HARD-MIN or HARD-MAX are set, they will be used instead of the min/max
+of the NUMS."
+  (let* ((minimum (or hard-min (apply #'min nums)))
+        (maximum (or hard-max (apply #'max nums)))
+        (range (- maximum minimum))
+        (rangeOrder (if (= range 0) 0
+                      (ceiling (- 1 (log range 10)))))
+        (range-factor (expt 10 rangeOrder))
+        (nice-min (if (= range 0) (car nums)
+                    (/ (float (floor (* minimum range-factor))) range-factor)))
+        (nice-max (if (= range 0) (car nums)
+                    (/ (float (ceiling (* maximum range-factor))) 
range-factor))))
+    `(:min ,minimum :max ,maximum :range ,range
+           :range-factor ,range-factor
+           :nice-min ,nice-min :nice-max ,nice-max :nice-range ,(- nice-max 
nice-min))))
+
+(defun org--plot/sensible-tick-num (table &optional hard-min hard-max)
+  "From a the values in a TABLE of data, guess an appropriate number of ticks.
+If HARD-MIN and HARD-MAX can be used to fix the ends of the axis."
+  (let* ((row-data
+         (mapcar (lambda (row) (org--plot/values-stats
+                                (mapcar #'string-to-number (cdr row))
+                                hard-min
+                                hard-max)) table))
+        (row-normalised-ranges (mapcar (lambda (r-data)
+                                         (let ((val (round (*
+                                                            (plist-get r-data 
:range-factor)
+                                                            (plist-get r-data 
:nice-range)))))
+                                           (if (= (% val 10) 0) (/ val 10) 
val)))
+                                       row-data))
+        (range-prime-decomposition (mapcar #'org--plot/prime-factors 
row-normalised-ranges))
+        (weighted-factors (sort (apply #'org--plot/merge-alists #'+ 0
+                                       (mapcar (lambda (factors) 
(org--plot/item-frequencies factors t))
+                                               range-prime-decomposition))
+                                (lambda (a b) (> (cdr a) (cdr b))))))
+    (apply #'* (org--plot/nice-frequency-pick weighted-factors))))
+
+(defun org--plot/nice-frequency-pick (frequencies)
+  "From a list of FREQUENCIES, try to sensibly pick a sample of the most 
frequent."
+  ;; TODO this mosly works decently, but could do with some tweaking to work 
more consistently.
+  (cl-case (length frequencies)
+    (1 (list (car (nth 0 frequencies))))
+    (2 (if (<= 3 (/ (cdr (nth 0 frequencies))
+                   (cdr (nth 1 frequencies))))
+          (make-list 2
+                     (car (nth 0 frequencies)))
+        (list (car (nth 0 frequencies))
+              (car (nth 1 frequencies)))))
+    (t
+     (let* ((total-count (apply #'+ (mapcar #'cdr frequencies)))
+           (n-freq (mapcar (lambda (freq) `(,(car freq) . ,(/ (float (cdr 
freq)) total-count))) frequencies))
+           (f-pick (list (car (car n-freq))))
+           (1-2-ratio (/ (cdr (nth 0 n-freq))
+                         (cdr (nth 1 n-freq))))
+           (2-3-ratio (/ (cdr (nth 1 n-freq))
+                         (cdr (nth 2 n-freq))))
+           (1-3-ratio (* 1-2-ratio 2-3-ratio))
+           (1-val (car (nth 0 n-freq)))
+           (2-val (car (nth 1 n-freq)))
+           (3-val (car (nth 2 n-freq))))
+       (when (> 1-2-ratio 4) (push 1-val f-pick))
+       (when (and (< 1-2-ratio 2-val)
+                 (< (* (apply #'* f-pick) 2-val) 30))
+        (push 2-val f-pick))
+       (when (and (< 1-3-ratio 3-val)
+                 (< (* (apply #'* f-pick) 3-val) 30))
+        (push 3-val f-pick))
+       f-pick))))
+
+(defun org--plot/merge-alists (function default alist1 alist2 &rest alists)
+  "Using FUNCTION, combine the elements of ALIST1, ALIST2 and any other ALISTS.
+When an element is only present in one alist, DEFAULT is used as the second
+argument for the FUNCTION."
+  (when (> (length alists) 0)
+    (setq alist2 (apply #'org--plot/merge-alists function default alist2 
alists)))
+  (cl-flet ((keys (alist) (mapcar #'car alist))
+           (lookup (key alist) (or (cdr (assoc key alist)) default)))
+    (cl-loop with keys = (cl-union (keys alist1) (keys alist2) :test 'equal)
+            for k in keys collect
+            (cons k (funcall function (lookup k alist1) (lookup k alist2))))))
+
+(defun org--plot/item-frequencies (values &optional normalise)
+  "Return an alist indicating the frequency of values in VALUES list.
+When NORMALISE is non-nil, the count is divided by the number of values."
+  (let ((normaliser (if normalise (float (length values)) 1)))
+    (cl-loop for (n . m) in (seq-group-by #'identity values)
+            collect (cons n (/ (length m) normaliser)))))
+
+(defun org--plot/prime-factors (value)
+  "Return the prime decomposition of VALUE, e.g. for 12, '(3 2 2)."
+  (let ((factors '(1)) (i 1))
+    (while (/= 1 value)
+      (setq i (1+ i))
+      (when (eq 0 (% value i))
+       (push i factors)
+       (setq value (/ value i))
+       (setq i (1- i))
+       ))
+    (cl-subseq factors 0 -1)))
+
+(defcustom org-plot/gnuplot-script-preamble ""
+  "String of function to be inserted before the gnuplot plot command is run.
+
+Note that this is in addition to, not instead of other content generated in
+`org-plot/gnuplot-script'.  If a function, it is called with the plot type as
+the argument, and must return a string to be used."
+  :group 'org-plot
+  :type '(choice string function))
+
+(defcustom org-plot/preset-plot-types
+  '((2d :plot-cmd "plot"
+       :check-ind-type t
+       :plot-func
+       (lambda (_table data-file num-cols params plot-str)
+         (let* ((type (plist-get params :plot-type))
+                (with (if (eq type 'grid) 'pm3d (plist-get params :with)))
+                (ind (plist-get params :ind))
+                (deps (if (plist-member params :deps) (plist-get params 
:deps)))
+                (text-ind (or (plist-get params :textind)
+                               (eq (plist-get params :with) 'histograms)))
+                (col-labels (plist-get params :labels))
+                res)
+           (dotimes (col num-cols res)
+             (unless (and (eq type '2d)
+                          (or (and ind (equal (1+ col) ind))
+                              (and deps (not (member (1+ col) deps)))))
+               (setf res
+                     (cons
+                      (format plot-str data-file
+                              (or (and ind (> ind 0)
+                                       (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))))
+                      res)))))))
+    (3d :plot-cmd "splot"
+       :plot-pre (lambda (_table _data-file _num-cols params _plot-str)
+                   (if (plist-get params :map) "set map"))
+       :plot-func
+       (lambda (_table data-file _num-cols params _plot-str)
+         (let* ((type (plist-get params :plot-type))
+                (with (if (eq type 'grid) 'pm3d (plist-get params :with))))
+           (list (format "'%s' matrix with %s title ''"
+                         data-file with)))))
+    (grid :plot-cmd "splot"
+         :plot-pre (lambda (_table _data-file _num-cols params _plot-str)
+                     (if (plist-get params :map) "set pm3d map" "set map"))
+         :data-dump (lambda (table data-file params _num-cols)
+                      (let ((y-labels (org-plot/gnuplot-to-grid-data
+                                       table data-file params)))
+                        (when y-labels (plist-put params :ylabels y-labels))))
+         :plot-func
+         (lambda (table data-file _num-cols params _plot-str)
+           (let* ((type (plist-get params :plot-type))
+                  (with (if (eq type 'grid) 'pm3d (plist-get params :with))))
+             (list (format "'%s' with %s title ''"
+                           data-file with)))))
+    (radar :plot-func
+          (lambda (table _data-file _num-cols params plot-str)
+            (list (org--plot/radar table params)))))
+  "List of plists describing the available plot types.
+The car is the type name, and the property :plot-func must be
+set.  The value of :plot-func is a lambda which yields plot-lines
+\(a list of strings) as the cdr.
+
+All lambda functions have the parameters of
+`org-plot/gnuplot-script' and PLOT-STR passed to them.  i.e. they
+are called with the following signature: (TABLE DATA-FILE
+NUM-COLS PARAMS PLOT-STR)
+
+Potentially useful parameters in PARAMS include:
+ :set :line :map :title :file :ind :timeind :timefmt :textind
+ :deps :labels :xlabels :ylabels :xmin :xmax :ymin :ymax :ticks
+
+In addition to :plot-func, the following optional properties may
+be set.
+
+- :plot-cmd - A gnuplot command appended to each plot-line.
+  Accepts string or nil.  Default value: nil.
+
+- :check-ind-type - Whether the types of ind values should be checked.
+  Accepts boolean.
+
+- :plot-str - the formula string passed to :plot-func as PLOT-STR
+  Accepts string.  Default value: \"'%s' using %s%d%s with %s title '%s'\"
+
+- :data-dump - Function to dump the table to a datafile for ease of
+  use.
+
+  Accepts lambda function.  Default lambda body:
+  (org-plot/gnuplot-to-data table data-file params)
+
+- :plot-pre - Gnuplot code to be inserted early into the script, just
+  after term and output have been set.
+
+   Accepts string, nil, or lambda function which returns string
+   or nil.  Defaults to nil."
+  :group 'org-plot
+  :type '(alist :value-type (symbol group)))
+
+(defvar org--plot/radar-template
+  "### spider plot/chart with gnuplot
+# also known as: radar chart, web chart, star chart, cobweb chart,
+#                radar plot,  web plot,  star plot,  cobweb plot,  etc. ...
+set datafile separator ' '
+set size square
+unset tics
+set angles degree
+set key bmargin center horizontal
+unset border
+
+# Load data and setup
+load \"%s\"
+
+# General settings
+DataColCount = words($Data[1])-1
+AxesCount = |$Data|-HeaderLines-1
+AngleOffset = 90
+Max = 1
+d=0.1*Max
+Direction = -1   # counterclockwise=1, clockwise = -1
+
+# Tic settings
+TicCount = %s
+TicOffset = 0.1
+TicValue(axis,i) = real(i)*(word($Settings[axis],3)-word($Settings[axis],2)) \\
+         / word($Settings[axis],4)+word($Settings[axis],2)
+TicLabelPosX(axis,i) = PosX(axis,i/TicCount) + PosY(axis, TicOffset)
+TicLabelPosY(axis,i) = PosY(axis,i/TicCount) - PosX(axis, TicOffset)
+TicLen = 0.03
+TicdX(axis,i) = 0.5*TicLen*cos(alpha(axis)-90)
+TicdY(axis,i) = 0.5*TicLen*sin(alpha(axis)-90)
+
+# Label
+LabOffset = 0.10
+LabX(axis) = PosX(axis+1,Max+2*d) + PosY(axis, LabOffset)
+LabY(axis) = PosY($0+1,Max+2*d)
+
+# Functions
+alpha(axis) = (axis-1)*Direction*360.0/AxesCount+AngleOffset
+PosX(axis,R) = R*cos(alpha(axis))
+PosY(axis,R) = R*sin(alpha(axis))
+Scale(axis,value) = 
real(value-word($Settings[axis],2))/(word($Settings[axis],3)-word($Settings[axis],2))
+
+# Spider settings
+set style arrow 1 dt 1 lw 1.0 @fgal head filled size 0.06,25     # style for 
axes
+set style arrow 2 dt 2 lw 0.5 @fgal nohead   # style for weblines
+set style arrow 3 dt 1 lw 1 @fgal nohead     # style for axis tics
+set samples AxesCount
+set isosamples TicCount
+set urange[1:AxesCount]
+set vrange[1:TicCount]
+set style fill transparent solid 0.2
+
+set xrange[-Max-4*d:Max+4*d]
+set yrange[-Max-4*d:Max+4*d]
+plot \\
+    '+' u (0):(0):(PosX($0,Max+d)):(PosY($0,Max+d)) w vec as 1 not, \\
+    $Data u (LabX($0)): \\
+       (LabY($0)):1 every ::HeaderLines w labels center enhanced @fgt not, \\
+    for [i=1:DataColCount] $Data u (PosX($0+1,Scale($0+1,column(i+1)))): \\
+       (PosY($0+1,Scale($0+1,column(i+1)))) every ::HeaderLines w filledcurves 
lt i title word($Data[1],i+1), \\
+%s
+#    '++' u (PosX($1,$2/TicCount)-TicdX($1,$2/TicCount)): \\
+#        (PosY($1,$2/TicCount)-TicdY($1,$2/TicCount)): \\
+#        (2*TicdX($1,$2/TicCount)):(2*TicdY($1,$2/TicCount)) \\
+#        w vec as 3 not, \\
+### end of code
+")
+
+(defvar org--plot/radar-ticks
+  "    '++' u (PosX($1,$2/TicCount)):(PosY($1,$2/TicCount)): \\
+       (PosX($1+1,$2/TicCount)-PosX($1,$2/TicCount)):  \\
+       (PosY($1+1,$2/TicCount)-PosY($1,$2/TicCount)) w vec as 2 not, \\
+    '++' u (TicLabelPosX(%s,$2)):(TicLabelPosY(%s,$2)): \\
+       (sprintf('%%g',TicValue(%s,$2))) w labels font ',8' @fgat not")
+
+(defvar org--plot/radar-setup-template
+  "# Data
+$Data <<HEREHAVESOMEDATA
+%s
+HEREHAVESOMEDATA
+HeaderLines = 1
+
+# Settings for scale and offset adjustments
+# axis min max tics axisLabelXoff axisLabelYoff
+$Settings <<EOD
+%s
+EOD
+")
+
+(defun org--plot/radar (table params)
+  "Create gnuplot code for a radar plot of TABLE with PARAMS."
+  (let* ((data
+         (concat "\"" (mapconcat #'identity (plist-get params :labels) "\" 
\"") "\""
+                 "\n"
+                 (mapconcat (lambda (row)
+                              (format
+                               "\"%s\" %s"
+                               (car row)
+                               (mapconcat #'identity (cdr row) " ")))
+                            (append table (list (car table)))
+                            "\n")))
+        (ticks (or (plist-get params :ticks)
+                   (org--plot/sensible-tick-num table
+                                                (plist-get params :ymin)
+                                                (plist-get params :ymax))))
+        (settings
+         (mapconcat (lambda (row)
+                      (let ((data (org--plot/values-stats
+                                   (mapcar #'string-to-number (cdr row)))))
+                        (format
+                         "\"%s\" %s %s %s"
+                         (car row)
+                         (or (plist-get params :ymin)
+                             (plist-get data :nice-min))
+                         (or (plist-get params :ymax)
+                             (plist-get data :nice-max))
+                         (if (eq ticks 0) 2 ticks)
+                         )))
+                    (append table (list (car table)))
+                    "\n"))
+        (setup-file (make-temp-file "org-plot-setup")))
+    (let ((coding-system-for-write 'utf-8))
+      (write-region (format org--plot/radar-setup-template data settings) nil 
setup-file nil :silent))
+    (format org--plot/radar-template
+           setup-file
+           (if (eq ticks 0) 2 ticks)
+           (if (eq ticks 0) ""
+             (apply #'format org--plot/radar-ticks
+                    (make-list 3 (if (and (plist-get params :ymin)
+                                          (plist-get params :ymax))
+                                     ;; FIXME multi-drawing of tick labels 
with "1"
+                                     "1" "$1")))))))
+
+(defcustom org-plot/gnuplot-term-extra ""
+  "String or function which provides the extra term options.
+E.g. a value of \"size 1050,650\" would cause
+\"set term ... size 1050,650\" to be used.
+If a function, it is called with the plot type as the argument."
+  :group 'org-plot
+  :type '(choice string function))
+
+(defun org-plot/gnuplot-script (table data-file num-cols params &optional 
preface)
+  "Write a gnuplot script for TABLE to DATA-FILE respecting options in PARAMS.
 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 (eq type 'grid) 'pm3d (plist-get params :with)))
-        (sets (plist-get params :set))
-        (lines (plist-get params :line))
-        (map (plist-get params :map))
-        (title (plist-get params :title))
-        (file (plist-get params :file))
-        (ind (plist-get params :ind))
-        (time-ind (plist-get params :timeind))
-        (timefmt (plist-get params :timefmt))
-        (text-ind (plist-get params :textind))
-        (deps (if (plist-member params :deps) (plist-get params :deps)))
-        (col-labels (plist-get params :labels))
-        (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 (pcase type
-                    (`2d "plot")
-                    (`3d "splot")
-                    (`grid "splot")))
-        (script "reset")
-        ;; ats = add-to-script
-        (ats (lambda (line) (setf script (concat script "\n" line))))
-        plot-lines)
-    (when file                         ; output file
-      (funcall ats (format "set term %s" (file-name-extension file)))
-      (funcall ats (format "set output '%s'" file)))
-    (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)
-      (funcall ats
-              (format "set ytics (%s)"
-                      (mapconcat (lambda (pair)
-                                   (format "\"%s\" %d" (cdr pair) (car pair)))
-                                 y-labels ", "))))
-    (when time-ind                     ; timestamp index
-      (funcall ats "set xdata time")
-      (funcall ats (concat "set timefmt \""
-                          (or timefmt  ; timefmt passed to gnuplot
-                              "%Y-%m-%d-%H:%M:%S") "\"")))
-    (unless preface
-      (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)
-                               (if text-ind (format ":xticlabel(%d)" ind) "")
-                               with
-                               (or (nth col col-labels)
-                                   (format "%d" (1+ col))))
-                       plot-lines)))))
-       (`3d
-        (setq plot-lines (list (format "'%s' matrix with %s title ''"
-                                       data-file with))))
-       (`grid
-        (setq plot-lines (list (format "'%s' with %s title ''"
-                                       data-file with)))))
+  (let* ((type-name (plist-get params :plot-type))
+        (type (cdr (assoc type-name org-plot/preset-plot-types))))
+    (unless type
+      (user-error "Org-plot type `%s' is undefined" type-name))
+    (let* ((sets (plist-get params :set))
+          (lines (plist-get params :line))
+          (title (plist-get params :title))
+          (file (plist-get params :file))
+          (time-ind (plist-get params :timeind))
+          (timefmt (plist-get params :timefmt))
+          (x-labels (plist-get params :xlabels))
+          (y-labels (plist-get params :ylabels))
+          (plot-str (or (plist-get type :plot-str)
+                        "'%s' using %s%d%s with %s title '%s'"))
+          (plot-cmd (plist-get type :plot-cmd))
+          (plot-pre (plist-get type :plot-pre))
+          (script "reset")
+          ;; ats = add-to-script
+          (ats (lambda (line) (when line (setf script (concat script "\n" 
line)))))
+          plot-lines)
+
+
+      ;; handle output file, background, and size
+      (funcall ats (format "set term %s %s"
+                          (if file (file-name-extension file) "GNUTERM")
+                          (if (stringp org-plot/gnuplot-term-extra)
+                              org-plot/gnuplot-term-extra
+                            (funcall org-plot/gnuplot-term-extra type))))
+      (when file ; output file
+       (funcall ats (format "set output '%s'" (expand-file-name file))))
+
+      (when plot-pre
+       (funcall ats (funcall plot-pre table data-file num-cols params 
plot-str)))
+
       (funcall ats
-              (concat plot-cmd " " (mapconcat #'identity
-                                              (reverse plot-lines)
-                                              ",\\\n    "))))
-    script))
+              (if (stringp org-plot/gnuplot-script-preamble)
+                  org-plot/gnuplot-script-preamble
+                (funcall org-plot/gnuplot-script-preamble type)))
+
+      (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)
+       (funcall ats
+                (format "set ytics (%s)"
+                        (mapconcat (lambda (pair)
+                                     (format "\"%s\" %d" (cdr pair) (car 
pair)))
+                                   y-labels ", "))))
+      (when time-ind                   ; timestamp index
+       (funcall ats "set xdata time")
+       (funcall ats (concat "set timefmt \""
+                            (or timefmt        ; timefmt passed to gnuplot
+                                "%Y-%m-%d-%H:%M:%S") "\"")))
+      (unless preface
+       (let ((type-func (plist-get type :plot-func)))
+         (when type-func
+           (setq plot-lines
+                 (funcall type-func table data-file num-cols params 
plot-str))))
+       (funcall ats
+                (concat plot-cmd
+                        (when plot-cmd " ")
+                        (mapconcat #'identity
+                                   (reverse plot-lines)
+                                   ",\\\n    "))))
+      script)))
+
+(defun org-plot/redisplay-img-in-buffer (img-file)
+  "Find any overlays for IMG-FILE in the current Org buffer, and refresh them."
+  (dolist (img-overlay org-inline-image-overlays)
+    (when (string= img-file (plist-get (cdr (overlay-get img-overlay 
'display)) :file))
+      (when (file-exists-p img-file)
+        (image-refresh (overlay-get img-overlay 'display))))))
 
 ;;-----------------------------------------------------------------------------
 ;; facade functions
@@ -283,15 +638,40 @@ line directly before or after the table."
     (when (get-buffer "*gnuplot*") ; reset *gnuplot* if it already running
       (with-current-buffer "*gnuplot*"
        (goto-char (point-max))))
-    (org-plot/goto-nearest-table)
-    ;; 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)))))
+    (save-excursion
+      (org-plot/goto-nearest-table)
+      ;; 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 options.
+      (while (and (equal 0 (forward-line -1))
+                  (looking-at "[[:space:]]*#\\+"))
+        (setf params (org-plot/collect-options params))))
     ;; collect table and table information
     (let* ((data-file (make-temp-file "org-plot"))
-          (table (org-table-collapse-header (org-table-to-lisp)))
-          (num-cols (length (car table))))
+           (table (let ((tbl (save-excursion
+                               (org-plot/goto-nearest-table)
+                               (org-table-to-lisp))))
+                   (when (pcase (plist-get params :transpose)
+                           (`y   t)
+                           (`yes t)
+                           (`t   t))
+                     (if (not (memq 'hline tbl))
+                         (setq tbl (apply #'cl-mapcar #'list tbl))
+                       ;; When present, remove hlines as they can't 
(currentily) be easily transposed.
+                       (setq tbl (apply #'cl-mapcar #'list
+                                        (remove 'hline tbl)))
+                       (push 'hline (cdr tbl))))
+                   tbl))
+          (num-cols (length (if (eq (nth 0 table) 'hline) (nth 1 table)
+                              (nth 0 table))))
+          (type (assoc (plist-get params :plot-type)
+                       org-plot/preset-plot-types)))
+
+      (unless type
+       (user-error "Org-plot type `%s' is undefined" (plist-get params 
:plot-type)))
+
       (run-with-idle-timer 0.1 nil #'delete-file data-file)
       (when (eq (cadr table) 'hline)
        (setf params
@@ -301,15 +681,12 @@ line directly before or after the table."
       (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).
-      (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)))))
+      ;; Dump table to datafile
+      (if-let ((dump-func (plist-get type :data-dump)))
+         (funcall dump-func table data-file num-cols params)
+       (org-plot/gnuplot-to-data table data-file params))
       ;; Check type of ind column (timestamp? text?)
-      (when (eq `2d (plist-get params :plot-type))
+      (when (plist-get params :check-ind-type)
        (let* ((ind (1- (plist-get params :ind)))
               (ind-column (mapcar (lambda (row) (nth ind row)) table)))
          (cond ((< ind 0) nil) ; ind is implicit
@@ -326,18 +703,23 @@ line directly before or after the table."
       (with-temp-buffer
        (if (plist-get params :script)  ; user script
            (progn (insert
-                    (org-plot/gnuplot-script data-file num-cols params t))
-                   (insert "\n")
-                   (insert-file-contents (plist-get params :script))
-                   (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)))
+                   (org-plot/gnuplot-script table data-file num-cols params t))
+                  (insert "\n")
+                  (insert-file-contents (plist-get params :script))
+                  (goto-char (point-min))
+                  (while (re-search-forward "\\$datafile" nil t)
+                    (replace-match data-file nil nil)))
+         (insert (org-plot/gnuplot-script table data-file num-cols params)))
        ;; Graph table.
        (gnuplot-mode)
-       (gnuplot-send-buffer-to-gnuplot))
+        (condition-case nil
+            (gnuplot-send-buffer-to-gnuplot)
+          (buffer-read-only nil)))
       ;; Cleanup.
-      (bury-buffer (get-buffer "*gnuplot*")))))
+      (bury-buffer (get-buffer "*gnuplot*"))
+      ;; Refresh any displayed images
+      (when (plist-get params :file)
+        (org-plot/redisplay-img-in-buffer (expand-file-name (plist-get params 
:file)))))))
 
 (provide 'org-plot)
 
diff --git a/lisp/org-protocol.el b/lisp/org-protocol.el
index 9969372..ca3249d 100644
--- a/lisp/org-protocol.el
+++ b/lisp/org-protocol.el
@@ -94,6 +94,15 @@
 ;; You may use the same bookmark URL for all those standard handlers and just
 ;; adjust the sub-protocol used:
 ;;
+;;     javascript:location.href='org-protocol://sub-protocol?'+
+;;           new URLSearchParams({
+;;                 url: location.href,
+;;                 title: document.title,
+;;                 body: window.getSelection()})
+;;
+;; Alternatively use the following expression that encodes space as \"%20\"
+;; instead of \"+\", so it is compatible with Org versions from 9.0 to 9.4:
+;;
 ;;     location.href='org-protocol://sub-protocol?url='+
 ;;           encodeURIComponent(location.href)+'&title='+
 ;;           encodeURIComponent(document.title)+'&body='+
@@ -103,6 +112,11 @@
 ;; char that, if present, triggers the use of a special template.
 ;; Example:
 ;;
+;;     location.href='org-protocol://capture?'+
+;;           new URLSearchParams({template:'x', /* ... */})
+;;
+;; or
+;;
 ;;     location.href='org-protocol://capture?template=x'+ ...
 ;;
 ;;  uses template ?x.
@@ -176,12 +190,13 @@ Possible properties are:
 
   :online-suffix     - the suffix to strip from the published URLs
   :working-suffix    - the replacement for online-suffix
-  :base-url          - the base URL, e.g. http://www.example.com/project/
+  :base-url          - the base URL, e.g. https://www.example.com/project/
                        Last slash required.
-  :working-directory - the local working directory.  This is, what base-url 
will
-                       be replaced with.
-  :redirects         - A list of cons cells, each of which maps a regular
-                       expression to match to a path relative to 
:working-directory.
+  :working-directory - the local working directory.  This is what
+                       base-url will be replaced with.
+  :redirects         - A list of cons cells, each of which maps a
+                       regular expression to match to a path relative
+                       to `:working-directory'.
 
 Example:
 
@@ -202,7 +217,8 @@ Example:
           :working-directory \"~/site/content/post/\"
           :online-suffix \".html\"
           :working-suffix \".md\"
-          :rewrites ((\"\\(https://site.com/[0-9]+/[0-9]+/[0-9]+/\\)\" . 
\".md\")))
+          :rewrites ((\"\\(https://site.com/[0-9]+/[0-9]+/[0-9]+/\\)\"
+                     . \".md\")))
          (\"GNU emacs OpenGrok\"
           :base-url \"https://opengrok.housegordon.com/source/xref/emacs/\";
           :working-directory \"~/dev/gnu-emacs/\")))
@@ -214,8 +230,9 @@ Example:
    does not include any suffix properties, allowing local source
    file to be opened as found by OpenGrok.
 
-Consider using the interactive functions `org-protocol-create' and
-`org-protocol-create-for-org' to help you filling this variable with valid 
contents."
+Consider using the interactive functions `org-protocol-create'
+and `org-protocol-create-for-org' to help you filling this
+variable with valid contents."
   :group 'org-protocol
   :type 'alist)
 
@@ -424,7 +441,12 @@ 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:
+The location for a browser's bookmark may look like this:
+
+  javascript:location.href = \\='org-protocol://store-link?\\=' +
+       new URLSearchParams({url:location.href, title:document.title});
+
+or to keep compatibility with Org versions from 9.0 to 9.4 it may be:
 
   javascript:location.href = \\
       \\='org-protocol://store-link?url=\\=' + \\
@@ -433,7 +455,9 @@ The location for a browser's bookmark has to look like this:
 
 Don't use `escape()'!  Use `encodeURIComponent()' instead.  The
 title of the page could contain slashes and the location
-definitely will.
+definitely will.  Org 9.4 and earlier could not decode \"+\"
+to space, that is why less readable latter expression may be necessary
+for backward compatibility.
 
 The sub-protocol used to reach this function is set in
 `org-protocol-protocol-alist'.
@@ -461,6 +485,14 @@ 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?\\=' +
+        new URLSearchParams({
+              url: location.href,
+              title: document.title,
+              body: window.getSelection()})
+
+or to keep compatibility with Org versions from 9.0 to 9.4:
+
   javascript:location.href = \\='org-protocol://capture?url=\\='+ \\
         encodeURIComponent(location.href) + \\='&title=\\=' + \\
         encodeURIComponent(document.title) + \\='&body=\\=' + \\
@@ -516,10 +548,11 @@ Now template ?b will be used."
 (defun org-protocol-convert-query-to-plist (query)
   "Convert QUERY key=value pairs in the URL to a property list."
   (when query
-    (apply 'append (mapcar (lambda (x)
-                            (let ((c (split-string x "=")))
-                              (list (intern (concat ":" (car c))) (cadr c))))
-                          (split-string query "&")))))
+    (let ((plus-decoded (replace-regexp-in-string "\\+" " " query t t)))
+      (apply 'append (mapcar (lambda (x)
+                              (let ((c (split-string x "=")))
+                                (list (intern (concat ":" (car c))) (cadr c))))
+                            (split-string plus-decoded "&"))))))
 
 (defun org-protocol-open-source (fname)
   "Process an org-protocol://open-source?url= style URL with FNAME.
@@ -529,11 +562,17 @@ in `org-protocol-project-alist'.
 
 The location for a browser's bookmark should look like this:
 
+  javascript:location.href = \\='org-protocol://open-source?\\=' +
+        new URLSearchParams({url: location.href})
+
+or if you prefer to keep compatibility with older Org versions (9.0 to 9.4),
+consider the following expression:
+
   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)
+  (let (;; (result nil)
        (f (org-protocol-sanitize-uri
            (plist-get (org-protocol-parse-parameters fname nil '(:url))
                       :url))))
@@ -551,7 +590,7 @@ The location for a browser's bookmark should look like this:
                   (f1 (substring f 0 (string-match "\\([\\?#].*\\)?$" f)))
                    (start-pos (+ (string-match wsearch f1) (length base-url)))
                    (end-pos (if strip-suffix
-                             (string-match (regexp-quote strip-suffix) f1)
+                               (string-match (regexp-quote strip-suffix) f1)
                              (length f1)))
                   ;; We have to compare redirects without suffix below:
                   (f2 (concat wdir (substring f1 start-pos end-pos)))
@@ -584,7 +623,7 @@ The location for a browser's bookmark should look like this:
               (if (file-exists-p the-file)
                   (message "%s: permission denied!" the-file)
                 (message "%s: no such file or directory." the-file))))))
-      result)))
+      nil))) ;; FIXME: Really?
 
 
 ;;; Core functions:
diff --git a/lisp/org-refile.el b/lisp/org-refile.el
index 913bec3..678759e 100644
--- a/lisp/org-refile.el
+++ b/lisp/org-refile.el
@@ -2,23 +2,23 @@
 
 ;; Copyright (C) 2010-2021 Free Software Foundation, Inc.
 
-;; Author: Carsten Dominik <carsten at orgmode dot org>
+;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;;
 ;; This file is part of GNU Emacs.
 
-;; This program is free software; you can redistribute it and/or modify
+;; 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.
 
-;; This program is distributed in the hope that it will be useful,
+;; 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 this program.  If not, see <https://www.gnu.org/licenses/>.
+;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 
@@ -214,7 +214,7 @@ converted to a headline before refiling."
                   org-org-menu
                   '("Edit Structure") i))
       '(["Refile Subtree" org-refile (org-in-subtree-not-table-p)]
-       ["Refile and copy Subtree" org-copy (org-in-subtree-not-table-p)]))
+       ["Refile and copy Subtree" org-refile-copy 
(org-in-subtree-not-table-p)]))
 
 (defun org-refile-marker (pos)
   "Get a new refile marker, but only if caching is in use."
@@ -383,8 +383,19 @@ the *old* location.")
   (let ((org-refile-keep t))
     (org-refile nil nil nil "Copy")))
 
+;;;###autoload
+(defun org-refile-reverse (&optional arg default-buffer rfloc msg)
+  "Refile while temporarily toggling `org-reverse-note-order'.
+So if `org-refile' would append the entry as the last entry under
+the target heading, `org-refile-reverse' will prepend it as the
+first entry, and vice-versa."
+  (interactive "P")
+  (let ((org-reverse-note-order (not (org-notes-order-reversed-p))))
+    (org-refile arg default-buffer rfloc msg)))
+
 (defvar org-capture-last-stored-marker)
 
+
 ;;;###autoload
 (defun org-refile (&optional arg default-buffer rfloc msg)
   "Move the entry or entries at point to another heading.
@@ -427,7 +438,7 @@ needed when passing RFLOC
 headline to refile under
 
 MSG is a string to replace \"Refile\" in the default prompt with
-another verb.  E.g. `org-copy' sets this parameter to \"Copy\".
+another verb.  E.g. `org-refile-copy' sets this parameter to \"Copy\".
 
 See also `org-refile-use-outline-path'.
 
diff --git a/lisp/org-src.el b/lisp/org-src.el
index c5dcf28..91a3d41 100644
--- a/lisp/org-src.el
+++ b/lisp/org-src.el
@@ -2,7 +2,7 @@
 ;;
 ;; Copyright (C) 2004-2021 Free Software Foundation, Inc.
 ;;
-;; Author: Carsten Dominik <carsten at orgmode dot org>
+;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 ;;        Bastien Guerry <bzg@gnu.org>
 ;;         Dan Davison <davison at stats dot ox dot ac dot uk>
 ;; Keywords: outlines, hypermedia, calendar, wp
@@ -299,6 +299,9 @@ is 0.")
   "File name associated to Org source buffer, or nil.")
 (put 'org-src-source-file-name 'permanent-local t)
 
+(defvar-local org-src--preserve-blank-line nil)
+(put 'org-src--preserve-blank-line 'permanent-local t)
+
 (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 " ]*"))
@@ -443,14 +446,21 @@ Assume point is in the corresponding edit buffer."
                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))
+       (contents (org-with-wide-buffer
+                   (let ((eol (line-end-position)))
+                     (list (buffer-substring (point-min) eol)
+                           (buffer-substring eol (point-max))))))
+       (write-back org-src--allow-write-back)
+        (preserve-blank-line org-src--preserve-blank-line)
+        marker)
     (with-current-buffer write-back-buf
       ;; Reproduce indentation parameters from source buffer.
       (setq indent-tabs-mode use-tabs?)
       (when (> source-tab-width 0) (setq tab-width source-tab-width))
       ;; Apply WRITE-BACK function on edit buffer contents.
-      (insert (org-no-properties contents))
+      (insert (org-no-properties (car contents)))
+      (setq marker (point-marker))
+      (insert (org-no-properties (car (cdr contents))))
       (goto-char (point-min))
       (when (functionp write-back) (save-excursion (funcall write-back)))
       ;; Add INDENTATION-OFFSET to every line in buffer,
@@ -458,10 +468,14 @@ Assume point is in the corresponding edit buffer."
       (when (> indentation-offset 0)
        (while (not (eobp))
          (skip-chars-forward " \t")
-         (let ((i (current-column)))
-           (delete-region (line-beginning-position) (point))
-           (indent-to (+ i indentation-offset)))
-         (forward-line))))))
+          (when (or (not (eolp))                               ; not a blank 
line
+                    (and (eq (point) (marker-position marker)) ; current line
+                         preserve-blank-line))
+           (let ((i (current-column)))
+             (delete-region (line-beginning-position) (point))
+             (indent-to (+ i indentation-offset))))
+         (forward-line)))
+      (set-marker marker nil))))
 
 (defun org-src--edit-element
     (datum name &optional initialize write-back contents remote)
@@ -506,6 +520,11 @@ Leave point in edit buffer."
             (block-ind (org-with-point-at (org-element-property :begin datum)
                          (current-indentation)))
             (content-ind org-edit-src-content-indentation)
+             (blank-line (save-excursion (beginning-of-line)
+                                         (looking-at-p "^[[:space:]]*$")))
+             (empty-line (and blank-line (looking-at-p "^$")))
+             (preserve-blank-line (or (and blank-line (not empty-line))
+                                      (and empty-line (= (+ block-ind 
content-ind) 0))))
             (preserve-ind
              (and (memq type '(example-block src-block))
                   (or (org-element-property :preserve-indent datum)
@@ -554,6 +573,7 @@ Leave point in edit buffer."
        (setq org-src--overlay overlay)
        (setq org-src--allow-write-back write-back)
        (setq org-src-source-file-name source-file-name)
+        (setq org-src--preserve-blank-line preserve-blank-line)
        ;; Start minor mode.
        (org-src-mode)
        ;; Clear undo information so we cannot undo back to the
@@ -584,7 +604,7 @@ Leave point in edit buffer."
 
 (defun org-src-font-lock-fontify-block (lang start end)
   "Fontify code block.
-This function is called by emacs automatic fontification, as long
+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)
@@ -679,7 +699,7 @@ This minor mode is turned on in two situations:
 \\{org-src-mode-map}
 
 See also `org-src-mode-hook'."
-  nil " OrgSrc" nil
+  :lighter " OrgSrc"
   (when org-edit-src-persistent-message
     (setq header-line-format
          (substitute-command-keys
@@ -1199,13 +1219,13 @@ Throw an error if there is no such buffer."
       ;; insert new contents.
       (delete-overlay overlay)
       (let ((expecting-bol (bolp)))
-       (if (version< emacs-version "26.1")
+       (if (version< emacs-version "27.1")
            (progn (delete-region beg end)
                   (insert (with-current-buffer write-back-buf 
(buffer-string))))
-           (save-restriction
-             (narrow-to-region beg end)
-             (replace-buffer-contents write-back-buf)
-             (goto-char (point-max))))
+         (save-restriction
+           (narrow-to-region beg end)
+           (replace-buffer-contents write-back-buf 0.1 nil)
+           (goto-char (point-max))))
        (when (and expecting-bol (not (bolp))) (insert "\n")))
       (kill-buffer write-back-buf)
       (save-buffer)
@@ -1246,14 +1266,14 @@ Throw an error if there is no such buffer."
        (undo-boundary)
        (goto-char beg)
        (let ((expecting-bol (bolp)))
-        (if (version< emacs-version "26.1")
+        (if (version< emacs-version "27.1")
             (progn (delete-region beg end)
                    (insert (with-current-buffer write-back-buf
                               (buffer-string))))
-            (save-restriction
-              (narrow-to-region beg end)
-              (replace-buffer-contents write-back-buf)
-              (goto-char (point-max))))
+          (save-restriction
+            (narrow-to-region beg end)
+            (replace-buffer-contents write-back-buf 0.1 nil)
+            (goto-char (point-max))))
         (when (and expecting-bol (not (bolp))) (insert "\n")))))
     (when write-back-buf (kill-buffer write-back-buf))
     ;; If we are to return to source buffer, put point at an
diff --git a/lisp/org-table.el b/lisp/org-table.el
index 3773b3e..89c57fb 100644
--- a/lisp/org-table.el
+++ b/lisp/org-table.el
@@ -2,7 +2,7 @@
 
 ;; Copyright (C) 2004-2021 Free Software Foundation, Inc.
 
-;; Author: Carsten Dominik <carsten at orgmode dot org>
+;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: https://orgmode.org
 ;;
@@ -332,7 +332,7 @@ relies on the variables to be present in the list."
 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. `hh:mm' selects to use hours and minutes, ignoring seconds.
+days.  `hh:mm' selects to use hours and minutes, ignoring seconds.
 The `U' flag in a table formula will select this specific format for
 a single formula."
   :group 'org-table-calculation
@@ -501,7 +501,7 @@ This may be useful when columns have been shrunk."
 ;;;###autoload
 (define-minor-mode org-table-header-line-mode
   "Display the first row of the table at point in the header line."
-  nil " TblHeader" nil
+  :lighter " TblHeader"
   (unless (eq major-mode 'org-mode)
     (user-error "Cannot turn org table header mode outside org-mode buffers"))
   (if org-table-header-line-mode
@@ -685,8 +685,6 @@ Will be filled automatically during use.")
     ("_" . "Names for values in row below this one.")
     ("^" . "Names for values in row above this one.")))
 
-(defvar org-tbl-calc-modes nil)
-
 (defvar org-pos nil)
 
 
@@ -730,18 +728,6 @@ Field is restored even in case of abnormal exit."
         (org-table-goto-column ,column)
         (set-marker ,line nil)))))
 
-(defsubst org-table--set-calc-mode (var &optional value)
-  (if (stringp var)
-      (setq var (assoc var '(("D" calc-angle-mode deg)
-                            ("R" calc-angle-mode rad)
-                            ("F" calc-prefer-frac t)
-                            ("S" calc-symbolic-mode t)))
-           value (nth 2 var) var (nth 1 var)))
-  (if (memq var org-tbl-calc-modes)
-      (setcar (cdr (memq var org-tbl-calc-modes)) value)
-    (cons var (cons value org-tbl-calc-modes)))
-  org-tbl-calc-modes)
-
 
 ;;; Predicates
 
@@ -876,52 +862,52 @@ nil      When nil, the command tries to be smart and 
figure out the
   (let* ((beg (min beg0 end0))
         (end (max beg0 end0))
         re)
-    (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)
-      (when (equal separator '(64))
-       (setq separator (read-regexp "Regexp for field separator")))
-      (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
-       (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))))
+    (when (> (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))
+    (when (equal separator '(64))
+      (setq separator (read-regexp "Regexp for field separator")))
+    (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
       (goto-char beg)
-      (if (equal separator '(4))
-         (while (< (point) end)
-           ;; parse the csv stuff
+      (setq separator
            (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)))
-                 ((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))))
+            ((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)))
+               ((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 separator)
@@ -944,7 +930,8 @@ lines.  It can have the following values:
 - regexp  When a regular expression, use it to match the separator."
   (interactive "f\nP")
   (when (and (called-interactively-p 'any)
-            (not (string-match-p (rx "." (or "txt" "tsv" "csv") eos) file)))
+            (not (string-match-p (rx "." (or "txt" "tsv" "csv") eos) file))
+             (not (yes-or-no-p "The file's extension is not .txt, .tsv or 
.csv.  Import? ")))
     (user-error "Cannot import such file"))
   (unless (bolp) (insert "\n"))
   (let ((beg (point))
@@ -1983,7 +1970,7 @@ lines."
 When this mode is active, the field editor window will always show the
 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
+  :lighter " TblFollow"
   (if org-table-follow-field-mode
       (add-hook 'post-command-hook 'org-table-follow-fields-with-editor
                'append 'local)
@@ -2015,7 +2002,7 @@ toggle `org-table-follow-field-mode'."
     (let ((b (save-excursion (skip-chars-backward "^|") (point)))
          (e (save-excursion (skip-chars-forward "^|\r\n") (point))))
       (remove-text-properties b e '(invisible t intangible t))
-      (if (and (boundp 'font-lock-mode) font-lock-mode)
+      (if font-lock-mode
          (font-lock-fontify-block))))
    (t
     (let ((pos (point-marker))
@@ -2443,51 +2430,45 @@ location of point."
                        equation
                      (org-table-get-formula equation (equal arg '(4)))))
           (n0 (org-table-current-column))
-          (org-tbl-calc-modes (copy-sequence org-calc-default-modes))
+          (calc-modes (copy-sequence org-calc-default-modes))
           (numbers nil)           ; was a variable, now fixed default
           (keep-empty nil)
-          n form form0 formrpl formrg bw fmt x ev orig c lispp literal
+          form form0 formrpl formrg bw fmt ev orig lispp literal
           duration duration-output-format)
       ;; Parse the format string.  Since we have a lot of modes, this is
       ;; a lot of work.  However, I think calc still uses most of the time.
-      (if (string-match ";" formula)
-         (let ((tmp (org-split-string formula ";")))
-           (setq formula (car tmp)
-                 fmt (concat (cdr (assoc "%" org-table-local-parameters))
-                             (nth 1 tmp)))
+      (if (string-match "\\(.*\\);\\(.*\\)" formula)
+         (progn
+           (setq fmt (concat (cdr (assoc "%" org-table-local-parameters))
+                             (match-string-no-properties 2 formula)))
+           (setq formula (match-string-no-properties 1 formula))
            (while (string-match "\\([pnfse]\\)\\(-?[0-9]+\\)" fmt)
-             (setq c (string-to-char (match-string 1 fmt))
-                   n (string-to-number (match-string 2 fmt)))
-             (if (= c ?p)
-                 (setq org-tbl-calc-modes
-                       (org-table--set-calc-mode 'calc-internal-prec n))
-               (setq org-tbl-calc-modes
-                     (org-table--set-calc-mode
-                      'calc-float-format
-                      (list (cdr (assoc c '((?n . float) (?f . fix)
-                                            (?s . sci) (?e . eng))))
-                            n))))
+             (let ((c (string-to-char (match-string 1 fmt)))
+                   (n (string-to-number (match-string 2 fmt))))
+               (cl-case c
+                 (?p (setf (cl-getf calc-modes 'calc-internal-prec) n))
+                 (?n (setf (cl-getf calc-modes 'calc-float-format) (list 
'float n)))
+                 (?f (setf (cl-getf calc-modes 'calc-float-format) (list 'fix 
n)))
+                 (?s (setf (cl-getf calc-modes 'calc-float-format) (list 'sci 
n)))
+                 (?e (setf (cl-getf calc-modes 'calc-float-format) (list 'eng 
n)))))
+             ;; Remove matched flags from the mode string.
              (setq fmt (replace-match "" t t fmt)))
-           (if (string-match "[tTU]" fmt)
-               (let ((ff (match-string 0 fmt)))
-                 (setq duration t numbers t
-                       duration-output-format
-                       (cond ((equal ff "T") nil)
-                             ((equal ff "t") org-table-duration-custom-format)
-                             ((equal ff "U") 'hh:mm))
-                       fmt (replace-match "" t t fmt))))
-           (if (string-match "N" fmt)
-               (setq numbers t
-                     fmt (replace-match "" t t fmt)))
-           (if (string-match "L" fmt)
-               (setq literal t
-                     fmt (replace-match "" t t fmt)))
-           (if (string-match "E" fmt)
-               (setq keep-empty t
-                     fmt (replace-match "" t t fmt)))
-           (while (string-match "[DRFS]" fmt)
-             (setq org-tbl-calc-modes
-                   (org-table--set-calc-mode (match-string 0 fmt)))
+           (while (string-match "\\([tTUNLEDRFSu]\\)" fmt)
+             (let ((c (string-to-char (match-string 1 fmt))))
+               (cl-case c
+                 (?t (setq duration t numbers t
+                            duration-output-format 
org-table-duration-custom-format))
+                 (?T (setq duration t numbers t duration-output-format nil))
+                 (?U (setq duration t numbers t duration-output-format 'hh:mm))
+                 (?N (setq numbers t))
+                 (?L (setq literal t))
+                 (?E (setq keep-empty t))
+                 (?D (setf (cl-getf calc-modes 'calc-angle-mode) 'deg))
+                 (?R (setf (cl-getf calc-modes 'calc-angle-mode) 'rad))
+                 (?F (setf (cl-getf calc-modes 'calc-prefer-frac) t))
+                 (?S (setf (cl-getf calc-modes 'calc-symbolic-mode) t))
+                 (?u (setf (cl-getf calc-modes 'calc-simplify-mode) 'units))))
+             ;; Remove matched flags from the mode string.
              (setq fmt (replace-match "" t t fmt)))
            (unless (string-match "\\S-" fmt)
              (setq fmt nil))))
@@ -2589,17 +2570,17 @@ location of point."
        (setq form0 form)
        ;; Insert the references to fields in same row
        (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)
-               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)))
+         (let* ((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)))
+           (setq 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
@@ -2631,7 +2612,7 @@ location of point."
 
          (setq ev (if (and duration (string-match 
"^[0-9]+:[0-9]+\\(?::[0-9]+\\)?$" form))
                       form
-                    (calc-eval (cons form org-tbl-calc-modes)
+                    (calc-eval (cons form calc-modes)
                                (when (and (not keep-empty) numbers) 'num)))
                ev (if duration (org-table-time-seconds-to-string
                                 (if (string-match 
"^[0-9]+:[0-9]+\\(?::[0-9]+\\)?$" ev)
@@ -3287,7 +3268,7 @@ Parameters get priority."
     (org-defkey map "\C-c}"    'org-table-fedit-toggle-coordinates)
     map))
 
-(easy-menu-define org-table-fedit-menu org-table-fedit-map "Org Edit Formulas 
Menu"
+(easy-menu-define org-table-fedit-menu org-table-fedit-map "Org Edit Formulas 
Menu."
   '("Edit-Formulas"
     ["Finish and Install" org-table-fedit-finish t]
     ["Finish, Install, and Apply" (org-table-fedit-finish t) :keys "C-u C-c 
C-c"]
@@ -4686,18 +4667,18 @@ blank, and the content is appended to the field above."
            (save-excursion (goto-char start) (move-beginning-of-line 1))
            (save-excursion (org-forward-paragraph) (point)))
           (org-table-cut-region (region-beginning) (region-end))
-          (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))
+         (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))
         (org-table-align))
     ;; No region, split the current field at point.
     (unless (org-get-alist-option org-M-RET-may-split-line 'table)
@@ -5096,7 +5077,7 @@ When LOCAL is non-nil, show references for the table at 
point."
 (put 'orgtbl-mode :included t)
 (put 'orgtbl-mode :menu-tag "Org Table Mode")
 
-(easy-menu-define orgtbl-mode-menu orgtbl-mode-map "OrgTbl menu"
+(easy-menu-define orgtbl-mode-menu orgtbl-mode-map "OrgTbl menu."
   '("OrgTbl"
     ["Create or convert" org-table-create-or-convert-from-region
      :active (not (org-at-table-p)) :keys "C-c |" ]
@@ -5161,7 +5142,7 @@ When LOCAL is non-nil, show references for the table at 
point."
 ;;;###autoload
 (define-minor-mode orgtbl-mode
   "The Org mode table editor as a minor mode for use in other modes."
-  :lighter " OrgTbl" :keymap orgtbl-mode-map
+  :lighter " OrgTbl"
   (org-load-modules-maybe)
   (cond
    ((derived-mode-p 'org-mode)
@@ -5346,7 +5327,7 @@ With prefix arg, also recompute table."
 (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."
+conflicting binding to this key outside `orgtbl-mode'."
   (interactive "P")
   (let* (orgtbl-mode (cmd (key-binding "\C-c|")))
     (if cmd
@@ -5585,7 +5566,7 @@ First element has index 0, or I0 if given."
 
 ;;;###autoload
 (defun orgtbl-to-generic (table params)
-  "Convert the orgtbl-mode TABLE to some other format.
+  "Convert the `orgtbl-mode' TABLE to some other format.
 
 This generic routine can be used for many standard cases.
 
@@ -5972,12 +5953,12 @@ information."
 
 ;;;###autoload
 (defun orgtbl-to-tsv (table params)
-  "Convert the orgtbl-mode table to TAB separated material."
+  "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.
+  "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)
@@ -5985,7 +5966,7 @@ This does take care of the proper quoting of fields with 
comma or quotes."
 
 ;;;###autoload
 (defun orgtbl-to-latex (table params)
-  "Convert the orgtbl-mode TABLE to LaTeX.
+  "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.
@@ -6018,7 +5999,7 @@ supported.  It is also possible to use the following ones:
 
 ;;;###autoload
 (defun orgtbl-to-html (table params)
-  "Convert the orgtbl-mode TABLE to HTML.
+  "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.
@@ -6049,7 +6030,7 @@ supported.  It is also possible to use the following one:
 
 ;;;###autoload
 (defun orgtbl-to-texinfo (table params)
-  "Convert the orgtbl-mode TABLE to 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.
@@ -6080,7 +6061,7 @@ supported.  It is also possible to use the following one:
 
 ;;;###autoload
 (defun orgtbl-to-orgtbl (table params)
-  "Convert the orgtbl-mode TABLE into another orgtbl-mode table.
+  "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.
@@ -6095,7 +6076,7 @@ be set to provide ORGTBL directives for the generated 
table."
   (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
@@ -6109,7 +6090,7 @@ supported."
      (replace-regexp-in-string "|-" "+-" (buffer-substring 1 (buffer-size))))))
 
 (defun orgtbl-to-unicode (table params)
-  "Convert the orgtbl-mode TABLE into a table with unicode characters.
+  "Convert the `orgtbl-mode' TABLE into a table with unicode characters.
 
 TABLE is a list, each entry either the symbol `hline' for
 a horizontal separator line, or a list of fields for that line.
@@ -6121,7 +6102,7 @@ supported.  It is also possible to use the following ones:
 
   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.
+  https://gnuvola.org/software/j/aa2u/ascii-art-to-unicode.el.
 
 :narrow
 
@@ -6226,7 +6207,7 @@ which will prompt for the width."
 
 (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
+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)."
   ;; https://en.wikipedia.org/wiki/Block_Elements
@@ -6236,7 +6217,7 @@ extent the font allows)."
 
 (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
+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
diff --git a/lisp/org-tempo.el b/lisp/org-tempo.el
index 36b8614..c121b8e 100644
--- a/lisp/org-tempo.el
+++ b/lisp/org-tempo.el
@@ -65,7 +65,7 @@ just like `org-structure-template-alist'.  The tempo snippet
 \"<KEY\" will be expanded using the KEYWORD value.  For example
 \"<L\" at the beginning of a line is expanded to \"#+latex:\".
 
-Do not use \"I\" as a KEY, as it it reserved for expanding
+Do not use \"I\" as a KEY, as it is reserved for expanding
 \"#+include\"."
   :group 'org-tempo
   :type '(repeat (cons (string :tag "Key")
diff --git a/lisp/org-timer.el b/lisp/org-timer.el
index b6802fe..bfcea44 100644
--- a/lisp/org-timer.el
+++ b/lisp/org-timer.el
@@ -2,7 +2,7 @@
 
 ;; Copyright (C) 2008-2021 Free Software Foundation, Inc.
 
-;; Author: Carsten Dominik <carsten at orgmode dot org>
+;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: https://orgmode.org
 ;;
@@ -366,7 +366,7 @@ VALUE can be `on', `off', or `paused'."
        (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))))))
+            (run-with-timer 1 1 #'org-timer-update-mode-line))))))
 
 (defun org-timer-update-mode-line ()
   "Update the timer time in the mode line."
@@ -400,16 +400,16 @@ 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 in minutes.
 
-Called with a `C-u' prefix arguments, use `org-timer-default-timer'
+Called with a \\[universal-argument] 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'
+With two \\[universal-argument] prefix arguments, use `org-timer-default-timer'
 without prompting the user for a duration and automatically
 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."
+using three \\[universal-argument] prefix arguments."
   (interactive "P")
   (when (and org-timer-start-time
             (not org-timer-countdown-timer))
@@ -456,14 +456,15 @@ using three `C-u' prefix arguments."
   "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)))
+  (let ((msg (format "%s: time out" title))
+        (sound org-clock-sound))
     (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)))))
+     secs nil (lambda ()
+               (setq org-timer-countdown-timer nil
+                     org-timer-start-time nil)
+               (org-notify msg sound)
+               (org-timer-set-mode-line 'off)
+               (run-hooks 'org-timer-done-hook)))))
 
 (defun org-timer--get-timer-title ()
   "Construct timer title.
diff --git a/lisp/org.el b/lisp/org.el
index 65f63c1..2ec6566 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -3,12 +3,13 @@
 ;; Carstens outline-mode for keeping track of everything.
 ;; Copyright (C) 2004-2021 Free Software Foundation, Inc.
 ;;
-;; Author: Carsten Dominik <carsten at orgmode dot org>
+;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 ;; Maintainer: Bastien Guerry <bzg@gnu.org>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: https://orgmode.org
+;; Package-Requires: ((emacs "25.1"))
 
-;; Version: 9.4.7
+;; Version: 9.5
 
 ;; This file is part of GNU Emacs.
 ;;
@@ -93,6 +94,7 @@
 (require 'org-compat)
 (require 'org-keys)
 (require 'ol)
+(require 'oc)
 (require 'org-table)
 
 ;; `org-outline-regexp' ought to be a defconst but is let-bound in
@@ -144,7 +146,6 @@ Stars are put in group 1 and the trimmed body in group 2.")
 (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-clocking-buffer "org-clock" ())
 (declare-function org-clocktable-shift "org-clock" (dir n))
 (declare-function org-columns-quit "org-colview" ())
 (declare-function org-columns-insert-dblock "org-colview" ())
@@ -196,7 +197,6 @@ Stars are put in group 1 and the trimmed body in group 2.")
 (declare-function org-toggle-archive-tag "org-archive" (&optional find-done))
 (declare-function org-update-radio-target-regexp "ol" ())
 
-(defvar ffap-url-regexp)
 (defvar org-element-paragraph-separate)
 (defvar org-indent-indentation-per-level)
 (defvar org-radio-target-regexp)
@@ -207,6 +207,8 @@ Stars are put in group 1 and the trimmed body in group 2.")
 ;; load languages based on value of `org-babel-load-languages'
 (defvar org-babel-load-languages)
 
+(defvar crm-separator)  ; dynamically scoped param
+
 ;;;###autoload
 (defun org-babel-do-load-languages (sym value)
   "Load the languages defined in `org-babel-load-languages'."
@@ -235,7 +237,11 @@ byte-compiled before it is loaded."
             tangled-file
             (file-attribute-modification-time
              (file-attributes (file-truename file))))
-      (org-babel-tangle-file file tangled-file "emacs-lisp\\|elisp"))
+      (org-babel-tangle-file file
+                             tangled-file
+                             (rx string-start
+                                 (or "emacs-lisp" "elisp")
+                                 string-end)))
     (if compile
        (progn
          (byte-compile-file tangled-file)
@@ -268,32 +274,25 @@ requirement."
                 (const :tag "Awk" awk)
                 (const :tag "C" C)
                 (const :tag "R" R)
-                (const :tag "Asymptote" asymptote)
-                (const :tag "Calc" calc)
+                 (const :tag "Calc" calc)
                 (const :tag "Clojure" clojure)
                 (const :tag "CSS" css)
                 (const :tag "Ditaa" ditaa)
                 (const :tag "Dot" dot)
-                (const :tag "Ebnf2ps" ebnf2ps)
-                (const :tag "Emacs Lisp" emacs-lisp)
+                 (const :tag "Emacs Lisp" emacs-lisp)
                 (const :tag "Forth" forth)
                 (const :tag "Fortran" fortran)
                 (const :tag "Gnuplot" gnuplot)
                 (const :tag "Haskell" haskell)
-                (const :tag "hledger" hledger)
-                (const :tag "IO" io)
-                (const :tag "J" J)
-                (const :tag "Java" java)
+                 (const :tag "Java" java)
                 (const :tag "Javascript" js)
                 (const :tag "LaTeX" latex)
-                (const :tag "Ledger" ledger)
-                (const :tag "Lilypond" lilypond)
+                 (const :tag "Lilypond" lilypond)
                 (const :tag "Lisp" lisp)
                 (const :tag "Makefile" makefile)
                 (const :tag "Maxima" maxima)
                 (const :tag "Matlab" matlab)
-                (const :tag "Mscgen" mscgen)
-                (const :tag "Ocaml" ocaml)
+                 (const :tag "Ocaml" ocaml)
                 (const :tag "Octave" octave)
                 (const :tag "Org" org)
                 (const :tag "Perl" perl)
@@ -306,11 +305,9 @@ requirement."
                 (const :tag "Scheme" scheme)
                 (const :tag "Screen" screen)
                 (const :tag "Shell Script" shell)
-                (const :tag "Shen" shen)
-                (const :tag "Sql" sql)
+                 (const :tag "Sql" sql)
                 (const :tag "Sqlite" sqlite)
-                (const :tag "Stan" stan)
-                (const :tag "Vala" vala))
+                (const :tag "Stan" stan))
                :value-type (boolean :tag "Activate" :value t)))
 
 ;;;; Customization variables
@@ -659,6 +656,10 @@ defined in org-duration.el.")
   :group 'org
   :type 'hook)
 
+(make-obsolete-variable
+ 'org-load-hook
+ "use `with-eval-after-load' instead." "9.5")
+
 (defcustom org-log-buffer-setup-hook nil
   "Hook that is run after an Org log buffer is created."
   :group 'org
@@ -685,15 +686,16 @@ defined in org-duration.el.")
     (org-load-modules-maybe 'force)
     (org-element-cache-reset 'all)))
 
-(defcustom org-modules '(ol-w3m ol-bbdb ol-bibtex ol-docview ol-gnus ol-info 
ol-irc ol-mhe ol-rmail ol-eww)
+(defcustom org-modules '(ol-doi ol-w3m ol-bbdb ol-bibtex ol-docview ol-gnus 
ol-info ol-irc ol-mhe ol-rmail ol-eww)
   "Modules that should always be loaded together with org.el.
 
-If a description starts with <C>, the file is not part of Emacs
-and loading it will require that you have downloaded and properly
-installed the Org mode distribution.
+If a description starts with <C>, the file is not part of Emacs and Org mode,
+so loading it will require that you have properly installed org-contrib
+package from NonGNU Emacs Lisp Package Archive
+http://elpa.nongnu.org/nongnu/org-contrib.html
 
 You can also use this system to load external packages (i.e. neither Org
-core modules, nor modules from the CONTRIB directory).  Just add symbols
+core modules, nor org-contrib modules).  Just add symbols
 to the end of the list.  If the package is called org-xyz.el, then you need
 to add the symbol `xyz', and the package must have a call to:
 
@@ -702,8 +704,7 @@ to add the symbol `xyz', and the package must have a call 
to:
 For export specific modules, see also `org-export-backends'."
   :group 'org
   :set 'org-set-modules
-  :version "26.1"
-  :package-version '(Org . "9.2")
+  :package-version '(Org . "9.5")
   :type
   '(set :greedy t
        (const :tag "   bbdb:              Links to BBDB entries" ol-bbdb)
@@ -711,6 +712,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 Docview buffers" ol-docview)
+        (const :tag "   doi:               Links to DOI references" ol-doi)
        (const :tag "   eww:               Store link to URL of Eww" ol-eww)
        (const :tag "   gnus:              Links to GNUS folders/messages" 
ol-gnus)
        (const :tag "   habit:             Track your consistency with habits" 
org-habit)
@@ -767,9 +769,10 @@ For export specific modules, see also 
`org-export-backends'."
 (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
-and loading it will require that you have downloaded and properly
-installed the Org mode distribution.
+If a description starts with <C>, the file is not part of Emacs and Org mode,
+so loading it will require that you have properly installed org-contrib
+package from NonGNU Emacs Lisp Package Archive
+http://elpa.nongnu.org/nongnu/org-contrib.html
 
 Unlike to `org-modules', libraries in this list will not be
 loaded along with Org, but only once the export framework is
@@ -945,6 +948,7 @@ the following lines anywhere in the buffer:
    #+STARTUP: fold              (or `overview', this is equivalent)
    #+STARTUP: nofold            (or `showall', this is equivalent)
    #+STARTUP: content
+   #+STARTUP: show<n>levels (<n> = 2..5)
    #+STARTUP: showeverything
 
 Set `org-agenda-inhibit-startup' to a non-nil value if you want
@@ -955,6 +959,10 @@ time."
   :type '(choice
          (const :tag "nofold: show all" nil)
          (const :tag "fold: overview" t)
+         (const :tag "fold: show two levels" show2levels)
+         (const :tag "fold: show three levels" show3levels)
+         (const :tag "fold: show four levels" show4evels)
+         (const :tag "fold: show five levels" show5levels)
          (const :tag "content: all headlines" content)
          (const :tag "show everything, even drawers" showeverything)))
 
@@ -1199,6 +1207,8 @@ Allowed visibility spans are
   ancestors      show current headline and its direct ancestors; if
                  point is not on headline, also show entry
 
+  ancestors-full show current subtree and its direct ancestors
+
   lineage        show current headline, its direct ancestors and all
                  their children; if point is not on headline, also show
                  entry and first child
@@ -1240,6 +1250,7 @@ more context."
                           (const minimal)
                           (const local)
                           (const ancestors)
+                           (const ancestors-full)
                           (const lineage)
                           (const tree)
                           (const canonical))))))
@@ -1580,14 +1591,13 @@ lines to the buffer:
   :group 'org-appearance
   :type 'boolean)
 
-(defcustom org-adapt-indentation t
+(defcustom org-adapt-indentation nil
   "Non-nil means adapt indentation to outline node level.
 
-When this variable is set to t, Org assumes that you write
-outlines by indenting text in each node to align with the
-headline (after the stars).
+When set to t, Org assumes that you write outlines by indenting
+text in each node to align with the headline, after the stars.
 
-When this variable is set to `headline-data', only adapt the
+When this variable is set to `headline-data', Org only adapts the
 indentation of the data lines right below the headline, such as
 planning/clock lines and property/logbook drawers.
 
@@ -1851,7 +1861,7 @@ 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
           <bbdb:Carsten Dominik>.
-plain     Plain links in normal text, no whitespace, like http://google.com.
+plain     Plain links in normal text, no whitespace, like https://gnu.org.
 radio     Text that is matched by a radio target, see manual for details.
 tag       Tag settings in a headline (link to tag search).
 date      Time stamps (link to calendar).
@@ -2442,8 +2452,20 @@ set a priority."
 
 (defcustom org-priority-highest ?A
   "The highest priority of TODO items.
+
 A character like ?A, ?B, etc., or a numeric value like 1, 2, etc.
-Must be smaller than `org-priority-lowest'."
+
+The default is the character ?A, which is 65 as a numeric value.
+
+If you set `org-priority-highest' to a numeric value inferior to
+65, Org assumes you want to use digits for the priority cookie.
+If you set it to >=65, Org assumes you want to use alphabetical
+characters.
+
+In both cases, the value of `org-priority-highest' must be
+smaller than `org-priority-lowest': for example, if \"A\" is the
+highest priority, it is smaller than the lowest \"C\" priority:
+65 < 67."
   :group 'org-priorities
   :type '(choice
          (character :tag "Character")
@@ -2452,8 +2474,20 @@ Must be smaller than `org-priority-lowest'."
 (defvaralias 'org-lowest-priority 'org-priority-lowest)
 (defcustom org-priority-lowest ?C
   "The lowest priority of TODO items.
-A character like ?A, ?B, etc., or a numeric value like 1, 2, etc.
-Must be higher than `org-priority-highest'."
+
+A character like ?C, ?B, etc., or a numeric value like 9, 8, etc.
+
+The default is the character ?C, which is 67 as a numeric value.
+
+If you set `org-priority-lowest' to a numeric value inferior to
+65, Org assumes you want to use digits for the priority cookie.
+If you set it to >=65, Org assumes you want to use alphabetical
+characters.
+
+In both cases, the value of `org-priority-lowest' must be greater
+than `org-priority-highest': for example, if \"C\" is the lowest
+priority, it is greater than the highest \"A\" priority: 67 >
+65."
   :group 'org-priorities
   :type '(choice
          (character :tag "Character")
@@ -3118,7 +3152,7 @@ it in the document property drawer.  For example:
 :CATEGORY: ELisp
 :END:
 
-Other ways to define it is as an emacs file variable, for example
+Other ways to define it is as an Emacs file variable, for example
 
 #   -*- mode: org; org-category: \"ELisp\"
 
@@ -3290,7 +3324,7 @@ All available processes and theirs documents can be found 
in
      :image-output-type "png"
      :image-size-adjust (1.0 . 1.0)
      :latex-compiler ("latex -interaction nonstopmode -output-directory %o %f")
-     :image-converter ("dvipng -D %D -T tight -o %O %f"))
+     :image-converter ("dvipng -D %D -T tight -bg Transparent -o %O %f"))
     (dvisvgm
      :programs ("latex" "dvisvgm")
      :description "dvi > svg"
@@ -3433,13 +3467,11 @@ header, or they will be appended."
   '(("AUTO" "inputenc"  t ("pdflatex"))
     ("T1"   "fontenc"   t ("pdflatex"))
     (""     "graphicx"  t)
-    (""     "grffile"   t)
     (""     "longtable" nil)
     (""     "wrapfig"   nil)
     (""     "rotating"  nil)
     ("normalem" "ulem"  t)
     (""     "amsmath"   t)
-    (""     "textcomp"  t)
     (""     "amssymb"   t)
     (""     "capt-of"   nil)
     (""     "hyperref"  nil))
@@ -3453,15 +3485,14 @@ Org mode to function properly:
 
 - inputenc, fontenc:  for basic font and character selection
 - graphicx: for including images
-- grffile: allow periods and spaces in graphics file names
 - longtable: For multipage tables
 - 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, 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.
+- amssymb: for various symbols used for interpreting the entities
+  in `org-entities'.  You can skip some of this package if you don't
+  use any of the symbols.
 - capt-of: for captions outside of floats
 - hyperref: for cross references
 
@@ -3575,10 +3606,11 @@ lines to the buffer:
 For example, a value \\='(title) for this list makes the document's title
 appear in the buffer without the initial \"#+TITLE:\" part."
   :group 'org-appearance
-  :version "24.1"
+  :package-version '(Org . "9.5")
   :type '(set (const :tag "#+AUTHOR" author)
              (const :tag "#+DATE" date)
              (const :tag "#+EMAIL" email)
+             (const :tag "#+SUBTITLE" subtitle)
              (const :tag "#+TITLE" title)))
 
 (defcustom org-custom-properties nil
@@ -3827,10 +3859,11 @@ This is needed for font-lock setup.")
   "Marker recording the last clock-in, but the headline position.")
 (defvar org-clock-heading ""
   "The heading of the current clock entry.")
-(defun org-clock-is-active ()
+(defun org-clocking-buffer ()
   "Return the buffer where the clock is currently running.
 Return nil if no clock is running."
   (marker-buffer org-clock-marker))
+(defalias 'org-clock-is-active #'org-clocking-buffer)
 
 (defun org-check-running-clock ()
   "Check if the current buffer contains the running clock.
@@ -4117,7 +4150,8 @@ groups carry important information:
   "Regular expression to match a timestamp time or time range.
 After a match, the following groups carry important information:
 0  the full match
-1  date plus weekday, for back referencing to make sure both times are on the 
same day
+1  date plus weekday, for back referencing to make sure
+     both times are on the same day
 2  the first time, range or not
 4  the second time, if it is a range.")
 
@@ -4126,6 +4160,10 @@ After a match, the following groups carry important 
information:
     ("overview" org-startup-folded t)
     ("nofold" org-startup-folded nil)
     ("showall" org-startup-folded nil)
+    ("show2levels" org-startup-folded show2levels)
+    ("show3levels" org-startup-folded show3levels)
+    ("show4levels" org-startup-folded show4levels)
+    ("show5levels" org-startup-folded show5levels)
     ("showeverything" org-startup-folded showeverything)
     ("content" org-startup-folded content)
     ("indent" org-startup-indented t)
@@ -4502,7 +4540,7 @@ directory."
                 (when (and (org-string-nw-p value)
                            (not buffer-read-only)) ;FIXME: bug in Gnus?
                   (let* ((uri (org-strip-quotes value))
-                         (uri-is-url (org-file-url-p uri))
+                         (uri-is-url (org-url-p uri))
                          (uri (if uri-is-url
                                   uri
                                 (expand-file-name uri))))
@@ -4632,11 +4670,6 @@ This is the cache of file URLs read using 
`org-file-contents'.")
   "Reset the cache of files downloaded by `org-file-contents'."
   (clrhash org--file-cache))
 
-(defun org-file-url-p (file)
-  "Non-nil if FILE is a URL."
-  (require 'ffap)
-  (string-match-p ffap-url-regexp file))
-
 (defun org-file-contents (file &optional noerror nocache)
   "Return the contents of FILE, as a string.
 
@@ -4651,7 +4684,7 @@ from file or URL, and return nil.
 
 If NOCACHE is non-nil, do a fresh fetch of FILE even if cached version
 is available.  This option applies only if FILE is a URL."
-  (let* ((is-url (org-file-url-p file))
+  (let* ((is-url (org-url-p file))
          (cache (and is-url
                      (not nocache)
                      (gethash file org--file-cache))))
@@ -4761,8 +4794,8 @@ This is for getting out of special buffers like capture.")
 ;; Other stuff we need.
 (require 'time-date)
 (unless (fboundp 'time-subtract) (defalias 'time-subtract 'subtract-time))
-(require 'easymenu)
-(require 'overlay)
+(when (< emacs-major-version 28)  ; preloaded in Emacs 28
+  (require 'easymenu))
 
 (require 'org-entities)
 (require 'org-faces)
@@ -4943,7 +4976,8 @@ The following commands are available:
                   ("9.1" . "26.1")
                   ("9.2" . "27.1")
                   ("9.3" . "27.1")
-                  ("9.4" . "27.2")))
+                  ("9.4" . "27.2")
+                  ("9.5" . "28.1")))
 
 (defvar org-mode-transpose-word-syntax-table
   (let ((st (make-syntax-table text-mode-syntax-table)))
@@ -5160,30 +5194,31 @@ This includes angle, plain, and bracket links."
                 (link (org-element-property :raw-link link-object))
                 (type (org-element-property :type link-object))
                 (path (org-element-property :path link-object))
+                 (face-property (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)))
                 (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)))
+                 (list '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)
+               (progn
+                  (add-face-text-property start end face-property)
+                 (add-text-properties start end properties))
              ;; Handle invisible parts in bracket links.
              (remove-text-properties start end '(invisible nil))
              (let ((hidden
@@ -5192,6 +5227,7 @@ This includes angle, plain, and bracket links."
                                    'org-link))
                             properties)))
                (add-text-properties start visible-start hidden)
+                (add-face-text-property start end face-property)
                (add-text-properties visible-start visible-end properties)
                (add-text-properties visible-end end hidden)
                (org-rear-nonsticky-at visible-start)
@@ -5321,7 +5357,7 @@ by a #."
                 (min (point-max) end-of-endline))
               '(face org-block-end-line)))
            t))
-        ((member dc1 '("+title:" "+author:" "+email:" "+date:"))
+        ((member dc1 '("+title:" "+subtitle:" "+author:" "+email:" "+date:"))
          (org-remove-flyspell-overlays-in
           (match-beginning 0)
           (if (equal "+title:" dc1) (match-end 2) (match-end 0)))
@@ -5394,22 +5430,26 @@ by a #."
          t)))))
 
 (defun org-fontify-extend-region (beg end _old-len)
-  (let ((begin-re "\\(\\\\\\[\\|\\(#\\+begin_\\|\\\\begin{\\)\\S-+\\)")
+  (let ((end (if (progn (goto-char end) (looking-at-p "^[*#]"))
+                 (1+ end) end))
+        (begin-re "\\(\\\\\\[\\|\\(#\\+begin_\\|\\\\begin{\\)\\S-+\\)")
        (end-re "\\(\\\\\\]\\|\\(#\\+end_\\|\\\\end{\\)\\S-+\\)")
-       (extend (lambda (r1 r2 dir)
-                 (let ((re (replace-regexp-in-string "\\(begin\\|end\\)" r1
-                            (replace-regexp-in-string "[][]" r2
-                             (match-string-no-properties 0)))))
-                   (re-search-forward (regexp-quote re) nil t dir)))))
+       (extend
+         (lambda (r1 r2 dir)
+          (let ((re (replace-regexp-in-string
+                      "\\(begin\\|end\\)" r1
+                     (replace-regexp-in-string
+                       "[][]" r2
+                      (match-string-no-properties 0)))))
+            (re-search-forward (regexp-quote re) nil t dir)))))
+    (goto-char beg)
+    (back-to-indentation)
     (save-match-data
-      (save-excursion
-       (goto-char beg)
-       (back-to-indentation)
-       (cond ((looking-at end-re)
-              (cons (or (funcall extend "begin" "[" -1) beg) end))
-             ((looking-at begin-re)
-              (cons beg (or (funcall extend "end" "]" 1) end)))
-             (t (cons beg end)))))))
+      (cond ((looking-at end-re)
+            (cons (or (funcall extend "begin" "[" -1) beg) end))
+           ((looking-at begin-re)
+            (cons beg (or (funcall extend "end" "]" 1) end)))
+           (t (cons beg end))))))
 
 (defun org-activate-footnote-links (limit)
   "Add text properties for footnotes."
@@ -5540,7 +5580,7 @@ highlighting was done, nil otherwise."
 
 (defun org-restart-font-lock ()
   "Restart `font-lock-mode', to force refontification."
-  (when (and (boundp 'font-lock-mode) font-lock-mode)
+  (when font-lock-mode
     (font-lock-mode -1)
     (font-lock-mode 1)))
 
@@ -5620,111 +5660,116 @@ 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-highlight-links)
-        (org-font-lock-extra-keywords
-         (list
-          ;; Call the hook
-          '(org-font-lock-hook)
-          ;; Headlines
-          `(,(if org-fontify-whole-heading-line
-                 "^\\(\\**\\)\\(\\* \\)\\(.*\n?\\)"
-               "^\\(\\**\\)\\(\\* \\)\\(.*\\)")
-            (1 (org-get-level-face 1))
-            (2 (org-get-level-face 2))
-            (3 (org-get-level-face 3)))
-          ;; Table lines
-          '("^[ \t]*\\(\\(|\\|\\+-[-+]\\).*\\S-\\)"
-            (1 'org-table t))
-          ;; Table internals
-          '("^[ \t]*|\\(?:.*?|\\)? *\\(:?=[^|\n]*\\)" (1 'org-formula t))
-          '("^[ \t]*| *\\([#*]\\) *|" (1 'org-formula t))
-          '("^[ \t]*|\\( *\\([$!_^/]\\) *|.*\\)|" (1 'org-formula t))
-          '("| *\\(<[lrc]?[0-9]*>\\)" (1 'org-formula t))
-          ;; Properties
-          (list org-property-re
-                '(1 'org-special-keyword t)
-                '(3 'org-property-value t))
-          ;; Drawers
-          '(org-fontify-drawers)
-          ;; 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-radio-target-regexp '(0 'org-target t))
-          (list org-target-regexp '(0 'org-target t))
-          ;; Diary sexps.
-          '("^&?%%(.*\\|<%%([^>\n]*?>" (0 'org-sexp-date t))
-          ;; Macro
-          '(org-fontify-macros)
-          ;; TODO keyword
-          (list (format org-heading-keyword-regexp-format
-                        org-todo-regexp)
-                '(2 (org-get-todo-face 2) t))
-          ;; TODO
-          (when org-fontify-todo-headline
-            (list (format org-heading-keyword-regexp-format
-                          (concat
-                           "\\(?:"
-                           (mapconcat 'regexp-quote org-not-done-keywords 
"\\|")
-                           "\\)"))
-                  '(2 'org-headline-todo t)))
-          ;; DONE
-          (when org-fontify-done-headline
-            (list (format org-heading-keyword-regexp-format
-                          (concat
-                           "\\(?:"
-                           (mapconcat 'regexp-quote org-done-keywords "\\|")
-                           "\\)"))
-                  '(2 'org-headline-done t)))
-          ;; Priorities
-          '(org-font-lock-add-priority-faces)
-          ;; Tags
-          '(org-font-lock-add-tag-faces)
-          ;; Tags groups
-          (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
-          (when em '(org-do-emphasis-faces))
-          ;; Checkboxes
-          '("^[ \t]*\\(?:[-+*]\\|[0-9]+[.)]\\)[ 
\t]+\\(?:\\[@\\(?:start:\\)?[0-9]+\\][ \t]*\\)?\\(\\[[- X]\\]\\)"
-            1 'org-checkbox prepend)
-          (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]+::\\)\\([ 
\t]+\\|$\\)"
-            1 'org-list-dt prepend)
-          ;; ARCHIVEd headings
-          (list (concat
-                 org-outline-regexp-bol
-                 "\\(.*:" org-archive-tag ":.*\\)")
-                '(1 'org-archived prepend))
-          ;; Specials
-          '(org-do-latex-and-related)
-          '(org-fontify-entities)
-          '(org-raise-scripts)
-          ;; Code
-          '(org-activate-code (1 'org-code t))
-          ;; COMMENT
-          (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))))
+  (let ((org-font-lock-extra-keywords
+        (list
+         ;; Call the hook
+         '(org-font-lock-hook)
+         ;; Headlines
+         `(,(if org-fontify-whole-heading-line
+                "^\\(\\**\\)\\(\\* \\)\\(.*\n?\\)"
+              "^\\(\\**\\)\\(\\* \\)\\(.*\\)")
+           (1 (org-get-level-face 1))
+           (2 (org-get-level-face 2))
+           (3 (org-get-level-face 3)))
+         ;; Table lines
+         '("^[ \t]*\\(\\(|\\|\\+-[-+]\\).*\\S-\\)"
+           (1 'org-table t))
+         ;; Table internals
+         '("^[ \t]*|\\(?:.*?|\\)? *\\(:?=[^|\n]*\\)" (1 'org-formula t))
+         '("^[ \t]*| *\\([#*]\\) *|" (1 'org-formula t))
+         '("^[ \t]*|\\( *\\([$!_^/]\\) *|.*\\)|" (1 'org-formula t))
+         '("| *\\(<[lrc]?[0-9]*>\\)" (1 'org-formula t))
+         ;; Properties
+         (list org-property-re
+               '(1 'org-special-keyword t)
+               '(3 'org-property-value t))
+         ;; Drawers
+         '(org-fontify-drawers)
+         ;; Link related fontification.
+         '(org-activate-links)
+         (when (memq 'tag org-highlight-links) '(org-activate-tags (1 'org-tag 
prepend)))
+         (when (memq 'radio org-highlight-links) '(org-activate-target-links 
(1 'org-link t)))
+         (when (memq 'date org-highlight-links) '(org-activate-dates (0 
'org-date t)))
+         (when (memq 'footnote org-highlight-links) 
'(org-activate-footnote-links))
+          ;; Targets.
+          (list org-radio-target-regexp '(0 'org-target t))
+         (list org-target-regexp '(0 'org-target t))
+         ;; Diary sexps.
+         '("^&?%%(.*\\|<%%([^>\n]*?>" (0 'org-sexp-date t))
+         ;; Macro
+         '(org-fontify-macros)
+         ;; TODO keyword
+         (list (format org-heading-keyword-regexp-format
+                       org-todo-regexp)
+               '(2 (org-get-todo-face 2) prepend))
+         ;; TODO
+         (when org-fontify-todo-headline
+           (list (format org-heading-keyword-regexp-format
+                         (concat
+                          "\\(?:"
+                          (mapconcat 'regexp-quote org-not-done-keywords "\\|")
+                          "\\)"))
+                 '(2 'org-headline-todo prepend)))
+         ;; DONE
+         (when org-fontify-done-headline
+           (list (format org-heading-keyword-regexp-format
+                         (concat
+                          "\\(?:"
+                          (mapconcat 'regexp-quote org-done-keywords "\\|")
+                          "\\)"))
+                 '(2 'org-headline-done prepend)))
+         ;; Priorities
+         '(org-font-lock-add-priority-faces)
+         ;; Tags
+         '(org-font-lock-add-tag-faces)
+         ;; Tags groups
+         (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
+         (when org-fontify-emphasized-text '(org-do-emphasis-faces))
+         ;; Checkboxes
+         '("^[ \t]*\\(?:[-+*]\\|[0-9]+[.)]\\)[ 
\t]+\\(?:\\[@\\(?:start:\\)?[0-9]+\\][ \t]*\\)?\\(\\[[- X]\\]\\)"
+           1 'org-checkbox prepend)
+         (when (cdr (assq 'checkbox org-list-automatic-rules))
+           '("\\[\\([0-9]*%\\)\\]\\|\\[\\([0-9]*\\)/\\([0-9]*\\)\\]"
+             (0 (org-get-checkbox-statistics-face) prepend)))
+         ;; Description list items
+          '("\\(?:^[ \t]*[-+]\\|^[ \t]+[*]\\)[ \t]+\\(.*?[ \t]+::\\)\\([ 
\t]+\\|$\\)"
+           1 'org-list-dt prepend)
+          ;; Inline export snippets
+          '("\\(@@\\)\\([a-z-]+:\\).*?\\(@@\\)"
+            (1 'font-lock-comment-face t)
+            (2 'org-tag t)
+            (3 'font-lock-comment-face t))
+         ;; ARCHIVEd headings
+         (list (concat
+                org-outline-regexp-bol
+                "\\(.*:" org-archive-tag ":.*\\)")
+               '(1 'org-archived prepend))
+         ;; Specials
+         '(org-do-latex-and-related)
+         '(org-fontify-entities)
+         '(org-raise-scripts)
+         ;; Code
+         '(org-activate-code (1 'org-code t))
+         ;; COMMENT
+         (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)
+          ;; Citations
+          '(org-cite-activate))))
     (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
@@ -5862,19 +5907,26 @@ If TAG is a number, get the corresponding match group."
 
 (defun org-font-lock-add-priority-faces (limit)
   "Add the special priority faces."
-  (while (re-search-forward org-priority-regexp limit t)
-    (add-text-properties
-     (match-beginning 1) (1+ (match-end 2))
-     (list 'face (org-get-priority-face (string-to-char (match-string 2)))
-          'font-lock-fontified t))))
+  (while (re-search-forward (concat "^\\*+" org-priority-regexp) limit t)
+    (let ((beg (match-beginning 1))
+         (end (1+ (match-end 2))))
+      (add-face-text-property
+       beg end
+       (org-get-priority-face (string-to-char (match-string 2))))
+      (add-text-properties
+       beg end
+       (list 'font-lock-fontified t)))))
 
 (defun org-font-lock-add-tag-faces (limit)
   "Add the special tag faces."
   (when (and org-tag-faces org-tags-special-faces-re)
     (while (re-search-forward org-tags-special-faces-re limit t)
+      (add-face-text-property
+       (match-beginning 1)
+       (match-end 1)
+       (org-get-tag-face 1))
       (add-text-properties (match-beginning 1) (match-end 1)
-                          (list 'face (org-get-tag-face 1)
-                                'font-lock-fontified t))
+                          (list 'font-lock-fontified t))
       (backward-char 1))))
 
 (defun org-unfontify-region (beg end &optional _maybe_loudly)
@@ -5948,8 +6000,9 @@ and subscripts."
   "Remove outline overlays that do not contain non-white stuff."
   (dolist (o (overlays-at pos))
     (and (eq 'outline (overlay-get o 'invisible))
-        (not (string-match-p "\\S-" (buffer-substring (overlay-start o)
-                                                    (overlay-end o))))
+        (not (string-match-p
+               "\\S-" (buffer-substring (overlay-start o)
+                                       (overlay-end o))))
         (delete-overlay o))))
 
 (defun org-show-empty-lines-in-parent ()
@@ -6158,9 +6211,38 @@ Return a non-nil value when toggling is successful."
 
 (defun org-hide-drawer-all ()
   "Fold all drawers in the current buffer."
+  (let ((begin (point-min))
+       (end (point-max)))
+    (org--hide-drawers begin end)))
+
+(defun org-cycle-hide-drawers (state)
+  "Re-hide all drawers after a visibility state change.
+STATE should be one of the symbols listed in the docstring of
+`org-cycle-hook'."
+  (when (derived-mode-p 'org-mode)
+    (cond ((not (memq state '(overview folded contents)))
+          (let* ((global? (eq state 'all))
+                 (beg (if global? (point-min) (line-beginning-position)))
+                 (end (cond (global? (point-max))
+                            ((eq state 'children) (org-entry-end-position))
+                            (t (save-excursion (org-end-of-subtree t t))))))
+            (org--hide-drawers beg end)))
+         ((memq state '(overview contents))
+          ;; Hide drawers before first heading.
+          (let ((beg (point-min))
+                (end (save-excursion
+                       (goto-char (point-min))
+                       (if (org-before-first-heading-p)
+                           (org-entry-end-position)
+                         (point-min)))))
+            (when (< beg end)
+              (org--hide-drawers beg end)))))))
+
+(defun org--hide-drawers (begin end)
+  "Hide all drawers between BEGIN and END."
   (save-excursion
-    (goto-char (point-min))
-    (while (re-search-forward org-drawer-regexp nil t)
+    (goto-char begin)
+    (while (re-search-forward org-drawer-regexp end t)
       (let* ((pair (get-char-property-and-overlay (line-beginning-position)
                                                  'invisible))
             (o (cdr-safe pair)))
@@ -6177,32 +6259,6 @@ Return a non-nil value when toggling is successful."
                 ;; `org-drawer-regexp'.
                 (goto-char (org-element-property :end drawer)))))))))))
 
-(defun org-cycle-hide-drawers (state)
-  "Re-hide all drawers after a visibility state change.
-STATE should be one of the symbols listed in the docstring of
-`org-cycle-hook'."
-  (when (and (derived-mode-p 'org-mode)
-            (not (memq state '(overview folded contents))))
-    (let* ((global? (eq state 'all))
-          (beg (if global? (point-min) (line-beginning-position)))
-          (end (cond (global? (point-max))
-                     ((eq state 'children) (org-entry-end-position))
-                     (t (save-excursion (org-end-of-subtree t t))))))
-      (save-excursion
-       (goto-char beg)
-       (while (re-search-forward org-drawer-regexp end t)
-         (pcase (get-char-property-and-overlay (point) 'invisible)
-           ;; Do not fold already folded drawers.
-           (`(outline . ,o) (goto-char (overlay-end o)))
-           (_
-            (let ((drawer (org-element-at-point)))
-              (when (memq (org-element-type drawer) '(drawer property-drawer))
-                (org-hide-drawer-toggle t nil 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)))))))))))
-
 ;;;; Visibility cycling
 
 (defvar-local org-cycle-global-status nil)
@@ -6561,6 +6617,14 @@ With a numeric prefix, show all headlines up to that 
level."
     (org-overview))
    ((eq org-startup-folded 'content)
     (org-content))
+   ((eq org-startup-folded 'show2levels)
+    (org-content 2))
+   ((eq org-startup-folded 'show3levels)
+    (org-content 3))
+   ((eq org-startup-folded 'show4levels)
+    (org-content 4))
+   ((eq org-startup-folded 'show5levels)
+    (org-content 5))
    ((or (eq org-startup-folded 'showeverything)
        (eq org-startup-folded nil))
     (org-show-all)))
@@ -6660,8 +6724,8 @@ This function is the default value of the hook 
`org-cycle-hook'."
   ;; First, find a reasonable region to look at:
   ;; Start two siblings above, end three below
   (let* ((beg (save-excursion
-               (and (org-get-last-sibling)
-                    (org-get-last-sibling))
+               (and (org-get-previous-sibling)
+                    (org-get-previous-sibling))
                (point)))
         (end (save-excursion
                (and (org-get-next-sibling)
@@ -6743,9 +6807,9 @@ be shown."
 
 (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."
+DETAIL is either nil, `minimal', `local', `ancestors',
+`ancestors-full', `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)))
@@ -6760,14 +6824,16 @@ information."
       (org-with-limited-levels
        (cl-case detail
         ((tree canonical t) (org-show-children))
-        ((nil minimal ancestors))
+        ((nil minimal ancestors ancestors-full))
         (t (save-excursion
              (outline-next-heading)
              (org-flag-heading nil)))))))
+  ;; Show whole subtree.
+  (when (eq detail 'ancestors-full) (org-show-subtree))
   ;; Show all siblings.
   (when (eq detail 'lineage) (org-show-siblings))
   ;; Show ancestors, possibly with their children.
-  (when (memq detail '(ancestors lineage tree canonical t))
+  (when (memq detail '(ancestors ancestors-full lineage tree canonical t))
     (save-excursion
       (while (org-up-heading-safe)
        (org-flag-heading nil)
@@ -6970,7 +7036,9 @@ unconditionally."
                           (org-before-first-heading-p)))
         (insert "\n")
         (backward-char))
-      (unless level (backward-char))
+      (when (and (not level) (not (eobp)) (not (bobp)))
+        (when (org-at-heading-p) (insert "\n"))
+        (backward-char))
       (unless (and blank? (org-previous-line-empty-p))
        (org-N-empty-lines-before-current (if blank? 1 0)))
       (insert stars " ")
@@ -7549,7 +7617,7 @@ case."
   (setq arg (prefix-numeric-value arg))
   (org-preserve-local-variables
    (let ((movfunc (if (> arg 0) 'org-get-next-sibling
-                   'org-get-last-sibling))
+                   'org-get-previous-sibling))
         (ins-point (make-marker))
         (cnt (abs arg))
         (col (current-column))
@@ -7904,7 +7972,7 @@ with the original repeater."
                "")))                   ;No time shift
         (doshift
          (and (org-string-nw-p shift)
-              (or (string-match "\\`[ \t]*\\([+-]?[0-9]+\\)\\([dwmy]\\)[ 
\t]*\\'"
+              (or (string-match "\\`[ \t]*\\([+-]?[0-9]+\\)\\([hdwmy]\\)[ 
\t]*\\'"
                                 shift)
                   (user-error "Invalid shift specification %s" shift)))))
     (goto-char end-of-tree)
@@ -7914,6 +7982,7 @@ with the original repeater."
           (shift-n (and doshift (string-to-number (match-string 1 shift))))
           (shift-what (pcase (and doshift (match-string 2 shift))
                         (`nil nil)
+                        ("h" 'hour)
                         ("d" 'day)
                         ("w" (setq shift-n (* 7 shift-n)) 'day)
                         ("m" 'month)
@@ -8274,7 +8343,7 @@ function is being called interactively."
             ;; The clock marker is lost when using `sort-subr'; mark
             ;; the clock with temporary `:org-clock-marker-backup'
             ;; text property.
-            (when (and (eq (org-clock-is-active) (current-buffer))
+            (when (and (eq (org-clocking-buffer) (current-buffer))
                        (<= start (marker-position org-clock-marker))
                        (>= end (marker-position org-clock-marker)))
               (with-silent-modifications
@@ -8788,7 +8857,7 @@ If the file does not exist, throw an error."
       (save-window-excursion
        (message "Running %s...done" cmd)
         ;; Handlers such as "gio open" and kde-open5 start viewer in background
-        ;; and exit immediately.  Use pipe connnection type instead of pty to
+        ;; and exit immediately.  Use pipe connection type instead of pty to
         ;; avoid killing children processes with SIGHUP when temporary terminal
         ;; session is finished.
         ;;
@@ -8893,9 +8962,10 @@ a link."
            ;; closest one.
            (org-element-lineage
             (org-element-context)
-            '(clock comment comment-block footnote-definition
-                    footnote-reference headline inline-src-block inlinetask
-                    keyword link node-property planning src-block timestamp)
+            '(citation citation-reference clock comment comment-block
+                        footnote-definition footnote-reference headline
+                        inline-src-block inlinetask keyword link node-property
+                        planning src-block timestamp)
             t))
           (type (org-element-type context))
           (value (org-element-property :value context)))
@@ -8906,7 +8976,7 @@ a link."
        ((memq type '(comment comment-block node-property keyword))
        (call-interactively #'org-open-at-point-global))
        ;; On a headline or an inlinetask, but not on a timestamp,
-       ;; a link, a footnote reference.
+       ;; a link, a footnote reference or a citation.
        ((memq type '(headline inlinetask))
        (org-match-line org-complex-heading-regexp)
        (let ((tags-beg (match-beginning 5))
@@ -8969,6 +9039,7 @@ a link."
        ((eq type 'inline-src-block) (org-babel-open-src-block-result))
        ((eq type 'timestamp) (org-follow-timestamp-link))
        ((eq type 'link) (org-link-open context arg))
+       ((memq type '(citation citation-reference)) (org-cite-follow context 
arg))
        (t (user-error "No link found")))))
   (run-hook-with-args 'org-follow-link-hook))
 
@@ -9103,6 +9174,7 @@ or to another Org file, automatically push the old 
position onto the ring."
 
 (defvar org-agenda-buffer-tmp-name)
 (defvar org-agenda-start-on-weekday)
+(defvar org-agenda-buffer-name)
 (defun org-follow-timestamp-link ()
   "Open an agenda view for the time-stamp date/range at point."
   ;; Avoid changing the global value.
@@ -9490,7 +9562,7 @@ If an element cannot be made unique, an error is raised."
                                (mapcar (apply-partially #'concat (substring  
key 0 1))
                                        (split-string (substring key 1) "" 
t)))))))
        (if (or (not potential-key) (assoc potential-key menu-keys))
-           (user-error "Could not make unique key for %s." key)
+            (user-error "Could not make unique key for `%s'" key)
          (push (cons potential-key key) menu-keys))))
     (mapcar #'car
            (cl-sort menu-keys #'<
@@ -10021,7 +10093,8 @@ all statistics cookies in the buffer."
   (if all
       (progn
        (org-update-checkbox-count 'all)
-       (org-map-region 'org-update-parent-todo-statistics (point-min) 
(point-max)))
+       (org-map-region 'org-update-parent-todo-statistics
+                        (point-min) (point-max)))
     (if (not (org-at-heading-p))
        (org-update-checkbox-count)
       (let ((pos (point-marker))
@@ -10030,15 +10103,17 @@ all statistics cookies in the buffer."
        (if (not (org-at-heading-p))
            (org-update-checkbox-count)
          (setq l1 (org-outline-level))
-         (setq end (save-excursion
-                     (outline-next-heading)
-                     (when (org-at-heading-p) (setq l2 (org-outline-level)))
-                     (point)))
+         (setq end
+                (save-excursion
+                 (outline-next-heading)
+                 (when (org-at-heading-p) (setq l2 (org-outline-level)))
+                 (point)))
          (if (and (save-excursion
                     (re-search-forward
                      "^[ \t]*\\([-+*]\\|[0-9]+[.)]\\) \\[[- X]\\]" end t))
-                  (not (save-excursion (re-search-forward
-                                        ":COOKIE_DATA:.*\\<todo\\>" end t))))
+                  (not (save-excursion
+                          (re-search-forward
+                          ":COOKIE_DATA:.*\\<todo\\>" end t))))
              (org-update-checkbox-count)
            (if (and l2 (> l2 l1))
                (progn
@@ -10059,8 +10134,9 @@ all statistics cookies in the buffer."
 When `org-hierarchical-todo-statistics' is nil, statistics will cover
 the entire subtree and this will travel up the hierarchy and update
 statistics everywhere."
-  (let* ((prop (save-excursion (org-up-heading-safe)
-                              (org-entry-get nil "COOKIE_DATA" 'inherit)))
+  (let* ((prop (save-excursion
+                 (org-up-heading-safe)
+                (org-entry-get nil "COOKIE_DATA" 'inherit)))
         (recursive (or (not org-hierarchical-todo-statistics)
                        (and prop (string-match "\\<recursive\\>" prop))))
         (lim (or (and prop (marker-position org-entry-property-inherited-from))
@@ -10305,7 +10381,8 @@ prefer a state in the current sequence over on in 
another sequence."
   "Return the TODO keyword of the current subtree."
   (save-excursion
     (org-back-to-heading t)
-    (and (let ((case-fold-search nil)) (looking-at org-todo-line-regexp))
+    (and (let ((case-fold-search nil))
+           (looking-at org-todo-line-regexp))
         (match-end 2)
         (match-string 2))))
 
@@ -10343,18 +10420,19 @@ this function is called before first heading.
 When optional argument TIMESTAMP is a string, extract the
 repeater from there instead."
   (save-match-data
-    (cond (timestamp
-          (and (string-match org-repeat-re timestamp)
-               (match-string-no-properties 1 timestamp)))
-         ((org-before-first-heading-p) nil)
-         (t
-          (save-excursion
-            (org-back-to-heading t)
-            (let ((end (org-entry-end-position)))
-              (catch :repeat
-                (while (re-search-forward org-repeat-re end t)
-                  (when (save-match-data (org-at-timestamp-p 'agenda))
-                    (throw :repeat (match-string-no-properties 1)))))))))))
+    (cond
+     (timestamp
+      (and (string-match org-repeat-re timestamp)
+          (match-string-no-properties 1 timestamp)))
+     ((org-before-first-heading-p) nil)
+     (t
+      (save-excursion
+       (org-back-to-heading t)
+       (let ((end (org-entry-end-position)))
+         (catch :repeat
+           (while (re-search-forward org-repeat-re end t)
+             (when (save-match-data (org-at-timestamp-p 'agenda))
+               (throw :repeat (match-string-no-properties 1)))))))))))
 
 (defvar org-last-changed-timestamp)
 (defvar org-last-inserted-timestamp)
@@ -10362,6 +10440,7 @@ repeater from there instead."
 (defvar org-log-note-purpose)
 (defvar org-log-note-how nil)
 (defvar org-log-note-extra)
+(defvar org-log-setup nil)
 (defun org-auto-repeat-maybe (done-word)
   "Check if the current headline contains a repeated time-stamp.
 
@@ -10380,10 +10459,11 @@ This function is run automatically after each state 
change to a DONE state."
         (end (copy-marker (org-entry-end-position))))
     (when (and repeat (not (= 0 (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)
-                         (and (stringp org-todo-repeat-to-state)
-                              org-todo-repeat-to-state)
-                         (and org-todo-repeat-to-state org-last-state))))
+      (let ((to-state
+             (or (org-entry-get nil "REPEAT_TO_STATE" 'selective)
+                (and (stringp org-todo-repeat-to-state)
+                     org-todo-repeat-to-state)
+                (and org-todo-repeat-to-state org-last-state))))
        (org-todo (cond ((and to-state (member to-state org-todo-keywords-1))
                         to-state)
                        ((eq interpret 'type) org-last-state)
@@ -10838,7 +10918,8 @@ narrowing."
             (let ((beg (point)))
               (insert ":" drawer ":\n:END:\n")
               (org-indent-region beg (point))
-              (org-flag-region (line-end-position -1) (1- (point)) t 'outline))
+              (org-flag-region (line-end-position -1)
+                                (1- (point)) t 'outline))
             (end-of-line -1)))))
       (t
        (org-end-of-meta-data org-log-state-notes-insert-after-drawers)
@@ -10850,7 +10931,6 @@ narrowing."
         (forward-line)))))
    (if (bolp) (point) (line-beginning-position 2))))
 
-(defvar org-log-setup nil)
 (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.
@@ -10906,19 +10986,19 @@ EXTRA is additional text that will be inserted into 
the notes buffer."
     (insert (format "# Insert note for %s.
 # Finish with C-c C-c, or cancel with C-c C-k.\n\n"
                    (cl-case org-log-note-purpose
-                    (clock-out "stopped clock")
-                    (done  "closed todo item")
-                    (reschedule "rescheduling")
-                    (delschedule "no longer scheduled")
-                    (redeadline "changing deadline")
-                    (deldeadline "removing deadline")
-                    (refile "refiling")
-                    (note "this entry")
-                    (state
-                     (format "state change from \"%s\" to \"%s\""
-                             (or org-log-note-previous-state "")
-                             (or org-log-note-state "")))
-                    (t (error "This should not happen")))))
+                     (clock-out "stopped clock")
+                     (done  "closed todo item")
+                     (reschedule "rescheduling")
+                     (delschedule "no longer scheduled")
+                     (redeadline "changing deadline")
+                     (deldeadline "removing deadline")
+                     (refile "refiling")
+                     (note "this entry")
+                     (state
+                      (format "state change from \"%s\" to \"%s\""
+                              (or org-log-note-previous-state "")
+                              (or org-log-note-state "")))
+                     (t (error "This should not happen")))))
     (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)))
@@ -11241,14 +11321,17 @@ or a character."
            (setq
             new
             (if nump
-                (string-to-number
-                 (read-string (format "Priority %s-%s, SPC to remove: "
-                                      (number-to-string org-priority-highest)
-                                      (number-to-string org-priority-lowest))))
+                 (let ((msg (format "Priority %s-%s, SPC to remove: "
+                                   (number-to-string org-priority-highest)
+                                   (number-to-string org-priority-lowest))))
+                   (if (< 9 org-priority-lowest)
+                      (string-to-number (read-string msg))
+                     (message msg)
+                     (string-to-number (char-to-string 
(read-char-exclusive)))))
               (progn (message "Priority %c-%c, SPC to remove: "
-                                org-priority-highest org-priority-lowest)
-                       (save-match-data
-                         (setq new (read-char-exclusive)))))))
+                              org-priority-highest org-priority-lowest)
+                     (save-match-data
+                       (setq new (read-char-exclusive)))))))
          (when (and (= (upcase org-priority-highest) org-priority-highest)
                     (= (upcase org-priority-lowest) org-priority-lowest))
            (setq new (upcase new)))
@@ -11772,7 +11855,7 @@ an accumulator used in recursive calls."
                (org--tags-expand-group (cdr group) tag-groups expanded))))))
   expanded)
 
-(defun org-tags-expand (match &optional single-as-list _downcased)
+(defun org-tags-expand (match &optional single-as-list)
   "Expand group tags in MATCH.
 
 This replaces every group tag in MATCH with a regexp tag search.
@@ -11799,9 +11882,7 @@ will be replaced like this:
 
 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.
-
-The DOWNCASED argument is obsolete and has no effect."
+the list of tags in this group."
   (unless (org-string-nw-p match) (error "Invalid match tag: %S" match))
   (let ((tag-groups
          (or org-tag-groups-alist-for-agenda org-tag-groups-alist)))
@@ -11983,12 +12064,15 @@ in Lisp code use `org-set-tags' instead."
                      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 (org-make-tag-string current-tags)
-                               'org-tags-history)))))))
+                  (let ((org-add-colon-after-tag-completion (< 1 (length 
table)))
+                         (crm-separator "[ \t]*:[ \t]*"))
+                    (mapconcat #'identity
+                                (completing-read-multiple
+                                "Tags: "
+                                org-last-tags-completion-table
+                                nil nil (org-make-tag-string current-tags)
+                                'org-tags-history)
+                                ":"))))))
          (org-set-tags tags)))))
     ;; `save-excursion' may not replace the point at the right
     ;; position.
@@ -12068,7 +12152,7 @@ This works in the agenda, and also in an Org buffer."
                     (org-global-tags-completion-table))
                  (org-global-tags-completion-table))))
           (completing-read
-           "Tag: " 'org-tags-completion-function nil nil nil
+           "Tag: " org-last-tags-completion-table nil nil nil
            'org-tags-history))
         (progn
           (message "[s]et or [r]emove? ")
@@ -12164,7 +12248,7 @@ Returns the new tags string, or nil to not change the 
current settings."
                                  fulltable))))
         (buf (current-buffer))
         (expert (eq org-fast-tag-selection-single-key 'expert))
-        (buffer-tags nil)
+        (tab-tags nil)
         (fwidth (+ maxlen 3 1 3))
         (ncol (/ (- (window-width) 4) fwidth))
         (i-face 'org-done)
@@ -12299,16 +12383,21 @@ Returns the new tags string, or nil to not change the 
current settings."
                    (setq current nil)
                    (when exit-after-next (setq exit-after-next 'now)))
                   ((= c ?\t)
-                   (condition-case nil
-                       (setq tg (completing-read
-                                 "Tag: "
-                                 (or buffer-tags
-                                     (with-current-buffer buf
-                                       (setq buffer-tags
-                                             (org-get-buffer-tags))))))
-                     (quit (setq tg "")))
+                    (condition-case nil
+                        (unless tab-tags
+                          (setq tab-tags
+                                (delq nil
+                                      (mapcar (lambda (x)
+                                                (let ((item (car-safe x)))
+                                                  (and (stringp item)
+                                                       (list item))))
+                                              (org--tag-add-to-alist
+                                               (with-current-buffer buf
+                                                 (org-get-buffer-tags))
+                                               table))))))
+                    (setq tg (completing-read "Tag: " tab-tags))
                    (when (string-match "\\S-" tg)
-                     (cl-pushnew (list tg) buffer-tags :test #'equal)
+                     (cl-pushnew (list tg) tab-tags :test #'equal)
                      (if (member tg current)
                          (setq current (delete tg current))
                        (push tg current)))
@@ -12416,12 +12505,12 @@ Inherited tags have the `inherited' text property."
 (defun org-map-entries (func &optional match scope &rest skip)
   "Call FUNC at each headline selected by MATCH in SCOPE.
 
-FUNC is a function or a lisp form.  The function will be called without
+FUNC 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.
 
-The call to FUNC will be wrapped into a save-excursion form, so FUNC
+The call to FUNC will be wrapped into a `save-excursion' form, so FUNC
 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
@@ -12592,12 +12681,12 @@ it will be found.  If the drawer does not exist, 
create it if
 FORCE is non-nil, or return nil."
   (org-with-wide-buffer
    (let ((beg (cond (beg (goto-char beg))
-                     ((or (not (featurep 'org-inlinetask))
-                          (org-inlinetask-in-task-p))
-                      (org-back-to-heading-or-point-min t) (point))
-                     (t (org-with-limited-levels
-                         (org-back-to-heading-or-point-min t))
-                        (point)))))
+                   ((or (not (featurep 'org-inlinetask))
+                        (org-inlinetask-in-task-p))
+                    (org-back-to-heading-or-point-min t) (point))
+                   (t (org-with-limited-levels
+                       (org-back-to-heading-or-point-min t))
+                      (point)))))
      ;; Move point to its position according to its positional rules.
      (cond ((org-before-first-heading-p)
            (while (and (org-at-comment-p) (bolp)) (forward-line)))
@@ -13365,11 +13454,12 @@ This is computed according to 
`org-property-set-functions-alist'."
   (or (cdr (assoc property org-property-set-functions-alist))
       'org-completing-read))
 
-(defun org-read-property-value (property &optional pom)
+(defun org-read-property-value (property &optional pom default)
   "Read value for PROPERTY, as a string.
 When optional argument POM is non-nil, completion uses additional
 information, i.e., allowed or existing values at point or marker
-POM."
+POM.
+Optional argument DEFAULT provides a default value for PROPERTY."
   (let* ((completion-ignore-case t)
         (allowed
          (or (org-property-get-allowed-values nil property 'table)
@@ -13385,7 +13475,8 @@ POM."
      (if allowed
         (funcall set-function
                  prompt allowed nil
-                 (not (get-text-property 0 'org-unrestricted (caar allowed))))
+                 (not (get-text-property 0 'org-unrestricted (caar allowed)))
+                 default nil default)
        (let ((all (mapcar #'list
                          (append (org-property-values property)
                                  (and pom
@@ -13711,7 +13802,7 @@ 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.
 
-When called from lisp, the timestamp is inactive if INACTIVE is
+When called from Lisp, the timestamp is inactive if INACTIVE is
 non-nil."
   (interactive "P")
   (let* ((ts (cond
@@ -14103,6 +14194,19 @@ user."
               (setq ans (replace-match (format "%02d:%02d" hour minute)
                                        t t ans))))
 
+    ;; Help matching HHhMM times, similarly as for am/pm times.
+    (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 
"\\(?:\\(?1:[012]?[0-9]\\)?h\\(?2:[0-5][0-9]\\)\\)\\|\\(?:\\(?1:[012]?[0-9]\\)h\\(?2:[0-5][0-9]\\)?\\)\\>"
 ans))
+              (setq hour (if (match-end 1)
+                             (string-to-number (match-string 1 ans))
+                           0)
+                    minute (if (match-end 2)
+                               (string-to-number (match-string 2 ans))
+                             0))
+              (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)
       (setq hour (string-to-number (match-string 1 ans))
@@ -15271,9 +15375,9 @@ This function is useful in a setup where one tracks Org 
files
 with a version control system, to revert on one machine after pulling
 changes from another.  I believe the procedure must be like this:
 
-1. M-x org-save-all-org-buffers
+1. \\[org-save-all-org-buffers]
 2. Pull changes from the other machine, resolve conflicts
-3. M-x org-revert-all-org-buffers"
+3. \\[org-revert-all-org-buffers]"
   (interactive)
   (unless (yes-or-no-p "Revert all Org buffers from their files? ")
     (user-error "Abort"))
@@ -15366,9 +15470,8 @@ used by the agenda files.  If ARCHIVE is `ifmode', do 
this only if
                               files)))
     (when org-agenda-skip-unavailable-files
       (setq files (delq nil
-                       (mapcar (function
-                                (lambda (file)
-                                  (and (file-readable-p file) file)))
+                       (mapcar (lambda (file)
+                                 (and (file-readable-p file) file))
                                files))))
     (when (or (eq archives t)
              (and (eq archives 'ifmode) (eq org-agenda-archives-mode t)))
@@ -15640,7 +15743,7 @@ When a buffer is unmodified, it is just killed.  When 
modified, it is saved
 This mode supports entering LaTeX environment and math in LaTeX fragments
 in Org mode.
 \\{org-cdlatex-mode-map}"
-  nil " OCDL" nil
+  :lighter " OCDL"
   (when org-cdlatex-mode
     (require 'cdlatex)
     (run-hooks 'cdlatex-mode-hook)
@@ -15984,15 +16087,25 @@ Some of the options can be changed using the variable
                         (fg
                          (let ((color (plist-get org-format-latex-options
                                                  :foreground)))
-                           (if (and forbuffer (eq color 'auto))
-                               (face-attribute face :foreground nil 'default)
-                             color)))
+                            (if forbuffer
+                                (cond
+                                 ((eq color 'auto)
+                                  (face-attribute face :foreground nil 
'default))
+                                 ((eq color 'default)
+                                  (face-attribute 'default :foreground nil))
+                                 (t color))
+                              color)))
                         (bg
                          (let ((color (plist-get org-format-latex-options
                                                  :background)))
-                           (if (and forbuffer (eq color 'auto))
-                               (face-attribute face :background nil 'default)
-                             color)))
+                            (if forbuffer
+                                (cond
+                                 ((eq color 'auto)
+                                  (face-attribute face :background nil 
'default))
+                                 ((eq color 'default)
+                                  (face-attribute 'default :background nil))
+                                 (t color))
+                              color)))
                         (hash (sha1 (prin1-to-string
                                      (list org-format-latex-header
                                            org-latex-default-packages-alist
@@ -16211,10 +16324,10 @@ a HTML file."
     (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))))
+    (setq bg (cond
+             ((eq bg 'default) (org-latex-color :background))
+             ((string= bg "Transparent") nil)
+             (t (org-latex-color-format bg))))
     ;; Remove TeX \par at end of snippet to avoid trailing space.
     (if (string-suffix-p string "\n")
         (aset string (1- (length string)) ?%)
@@ -16223,8 +16336,10 @@ a HTML file."
       (insert latex-header)
       (insert "\n\\begin{document}\n"
              "\\definecolor{fg}{rgb}{" fg "}%\n"
-             "\\definecolor{bg}{rgb}{" bg "}%\n"
-             "\n\\pagecolor{bg}%\n"
+             (if bg
+                 (concat "\\definecolor{bg}{rgb}{" bg "}%\n"
+                         "\n\\pagecolor{bg}%\n")
+               "")
              "\n{\\color{fg}\n"
              string
              "\n}\n"
@@ -16494,30 +16609,7 @@ buffer boundaries with possible narrowing."
                                  (ignore-errors (org-attach-expand path)))
                               (expand-file-name path))))
                  (when (and file (file-exists-p file))
-                   (let ((width
-                          ;; Apply `org-image-actual-width' specifications.
-                          (cond
-                           ((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.
-                             (pcase (org-element-lineage link '(paragraph))
-                               (`nil nil)
-                               (p
-                                (let* ((case-fold-search t)
-                                       (end (org-element-property 
:post-affiliated p))
-                                       (re "^[ \t]*#\\+attr_.*?: +.*?:width 
+\\(\\S-+\\)"))
-                                  (when (org-with-point-at
-                                            (org-element-property :begin p)
-                                          (re-search-forward re end 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)
-                           (t nil)))
+                   (let ((width (org-display-inline-image--width link))
                          (old (get-char-property-and-overlay
                                (org-element-property :begin link)
                                'org-image-overlay)))
@@ -16542,6 +16634,58 @@ buffer boundaries with possible narrowing."
                                (overlay-put ov 'keymap image-map))
                              (push ov org-inline-image-overlays))))))))))))))))
 
+(defvar visual-fill-column-width) ; Silence compiler warning
+(defun org-display-inline-image--width (link)
+  "Determine the display width of the image LINK, in pixels.
+- When `org-image-actual-width' is t, the image's pixel width is used.
+- When `org-image-actual-width' is a number, that value will is used.
+- When `org-image-actual-width' is nil or a list, the first :width attribute
+  set (if it exists) is used to set the image width.  A width of X% is
+  divided by 100.
+  If no :width attribute is given and `org-image-actual-width' is a list with
+  a number as the car, then that number is used as the default value.
+  If the value is a float between 0 and 2, it interpreted as that proportion
+  of the text width in the buffer."
+  ;; Apply `org-image-actual-width' specifications.
+  (cond
+   ((eq org-image-actual-width t) nil)
+   ((listp org-image-actual-width)
+    (let* ((case-fold-search t)
+           (par (org-element-lineage link '(paragraph)))
+           (attr-re "^[ \t]*#\\+attr_.*?: +.*?:width +\\(\\S-+\\)")
+           (par-end (org-element-property :post-affiliated par))
+           ;; Try to find an attribute providing a :width.
+           (attr-width
+            (when (and par (org-with-point-at
+                               (org-element-property :begin par)
+                             (re-search-forward attr-re par-end t)))
+              (match-string 1)))
+           (attr-width-val
+            (cond
+             ((null attr-width) nil)
+             ((string-match-p "\\`[0-9.]+%" attr-width)
+              (/ (string-to-number attr-width) 100.0))
+             (t (string-to-number attr-width))))
+           ;; Fallback to `org-image-actual-width' if no explicit width is 
given.
+           (width (or attr-width-val (car org-image-actual-width))))
+      (if (and (floatp width) (<= 0.0 width 2.0))
+          ;; A float in [0,2] should be interpereted as this portion of
+          ;; the text width in the window.  This works well with cases like
+          ;; #+attr_latex: :width 0.X\{line,page,column,etc.}width,
+          ;; as the "0.X" is pulled out as a float.  We use 2 as the upper
+          ;; bound as cases such as 1.2\linewidth are feasible.
+          (round (* width
+                    (window-pixel-width)
+                    (/ (or (and (bound-and-true-p visual-fill-column-mode)
+                                (or visual-fill-column-width 
auto-fill-function))
+                           (when auto-fill-function fill-column)
+                           (window-text-width))
+                       (float (window-total-width)))))
+        width)))
+   ((numberp org-image-actual-width)
+    org-image-actual-width)
+   (t nil)))
+
 (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))
@@ -16925,7 +17069,8 @@ When ARG is a numeric prefix, show contents of this 
level."
       (message "Content view to level: %d" arg)
       (org-content (prefix-numeric-value arg2))
       (org-cycle-show-empty-lines t)
-      (setq org-cycle-global-status 'overview)))
+      (setq org-cycle-global-status 'overview)
+      (run-hook-with-args 'org-cycle-hook 'overview)))
    (t (call-interactively 'org-global-cycle))))
 
 (defun org-shiftmetaleft ()
@@ -17416,7 +17561,7 @@ 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 in a LaTeX environment, call `org-edit-latex-environment'.
-When at an #+INCLUDE keyword, visit the included file.
+When at an INCLUDE, SETUPFILE or BIBLIOGRAPHY keyword, visit the included file.
 When at a footnote reference, call `org-edit-footnote-reference'.
 When at a planning line call, `org-deadline' and/or `org-schedule'.
 When at an active timestamp, call `org-time-stamp'.
@@ -17442,14 +17587,14 @@ Otherwise, return a user error."
                       session params))))))
       (`keyword
        (unless (member (org-element-property :key element)
-                      '("INCLUDE" "SETUPFILE"))
+                      '("BIBLIOGRAPHY" "INCLUDE" "SETUPFILE"))
         (user-error "No special environment to edit here"))
        (let ((value (org-element-property :value element)))
         (unless (org-string-nw-p value) (user-error "No file to edit"))
         (let ((file (and (string-match "\\`\"\\(.*?\\)\"\\|\\S-+" value)
                          (or (match-string 1 value)
                              (match-string 0 value)))))
-          (when (org-file-url-p file)
+          (when (org-url-p file)
             (user-error "Files located with a URL cannot be edited"))
           (org-link-open-from-string
            (format "[[%s]]" (expand-file-name file))))))
@@ -17694,28 +17839,35 @@ This command does many different things, depending on 
context:
        (`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"))
-          (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))))))
+        ;; At a table, generate a plot if on the #+plot line,
+         ;; recalculate every field and align it otherwise.  Also
+        ;; send the table if necessary.
+         (cond
+          ((and (org-match-line "[ \t]*#\\+plot:")
+                (< (point) (org-element-property :post-affiliated context)))
+           (org-plot/gnuplot))
+          ;; If the table has a `table.el' type, just give up.
+          ((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")))
+          ;; At a table row or cell, maybe recalculate line but always
+         ;; align table.
+          ((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))))
+          (t
+           (org-table-maybe-eval-formula)
+           (cond (arg (call-interactively #'org-table-recalculate))
+                 ((org-table-maybe-recalculate-line))
+                 (t (org-table-align))))))
        ((or `timestamp (and `planning (guard (org-at-timestamp-p 'lax))))
         (org-timestamp-change 0 'day))
        ((and `nil (guard (org-at-heading-p)))
@@ -17730,7 +17882,7 @@ Use `\\[org-edit-special]' to edit table.el tables"))
           "`\\[org-ctrl-c-ctrl-c]' can do nothing useful here"))))))))
 
 (defun org-mode-restart ()
-"Restart `org-mode'."
+  "Restart `org-mode'."
   (interactive)
   (let ((indent-status (bound-and-true-p org-indent-mode)))
     (funcall major-mode)
@@ -17846,7 +17998,7 @@ object (e.g., within a comment).  In these case, you 
need to use
 `org-open-at-point' directly."
   (interactive "i\nP\np")
   (let* ((context (if org-return-follows-link (org-element-context)
-                  (org-element-at-point)))
+                   (org-element-at-point)))
          (element-type (org-element-type context)))
     (cond
      ;; In a table, call `org-table-next-row'.  However, before first
@@ -17916,7 +18068,7 @@ object (e.g., within a comment).  In these case, you 
need to use
 Call `org-table-next-row' or `org-return', depending on context.
 See the individual commands for more information.
 
-When inserting a newline, if `org-adapt-indentation' is `t':
+When inserting a newline, if `org-adapt-indentation' is t:
 indent the line if `electric-indent-mode' is disabled, don't
 indent it if it is enabled."
   (interactive)
@@ -17992,15 +18144,14 @@ when a numeric prefix argument is given, its value 
determines the
 number of stars to add."
   (interactive "P")
   (let ((skip-blanks
-        (function
-         ;; Return beginning of first non-blank line, starting from
-         ;; line at POS.
-         (lambda (pos)
-           (save-excursion
-             (goto-char pos)
-             (while (org-at-comment-p) (forward-line))
-             (skip-chars-forward " \r\t\n")
-             (point-at-bol)))))
+        ;; Return beginning of first non-blank line, starting from
+        ;; line at POS.
+        (lambda (pos)
+          (save-excursion
+            (goto-char pos)
+            (while (org-at-comment-p) (forward-line))
+            (skip-chars-forward " \r\t\n")
+            (point-at-bol))))
        beg end toggled)
     ;; Determine boundaries of changes.  If a universal prefix has
     ;; been given, put the list in a region.  If region ends at a bol,
@@ -18087,7 +18238,7 @@ an argument, unconditionally call `org-insert-heading'."
        (not (org-at-table-p))))
 
 ;; Define the Org mode menus
-(easy-menu-define org-org-menu org-mode-map "Org menu"
+(easy-menu-define org-org-menu org-mode-map "Org menu."
   `("Org"
     ("Show/Hide"
      ["Cycle Visibility" org-cycle :active (or (bobp) (outline-on-heading-p))]
@@ -18272,7 +18423,7 @@ an argument, unconditionally call `org-insert-heading'."
      ["Reload Org (after update)" org-reload t]
      ["Reload Org uncompiled" (org-reload t) :active t :keys "C-u C-c C-x 
!"])))
 
-(easy-menu-define org-tbl-menu org-mode-map "Org Table menu"
+(easy-menu-define org-tbl-menu org-mode-map "Org Table menu."
   '("Table"
     ["Align" org-ctrl-c-ctrl-c :active (org-at-table-p)]
     ["Next Field" org-cycle (org-at-table-p)]
@@ -18413,7 +18564,7 @@ Your bug report will be posted to the Org mailing list.
 ------------------------------------------------------------------------")
     (save-excursion
       (when (re-search-backward "^\\(Subject: \\)Org mode version \\(.*?\\);[ 
\t]*\\(.*\\)" nil t)
-       (replace-match "\\1Bug: \\3 [\\2]")))))
+       (replace-match "\\1[BUG] \\3 [\\2]")))))
 
 
 (defun org-install-agenda-files-menu ()
@@ -19003,7 +19154,7 @@ Indentation is done according to the following rules:
        Else, indent like parent's first line.
 
     3. Otherwise, indent relatively to current level, if
-       `org-adapt-indentation' is `t', or to left margin.
+       `org-adapt-indentation' is t, or to left margin.
 
   - On a blank line at the end of an element, indent according to
     the type of the element.  More precisely
@@ -19058,6 +19209,21 @@ Also align node properties according to 
`org-property-format'."
                     (org-with-point-at (org-element-property :end element)
                       (skip-chars-backward " \t\n")
                       (line-beginning-position))))
+             ;; At the beginning of a blank line, do some preindentation.  This
+             ;; signals org-src--edit-element to preserve the indentation on 
exit
+             (when (and (looking-at-p "^[[:space:]]*$")
+                        (not org-src-preserve-indentation))
+               (let ((element (org-element-at-point))
+                     block-content-ind some-ind)
+                 (org-with-point-at (org-element-property :begin element)
+                   (setq block-content-ind (+ (current-indentation)
+                                              
org-edit-src-content-indentation))
+                   (forward-line)
+                  (save-match-data (re-search-forward "^[ \t]*\\S-" nil t))
+                   (backward-char)
+                   (setq some-ind (if (looking-at-p "#\\+end_src")
+                                      block-content-ind 
(current-indentation))))
+                 (indent-line-to (min block-content-ind some-ind))))
             (org-babel-do-key-sequence-in-edit-buffer (kbd "TAB")))
            (t
             (let ((column (org--get-expected-indentation element nil)))
@@ -19724,15 +19890,15 @@ When BLOCK-REGEXP is non-nil, use this regexp to find 
blocks."
 ;; example-block) don't accept comments.  Usual Emacs comment commands
 ;; cannot cope with those requirements.  Therefore, Org replaces them.
 
-;; Org still relies on `comment-dwim', but cannot trust
-;; `comment-only-p'.  So, `comment-region-function' and
-;; `uncomment-region-function' both point
-;; to`org-comment-or-uncomment-region'.  Eventually,
-;; `org-insert-comment' takes care of insertion of comments at the
+;; Org still relies on 'comment-dwim', but cannot trust
+;; 'comment-only-p'.  So, 'comment-region-function' and
+;; 'uncomment-region-function' both point
+;; to 'org-comment-or-uncomment-region'.  Eventually,
+;; 'org-insert-comment' takes care of insertion of comments at the
 ;; beginning of line.
 
-;; `org-setup-comments-handling' install comments related variables
-;; during `org-mode' initialization.
+;; 'org-setup-comments-handling' install comments related variables
+;; during 'org-mode' initialization.
 
 (defun org-setup-comments-handling ()
   (interactive)
@@ -19974,7 +20140,7 @@ it has a `diary' type."
 (defvar org--rds)
 
 (defun org-reftex-citation ()
-  "Use reftex-citation to insert a citation into the buffer.
+  "Use `reftex-citation' to insert a citation into the buffer.
 This looks for a line like
 
 #+BIBLIOGRAPHY: foo plain option:-d
@@ -20294,7 +20460,7 @@ interactive command with similar behavior."
        (call-interactively command))))))
 
 (defun org-yank-folding-would-swallow-text (beg end)
-  "Would hide-subtree at BEG swallow any text after END?"
+  "Would `hide-subtree' at BEG swallow any text after END?"
   (let (level)
     (org-with-limited-levels
      (save-excursion
@@ -20391,7 +20557,7 @@ unless optional argument NO-INHERITANCE is non-nil."
 
 (defun org-point-at-end-of-empty-headline ()
   "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
+If the heading only contains a TODO keyword, it is still considered
 empty."
   (let ((case-fold-search nil))
     (and (looking-at "[ \t]*$")
@@ -20410,6 +20576,10 @@ This function considers both visible and invisible 
heading lines.
 With argument, move up ARG levels."
   (outline-up-heading arg t))
 
+(defvar-local org--up-heading-cache nil
+  "Buffer-local `org-up-heading-safe' cache.")
+(defvar-local org--up-heading-cache-tick nil
+  "Buffer `buffer-chars-modified-tick' in `org--up-heading-cache'.")
 (defun org-up-heading-safe ()
   "Move to the heading line of which the present line is a subheading.
 This version will not throw an error.  It will return the level of the
@@ -20419,10 +20589,28 @@ 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."
   (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)))))
+    (let (level-cache)
+      (unless org--up-heading-cache
+        (setq org--up-heading-cache (make-hash-table)))
+      (if (and (eq (buffer-chars-modified-tick) org--up-heading-cache-tick)
+               (setq level-cache (gethash (point) org--up-heading-cache)))
+          (when (<= (point-min) (car level-cache) (point-max))
+            ;; Parent is inside accessible part of the buffer.
+            (progn (goto-char (car level-cache))
+                   (cdr level-cache)))
+        ;; Buffer modified.  Invalidate cache.
+        (unless (eq (buffer-chars-modified-tick) org--up-heading-cache-tick)
+          (setq-local org--up-heading-cache-tick
+                      (buffer-chars-modified-tick))
+          (clrhash org--up-heading-cache))
+        (let* ((level-up (1- (funcall outline-level)))
+               (pos (point))
+               (result (and (> level-up 0)
+                           (re-search-backward
+                             (format "^\\*\\{1,%d\\} " level-up) nil t)
+                           (funcall outline-level))))
+          (when result (puthash pos (cons (point) result) 
org--up-heading-cache))
+          result)))))
 
 (defun org-up-heading-or-point-min ()
   "Move to the heading line of which the present is a subheading, or point-min.
@@ -20482,10 +20670,10 @@ 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 (ignore-errors (org-back-to-heading t))
-      (setq level (outline-level))
+    (when (org-back-to-heading-or-point-min t)
+      (setq level (org-outline-level))
       (forward-char 1)
-      (if (and (re-search-forward re nil t) (> (outline-level) level))
+      (if (and (re-search-forward re nil t) (> (org-outline-level) level))
          (progn (goto-char (match-beginning 0)) t)
        (goto-char pos) nil))))
 
@@ -20519,7 +20707,7 @@ This is like outline-next-sibling, but invisible 
headings are ok."
     (unless (or (eobp) (< (funcall outline-level) level))
       (point))))
 
-(defun org-get-last-sibling ()
+(defun org-get-previous-sibling ()
   "Move to previous heading of the same level, and return point.
 If there is no such heading, return nil."
   (let ((opoint (point))
@@ -20576,8 +20764,7 @@ When optional argument FULL is t, also skip planning 
information,
 clocking lines and any kind of drawer.
 
 When FULL is non-nil but not t, skip planning information,
-clocking lines and only non-regular drawers, i.e. properties and
-logbook drawers."
+properties, clocking lines and logbook drawers."
   (org-back-to-heading t)
   (forward-line)
   ;; Skip planning information.
diff --git a/lisp/ox-ascii.el b/lisp/ox-ascii.el
index 0dfa3b4..78e6fb4 100644
--- a/lisp/ox-ascii.el
+++ b/lisp/ox-ascii.el
@@ -3,6 +3,7 @@
 ;; Copyright (C) 2012-2021 Free Software Foundation, Inc.
 
 ;; Author: Nicolas Goaziou <n.goaziou at gmail dot com>
+;; Maintainer: Nicolas Goaziou <n.goaziou at gmail dot com>
 ;; Keywords: outlines, hypermedia, calendar, wp
 
 ;; This file is part of GNU Emacs.
@@ -479,6 +480,9 @@ HOW determines the type of justification: it can be `left',
     (insert s)
     (goto-char (point-min))
     (let ((fill-column text-width)
+          ;; Ensure that `indent-tabs-mode' is nil so that indentation
+          ;; will always be achieved using spaces rather than tabs.
+          (indent-tabs-mode nil)
          ;; Disable `adaptive-fill-mode' so it doesn't prevent
          ;; filling lines matching `adaptive-fill-regexp'.
          (adaptive-fill-mode nil))
@@ -1376,7 +1380,7 @@ contextual information."
 ;;;; 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."
@@ -1940,33 +1944,32 @@ CONTENTS is the row contents.  INFO is a plist used as
 a communication channel."
   (when (eq (org-element-property :type table-row) 'standard)
     (let ((build-hline
-          (function
-           (lambda (lcorner horiz vert rcorner)
-             (concat
-              (apply
-               'concat
-               (org-element-map table-row 'table-cell
-                 (lambda (cell)
-                   (let ((width (org-ascii--table-cell-width cell info))
-                         (borders (org-export-table-cell-borders cell info)))
-                     (concat
-                      ;; In order to know if CELL starts the row, do
-                      ;; not compare it with the first cell in the
-                      ;; row as there might be a special column.
-                      ;; Instead, compare it with first exportable
-                      ;; cell, obtained with `org-element-map'.
-                      (when (and (memq 'left borders)
-                                 (eq (org-element-map table-row 'table-cell
-                                       'identity info t)
-                                     cell))
-                        lcorner)
-                      (make-string (+ 2 width) (string-to-char horiz))
-                      (cond
-                       ((not (memq 'right borders)) nil)
-                       ((eq (car (last (org-element-contents table-row))) cell)
-                        rcorner)
-                       (t vert)))))
-                 info)) "\n"))))
+          (lambda (lcorner horiz vert rcorner)
+            (concat
+             (apply
+              'concat
+              (org-element-map table-row 'table-cell
+                (lambda (cell)
+                  (let ((width (org-ascii--table-cell-width cell info))
+                        (borders (org-export-table-cell-borders cell info)))
+                    (concat
+                     ;; In order to know if CELL starts the row, do
+                     ;; not compare it with the first cell in the
+                     ;; row as there might be a special column.
+                     ;; Instead, compare it with first exportable
+                     ;; cell, obtained with `org-element-map'.
+                     (when (and (memq 'left borders)
+                                (eq (org-element-map table-row 'table-cell
+                                      'identity info t)
+                                    cell))
+                       lcorner)
+                     (make-string (+ 2 width) (string-to-char horiz))
+                     (cond
+                      ((not (memq 'right borders)) nil)
+                      ((eq (car (last (org-element-contents table-row))) cell)
+                       rcorner)
+                      (t vert)))))
+                info)) "\n")))
          (utf8p (eq (plist-get info :ascii-charset) 'utf-8))
          (borders (org-export-table-cell-borders
                    (org-element-map table-row 'table-cell 'identity info t)
@@ -2088,7 +2091,7 @@ a communication channel."
 
 ;;;###autoload
 (defun org-ascii-export-as-ascii
-  (&optional async subtreep visible-only body-only ext-plist)
+    (&optional async subtreep visible-only body-only ext-plist)
   "Export current buffer to a text buffer.
 
 If narrowing is active in the current buffer, only export its
@@ -2123,7 +2126,7 @@ is non-nil."
 
 ;;;###autoload
 (defun org-ascii-export-to-ascii
-  (&optional async subtreep visible-only body-only ext-plist)
+    (&optional async subtreep visible-only body-only ext-plist)
   "Export current buffer to a text file.
 
 If narrowing is active in the current buffer, only export its
diff --git a/lisp/ox-beamer.el b/lisp/ox-beamer.el
index 1a1732b..ca0f1c7 100644
--- a/lisp/ox-beamer.el
+++ b/lisp/ox-beamer.el
@@ -4,6 +4,7 @@
 
 ;; Author: Carsten Dominik <carsten.dominik AT gmail DOT com>
 ;;         Nicolas Goaziou <n.goaziou AT gmail DOT com>
+;; Maintainer: Nicolas Goaziou <n.goaziou at gmail dot com>
 ;; Keywords: org, wp, tex
 
 ;; This file is part of GNU Emacs.
@@ -149,7 +150,7 @@ which is replaced with the subtitle."
 
 (defconst org-beamer-column-widths
   "0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 0.0 :ETC"
-"The column widths that should be installed as allowed property values.")
+  "The column widths that should be installed as allowed property values.")
 
 (defconst org-beamer-environments-special
   '(("againframe"     "A")
@@ -379,13 +380,12 @@ used as a communication channel."
           :parent 'latex
           :transcoders
           (let ((protected-output
-                 (function
-                  (lambda (object contents info)
-                    (let ((code (org-export-with-backend
-                                 'beamer object contents info)))
-                      (if (org-string-nw-p code) (concat "\\protect" code)
-                        code))))))
-            (mapcar #'(lambda (type) (cons type protected-output))
+                 (lambda (object contents info)
+                   (let ((code (org-export-with-backend
+                                'beamer object contents info)))
+                     (if (org-string-nw-p code) (concat "\\protect" code)
+                       code)))))
+             (mapcar (lambda (type) (cons type protected-output))
                     '(bold footnote-reference italic strike-through timestamp
                            underline))))
          headline
@@ -426,16 +426,16 @@ used as a communication channel."
                    ;; Collect nonempty options from default value and
                    ;; headline's properties.
                    (cl-remove-if-not #'org-string-nw-p
-                    (append
-                     (org-split-string
-                      (plist-get info :beamer-frame-default-options) ",")
-                     (and beamer-opt
-                          (org-split-string
-                           ;; Remove square brackets if user provided
-                           ;; them.
-                           (and (string-match "^\\[?\\(.*\\)\\]?$" beamer-opt)
-                                (match-string 1 beamer-opt))
-                           ",")))))
+                                     (append
+                                      (org-split-string
+                                       (plist-get info 
:beamer-frame-default-options) ",")
+                                      (and beamer-opt
+                                           (org-split-string
+                                            ;; Remove square brackets if user 
provided
+                                            ;; them.
+                                            (and (string-match 
"^\\[?\\(.*\\)\\]?$" beamer-opt)
+                                                 (match-string 1 beamer-opt))
+                                            ",")))))
                   (fragile
                    ;; Add "fragile" option if necessary.
                    (and fragilep
@@ -812,17 +812,16 @@ holding export options."
      (org-latex-make-preamble info)
      ;; Insert themes.
      (let ((format-theme
-           (function
-            (lambda (prop command)
-              (let ((theme (plist-get info prop)))
-                (when theme
-                  (concat command
-                          (if (not (string-match "\\[.*\\]" theme))
-                              (format "{%s}\n" theme)
-                            (format "%s{%s}\n"
-                                    (match-string 0 theme)
-                                    (org-trim
-                                     (replace-match "" nil nil theme)))))))))))
+           (lambda (prop command)
+             (let ((theme (plist-get info prop)))
+               (when theme
+                 (concat command
+                         (if (not (string-match "\\[.*\\]" theme))
+                             (format "{%s}\n" theme)
+                           (format "%s{%s}\n"
+                                   (match-string 0 theme)
+                                   (org-trim
+                                    (replace-match "" nil nil theme))))))))))
        (mapconcat (lambda (args) (apply format-theme args))
                  '((:beamer-theme "\\usetheme")
                    (:beamer-color-theme "\\usecolortheme")
@@ -895,14 +894,16 @@ holding export options."
 ;;; Minor Mode
 
 
-(defvar org-beamer-mode-map (make-sparse-keymap)
+(defvar org-beamer-mode-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map "\C-c\C-b" 'org-beamer-select-environment)
+    map)
   "The keymap for `org-beamer-mode'.")
-(define-key org-beamer-mode-map "\C-c\C-b" 'org-beamer-select-environment)
 
 ;;;###autoload
 (define-minor-mode org-beamer-mode
   "Support for editing Beamer oriented Org mode files."
-  nil " Bm" 'org-beamer-mode-map)
+  :lighter " Bm")
 
 (when (fboundp 'font-lock-add-keywords)
   (font-lock-add-keywords
@@ -958,7 +959,7 @@ value."
 
 ;;;###autoload
 (defun org-beamer-export-as-latex
-  (&optional async subtreep visible-only body-only ext-plist)
+    (&optional async subtreep visible-only body-only ext-plist)
   "Export current buffer as a Beamer buffer.
 
 If narrowing is active in the current buffer, only export its
@@ -993,7 +994,7 @@ is non-nil."
 
 ;;;###autoload
 (defun org-beamer-export-to-latex
-  (&optional async subtreep visible-only body-only ext-plist)
+    (&optional async subtreep visible-only body-only ext-plist)
   "Export current buffer as a Beamer presentation (tex).
 
 If narrowing is active in the current buffer, only export its
@@ -1027,7 +1028,7 @@ Return output file's name."
 
 ;;;###autoload
 (defun org-beamer-export-to-pdf
-  (&optional async subtreep visible-only body-only ext-plist)
+    (&optional async subtreep visible-only body-only ext-plist)
   "Export current buffer as a Beamer presentation (PDF).
 
 If narrowing is active in the current buffer, only export its
@@ -1078,7 +1079,7 @@ aid, but the tag does not have any semantic meaning."
         (org-current-tag-alist
          (append '((:startgroup))
                  (mapcar (lambda (e) (cons (concat "B_" (car e))
-                                      (string-to-char (nth 1 e))))
+                                           (string-to-char (nth 1 e))))
                          envs)
                  '((:endgroup))
                  '(("BMCOL" . ?|))))
diff --git a/lisp/ox-html.el b/lisp/ox-html.el
index d119c17..60bb77d 100644
--- a/lisp/ox-html.el
+++ b/lisp/ox-html.el
@@ -2,8 +2,9 @@
 
 ;; Copyright (C) 2011-2021 Free Software Foundation, Inc.
 
-;; Author: Carsten Dominik <carsten at orgmode dot org>
+;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 ;;      Jambunathan K <kjambunathan at gmail dot com>
+;; Maintainer: TEC <tecosaur@gmail.com>
 ;; Keywords: outlines, hypermedia, calendar, wp
 
 ;; This file is part of GNU Emacs.
@@ -113,6 +114,7 @@
   :options-alist
   '((:html-doctype "HTML_DOCTYPE" nil org-html-doctype)
     (:html-container "HTML_CONTAINER" nil org-html-container-element)
+    (:html-content-class "HTML_CONTENT_CLASS" nil org-html-content-class)
     (:description "DESCRIPTION" nil nil newline)
     (:keywords "KEYWORDS" nil nil space)
     (:html-html5-fancy nil "html5-fancy" org-html-html5-fancy)
@@ -192,7 +194,7 @@
 (defvar htmlize-buffer-places)  ; from htmlize.el
 
 (defvar org-html--pre/postamble-class "status"
-  "CSS class used for pre/postamble")
+  "CSS class used for pre/postamble.")
 
 (defconst org-html-doctype-alist
   '(("html4-strict" . "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\"
@@ -231,10 +233,9 @@ property on the headline itself.")
     ("\\.\\.\\." . "&#x2026;"))                ; hellip
   "Regular expressions for special string conversion.")
 
-(defconst org-html-scripts
-  "<script type=\"text/javascript\">
+(defcustom org-html-scripts
+  "<script>
 // @license 
magnet:?xt=urn:btih:1f739d935676111cfff4b4693e3816e664797050&amp;dn=gpl-3.0.txt 
GPL-v3-or-Later
-<!--/*--><![CDATA[/*><!--*/
      function CodeHighlightOn(elem, id)
      {
        var target = document.getElementById(id);
@@ -251,14 +252,16 @@ property on the headline itself.")
          target.classList.remove(\"code-highlighted\");
        }
      }
-    /*]]>*///-->
 // @license-end
 </script>"
-  "Basic JavaScript that is needed by HTML files produced by Org mode.")
+  "Basic JavaScript to allow highlighting references in code blocks."
+  :group 'org-export-html
+  :package-version '(Org . "9.5")
+  :type 'string)
 
-(defconst org-html-style-default
-  "<style type=\"text/css\">
- <!--/*--><![CDATA[/*><!--*/
+(defcustom org-html-style-default
+  "<style>
+  #content { max-width: 60em; margin: auto; }
   .title  { text-align: center;
              margin-bottom: .2em; }
   .subtitle { text-align: center;
@@ -279,8 +282,9 @@ property on the headline itself.")
   #postamble p, #preamble p { font-size: 90%; margin: .2em; }
   p.verse { margin-left: 3%; }
   pre {
-    border: 1px solid #ccc;
-    box-shadow: 3px 3px 3px #eee;
+    border: 1px solid #e6e6e6;
+    border-radius: 3px;
+    background-color: #f2f2f2;
     padding: 8pt;
     font-family: monospace;
     overflow: auto;
@@ -289,21 +293,21 @@ property on the headline itself.")
   pre.src {
     position: relative;
     overflow: auto;
-    padding-top: 1.2em;
   }
   pre.src:before {
     display: none;
     position: absolute;
-    background-color: white;
-    top: -10px;
-    right: 10px;
+    top: -8px;
+    right: 12px;
     padding: 3px;
-    border: 1px solid black;
+    color: #555;
+    background-color: #f2f2f299;
   }
   pre.src:hover:before { display: inline; margin-top: 14px;}
   /* Languages per Org manual */
   pre.src-asymptote:before { content: 'Asymptote'; }
   pre.src-awk:before { content: 'Awk'; }
+  pre.src-authinfo::before { content: 'Authinfo'; }
   pre.src-C:before { content: 'C'; }
   /* pre.src-C++ doesn't work in CSS */
   pre.src-clojure:before { content: 'Clojure'; }
@@ -439,12 +443,14 @@ property on the headline itself.")
   .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.
 You can use `org-html-head' and `org-html-head-extra' to add to
 this style.  If you don't want to include this default style,
-customize `org-html-head-include-default-style'.")
+customize `org-html-head-include-default-style'."
+  :group 'org-export-html
+  :package-version '(Org . "9.5")
+  :type 'string)
 
 
 ;;; User Configuration Variables
@@ -508,17 +514,15 @@ means to use the maximum value consistent with other 
options."
           org-html-infojs-opts-table)))
 
 (defcustom org-html-infojs-template
-  "<script type=\"text/javascript\" src=\"%SCRIPT_PATH\">
+  "<script src=\"%SCRIPT_PATH\">
 // @license 
magnet:?xt=urn:btih:1f739d935676111cfff4b4693e3816e664797050&amp;dn=gpl-3.0.txt 
GPL-v3-or-Later
 // @license-end
 </script>
 
-<script type=\"text/javascript\">
+<script>
 // @license 
magnet:?xt=urn:btih:1f739d935676111cfff4b4693e3816e664797050&amp;dn=gpl-3.0.txt 
GPL-v3-or-Later
-<!--/*--><![CDATA[/*><!--*/
 %MANAGER_OPTIONS
 org_html_manager.setup();  // activate after the parameters are set
-/*]]>*///-->
 // @license-end
 </script>"
   "The template for the export style additions when org-info.js is used.
@@ -779,7 +783,7 @@ The function should return the string to be exported."
   "The MathJax command to use when referencing equations.
 
 This is a format control string that expects a single string argument
-specifying the label that is being referenced. The argument is
+specifying the label that is being referenced.  The argument is
 generated automatically on export.
 
 The default is to wrap equations in parentheses (using \"\\eqref{%s}\)\".
@@ -822,13 +826,13 @@ e.g. \"tex:mathjax\".  Allowed values are:
 ;;;; Links :: Generic
 
 (defcustom org-html-link-org-files-as-html t
-  "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 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.
+  "Non-nil means make file links to \"file.org\" point to \"file.html\".
+
+When Org mode is exporting an Org file to HTML, links to non-HTML files
+are directly put into a \"href\" tag in 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 file will also be converted to HTML.
+
 When nil, the links still point to the plain \".org\" file."
   :group 'org-export-html
   :type 'boolean)
@@ -845,16 +849,15 @@ link to the image."
   :type 'boolean)
 
 (defcustom org-html-inline-image-rules
-  `(("file" . ,(regexp-opt '(".jpeg" ".jpg" ".png" ".gif" ".svg")))
-    ("http" . ,(regexp-opt '(".jpeg" ".jpg" ".png" ".gif" ".svg")))
-    ("https" . ,(regexp-opt '(".jpeg" ".jpg" ".png" ".gif" ".svg"))))
+  `(("file" . ,(regexp-opt '(".jpeg" ".jpg" ".png" ".gif" ".svg" ".webp")))
+    ("http" . ,(regexp-opt '(".jpeg" ".jpg" ".png" ".gif" ".svg" ".webp")))
+    ("https" . ,(regexp-opt '(".jpeg" ".jpg" ".png" ".gif" ".svg" ".webp"))))
   "Rules characterizing image files that can be inlined into HTML.
 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-html
-  :version "24.4"
-  :package-version '(Org . "8.0")
+  :package-version '(Org . "9.5")
   :type '(alist :key-type (string :tag "Type")
                :value-type (regexp :tag "Path")))
 
@@ -871,7 +874,7 @@ link's path."
 (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,`inline-css'
-to export the CSS attribute values inline in the HTML or `nil' to
+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.
 
@@ -1057,13 +1060,7 @@ publishing, with :html-doctype."
 
 (defcustom org-html-html5-fancy nil
   "Non-nil means using new HTML5 elements.
-This variable is ignored for anything other than HTML5 export.
-
-For compatibility with Internet Explorer, it's probably a good
-idea to download some form of the html5shiv (for instance
-https://code.google.com/p/html5shiv/) and add it to your
-HTML_HEAD_EXTRA, so that your pages don't break for users of IE
-versions 8 and below."
+This variable is ignored for anything other than HTML5 export."
   :group 'org-export-html
   :version "24.4"
   :package-version '(Org . "8.0")
@@ -1081,6 +1078,16 @@ org-info.js for your website."
   :package-version '(Org . "8.0")
   :type 'string)
 
+(defcustom org-html-content-class "content"
+  "CSS class name to use for the top level content wrapper.
+Can be set with the in-buffer HTML_CONTENT_CLASS property or for
+publishing, with :html-content-class."
+  :group 'org-export-html
+  :version "27.2"
+  :package-version '(Org . "9.5")
+  :type 'string)
+
+
 (defcustom org-html-divs
   '((preamble  "div" "preamble")
     (content   "div" "content")
@@ -1107,15 +1114,15 @@ org-info.js for your website."
 
 (defconst org-html-checkbox-types
   '((unicode .
-     ((on . "&#x2611;") (off . "&#x2610;") (trans . "&#x2610;")))
+             ((on . "&#x2611;") (off . "&#x2610;") (trans . "&#x2610;")))
     (ascii .
-     ((on . "<code>[X]</code>")
-      (off . "<code>[&#xa0;]</code>")
-      (trans . "<code>[-]</code>")))
+           ((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' />"))))
+          (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'.
@@ -1126,7 +1133,7 @@ The choices are:
   `html'    HTML checkboxes
 
 Note that only the ascii characters implement tri-state
-checkboxes. The other two use the `off' checkbox for `trans'.")
+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.
@@ -1189,7 +1196,7 @@ You can also customize this for each buffer, using 
something like
 
 For further information about MathJax options, see the MathJax documentation:
 
-  http://docs.mathjax.org/";
+  https://docs.mathjax.org/";
   :group 'org-export-html
   :package-version '(Org . "8.3")
   :type '(list :greedy t
@@ -1249,8 +1256,7 @@ For further information about MathJax options, see the 
MathJax documentation:
              }
 });
 </script>
-<script type=\"text/javascript\"
-        src=\"%PATH\"></script>"
+<script src=\"%PATH\"></script>"
   "The MathJax template.  See also `org-html-mathjax-options'."
   :group 'org-export-html
   :type 'string)
@@ -1411,10 +1417,9 @@ ignored."
 
 ;;;; Template :: Scripts
 
-(defcustom org-html-head-include-scripts t
+(defcustom org-html-head-include-scripts nil
   "Non-nil means include the JavaScript snippets in exported HTML files.
-The actual script is defined in `org-html-scripts' and should
-not be modified."
+The actual script is defined in `org-html-scripts'."
   :group 'org-export-html
   :version "24.4"
   :package-version '(Org . "8.0")
@@ -1422,6 +1427,23 @@ not be modified."
 
 ;;;; Template :: Styles
 
+(defcustom org-html-meta-tags #'org-html-meta-tags-default
+  "Form that is used to produce meta tags in the HTML head.
+
+Can be a list where each item is a list of arguments to be passed
+to `org-html--build-meta-entry'.  Any nil items are ignored.
+
+Also accept a function which gives such a list when called with a
+single argument (INFO, a communication plist)."
+  :group 'org-export-html
+  :package-version '(Org . "9.5")
+  :type '(choice
+         (repeat
+          (list (string :tag "Meta label")
+                (string :tag "label value")
+                (string :tag "Content value")))
+         function))
+
 (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
@@ -1444,14 +1466,12 @@ done, timestamp, timestamp-kwd, tag, target.
 
 For example, a valid value would be:
 
-   <style type=\"text/css\">
-    /*<![CDATA[*/
+   <style>
       p { font-weight: normal; color: gray; }
       h1 { color: black; }
       .title { text-align: center; }
       .todo, .timestamp-kwd { color: red; }
       .done { color: green; }
-    /*]]>*/
    </style>
 
 If you want to refer to an external style, use something like
@@ -1585,7 +1605,7 @@ CSS classes, then this prefix can be very useful."
 
 (defun org-html-html5-p (info)
   (let ((dt (downcase (plist-get info :html-doctype))))
-       (member dt '("html5" "xhtml5" "<!doctype html>"))))
+    (member dt '("html5" "xhtml5" "<!doctype html>"))))
 
 (defun org-html--html5-fancy-p (info)
   "Non-nil when exporting to HTML5 with fancy elements.
@@ -1677,43 +1697,20 @@ 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."
-  (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
-                      (concat "^" org-preview-latex-image-directory) 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."))))
+  (org-html-close-tag
+   "img"
+   (org-html--make-attribute-string
+    (org-combine-plists
+     (list :src source
+           :alt (if (string-match-p
+                     (concat "^" org-preview-latex-image-directory) source)
+                    (org-html-encode-plain-text
+                     (org-find-text-property-in-string 'org-latex-src source))
+                  (file-name-nondirectory source)))
+     (if (string= "svg" (file-name-extension source))
+         (org-combine-plists '(:class "org-svg") attributes '(:fallback nil))
+       attributes)))
+   info))
 
 (defun org-html--textarea-block (element)
   "Transcode ELEMENT into a textarea block.
@@ -1817,12 +1814,12 @@ INFO is a plist used as a communication channel."
                    (anchor (org-html--anchor
                             (format "fn.%d" n)
                             n
-                            (format " class=\"footnum\" href=\"#fnr.%d\"" n)
+                            (format " class=\"footnum\" href=\"#fnr.%d\" 
role=\"doc-backlink\"" n)
                             info))
                    (contents (org-trim (org-export-data def info))))
                (format "<div class=\"footdef\">%s %s</div>\n"
                        (format (plist-get info :html-footnote-format) anchor)
-                       (format "<div class=\"footpara\">%s</div>"
+                       (format "<div class=\"footpara\" 
role=\"doc-footnote\">%s</div>"
                                (if (not inline?) contents
                                  (format "<p class=\"footpara\">%s</p>"
                                          contents))))))))
@@ -1832,78 +1829,93 @@ INFO is a plist used as a communication channel."
 
 ;;; Template
 
+(defun org-html-meta-tags-default (info)
+  "A default value for `org-html-meta-tags'.
+
+Generate a list items, each of which is a list of arguments that can
+be passed to `org-html--build-meta-entry', to generate meta tags to be
+included in the HTML head.
+
+Use document's plist INFO to derive relevant information for the tags."
+  (let ((author (and (plist-get info :with-author)
+                     (let ((auth (plist-get info :author)))
+                       ;; Return raw Org syntax.
+                       (and auth (org-element-interpret-data auth))))))
+    (list
+     (when (org-string-nw-p author)
+       (list "name" "author" author))
+     (when (org-string-nw-p (plist-get info :description))
+       (list "name" "description"
+             (plist-get info :description)))
+     (when (org-string-nw-p (plist-get info :keywords))
+       (list "name" "keywords" (plist-get info :keywords)))
+     '("name" "generator" "Org Mode"))))
+
+(defun org-html--build-meta-entry
+    (label identity &optional content-format &rest content-formatters)
+  "Build a meta tag using the provided information.
+
+Construct <meta> tag of form <meta LABEL=\"IDENTITY\" />, or when 
CONTENT-FORMAT
+is present: <meta LABEL=\"IDENTITY\" content=\"{content}\" />
+
+Here {content} is determined by applying any CONTENT-FORMATTERS to the
+CONTENT-FORMAT and encoding the result as plain text."
+  (concat "<meta "
+         (format "%s=\"%s" label identity)
+         (when content-format
+           (concat "\" content=\""
+                   (replace-regexp-in-string
+                    "\"" "&quot;"
+                    (org-html-encode-plain-text
+                     (if content-formatters
+                         (apply #'format content-format content-formatters)
+                       content-format)))))
+         "\" />\n"))
+
 (defun org-html--build-meta-info (info)
   "Return meta tags for exported document.
 INFO is a plist used as a communication channel."
-  (let* ((protect-string
-          (lambda (str)
-            (replace-regexp-in-string
-             "\"" "&quot;" (org-html-encode-plain-text str))))
-         (title (org-export-data (plist-get info :title) info))
-         ;; Set title to an invisible character instead of leaving it
-         ;; empty, which is invalid.
-         (title (if (org-string-nw-p title) title "&lrm;"))
-         (author (and (plist-get info :with-author)
-                      (let ((auth (plist-get info :author)))
-                       ;; Return raw Org syntax.
-                        (and auth (org-element-interpret-data auth)))))
-         (description (plist-get info :description))
-         (keywords (plist-get info :keywords))
-         (charset (or (and org-html-coding-system
-                           (fboundp 'coding-system-get)
-                           (coding-system-get org-html-coding-system
-                                              'mime-charset))
-                      "iso-8859-1")))
+  (let* ((title (org-html-plain-text
+                (org-element-interpret-data (plist-get info :title)) info))
+        ;; Set title to an invisible character instead of leaving it
+        ;; empty, which is invalid.
+        (title (if (org-string-nw-p title) title "&lrm;"))
+        (charset (or (and org-html-coding-system
+                          (fboundp 'coding-system-get)
+                          (symbol-name
+                           (coding-system-get org-html-coding-system
+                                              'mime-charset)))
+                     "iso-8859-1")))
     (concat
      (when (plist-get info :time-stamp-file)
        (format-time-string
        (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" "http-equiv=\"Content-Type\" content=\"text/html;charset=%s\""
-        info))
-      charset) "\n"
+
+     (if (org-html-html5-p info)
+        (org-html--build-meta-entry "charset" charset)
+       (org-html--build-meta-entry "http-equiv" "Content-Type"
+                                  (concat "text/html;charset=" charset)))
+
      (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")))
+       (if viewport-options
+          (org-html--build-meta-entry "name" "viewport"
+                                      (mapconcat
+                                       (lambda (elm)
+                                          (format "%s=%s" (car elm) (cadr 
elm)))
+                                       viewport-options ", "))))
+
      (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\""
-                                      (funcall protect-string author))
-                              info)
-          "\n"))
-     (and (org-string-nw-p description)
-         (concat
-          (org-html-close-tag "meta"
-                              (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\""
-                                      (funcall protect-string keywords))
-                              info)
-          "\n")))))
+
+     (mapconcat
+      (lambda (args) (apply #'org-html--build-meta-entry args))
+      (delq nil (if (functionp org-html-meta-tags)
+                   (funcall org-html-meta-tags info)
+                 org-html-meta-tags))
+      ""))))
 
 (defun org-html--build-head (info)
   "Return information for the <head>..</head> of the HTML output.
@@ -2085,7 +2097,10 @@ holding export options."
    (org-html--build-pre/postamble 'preamble info)
    ;; Document contents.
    (let ((div (assq 'content (plist-get info :html-divs))))
-     (format "<%s id=\"%s\">\n" (nth 1 div) (nth 2 div)))
+     (format "<%s id=\"%s\" class=\"%s\">\n"
+             (nth 1 div)
+             (nth 2 div)
+             (plist-get info :html-content-class)))
    ;; Document title.
    (when (plist-get info :with-title)
      (let ((title (and (plist-get info :with-title)
@@ -2101,7 +2116,7 @@ holding export options."
          (if subtitle
              (format
               (if html5-fancy
-                  "<p class=\"subtitle\">%s</p>\n"
+                  "<p class=\"subtitle\" role=\"doc-subtitle\">%s</p>\n"
                 (concat "\n" (org-html-close-tag "br" nil info) "\n"
                         "<span class=\"subtitle\">%s</span>\n"))
               (org-export-data subtitle info))
@@ -2229,7 +2244,7 @@ is the language used for CODE, as a string, or nil."
            (if (and beg end) (substring code beg end) code)))))))))
 
 (defun org-html-do-format-code
-  (code &optional lang refs retain-labels num-start wrap-lines)
+    (code &optional lang refs retain-labels num-start wrap-lines)
   "Format CODE string as source code.
 Optional arguments LANG, REFS, RETAIN-LABELS, NUM-START, WRAP-LINES
 are, respectively, the language of the source code, as a string, an
@@ -2302,14 +2317,14 @@ of contents as a string, or nil if it is empty."
                         (org-export-get-relative-level headline info)))
                 (org-export-collect-headlines info depth scope))))
     (when toc-entries
-      (let ((toc (concat "<div id=\"text-table-of-contents\">"
+      (let ((toc (concat "<div id=\"text-table-of-contents\" role=\"doc-toc\">"
                         (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)
+           (concat (format "<%s id=\"table-of-contents\" role=\"doc-toc\">\n" 
outer-tag)
                    (let ((top-level (plist-get info :html-toplevel-hlevel)))
                      (format "<h%d>%s</h%d>\n"
                              top-level
@@ -2582,7 +2597,7 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
      (format
       (plist-get info :html-footnote-format)
       (org-html--anchor
-       id n (format " class=\"footref\" href=\"#fn.%d\"" n) info)))))
+       id n (format " class=\"footref\" href=\"#fn.%d\" role=\"doc-backlink\"" 
n) info)))))
 
 ;;;; Headline
 
@@ -2717,7 +2732,7 @@ holding contextual information."
             todo todo-type priority text tags contents info)))
 
 (defun org-html-format-inlinetask-default-function
-  (todo todo-type priority text tags contents info)
+    (todo todo-type priority text tags contents info)
   "Default format function for inlinetasks.
 See `org-html-format-inlinetask-function' for details."
   (format "<div class=\"inlinetask\">\n<b>%s</b>%s\n%s</div>"
@@ -3462,12 +3477,12 @@ 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))
-         (code (org-html-format-code src-block info))
-         (label (let ((lbl (org-html--reference src-block info t)))
-                  (if lbl (format " id=\"%s\"" lbl) "")))
-         (klipsify  (and  (plist-get info :html-klipsify-src)
-                           (member lang '("javascript" "js"
-                                         "ruby" "scheme" "clojure" "php" 
"html")))))
+          (code (org-html-format-code src-block info))
+          (label (let ((lbl (org-html--reference src-block info t)))
+                   (if lbl (format " id=\"%s\"" lbl) "")))
+          (klipsify  (and  (plist-get info :html-klipsify-src)
+                            (member lang '("javascript" "js"
+                                          "ruby" "scheme" "clojure" "php" 
"html")))))
       (if (not lang) (format "<pre class=\"example\"%s>\n%s</pre>" label code)
        (format "<div class=\"org-src-container\">\n%s%s\n</div>"
                ;; Build caption.
@@ -3771,7 +3786,7 @@ contextual information."
 
 ;;;###autoload
 (defun org-html-export-as-html
-  (&optional async subtreep visible-only body-only ext-plist)
+    (&optional async subtreep visible-only body-only ext-plist)
   "Export current buffer to an HTML buffer.
 
 If narrowing is active in the current buffer, only export its
@@ -3816,7 +3831,7 @@ to convert it."
 
 ;;;###autoload
 (defun org-html-export-to-html
-  (&optional async subtreep visible-only body-only ext-plist)
+    (&optional async subtreep visible-only body-only ext-plist)
   "Export current buffer to a HTML file.
 
 If narrowing is active in the current buffer, only export its
diff --git a/lisp/ox-icalendar.el b/lisp/ox-icalendar.el
index b8834c4..9170059 100644
--- a/lisp/ox-icalendar.el
+++ b/lisp/ox-icalendar.el
@@ -2,8 +2,9 @@
 
 ;; Copyright (C) 2004-2021 Free Software Foundation, Inc.
 
-;; Author: Carsten Dominik <carsten at orgmode dot org>
+;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 ;;      Nicolas Goaziou <n dot goaziou at gmail dot com>
+;; Maintainer: Nicolas Goaziou <n.goaziou at gmail dot com>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: https://orgmode.org
 
@@ -32,6 +33,7 @@
 ;;; Code:
 
 (require 'cl-lib)
+(require 'org-agenda)
 (require 'ox-ascii)
 (declare-function org-bbdb-anniv-export-ical "ol-bbdb" nil)
 
@@ -281,7 +283,6 @@ re-read the iCalendar file.")
                     (inlinetask . ignore)
                     (planning . ignore)
                     (section . ignore)
-                    (inner-template . (lambda (c i) c))
                     (template . org-icalendar-template))
   :options-alist
   '((:exclude-tags
@@ -370,7 +371,6 @@ A headline is blocked when either
                   (1- (length org-icalendar-date-time-format)))
              ?Z))
 
-(defvar org-agenda-default-appointment-duration) ; From org-agenda.el.
 (defun org-icalendar-convert-timestamp (timestamp keyword &optional end tz)
   "Convert TIMESTAMP to iCalendar format.
 
@@ -722,7 +722,7 @@ Return VEVENT component as a string."
             "END:VEVENT"))))
 
 (defun org-icalendar--vtodo
-  (entry uid summary location description categories timezone class)
+    (entry uid summary location description categories timezone class)
   "Create a VTODO component.
 
 ENTRY is either a headline or an inlinetask element.  UID is the
@@ -849,7 +849,7 @@ CALSCALE:GREGORIAN\n"
 
 ;;;###autoload
 (defun org-icalendar-export-to-ics
-  (&optional async subtreep visible-only body-only)
+    (&optional async subtreep visible-only body-only)
   "Export current buffer to an iCalendar file.
 
 If narrowing is active in the current buffer, only export its
diff --git a/contrib/lisp/ox-koma-letter.el b/lisp/ox-koma-letter.el
similarity index 99%
rename from contrib/lisp/ox-koma-letter.el
rename to lisp/ox-koma-letter.el
index a386048..3bd2f68 100644
--- a/contrib/lisp/ox-koma-letter.el
+++ b/lisp/ox-koma-letter.el
@@ -6,8 +6,11 @@
 ;;         Alan Schmitt <alan.schmitt AT polytechnique DOT org>
 ;;         Viktor Rosenfeld <listuser36 AT gmail DOT com>
 ;;         Rasmus Pank Roulund <emacs AT pank DOT eu>
+;; Maintainer: Marco Wahl <marcowahlsoft@gmail.com>
 ;; Keywords: org, wp, tex
 
+;; 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
@@ -19,7 +22,7 @@
 ;; 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/>.
+;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 ;;
@@ -74,8 +77,8 @@
 ;;
 ;; The following variables works differently from the main LaTeX class
 ;;   - AUTHOR: Default to user-full-name but may be disabled.
-;;     (See also `org-koma-letter-author'),
-;;   - EMAIL: Same as AUTHOR. (see also `org-koma-letter-email'),
+;;     (See also `org-koma-letter-author'.)
+;;   - EMAIL: Same as AUTHOR.  (See also `org-koma-letter-email'.)
 ;;
 ;; FROM_LOGO uses LaTeX markup.  FROM_LOGO provides the
 ;; "includegraphics" command to tell LaTeX where to find the logo.
@@ -475,7 +478,7 @@ e.g. \"title-subject:t\"."
   "Header tags to be inserted in the letter after closing.")
 
 (defconst org-koma-letter-special-tags-as-macro '(ps encl cc)
-  "Header tags to be inserted as macros")
+  "Header tags to be inserted as macros.")
 
 (defconst org-koma-letter-special-tags-after-letter '(after_letter)
   "Header tags to be inserted after the letter.")
@@ -604,7 +607,7 @@ such as the one tagged with PS."
 
 
 (defun org-koma-letter--add-latex-newlines (string)
-  "Replace regular newlines with LaTeX newlines (i.e. `\\\\')"
+  "Replace regular newlines with LaTeX newlines (i.e. `\\\\')."
   (let ((str (org-trim string)))
     (when (org-string-nw-p str)
       (replace-regexp-in-string "\n" "\\\\\\\\\n" str))))
diff --git a/lisp/ox-latex.el b/lisp/ox-latex.el
index 28484dc..993c2c6 100644
--- a/lisp/ox-latex.el
+++ b/lisp/ox-latex.el
@@ -121,6 +121,7 @@
     (: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-quote-environment nil nil 
org-latex-default-quote-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)
@@ -296,7 +297,7 @@
     ("uk" "ukrainian")
     ("ur" "urdu")
     ("vi" "vietnamese"))
-  "Alist between language code and corresponding Polyglossia option")
+  "Alist between language code and corresponding Polyglossia option.")
 
 (defconst org-latex-table-matrix-macros '(("bordermatrix" . "\\cr")
                                          ("qbordermatrix" . "\\cr")
@@ -307,14 +308,14 @@
   (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")))
+    '("equation" "eqnarray" "math" "displaymath"
+      "align"  "gather" "multline" "flalign"  "alignat"
+      "xalignat" "xxalignat"
+      "subequations"
+      ;; breqn
+      "dmath" "dseries" "dgroup" "darray"
+      ;; empheq
+      "empheq")))
   "Regexp of LaTeX math environments.")
 
 
@@ -345,7 +346,7 @@ symbols are: `image', `table', `src-block' and 
`special-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.
+  "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
@@ -380,6 +381,9 @@ will be exported to LaTeX as:
   This is section \\ref{sec:foo}.
   And this is still section \\ref{sec:foo}.
 
+A non-default value of `org-latex-reference-command' will change the
+command (\\ref by default) used to create label references.
+
 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.
@@ -399,6 +403,18 @@ references."
   :version "26.1"
   :package-version '(Org . "8.3"))
 
+(defcustom org-latex-reference-command "\\ref{%s}"
+  "Format string that takes a reference to produce a LaTeX reference command.
+
+The reference is a label such as sec:intro.  A format string of \"\\ref{%s}\"
+produces numbered references and will always work.  It may be desirable to make
+use of a package such as hyperref or cleveref and then change the format string
+to \"\\autoref{%s}\" or \"\\cref{%s}\" for example."
+  :group 'org-export-latex
+  :type 'string
+  :package-version '(Org . "9.5")
+  :safe t)
+
 ;;;; Preamble
 
 (defcustom org-latex-default-class "article"
@@ -772,6 +788,13 @@ default we use here encompasses both."
   :package-version '(Org . "8.0")
   :type 'string)
 
+(defcustom org-latex-default-quote-environment "quote"
+  "Default environment used to `quote' blocks."
+  :group 'org-export-latex
+  :package-version '(Org . "9.5")
+  :type 'string
+  :safe t)
+
 (defcustom org-latex-default-table-mode 'table
   "Default mode for tables.
 
@@ -932,7 +955,7 @@ using customize, or with
   (add-to-list \\='org-latex-packages-alist \\='(\"newfloat\" \"minted\"))
 
 In addition, it is necessary to install pygments
-\(URL `http://pygments.org>'), and to configure the variable
+\(URL `https://pygments.org>'), and to configure the variable
 `org-latex-pdf-process' so that the -shell-escape option is
 passed to pdflatex.
 
@@ -1157,9 +1180,11 @@ A better approach is to use a compiler suit such as 
`latexmk'."
   :package-version '(Org . "9.0"))
 
 (defcustom org-latex-pdf-process
-  '("%latex -interaction nonstopmode -output-directory %o %f"
-    "%latex -interaction nonstopmode -output-directory %o %f"
-    "%latex -interaction nonstopmode -output-directory %o %f")
+  (if (executable-find "latexmk")
+      '("latexmk -f -pdf -%latex -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
@@ -1203,7 +1228,7 @@ file name as its single argument."
          (const :tag "texi2dvi"
                 ("cd %o; LATEX=\"%latex\" texi2dvi -p -b -V %b.tex"))
          (const :tag "latexmk"
-                ("latexmk -g -pdf -pdflatex=\"%latex\" -outdir=%o %f"))
+                ("latexmk -f -pdf -%latex -interaction=nonstopmode 
-output-directory=%o %f"))
          (function)))
 
 (defcustom org-latex-logfiles-extensions
@@ -1486,7 +1511,10 @@ nil."
               (pcase-let ((`(,keyword ,value) pair))
                 (concat keyword
                         (and (> (length value) 0)
-                             (concat "=" value)))))
+                             (concat "="
+                                      (if (string-match-p (rx (any "[]")) 
value)
+                                          (format "{%s}" value)
+                                        value))))))
             options
             ","))
 
@@ -1605,9 +1633,9 @@ INFO is a plist used as a communication channel."
   "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))))
+    (and (org-string-nw-p org-latex-compiler-file-string)
+        (member (or compiler "") org-latex-compilers)
+        (format org-latex-compiler-file-string compiler))))
 
 
 ;;; Filters
@@ -1889,10 +1917,11 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
                (org-export-get-footnote-definition footnote-reference info)
                info t)))
       ;; Use \footnotemark if reference is within another footnote
-      ;; reference, footnote definition, table cell or item's tag.
+      ;; reference, footnote definition, table cell, verse block, or
+      ;; item's tag.
       ((or (org-element-lineage footnote-reference
                                '(footnote-reference footnote-definition
-                                                    table-cell))
+                                                    table-cell verse-block))
           (eq 'item (org-element-type
                      (org-export-get-parent-element footnote-reference))))
        "\\footnotemark")
@@ -1904,7 +1933,8 @@ CONTENTS is nil.  INFO is a plist holding contextual 
information."
                  ;; Only insert a \label if there exist another
                  ;; reference to def.
                  (cond ((not label) "")
-                       ((org-element-map (plist-get info :parse-tree) 
'footnote-reference
+                       ((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)
@@ -2096,8 +2126,8 @@ contextual information."
   (let* ((code (org-element-property :value inline-src-block))
         (separator (org-latex--find-verb-separator code)))
     (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)))
+      ;; Do not use a special package: transcode it verbatim, as code.
+      ((nil) (org-latex--text-markup code 'code info))
       ;; Use minted package.
       (minted
        (let* ((org-lang (org-element-property :language inline-src-block))
@@ -2382,8 +2412,8 @@ used as a communication channel."
                        ((string= float "sideways") 'sideways)
                        ((string= float "multicolumn") 'multicolumn)
                        ((and (plist-member attr :float) (not float)) 'nonfloat)
-                       ((or float
-                            (org-element-property :caption parent)
+                        (float float)
+                       ((or (org-element-property :caption parent)
                             (org-string-nw-p (plist-get attr :caption)))
                         'figure)
                        (t 'nonfloat))))
@@ -2475,6 +2505,18 @@ used as a communication channel."
                                                   nil t))))
     ;; Return proper string, depending on FLOAT.
     (pcase float
+      ((and (pred stringp) env-string)
+       (format "\\begin{%s}%s
+%s%s
+%s%s
+%s\\end{%s}"
+               env-string
+               placement
+               (if caption-above-p caption "")
+               (if center "\\centering" "")
+               comment-include image-code
+               (if caption-above-p "" caption)
+               env-string))
       (`wrap (format "\\begin{wrapfigure}%s
 %s%s
 %s%s
@@ -2581,7 +2623,7 @@ INFO is a plist holding contextual information.  See
           (let ((label (org-latex--label destination info t)))
             (if (and (not desc)
                      (org-export-numbered-headline-p destination info))
-                (format "\\ref{%s}" label)
+                (format org-latex-reference-command label)
               (format "\\hyperref[%s]{%s}" label
                       (or desc
                           (org-export-data
@@ -2589,7 +2631,7 @@ INFO is a plist holding contextual information.  See
           ;; Fuzzy link points to a target.  Do as above.
          (otherwise
           (let ((ref (org-latex--label destination info t)))
-            (if (not desc) (format "\\ref{%s}" ref)
+            (if (not desc) (format org-latex-reference-command ref)
               (format "\\hyperref[%s]{%s}" ref desc)))))))
      ;; Coderef: replace link with the reference name or the
      ;; equivalent line number.
@@ -2881,9 +2923,19 @@ channel."
   "Transcode a QUOTE-BLOCK element from Org to LaTeX.
 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) info))
-
+  (let ((environment
+        (or (org-export-read-attribute :attr_latex quote-block :environment)
+            (plist-get info :latex-default-quote-environment)))
+       (options
+        (or (org-export-read-attribute :attr_latex quote-block :options)
+            "")))
+    (org-latex--wrap-label
+     quote-block (format "\\begin{%s}%s\n%s\\end{%s}"
+                        environment
+                        options
+                        contents
+                        environment)
+     info)))
 
 ;;;; Radio Target
 
@@ -3203,9 +3255,9 @@ centered."
 (defun org-latex--decorate-table (table attributes caption above? info)
   "Decorate TABLE string with caption and float environment.
 
-ATTRIBUTES is the plist containing is LaTeX attributes.  CAPTION
-is its caption, as a string or nil.  It is located above the
-table if ABOVE? is non-nil.  INFO is the plist containing current
+ATTRIBUTES is the plist containing LaTeX attributes.  CAPTION is
+its caption, as a string or nil.  It is located above the table
+if ABOVE? is non-nil.  INFO is the plist containing current
 export parameters.
 
 Return new environment, as a string."
@@ -3214,7 +3266,8 @@ Return new environment, as a string."
            (cond ((and (not float) (plist-member attributes :float)) nil)
                  ((member float '("sidewaystable" "sideways")) "sidewaystable")
                  ((equal float "multicolumn") "table*")
-                 ((or float (org-string-nw-p caption)) "table")
+                  (float float)
+                 ((org-string-nw-p caption) "table")
                  (t nil))))
         (placement
          (or (plist-get attributes :placement)
@@ -3509,29 +3562,44 @@ channel."
   "Transcode a VERSE-BLOCK element from Org to LaTeX.
 CONTENTS is verse block contents.  INFO is a plist holding
 contextual information."
-  (org-latex--wrap-label
-   verse-block
-   ;; In a verse environment, add a line break to each newline
-   ;; 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.
-   (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))
-
+  (let* ((lin (org-export-read-attribute :attr_latex verse-block :lines))
+         (latcode (org-export-read-attribute :attr_latex verse-block 
:latexcode))
+         (cent (org-export-read-attribute :attr_latex verse-block :center))
+         (attr (concat
+               (if cent "[\\versewidth]" "")
+               (if lin (format "\n\\poemlines{%s}" lin) "")
+               (if latcode (format "\n%s" latcode) "")))
+         (versewidth (org-export-read-attribute :attr_latex verse-block 
:versewidth))
+         (vwidth (if versewidth (format "\\settowidth{\\versewidth}{%s}\n" 
versewidth) ""))
+         (linreset (if lin "\n\\poemlines{0}" "")))
+    (concat
+     (org-latex--wrap-label
+      verse-block
+      ;; In a verse environment, add a line break to each newline
+      ;; 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.
+      (format "%s\\begin{verse}%s\n%s\\end{verse}%s"
+             vwidth
+             attr
+             (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) linreset)
+      info)
+     ;; Insert footnote definitions, if any, after the environment, so
+     ;; the special formatting above is not applied to them.
+     (org-latex--delayed-footnotes-definitions verse-block info))))
 
 
 ;;; End-user functions
 
 ;;;###autoload
 (defun org-latex-export-as-latex
-  (&optional async subtreep visible-only body-only ext-plist)
+    (&optional async subtreep visible-only body-only ext-plist)
   "Export current buffer as a LaTeX buffer.
 
 If narrowing is active in the current buffer, only export its
@@ -3575,7 +3643,7 @@ command to convert it."
 
 ;;;###autoload
 (defun org-latex-export-to-latex
-  (&optional async subtreep visible-only body-only ext-plist)
+    (&optional async subtreep visible-only body-only ext-plist)
   "Export current buffer to a LaTeX file.
 
 If narrowing is active in the current buffer, only export its
@@ -3607,7 +3675,7 @@ file-local settings."
 
 ;;;###autoload
 (defun org-latex-export-to-pdf
-  (&optional async subtreep visible-only body-only ext-plist)
+    (&optional async subtreep visible-only body-only ext-plist)
   "Export current buffer to LaTeX then process through to PDF.
 
 If narrowing is active in the current buffer, only export its
diff --git a/lisp/ox-man.el b/lisp/ox-man.el
index 6cace7e..6d3476c 100644
--- a/lisp/ox-man.el
+++ b/lisp/ox-man.el
@@ -1,4 +1,4 @@
-;; ox-man.el --- Man Back-End for Org Export Engine -*- lexical-binding: t; -*-
+;;; ox-man.el --- Man Back-End for Org Export Engine -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2011-2021 Free Software Foundation, Inc.
 
@@ -186,7 +186,7 @@ When nil, no transformation is made."
     (ldap "ldap") (opa "opa")
     (php "php") (postscript "postscript") (prolog "prolog")
     (properties "properties") (makefile "makefile")
-    (tml "tml") (vala "vala") (vbscript "vbscript") (xorg "xorg"))
+    (tml "tml") (vbscript "vbscript") (xorg "xorg"))
   "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
@@ -301,12 +301,12 @@ CONTENTS is the transcoded contents string.  INFO is a 
plist
 holding export options."
   (let* ((title (when (plist-get info :with-title)
                  (org-export-data (plist-get info :title) info)))
-        (attr (read (format "(%s)"
-                            (mapconcat
-                             #'identity
-                             (list (plist-get info :man-class-options))
-                             " "))))
-        (section-item (plist-get attr :section-id)))
+         (attr (read (format "(%s)"
+                             (mapconcat
+                              #'identity
+                              (list (plist-get info :man-class-options))
+                              " "))))
+         (section-item (plist-get attr :section-id)))
 
     (concat
 
@@ -365,9 +365,9 @@ holding contextual information."
 
 (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.
-   INFO is a plist holding contextual information. "
+DRAWER holds the drawer information
+CONTENTS holds the contents of the block.
+INFO is a plist holding contextual information."
   contents)
 
 
@@ -825,10 +825,10 @@ contextual information."
    ;; Case 1: verbatim table.
    ((or (plist-get info :man-tables-verbatim)
         (let ((attr (read (format "(%s)"
-                 (mapconcat
-                  #'identity
-                  (org-element-property :attr_man table)
-                  " ")))))
+                                  (mapconcat
+                                   #'identity
+                                   (org-element-property :attr_man table)
+                                   " ")))))
 
           (and attr (plist-get attr :verbatim))))
 
@@ -1053,7 +1053,7 @@ contextual information."
 ;;; Interactive functions
 
 (defun org-man-export-to-man
-  (&optional async subtreep visible-only body-only ext-plist)
+    (&optional async subtreep visible-only body-only ext-plist)
   "Export current buffer to a Man file.
 
 If narrowing is active in the current buffer, only export its
@@ -1086,7 +1086,7 @@ Return output file's name."
       async subtreep visible-only body-only ext-plist)))
 
 (defun org-man-export-to-pdf
-  (&optional async subtreep visible-only body-only ext-plist)
+    (&optional async subtreep visible-only body-only ext-plist)
   "Export current buffer to Groff then process through to PDF.
 
 If narrowing is active in the current buffer, only export its
diff --git a/lisp/ox-md.el b/lisp/ox-md.el
index f4afe6b..348b6d0 100644
--- a/lisp/ox-md.el
+++ b/lisp/ox-md.el
@@ -3,6 +3,7 @@
 ;; Copyright (C) 2012-2021 Free Software Foundation, Inc.
 
 ;; Author: Nicolas Goaziou <n.goaziou@gmail.com>
+;; Maintainer: Nicolas Goaziou <n.goaziou at gmail dot com>
 ;; Keywords: org, wp, markdown
 
 ;; This file is part of GNU Emacs.
@@ -57,10 +58,10 @@ This variable can be set to either `atx' or `setext'."
   "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"))
+  :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.
@@ -100,6 +101,8 @@ The %s will be replaced by the footnote reference itself."
                     (italic . org-md-italic)
                     (item . org-md-item)
                     (keyword . org-md-keyword)
+                     (latex-environment . org-md-latex-environment)
+                     (latex-fragment . org-md-latex-fragment)
                     (line-break . org-md-line-break)
                     (link . org-md-link)
                     (node-property . org-md-node-property)
@@ -210,9 +213,9 @@ the section."
                (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")))))
+      ;; Use "Atx" style
+      (let ((level-mark (make-string level ?#)))
+        (concat "\n" anchor-lines level-mark " " title tags "\n\n")))))
 
 (defun org-md--build-toc (info &optional n _keyword scope)
   "Return a table of contents.
@@ -460,6 +463,35 @@ channel."
     (_ (org-export-with-backend 'html keyword contents info))))
 
 
+;;;; Latex Environment
+
+(defun org-md-latex-environment (latex-environment _contents info)
+  "Transcode a LATEX-ENVIRONMENT object from Org to Markdown.
+CONTENTS is nil.  INFO is a plist holding contextual information."
+  (when (plist-get info :with-latex)
+    (let ((latex-frag (org-remove-indentation
+                       (org-element-property :value latex-environment)))
+          (label (org-html--reference latex-environment info t)))
+      (if (org-string-nw-p label)
+          (replace-regexp-in-string "\\`.*"
+                                    (format "\\&\n\\\\label{%s}" label)
+                                    latex-frag)
+        latex-frag))))
+
+;;;; Latex Fragment
+
+(defun org-md-latex-fragment (latex-fragment _contents info)
+  "Transcode a LATEX-FRAGMENT object from Org to Markdown.
+CONTENTS is nil.  INFO is a plist holding contextual information."
+  (when (plist-get info :with-latex)
+    (let ((frag (org-element-property :value latex-fragment)))
+      (cond
+       ((string-match-p "^\\\\(" frag)
+        (concat "$" (substring frag 2 -2) "$"))
+       ((string-match-p "^\\\\\\[" frag)
+        (concat "$$" (substring frag 2 -2) "$$"))
+       (t frag))))) ; either already $-deliminated or a macro
+
 ;;;; Line Break
 
 (defun org-md-line-break (_line-break _contents _info)
@@ -543,7 +575,12 @@ INFO is a plist holding contextual information.  See
      ((string= type "coderef")
       (format (org-export-get-coderef-format path desc)
              (org-export-resolve-coderef path info)))
-     ((equal type "radio") desc)
+     ((string= type "radio")
+      (let ((destination (org-export-resolve-radio-link link info)))
+       (if (not destination) desc
+         (format "<a href=\"#%s\">%s</a>"
+                 (org-export-get-reference destination info)
+                 desc))))
      (t (if (not desc) (format "<%s>" path)
          (format "[%s](%s)" desc path))))))
 
diff --git a/lisp/ox-odt.el b/lisp/ox-odt.el
index 2d550d9..f186ebb 100644
--- a/lisp/ox-odt.el
+++ b/lisp/ox-odt.el
@@ -251,7 +251,7 @@ Use `org-odt-add-automatic-style' to add update this 
variable.'")
 
 (defvar org-odt-object-counters nil
   "Running counters for various OBJECT-TYPEs.
-Use this to generate automatic names and style-names. See
+Use this to generate automatic names and style-names.  See
 `org-odt-add-automatic-style'.")
 
 (defvar org-odt-src-block-paragraph-format
@@ -277,8 +277,7 @@ according to the default face identified by the 
`htmlfontify'.")
 (defvar org-odt-default-image-sizes-alist
   '(("as-char" . (5 . 0.4))
     ("paragraph" . (5 . 5)))
-  "Hardcoded image dimensions one for each of the anchor
-  methods.")
+  "Hardcoded image dimensions one for each of the anchor methods.")
 
 ;; A4 page size is 21.0 by 29.7 cms
 ;; The default page settings has 2cm margin on each of the sides. So
@@ -450,7 +449,7 @@ Valid values are one of:
 4. list of the form (ODT-OR-OTT-FILE (FILE-MEMBER-1 FILE-MEMBER-2
 ...))
 
-In case of option 1, an in-built styles.xml is used. See
+In case of option 1, an in-built styles.xml is used.  See
 `org-odt-styles-dir' for more information.
 
 In case of option 3, the specified file is unzipped and the
@@ -982,7 +981,7 @@ See `org-odt--build-date-styles' for implementation 
details."
 ;;;; Frame
 
 (defun org-odt--frame (text width height style &optional extra
-                             anchor-type &rest title-and-desc)
+                           anchor-type &rest title-and-desc)
   (let ((frame-attrs
         (concat
          (if width (format " svg:width=\"%0.2fcm\"" width) "")
@@ -1044,7 +1043,7 @@ See `org-odt--build-date-styles' for implementation 
details."
 ;;;; Textbox
 
 (defun org-odt--textbox (text width height style &optional
-                               extra anchor-type)
+                             extra anchor-type)
   (org-odt--frame
    (format "\n<draw:text-box %s>%s\n</draw:text-box>"
           (concat (format " fo:min-height=\"%0.2fcm\"" (or height .2))
@@ -1778,8 +1777,8 @@ INFO is a plist holding contextual information."
          (if (functionp format-function) format-function
            (cl-function
             (lambda (todo todo-type priority text tags
-                     &key _level _section-number _headline-label
-                     &allow-other-keys)
+                          &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
@@ -1852,7 +1851,7 @@ holding contextual information."
         contents))))))
 
 (defun org-odt-format-headline-default-function
-  (todo todo-type priority text tags)
+    (todo todo-type priority text tags)
   "Default format function for a headline.
 See `org-odt-format-headline-function' for details."
   (concat
@@ -1930,7 +1929,7 @@ holding contextual information."
             todo todo-type priority text tags contents)))
 
 (defun org-odt-format-inlinetask-default-function
-  (todo todo-type priority name tags contents)
+    (todo todo-type priority name tags contents)
   "Default format function for inlinetasks.
 See `org-odt-format-inlinetask-function' for details."
   (format "\n<text:p text:style-name=\"%s\">%s</text:p>"
@@ -2111,7 +2110,8 @@ SHORT-CAPTION are strings."
         (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))
+        ;; (short-caption nil)
+        )
     (when (or label caption)
       (let* ((default-category
               (cl-case (org-element-type element)
@@ -2159,7 +2159,7 @@ SHORT-CAPTION are strings."
                           "<text:sequence text:ref-name=\"%s\" 
text:name=\"%s\" text:formula=\"ooow:%s+1\" 
style:num-format=\"1\">%s</text:sequence>"
                           label counter counter seqno))
                   (?c . ,(or caption "")))))
-              short-caption))
+              nil)) ;; short-caption
            ;; Case 2: Handle Label reference.
            (reference
             (let* ((fmt (cddr (assoc-string label-style org-odt-label-styles 
t)))
@@ -2175,7 +2175,7 @@ SHORT-CAPTION are strings."
 ;;;; Links :: Inline Images
 
 (defun org-odt--copy-image-file (path)
-  "Return the internal name of the file"
+  "Return the internal name of the file."
   (let* ((image-type (file-name-extension path))
         (media-type (format "image/%s" image-type))
         (target-dir "Images/")
@@ -2198,7 +2198,7 @@ SHORT-CAPTION are strings."
 (declare-function image-size "image.c" (spec &optional pixels frame))
 
 (defun org-odt--image-size
-  (file info &optional user-width user-height scale dpi embed-as)
+    (file info &optional user-width user-height scale dpi embed-as)
   (let* ((--pixels-to-cms
           (lambda (pixels dpi)
             (let ((cms-per-inch 2.54)
@@ -2362,14 +2362,14 @@ used as a communication channel."
         ;; If yes, note down its contents.  It will go in to frame
         ;; description.  This quite useful for debugging.
         (desc (and replaces (org-element-property :value replaces)))
-        width height)
+        ) ;; width height
     (cond
      ((eq embed-as 'character)
-      (org-odt--render-image/formula "InlineFormula" href width height
+      (org-odt--render-image/formula "InlineFormula" href nil nil ;; width 
height
                                     nil nil title desc))
      (t
       (let* ((equation (org-odt--render-image/formula
-                       "CaptionedDisplayFormula" href width height
+                       "CaptionedDisplayFormula" href nil nil ;; width height
                        captions nil title desc))
             (label
              (let* ((org-odt-category-map-alist
@@ -2379,7 +2379,7 @@ used as a communication channel."
        (concat equation "<text:tab/>" label))))))
 
 (defun org-odt--copy-formula-file (src-file)
-  "Return the internal name of the file"
+  "Return the internal name of the file."
   (let* ((target-dir (format "Formula-%04d/"
                             (cl-incf org-odt-embedded-formulas-count)))
         (target-file (concat target-dir "content.xml")))
@@ -2399,7 +2399,7 @@ used as a communication channel."
        ;; Case 2: OpenDocument formula.
        ((string= ext "odf")
        (org-odt--zip-extract src-file "content.xml"
-                               (concat org-odt-zip-dir target-dir)))
+                             (concat org-odt-zip-dir target-dir)))
        (t (error "%s is not a formula file" src-file))))
     ;; Enter the formula file in to manifest.
     (org-odt-create-manifest-file-entry "text/xml" target-file)
@@ -2467,15 +2467,14 @@ used as a communication channel."
         (outer (nth 2 frame-cfg))
         ;; User-specified frame params (from #+ATTR_ODT spec)
         (user user-frame-params)
-        (--merge-frame-params (function
-                               (lambda (default user)
-                                 "Merge default and user frame params."
-                                 (if (not user) default
-                                   (cl-assert (= (length default) 3))
-                                   (cl-assert (= (length user) 3))
-                                   (cl-loop for u in user
-                                            for d in default
-                                            collect (or u d)))))))
+        (--merge-frame-params (lambda (default user)
+                                "Merge default and user frame params."
+                                (if (not user) default
+                                  (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
@@ -2651,7 +2650,7 @@ Return nil, otherwise."
           (format "<text:bookmark-ref 
text:reference-format=\"number-all-superior\" 
text:ref-name=\"%s\">%s</text:bookmark-ref>"
                   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.
@@ -3031,7 +3030,7 @@ holding contextual information."
            (anchor (plist-get attributes :anchor)))
        (format "\n<text:p text:style-name=\"%s\">%s</text:p>"
                "Text_20_body" (org-odt--textbox contents width height
-                                                  style extra anchor))))
+                                                style extra anchor))))
      (t contents))))
 
 
@@ -3772,13 +3771,13 @@ contextual information."
                       ;; 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))
+                           (list 'paragraph
+                                 (list :style "OrgFormula"
+                                       :name
+                                       (org-element-property :name latex-*)
+                                       :caption
+                                       (org-element-property :caption 
latex-*)))
+                         link))
                       ;; LaTeX fragment.  No special action.
                       (latex-fragment link))))
                ;; Note down the object that link replaces.
@@ -3841,15 +3840,15 @@ contextual information."
                (mapcar
                 (lambda (item)
                   (org-element-adopt-elements
-                   (list 'item (list :checkbox (org-element-property
-                                                :checkbox item)))
-                   (list 'paragraph (list :style "Text_20_body_20_bold")
-                         (or (org-element-property :tag item) "(no term)"))
-                   (org-element-adopt-elements
-                    (list 'plain-list (list :type 'descriptive-2))
-                    (apply 'org-element-adopt-elements
-                           (list 'item nil)
-                           (org-element-contents item)))))
+                      (list 'item (list :checkbox (org-element-property
+                                                   :checkbox item)))
+                    (list 'paragraph (list :style "Text_20_body_20_bold")
+                          (or (org-element-property :tag item) "(no term)"))
+                    (org-element-adopt-elements
+                        (list 'plain-list (list :type 'descriptive-2))
+                      (apply 'org-element-adopt-elements
+                             (list 'item nil)
+                             (org-element-contents item)))))
                 (org-element-contents el)))))
       nil)
     info)
diff --git a/lisp/ox-org.el b/lisp/ox-org.el
index 26259d8..11d9c09 100644
--- a/lisp/ox-org.el
+++ b/lisp/ox-org.el
@@ -3,6 +3,7 @@
 ;; Copyright (C) 2013-2021 Free Software Foundation, Inc.
 
 ;; Author: Nicolas Goaziou <n.goaziou@gmail.com>
+;; Maintainer: Nicolas Goaziou <n.goaziou at gmail dot com>
 ;; Keywords: org, wp
 
 ;; This file is part of GNU Emacs.
@@ -140,7 +141,7 @@ CONTENTS and INFO are ignored."
 CONTENTS is its contents, as a string or nil.  INFO is ignored."
   (let ((case-fold-search t))
     (replace-regexp-in-string
-     "^[ \t]*#\\+ATTR_[-_A-Za-z0-9]+:\\(?: .*\\)?\n" ""
+     "^[ \t]*#\\+attr_[-_a-za-z0-9]+:\\(?: .*\\)?\n" ""
      (org-export-expand blob contents t))))
 
 (defun org-org-headline (headline contents info)
@@ -184,26 +185,26 @@ as a communication channel."
               (org-element-map (plist-get info :parse-tree) 'keyword
                 (lambda (k)
                   (and (string-equal (org-element-property :key k) "OPTIONS")
-                       (concat "#+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)))
+       (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))))
+              (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))))
+              (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))))
+              (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)))
+       (format "#+creator: %s\n" (plist-get info :creator)))
    contents))
 
 (defun org-org-timestamp (timestamp _contents _info)
@@ -238,7 +239,7 @@ a communication channel."
 
 ;;;###autoload
 (defun org-org-export-as-org
-  (&optional async subtreep visible-only body-only ext-plist)
+    (&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
@@ -273,7 +274,7 @@ non-nil."
 
 ;;;###autoload
 (defun org-org-export-to-org
-  (&optional async subtreep visible-only body-only ext-plist)
+    (&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
diff --git a/lisp/ox-publish.el b/lisp/ox-publish.el
index 6f82b48..bc9b17a 100644
--- a/lisp/ox-publish.el
+++ b/lisp/ox-publish.el
@@ -2,7 +2,7 @@
 ;; Copyright (C) 2006-2021 Free Software Foundation, Inc.
 
 ;; Author: David O'Toole <dto@gnu.org>
-;; Maintainer: Carsten Dominik <carsten at orgmode dot org>
+;; Maintainer: Nicolas Goaziou <n.goaziou at gmail dot com>
 ;; Keywords: hypermedia, outlines, wp
 
 ;; This file is part of GNU Emacs.
@@ -358,7 +358,7 @@ You can overwrite this default per project in your
   (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
@@ -375,7 +375,7 @@ still decide about that independently."
     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))
@@ -617,7 +617,8 @@ files, when entire projects are published (see
                          (abbreviate-file-name filename))))
         (project-plist (cdr project))
         (publishing-function
-         (pcase (org-publish-property :publishing-function project)
+         (pcase (org-publish-property :publishing-function project
+                                       'org-html-publish-to-html)
            (`nil (user-error "No publishing function chosen"))
            ((and f (pred listp)) f)
            (f (list f))))
@@ -1064,7 +1065,7 @@ publishing directory."
                  (setq full-index
                        (sort (nreverse full-index)
                              (lambda (a b) (string< (downcase (car a))
-                                               (downcase (car b)))))))
+                                                    (downcase (car b)))))))
       (let ((index (org-publish-cache-get-file-property file :index)))
        (dolist (term index)
          (unless (member term full-index) (push term full-index)))))
@@ -1270,7 +1271,7 @@ If FREE-CACHE, empty the cache."
   org-publish-cache)
 
 (defun org-publish-reset-cache ()
-  "Empty org-publish-cache and reset it nil."
+  "Empty `org-publish-cache' and reset it nil."
   (message "%s" "Resetting org-publish-cache")
   (when (hash-table-p org-publish-cache)
     (clrhash org-publish-cache))
@@ -1290,29 +1291,28 @@ the file including them will be republished as well."
         (org-inhibit-startup t)
         included-files-ctime)
     (when (equal (file-name-extension filename) "org")
-      (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)))
-                 (when (eq 'keyword (org-element-type element))
-                   (let* ((value (org-element-property :value element))
-                          (filename
-                           (and (string-match "\\`\\(\".+?\"\\|\\S-+\\)" value)
-                                (let ((m (org-strip-quotes
-                                          (match-string 1 value))))
-                                  ;; Ignore search suffix.
-                                  (if (string-match "::.*?\\'" m)
-                                      (substring m 0 (match-beginning 0))
-                                    m)))))
-                     (when filename
-                       (push (org-publish-cache-ctime-of-src
-                              (expand-file-name filename))
-                             included-files-ctime)))))))
-         (unless visiting (kill-buffer buf)))))
+      (let ((case-fold-search t))
+       (with-temp-buffer
+          (delay-mode-hooks
+            (org-mode)
+            (insert-file-contents filename)
+           (goto-char (point-min))
+           (while (re-search-forward "^[ \t]*#\\+INCLUDE:" nil t)
+             (let ((element (org-element-at-point)))
+               (when (eq 'keyword (org-element-type element))
+                 (let* ((value (org-element-property :value element))
+                        (include-filename
+                         (and (string-match "\\`\\(\".+?\"\\|\\S-+\\)" value)
+                              (let ((m (org-strip-quotes
+                                        (match-string 1 value))))
+                                ;; Ignore search suffix.
+                                (if (string-match "::.*?\\'" m)
+                                    (substring m 0 (match-beginning 0))
+                                  m)))))
+                   (when include-filename
+                     (push (org-publish-cache-ctime-of-src
+                            (expand-file-name include-filename 
(file-name-directory filename)))
+                           included-files-ctime))))))))))
     (or (null pstamp)
        (let ((ctime (org-publish-cache-ctime-of-src filename)))
          (or (time-less-p pstamp ctime)
@@ -1320,7 +1320,7 @@ the file including them will be republished as well."
                       included-files-ctime))))))
 
 (defun org-publish-cache-set-file-property
-  (filename property value &optional project-name)
+    (filename property value &optional project-name)
   "Set the VALUE for a PROPERTY of file FILENAME in publishing cache to VALUE.
 Use cache file of PROJECT-NAME.  If the entry does not exist, it
 will be created.  Return VALUE."
diff --git a/lisp/ox-texinfo.el b/lisp/ox-texinfo.el
index c1f4197..8b949b3 100644
--- a/lisp/ox-texinfo.el
+++ b/lisp/ox-texinfo.el
@@ -2,6 +2,7 @@
 
 ;; Copyright (C) 2012-2021 Free Software Foundation, Inc.
 ;; Author: Jonathan Leech-Pepin <jonathan.leechpepin at gmail dot com>
+;; Maintainer: Nicolas Goaziou <n.goaziou at gmail dot com>
 ;; Keywords: outlines, hypermedia, calendar, wp
 
 ;; This file is part of GNU Emacs.
@@ -420,8 +421,8 @@ If two strings share the same prefix (e.g. \"ISO-8859-1\" 
and
 (defun org-texinfo--normalize-headlines (tree _backend info)
   "Normalize headlines in TREE.
 
-BACK-END is the symbol specifying back-end used for export. INFO
-is a plist used as a communication channel.
+BACK-END is the symbol specifying back-end used for export.
+INFO is a plist used as a communication channel.
 
 Make sure every headline in TREE contains a section, since those
 are required to install a menu.  Also put exactly one blank line
@@ -927,7 +928,7 @@ holding contextual information."
         contents))))))
 
 (defun org-texinfo-format-headline-default-function
-  (todo _todo-type priority text tags)
+    (todo _todo-type priority text tags)
   "Default format function for a headline.
 See `org-texinfo-format-headline-function' for details."
   (concat (and todo (format "@strong{%s} " todo))
@@ -964,7 +965,7 @@ holding contextual information."
             todo todo-type priority title tags contents)))
 
 (defun org-texinfo-format-inlinetask-default-function
-  (todo _todo-type priority title tags contents)
+    (todo _todo-type priority title tags contents)
   "Default format function for inlinetasks.
 See `org-texinfo-format-inlinetask-function' for details."
   (let ((full-title
@@ -1605,7 +1606,7 @@ channel."
 
 (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
+CONTENTS is verse block contents.  INFO is a plist holding
 contextual information."
   (format "@display\n%s@end display" contents))
 
@@ -1614,7 +1615,7 @@ contextual information."
 
 ;;;###autoload
 (defun org-texinfo-export-to-texinfo
-  (&optional async subtreep visible-only body-only ext-plist)
+    (&optional async subtreep visible-only body-only ext-plist)
   "Export current buffer to a Texinfo file.
 
 If narrowing is active in the current buffer, only export its
@@ -1647,9 +1648,25 @@ Return output file's name."
     (org-export-to-file 'texinfo outfile
       async subtreep visible-only body-only ext-plist)))
 
+(defun org-texinfo-export-to-texinfo-batch ()
+  "Export Org file INFILE to Texinfo file OUTFILE, in batch mode.
+Overwrites existing output file.
+Usage: emacs -batch -f org-texinfo-export-to-texinfo-batch INFILE OUTFILE"
+  (or noninteractive (user-error "Batch mode use only"))
+  (let ((infile (pop command-line-args-left))
+       (outfile (pop command-line-args-left))
+       (org-export-coding-system org-texinfo-coding-system)
+        (make-backup-files nil))
+    (unless (file-readable-p infile)
+      (message "File `%s' not readable" infile)
+      (kill-emacs 1))
+    (with-temp-buffer
+      (insert-file-contents infile)
+      (org-export-to-file 'texinfo outfile))))
+
 ;;;###autoload
 (defun org-texinfo-export-to-info
-  (&optional async subtreep visible-only body-only ext-plist)
+    (&optional async subtreep visible-only body-only ext-plist)
   "Export current buffer to Texinfo then process through to INFO.
 
 If narrowing is active in the current buffer, only export its
diff --git a/lisp/ox.el b/lisp/ox.el
index 8ab4314..9ab813a 100644
--- a/lisp/ox.el
+++ b/lisp/ox.el
@@ -3,6 +3,7 @@
 ;; Copyright (C) 2012-2021 Free Software Foundation, Inc.
 
 ;; Author: Nicolas Goaziou <n.goaziou at gmail dot com>
+;; Maintainer: Nicolas Goaziou <n.goaziou at gmail dot com>
 ;; Keywords: outlines, hypermedia, calendar, wp
 
 ;; This file is part of GNU Emacs.
@@ -73,6 +74,8 @@
 
 (require 'cl-lib)
 (require 'ob-exp)
+(require 'oc)
+(require 'oc-basic)    ;default value for `org-cite-export-processors'
 (require 'ol)
 (require 'org-element)
 (require 'org-macro)
@@ -139,7 +142,9 @@
     (: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))
+    (:with-todo-keywords nil "todo" org-export-with-todo-keywords)
+    ;; Citations processing.
+    (:cite-export "CITE_EXPORT" nil org-cite-export-processors))
   "Alist between export properties and ways to set them.
 
 The key of the alist is the property name, and the value is a list
@@ -294,7 +299,7 @@ and its CDR is a list of export options.")
 
 (defvar org-export-dispatch-last-position (make-marker)
   "The position where the last export command was created using the dispatcher.
-This marker will be used with `C-u C-c C-e' to make sure export repetition
+This marker will be used with `\\[universal-argument] C-c C-e' to make sure 
export repetition
 uses the same subtree if the previous command was restricted to a subtree.")
 
 ;; For compatibility with Org < 8
@@ -1207,12 +1212,12 @@ keywords are understood:
       or
 
       \\='(?l \"Export to LaTeX\"
-           (?p \"As PDF file\" org-latex-export-to-pdf)
-           (?o \"As PDF file and open\"
-               (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)))))))
+           ((?p \"As PDF file\" org-latex-export-to-pdf)
+            (?o \"As PDF file and open\"
+                (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)))))))
 
       or the following, which will be added to the previous
       sub-menu,
@@ -1571,7 +1576,7 @@ process."
                 plist
                 prop
                 ;; Evaluate default value provided.
-                (let ((value (eval (nth 3 cell))))
+                (let ((value (eval (nth 3 cell) t)))
                   (if (eq (nth 4 cell) 'parse)
                       (org-element-parse-secondary-string
                        value (org-element-restriction 'keyword))
@@ -1880,6 +1885,8 @@ Return a string."
                (cond
                 ;; Ignored element/object.
                 ((memq data (plist-get info :ignore-list)) nil)
+                 ;; Raw code.
+                 ((eq type 'raw) (car (org-element-contents data)))
                 ;; Plain text.
                 ((eq type 'plain-text)
                  (org-export-filter-apply-functions
@@ -1946,7 +1953,7 @@ Return a string."
           data
           (cond
            ((not results) "")
-           ((memq type '(org-data plain-text nil)) results)
+           ((memq type '(nil org-data plain-text raw)) results)
            ;; Append the same white space between elements or objects
            ;; as in the original buffer, and call appropriate filters.
            (t
@@ -2561,16 +2568,16 @@ another buffer, effectively cloning the original buffer 
there.
 
 The function assumes BUFFER's major mode is `org-mode'."
   (with-current-buffer buffer
-    `(lambda ()
-       (let ((inhibit-modification-hooks t))
-        ;; Set major mode. Ignore `org-mode-hook' as it has been run
-        ;; already in BUFFER.
-        (let ((org-mode-hook nil) (org-inhibit-startup t)) (org-mode))
-        ;; Copy specific buffer local variables and variables set
-        ;; through BIND keywords.
-        ,@(let ((bound-variables (org-export--list-bound-variables))
-                vars)
-            (dolist (entry (buffer-local-variables (buffer-base-buffer)) vars)
+    (let ((str (org-with-wide-buffer (buffer-string)))
+          (narrowing
+           (if (org-region-active-p)
+              (list (region-beginning) (region-end))
+            (list (point-min) (point-max))))
+         (pos (point))
+         (varvals
+          (let ((bound-variables (org-export--list-bound-variables))
+                (varvals nil))
+            (dolist (entry (buffer-local-variables (buffer-base-buffer)))
               (when (consp entry)
                 (let ((var (car entry))
                       (val (cdr entry)))
@@ -2585,27 +2592,35 @@ The function assumes BUFFER's major mode is `org-mode'."
                        ;; Skip unreadable values, as they cannot be
                        ;; sent to external process.
                        (or (not val) (ignore-errors (read (format "%S" val))))
-                       (push `(set (make-local-variable (quote ,var))
-                                   (quote ,val))
-                             vars))))))
-        ;; Whole buffer contents.
-        (insert ,(org-with-wide-buffer (buffer-string)))
-        ;; Narrowing.
-        ,(if (org-region-active-p)
-             `(narrow-to-region ,(region-beginning) ,(region-end))
-           `(narrow-to-region ,(point-min) ,(point-max)))
-        ;; Current position of point.
-        (goto-char ,(point))
-        ;; Overlays with invisible property.
-        ,@(let (ov-set)
-            (dolist (ov (overlays-in (point-min) (point-max)) ov-set)
+                       (push (cons var val) varvals)))))
+             varvals))
+         (ols
+          (let (ov-set)
+            (dolist (ov (overlays-in (point-min) (point-max)))
               (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)))))))))
+                  (push (list (overlay-start ov) (overlay-end ov)
+                              invis-prop)
+                        ov-set))))
+            ov-set)))
+      (lambda ()
+       (let ((inhibit-modification-hooks t))
+         ;; Set major mode. Ignore `org-mode-hook' as it has been run
+         ;; already in BUFFER.
+         (let ((org-mode-hook nil) (org-inhibit-startup t)) (org-mode))
+         ;; Copy specific buffer local variables and variables set
+         ;; through BIND keywords.
+         (pcase-dolist (`(,var . ,val) varvals)
+           (set (make-local-variable var) val))
+         ;; Whole buffer contents.
+         (insert str)
+         ;; Narrowing.
+         (apply #'narrow-to-region narrowing)
+         ;; Current position of point.
+         (goto-char pos)
+         ;; Overlays with invisible property.
+         (pcase-dolist (`(,start ,end ,invis) ols)
+           (overlay-put (make-overlay start end) 'invisible invis)))))))
 
 (defun org-export--delete-comment-trees ()
   "Delete commented trees and commented inlinetasks in the buffer.
@@ -2708,11 +2723,11 @@ a list of footnote definitions or in the widened 
buffer."
               (and (or (eq (org-element-type f) 'footnote-definition)
                        (eq (org-element-property :type f) 'inline))
                    (org-element-property :label f)))))
-         seen)
+         ) ;; seen
       (dolist (l (funcall list-labels tree))
-       (cond ((member l seen))
-             ((member l known-definitions) (push l defined))
-             (t (push l undefined)))))
+       (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
@@ -2724,7 +2739,7 @@ a list of footnote definitions or in the widened buffer."
               (cond
                ((cl-some
                  (lambda (d) (and (equal (org-element-property :label d) label)
-                             d))
+                                  d))
                  definitions))
                ((pcase (org-footnote-get-definition label)
                   (`(,_ ,beg . ,_)
@@ -2787,16 +2802,16 @@ containing their first reference."
    ;; 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)))))
+        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
@@ -2819,8 +2834,8 @@ containing their first reference."
                                          d))
                                   definitions)))
                            (org-element-adopt-elements
-                            (org-element-lineage reference '(section))
-                            definition)
+                               (org-element-lineage reference '(section))
+                             definition)
                            ;; Also insert definitions for nested
                            ;; references, if any.
                            (funcall insert-definitions definition))))))))))
@@ -2949,10 +2964,8 @@ Return code as a string."
                             (org-export-backend-name backend))
         (org-export-expand-include-keyword)
         (org-export--delete-comment-trees)
-        (org-macro-initialize-templates)
-        (org-macro-replace-all (append org-macro-templates
-                                       org-export-global-macros)
-                               parsed-keywords)
+        (org-macro-initialize-templates org-export-global-macros)
+        (org-macro-replace-all org-macro-templates parsed-keywords)
         ;; Refresh buffer properties and radio targets after previous
         ;; potentially invasive changes.
         (org-set-regexps-and-options)
@@ -2979,6 +2992,10 @@ Return code as a string."
         (setq info
               (org-combine-plists
                info (org-export-get-environment backend subtreep ext-plist)))
+         ;; Pre-process citations environment, i.e. install
+        ;; bibliography list, and citation processor in INFO.
+        (org-cite-store-bibliography info)
+         (org-cite-store-export-processor info)
         ;; De-activate uninterpreted data from parsed keywords.
         (dolist (entry (append (org-export-get-all-options backend)
                                org-export-options-alist))
@@ -3012,6 +3029,11 @@ Return code as a string."
         ;; Now tree is complete, compute its properties and add them
         ;; to communication channel.
         (setq info (org-export--collect-tree-properties tree info))
+         ;; Process citations and bibliography.  Replace each citation
+        ;; and "print_bibliography" keyword in the parse tree with
+        ;; the output of the selected citation export processor.
+         (org-cite-process-citations info)
+         (org-cite-process-bibliography info)
         ;; Eventually transcode TREE.  Wrap the resulting string into
         ;; a template.
         (let* ((body (org-element-normalize-string
@@ -3024,16 +3046,19 @@ Return code as a string."
                              (funcall inner-template body info))
                            info))
                (template (cdr (assq 'template
-                                    (plist-get info :translate-alist)))))
+                                    (plist-get info :translate-alist))))
+                (output
+                 (if (or (not (functionp template)) body-only) full-body
+                  (funcall template full-body info))))
+           ;; Call citation export finalizer.
+           (setq output (org-cite-finalize-export output info))
           ;; Remove all text properties since they cannot be
           ;; retrieved from an external process.  Finally call
           ;; final-output filter and return result.
           (org-no-properties
            (org-export-filter-apply-functions
             (plist-get info :filter-final-output)
-            (if (or (not (functionp template)) body-only) full-body
-              (funcall template full-body info))
-            info))))))))
+            output info))))))))
 
 ;;;###autoload
 (defun org-export-string-as (string backend &optional body-only ext-plist)
@@ -3106,22 +3131,22 @@ 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)) " ")
-                             (eval (nth 3 entry)))))
+                               (mapconcat #'identity (eval (nth 3 entry) t) " 
")
+                             (eval (nth 3 entry) t))))
                       (push (cons keyword value) keywords))))
          (option (unless (assoc option options)
-                   (push (cons option (eval (nth 3 entry))) options))))))
+                   (push (cons option (eval (nth 3 entry) t)) options))))))
     ;; Move to an appropriate location in order to insert options.
     (unless subtreep (beginning-of-line))
     ;; First (multiple) OPTIONS lines.  Never go past fill-column.
     (when options
       (let ((items
             (mapcar
-             #'(lambda (opt) (format "%s:%S" (car opt) (cdr opt)))
+              (lambda (opt) (format "%s:%S" (car opt) (cdr opt)))
              (sort options (lambda (k1 k2) (string< (car k1) (car k2)))))))
        (if subtreep
            (org-entry-put
-            node "EXPORT_OPTIONS" (mapconcat 'identity items " "))
+            node "EXPORT_OPTIONS" (mapconcat #'identity items " "))
          (while items
            (insert "#+options:")
            (let ((width 10))
@@ -3611,7 +3636,7 @@ will become the empty string."
         (attributes
          (let ((value (org-element-property attribute element)))
            (when value
-             (let ((s (mapconcat 'identity value " ")) result)
+             (let ((s (mapconcat #'identity value " ")) result)
                (while (string-match
                        "\\(?:^\\|[ \t]+\\)\\(:[-a-zA-Z0-9_]+\\)\\([ 
\t]+\\|$\\)"
                        s)
@@ -3661,7 +3686,8 @@ 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)))
-    (when (memq type '(nil org-data)) (error "No foreign transcoder 
available"))
+    (when (memq type '(nil org-data raw))
+      (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"))
@@ -4196,10 +4222,10 @@ Return modified DATA."
                             (or rules org-export-default-inline-image-rule))
                ;; Replace contents with image link.
                (org-element-adopt-elements
-                (org-element-set-contents l nil)
-                (with-temp-buffer
-                  (save-excursion (insert contents))
-                  (org-element-link-parser))))))))
+                   (org-element-set-contents l nil)
+                 (with-temp-buffer
+                   (save-excursion (insert contents))
+                   (org-element-link-parser))))))))
       info nil nil t))
   data)
 
@@ -4555,6 +4581,17 @@ objects of the same type."
            ((funcall predicate el info) (cl-incf counter) nil)))
         info 'first-match)))))
 
+;;;; For Raw objects
+;;
+;; `org-export-raw-string' builds a pseudo-object out of a string
+;; that any export back-end returns as-is.
+
+(defun org-export-raw-string (s)
+  "Return a raw object containing string S.
+A raw string is exported as-is, with no additional processing
+from the export back-end."
+  (unless (stringp s) (error "Wrong raw contents type: %S" s))
+  (org-element-create 'raw nil s))
 
 ;;;; For Src-Blocks
 ;;
@@ -4704,7 +4741,7 @@ code."
             ;; should start six columns after the widest line of code,
             ;; wrapped with parenthesis.
             (max-width
-             (+ (apply 'max (mapcar 'length code-lines))
+             (+ (apply #'max (mapcar #'length code-lines))
                 (if (not num-start) 0 (length (format num-fmt num-start))))))
        (org-export-format-code
         code
@@ -5084,8 +5121,8 @@ 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.
   (or (eq (car (last (org-element-contents
-                        (org-export-get-parent table-cell))))
-            table-cell)
+                     (org-export-get-parent table-cell))))
+         table-cell)
       (memq 'right (org-export-table-cell-borders table-cell info))))
 
 (defun org-export-table-row-starts-rowgroup-p (table-row info)
@@ -5400,6 +5437,16 @@ transcoding it."
      (secondary-closing
       :utf-8 "โ€˜" :html "&lsquo;" :latex "\\grq{}" :texinfo "@quoteleft{}")
      (apostrophe :utf-8 "โ€™" :html "&rsquo;"))
+    ("el"
+     (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;"))
     ("en"
      (primary-opening :utf-8 "โ€œ" :html "&ldquo;" :latex "``" :texinfo "``")
      (primary-closing :utf-8 "โ€" :html "&rdquo;" :latex "''" :texinfo "''")
@@ -5439,6 +5486,12 @@ transcoding it."
      (secondary-closing
       :utf-8 "โ€˜" :html "&lsquo;" :latex "\\grq{}" :texinfo "@quoteleft{}")
      (apostrophe :utf-8 "โ€™" :html "&rsquo;"))
+    ("it"
+     (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;"))
     ("no"
      ;; https://nn.wikipedia.org/wiki/Sitatteikn
      (primary-opening
@@ -5485,7 +5538,7 @@ transcoding it."
      (apostrophe :utf-8 "โ€™" :html "&rsquo;"))
     ("ru"
      ;; 
https://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/
+     ;; https://www.artlebedev.ru/kovodstvo/sections/104/
      (primary-opening :utf-8 "ยซ" :html "&laquo;" :latex "{}<<"
                      :texinfo "@guillemetleft{}")
      (primary-closing :utf-8 "ยป" :html "&raquo;" :latex ">>{}"
@@ -5747,6 +5800,7 @@ them."
      ("ru" :html "&#1040;&#1074;&#1090;&#1086;&#1088;" :utf-8 "ะะฒั‚ะพั€")
      ("sl" :default "Avtor")
      ("sv" :html "F&ouml;rfattare")
+     ("tr" :default "Yazar")
      ("uk" :html "&#1040;&#1074;&#1090;&#1086;&#1088;" :utf-8 "ะะฒั‚ะพั€")
      ("zh-CN" :html "&#20316;&#32773;" :utf-8 "ไฝœ่€…")
      ("zh-TW" :html "&#20316;&#32773;" :utf-8 "ไฝœ่€…"))
@@ -5759,12 +5813,14 @@ them."
      ("it" :default "Continua da pagina precedente")
      ("ja" :default "ๅ‰ใƒšใƒผใ‚ธใ‹ใ‚‰ใฎ็ถšใ")
      ("nl" :default "Vervolg van vorige pagina")
+     ("pl" :default "Ciฤ…g dalszy poprzedniej strony")
      ("pt" :default "Continuaรงรฃo da pรกgina anterior")
      ("pt_BR" :html "Continua&ccedil;&atilde;o da p&aacute;gina anterior" 
:ascii "Continuacao da pagina anterior" :default "Continuaรงรฃo da pรกgina 
anterior")
      ("ro" :default "Continuare de pe pagina precedentฤƒ")
      ("ru" :html 
"(&#1055;&#1088;&#1086;&#1076;&#1086;&#1083;&#1078;&#1077;&#1085;&#1080;&#1077;)"
       :utf-8 "(ะŸั€ะพะดะพะปะถะตะฝะธะต)")
-     ("sl" :default "Nadaljevanje s prejลกnje strani"))
+     ("sl" :default "Nadaljevanje s prejลกnje strani")
+     ("tr" :default "ร–nceki sayfadan devam ediyor"))
     ("Continued on next page"
      ("ar" :default "ุงู„ุชุชู…ุฉ ููŠ ุงู„ุตูุญุฉ ุงู„ุชุงู„ูŠุฉ")
      ("cs" :default "Pokraฤuje na dalลกรญ strรกnce")
@@ -5774,18 +5830,21 @@ them."
      ("it" :default "Continua alla pagina successiva")
      ("ja" :default "ๆฌกใƒšใƒผใ‚ธใซ็ถšใ")
      ("nl" :default "Vervolg op volgende pagina")
+     ("pl" :default "Kontynuacja na nastฤ™pnej stronie")
      ("pt" :default "Continua na pรกgina seguinte")
      ("pt_BR" :html "Continua na pr&oacute;xima p&aacute;gina" :ascii 
"Continua na proxima pagina" :default "Continua na prรณxima pรกgina")
      ("ro" :default "Continuare pe pagina urmฤƒtoare")
      ("ru" :html 
"(&#1055;&#1088;&#1086;&#1076;&#1086;&#1083;&#1078;&#1077;&#1085;&#1080;&#1077; 
&#1089;&#1083;&#1077;&#1076;&#1091;&#1077;&#1090;)"
       :utf-8 "(ะŸั€ะพะดะพะปะถะตะฝะธะต ัะปะตะดัƒะตั‚)")
-     ("sl" :default "Nadaljevanje na naslednji strani"))
+     ("sl" :default "Nadaljevanje na naslednji strani")
+     ("tr" :default "Devamฤฑ sonraki sayfada"))
     ("Created"
      ("cs" :default "Vytvoล™eno")
      ("nl" :default "Gemaakt op")  ;; must be followed by a date or date+time
      ("pt_BR" :default "Criado em")
      ("ro" :default "Creat")
-     ("sl" :default "Ustvarjeno"))
+     ("sl" :default "Ustvarjeno")
+     ("tr" :default "OluลŸturuldu"))
     ("Date"
      ("ar" :default "ุจุชุงุฑูŠุฎ")
      ("ca" :default "Data")
@@ -5810,6 +5869,7 @@ them."
      ("ru" :html "&#1044;&#1072;&#1090;&#1072;" :utf-8 "ะ”ะฐั‚ะฐ")
      ("sl" :default "Datum")
      ("sv" :default "Datum")
+     ("tr" :default "Tarih")
      ("uk" :html "&#1044;&#1072;&#1090;&#1072;" :utf-8 "ะ”ะฐั‚ะฐ")
      ("zh-CN" :html "&#26085;&#26399;" :utf-8 "ๆ—ฅๆœŸ")
      ("zh-TW" :html "&#26085;&#26399;" :utf-8 "ๆ—ฅๆœŸ"))
@@ -5833,6 +5893,7 @@ them."
       :utf-8 "ะฃั€ะฐะฒะฝะตะฝะธะต")
      ("sl" :default "Enaฤba")
      ("sv" :default "Ekvation")
+     ("tr" :default "EลŸitlik")
      ("zh-CN" :html "&#26041;&#31243;" :utf-8 "ๆ–น็จ‹"))
     ("Figure"
      ("ar" :default "ุดูƒู„")
@@ -5852,6 +5913,7 @@ them."
      ("ro" :default "Imaginea")
      ("ru" :html "&#1056;&#1080;&#1089;&#1091;&#1085;&#1086;&#1082;" :utf-8 
"ะ ะธััƒะฝะพะบ")
      ("sv" :default "Illustration")
+     ("tr" :default "ลžekil")
      ("zh-CN" :html "&#22270;" :utf-8 "ๅ›พ"))
     ("Figure %d:"
      ("ar" :default "ุดูƒู„ %d:")
@@ -5873,6 +5935,7 @@ them."
      ("ru" :html "&#1056;&#1080;&#1089;. %d.:" :utf-8 "ะ ะธั. %d.:")
      ("sl" :default "Slika %d")
      ("sv" :default "Illustration %d")
+     ("tr" :default "ลžekil %d:")
      ("zh-CN" :html "&#22270;%d&nbsp;" :utf-8 "ๅ›พ%d "))
     ("Footnotes"
      ("ar" :default "ุงู„ู‡ูˆุงู…ุด")
@@ -5881,7 +5944,7 @@ them."
      ("da" :default "Fodnoter")
      ("de" :html "Fu&szlig;noten" :default "FuรŸnoten")
      ("eo" :default "Piednotoj")
-     ("es" :ascii "Nota al pie de pagina" :html "Nota al pie de p&aacute;gina" 
:default "Nota al pie de pรกgina")
+     ("es" :ascii "Notas al pie de pagina" :html "Notas al pie de 
p&aacute;gina" :default "Notas al pie de pรกgina")
      ("et" :html "Allm&#228;rkused" :utf-8 "Allmรคrkused")
      ("fi" :default "Alaviitteet")
      ("fr" :default "Notes de bas de page")
@@ -5899,6 +5962,7 @@ them."
      ("ru" :html "&#1057;&#1085;&#1086;&#1089;&#1082;&#1080;" :utf-8 "ะกะฝะพัะบะธ")
      ("sl" :default "Opombe")
      ("sv" :default "Fotnoter")
+     ("tr" :default "Dipnotlar")
      ("uk" :html "&#1055;&#1088;&#1080;&#1084;&#1110;&#1090;&#1082;&#1080;"
       :utf-8 "ะŸั€ะธะผั–ั‚ะบะธ")
      ("zh-CN" :html "&#33050;&#27880;" :utf-8 "่„šๆณจ")
@@ -5919,6 +5983,7 @@ them."
      ("ru" :html "&#1057;&#1087;&#1080;&#1089;&#1086;&#1082; 
&#1088;&#1072;&#1089;&#1087;&#1077;&#1095;&#1072;&#1090;&#1086;&#1082;"
       :utf-8 "ะกะฟะธัะพะบ ั€ะฐัะฟะตั‡ะฐั‚ะพะบ")
      ("sl" :default "Seznam programskih izpisov")
+     ("tr" :default "Program Listesi")
      ("zh-CN" :html "&#20195;&#30721;&#30446;&#24405;" :utf-8 "ไปฃ็ ็›ฎๅฝ•"))
     ("List of Tables"
      ("ar" :default "ู‚ุงุฆู…ุฉ ุจุงู„ุฌุฏุงูˆู„")
@@ -5941,6 +6006,7 @@ them."
       :utf-8 "ะกะฟะธัะพะบ ั‚ะฐะฑะปะธั†")
      ("sl" :default "Seznam tabel")
      ("sv" :default "Tabeller")
+     ("tr" :default "Tablo Listesi")
      ("zh-CN" :html "&#34920;&#26684;&#30446;&#24405;" :utf-8 "่กจๆ ผ็›ฎๅฝ•"))
     ("Listing"
      ("ar" :default "ุจุฑู†ุงู…ุฌ")
@@ -5960,6 +6026,7 @@ them."
      ("ru" :html 
"&#1056;&#1072;&#1089;&#1087;&#1077;&#1095;&#1072;&#1090;&#1082;&#1072;"
       :utf-8 "ะ ะฐัะฟะตั‡ะฐั‚ะบะฐ")
      ("sl" :default "Izpis programa")
+     ("tr" :default "Program")
      ("zh-CN" :html "&#20195;&#30721;" :utf-8 "ไปฃ็ "))
     ("Listing %d:"
      ("ar" :default "ุจุฑู†ุงู…ุฌ %d:")
@@ -5979,6 +6046,7 @@ them."
      ("ru" :html 
"&#1056;&#1072;&#1089;&#1087;&#1077;&#1095;&#1072;&#1090;&#1082;&#1072; %d.:"
       :utf-8 "ะ ะฐัะฟะตั‡ะฐั‚ะบะฐ %d.:")
      ("sl" :default "Izpis programa %d")
+     ("tr" :default "Program %d:")
      ("zh-CN" :html "&#20195;&#30721;%d&nbsp;" :utf-8 "ไปฃ็ %d "))
     ("References"
      ("ar" :default "ุงู„ู…ุฑุงุฌุน")
@@ -5990,7 +6058,8 @@ them."
      ("nl" :default "Bronverwijzingen")
      ("pt_BR" :html "Refer&ecirc;ncias" :default "Referรชncias" :ascii 
"Referencias")
      ("ro" :default "Bibliografie")
-     ("sl" :default "Reference"))
+     ("sl" :default "Reference")
+     ("tr" :default "Referanslar"))
     ("See figure %s"
      ("cs" :default "Viz obrรกzek %s")
      ("fr" :default "cf. figure %s"
@@ -6000,7 +6069,8 @@ them."
       :html "Zie figuur&nbsp;%s" :latex "Zie figuur~%s")
      ("pt_BR" :default "Veja a figura %s")
      ("ro" :default "Vezi figura %s")
-     ("sl" :default "Glej sliko %s"))
+     ("sl" :default "Glej sliko %s")
+     ("tr" :default "bkz. ลŸekil %s"))
     ("See listing %s"
      ("cs" :default "Viz program %s")
      ("fr" :default "cf. programme %s"
@@ -6009,7 +6079,8 @@ them."
       :html "Zie programma&nbsp;%s" :latex "Zie programma~%s")
      ("pt_BR" :default "Veja a listagem %s")
      ("ro" :default "Vezi tabelul %s")
-     ("sl" :default "Glej izpis programa %s"))
+     ("sl" :default "Glej izpis programa %s")
+     ("tr" :default "bkz. program %s"))
     ("See section %s"
      ("ar" :default "ุงู†ุธุฑ ู‚ุณู… %s")
      ("cs" :default "Viz sekce %s")
@@ -6028,6 +6099,7 @@ them."
      ("ru" :html "&#1057;&#1084;. &#1088;&#1072;&#1079;&#1076;&#1077;&#1083; 
%s"
       :utf-8 "ะกะผ. ั€ะฐะทะดะตะป %s")
      ("sl" :default "Glej poglavje %d")
+     ("tr" :default "bkz. bรถlรผm %s")
      ("zh-CN" :html "&#21442;&#35265;&#31532;%s&#33410;" :utf-8 "ๅ‚่ง็ฌฌ%s่Š‚"))
     ("See table %s"
      ("cs" :default "Viz tabulka %s")
@@ -6038,7 +6110,8 @@ them."
       :html "Zie tabel&nbsp;%s" :latex "Zie tabel~%s")
      ("pt_BR" :default "Veja a tabela %s")
      ("ro" :default "Vezi tabelul %s")
-     ("sl" :default "Glej tabelo %s"))
+     ("sl" :default "Glej tabelo %s")
+     ("tr" :default "bkz. tablo %s"))
     ("Table"
      ("ar" :default "ุฌุฏูˆู„")
      ("cs" :default "Tabulka")
@@ -6054,6 +6127,7 @@ them."
      ("ro" :default "Tabel")
      ("ru" :html "&#1058;&#1072;&#1073;&#1083;&#1080;&#1094;&#1072;"
       :utf-8 "ะขะฐะฑะปะธั†ะฐ")
+     ("tr" :default "Tablo")
      ("zh-CN" :html "&#34920;" :utf-8 "่กจ"))
     ("Table %d:"
      ("ar" :default "ุฌุฏูˆู„ %d:")
@@ -6076,6 +6150,7 @@ them."
       :utf-8 "ะขะฐะฑะปะธั†ะฐ %d.:")
      ("sl" :default "Tabela %d")
      ("sv" :default "Tabell %d")
+     ("tr" :default "Tablo %d")
      ("zh-CN" :html "&#34920;%d&nbsp;" :utf-8 "่กจ%d "))
     ("Table of Contents"
      ("ar" :default "ู‚ุงุฆู…ุฉ ุงู„ู…ุญุชูˆูŠุงุช")
@@ -6103,6 +6178,7 @@ them."
       :utf-8 "ะกะพะดะตั€ะถะฐะฝะธะต")
      ("sl" :default "Kazalo")
      ("sv" :html "Inneh&aring;ll")
+     ("tr" :default "ฤฐรงindekiler")
      ("uk" :html "&#1047;&#1084;&#1110;&#1089;&#1090;" :utf-8 "ะ—ะผั–ัั‚")
      ("zh-CN" :html "&#30446;&#24405;" :utf-8 "็›ฎๅฝ•")
      ("zh-TW" :html "&#30446;&#37636;" :utf-8 "็›ฎ้Œ„"))
@@ -6121,6 +6197,7 @@ them."
      ("ru" :html 
"&#1053;&#1077;&#1080;&#1079;&#1074;&#1077;&#1089;&#1090;&#1085;&#1072;&#1103; 
&#1089;&#1089;&#1099;&#1083;&#1082;&#1072;"
       :utf-8 "ะะตะธะทะฒะตัั‚ะฝะฐั ััั‹ะปะบะฐ")
      ("sl" :default "Neznana referenca")
+     ("tr" :default "Bilinmeyen referans")
      ("zh-CN" :html "&#26410;&#30693;&#24341;&#29992;" :utf-8 "ๆœช็Ÿฅๅผ•็”จ")))
   "Dictionary for export engine.
 
@@ -6178,97 +6255,93 @@ to `:default' encoding.  If it fails, return S."
 ;; For back-ends, `org-export-add-to-stack' add a new source to stack.
 ;; It should be used whenever `org-export-async-start' is called.
 
-(defmacro org-export-async-start  (fun &rest body)
+(defun org-export-async-start  (fun body)
   "Call function FUN on the results returned by BODY evaluation.
 
-FUN is an anonymous function of one argument.  BODY evaluation
-happens in an asynchronous process, from a buffer which is an
-exact copy of the current one.
+FUN is an anonymous function of one argument.  BODY should be a valid
+ELisp source expression.  BODY evaluation happens in an asynchronous process,
+from a buffer which is an exact copy of the current one.
 
 Use `org-export-add-to-stack' in FUN in order to register results
 in the stack.
 
 This is a low level function.  See also `org-export-to-buffer'
 and `org-export-to-file' for more specialized functions."
-  (declare (indent 1) (debug t))
-  (org-with-gensyms (process temp-file copy-fun proc-buffer coding)
-    ;; Write the full sexp evaluating BODY in a copy of the current
-    ;; buffer to a temporary file, as it may be too long for program
-    ;; args in `start-process'.
-    `(with-temp-message "Initializing asynchronous export process"
-       (let ((,copy-fun (org-export--generate-copy-script (current-buffer)))
-             (,temp-file (make-temp-file "org-export-process"))
-             (,coding buffer-file-coding-system))
-         (with-temp-file ,temp-file
-           (insert
-            ;; Null characters (from variable values) are inserted
-            ;; within the file.  As a consequence, coding system for
-            ;; buffer contents will not be recognized properly.  So,
-            ;; we make sure it is the same as the one used to display
-            ;; the original buffer.
-            (format ";; -*- coding: %s; -*-\n%S"
-                    ,coding
-                    `(with-temp-buffer
-                       (when org-export-async-debug '(setq debug-on-error t))
-                       ;; Ignore `kill-emacs-hook' and code evaluation
-                       ;; queries from Babel as we need a truly
-                       ;; non-interactive process.
-                       (setq kill-emacs-hook nil
-                             org-babel-confirm-evaluate-answer-no t)
-                       ;; Initialize export framework.
-                       (require 'ox)
-                       ;; Re-create current buffer there.
-                       (funcall ,,copy-fun)
-                       (restore-buffer-modified-p nil)
-                       ;; Sexp to evaluate in the buffer.
-                       (print (progn ,,@body))))))
-         ;; Start external process.
-         (let* ((process-connection-type nil)
-                (,proc-buffer (generate-new-buffer-name "*Org Export 
Process*"))
-                (,process
-                (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.
-           (let ((handler ,fun))
-             (set-process-sentinel
-              ,process
-              `(lambda (p status)
-                 (let ((proc-buffer (process-buffer p)))
-                   (when (eq (process-status p) 'exit)
-                     (unwind-protect
-                         (if (zerop (process-exit-status p))
-                             (unwind-protect
-                                 (let ((results
-                                        (with-current-buffer proc-buffer
-                                          (goto-char (point-max))
-                                          (backward-sexp)
-                                          (read (current-buffer)))))
-                                   (funcall ,handler results))
-                               (unless org-export-async-debug
-                                 (and (get-buffer proc-buffer)
-                                      (kill-buffer proc-buffer))))
-                           (org-export-add-to-stack proc-buffer nil p)
-                           (ding)
-                           (message "Process `%s' exited abnormally" p))
-                       (unless org-export-async-debug
-                         (delete-file ,,temp-file)))))))))))))
+  (declare (indent 1))
+  ;; Write the full sexp evaluating BODY in a copy of the current
+  ;; buffer to a temporary file, as it may be too long for program
+  ;; args in `start-process'.
+  (with-temp-message "Initializing asynchronous export process"
+    (let ((copy-fun (org-export--generate-copy-script (current-buffer)))
+          (temp-file (make-temp-file "org-export-process")))
+      (let ((coding-system-for-write 'utf-8-emacs-unix))
+        (write-region
+         ;; Null characters (from variable values) are inserted
+         ;; within the file.  As a consequence, coding system for
+         ;; buffer contents could fail to be recognized properly.
+         (format ";; -*- coding: utf-8-emacs-unix; lexical-binding:t -*-\n%S"
+                 `(with-temp-buffer
+                    ,(when org-export-async-debug '(setq debug-on-error t))
+                    ;; Ignore `kill-emacs-hook' and code evaluation
+                    ;; queries from Babel as we need a truly
+                    ;; non-interactive process.
+                    (setq kill-emacs-hook nil
+                          org-babel-confirm-evaluate-answer-no t)
+                    ;; Initialize export framework.
+                    (require 'ox)
+                    ;; Re-create current buffer there.
+                    (funcall ',copy-fun)
+                    (restore-buffer-modified-p nil)
+                    ;; Sexp to evaluate in the buffer.
+                    (print ,body)))
+         nil temp-file nil 'silent))
+      ;; Start external process.
+      (let* ((process-connection-type nil)
+             (proc-buffer (generate-new-buffer-name "*Org Export Process*"))
+             (process
+             (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.
+        (let ((handler fun))
+          (set-process-sentinel
+           process
+           (lambda (p _status)
+             (let ((proc-buffer (process-buffer p)))
+               (when (eq (process-status p) 'exit)
+                 (unwind-protect
+                     (if (zerop (process-exit-status p))
+                         (unwind-protect
+                             (let ((results
+                                    (with-current-buffer proc-buffer
+                                      (goto-char (point-max))
+                                      (backward-sexp)
+                                      (read (current-buffer)))))
+                               (funcall handler results))
+                           (unless org-export-async-debug
+                             (and (get-buffer proc-buffer)
+                                  (kill-buffer proc-buffer))))
+                       (org-export-add-to-stack proc-buffer nil p)
+                       (ding)
+                       (message "Process `%s' exited abnormally" p))
+                   (unless org-export-async-debug
+                     (delete-file temp-file))))))))))))
 
 ;;;###autoload
 (defun org-export-to-buffer
-  (backend buffer
-          &optional async subtreep visible-only body-only ext-plist
-          post-process)
+    (backend buffer
+            &optional async subtreep visible-only body-only ext-plist
+            post-process)
   "Call `org-export-as' with output to a specified buffer.
 
 BACKEND is either an export back-end, as returned by, e.g.,
@@ -6303,14 +6376,15 @@ This function returns BUFFER."
   (declare (indent 2))
   (if async
       (org-export-async-start
-         `(lambda (output)
-            (with-current-buffer (get-buffer-create ,buffer)
-              (erase-buffer)
-              (setq buffer-file-coding-system ',buffer-file-coding-system)
-              (insert output)
-              (goto-char (point-min))
-              (org-export-add-to-stack (current-buffer) ',backend)
-              (ignore-errors (funcall ,post-process))))
+         (let ((cs buffer-file-coding-system))
+           (lambda (output)
+             (with-current-buffer (get-buffer-create buffer)
+               (erase-buffer)
+               (setq buffer-file-coding-system cs)
+               (insert output)
+               (goto-char (point-min))
+               (org-export-add-to-stack (current-buffer) backend)
+               (ignore-errors (funcall post-process)))))
        `(org-export-as
          ',backend ,subtreep ,visible-only ,body-only ',ext-plist))
     (let ((output
@@ -6331,8 +6405,8 @@ This function returns BUFFER."
 
 ;;;###autoload
 (defun org-export-to-file
-  (backend file &optional async subtreep visible-only body-only ext-plist
-          post-process)
+    (backend file &optional async subtreep visible-only body-only ext-plist
+            post-process)
   "Call `org-export-as' with output to a specified file.
 
 BACKEND is either an export back-end, as returned by, e.g.,
@@ -6366,11 +6440,12 @@ or FILE."
   (declare (indent 2))
   (if (not (file-writable-p file)) (error "Output file not writable")
     (let ((ext-plist (org-combine-plists `(:output-file ,file) ext-plist))
-         (encoding (or org-export-coding-system buffer-file-coding-system)))
+         (encoding (or org-export-coding-system buffer-file-coding-system))
+          auto-mode-alist)
       (if async
           (org-export-async-start
-             `(lambda (file)
-                (org-export-add-to-stack (expand-file-name file) ',backend))
+             (lambda (file)
+               (org-export-add-to-stack (expand-file-name file) backend))
            `(let ((output
                    (org-export-as
                     ',backend ,subtreep ,visible-only ,body-only
@@ -6488,7 +6563,7 @@ If optional argument SOURCE is non-nil, remove it 
instead."
   (let ((source (or source (org-export--stack-source-at-point))))
     (setq org-export-stack-contents
          (cl-remove-if (lambda (el) (equal (car el) source))
-                        org-export-stack-contents))))
+                       org-export-stack-contents))))
 
 (defun org-export-stack-view (&optional in-emacs)
   "View export results at point in stack.
@@ -6504,16 +6579,16 @@ 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 "\C-n" 'next-line)
-    (define-key km [down] 'next-line)
-    (define-key km "\C-p" 'previous-line)
-    (define-key km "\C-?" 'previous-line)
-    (define-key km [up] 'previous-line)
-    (define-key km "C" 'org-export-stack-clear)
-    (define-key km "v" 'org-export-stack-view)
-    (define-key km (kbd "RET") 'org-export-stack-view)
-    (define-key km "d" 'org-export-stack-remove)
+    (define-key km " " #'next-line)
+    (define-key km "\C-n" #'next-line)
+    (define-key km [down] #'next-line)
+    (define-key km "\C-p" #'previous-line)
+    (define-key km "\C-?" #'previous-line)
+    (define-key km [up] #'previous-line)
+    (define-key km "C"  #'org-export-stack-clear)
+    (define-key km "v"  #'org-export-stack-view)
+    (define-key km (kbd "RET") #'org-export-stack-view)
+    (define-key km "d" #'org-export-stack-remove)
     km)
   "Keymap for Org Export Stack.")
 
@@ -6711,7 +6786,7 @@ 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))
-               (propertize key 'face 'org-warning)
+               (propertize key 'face 'org-dispatcher-highlight)
              key)))
         (fontify-value
          (lambda (value)
@@ -6730,16 +6805,16 @@ back to standard interface."
                          (cond ((and (numberp key-a) (numberp key-b))
                                 (< key-a key-b))
                                ((numberp key-b) t)))))
-               'car-less-than-car))
+               #'car-less-than-car))
         ;; Compute a list of allowed keys based on the first key
         ;; pressed, if any.  Some keys
         ;; (?^B, ?^V, ?^S, ?^F, ?^A, ?&, ?# and ?q) are always
         ;; available.
         (allowed-keys
          (nconc (list 2 22 19 6 1)
-                (if (not first-key) (org-uniquify (mapcar 'car entries))
+                (if (not first-key) (org-uniquify (mapcar #'car entries))
                   (let (sub-menu)
-                    (dolist (entry entries (sort (mapcar 'car sub-menu) '<))
+                    (dolist (entry entries (sort (mapcar #'car sub-menu) #'<))
                       (when (eq (car entry) first-key)
                         (setq sub-menu (append (nth 2 entry) sub-menu))))))
                 (cond ((eq first-key ?P) (list ?f ?p ?x ?a))
diff --git a/mk/default.mk b/mk/default.mk
index e92d58c..4ffb076 100644
--- a/mk/default.mk
+++ b/mk/default.mk
@@ -26,10 +26,6 @@ infodir = $(prefix)/info
 # the branch when undefined.
 GIT_BRANCH =
 
-# Define if you want to include some (or all) files from contrib/lisp
-# just the filename please (no path prefix, no .el suffix), maybe with globbing
-#ORG_ADD_CONTRIB = ox-* # e.g. the contributed exporter
-
 # Where to create temporary files for the testsuite
 # respect TMPDIR if it is already defined in the environment
 TMPDIR ?= /tmp
@@ -43,7 +39,7 @@ BTEST_POST  =
               # -L <path-to>/ert      # needed for Emacs23, Emacs24 has ert 
built in
               # -L <path-to>/ess      # needed for running R tests
               # -L <path-to>/htmlize  # need at least version 1.34 for source 
code formatting
-BTEST_OB_LANGUAGES = awk C fortran maxima lilypond octave perl python vala
+BTEST_OB_LANGUAGES = awk C fortran maxima lilypond octave perl python
               # R                     # requires ESS to be installed and 
configured
               # ruby                  # requires inf-ruby to be installed and 
configured
 # extra packages to require for testing
diff --git a/mk/guidesplit.pl b/mk/guidesplit.pl
index eef0f7c..fc92d2d 100755
--- a/mk/guidesplit.pl
+++ b/mk/guidesplit.pl
@@ -37,8 +37,8 @@ EOF
 
 $script = <<'EOF';
 </style><link rel="stylesheet" href="https://orgmode.org/org.css"; 
type="text/css" />
-<script type="text/javascript" src="https://orgmode.org/org-keys.js";></script>
-<script type="text/javascript">
+<script src="https://orgmode.org/org-keys.js";></script>
+<script>
   <!--/*--><![CDATA[/*><!--*/
    OrgKeyReader.registerHref('h', 'index.html');
    OrgKeyReader.registerHref('t', 'index.html');
diff --git a/mk/mansplit.pl b/mk/mansplit.pl
index 0bf39b3..0dcb11b 100755
--- a/mk/mansplit.pl
+++ b/mk/mansplit.pl
@@ -45,8 +45,8 @@ EOF
 
 $script = <<'EOF';
 <link rel="stylesheet" href="https://orgmode.org/org-manual.css"; 
type="text/css" />
-<script type="text/javascript" src="https://orgmode.org/org-keys.js";></script>
-<script type="text/javascript">
+<script src="https://orgmode.org/org-keys.js";></script>
+<script>
   <!--/*--><![CDATA[/*><!--*/
    OrgKeyReader.registerHref('h', 'index.html');
    OrgKeyReader.registerHref('t', 'index.html');
diff --git a/mk/orgcard2txt.pl b/mk/orgcard2txt.pl
index 3cd62d0..4f7c2f3 100755
--- a/mk/orgcard2txt.pl
+++ b/mk/orgcard2txt.pl
@@ -14,7 +14,7 @@
 # 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/>.
+# along with this program.  If not, see <https://www.gnu.org/licenses/>.
 #
 # Usage:
 # ======
diff --git a/mk/server.mk b/mk/server.mk
deleted file mode 100644
index 43811dd..0000000
--- a/mk/server.mk
+++ /dev/null
@@ -1,134 +0,0 @@
-#----------------------------------------------------------------------
-# This file is used for maintenance of org on the server.
-#----------------------------------------------------------------------
-.PHONY:        helpserver \
-       release rel-dirty rel-up cleanrel \
-       elpa elpa-dirty elpa-up \
-       doc-up \
-       upload-release upload-elpa upload-doc upload \
-       tagwarn version
-
-help helpall helpserver::
-       $(info )
-       $(info Maintenance)
-       $(info ===========)
-       $(info release             - clean up, create the distribution archives)
-       $(info elpa                - clean up, create the org-*.tar ELPA 
archive)
-       $(info elpaplus            - clean up, create the 
org-plus-contrib-*.tar ELPA archive)
-       $(info upload-release      - clean up, populate the server with 
archives)
-       $(info upload-elpa         - clean up, populate the server with 
org-*.tar)
-       $(info upload-elpaplus     - clean up, populate the server with 
org-plus-contrib-*.tar)
-       $(info upload-doc          - clean up, populate the server with docs)
-       $(info upload              - clean up, populate the server with 
everything)
-
-helpserver::
-       @echo ""
-
-#----------------------------------------------------------------------
-
-SERVROOT ?= upload
-SERVERMK ?= true # or just any value at all, really
-
-#----------------------------------------------------------------------
-
-ORGFULL   = README COPYING lisp/ \
-               Makefile request-assign-future.txt \
-               mk/default.mk mk/targets.mk mk/version.mk \
-               mk/org-fixup.el \
-               etc/ contrib/ doc/ testing/
-ORGFULL  := $(ORGFULL:%/=%/*)
-ORGELPA   = README_ELPA COPYING etc/ORG-NEWS lisp/ \
-               doc/dir doc/org.info doc/orgguide.info doc/orgcard.pdf \
-               etc/styles/ org-pkg.el
-ORGELPA  := $(ORGELPA:%/=%/*)
-ORGELPAPLUS := $(ORGELPA:org-pkg%=org-plus-contrib-pkg%)
-
-release:       cleanall info pdf card rel-dirty tagwarn
-rel-dirty rel-up:      ORGDIR=org-$(GITVERSION:release_%=%)
-rel-dirty:
-       @$(MAKE) GITVERSION=$(GITVERSION:release_%=%)-dist version autoloads
-       -@$(RM) $(ORGDIR) $(ORGTAR) $(ORGRZIP)
-       ln -s . $(ORGDIR)
-       tar -zcf $(ORGDIR).tar.gz $(foreach dist, $(ORGFULL), $(ORGDIR)/$(dist))
-       zip -r9  $(ORGDIR).zip    $(foreach dist, $(ORGFULL), $(ORGDIR)/$(dist))
-       -@$(RM) $(ORGDIR)
-rel-up:        info pdf card rel-dirty
-       $(CP) $(ORGDIR).tar.gz $(ORGDIR).zip $(SERVROOT)/
-
-PKG_TAG = $(shell date +%Y%m%d)
-PKG_DOC = "Outline-based notes management and organizer"
-PKG_REQ = "" # marmalade chokes on explicit "nil"
-
-elpa:          cleanall info card elpa-dirty
-elpa-dirty elpa-up:    ORGDIR=org-$(PKG_TAG)
-elpa-dirty:
-       @$(MAKE) GITVERSION=$(GITVERSION:release_%=%)-elpa version autoloads
-       -@$(RM) $(ORGDIR) $(ORGTAR) $(ORGZIP)
-       ln -s . $(ORGDIR)
-       echo "(define-package \"org\""                        > org-pkg.el
-       echo "  \"$(PKG_TAG)\" \"$(PKG_DOC)\" ($(PKG_REQ)))" >> org-pkg.el
-       echo ";; Local Variables:"                           >> org-pkg.el
-       echo ";; no-byte-compile: t"                         >> org-pkg.el
-       echo ";; End:"                                       >> org-pkg.el
-       tar --exclude=Makefile \
-         --transform='s:\(lisp\|doc\)/::' -cf $(ORGDIR).tar \
-         $(foreach dist, $(ORGELPA), $(ORGDIR)/$(dist))
-       -@$(RM) $(ORGDIR) org-pkg.el
-elpa-up:       info card elpa-dirty archive-contents
-       $(CP) archive-contents $(ORGDIR).tar $(SERVROOT)/elpa/
-
-archive-contents:
-       echo "(1 (org              . [($(PKG_TAG)) ($(PKG_REQ)) \"$(PKG_DOC)\" 
tar])"   > $@
-       echo "   (org-plus-contrib . [($(PKG_TAG)) ($(PKG_REQ)) \"$(PKG_DOC)\" 
tar]))" >> $@
-
-elpaplus:              cleanall info card elpaplus-dirty
-elpaplus-dirty elpaplus-up:    ORG_ADD_CONTRIB=org*.el ob-*.el ox-*.el ol-*.el
-elpaplus-dirty elpaplus-up:    ORGDIR=org-plus-contrib-$(PKG_TAG)
-elpaplus-dirty:
-       @$(MAKE) GITVERSION=$(GITVERSION:release_%=%)-elpaplus version autoloads
-       -@$(RM) $(ORGDIR) $(ORGTAR) $(ORGZIP)
-       ln -s . $(ORGDIR)
-       echo "(define-package \"org-plus-contrib\""           > 
org-plus-contrib-pkg.el
-       echo "  \"$(PKG_TAG)\" \"$(PKG_DOC)\" ($(PKG_REQ)))" >> 
org-plus-contrib-pkg.el
-       echo ";; Local Variables:"                           >> 
org-plus-contrib-pkg.el
-       echo ";; no-byte-compile: t"                         >> 
org-plus-contrib-pkg.el
-       echo ";; End:"                                       >> 
org-plus-contrib-pkg.el
-       tar --exclude=Makefile \
-         --transform='s:\(lisp\|doc\)/::' -cf $(ORGDIR).tar \
-         $(foreach dist, $(ORGELPAPLUS), $(ORGDIR)/$(dist))
-       -@$(RM) $(ORGDIR) org-plus-contrib-pkg.el
-       @$(MAKE) cleanlisp
-elpaplus-up:   info card elpaplus-dirty archive-contents
-       $(CP) archive-contents $(ORGDIR).tar $(SERVROOT)/elpa/
-
-tagwarn:
-       $(if $(filter-out $(ORGVERSION), $(GITVERSION)), \
-         $(info  ======================================================) \
-         $(info  =                                                    =) \
-         $(info  = A release should only be made from a revision that =) \
-         $(info  = has an annotated tag!                              =) \
-         $(info  =                                                    =) \
-         $(info  ======================================================))
-
-version:
-       @echo ORGVERSION=$(ORGVERSION) GITVERSION=$(GITVERSION)$(ORGDIST)
-       @echo "ORGVERSION       ?= $(ORGVERSION)"  > mk/version.mk
-       @echo "GITVERSION       ?= $(GITVERSION)" >> mk/version.mk
-
-cleanall clean:        cleanrel
-cleanrel:
-       -$(RM) archive-contents org-$(PKG_TAG)* org-$(DISTVERSION)* org-*.zip 
org-*.tar* mk/version.mk
-
-doc-up:        info pdf card html
-       $(MAKE) -C doc manual guide
-       $(CP) doc/org.html     $(SERVROOT)
-       $(CP) doc/org.pdf      $(SERVROOT)
-       $(CP) doc/orgguide.pdf $(SERVROOT)
-       $(CP) doc/manual/*     $(SERVROOT)/manual
-       $(CP) doc/guide/*      $(SERVROOT)/guide
-
-upload:                        cleanall rel-up doc-up elpa-up elpaplus-up
-upload-elpa:           cleanall elpa-up
-upload-elpaplus:       cleanall elpaplus-up
-upload-release:                cleanall rel-up
-upload-doc:            cleanall doc-up
diff --git a/mk/targets.mk b/mk/targets.mk
index fc5bed1..6de77b1 100644
--- a/mk/targets.mk
+++ b/mk/targets.mk
@@ -1,11 +1,11 @@
 .EXPORT_ALL_VARIABLES:
 .NOTPARALLEL: .PHONY
 # Additional distribution files
-DISTFILES_extra=  Makefile request-assign-future.txt contrib etc
+DISTFILES_extra=  Makefile request-assign-future.txt etc
 
 LISPDIRS      = lisp
 OTHERDIRS     = doc etc
-CLEANDIRS     = contrib testing mk
+CLEANDIRS     = testing mk
 SUBDIRS       = $(OTHERDIRS) $(LISPDIRS)
 INSTSUB       = $(SUBDIRS:%=install-%)
 ORG_MAKE_DOC ?= info html pdf
@@ -15,8 +15,8 @@ ifneq ($(wildcard .git),)
   ifeq ($(ORGVERSION),)
     # In elpa.git, there are no tags available.  Fall back to using
     # the org.el header.
-    ORGVERSION := $(shell $(BATCH) --eval "(require 'lisp-mnt)" \
-      --visit lisp/org.el --eval '(princ (lm-header "version"))')
+    ORGVERSION := $(patsubst %-dev,%,$(shell $(BATCH) --eval "(require 
'lisp-mnt)" \
+      --visit lisp/org.el --eval '(princ (lm-header "version"))'))
     GITVERSION ?= $(ORGVERSION)-g$(shell git rev-parse --short=6 HEAD)
   else
     GITVERSION ?= $(shell git describe --match release\* --abbrev=6 HEAD)
@@ -37,7 +37,7 @@ endif
        check test install $(INSTSUB) \
        info html pdf card refcard doc docs \
        autoloads cleanall clean $(CLEANDIRS:%=clean%) \
-       clean-install cleanelc cleandirs cleanaddcontrib \
+       clean-install cleanelc cleandirs \
        cleanlisp cleandoc cleandocs cleantest \
        compile compile-dirty uncompiled \
        config config-test config-exe config-all config-eol config-version \
@@ -55,13 +55,6 @@ config config-all::
        $(info ========= Emacs executable and Installation paths)
        $(foreach var,$(CONF_BASE),$(info $(var)        = $($(var))$(EOL)))
        $(foreach var,$(CONF_DEST),$(info $(var)        = 
$(DESTDIR)$($(var))$(EOL)))
-       $(info ========= Additional files from contrib/lisp)
-       $(info $(notdir \
-               $(wildcard \
-               $(addsuffix .el, \
-               $(addprefix contrib/lisp/, \
-               $(basename \
-               $(notdir $(ORG_ADD_CONTRIB))))))))
 config-test config-all::
        $(info )
        $(info ========= Test configuration)
@@ -115,7 +108,6 @@ ifeq ($(TEST_NO_AUTOCLEAN),) # define this variable to 
leave $(testdir) around f
        $(MAKE) cleantest
 endif
 
-up0::  cleanaddcontrib
 up0 up1 up2::
        git checkout $(GIT_BRANCH)
        git remote update
@@ -145,7 +137,7 @@ cleandirs:
 
 clean: cleanlisp cleandoc
 
-cleanall: cleandirs cleantest cleanaddcontrib
+cleanall: cleandirs cleantest
        -$(FIND) . \( -name \*~ -o -name \*# -o -name .#\* \) -exec $(RM) {} +
        -$(FIND) $(CLEANDIRS) \( -name \*~ -o -name \*.elc \) -exec $(RM) {} +
 
@@ -155,10 +147,6 @@ $(CLEANDIRS:%=clean%):
 cleanelc:
        $(MAKE) -C lisp $@
 
-cleanaddcontrib:
-       -$(RM) $(wildcard $(addprefix lisp/,$(notdir $(wildcard 
contrib/lisp/*.el))))
-
-cleanlisp:     cleanaddcontrib
 cleanlisp cleandoc:
        $(MAKE) -C $(@:clean%=%) clean
 
diff --git a/testing/lisp/test-ob-C.el b/testing/lisp/test-ob-C.el
index 6b6b728..12a5e54 100644
--- a/testing/lisp/test-ob-C.el
+++ b/testing/lisp/test-ob-C.el
@@ -16,7 +16,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
 (unless (featurep 'ob-C)
diff --git a/testing/lisp/test-ob-R.el b/testing/lisp/test-ob-R.el
index 7ce340b..1e60ae9 100644
--- a/testing/lisp/test-ob-R.el
+++ b/testing/lisp/test-ob-R.el
@@ -16,7 +16,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
 (org-test-for-executable "R")
@@ -97,6 +97,155 @@ x
      (org-babel-goto-named-result "TESTSRC") (forward-line 1)
      (should (string= "[[file:junk/test.org]]"
                      (buffer-substring-no-properties (point-at-bol) 
(point-at-eol)))))))
+
+
+
+(ert-deftest test-ob-r/output-with-<> ()
+  "make sure angle brackets are well formatted"
+    (let (ess-ask-for-ess-directory ess-history-file)
+      (should (string="[1] \"<X> <Y> <!>\"
+[1] \"one <two> three\"
+[1] \"end35\"
+"
+  (org-test-with-temp-text "#+begin_src R :results output
+     print(\"<X> <Y> <!>\")
+     print(\"one <two> three\")
+     print(\"end35\")
+   #+end_src
+"
+    (org-babel-execute-src-block))
+))))
+
+
+
+
+;; (ert-deftest test-ob-r/output-with-error ()
+;;   "make sure angle brackets are well formatted"
+;;     (let (ess-ask-for-ess-directory ess-history-file)
+;;       (should (string="Error in print(1/a) : object 'a' not found"
+;;   (org-test-with-temp-text "#+begin_src R :results output
+;;   print(1/a)
+;;  #+end_src
+;; "
+;;     (org-babel-execute-src-block))
+;; ))))
+
+
+(ert-deftest test-ob-R/output-nonprinted ()
+  (let (ess-ask-for-ess-directory ess-history-file)
+    (org-test-with-temp-text
+     "#+begin_src R :results output
+4.0 * 3.5
+log(10)
+log10(10)
+(3 + 1) * 5
+3^-1
+1/0
+#+end_src"
+     (should (string= "[1] 14\n[1] 2.302585\n[1] 1\n[1] 20\n[1] 0.3333333\n[1] 
Inf\n" (org-babel-execute-src-block))))))
+
+(ert-deftest test-ob-r/NA-blank ()
+  "For :results value, NAs should be empty"
+  (let (ess-ask-for-ess-directory ess-history-file)
+    (should (equal '(("A" "B") hline ("" 1) (1 2) (1 "") (1 4) (1 4))
+  (org-test-with-temp-text "#+BEGIN_SRC R :results value :colnames yes
+  data.frame(A=c(NA,1,1,1,1),B=c(1,2,NA,4,4))
+#+end_src"     
+  (org-babel-execute-src-block))))))
+
+
+(ert-deftest ob-session-async-R-simple-session-async-value ()
+  (let (ess-ask-for-ess-directory
+        ess-history-file
+        (org-babel-temporary-directory "/tmp")
+        (org-confirm-babel-evaluate nil))
+    (org-test-with-temp-text
+     "#+begin_src R :session R :async yes\n  Sys.sleep(.1)\n  
paste(\"Yep!\")\n#+end_src\n"
+     (should (let ((expected "Yep!"))
+              (and (not (string= expected (org-babel-execute-src-block)))
+                   (string= expected
+                            (progn
+                              (sleep-for 0 200)
+                              (goto-char (org-babel-where-is-src-block-result))
+                              (org-babel-read-result)))))))))
+
+(ert-deftest ob-session-async-R-simple-session-async-output ()
+  (let (ess-ask-for-ess-directory
+        ess-history-file
+        (org-babel-temporary-directory "/tmp")
+        (org-confirm-babel-evaluate nil))
+    (org-test-with-temp-text
+     "#+begin_src R :session R :results output :async yes\n  Sys.sleep(.1)\n  
1:5\n#+end_src\n"
+     (should (let ((expected "[1] 1 2 3 4 5"))
+              (and (not (string= expected (org-babel-execute-src-block)))
+                   (string= expected
+                            (progn
+                              (sleep-for 0 200)
+                              (goto-char (org-babel-where-is-src-block-result))
+                              (org-babel-read-result)))))))))
+
+(ert-deftest ob-session-async-R-named-output ()
+  (let (ess-ask-for-ess-directory
+        ess-history-file
+        (org-babel-temporary-directory "/tmp")
+        org-confirm-babel-evaluate
+        (src-block "#+begin_src R :async :session R :results output\n  
1:5\n#+end_src")
+        (results-before "\n\n#+NAME: foobar\n#+RESULTS:\n: [1] 1")
+        (results-after "\n\n#+NAME: foobar\n#+RESULTS:\n: [1] 1 2 3 4 5\n"))
+    (org-test-with-temp-text
+     (concat src-block results-before)
+     (should (progn (org-babel-execute-src-block)
+                    (sleep-for 0 200)
+                    (string= (concat src-block results-after)
+                             (buffer-string)))))))
+
+(ert-deftest ob-session-async-R-named-value ()
+  (let (ess-ask-for-ess-directory
+        ess-history-file
+        org-confirm-babel-evaluate
+        (org-babel-temporary-directory "/tmp")
+        (src-block "#+begin_src R :async :session R :results value\n  
paste(\"Yep!\")\n#+end_src")
+        (results-before "\n\n#+NAME: foobar\n#+RESULTS:\n: [1] 1")
+        (results-after "\n\n#+NAME: foobar\n#+RESULTS:\n: Yep!\n"))
+    (org-test-with-temp-text
+     (concat src-block results-before)
+     (should (progn (org-babel-execute-src-block)
+                    (sleep-for 0 200)
+                    (string= (concat src-block results-after)
+                             (buffer-string)))))))
+
+(ert-deftest ob-session-async-R-output-drawer ()
+  (let (ess-ask-for-ess-directory
+        ess-history-file
+        org-confirm-babel-evaluate
+        (org-babel-temporary-directory "/tmp")
+        (src-block "#+begin_src R :async :session R :results output drawer\n  
1:5\n#+end_src")
+        (result "\n\n#+RESULTS:\n:results:\n[1] 1 2 3 4 5\n:end:\n"))
+    (org-test-with-temp-text
+     src-block
+     (should (progn (org-babel-execute-src-block)
+                    (sleep-for 0 200)
+                    (string= (concat src-block result)
+                             (buffer-string)))))))
+
+(ert-deftest ob-session-async-R-value-drawer ()
+  (let (ess-ask-for-ess-directory
+        ess-history-file
+        org-confirm-babel-evaluate
+        (org-babel-temporary-directory "/tmp")
+        (src-block "#+begin_src R :async :session R :results value drawer\n  
1:3\n#+end_src")
+        (result "\n\n#+RESULTS:\n:results:\n1\n2\n3\n:end:\n"))
+    (org-test-with-temp-text
+     src-block
+     (should (progn (org-babel-execute-src-block)
+                    (sleep-for 0 200)
+                    (string= (concat src-block result)
+                             (buffer-string)))))))
+
+
+
+
 (provide 'test-ob-R)
 
 ;;; test-ob-R.el ends here
+ 
diff --git a/testing/lisp/test-ob-awk.el b/testing/lisp/test-ob-awk.el
index 491380b..7f3c0f3 100644
--- a/testing/lisp/test-ob-awk.el
+++ b/testing/lisp/test-ob-awk.el
@@ -16,7 +16,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
 (org-test-for-executable "awk")
diff --git a/testing/lisp/test-ob-clojure.el b/testing/lisp/test-ob-clojure.el
index d114a74..921b9fe 100644
--- a/testing/lisp/test-ob-clojure.el
+++ b/testing/lisp/test-ob-clojure.el
@@ -16,7 +16,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Comments:
 
diff --git a/testing/lisp/test-ob-emacs-lisp.el 
b/testing/lisp/test-ob-emacs-lisp.el
index 9bdd6dc..5f79c33 100644
--- a/testing/lisp/test-ob-emacs-lisp.el
+++ b/testing/lisp/test-ob-emacs-lisp.el
@@ -16,7 +16,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Comments:
 
diff --git a/testing/lisp/test-ob-eshell.el b/testing/lisp/test-ob-eshell.el
index 5b0eb27..d747426 100644
--- a/testing/lisp/test-ob-eshell.el
+++ b/testing/lisp/test-ob-eshell.el
@@ -16,7 +16,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Comment:
 
diff --git a/testing/lisp/test-ob-exp.el b/testing/lisp/test-ob-exp.el
index 11ec1ed..6cd7514 100644
--- a/testing/lisp/test-ob-exp.el
+++ b/testing/lisp/test-ob-exp.el
@@ -16,7 +16,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Comments:
 
diff --git a/testing/lisp/test-ob-fortran.el b/testing/lisp/test-ob-fortran.el
index 0dc7793..79a35d5 100644
--- a/testing/lisp/test-ob-fortran.el
+++ b/testing/lisp/test-ob-fortran.el
@@ -16,7 +16,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
 (org-test-for-executable "gfortran")
diff --git a/testing/lisp/test-ob-header-arg-defaults.el 
b/testing/lisp/test-ob-header-arg-defaults.el
index b625d69..1106892 100644
--- a/testing/lisp/test-ob-header-arg-defaults.el
+++ b/testing/lisp/test-ob-header-arg-defaults.el
@@ -16,7 +16,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
 
diff --git a/testing/lisp/test-ob-java.el b/testing/lisp/test-ob-java.el
new file mode 100644
index 0000000..cc3bc5a
--- /dev/null
+++ b/testing/lisp/test-ob-java.el
@@ -0,0 +1,616 @@
+;;; test-ob-java.el --- tests for ob-java.el
+
+;; Copyright (c) 2020-2021 Free Software Foundation, Inc.
+;; Authors: Eric Schulte
+;;          Dan Davison
+;; Maintainer: Ian Martins <ianxm@jhu.edu>
+
+;; This file is not 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 this program.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+(require 'org-test "../testing/org-test")
+
+(require 'ob-core)
+(defvar org-babel-temporary-directory ; from ob-core
+  (if (boundp 'org-babel-temporary-directory)
+    org-babel-temporary-directory
+  (temporary-file-directory)))
+
+(org-test-for-executable "java")
+(org-test-for-executable "javac")
+(unless (featurep 'ob-java)
+  (signal 'missing-test-dependency "Support for java code blocks"))
+
+; simple tests
+
+(ert-deftest ob-java/simple ()
+  "Hello world program that writes output. Also tests that
+ob-java defaults to scripting mode."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :results silent
+System.out.print(42);
+#+end_src"
+   (should (string= "42" (org-babel-execute-src-block)))))
+
+(ert-deftest ob-java/simple-with-bracket ()
+  "Hello world program that outputs an open square bracket."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :results output silent
+System.out.print(\"[42\");
+#+end_src"
+   (should (string= "[42" (org-babel-execute-src-block)))))
+
+(ert-deftest ob-java/simple-with-quote ()
+  "Hello world program that writes quotes."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :results output silent
+System.out.print(\"\\\"42\\\"\");
+#+end_src"
+   (should (string= "\"42\"" (org-babel-execute-src-block)))))
+
+(ert-deftest ob-java/simple-return-int ()
+  "Hello world program that returns an int value."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :results value silent
+return 42;
+#+end_src"
+   (should (eq 42 (org-babel-execute-src-block)))))
+
+(ert-deftest ob-java/simple-return-float ()
+  "Hello world program that returns a float value."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :results value silent
+return 42.0;
+#+end_src"
+   (should (equal 42.0 (org-babel-execute-src-block)))))
+
+(ert-deftest ob-java/simple-return-string ()
+  "Hello world program that returns a string value."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :results value silent
+return \"forty two\";
+#+end_src"
+    (should (string= "forty two" (org-babel-execute-src-block)))))
+
+(ert-deftest ob-java/simple-with-main ()
+  "Hello world program that defines a main function."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :results output silent
+public static void main(String[] args) {
+    System.out.print(42);
+}
+#+end_src"
+    (should (string= "42" (org-babel-execute-src-block)))))
+
+(ert-deftest ob-java/simple-with-two-methods ()
+  "Hello world program with two methods and no class."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :results output silent
+public static void main(String[] args) {
+    System.out.print(foo());
+}
+public static int foo() {
+    return 42;
+}
+#+end_src"
+    (should (string= "42" (org-babel-execute-src-block)))))
+
+(ert-deftest ob-java/simple-with-no-main ()
+  "Hello world program with no main method.  Babel adds a dummy one so it can 
run without error."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :results output silent
+public static int foo() {
+    return 42;
+}
+#+end_src"
+    (should (string= "success" (org-babel-execute-src-block)))))
+
+(ert-deftest ob-java/simple-with-main-args-array ()
+  "Hello world program that defines a main function with the square brackets 
after `args'."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :results output silent
+public static void main(String args[]) {
+    System.out.print(42);
+}
+#+end_src"
+    (should (string= "42" (org-babel-execute-src-block)))))
+
+(ert-deftest ob-java/simple-with-main-whitespace ()
+  "Hello world program that defines a main function with the square brackets 
after `args'."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :results output silent
+public
+static
+void
+main
+ (
+ String
+ args []
+ )
+{
+    System.out.print(42);
+}
+#+end_src"
+    (should (string= "42" (org-babel-execute-src-block)))))
+
+(ert-deftest ob-java/simple-with-class ()
+  "Hello world program that defines a class."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :results output silent
+public class Simple {
+    public static void main(String[] args) {
+        System.out.print(42);
+    }
+}
+#+end_src"
+   (should (string= "42" (org-babel-execute-src-block)))))
+
+(ert-deftest ob-java/simple-with-non-public-class ()
+  "Hello world program that defines a non-public class."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :results output silent
+class Simple {
+    public static void main(String[] args) {
+        System.out.print(42);
+    }
+}
+#+end_src"
+   (should (string= "42" (org-babel-execute-src-block)))))
+
+(ert-deftest ob-java/simple-with-class-and-package ()
+  "Hello world program that defines a class and package."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :results output silent
+package pkg;
+public class Simple {
+    public static void main(String[] args) {
+        System.out.print(42);
+    }
+}
+#+end_src"
+    (should (string= "42" (org-babel-execute-src-block)))))
+
+(ert-deftest ob-java/simple-with-class-attr ()
+  "Hello world program with class header attribute."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :results output silent :classname Simple
+public static void main(String[] args) {
+    System.out.print(42);
+}
+#+end_src"
+   (should (string= "42" (org-babel-execute-src-block)))))
+
+(ert-deftest ob-java/simple-with-class-attr-with-package ()
+  "Hello world program with class attr with package."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :results output silent :classname pkg.Simple
+public static void main(String[] args) {
+    System.out.print(42);
+}
+#+end_src"
+    (should (string= "42" (org-babel-execute-src-block)))))
+
+
+(ert-deftest ob-java/one-arg ()
+  "Command line arg."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :results output silent :cmdargs \"fortytwo\"
+System.out.print(args[0]);
+#+end_src"
+    (should (string= "fortytwo" (org-babel-execute-src-block)))))
+
+(ert-deftest ob-java/args-quoted-string ()
+  "Two command line args, first contains a space."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :results output silent :cmdargs \"\\\"forty 
two\\\" 42\"
+System.out.println(args[0]);
+System.out.println(args[1]);
+#+end_src"
+    (should (string= "forty two\n42\n" (org-babel-execute-src-block)))))
+
+;; var tests
+
+(ert-deftest ob-java/integer-var ()
+  "Read and write an integer variable."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :var a=42 :results output silent
+System.out.print(a);
+#+end_src"
+    (should (string= "42" (org-babel-execute-src-block)))))
+
+(ert-deftest ob-java/var-with-main ()
+  "Read and write an integer variable, with main function provided."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :var a=42 :results output silent
+public static void main(String[] args) {
+    System.out.print(a);
+}
+#+end_src"
+    (should (string= "42" (org-babel-execute-src-block)))))
+
+(ert-deftest ob-java/var-with-class ()
+  "Read and write an integer variable, with class provided."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :var a=42 :results output silent
+public class Main {
+    public static void main(String[] args) {
+        System.out.print(a);
+    }
+}
+#+end_src"
+    (should (string= "42" (org-babel-execute-src-block)))))
+
+(ert-deftest ob-java/var-with-class-and-package ()
+  "Read and write an integer variable, with class and package provided."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :var a=42 :results output silent
+package pkg;
+public class Main {
+    public static void main(String[] args) {
+        System.out.print(a);
+    }
+}
+#+end_src"
+    (should (string= "42" (org-babel-execute-src-block)))))
+
+(ert-deftest ob-java/var-with-class-and-hanging-curlies ()
+  "Read and write an integer variable, with class with hanging curlies."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :var a=42 :results output silent
+public class Main
+{
+    public static void main(String[] args)
+    {
+        System.out.print(a);
+    }
+}
+#+end_src"
+    (should (string= "42" (org-babel-execute-src-block)))))
+
+(ert-deftest ob-java/two-vars ()
+  "Read two integer variables, combine and write them."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :var a=21 b=2 :results output silent
+System.out.print(a*b);
+#+end_src"
+    (should (string= "42" (org-babel-execute-src-block)))))
+
+(ert-deftest ob-java/string-var ()
+  "Read and write a string variable."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :var a=\"forty two\" :results output silent
+System.out.print(String.format(\"%s, len=%d\", a, a.length()));
+#+end_src"
+    (should (string= "forty two, len=9" (org-babel-execute-src-block)))))
+
+(ert-deftest ob-java/multiline-string-var ()
+  "Java doesn't support multiline string literals, so this errors."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :var a=\"forty\ntwo\" :results output silent
+System.out.print(String.format(\"%s, len=%d\", a, a.length()));
+#+end_src"
+    (should-error (org-babel-execute-src-block)))
+  :type 'error)
+
+;; return list
+
+(ert-deftest ob-java/return-vector-using-list ()
+  "Return a vector using a list."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :results value vector silent
+import java.util.List;
+import java.util.Arrays;
+List<List<Integer>> a = Arrays.asList(Arrays.asList(4),
+                                      Arrays.asList(2));
+return a;
+#+end_src"
+    (should (equal '((4) (2))
+                   (org-babel-execute-src-block)))))
+
+(ert-deftest ob-java/return-vector-using-array ()
+  "Return a vector using an array."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :results value vector silent
+Integer[][] a = {{4}, {2}};
+return a;
+#+end_src"
+    (should (equal '((4) (2))
+                   (org-babel-execute-src-block)))))
+
+(ert-deftest ob-java/read-return-list ()
+  "Read and return a list."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :var a=java_list :results value silent
+import java.util.List;
+import java.util.Arrays;
+List<String> b = Arrays.asList(a.get(0).get(0),
+                               a.get(1).get(0));
+return b;
+#+end_src
+
+#+name: java_list
+- forty
+- two"
+    (should (equal '("forty" "two")
+                   (org-babel-execute-src-block)))))
+
+(ert-deftest ob-java/read-list-return-array ()
+  "Read a list and return an array."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :var a=java_list :results value silent
+String[] b = {a.get(0).get(0), a.get(1).get(0)};
+return b;
+#+end_src
+
+#+name: java_list
+- forty
+- two"
+    (should (equal '("forty" "two")
+                   (org-babel-execute-src-block)))))
+
+(ert-deftest ob-java/read-return-list-with-package ()
+  "Return a vector."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :var a=java_list :results value silent
+package pkg;
+import java.util.List;
+import java.util.Arrays;
+List<String> b = Arrays.asList(a.get(0).get(0),
+                               a.get(1).get(0));
+return b;
+#+end_src
+
+#+name: java_list
+- forty
+- two"
+    (should (equal '("forty" "two")
+                   (org-babel-execute-src-block)))))
+
+(ert-deftest ob-java/output-list-with-spaces ()
+  "Return a vector."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :results output list raw silent
+System.out.println(\"forty two\");
+System.out.println(\"forty two\");
+#+end_src"
+    (should (equal "forty two\nforty two\n"
+                   (org-babel-execute-src-block)))))
+
+;; list vars
+
+(ert-deftest ob-java/list-var ()
+  "Read and write a list variable."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :var a='(\"forty\" \"two\") :results value 
silent
+import java.util.List;
+List<String> b = a;
+return b;
+#+end_src"
+    (should (equal '("forty" "two")
+                   (org-babel-execute-src-block)))))
+
+(ert-deftest ob-java/vector-var ()
+  "Read and write a vector variable."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :var a='[\"forty\" \"two\"] :results value 
silent
+import java.util.List;
+List<String> b = a;
+return b;
+#+end_src"
+    (should (equal '("forty" "two")
+                   (org-babel-execute-src-block)))))
+
+(ert-deftest ob-java/matrix-var ()
+  "Read and write matrix variable."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :var a=java_matrix :results value silent
+import java.util.List;
+import java.util.Arrays;
+List<List<Integer>> b = Arrays.asList(Arrays.asList(a.get(0).get(0), 
a.get(1).get(0)),
+                                      Arrays.asList(a.get(0).get(1), 
a.get(1).get(1)));
+return b; // transpose
+#+end_src
+
+#+name: java_matrix
+| 2 | 1 |
+| 4 | 2 |"
+    (should (equal '((2 4) (1 2))
+                   (org-babel-execute-src-block)))))
+
+(ert-deftest ob-java/matrix-var-with-header ()
+  "Read matrix variable and write it with header."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :var a=java_matrix :results value table 
silent
+import java.util.List;
+import java.util.Arrays;
+List<List> b = Arrays.asList(Arrays.asList(\"col1\", \"col2\"),
+                                     null,
+                                     Arrays.asList(a.get(0).get(0), 
a.get(1).get(0)),
+                                     Arrays.asList(a.get(0).get(1), 
a.get(1).get(1)));
+return b; // transpose
+#+end_src
+
+#+name: java_matrix
+| 2 | 1 |
+| 4 | 2 |"
+    (should (equal '(("col1" "col2") hline (2 4) (1 2))
+                   (org-babel-execute-src-block)))))
+
+;; output table
+
+(ert-deftest ob-java/output-table-with-header ()
+  "Write a table that includes a header."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :var a=java_matrix :results output raw table 
silent
+System.out.println(\"|col1|col2|\");
+System.out.println(\"|-\");
+for (int ii=0; ii<a.size(); ii++) {
+    for (int jj=0; jj<a.get(0).size(); jj++) {
+        System.out.print(\"|\" + a.get(ii).get(jj));
+    }
+    System.out.println(\"\");
+ }
+#+end_src
+
+#+name: java_matrix
+| 2 | 1 |
+| 4 | 2 |"
+    (should (equal "|col1|col2|\n|-\n|2|1\n|4|2\n"
+                   (org-babel-execute-src-block)))))
+
+(ert-deftest ob-java/inhomogeneous_table ()
+  "Read and write an inhomogeneous table."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :var a=java_table :results value silent
+import java.util.List;
+import java.util.Arrays;
+List<List> b = Arrays.asList(Arrays.asList(a.get(0).get(0),
+                                           
Integer.parseInt(a.get(0).get(1))*2),
+                             Arrays.asList(a.get(1).get(0),
+                                           
Integer.parseInt(a.get(1).get(1))*2));
+return b;
+#+end_src
+
+#+name: java_table
+  | string | number |
+  |--------+--------|
+  | forty  |      2 |
+  | two    |      1 |"
+   (should (equal
+            '(("forty" 4) ("two" 2))
+            (org-babel-execute-src-block)))))
+
+;; imports
+
+(ert-deftest ob-java/import_library ()
+  "Import a standard java library."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :results output silent :imports 
java.util.Base64
+byte[] encoded = Base64.getEncoder().encode(\"42\".getBytes());
+String decoded = new String(Base64.getDecoder().decode(encoded));
+System.out.print(String.format(\"encoded=%s, decoded=%s\", new 
String(encoded), decoded));
+#+end_src"
+   (should (string=
+            "encoded=NDI=, decoded=42"
+            (org-babel-execute-src-block)))))
+
+(ert-deftest ob-java/import_library_inline ()
+  "Import a standard java library."
+  (org-test-with-temp-text
+      "#+begin_src java :dir 'nil :results output silent
+import java.util.Base64;
+byte[] encoded = Base64.getEncoder().encode(\"42\".getBytes());
+String decoded = new String(Base64.getDecoder().decode(encoded));
+System.out.print(String.format(\"encoded=%s, decoded=%s\", new 
String(encoded), decoded));
+#+end_src"
+   (should (string=
+            "encoded=NDI=, decoded=42"
+            (org-babel-execute-src-block)))))
+
+;; tangle
+
+(ert-deftest ob-java/tangle ()
+  "Tangle a source block."
+  (org-test-with-temp-text-in-file
+      "#+begin_src java :dir 'nil :tangle \"Tangle.java\" :results value 
:classname Tangle
+return \"tangled\";
+#+end_src"
+    (should
+     (string=
+      "public class Tangle {
+    public static void main(String[] args) {
+        return \"tangled\";
+    }
+}
+"
+      (unwind-protect
+          (progn (org-babel-tangle)
+                 (with-temp-buffer
+                   (insert-file-contents "Tangle.java")
+                   (untabify (point-min) (point-max))
+                   (buffer-string)))
+        (delete-file "Tangle.java"))))))
+
+(ert-deftest ob-java/tangle-with-package ()
+  "Tangle a source block."
+  (org-test-with-temp-text-in-file
+      "#+begin_src java :dir 'nil :tangle \"tangle/Tangle.java\" :results 
value :classname tangle.Tangle
+return \"tangled\";
+#+end_src"
+    (should
+     (string=
+      "package tangle;
+
+public class Tangle {
+    public static void main(String[] args) {
+        return \"tangled\";
+    }
+}
+"
+      (unwind-protect
+          (progn
+            (make-directory "tangle")
+            (org-babel-tangle)
+            (with-temp-buffer
+              (insert-file-contents "tangle/Tangle.java")
+              (untabify (point-min) (point-max))
+              (buffer-string)))
+        (delete-file "tangle/Tangle.java")
+        (delete-directory "tangle"))))))
+
+
+;; specify output dir
+
+(ert-deftest ob-java/simple-dir ()
+  "Hello world program that writes output."
+  (org-test-with-temp-text
+      (format  "#+begin_src java :dir %s :results output silent
+System.out.print(42);
+#+end_src" org-babel-temporary-directory)
+    (should (string=
+             "42"
+             (unwind-protect
+                 (org-babel-execute-src-block)
+               (delete-file (concat (file-name-as-directory 
org-babel-temporary-directory)
+                                    "Main.java"))
+               (delete-file (concat (file-name-as-directory 
org-babel-temporary-directory)
+                                    "Main.class")))))))
+
+(ert-deftest ob-java/simple-dir-with-package ()
+  "Hello world program that writes output."
+  (org-test-with-temp-text
+      (format "#+begin_src java :dir %s :results output silent
+package pkg;
+
+public class Main {
+    public static void main(String[] args) {
+      System.out.print(42);
+    }
+}
+#+end_src" org-babel-temporary-directory)
+    (should (string=
+             "42"
+             (unwind-protect
+                 (org-babel-execute-src-block)
+               (delete-file (concat (file-name-as-directory 
org-babel-temporary-directory)
+                                    "pkg/Main.java"))
+               (delete-file (concat (file-name-as-directory 
org-babel-temporary-directory)
+                                    "pkg/Main.class"))
+               (delete-directory (concat (file-name-as-directory 
org-babel-temporary-directory)
+                                         "pkg")))))))
+
+
+;;; test-ob-java.el ends here
diff --git a/testing/lisp/test-ob-julia.el b/testing/lisp/test-ob-julia.el
new file mode 100644
index 0000000..f6d2172
--- /dev/null
+++ b/testing/lisp/test-ob-julia.el
@@ -0,0 +1,274 @@
+;;; test-ob-python.el --- tests for ob-python.el
+
+;; Copyright (c) 2011-2014, 2019, 2021 Eric Schulte
+;; Authors: Pedro Bruel, based on test-ob-python.el by Eric Schulte
+;; Maintainer: Pedro Bruel <pedro.bruel@gmail.com>
+
+;; This file is not 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 this program.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+(org-test-for-executable "julia")
+(unless (featurep 'ob-julia)
+  (signal 'missing-test-dependency "Support for julia code blocks"))
+
+(ert-deftest test-ob-julia/colnames-yes-header-argument ()
+  (should
+   (equal '(("col") hline ("a") ("b"))
+         (org-test-with-temp-text "#+name: eg
+| col |
+|-----|
+| a   |
+| b   |
+
+#+header: :colnames yes
+#+header: :var x = eg
+<point>#+begin_src julia
+return x
+#+end_src"
+           (org-babel-execute-src-block)))))
+
+(ert-deftest test-ob-julia/colnames-yes-header-argument-again ()
+  (should
+   (equal '(("a") hline ("b*") ("c*"))
+         (org-test-with-temp-text "#+name: less-cols
+| a |
+|---|
+| b |
+| c |
+
+#+header: :colnames yes
+<point>#+begin_src julia :var tab=less-cols
+  return [[val + '*' for val in row] for row in tab]
+#+end_src"
+           (org-babel-execute-src-block)))))
+
+(ert-deftest test-ob-julia/colnames-nil-header-argument ()
+  (should
+   (equal '(("col") hline ("a") ("b"))
+         (org-test-with-temp-text "#+name: eg
+| col |
+|-----|
+| a   |
+| b   |
+
+#+header: :colnames nil
+#+header: :var x = eg
+<point>#+begin_src julia
+return x
+#+end_src"
+           (org-babel-execute-src-block)))))
+
+(ert-deftest test-ob-julia/colnames-no-header-argument-again ()
+  (should
+   (equal '(("a*") ("b*") ("c*"))
+         (org-test-with-temp-text "#+name: less-cols
+| a |
+|---|
+| b |
+| c |
+
+#+header: :colnames no
+<point>#+begin_src julia :var tab=less-cols
+  return [[val + '*' for val in row] for row in tab]
+#+end_src"
+           (org-babel-execute-src-block)))))
+
+(ert-deftest test-ob-julia/colnames-no-header-argument ()
+  (should
+   (equal '(("col") ("a") ("b"))
+         (org-test-with-temp-text "#+name: eg
+| col |
+|-----|
+| a   |
+| b   |
+
+#+header: :colnames no
+#+header: :var x = eg
+<point>#+begin_src julia
+return x
+#+end_src"
+           (org-babel-execute-src-block)))))
+
+(ert-deftest test-ob-julia/session-multiline ()
+  (should
+   (equal "20"
+         (org-test-with-temp-text "#+begin_src julia :session :results output
+  foo = 0
+  for _ in range(10):
+      foo += 1
+
+      foo += 1
+
+  print(foo)
+#+end_src"
+           (org-babel-execute-src-block)))))
+
+(ert-deftest 
test-ob-julia/insert-necessary-blank-line-when-sending-code-to-interpreter ()
+  (should
+   (equal 2 (org-test-with-temp-text "#+begin_src julia :session :results value
+if True:
+    1
+2
+#+end_src"
+             ;; Previously, while adding `:session' to a normal code
+             ;; block, also need to add extra blank lines to end
+             ;; indent block or indicate logical sections. Now, the
+             ;; `org-babel-julia-evaluate-session' can do it
+             ;; automatically:
+             ;;
+             ;; >>> if True:
+             ;; >>>     1
+             ;; >>> <insert_blank_line_here>
+             ;; >>> 2
+             (org-babel-execute-maybe)
+             (org-babel-execute-src-block)))))
+
+(ert-deftest test-ob-julia/if-else-block ()
+  (should
+   (equal "success" (org-test-with-temp-text "#+begin_src julia :session 
:results value
+value = 'failure'
+if False:
+    pass
+else:
+    value = 'success'
+value
+#+end_src"
+             (org-babel-execute-src-block)))))
+
+(ert-deftest test-ob-julia/indent-block-with-blank-lines ()
+  (should
+   (equal 20
+         (org-test-with-temp-text "#+begin_src julia :session :results value
+  foo = 0
+  for i in range(10):
+      foo += 1
+
+      foo += 1
+
+  foo
+#+end_src"
+           (org-babel-execute-src-block)))))
+
+(ert-deftest test-ob-julia/assign-underscore ()
+  (should
+   (equal "success"
+         (org-test-with-temp-text "#+begin_src julia :session :results value
+_ = 'failure'
+'success'
+#+end_src"
+           (org-babel-execute-src-block)))))
+
+(ert-deftest test-ob-julia/multiline-var ()
+  (should
+   (equal "a\nb\nc"
+         (org-test-with-temp-text "#+begin_src julia :var text=\"a\\nb\\nc\"
+return text
+#+end_src"
+           (org-babel-execute-src-block)))))
+
+(ert-deftest test-ob-julia/multiline-str ()
+  (should
+   (equal "a\nb\nc"
+         (org-test-with-temp-text "#+begin_src julia
+text=\"a\\nb\\nc\"
+return text
+#+end_src"
+           (org-babel-execute-src-block)))))
+
+(ert-deftest test-ob-julia/header-var-assignment ()
+  (should
+   (equal "success"
+         (org-test-with-temp-text "#+begin_src julia :var text=\"failure\"
+text
+text=\"success\"
+return text
+#+end_src"
+           (org-babel-execute-src-block)))))
+
+(ert-deftest test-ob-julia/session-value-sleep ()
+  (should
+   (equal "success"
+         (org-test-with-temp-text "#+begin_src julia :session :results value
+import time
+time.sleep(.1)
+'success'
+#+end_src"
+           (org-babel-execute-src-block)))))
+
+(ert-deftest test-ob-julia/async-simple-session-output ()
+  (let ((org-babel-temporary-directory temporary-file-directory)
+        (org-confirm-babel-evaluate nil))
+    (org-test-with-temp-text
+     "#+begin_src julia :session :async yes :results output
+import time
+time.sleep(.1)
+print('Yep!')
+#+end_src\n"
+     (should (let ((expected "Yep!"))
+              (and (not (string= expected (org-babel-execute-src-block)))
+                   (string= expected
+                            (progn
+                              (sleep-for 0 200)
+                              (goto-char (org-babel-where-is-src-block-result))
+                              (org-babel-read-result)))))))))
+
+(ert-deftest test-ob-julia/async-named-output ()
+  (let (org-confirm-babel-evaluate
+        (org-babel-temporary-directory temporary-file-directory)
+        (src-block "#+begin_src julia :async :session :results output
+print(\"Yep!\")
+#+end_src")
+        (results-before "
+
+#+NAME: foobar
+#+RESULTS:
+: Nope!")
+        (results-after "
+
+#+NAME: foobar
+#+RESULTS:
+: Yep!
+"))
+    (org-test-with-temp-text
+     (concat src-block results-before)
+     (should (progn (org-babel-execute-src-block)
+                    (sleep-for 0 200)
+                    (string= (concat src-block results-after)
+                             (buffer-string)))))))
+
+(ert-deftest test-ob-julia/async-output-drawer ()
+  (let (org-confirm-babel-evaluate
+        (org-babel-temporary-directory temporary-file-directory)
+        (src-block "#+begin_src julia :async :session :results output drawer
+print(list(range(3)))
+#+end_src")
+        (result "
+
+#+RESULTS:
+:results:
+[0, 1, 2]
+:end:
+"))
+    (org-test-with-temp-text
+     src-block
+     (should (progn (org-babel-execute-src-block)
+                    (sleep-for 0 200)
+                    (string= (concat src-block result)
+                             (buffer-string)))))))
+
+(provide 'test-ob-julia)
+
+;;; test-ob-julia.el ends here
diff --git a/testing/lisp/test-ob-lilypond.el b/testing/lisp/test-ob-lilypond.el
index 7de16ed..1c1d733 100644
--- a/testing/lisp/test-ob-lilypond.el
+++ b/testing/lisp/test-ob-lilypond.el
@@ -16,7 +16,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
 (unless (featurep 'ob-lilypond)
diff --git a/testing/lisp/test-ob-lob.el b/testing/lisp/test-ob-lob.el
index bf33980..c661d5a 100644
--- a/testing/lisp/test-ob-lob.el
+++ b/testing/lisp/test-ob-lob.el
@@ -16,7 +16,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 (eval-and-compile (require 'cl-lib))
 
diff --git a/testing/lisp/test-ob-lua.el b/testing/lisp/test-ob-lua.el
index 581a09e..7d82dd9 100644
--- a/testing/lisp/test-ob-lua.el
+++ b/testing/lisp/test-ob-lua.el
@@ -16,7 +16,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
 (unless (featurep 'ob-lua)
diff --git a/testing/lisp/test-ob-maxima.el b/testing/lisp/test-ob-maxima.el
index d7893dc..08f7dc0 100644
--- a/testing/lisp/test-ob-maxima.el
+++ b/testing/lisp/test-ob-maxima.el
@@ -16,7 +16,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 (org-test-for-executable "maxima")
 (unless (featurep 'ob-maxima)
diff --git a/testing/lisp/test-ob-octave.el b/testing/lisp/test-ob-octave.el
index 4a1063a..7e20add 100644
--- a/testing/lisp/test-ob-octave.el
+++ b/testing/lisp/test-ob-octave.el
@@ -16,7 +16,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 (org-test-for-executable "octave")
 (unless (featurep 'ob-octave)
diff --git a/testing/lisp/test-ob-perl.el b/testing/lisp/test-ob-perl.el
index 0e80e88..38521db 100644
--- a/testing/lisp/test-ob-perl.el
+++ b/testing/lisp/test-ob-perl.el
@@ -16,7 +16,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
 (org-test-for-executable "perl")
diff --git a/testing/lisp/test-ob-plantuml.el b/testing/lisp/test-ob-plantuml.el
index b4ae0e8..bdbd1a7 100644
--- a/testing/lisp/test-ob-plantuml.el
+++ b/testing/lisp/test-ob-plantuml.el
@@ -16,7 +16,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
 (unless (featurep 'ob-plantuml)
diff --git a/testing/lisp/test-ob-python.el b/testing/lisp/test-ob-python.el
index a2cc7b7..2032b7e 100644
--- a/testing/lisp/test-ob-python.el
+++ b/testing/lisp/test-ob-python.el
@@ -16,7 +16,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
 (org-test-for-executable "python")
@@ -207,6 +207,67 @@ time.sleep(.1)
 #+end_src"
            (org-babel-execute-src-block)))))
 
+(ert-deftest test-ob-python/async-simple-session-output ()
+  (let ((org-babel-temporary-directory temporary-file-directory)
+        (org-confirm-babel-evaluate nil))
+    (org-test-with-temp-text
+     "#+begin_src python :session :async yes :results output
+import time
+time.sleep(.1)
+print('Yep!')
+#+end_src\n"
+     (should (let ((expected "Yep!"))
+              (and (not (string= expected (org-babel-execute-src-block)))
+                   (string= expected
+                            (progn
+                              (sleep-for 0 200)
+                              (goto-char (org-babel-where-is-src-block-result))
+                              (org-babel-read-result)))))))))
+
+(ert-deftest test-ob-python/async-named-output ()
+  (let (org-confirm-babel-evaluate
+        (org-babel-temporary-directory temporary-file-directory)
+        (src-block "#+begin_src python :async :session :results output
+print(\"Yep!\")
+#+end_src")
+        (results-before "
+
+#+NAME: foobar
+#+RESULTS:
+: Nope!")
+        (results-after "
+
+#+NAME: foobar
+#+RESULTS:
+: Yep!
+"))
+    (org-test-with-temp-text
+     (concat src-block results-before)
+     (should (progn (org-babel-execute-src-block)
+                    (sleep-for 0 200)
+                    (string= (concat src-block results-after)
+                             (buffer-string)))))))
+
+(ert-deftest test-ob-python/async-output-drawer ()
+  (let (org-confirm-babel-evaluate
+        (org-babel-temporary-directory temporary-file-directory)
+        (src-block "#+begin_src python :async :session :results output drawer
+print(list(range(3)))
+#+end_src")
+        (result "
+
+#+RESULTS:
+:results:
+[0, 1, 2]
+:end:
+"))
+    (org-test-with-temp-text
+     src-block
+     (should (progn (org-babel-execute-src-block)
+                    (sleep-for 0 200)
+                    (string= (concat src-block result)
+                             (buffer-string)))))))
+
 (provide 'test-ob-python)
 
 ;;; test-ob-python.el ends here
diff --git a/testing/lisp/test-ob-ruby.el b/testing/lisp/test-ob-ruby.el
index 4d676fe..9f224a7 100644
--- a/testing/lisp/test-ob-ruby.el
+++ b/testing/lisp/test-ob-ruby.el
@@ -14,7 +14,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
 (org-test-for-executable "ruby")
diff --git a/testing/lisp/test-ob-scheme.el b/testing/lisp/test-ob-scheme.el
index da8ddf6..132914a 100644
--- a/testing/lisp/test-ob-scheme.el
+++ b/testing/lisp/test-ob-scheme.el
@@ -15,7 +15,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 
diff --git a/testing/lisp/test-ob-sed.el b/testing/lisp/test-ob-sed.el
index 2d6899c..d8e5cac 100644
--- a/testing/lisp/test-ob-sed.el
+++ b/testing/lisp/test-ob-sed.el
@@ -16,7 +16,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
 
diff --git a/testing/lisp/test-ob-shell.el b/testing/lisp/test-ob-shell.el
index 0aadb35..2f346f6 100644
--- a/testing/lisp/test-ob-shell.el
+++ b/testing/lisp/test-ob-shell.el
@@ -16,7 +16,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Comment:
 
diff --git a/testing/lisp/test-ob-sql.el b/testing/lisp/test-ob-sql.el
new file mode 100644
index 0000000..aacdaa7
--- /dev/null
+++ b/testing/lisp/test-ob-sql.el
@@ -0,0 +1,380 @@
+;;; test-ob-sql.el --- tests for ob-sql.el
+
+;; Copyright (C) 2021 Robin Joy
+
+;; Author: Robin Joy <rcj@robinjoy.net>
+;; Keywords: lisp
+
+;; 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/>.
+
+;;; Code:
+
+(unless (featurep 'ob-sql)
+  (signal 'missing-test-dependency "Support for sql code blocks"))
+
+(defmacro ob-sql/command (&rest body)
+  "Execute body and return the command that would have been executed."
+  `(cl-letf (((symbol-function 'org-babel-eval)
+              (lambda (command &rest _) (throw 'sql-command command))))
+     (catch 'sql-command
+       ,@body)))
+
+(defmacro ob-sql/command-should-contain (regexp sql-block)
+  "Check that REGEXP is contained in the command executed when evaluating 
SQL-BLOCK."
+  `(let ((regexps ,(if (listp regexp) regexp `(list ,regexp)))
+         (command (ob-sql/command (org-test-with-temp-text
+                                      ,sql-block
+                                    (org-babel-next-src-block)
+                                    (org-babel-execute-src-block)))))
+     (dolist (regexp regexps)
+       (should (string-match-p regexp command)))))
+
+(defmacro ob-sql/command-should-not-contain (regexp sql-block)
+  "Check that REGEXP is not contained in the command executed when evaluating 
SQL-BLOCK."
+  `(let ((command (ob-sql/command
+                   (org-test-with-temp-text
+                       ,sql-block
+                     (org-babel-next-src-block)
+                     (org-babel-execute-src-block)))))
+     (should-not (string-match-p ,regexp command))))
+
+;;; dbish
+(ert-deftest ob-sql/engine-dbi-uses-dbish ()
+  (ob-sql/command-should-contain "^dbish " "
+#+begin_src sql :engine dbi
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-dbish-uses-batch-mode ()
+  (ob-sql/command-should-contain " --batch " "
+#+begin_src sql :engine dbi :dbuser dummy
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-dbish-can-pass-additional-cmdline-params ()
+  (ob-sql/command-should-contain " cmdlineparams " "
+#+begin_src sql :engine dbi :dbpassword dummy :cmdline cmdlineparams
+  select * from dummy;
+#+end_src"))
+
+;;; monetdb
+(ert-deftest ob-sql/engine-monetdb-uses-mclient ()
+  (ob-sql/command-should-contain "^mclient " "
+#+begin_src sql :engine monetdb
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-monetdb-outputs-values-tab-separated ()
+  (ob-sql/command-should-contain " -f tab " "
+#+begin_src sql :engine monetdb
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-monetdb-can-pass-additional-cmdline-params ()
+  (ob-sql/command-should-contain " cmdlineparams " "
+#+begin_src sql :engine monetdb :dbpassword dummy :cmdline cmdlineparams
+  select * from dummy;
+#+end_src"))
+
+;;; mssql
+(ert-deftest ob-sql/engine-mssql-uses-sqlcmd ()
+  (ob-sql/command-should-contain "^sqlcmd " "
+#+begin_src sql :engine mssql
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-mssql-outputs-values-tab-separated ()
+  (ob-sql/command-should-contain " -s \"\t\" " "
+#+begin_src sql :engine mssql
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-mssql-can-pass-additional-cmdline-params ()
+  (ob-sql/command-should-contain " cmdlineparams " "
+#+begin_src sql :engine mssql :dbpassword dummy :cmdline cmdlineparams
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-mssql-passes-user-if-provided ()
+  (ob-sql/command-should-contain " -U \"dummy\" " "
+#+begin_src sql :engine mssql :dbuser dummy
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-mssql-passes-password-if-provided ()
+  (ob-sql/command-should-contain " -P \"dummy\" " "
+#+begin_src sql :engine mssql :dbpassword dummy
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-mssql-passes-dbhost-if-provided ()
+  (ob-sql/command-should-contain " -S \"localhost\" " "
+#+begin_src sql :engine mssql :dbhost localhost
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-mssql-passes-database-if-provided ()
+  (ob-sql/command-should-contain " -d \"R01\" " "
+#+begin_src sql :engine mssql :database R01
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-mssql-passes-all-parameter-provided ()
+  (ob-sql/command-should-contain '(" -d \"R01\" " " -S \"localhost\" " " -P 
\"pwd\" " " -U \"usr\" ") "
+#+begin_src sql :engine mssql :database R01 :dbhost localhost :dbport 30101 
:dbinstance 1 :dbuser usr :dbpassword pwd
+  select * from dummy;
+#+end_src"))
+
+;;; MySQL
+(ert-deftest ob-sql/engine-mysql-uses-mysql ()
+  (ob-sql/command-should-contain "^mysql " "
+#+begin_src sql :engine mysql
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-mysql-passes-user-if-provided ()
+  (ob-sql/command-should-contain " -udummy " "
+#+begin_src sql :engine mysql :dbuser dummy
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-mysql-passes-password-if-provided ()
+  (ob-sql/command-should-contain " -pdummy " "
+#+begin_src sql :engine mysql :dbpassword dummy
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-mysql-passes-dbhost-if-provided ()
+  (ob-sql/command-should-contain " -hlocalhost " "
+#+begin_src sql :engine mysql :dbhost localhost
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-mysql-passes-host-if-provided ()
+  (ob-sql/command-should-contain " -P30101 " "
+#+begin_src sql :engine mysql :dbport 30101
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-mysql-passes-database-if-provided ()
+  (ob-sql/command-should-contain " -dR01 " "
+#+begin_src sql :engine mysql :database R01
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-mysql-passes-all-parameter-provided ()
+  (ob-sql/command-should-contain '(" -dR01 " " -hlocalhost " " -P30101 " " 
-ppwd " " -uusr ") "
+#+begin_src sql :engine mysql :database R01 :dbhost localhost :dbport 30101 
:dbinstance 1 :dbuser usr :dbpassword pwd
+  select * from dummy;
+#+end_src"))
+
+;;; oracle
+(ert-deftest ob-sql/engine-oracle-uses-sqlplus ()
+  (ob-sql/command-should-contain "^sqlplus " "
+#+begin_src sql :engine oracle :dbuser dummy :dbpassword dummy :database dummy
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest 
ob-sql/engine-oracle-passes-user-pwd-database-host-port-if-provided ()
+  (ob-sql/command-should-contain " dummy/dummypwd@localhost:12345/R01 " "
+#+begin_src sql :engine oracle :dbuser dummy :dbpassword dummypwd :dbhost 
localhost :database R01 :dbport 12345
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest 
ob-sql/engine-oracle-passes-user-pwd-database-if-no-host-port-provided ()
+  (ob-sql/command-should-contain " dummy/dummypwd@R01 " "
+#+begin_src sql :engine oracle :dbuser dummy :dbpassword dummypwd :database R01
+  select * from dummy;
+#+end_src"))
+
+;;; postgresql
+(ert-deftest ob-sql/engine-postgresql-uses-psql ()
+  (ob-sql/command-should-contain "^psql " "
+#+begin_src sql :engine postgresql
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-postgresql-passes-password-if-provided ()
+  (ob-sql/command-should-contain "^PGPASSWORD=dummy " "
+#+begin_src sql :engine postgresql :dbpassword dummy
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-postgresql-stop-on-error ()
+  (ob-sql/command-should-contain " --set=\"ON_ERROR_STOP=1\" " "
+#+begin_src sql :engine postgresql
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest 
ob-sql/engine-postgresql-does-not-output-column-names-if-requested ()
+  (ob-sql/command-should-contain " -t " "
+#+begin_src sql :engine postgresql :colnames no
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-postgresql-outputs-column-names-by-default ()
+  (ob-sql/command-should-not-contain " -t " "
+#+begin_src sql :engine postgresql
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-postgresql-can-pass-additional-cmdline-params ()
+  (ob-sql/command-should-contain " cmdlineparams$" "
+#+begin_src sql :engine postgresql :dbpassword dummy :cmdline cmdlineparams
+  select * from dummy;
+#+end_src"))
+
+;;; SAP HANA
+(ert-deftest ob-sql/engine-saphana-uses-hdbsql ()
+  (ob-sql/command-should-contain "^hdbsql " "
+#+begin_src sql :engine saphana
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-saphana-passes-user-if-provided ()
+  (ob-sql/command-should-contain " -u dummy " "
+#+begin_src sql :engine saphana :dbuser dummy
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-saphana-passes-password-if-provided ()
+  (ob-sql/command-should-contain " -p dummy " "
+#+begin_src sql :engine saphana :dbpassword dummy
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-saphana-passes-dbinstance-if-provided ()
+  (ob-sql/command-should-contain " -i 1 " "
+#+begin_src sql :engine saphana :dbinstance 1
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-saphana-passes-dbhost-if-provided ()
+  (ob-sql/command-should-contain " -n localhost " "
+#+begin_src sql :engine saphana :dbhost localhost
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-saphana-passes-dbhost-and-dbport-if-provided ()
+  (ob-sql/command-should-contain " -n localhost:30101 " "
+#+begin_src sql :engine saphana :dbhost localhost :dbport 30101
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest 
ob-sql/engine-saphana-does-not-pass-host-port-if-only-port-provided ()
+  (ob-sql/command-should-not-contain " -n" "
+#+begin_src sql :engine saphana :dbport 30101
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-saphana-passes-database-if-provided ()
+  (ob-sql/command-should-contain " -d R01 " "
+#+begin_src sql :engine saphana :database R01
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-saphana-passes-all-parameter-provided ()
+  (ob-sql/command-should-contain '(" -d R01 " " -n localhost:30101 " " -i 1 " 
" -p pwd " " -u usr") "
+#+begin_src sql :engine saphana :database R01 :dbhost localhost :dbport 30101 
:dbinstance 1 :dbuser usr :dbpassword pwd
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-saphana-can-pass-additional-cmdline-params ()
+  (ob-sql/command-should-contain " cmdlineparams$" "
+#+begin_src sql :engine saphana :dbpassword dummy :cmdline cmdlineparams
+  select * from dummy;
+#+end_src"))
+
+;;; sqsh
+(ert-deftest ob-sql/engine-sqsh-uses-sqsh ()
+  (ob-sql/command-should-contain "^sqsh " "
+#+begin_src sql :engine sqsh
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-sqsh-can-pass-additional-cmdline-params ()
+  (ob-sql/command-should-contain " cmdlineparams " "
+#+begin_src sql :engine sqsh :dbpassword dummy :cmdline cmdlineparams
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-sqsh-passes-user-if-provided ()
+  (ob-sql/command-should-contain " -U \"dummy\" " "
+#+begin_src sql :engine sqsh :dbuser dummy
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-sqsh-passes-password-if-provided ()
+  (ob-sql/command-should-contain " -P \"dummy\" " "
+#+begin_src sql :engine sqsh :dbpassword dummy
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-sqsh-passes-host-if-provided ()
+  (ob-sql/command-should-contain " -S \"localhost\" " "
+#+begin_src sql :engine sqsh :dbhost localhost
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-sqsh-passes-database-if-provided ()
+  (ob-sql/command-should-contain " -D \"R01\" " "
+#+begin_src sql :engine sqsh :database R01
+  select * from dummy;
+#+end_src"))
+
+
+;;; vertica
+(ert-deftest ob-sql/engine-vertica-uses-vsql ()
+  (ob-sql/command-should-contain "^vsql " "
+#+begin_src sql :engine vertica
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-vertica-can-pass-additional-cmdline-params ()
+  (ob-sql/command-should-contain " cmdlineparams$" "
+#+begin_src sql :engine vertica :dbpassword dummy :cmdline cmdlineparams
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-vertica-passes-user-if-provided ()
+  (ob-sql/command-should-contain " -U dummy " "
+#+begin_src sql :engine vertica :dbuser dummy
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-vertica-passes-password-if-provided ()
+  (ob-sql/command-should-contain " -w dummy " "
+#+begin_src sql :engine vertica :dbpassword dummy
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-vertica-passes-host-if-provided ()
+  (ob-sql/command-should-contain " -h localhost " "
+#+begin_src sql :engine vertica :dbhost localhost
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-vertica-passes-database-if-provided ()
+  (ob-sql/command-should-contain " -d R01 " "
+#+begin_src sql :engine vertica :database R01
+  select * from dummy;
+#+end_src"))
+
+(ert-deftest ob-sql/engine-vertica-passes-port-if-provided ()
+  (ob-sql/command-should-contain " -p 12345 " "
+#+begin_src sql :engine vertica :dbport 12345
+  select * from dummy;
+#+end_src"))
+
+;;; test-ob-sqlite.el ends here
diff --git a/testing/lisp/test-ob-sqlite.el b/testing/lisp/test-ob-sqlite.el
index f6ffa6a..c2dc480 100644
--- a/testing/lisp/test-ob-sqlite.el
+++ b/testing/lisp/test-ob-sqlite.el
@@ -16,11 +16,10 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
 (org-test-for-executable "sqlite3")
-(require 'ob-sqlite)
 (unless (featurep 'ob-sqlite)
   (signal 'missing-test-dependency "Support for sqlite code blocks"))
 
diff --git a/testing/lisp/test-ob-table.el b/testing/lisp/test-ob-table.el
index bfa0173..3f450c2 100644
--- a/testing/lisp/test-ob-table.el
+++ b/testing/lisp/test-ob-table.el
@@ -16,7 +16,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Comments:
 
diff --git a/testing/lisp/test-ob-tangle.el b/testing/lisp/test-ob-tangle.el
index cfdf16d..2ed4ba0 100644
--- a/testing/lisp/test-ob-tangle.el
+++ b/testing/lisp/test-ob-tangle.el
@@ -16,7 +16,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Comments:
 
@@ -308,7 +308,7 @@ another block
              (delete-file file)))))
   ;; Preserve order with mixed languages.
   (should
-   (equal '("1" "3" "2" "4")
+   (equal '("1" "2" "3" "4")
          (let ((file (make-temp-file "org-tangle-")))
            (unwind-protect
                (progn
diff --git a/testing/lisp/test-ob-vala.el b/testing/lisp/test-ob-vala.el
deleted file mode 100644
index 8f1cf54..0000000
--- a/testing/lisp/test-ob-vala.el
+++ /dev/null
@@ -1,104 +0,0 @@
-;;; test-ob-vala.el --- tests for ob-vala.el
-
-;; Copyright (C) 2017, 2019 Christian Garbs
-;; Authors: Christian Garbs
-
-;; This file is not 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 this program.  If not, see <http://www.gnu.org/licenses/>.
-
-;;; Code:
-(unless (featurep 'ob-vala)
-  (signal 'missing-test-dependency "Support for Vala code blocks"))
-
-(org-test-for-executable org-babel-vala-compiler)
-
-(ert-deftest ob-vala/assert ()
-  (should t))
-
-(ert-deftest ob-vala/static-output ()
-  "Parse static output to variable."
-  (should (= 42
-            (org-test-with-temp-text
-             "
-#+begin_src vala
-  class Demo.HelloWorld : GLib.Object {
-      public static int main(string[] args) {
-          stdout.printf(\"42\n\");
-          return 0;
-      }
-  }
-#+end_src"
-             (org-babel-next-src-block)
-             (org-babel-execute-src-block)))))
-
-(ert-deftest ob-vala/return-numerics ()
-  "Return multiple numeric values."
-  (should (equal '((0) (1) (2))
-                (org-test-with-temp-text
-                 "
-#+begin_src vala
-  class Demo.HelloWorld : GLib.Object {
-      public static int main(string[] args) {
-          for (int i=0; i<3; i++) {
-              stdout.printf(\"%d\n\", i);
-          }
-          return 0;
-      }
-  }
-#+end_src"
-                 (org-babel-next-src-block)
-                 (org-babel-execute-src-block)))))
-
-(ert-deftest ob-vala/compiler-args ()
-  "Pass compiler arguments."
-  (should (string= "Foo"
-                  (org-test-with-temp-text
-                   "
-#+begin_src vala :flags -D FOO
-  class Demo.HelloWorld : GLib.Object {
-      public static int main(string[] args) {
-#if FOO
-          stdout.printf(\"Foo\n\");
-#else
-          stdout.printf(\"No foo\n\");
-#endif
-          return 0;
-      }
-  }
-#+end_src"
-                   (org-babel-next-src-block)
-                   (org-babel-execute-src-block)))))
-
-(ert-deftest ob-vala/comdline-args ()
-  "Pass commandline arguments."
-  (should (equal '(("foo") ("bar"))
-                (org-test-with-temp-text
-                 "
-#+begin_src vala :cmdline foo bar
-  class Demo.HelloWorld : GLib.Object {
-      public static int main(string[] args) {
-          // skip args[0], it is the binary name
-          for (int i=1; i < args.length; i++) {
-              stdout.printf(\"%s\n\" , args[i]);
-          }
-          return 0;
-      }
-  }
-#+end_src"
-                 (org-babel-next-src-block)
-                 (org-babel-execute-src-block)))))
-
-
-;;; test-ob-vala.el ends here
diff --git a/testing/lisp/test-ob.el b/testing/lisp/test-ob.el
index 648e9c1..a5ae8e3 100644
--- a/testing/lisp/test-ob.el
+++ b/testing/lisp/test-ob.el
@@ -16,7 +16,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
 
@@ -178,6 +178,22 @@ should still return the link."
                            (point-at-bol)
                            (point-at-eol))))))
 
+(ert-deftest test-ob/cons-cell-as-variable ()
+  "Test that cons cell can be assigned as variable."
+  (org-test-with-temp-text "
+
+#+name: cons
+#+begin_src emacs-lisp
+  (cons 1 2)
+#+end_src
+
+#+begin_src emacs-lisp :var x=cons
+  x
+#+end_src"
+
+    (org-babel-next-src-block 2)
+    (should (equal (cons 1 2) (org-babel-execute-src-block)))))
+
 (ert-deftest test-ob/multi-line-header-arguments ()
   "Test that multi-line header arguments and can be read."
   (org-test-with-temp-text-in-file "
@@ -1084,7 +1100,25 @@ trying to find the :END: marker."
     (org-babel-execute-src-block)
     (goto-char (point-min))
     (should (search-forward "[[file:foo][bar]]" nil t))
-    (should (search-forward "[[file:foo][foo]]" nil t))))
+    (should (search-forward "[[file:foo][foo]]" nil t)))
+  (should (string-match-p
+           (regexp-quote "[[file:foo]]")
+           (org-test-with-temp-text "
+#+begin_src emacs-lisp :results file :file-desc []
+  \"foo\"
+#+end_src"
+             (org-babel-next-src-block)
+             (org-babel-execute-src-block)
+             (buffer-substring-no-properties (point-min) (point-max)))))
+  (should (string-match-p
+           (regexp-quote "[[file:foo][foo]]")
+           (org-test-with-temp-text "
+#+begin_src emacs-lisp :results file :file-desc
+  \"foo\"
+#+end_src"
+             (org-babel-next-src-block)
+             (org-babel-execute-src-block)
+             (buffer-substring-no-properties (point-min) (point-max))))))
 
 (ert-deftest test-ob/result-file-link-type-header-argument ()
   "Ensure that the result is a link to a file.
diff --git a/testing/lisp/test-oc.el b/testing/lisp/test-oc.el
new file mode 100644
index 0000000..fc90a21
--- /dev/null
+++ b/testing/lisp/test-oc.el
@@ -0,0 +1,1812 @@
+;;; test-oc.el --- Tests for Org Cite library        -*- lexical-binding: t; 
-*-
+
+;; Copyright (C) 2021  Nicolas Goaziou
+
+;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'oc)
+(require 'ox)
+;; We need `org-test-with-parsed-data' macro.
+(require 'test-ox "../testing/lisp/test-ox.el")
+
+(ert-deftest test-org-cite/register-processor ()
+  "Test `org-cite-register-processor'."
+  ;; Default test.
+  (should
+   (let ((org-cite--processors nil))
+     (org-cite-register-processor 'name)))
+  ;; Handle duplicate processor.
+  (should
+   (let ((org-cite--processors nil))
+     (org-cite-register-processor 'name)
+     (org-cite-register-processor 'name)))
+  ;; Invalid name type.
+  (should-error (org-cite-register-processor "name"))
+  ;; Unknown property.
+  (should-error
+   (let ((org-cite--processors nil))
+     (org-cite-register-processor :foo 'bar))))
+
+(ert-deftest test-org-cite/unregister-processor ()
+  "Test `org-cite-unregister-processor'."
+  ;; Default test.
+  (should-not
+   (let ((org-cite--processors nil))
+     (org-cite-register-processor 'name)
+     (org-cite-unregister-processor 'name)
+     org-cite--processors))
+  ;; Error out with an unknown processor.
+  (should-error
+   (let ((org-cite--processors nil))
+     (org-cite-unregister-processor 'name))))
+
+(ert-deftest test-org-cite/inside-footnote-p ()
+  "Test `org-cite-inside-footnote-p'."
+  ;; Regular tests.
+  (should
+   (org-test-with-parsed-data "[fn:1] <point>[cite:@key]"
+     (org-cite-inside-footnote-p
+      (org-element-map tree 'citation #'identity info t))))
+  (should
+   (org-test-with-parsed-data "[fn::<point>[cite:@key]]"
+     (org-cite-inside-footnote-p
+      (org-element-map tree 'citation #'identity info t))))
+  (should-not
+   (org-test-with-parsed-data "[cite:@key]"
+     (org-cite-inside-footnote-p
+      (org-element-map tree 'citation #'identity info t))))
+  (should
+   (org-test-with-parsed-data "[fn:1] Text.<point>[cite:@key]"
+     (org-cite-inside-footnote-p
+      (org-element-map tree 'citation #'identity info t))))
+  (should
+   (org-test-with-parsed-data "[fn:1] <point>[cite:@key]\n: fixed width"
+     (org-cite-inside-footnote-p
+      (org-element-map tree 'citation #'identity info t))))
+  (should
+   (org-test-with-parsed-data "[fn:1] <point>[cite:@key]  "
+     (org-cite-inside-footnote-p
+      (org-element-map tree 'citation #'identity info t))))
+  ;; Test optional argument.
+  (should
+   (org-test-with-parsed-data "[fn:1] <point>[cite:@key]"
+     (org-cite-inside-footnote-p
+      (org-element-map tree 'citation #'identity info t)
+      t)))
+  (should-not
+   (org-test-with-parsed-data "[fn:1] <point>See [cite:@key]."
+     (org-cite-inside-footnote-p
+      (org-element-map tree 'citation #'identity info t)
+      t)))
+  (should
+   (org-test-with-parsed-data "[fn::<point>[cite:@key]]"
+     (org-cite-inside-footnote-p
+      (org-element-map tree 'citation #'identity info t)
+      t)))
+  (should-not
+   (org-test-with-parsed-data "[fn::<point>See [cite:@key].]"
+     (org-cite-inside-footnote-p
+      (org-element-map tree 'citation #'identity info t)
+      t))))
+
+(ert-deftest test-org-cite/processor-has-capability-p ()
+  "Test `org-cite-processor-has-capability-p'."
+  ;; Unknown capability error.
+  (should-error
+   (let ((org-cite--processors nil))
+     (org-cite-register-processor 'name :activate #'ignore)
+     (org-cite-processor-has-capability-p 'name 'unknown)))
+  ;; Test `activate' capability.
+  (should
+   (let ((org-cite--processors nil))
+     (org-cite-register-processor 'name :activate #'ignore)
+     (org-cite-processor-has-capability-p 'name 'activate)))
+  (should-not
+   (let ((org-cite--processors nil))
+     (org-cite-register-processor 'name :follow #'ignore)
+     (org-cite-processor-has-capability-p 'name 'activate)))
+  ;; Test `export' capability.
+  (should
+   (let ((org-cite--processors nil))
+     (org-cite-register-processor 'name
+       :export-bibliography #'ignore
+       :export-citation #'ignore)
+     (org-cite-processor-has-capability-p 'name 'export)))
+  (should
+   (let ((org-cite--processors nil))
+     (org-cite-register-processor 'name :export-citation #'ignore)
+     (org-cite-processor-has-capability-p 'name 'export)))
+  (should-not
+   (let ((org-cite--processors nil))
+     (org-cite-register-processor 'name :export-bibliography #'ignore)
+     (org-cite-processor-has-capability-p 'name 'export)))
+  ;; Test `follow' capability.
+  (should
+   (let ((org-cite--processors nil))
+     (org-cite-register-processor 'name :follow #'ignore)
+     (org-cite-processor-has-capability-p 'name 'follow)))
+  (should-not
+   (let ((org-cite--processors nil))
+     (org-cite-register-processor 'name :activate #'ignore)
+     (org-cite-processor-has-capability-p 'name 'follow)))
+  ;; Unknown processors have no capabilities.
+  (should-not (org-cite-processor-has-capability-p 'foo 'activate))
+  (should-not (org-cite-processor-has-capability-p 'foo 'export))
+  (should-not (org-cite-processor-has-capability-p 'foo 'follow)))
+
+(ert-deftest test-org-cite/get-references ()
+  "Test `org-cite-get-references'."
+  ;; Return a list of citation reference objects.
+  (should
+   (equal '(citation-reference)
+          (org-test-with-temp-text "[cite:@a]"
+            (mapcar #'org-element-type
+                    (org-cite-get-references (org-element-context))))))
+  (should
+   (equal '("a")
+          (org-test-with-temp-text "[cite:@a]"
+            (mapcar (lambda (r) (org-element-property :key r))
+                    (org-cite-get-references (org-element-context))))))
+  ;; Preserve order of references.
+  (should
+   (equal '("a" "b")
+          (org-test-with-temp-text "[cite:@a;@b]"
+            (mapcar (lambda (r) (org-element-property :key r))
+                    (org-cite-get-references (org-element-context))))))
+  ;; Parse prefix and suffix.
+  (should
+   (equal '("a" "b")
+          (org-test-with-temp-text "[cite:prefix @a suffix;@b]"
+            (mapcar (lambda (r) (org-element-property :key r))
+                    (org-cite-get-references (org-element-context))))))
+  (should
+   (equal '(("prefix ") nil)
+          (org-test-with-temp-text "[cite:prefix @a suffix;@b]"
+            (mapcar (lambda (r) (org-element-property :prefix r))
+                    (org-cite-get-references (org-element-context))))))
+  (should
+   (equal '((" suffix") nil)
+          (org-test-with-temp-text "[cite:prefix @a suffix;@b]"
+            (mapcar (lambda (r) (org-element-property :suffix r))
+                    (org-cite-get-references (org-element-context))))))
+  ;; Ignore common prefix and suffix.
+  (should
+   (equal '("a")
+          (org-test-with-temp-text "[cite:common prefix; @a ; common suffix]"
+            (mapcar (lambda (r) (org-element-property :key r))
+                    (org-cite-get-references (org-element-context))))))
+  ;; Preserve buffer positions.
+  (should
+   (org-test-with-temp-text "[cite:@a] [cite<point>:@b]"
+     (= (1+ (point))
+        (org-element-property :begin
+                              (car (org-cite-get-references 
(org-element-context)))))))
+  ;; Handle citation from a full parse tree.
+  (should
+   (equal '(1 2)
+          (org-test-with-temp-text "[cite:@a] [cite:@a;@b]"
+            (org-element-map (org-element-parse-buffer) 'citation
+              (lambda (c) (length (org-cite-get-references c)))))))
+  ;; Test optional argument.
+  (should
+   (equal '("a" "b")
+          (org-test-with-temp-text "[cite:@a;@b]"
+            (org-cite-get-references (org-element-context) t))))
+  (should
+   (equal '("a" "b")
+          (org-test-with-temp-text "[cite:@a;@b]"
+            (org-element-map (org-element-parse-buffer) 'citation
+              (lambda (c) (org-cite-get-references c t)) nil t)))))
+
+(ert-deftest test-org-cite/key-boundaries ()
+  "Test `org-cite-key-boundaries'."
+  (should
+   (equal "@key"
+          (org-test-with-temp-text "[cite:<point>@key]"
+            (let ((boundaries (org-cite-key-boundaries (org-element-context))))
+              (buffer-substring-no-properties
+               (car boundaries)
+               (cdr boundaries))))))
+  (should
+   (equal "@key"
+          (org-test-with-temp-text "[cite:<point>prefix @key]"
+            (let ((boundaries (org-cite-key-boundaries (org-element-context))))
+              (buffer-substring-no-properties
+               (car boundaries)
+               (cdr boundaries))))))
+  (should
+   (equal "@key"
+          (org-test-with-temp-text "[cite:<point>@key suffix]"
+            (let ((boundaries (org-cite-key-boundaries (org-element-context))))
+              (buffer-substring-no-properties
+               (car boundaries)
+               (cdr boundaries))))))
+  (should
+   (equal "@key"
+          (org-test-with-temp-text "[cite:global ;<point>@key]"
+            (let ((boundaries (org-cite-key-boundaries (org-element-context))))
+              (buffer-substring-no-properties
+               (car boundaries)
+               (cdr boundaries))))))
+  (should
+   (equal "@key"
+          (org-test-with-temp-text "[cite:<point>@key; global]"
+            (let ((boundaries (org-cite-key-boundaries (org-element-context))))
+              (buffer-substring-no-properties
+               (car boundaries)
+               (cdr boundaries)))))))
+
+(ert-deftest test-org-cite/supported-styles ()
+  "Test `org-cite-supported-styles'."
+  ;; Default behavior is to use export processors.
+  (should
+   (equal '((("")))
+          (let ((org-cite--processors nil)
+                (org-cite-export-processors '((t test))))
+            (org-cite-register-processor 'test :cite-styles '(((""))))
+            (org-cite-supported-styles))))
+  (should
+   (equal '((("foo" "f")) (("")))
+          (let ((org-cite--processors nil)
+                (org-cite-export-processors '((t test))))
+            (org-cite-register-processor 'test
+              :cite-styles '((("foo" "f")) ((""))))
+            (org-cite-supported-styles))))
+  ;; Explicitly provide a processor.
+  (should
+   (equal '((("")))
+          (let ((org-cite--processors nil))
+            (org-cite-register-processor 'test :cite-styles '(((""))))
+            (org-cite-supported-styles '(test)))))
+  ;; Merge style shortcuts.
+  (should
+   (equal '((("foo" "f" "g")))
+          (let ((org-cite--processors nil))
+            (org-cite-register-processor 'test :cite-styles '((("foo" "f"))))
+            (org-cite-register-processor 'test2 :cite-styles '((("foo" "g"))))
+            (org-cite-supported-styles '(test test2)))))
+  ;; Merge style variants.
+  (should
+   (equal '((("foo") ("bar") ("baz")))
+          (let ((org-cite--processors nil))
+            (org-cite-register-processor 'test
+              :cite-styles '((("foo") ("bar"))))
+            (org-cite-register-processor 'test2
+              :cite-styles '((("foo") ("baz"))))
+            (org-cite-supported-styles '(test test2)))))
+  ;; Merge variant shortcuts.
+  (should
+   (equal '((("foo") ("bar" "b" "c")))
+          (let ((org-cite--processors nil))
+            (org-cite-register-processor 'test
+              :cite-styles '((("foo") ("bar" "b"))))
+            (org-cite-register-processor 'test2
+              :cite-styles '((("foo") ("bar" "c"))))
+            (org-cite-supported-styles '(test test2)))))
+  ;; Ignore duplicates.
+  (should
+   (equal '((("foo") ("bar")))
+          (let ((org-cite--processors nil))
+            (org-cite-register-processor 'test
+              :cite-styles '((("foo") ("bar"))))
+            (org-cite-register-processor 'test2
+              :cite-styles '((("foo") ("bar"))))
+            (org-cite-supported-styles '(test test2)))))
+  (should
+   (equal '((("foo") ("bar" "b")))
+          (let ((org-cite--processors nil))
+            (org-cite-register-processor 'test
+              :cite-styles '((("foo") ("bar" "b"))))
+            (org-cite-register-processor 'test2
+              :cite-styles '((("foo") ("bar" "b"))))
+            (org-cite-supported-styles '(test test2))))))
+
+(ert-deftest test-org-cite/delete-citation ()
+  "Test `org-cite-delete-citation'."
+  ;; Error when not on a citation or citation reference.
+  (should-error
+   (org-test-with-temp-text "Text"
+     (org-cite-delete-citation (org-element-context))))
+  ;; When argument is a citation, delete it completely.  Manage
+  ;; properly blanks around it.
+  (should
+   (equal ""
+          (org-test-with-temp-text "[cite:@key]"
+            (org-cite-delete-citation (org-element-context))
+            (buffer-string))))
+  (should
+   (equal "Before After"
+          (org-test-with-temp-text "Before [<point>cite:@key] After"
+            (org-cite-delete-citation (org-element-context))
+            (buffer-string))))
+  (should
+   (equal "Before After"
+          (org-test-with-temp-text "Before [<point>cite:@key]After"
+            (org-cite-delete-citation (org-element-context))
+            (buffer-string))))
+  (should
+   (equal "Before After"
+          (org-test-with-temp-text "Before[<point>cite:@key] After"
+            (org-cite-delete-citation (org-element-context))
+            (buffer-string))))
+  ;; Ensure there is at least a blank to separate consecutive objects.
+  (should
+   (equal "Before After"
+          (org-test-with-temp-text "Before[<point>cite:@key]After"
+            (org-cite-delete-citation (org-element-context))
+            (buffer-string))))
+  ;; Remove trailing blanks when removing the citation.
+  (should
+   (equal "Before"
+          (org-test-with-temp-text "Before[<point>cite:@key]  "
+            (org-cite-delete-citation (org-element-context))
+            (buffer-string))))
+  ;; Preserve indentation if citation is at the beginning of the line.
+  (should
+   (equal "  After"
+          (org-test-with-temp-text "  [<point>cite:@key] After"
+            (org-cite-delete-citation (org-element-context))
+            (buffer-string))))
+  ;; When the citation is alone on a line, remove the whole line.
+  (should
+   (equal "Line 1\nLine 3"
+          (org-test-with-temp-text "Line 1\n[<point>cite:@key]\nLine 3"
+            (org-cite-delete-citation (org-element-context))
+            (buffer-string))))
+  ;; When there is only one citation reference object, remove the full
+  ;; citation.
+  (should
+   (equal ""
+          (org-test-with-temp-text "[cite:@<point>key]"
+            (org-cite-delete-citation (org-element-context))
+            (buffer-string))))
+  (should
+   (equal ""
+          (org-test-with-temp-text "[cite:pre @<point>key post]"
+            (org-cite-delete-citation (org-element-context))
+            (buffer-string))))
+  (should
+   (equal ""
+          (org-test-with-temp-text "[cite:pre; @<point>key ;post]"
+            (org-cite-delete-citation (org-element-context))
+            (buffer-string))))
+  ;; Otherwise, remove the reference, including any affix.
+  (should
+   (equal "[cite:@before;@after]"
+          (org-test-with-temp-text "[cite:@before;@<point>key;@after]"
+            (org-cite-delete-citation (org-element-context))
+            (buffer-string))))
+  (should
+   (equal "[cite:@before;@after]"
+          (org-test-with-temp-text "[cite:@before;pre @<point>key post;@after]"
+            (org-cite-delete-citation (org-element-context))
+            (buffer-string))))
+  (should
+   (equal "[cite:@before]"
+          (org-test-with-temp-text "[cite:@before;@<point>key]"
+            (org-cite-delete-citation (org-element-context))
+            (buffer-string))))
+  (should
+   (equal "[cite:@before;post]"
+          (org-test-with-temp-text "[cite:@before;@<point>key;post]"
+            (org-cite-delete-citation (org-element-context))
+            (buffer-string))))
+  (should
+   (equal "[cite:@after]"
+          (org-test-with-temp-text "[cite:@<point>key;@after]"
+            (org-cite-delete-citation (org-element-context))
+            (buffer-string))))
+  (should
+   (equal "[cite:pre;@after]"
+          (org-test-with-temp-text "[cite:pre;@<point>key;@after]"
+            (org-cite-delete-citation (org-element-context))
+            (buffer-string)))))
+
+(ert-deftest test-org-cite/list-bibliography-files ()
+  "Test `org-cite-list-bibliography-files'."
+  (should
+   (equal '("/bibliography")
+          (org-test-with-temp-text "#+bibliography: /bibliography"
+            (let ((org-cite-global-bibliography nil))
+              (org-cite-list-bibliography-files)))))
+  (should
+   (equal '("/bibliography")
+          (org-test-with-temp-text "#+bibliography: \"/bibliography\""
+            (let ((org-cite-global-bibliography nil))
+              (org-cite-list-bibliography-files)))))
+  (should
+   (equal '("/bibliography" "/other-bibliography")
+          (org-test-with-temp-text "#+bibliography: /bibliography"
+            (let ((org-cite-global-bibliography '("/other-bibliography")))
+              (org-cite-list-bibliography-files)))))
+  (should
+   (equal '(t)
+          (org-test-with-temp-text "#+bibliography: ./bibliography"
+            (let ((org-cite-global-bibliography nil))
+              (mapcar #'file-name-absolute-p 
(org-cite-list-bibliography-files))))))
+  (should
+   (equal '("/bibliographyA" "/bibliographyB")
+          (org-test-with-temp-text
+              "#+bibliography: /bibliographyA\n#+bibliography: /bibliographyB"
+            (let ((org-cite-global-bibliography nil))
+              (org-cite-list-bibliography-files)))))
+  (should
+   (equal '("/bibliographyA")
+          (org-test-with-temp-text
+              "#+bibliography: /bibliographyA\n#+bibliography: /bibliographyA"
+            (let ((org-cite-global-bibliography nil))
+              (org-cite-list-bibliography-files))))))
+
+(ert-deftest test-org-cite/bibliography-style ()
+  "Test `org-cite-bibliography-style'."
+  ;; Extract style from global processor definition.
+  (should
+   (equal "a"
+          (catch :exit
+            (org-test-with-temp-text "#+print_bibliography:"
+              (let ((org-cite-export-processors '((t . (foo "a" "b"))))
+                    (org-cite--processors nil))
+                (org-cite-register-processor 'foo
+                  :export-bibliography (lambda (_ _ s _ _ _) (throw :exit s))
+                  :export-citation #'ignore)
+                (org-export-as (org-export-create-backend)))))))
+  ;; Extract style from local processor definition.
+  (should
+   (equal "a"
+          (catch :exit
+            (org-test-with-temp-text
+                "#+cite_export: foo a b\n#+print_bibliography:"
+              (let ((org-cite-export-processors nil)
+                    (org-cite--processors nil))
+                (org-cite-register-processor 'foo
+                  :export-bibliography (lambda (_ _ s _ _ _) (throw :exit s))
+                  :export-citation #'ignore)
+                (org-export-as (org-export-create-backend)))))))
+  (should
+   (equal "a b"
+          (catch :exit
+            (org-test-with-temp-text
+                "#+cite_export: foo \"a b\" c\n#+print_bibliography:"
+              (let ((org-cite-export-processors nil)
+                    (org-cite--processors nil))
+                (org-cite-register-processor 'foo
+                  :export-bibliography (lambda (_ _ s _ _ _) (throw :exit s))
+                  :export-citation #'ignore)
+                (org-export-as (org-export-create-backend)))))))
+  ;; Test priority: first keyword, then local.
+  (should
+   (equal "local"
+          (catch :exit
+            (org-test-with-temp-text
+                "#+print_bibliography:\n#+cite_export: foo local a\n[cite:@a]"
+              (let ((org-cite-export-processors '((t . (foo "global" "b"))))
+                    (org-cite--processors nil))
+                (org-cite-register-processor 'foo
+                  :export-bibliography (lambda (_ _ s _ _ _) (throw :exit s))
+                  :export-citation #'ignore)
+                (org-export-as (org-export-create-backend)))))))
+  ;; Explicit "nil" styles forces default style.
+  (should-not
+   (catch :exit
+     (org-test-with-temp-text
+         "#+print_bibliography:\n#+cite_export: foo nil a\n[cite:@a]"
+       (let ((org-cite-export-processors '((t . (foo "global" "b"))))
+             (org-cite--processors nil))
+         (org-cite-register-processor 'foo
+           :export-bibliography (lambda (_ _ s _ _ _) (throw :exit s))
+           :export-citation #'ignore)
+         (org-export-as (org-export-create-backend)))))))
+
+(ert-deftest test-org-cite/bibliography-properties ()
+  "Test `org-cite-bibliography-properties'."
+  ;; Return nil without properties.
+  (should-not
+   (org-test-with-parsed-data "#+print_bibliography:"
+     (org-element-map tree 'keyword
+       #'org-cite-bibliography-properties info t)))
+  ;; Regular tests.
+  (should
+   (equal
+    '(:key "value")
+    (org-test-with-parsed-data "#+print_bibliography: :key value"
+      (org-element-map tree 'keyword
+        #'org-cite-bibliography-properties info t))))
+  (should
+   (equal
+    '(:key "value" :key2 "value2")
+    (org-test-with-parsed-data "#+print_bibliography: :key value :key2 value2"
+      (org-element-map tree 'keyword
+        #'org-cite-bibliography-properties info t))))
+  ;; Allow empty values.
+  (should
+   (equal
+    '(:key)
+    (org-test-with-parsed-data "#+print_bibliography: :key"
+      (org-element-map tree 'keyword
+        #'org-cite-bibliography-properties info t))))
+  (should
+   (equal
+    '(:key "")
+    (org-test-with-parsed-data "#+print_bibliography: :key \"\""
+      (org-element-map tree 'keyword
+        #'org-cite-bibliography-properties info t))))
+  ;; Allow space with double quotes.
+  (should
+   (equal
+    '(:key "space space")
+    (org-test-with-parsed-data "#+print_bibliography: :key \"space space\""
+      (org-element-map tree 'keyword
+        #'org-cite-bibliography-properties info t))))
+  ;; Ignore spurious values.
+  (should
+   (equal
+    '(:key "space")
+    (org-test-with-parsed-data "#+print_bibliography: :key space space"
+      (org-element-map tree 'keyword
+        #'org-cite-bibliography-properties info t))))
+  ;; Gracefully handle incomplete quotations.
+  (should
+   (equal
+    '(:key "\"space" :key2 "value2")
+    (org-test-with-parsed-data "#+print_bibliography: :key \"space :key2 
value2"
+      (org-element-map tree 'keyword
+        #'org-cite-bibliography-properties info t)))))
+
+(ert-deftest test-org-cite/citation-style ()
+  "Test `org-cite-citation-style'."
+  ;; Extract style from global processor definition.
+  (should
+   (equal '("b")
+          (catch :exit
+            (org-test-with-temp-text "[cite:@a]"
+              (let ((org-cite-export-processors '((t . (foo "a" "b"))))
+                    (org-cite--processors nil))
+                (org-cite-register-processor 'foo
+                  :export-citation (lambda (_ s _ _) (throw :exit s)))
+                (org-export-as (org-export-create-backend)))))))
+  (should
+   (equal '("b" . "variant")
+          (catch :exit
+            (org-test-with-temp-text "[cite:@a]"
+              (let ((org-cite-export-processors '((t . (foo "a" "b/variant"))))
+                    (org-cite--processors nil))
+                (org-cite-register-processor 'foo
+                  :export-citation (lambda (_ s _ _) (throw :exit s)))
+                (org-export-as (org-export-create-backend)))))))
+  ;; Extract style from local processor definition.
+  (should
+   (equal '("b")
+          (catch :exit
+            (org-test-with-temp-text "#+cite_export: foo a b\n[cite:@a]"
+              (let ((org-cite-export-processors nil)
+                    (org-cite--processors nil))
+                (org-cite-register-processor 'foo
+                  :export-citation (lambda (_ s _ _) (throw :exit s)))
+                (org-export-as (org-export-create-backend)))))))
+  (should
+   (equal '("b c")
+          (catch :exit
+            (org-test-with-temp-text "#+cite_export: foo a \"b c\"\n[cite:@a]"
+              (let ((org-cite-export-processors nil)
+                    (org-cite--processors nil))
+                (org-cite-register-processor 'foo
+                  :export-citation (lambda (_ s _ _) (throw :exit s)))
+                (org-export-as (org-export-create-backend)))))))
+  (should
+   (equal '("b" . "variant")
+          (catch :exit
+            (org-test-with-temp-text "#+cite_export: foo a 
b/variant\n[cite:@a]"
+              (let ((org-cite-export-processors nil)
+                    (org-cite--processors nil))
+                (org-cite-register-processor 'foo
+                  :export-citation (lambda (_ s _ _) (throw :exit s)))
+                (org-export-as (org-export-create-backend)))))))
+  (should
+   (equal '("b c" . "variant")
+          (catch :exit
+            (org-test-with-temp-text
+                "#+cite_export: foo a \"b c/variant\"\n[cite:@a]"
+              (let ((org-cite-export-processors nil)
+                    (org-cite--processors nil))
+                (org-cite-register-processor 'foo
+                  :export-citation (lambda (_ s _ _) (throw :exit s)))
+                (org-export-as (org-export-create-backend)))))))
+  ;; Extract style from citation itself.
+  (should
+   (equal '("b")
+          (catch :exit
+            (org-test-with-temp-text "[cite/b:@a]"
+              (let ((org-cite-export-processors '((t . (foo nil nil))))
+                    (org-cite--processors nil))
+                (org-cite-register-processor 'foo
+                  :export-citation (lambda (_ s _ _) (throw :exit s)))
+                (org-export-as (org-export-create-backend)))))))
+  (should
+   (equal '("b" . "variant")
+          (catch :exit
+            (org-test-with-temp-text "[cite/b/variant:@a]"
+              (let ((org-cite-export-processors '((t . (foo nil nil))))
+                    (org-cite--processors nil))
+                (org-cite-register-processor 'foo
+                  :export-citation (lambda (_ s _ _) (throw :exit s)))
+                (org-export-as (org-export-create-backend)))))))
+  ;; Test priority: first object, then local.
+  (should
+   (equal '("object")
+          (catch :exit
+            (org-test-with-temp-text
+                "#+cite_export: foo nil local\n[cite/object:@a]"
+              (let ((org-cite-export-processors '((t . (foo nil "global"))))
+                    (org-cite--processors nil))
+                (org-cite-register-processor 'foo
+                  :export-citation (lambda (_ s _ _) (throw :exit s)))
+                (org-export-as (org-export-create-backend)))))))
+  (should
+   (equal '("local")
+          (catch :exit
+            (org-test-with-temp-text
+                "#+cite_export: foo nil local\n[cite:@a]"
+              (let ((org-cite-export-processors '((t . (foo nil "global"))))
+                    (org-cite--processors nil))
+                (org-cite-register-processor 'foo
+                  :export-citation (lambda (_ s _ _) (throw :exit s)))
+                (org-export-as (org-export-create-backend)))))))
+  ;; Force default style with "nil".
+  (should
+   (equal '(nil)
+          (catch :exit
+            (org-test-with-temp-text
+                "#+cite_export: foo nil nil\n[cite:@a]"
+              (let ((org-cite-export-processors '((t . (foo nil "global"))))
+                    (org-cite--processors nil))
+                (org-cite-register-processor 'foo
+                  :export-citation (lambda (_ s _ _) (throw :exit s)))
+                (org-export-as (org-export-create-backend)))))))
+  (should
+   (equal '(nil)
+          (catch :exit
+            (org-test-with-temp-text "[cite/nil:@a]"
+              (let ((org-cite-export-processors '((t . (foo nil "global"))))
+                    (org-cite--processors nil))
+                (org-cite-register-processor 'foo
+                  :export-citation (lambda (_ s _ _) (throw :exit s)))
+                (org-export-as (org-export-create-backend)))))))
+  ;; Test variant inheritance.
+  (should
+   (equal '("local" . "v2")
+          (catch :exit
+            (org-test-with-temp-text "[cite/local/v2:@a]"
+              (let ((org-cite-export-processors '((t . (foo nil "global/v1"))))
+                    (org-cite--processors nil))
+                (org-cite-register-processor 'foo
+                  :export-citation (lambda (_ s _ _) (throw :exit s)))
+                (org-export-as (org-export-create-backend)))))))
+  (should
+   (equal '("global" . "v2")
+          (catch :exit
+            (org-test-with-temp-text "[cite//v2:@a]"
+              (let ((org-cite-export-processors '((t . (foo nil "global/v1"))))
+                    (org-cite--processors nil))
+                (org-cite-register-processor 'foo
+                  :export-citation (lambda (_ s _ _) (throw :exit s)))
+                (org-export-as (org-export-create-backend)))))))
+  (should
+   (equal '(nil . "v2")
+          (catch :exit
+            (org-test-with-temp-text "[cite/nil/v2:@a]"
+              (let ((org-cite-export-processors '((t . (foo nil "global/v1"))))
+                    (org-cite--processors nil))
+                (org-cite-register-processor 'foo
+                  :export-citation (lambda (_ s _ _) (throw :exit s)))
+                (org-export-as (org-export-create-backend)))))))
+  (should
+   (equal '("local" . nil)
+          (catch :exit
+            (org-test-with-temp-text "[cite/local:@a]"
+              (let ((org-cite-export-processors '((t . (foo nil "global/v1"))))
+                    (org-cite--processors nil))
+                (org-cite-register-processor 'foo
+                  :export-citation (lambda (_ s _ _) (throw :exit s)))
+                (org-export-as (org-export-create-backend))))))))
+
+(ert-deftest test-org-cite/list-citations ()
+  "Test `org-cite-list-citations'."
+  (should
+   (equal '("a")
+          (org-test-with-parsed-data "Test [cite:@a]"
+            (cl-mapcan (lambda (c)
+                         (mapcar (lambda (ref)
+                                   (org-element-property :key ref))
+                                 (org-element-contents c)))
+                       (org-cite-list-citations info)))))
+  (should
+   (equal '("a" "b")
+          (org-test-with-parsed-data "Test [cite:@a] [cite:@b]"
+            (cl-mapcan (lambda (c)
+                         (mapcar (lambda (ref)
+                                   (org-element-property :key ref))
+                                 (org-element-contents c)))
+                       (org-cite-list-citations info)))))
+  (should
+   (equal '("a")
+          (org-test-with-parsed-data "Test[fn:1]\n[fn:1] [cite:@a]"
+            (cl-mapcan (lambda (c)
+                         (mapcar (lambda (ref)
+                                   (org-element-property :key ref))
+                                 (org-element-contents c)))
+                       (org-cite-list-citations info)))))
+  (should
+   (equal '("a" "b")
+          (org-test-with-parsed-data "First[cite:@a] Second[fn:1]\n[fn:1] 
[cite:@b]"
+            (cl-mapcan (lambda (c)
+                         (mapcar (lambda (ref)
+                                   (org-element-property :key ref))
+                                 (org-element-contents c)))
+                       (org-cite-list-citations info)))))
+  (should
+   (equal '("b" "a")
+          (org-test-with-parsed-data "First[fn:1] Second[cite:@a]\n[fn:1] 
[cite:@b]"
+            (cl-mapcan (lambda (c)
+                         (mapcar (lambda (ref)
+                                   (org-element-property :key ref))
+                                 (org-element-contents c)))
+                       (org-cite-list-citations info)))))
+  (should
+   (equal '("a" "b")
+          (org-test-with-parsed-data
+              "Text[fn:1][fn:2]\n[fn:1] [cite:@a]\n\n[fn:2] [cite:@b]"
+            (cl-mapcan (lambda (c)
+                         (mapcar (lambda (ref)
+                                   (org-element-property :key ref))
+                                 (org-element-contents c)))
+                       (org-cite-list-citations info)))))
+  (should
+   (equal '("b" "a")
+          (org-test-with-parsed-data
+              "Text[fn:1]\n[fn:1] [fn:2][cite:@a]\n\n[fn:2] [cite:@b]"
+            (cl-mapcan (lambda (c)
+                         (mapcar (lambda (ref)
+                                   (org-element-property :key ref))
+                                 (org-element-contents c)))
+                       (org-cite-list-citations info)))))
+  (should
+   (equal '("a" "b")
+          (org-test-with-parsed-data
+              "Text[fn:1]\n[fn:1] [cite:@a][fn:2]\n\n[fn:2] [cite:@b]"
+            (cl-mapcan (lambda (c)
+                         (mapcar (lambda (ref)
+                                   (org-element-property :key ref))
+                                 (org-element-contents c)))
+                       (org-cite-list-citations info)))))
+  (should
+   (equal '("a")
+          (org-test-with-parsed-data "Text[fn::[cite:@a]]"
+            (cl-mapcan (lambda (c)
+                         (mapcar (lambda (ref)
+                                   (org-element-property :key ref))
+                                 (org-element-contents c)))
+                       (org-cite-list-citations info))))))
+
+(ert-deftest test-org-cite/list-keys ()
+  "Test `org-cite-list-keys'."
+  (should
+   (equal '("a")
+          (org-test-with-parsed-data "Test [cite:@a]"
+            (org-cite-list-keys info))))
+  (should
+   (equal '("a" "b")
+          (org-test-with-parsed-data "Test [cite:@a] [cite:@b]"
+            (org-cite-list-keys info))))
+  ;; Remove duplicates.
+  (should
+   (equal '("a")
+          (org-test-with-parsed-data "Test [cite:@a] [cite:@a]"
+            (org-cite-list-keys info))))
+  ;; Keys are ordered by first appearance in the document.
+  (should
+   (equal '("a" "b")
+          (org-test-with-parsed-data "Test [cite:@a] [cite:@b] [cite:@a]"
+            (org-cite-list-keys info))))
+  (should
+   (equal '("a" "b" "c")
+          (org-test-with-parsed-data
+              "Test [cite:@a][fn:1] [cite:@c] [cite:@a]\n[fn:1] [cite:@b]"
+            (org-cite-list-keys info)))))
+
+(ert-deftest test-org-cite/key-number ()
+  "Test `org-cite-key-number'."
+  (should
+   (= 1 (org-test-with-parsed-data "[cite:@key]"
+          (org-cite-key-number "key" info))))
+  (should
+   (equal '(1 2)
+          (org-test-with-parsed-data "[cite:@key] [cite:@key2] [cite:@key]"
+            (list (org-cite-key-number "key" info)
+                  (org-cite-key-number "key2" info)))))
+  ;; When "predicate" is nil, keys are sorted by appearance order in
+  ;; the buffer.
+  (should
+   (equal '((1 . "a") (2 . "c") (3 . "b"))
+          (org-test-with-parsed-data
+              "[cite:@a][fn:1] [cite:@b]\n[fn:1] [cite:@c]"
+            (sort (mapcar (lambda (key)
+                            (cons (org-cite-key-number key info) key))
+                          '("a" "b" "c"))
+                  #'car-less-than-car))))
+  (should
+   (equal '((1 . "a") (2 . "b") (3 . "c"))
+          (org-test-with-parsed-data
+              "[cite:@a][fn:1] [cite:@b]\n[fn:1] [cite:@c]"
+            (sort (mapcar (lambda (key)
+                            (cons (org-cite-key-number key info #'string<) 
key))
+                          '("a" "b" "c"))
+                  #'car-less-than-car)))))
+
+(ert-deftest test-org-cite/wrap-citation ()
+  "Test `org-cite-wrap-citation'."
+  ;; Reference test.
+  (should
+   (org-test-with-parsed-data "[cite:@key]"
+     (org-element-map tree 'citation
+       (lambda (c)
+         (org-cite-wrap-citation c info)
+         (org-cite-inside-footnote-p c))
+       info)))
+  ;; Created footnote is anonymous.
+  (should-not
+   (org-test-with-parsed-data "[cite:@key]  "
+     (org-element-map tree 'citation
+       (lambda (c)
+         (org-cite-wrap-citation c info)
+         (org-element-property :label (org-cite-inside-footnote-p c)))
+       info)))
+  ;; Created footnote is inline.
+  (should
+   (equal '(inline)
+          (org-test-with-parsed-data "[cite:@key]"
+            (org-element-map tree 'citation
+              (lambda (c)
+                (org-cite-wrap-citation c info)
+                (org-element-property :type
+                                      (org-cite-inside-footnote-p c)))
+              info))))
+  ;; Preserve `:post-blank' property.
+  (should
+   (equal '(2)
+          (org-test-with-parsed-data "[cite:@key]  "
+            (org-element-map tree 'citation
+              (lambda (c)
+                (org-cite-wrap-citation c info)
+                (org-element-property :post-blank
+                                      (org-cite-inside-footnote-p c)))
+              info))))
+  ;; Set `:post-blank' to 0 in the element before new footnote.
+  (should-not
+   (org-test-with-parsed-data "Text [cite:@key]"
+     (org-element-map tree 'citation
+       (lambda (c)
+         (org-cite-wrap-citation c info)
+         (let ((previous
+                (org-export-get-previous-element
+                 (org-cite-inside-footnote-p c) info)))
+           (string-match (rx blank string-end) previous)))
+       info)))
+  (should
+   (equal '(0)
+          (org-test-with-parsed-data "*Text* [cite:@key]"
+            (org-element-map tree 'citation
+              (lambda (c)
+                (org-cite-wrap-citation c info)
+                (let ((previous
+                       (org-export-get-previous-element
+                        (org-cite-inside-footnote-p c) info)))
+                  (org-element-property :post-blank previous)))
+              info))))
+  (should
+   (equal '("Text")
+          (org-test-with-parsed-data "Text [cite:@key]"
+            (org-element-map tree 'citation
+              (lambda (c)
+                (org-cite-wrap-citation c info)
+                (org-export-get-previous-element
+                 (org-cite-inside-footnote-p c) info))
+              info)))))
+
+(defun test-org-cite--export-with-rule (text &optional rule punct)
+  "Export TEXT string using RULE for punctuation positioning.
+Call `org-cite-adjust-note' on each citation object with RULE and, PUNCT
+arguments.  Replace citation with \"@\" character in the output."
+  (org-test-with-temp-text text
+    (let ((org-cite--processors nil))
+      (org-cite-register-processor 'test
+        :export-citation
+        (lambda (citation _s _b info)
+          (org-cite-adjust-note citation info rule punct)
+          "@"))
+      (let ((org-cite-export-processors '((t . (test nil nil)))))
+        (org-trim
+         (org-export-as
+         (org-export-create-backend
+          :transcoders
+          '((section . (lambda (_s c _i) (replace-regexp-in-string " @" "@" 
c)))
+             (paragraph . (lambda (_s c _i) c))))))))))
+
+(ert-deftest test-org-cite/adjust-note ()
+  "Test `org-cite-adjust-note' function."
+  ;; Basic tests for all rules.  In the output, @ replaces citation.
+  (let ((cases '("\"[cite:@k]!"
+                 ".\"[cite:@k]!"
+                 "\"[cite:@k]"
+                 ".\"[cite:@k]"
+                 ".[cite:@k]"
+                 "[cite:@k]!")))
+    (should                             ;test (inside inside after)
+     (equal
+      '(iia "!@\"" ".@\"!" "@\"" ".@\"" ".@" "!@")
+      (cons 'iia
+            (mapcar (lambda (c)
+                      (test-org-cite--export-with-rule
+                       c '(inside inside after)))
+                    cases))))
+    (should                             ;test (inside inside before)
+     (equal
+      '(iib "@!\"" "@.\"!" "@\"" "@.\"" "@." "@!")
+      (cons 'iib
+            (mapcar (lambda (c)
+                      (test-org-cite--export-with-rule
+                       c '(inside inside before)))
+                    cases))))
+    (should                             ;test (inside outside after)
+     (equal
+      '(ioa "!\"@" ".\"!@" "\"@" ".\"@" ".@" "!@")
+      (cons 'ioa
+            (mapcar (lambda (c)
+                      (test-org-cite--export-with-rule
+                       c '(inside outside after)))
+                    cases))))
+    (should                             ;test (inside outside before)
+     (equal
+      '(iob "!\"@" ".\"@!" "\"@" ".\"@" "@." "@!")
+      (cons 'iob
+            (mapcar (lambda (c)
+                      (test-org-cite--export-with-rule
+                       c '(inside outside before)))
+                    cases))))
+    (should                             ;test (inside same after)
+     (equal
+      '(isa "!@\"" ".\"!@" "\"@" ".@\"" ".@" "!@")
+      (cons 'isa
+            (mapcar (lambda (c)
+                      (test-org-cite--export-with-rule
+                       c '(inside same after)))
+                    cases))))
+    (should                             ;test (inside same before)
+     (equal
+      '(isb "@!\"" ".\"@!" "\"@" "@.\"" "@." "@!")
+      (cons 'isb
+            (mapcar (lambda (c)
+                      (test-org-cite--export-with-rule
+                       c '(inside same before)))
+                    cases))))
+    (should                             ;test (outside inside after)
+     (equal
+      '(oia "@\"!" ".@\"!" "@\"" "@\"." ".@" "!@")
+      (cons 'oia
+            (mapcar (lambda (c)
+                      (test-org-cite--export-with-rule
+                       c '(outside inside after)))
+                    cases))))
+    (should                             ;test (outside inside before)
+     (equal
+      '(oib "@\"!" "@.\"!" "@\"" "@\"." "@." "@!")
+      (cons 'oib
+            (mapcar (lambda (c)
+                      (test-org-cite--export-with-rule
+                       c '(outside inside before)))
+                    cases))))
+    (should                             ;test (outside outside after)
+     (equal
+      '(ooa "\"!@" ".\"!@" "\"@" "\".@" ".@" "!@")
+      (cons 'ooa
+            (mapcar (lambda (c)
+                      (test-org-cite--export-with-rule
+                       c '(outside outside after)))
+                    cases))))
+    (should                             ;test (outside outside before)
+     (equal
+      '(oob "\"@!" ".\"@!" "\"@" "\"@." "@." "@!")
+      (cons 'oob
+            (mapcar (lambda (c)
+                      (test-org-cite--export-with-rule
+                       c '(outside outside before)))
+                    cases))))
+    (should                             ;test (outside same after)
+     (equal
+      '(osa "\"!@" ".\"!@" "\"@" "\".@" ".@" "!@")
+      (cons 'osa
+            (mapcar (lambda (c)
+                      (test-org-cite--export-with-rule
+                       c '(outside same after)))
+                    cases))))
+    (should                             ;test (outside same before)
+     (equal
+      '(osb "\"@!" ".\"@!" "\"@" "\"@." "@." "@!")
+      (cons 'osb
+            (mapcar (lambda (c)
+                      (test-org-cite--export-with-rule
+                       c '(outside same before)))
+                    cases)))))
+  ;; Test `adaptive' behaviour.
+  (should
+   (equal "@\"."
+          (test-org-cite--export-with-rule ".\" [cite:@k]"
+                                           '(adaptive inside after))))
+  (should
+   (equal "@\"!"
+          (test-org-cite--export-with-rule "\" [cite:@k]!"
+                                           '(adaptive inside after))))
+  (should
+   (equal ".@\""
+          (test-org-cite--export-with-rule ".\"[cite:@k]"
+                                           '(adaptive inside after))))
+  (should
+   (equal "!@\""
+          (test-org-cite--export-with-rule "\"[cite:@k]!"
+                                           '(adaptive inside after))))
+  ;; Handle white space when inserting citation before quotation mark
+  ;; or punctuation.
+  (should
+   (equal ",@\" next"
+          (test-org-cite--export-with-rule ",\" [cite:@k] next"
+                                           '(inside inside after))))
+  (should
+   (equal "@,\" next"
+          (test-org-cite--export-with-rule ",\" [cite:@k] next"
+                                           '(inside inside before))))
+  (should
+   (equal "@\"."
+          (test-org-cite--export-with-rule "\" [cite:@k]."
+                                           '(outside inside before))))
+  (should
+   (equal "@\" !"
+          (test-org-cite--export-with-rule "\" [cite:@k] !"
+                                           '(outside inside before))))
+  (should
+   (equal "text@ !"
+          (test-org-cite--export-with-rule "text ![cite:@k]"
+                                           '(inside outside before))))
+  ;; Preserve white space between citation and final punctuation when
+  ;; moving citation past final punctuation.
+  (should
+   (equal "text !@"
+          (test-org-cite--export-with-rule "text [cite:@k] !"
+                                           '(inside inside after))))
+  (should
+   (equal "text\n !@"
+          (test-org-cite--export-with-rule "text [cite:@k]\n !"
+                                           '(inside inside after))))
+  ;; Choose punctuation with optional argument.
+  (should-not
+   (equal "!@"
+          (test-org-cite--export-with-rule "[cite:@k]!"
+                                           '(inside outside after)
+                                           '("."))))
+  (should
+   (equal ".@"
+          (test-org-cite--export-with-rule "[cite:@k]."
+                                           '(inside outside after)
+                                           '(".")))))
+
+(ert-deftest test-org-cite/parse-elements ()
+  "Test `org-cite-parse-elements' function."
+  (should-error (org-cite-parse-elements "* H"))
+  (should-error (org-cite-parse-elements "Paragraph\n* H"))
+  (should
+   (equal '(paragraph)
+          (mapcar #'org-element-type (org-cite-parse-elements "s"))))
+  (should
+   (equal '(paragraph paragraph)
+          (mapcar #'org-element-type (org-cite-parse-elements 
"Text\n\nText")))))
+
+(ert-deftest test-org-cite/parse-objects ()
+  "Test `org-cite-parse-objects' function."
+  (should
+   (equal '(plain-text)
+          (mapcar #'org-element-type (org-cite-parse-objects "s"))))
+  (should
+   (equal '(plain-text bold)
+          (mapcar #'org-element-type (org-cite-parse-objects "s *b*"))))
+  (should
+   (equal '(link)
+          (mapcar #'org-element-type (org-cite-parse-objects "[[link]]"))))
+  ;; When optional argument is non-nil, only recognize types allowed
+  ;; in as a citation reference affix.
+  (should-not
+   (equal '(link)
+          (mapcar #'org-element-type (org-cite-parse-objects "[[link]]" t))))
+  (should
+   (equal '(bold)
+          (mapcar #'org-element-type (org-cite-parse-objects "*b*" t)))))
+
+(ert-deftest test-org-cite/make-paragraph ()
+  "Test `org-cite-make-paragraph' function."
+  ;; Check string as argument.
+  (should
+   (eq 'paragraph
+       (org-element-type (org-cite-make-paragraph "a"))))
+  (should
+   (equal '("a")
+          (org-element-contents (org-cite-make-paragraph "a"))))
+  ;; Check object as argument.
+  (should
+   (eq 'paragraph
+       (org-element-type
+        (org-cite-make-paragraph (org-element-create 'bold nil "b")))))
+  (should
+   (equal '(bold)
+          (mapcar #'org-element-type
+                  (org-element-contents
+                   (org-cite-make-paragraph (org-element-create 'bold nil 
"b"))))))
+  ;; Check secondary string as argument.
+  (should
+   (eq 'paragraph
+       (org-element-type (org-cite-make-paragraph '("a")))))
+  (should
+   (equal '("a")
+          (org-element-contents (org-cite-make-paragraph '("a")))))
+  ;; Mix all types of arguments.
+  (should
+   (equal '(plain-text bold plain-text)
+          (mapcar #'org-element-type
+                  (org-element-contents
+                   (org-cite-make-paragraph
+                    "a" (org-element-create 'bold nil "b") '("c"))))))
+  ;; Check `:parent' property.
+  (should
+   (eq 'paragraph
+       (org-element-type
+        (org-element-property
+         :parent
+         (car (org-element-contents (org-cite-make-paragraph "a"))))))))
+
+(ert-deftest test-org-cite/emphasize ()
+  "Test `org-cite-emphasize' function."
+  ;; Raise an error if first argument has wrong type.
+  (should-error (org-cite-emphasize 'code "a"))
+  ;; Check string argument.
+  (should (eq 'bold (org-element-type (org-cite-emphasize 'bold "a"))))
+  (should (equal '("a") (org-element-contents (org-cite-emphasize 'bold "a"))))
+  ;; Check object argument.
+  (should
+   (eq 'bold
+       (org-element-type
+        (org-cite-emphasize 'bold (org-element-create 'bold nil "a")))))
+  (should
+   (equal '(italic)
+          (mapcar #'org-element-type
+                  (org-element-contents
+                   (org-cite-emphasize 'bold
+                     (org-element-create 'italic nil "a"))))))
+  ;; Check secondary string argument.
+  (should (eq 'bold (org-element-type (org-cite-emphasize 'bold '("a")))))
+  (should (equal '("a") (org-element-contents (org-cite-emphasize 'bold 
'("a")))))
+  ;; Mix all types of arguments.
+  (should
+   (equal '(plain-text italic plain-text)
+          (mapcar #'org-element-type
+                  (org-element-contents
+                   (org-cite-emphasize 'bold
+                     "a" (org-element-create 'italic nil "b") '("c"))))))
+  ;; Check `:parent' property.
+  (should
+   (eq 'bold
+       (org-element-type
+        (org-element-property
+         :parent
+         (car (org-element-contents (org-cite-emphasize 'bold "a"))))))))
+
+(ert-deftest test-org-cite/concat ()
+  "Test `org-cite-concat' function."
+  ;; Return nil when there is no data.
+  (should
+   (equal "" (org-element-interpret-data (org-cite-concat))))
+  ;; Concatenate strings, objects and secondary strings.
+  (should
+   (equal "ab"
+          (org-element-interpret-data (org-cite-concat "a" "b"))))
+  (should
+   (equal "*a* b"
+          (org-element-interpret-data
+           (org-cite-concat (org-element-create 'bold nil "a") " b"))))
+  (should
+   (equal "*a* b"
+          (org-element-interpret-data
+           (org-cite-concat
+            (list (org-element-create 'bold nil "a")) " b"))))
+  ;; Return an error for any other object type.
+  (should-error (org-cite-concat 2)))
+
+(ert-deftest test-org-cite/mapconcat ()
+  "Test `org-cite-mapconcat' function."
+  (should
+   (equal ""
+          (org-element-interpret-data
+           (org-cite-mapconcat #'identity nil ""))))
+  (should
+   (equal "ab"
+          (org-element-interpret-data
+           (org-cite-mapconcat #'identity '("a" "b") ""))))
+  (should
+   (equal "*a* b *c*"
+          (org-element-interpret-data
+           (org-cite-mapconcat
+            #'identity
+            (list (org-element-create 'bold nil "a")
+                  (list " b " (org-element-create 'bold nil "c"))) ""))))
+  (should
+   (equal "*a* *b*"
+          (org-element-interpret-data
+           (org-cite-mapconcat
+            (lambda (s) (org-element-create 'bold nil s))
+            '("a" "b") " "))))
+  (should
+   (equal "*a* b*c*"
+          (org-element-interpret-data
+           (org-cite-mapconcat
+            #'identity
+            (list (org-element-create 'bold nil "a")
+                  (list "b" (org-element-create 'bold nil "c"))) " ")))))
+
+
+;;; TEST capabilities.
+(ert-deftest test-org-cite/activate-capability ()
+  "Test \"activate\" capability."
+  ;; Standard test.
+  (should
+   (eq 'success
+       (catch :exit
+         (org-test-with-temp-text "[cite:@key]"
+           (let ((org-cite--processors nil)
+                 (org-cite-activate-processor 'foo))
+             (org-cite-register-processor 'foo
+               :activate (lambda (_) (throw :exit 'success)))
+             (font-lock-ensure))))))
+  ;; If there is no "follow" processor, or if processor does not
+  ;; handle this capability, fall back to fontifying whole citation
+  ;; with `org-cite' face and each key with `org-cite-key' face.
+  (should
+   (eq 'org-cite
+       (org-test-with-temp-text "[cite:@key]"
+         (let ((org-cite-activate-processor nil))
+           (font-lock-ensure)
+           (face-at-point)))))
+  (should
+   (eq 'org-cite-key
+       (org-test-with-temp-text "[cite:@<point>key]"
+         (let ((org-cite-activate-processor nil))
+           (font-lock-ensure)
+           (face-at-point)))))
+  (should
+   (eq 'org-cite
+       (org-test-with-temp-text "[cite:@key]"
+         (let ((org-cite--processors nil)
+               (org-cite-activate-processor 'foo))
+           (org-cite-register-processor 'foo)
+           (font-lock-ensure)
+           (face-at-point))))))
+
+(ert-deftest test-org-cite/export-capability ()
+  "Test \"export\" capability."
+  ;; Regular citations export.
+  (should
+   (eq 'success
+       (catch :exit
+         (org-test-with-temp-text "[cite:@key]"
+           (let ((org-cite--processors nil)
+                 (org-cite-export-processors '((t . (foo nil nil)))))
+             (org-cite-register-processor 'foo
+               :export-citation (lambda (&rest _) (throw :exit 'success)))
+             (org-export-as (org-export-create-backend)))))))
+  ;; Export citation as string.
+  (should
+   (equal "citation\n"
+          (org-test-with-temp-text "[cite:@key]"
+            (let ((org-cite--processors nil)
+                  (org-cite-export-processors '((t . (foo nil nil)))))
+              (org-cite-register-processor 'foo
+                :export-citation (lambda (&rest _) "citation"))
+              (org-export-as (org-export-create-backend
+                              :transcoders
+                              '((section . (lambda (_ c _) c))
+                                (paragraph . (lambda (_ c _) c)))))))))
+  ;; Export citation as parsed object.
+  (should
+   (equal "success\n"
+          (org-test-with-temp-text "[cite:@key]"
+            (let ((org-cite--processors nil)
+                  (org-cite-export-processors '((t . (foo nil nil)))))
+              (org-cite-register-processor 'foo
+                :export-citation (lambda (&rest _)
+                                   (org-element-create 'bold nil "cite")))
+              (org-export-as (org-export-create-backend
+                              :transcoders
+                              '((section . (lambda (_ c _) c))
+                                (paragraph . (lambda (_ c _) c))
+                                (bold . (lambda (&rest _) "success")))))))))
+  ;; Export citation as a secondary string.
+  (should
+   (equal "boldtwo\n"
+          (org-test-with-temp-text "[cite:@key]"
+            (let ((org-cite--processors nil)
+                  (org-cite-export-processors '((t . (foo nil nil)))))
+              (org-cite-register-processor 'foo
+                :export-citation (lambda (&rest _)
+                                   (list (org-element-create 'bold nil "one")
+                                         "two")))
+              (org-export-as (org-export-create-backend
+                              :transcoders
+                              '((section . (lambda (_ c _) c))
+                                (paragraph . (lambda (_ c _) c))
+                                (bold . (lambda (&rest _) "bold")))))))))
+  ;; When exporting citation as a secondary string, last object
+  ;; inherits post-blank from initial citation.
+  (should
+   (equal "twobold one-space\n"
+          (org-test-with-temp-text "[cite:@key] one-space"
+            (let ((org-cite--processors nil)
+                  (org-cite-export-processors '((t . (foo nil nil)))))
+              (org-cite-register-processor 'foo
+                :export-citation (lambda (&rest _)
+                                   (list "two"
+                                         (org-element-create 'bold nil 
"one"))))
+              (org-export-as (org-export-create-backend
+                              :transcoders
+                              '((section . (lambda (_ c _) c))
+                                (paragraph . (lambda (_ c _) c))
+                                (bold . (lambda (&rest _) "bold")))))))))
+  (should
+   (equal "boldtwo one-space\n"
+          (org-test-with-temp-text "[cite:@key] one-space"
+            (let ((org-cite--processors nil)
+                  (org-cite-export-processors '((t . (foo nil nil)))))
+              (org-cite-register-processor 'foo
+                :export-citation (lambda (&rest _)
+                                   (list (org-element-create 'bold nil "one")
+                                         "two")))
+              (org-export-as (org-export-create-backend
+                              :transcoders
+                              '((section . (lambda (_ c _) c))
+                                (paragraph . (lambda (_ c _) c))
+                                (bold . (lambda (&rest _) "bold")))))))))
+  ;; Regular bibliography export.
+  (should
+   (eq 'success
+       (catch :exit
+         (org-test-with-temp-text "#+print_bibliography:"
+           (let ((org-cite--processors nil)
+                 (org-cite-export-processors '((t . (foo nil nil)))))
+             (org-cite-register-processor 'foo
+               :export-bibliography (lambda (&rest _) (throw :exit 'success))
+               :export-citation #'ignore)
+             (org-export-as (org-export-create-backend)))))))
+  (should
+   (equal ""
+          (org-test-with-temp-text "#+print_bibliography:"
+            (let ((org-cite--processors nil)
+                  (org-cite-export-processors '((t . (foo nil nil)))))
+              (org-cite-register-processor 'foo
+                :export-citation #'ignore)
+              (org-export-as (org-export-create-backend
+                              :transcoders
+                              '((section . (lambda (_ c _) c))
+                                (paragraph . (lambda (_ c _) c)))))))))
+  ;; Export bibliography as string.
+  (should
+   (equal "bibliography\n"
+          (org-test-with-temp-text "#+print_bibliography:"
+            (let ((org-cite--processors nil)
+                  (org-cite-export-processors '((t . (foo nil nil)))))
+              (org-cite-register-processor 'foo
+                :export-bibliography (lambda (&rest _) "bibliography")
+                :export-citation #'ignore)
+              (org-export-as (org-export-create-backend
+                              :transcoders
+                              '((section . (lambda (_ c _) c))
+                                (paragraph . (lambda (_ c _) c)))))))))
+  ;; Export bibliography as a parsed element.
+  (should
+   (equal "success\n"
+          (org-test-with-temp-text "#+print_bibliography:"
+            (let ((org-cite--processors nil)
+                  (org-cite-export-processors '((t . (foo nil nil)))))
+              (org-cite-register-processor 'foo
+                :export-bibliography
+                (lambda (&rest _)
+                  (org-element-create 'example-block '(:value "foo")))
+                :export-citation #'ignore)
+              (org-export-as
+               (org-export-create-backend
+                :transcoders
+                '((section . (lambda (_ c _) c))
+                  (example-block . (lambda (&rest _) "success")))))))))
+  ;; Export bibliography as a list of parsed elements.
+  (should
+   (equal "success\nsuccess\n"
+          (org-test-with-temp-text "#+print_bibliography:"
+            (let ((org-cite--processors nil)
+                  (org-cite-export-processors '((t . (foo nil nil)))))
+              (org-cite-register-processor 'foo
+                :export-bibliography
+                (lambda (&rest _)
+                  (list (org-element-create 'example-block '(:value "foo"))
+                        (org-element-create 'example-block '(:value "bar"))))
+                :export-citation #'ignore)
+              (org-export-as
+               (org-export-create-backend
+                :transcoders
+                '((section . (lambda (_ c _) c))
+                  (example-block . (lambda (&rest _) "success")))))))))
+  ;; When exporting bibliography as a list of parsed elements, the
+  ;; last element inherits post-blank from initial keyword.
+  (should
+   (equal "success\nsuccess\n\nText\n"
+          (org-test-with-temp-text "#+print_bibliography:\n\nText"
+            (let ((org-cite--processors nil)
+                  (org-cite-export-processors '((t . (foo nil nil)))))
+              (org-cite-register-processor 'foo
+                :export-bibliography
+                (lambda (&rest _)
+                  (list (org-element-create 'example-block '(:value "foo"))
+                        (org-element-create 'example-block '(:value "bar"))))
+                :export-citation #'ignore)
+              (org-export-as
+               (org-export-create-backend
+                :transcoders
+                '((section . (lambda (_ c _) c))
+                  (example-block . (lambda (&rest _) "success"))
+                  (paragraph . (lambda (_ c _) c)))))))))
+  ;; Use more appropriate citation processor.
+  (should
+   (equal
+    '(p1 p1 p1 p3)
+    (org-test-with-temp-text "[cite:@a]"
+      (let ((org-export-registered-backends nil)
+            (org-cite--procesors nil)
+            (org-cite-export-processors
+             '((b1 . (p1))
+               (t  . (p3)))))
+        (org-cite-register-processor 'p1
+          :export-citation (lambda (&rest _) (throw :exit 'p1)))
+        (org-cite-register-processor 'p2
+          :export-citation (lambda (&rest _) (throw :exit 'p2)))
+        (org-cite-register-processor 'p3
+          :export-citation (lambda (&rest _) (throw :exit 'p3)))
+        (org-export-define-backend 'b1 nil)
+        (org-export-define-derived-backend 'b2 'b1)
+        (org-export-define-derived-backend 'b3 'b2)
+        (list (catch :exit (org-export-as 'b1))
+              (catch :exit (org-export-as 'b2))
+              (catch :exit (org-export-as 'b3))
+              (catch :exit (org-export-as (org-export-create-backend))))))))
+  (should
+   (eq 'p2
+       (org-test-with-temp-text "#+cite_export: p2\n[cite:@a]"
+         (let ((org-export-registered-backends nil)
+               (org-cite--procesors nil)
+               (org-cite-export-processors '((t  . (p1)))))
+           (org-cite-register-processor 'p1
+             :export-citation (lambda (&rest _) (throw :exit 'p1)))
+           (org-cite-register-processor 'p2
+             :export-citation (lambda (&rest _) (throw :exit 'p2)))
+           (catch :exit (org-export-as (org-export-create-backend)))))))
+  ;; Test finalizer.
+  (should
+   (eq 'success
+       (catch :exit
+         (org-test-with-temp-text "[cite:@key]"
+           (let ((org-cite--processors nil)
+                 (org-cite-export-processors '((t . (foo nil nil)))))
+             (org-cite-register-processor 'foo
+               :export-citation (lambda (&rest _) "")
+               :export-finalizer (lambda (&rest _) (throw :exit 'success)))
+             (org-export-as (org-export-create-backend)))))))
+  (should
+   (equal "finalized!"
+          (org-test-with-temp-text "[cite:@key]"
+            (let ((org-cite--processors nil)
+                  (org-cite-export-processors '((t . (foo nil nil)))))
+              (org-cite-register-processor 'foo
+                :export-citation #'ignore
+                :export-finalizer (lambda (&rest _) "finalized!"))
+              (org-export-as (org-export-create-backend))))))
+  ;; Ignore citations when there is no selected "export" processor.
+  ;; In that case, white space is removed before the citation, not
+  ;; after.
+  (should
+   (equal ""
+          (org-test-with-temp-text "[cite:@key]"
+            (let ((org-cite-export-processors nil))
+              (org-export-as (org-export-create-backend
+                              :transcoders
+                              '((section . (lambda (_ c _) c))
+                                (paragraph . (lambda (_ c _) c)))))))))
+  (should
+   (equal "Text.\n"
+          (org-test-with-temp-text "Text [cite:@key]."
+            (let ((org-cite-export-processors nil))
+              (org-export-as (org-export-create-backend
+                              :transcoders
+                              '((section . (lambda (_ c _) c))
+                                (paragraph . (lambda (_ c _) c)))))))))
+  ;; Throw an error if selected processor does not handle "export"
+  ;; capability.
+  (should-error
+   (org-test-with-temp-text "[cite:@key]"
+     (let ((org-cite--processors nil)
+           (org-cite-export-processors '((t . (foo nil nil)))))
+       (org-cite-register-processor 'foo)
+       (org-export-as (org-export-create-backend))))))
+
+(ert-deftest test-org-cite/follow-capability ()
+  "Test \"follow\" capability."
+  ;; Standard test.
+  (should
+   (eq 'success
+       (catch :exit
+         (org-test-with-temp-text "[cite:@key]"
+           (let ((org-cite--processors nil)
+                 (org-cite-follow-processor 'foo))
+             (org-cite-register-processor 'foo
+               :follow (lambda (_ _) (throw :exit 'success)))
+             (org-open-at-point))))))
+  ;; Throw an error if there is no "follow" processor, or if it is
+  ;; unable to follow a citation.
+  (should-error
+   (org-test-with-temp-text "[cite:@key]"
+     (let ((org-cite-follow-processor nil))
+       (org-open-at-point))))
+  (should-error
+   (org-test-with-temp-text "[cite:@key]"
+     (let ((org-cite--processors nil)
+           (org-cite-follow-processor 'foo))
+       (org-cite-register-processor 'foo)
+       (org-open-at-point)))))
+
+(ert-deftest test-org-cite/make-insert-processor ()
+  "Test `org-cite-make-insert-processor'."
+  (should-error (org-cite-make-insert-processor 1 2))
+  (should-error
+   (org-test-with-temp-text "[cite:@<point>a]"
+     (let ((org-cite--processors nil)
+           (org-cite-insert-processor 'foo))
+       (org-cite-register-processor 'foo
+         :insert (org-cite-make-insert-processor
+                  #'ignore (lambda (&rest _) "s")))
+       (org-cite-insert nil))))
+  (should
+   (equal "[cite:@k]"
+          (org-test-with-temp-text "[cite:@<point>a]"
+            (let ((org-cite--processors nil)
+                  (org-cite-insert-processor 'foo))
+              (org-cite-register-processor 'foo
+                :insert (org-cite-make-insert-processor
+                         (lambda (&rest _) "k") (lambda (&rest _) "s")))
+              (org-cite-insert nil)
+              (buffer-string)))))
+  (should
+   (equal "[cite:@k;@a]"
+          (org-test-with-temp-text "[cite:<point>@a]"
+            (let ((org-cite--processors nil)
+                  (org-cite-insert-processor 'foo))
+              (org-cite-register-processor 'foo
+                :insert (org-cite-make-insert-processor
+                         (lambda (&rest _) "k") (lambda (&rest _) "s")))
+              (org-cite-insert nil)
+              (buffer-string)))))
+  (should
+   (equal "[cite:@k;pre @a]"
+          (org-test-with-temp-text "[cite:<point>pre @a]"
+            (let ((org-cite--processors nil)
+                  (org-cite-insert-processor 'foo))
+              (org-cite-register-processor 'foo
+                :insert (org-cite-make-insert-processor
+                         (lambda (&rest _) "k") (lambda (&rest _) "s")))
+              (org-cite-insert nil)
+              (buffer-string)))))
+  (should
+   (equal "[cite:pre;@k;@a]"
+          (org-test-with-temp-text "[cite:<point>pre;@a]"
+            (let ((org-cite--processors nil)
+                  (org-cite-insert-processor 'foo))
+              (org-cite-register-processor 'foo
+                :insert (org-cite-make-insert-processor
+                         (lambda (&rest _) "k") (lambda (&rest _) "s")))
+              (org-cite-insert nil)
+              (buffer-string)))))
+  (should
+   (equal "[cite:@a;@k]"
+          (org-test-with-temp-text "[cite:@a<point>]"
+            (let ((org-cite--processors nil)
+                  (org-cite-insert-processor 'foo))
+              (org-cite-register-processor 'foo
+                :insert (org-cite-make-insert-processor
+                         (lambda (&rest _) "k") (lambda (&rest _) "s")))
+              (org-cite-insert nil)
+              (buffer-string)))))
+  (should
+   (equal "[cite:@a post;@k]"
+          (org-test-with-temp-text "[cite:@a post<point>]"
+            (let ((org-cite--processors nil)
+                  (org-cite-insert-processor 'foo))
+              (org-cite-register-processor 'foo
+                :insert (org-cite-make-insert-processor
+                         (lambda (&rest _) "k") (lambda (&rest _) "s")))
+              (org-cite-insert nil)
+              (buffer-string)))))
+  (should
+   (equal "[cite:@a;@k;post]"
+          (org-test-with-temp-text "[cite:@a;post<point>]"
+            (let ((org-cite--processors nil)
+                  (org-cite-insert-processor 'foo))
+              (org-cite-register-processor 'foo
+                :insert (org-cite-make-insert-processor
+                         (lambda (&rest _) "k") (lambda (&rest _) "s")))
+              (org-cite-insert nil)
+              (buffer-string)))))
+  (should
+   (equal ""
+          (org-test-with-temp-text "[cite:@<point>a]"
+            (let ((org-cite--processors nil)
+                  (org-cite-insert-processor 'foo))
+              (org-cite-register-processor 'foo
+                :insert (org-cite-make-insert-processor
+                         (lambda (&rest _) "k") (lambda (&rest _) "s")))
+              (org-cite-insert t)
+              (buffer-string)))))
+  (should
+   (equal "[cite/s:@a]"
+          (org-test-with-temp-text "[cite<point>:@a]"
+            (let ((org-cite--processors nil)
+                  (org-cite-insert-processor 'foo))
+              (org-cite-register-processor 'foo
+                :insert (org-cite-make-insert-processor
+                         (lambda (&rest _) "k") (lambda (&rest _) "s")))
+              (org-cite-insert nil)
+              (buffer-string)))))
+  (should
+   (equal "[cite:@a]"
+          (org-test-with-temp-text "[cite<point>/style:@a]"
+            (let ((org-cite--processors nil)
+                  (org-cite-insert-processor 'foo))
+              (org-cite-register-processor 'foo
+                :insert (org-cite-make-insert-processor
+                         (lambda (&rest _) "k") (lambda (&rest _) "")))
+              (org-cite-insert nil)
+              (buffer-string)))))
+  (should-error
+   (org-test-with-temp-text "[cite<point>/style:@a]"
+     (let ((org-cite--processors nil)
+           (org-cite-insert-processor 'foo))
+       (org-cite-register-processor 'foo
+         :insert (org-cite-make-insert-processor
+                  (lambda (&rest _) "k") #'ignore))
+       (org-cite-insert nil))))
+  (should
+   (equal "[cite:@a][cite:@k]"
+          (org-test-with-temp-text "[cite:@a]<point>"
+            (let ((org-cite--processors nil)
+                  (org-cite-insert-processor 'foo))
+              (org-cite-register-processor 'foo
+                :insert (org-cite-make-insert-processor
+                         (lambda (&rest _) '("k")) (lambda (&rest _) "s")))
+              (org-cite-insert nil)
+              (buffer-string)))))
+  (should
+   (equal "[cite:@k][cite:@a]"
+          (org-test-with-temp-text "<point>[cite:@a]"
+            (let ((org-cite--processors nil)
+                  (org-cite-insert-processor 'foo))
+              (org-cite-register-processor 'foo
+                :insert (org-cite-make-insert-processor
+                         (lambda (&rest _) '("k")) (lambda (&rest _) "s")))
+              (org-cite-insert nil)
+              (buffer-string)))))
+  (should
+   (equal "[cite/s:@k][cite:@a]"
+          (org-test-with-temp-text "<point>[cite:@a]"
+            (let ((org-cite--processors nil)
+                  (org-cite-insert-processor 'foo))
+              (org-cite-register-processor 'foo
+                :insert (org-cite-make-insert-processor
+                         (lambda (&rest _) '("k")) (lambda (&rest _) "s")))
+              (org-cite-insert t)
+              (buffer-string))))))
+
+(ert-deftest test-org-cite/insert-capability ()
+  "Test \"insert\" capability."
+  ;; Standard test.
+  (should
+   (eq 'success
+       (catch :exit
+         (org-test-with-temp-text ""
+           (let ((org-cite--processors nil)
+                 (org-cite-insert-processor 'foo))
+             (org-cite-register-processor 'foo
+               :insert (lambda (_ _) (throw :exit 'success)))
+             (call-interactively #'org-cite-insert))))))
+  ;; Throw an error if there is no "insert" processor, or if it is
+  ;; unable to insert a citation.
+  (should-error
+   (org-test-with-temp-text ""
+     (let ((org-cite-insert-processor nil))
+       (call-interactively #'org-cite-insert))))
+  (should-error
+   (org-test-with-temp-text ""
+     (let ((org-cite--processors nil)
+           (org-cite-insert-processor 'foo))
+       (org-cite-register-processor 'foo)
+       (call-interactively #'org-cite-insert))))
+  ;; Throw an error if the location is inappropriate for a citation.
+  (should-error
+   (org-test-with-temp-text "=verbatim<point> text="
+     (let ((org-cite--processors nil)
+           (org-cite-insert-processor 'foo))
+       (org-cite-register-processor 'foo
+         :insert (lambda (_ _) (throw :exit 'success)))
+       (call-interactively #'org-cite-insert))))
+  ;; Allow inserting citations in captions.
+  (should
+   (eq 'success
+       (catch :exit
+         (org-test-with-temp-text "#+caption: <point>\n| table |"
+           (let ((org-cite--processors nil)
+                 (org-cite-insert-processor 'foo))
+             (org-cite-register-processor 'foo
+               :insert (lambda (_ _) (throw :exit 'success)))
+             (call-interactively #'org-cite-insert))))))
+  ;; Allow inserting citations in table cells.
+  (should
+   (eq 'success
+       (catch :exit
+         (org-test-with-temp-text "| <point>table |"
+           (let ((org-cite--processors nil)
+                 (org-cite-insert-processor 'foo))
+             (org-cite-register-processor 'foo
+               :insert (lambda (_ _) (throw :exit 'success)))
+             (call-interactively #'org-cite-insert))))))
+  (should
+   (eq 'success
+       (catch :exit
+         (org-test-with-temp-text "| table<point> |"
+           (let ((org-cite--processors nil)
+                 (org-cite-insert-processor 'foo))
+             (org-cite-register-processor 'foo
+               :insert (lambda (_ _) (throw :exit 'success)))
+             (call-interactively #'org-cite-insert))))))
+  (should
+   (eq 'success
+       (catch :exit
+         (org-test-with-temp-text "| table  <point> |"
+           (let ((org-cite--processors nil)
+                 (org-cite-insert-processor 'foo))
+             (org-cite-register-processor 'foo
+               :insert (lambda (_ _) (throw :exit 'success)))
+             (call-interactively #'org-cite-insert)))))))
+
+(provide 'test-oc)
+;;; test-oc.el ends here
diff --git a/testing/lisp/test-ol-bbdb.el b/testing/lisp/test-ol-bbdb.el
index 9c6885f..114e462 100644
--- a/testing/lisp/test-ol-bbdb.el
+++ b/testing/lisp/test-ol-bbdb.el
@@ -16,7 +16,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 
diff --git a/testing/lisp/test-org-agenda.el b/testing/lisp/test-org-agenda.el
index e1c64d8..57cc18b 100644
--- a/testing/lisp/test-org-agenda.el
+++ b/testing/lisp/test-org-agenda.el
@@ -15,7 +15,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 
@@ -23,7 +23,7 @@
 
 ;;; Code:
 
-(require 'org-test)
+(require 'org-test "../testing/org-test")
 (require 'org-agenda)
 (eval-and-compile (require 'cl-lib))
 
@@ -42,6 +42,13 @@
   (mapc #'kill-buffer
        (org-test-agenda--agenda-buffers)))
 
+(defmacro org-test-agenda-with-agenda (text &rest body)
+  (declare (indent 1))
+  `(org-test-with-temp-text-in-file ,text
+     (let ((org-agenda-files `(,buffer-file-name)))
+       ,@body
+       (org-test-agenda--kill-all-agendas))))
+
 
 ;; Test the Agenda
 
@@ -192,6 +199,67 @@
     (should (search-forward "f0bcf0cd8bad93c1451bb6e1b2aaedef5cce7cbb" nil t))
     (org-test-agenda--kill-all-agendas)))
 
+;; agenda bulk actions
+
+(ert-deftest test-org-agenda/bulk ()
+  "Bulk actions are applied to marked items."
+  (org-test-agenda-with-agenda "* TODO a\n* TODO b"
+    (org-todo-list)
+    (org-agenda-bulk-mark-all)
+    (cl-letf (((symbol-function 'read-char-exclusive)
+               (lambda () ?t))
+              ((symbol-function 'completing-read)
+               (lambda (&rest rest) "DONE")))
+      (org-agenda-bulk-action))
+    (org-agenda-previous-item 99)
+    (should (looking-at ".*DONE a"))
+    (org-agenda-next-item 1)
+    (should (looking-at ".*DONE b"))))
+
+(ert-deftest test-org-agenda/bulk-custom ()
+  "Custom bulk actions are applied to all marked items."
+  (org-test-agenda-with-agenda "* TODO a\n* TODO b"
+    (org-todo-list)
+    (org-agenda-bulk-mark-all)
+
+    ;; Mock read functions
+    (let* ((f-call-cnt 0)
+           (org-agenda-bulk-custom-functions
+           `((?P ,(lambda () (setq f-call-cnt (1+ f-call-cnt)))))))
+      (cl-letf* (((symbol-function 'read-char-exclusive)
+                  (lambda () ?P)))
+        (org-agenda-bulk-action)
+        (should (= f-call-cnt 2))))))
+
+(ert-deftest test-org-agenda/bulk-custom-arg-func ()
+  "Argument collection functions can be specified for custom bulk
+functions."
+  (org-test-agenda-with-agenda "* TODO a\n* TODO b"
+    (org-todo-list)
+    (org-agenda-bulk-mark-all)
+    (let* ((f-called-cnt 0)
+           (arg-f-call-cnt 0)
+           (f-called-args nil)
+           (org-agenda-bulk-custom-functions
+            `((?P
+               ;; Custom bulk function
+               ,(lambda (&rest args)
+                  (message "test" args)
+                  (setq f-called-cnt (1+ f-called-cnt)
+
+                        f-called-args args))
+               ;; Argument collection function
+               ,(lambda ()
+                  (setq arg-f-call-cnt (1+ arg-f-call-cnt))
+                  '(1 2 3))))))
+      (cl-letf (((symbol-function 'read-char-exclusive)
+                 (lambda () ?P)))
+        (org-agenda-bulk-action))
+      (should (= f-called-cnt 2))
+      (should (= arg-f-call-cnt 1))
+      (should (equal f-called-args '(1 2 3))))))
+
+
 
 (provide 'test-org-agenda)
 
diff --git a/testing/lisp/test-org-archive.el b/testing/lisp/test-org-archive.el
index d24a547..cd8cbe8 100644
--- a/testing/lisp/test-org-archive.el
+++ b/testing/lisp/test-org-archive.el
@@ -15,7 +15,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
 
diff --git a/testing/lisp/test-org-attach-git.el 
b/testing/lisp/test-org-attach-git.el
index 36cb83b..4254a15 100644
--- a/testing/lisp/test-org-attach-git.el
+++ b/testing/lisp/test-org-attach-git.el
@@ -16,7 +16,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
 (org-test-for-executable "git-annex")
diff --git a/testing/lisp/test-org-attach.el b/testing/lisp/test-org-attach.el
index 168e5d5..6caf938 100644
--- a/testing/lisp/test-org-attach.el
+++ b/testing/lisp/test-org-attach.el
@@ -16,7 +16,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 
@@ -24,7 +24,7 @@
 
 ;;; Code:
 
-(require 'org-test)
+(require 'org-test "../testing/org-test")
 (require 'org-attach)
 (eval-and-compile (require 'cl-lib))
 
diff --git a/testing/lisp/test-org-capture.el b/testing/lisp/test-org-capture.el
index d76277f..ea42fa3 100644
--- a/testing/lisp/test-org-capture.el
+++ b/testing/lisp/test-org-capture.el
@@ -15,7 +15,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 
diff --git a/testing/lisp/test-org-clock.el b/testing/lisp/test-org-clock.el
index 771a777..d2179e1 100644
--- a/testing/lisp/test-org-clock.el
+++ b/testing/lisp/test-org-clock.el
@@ -5,7 +5,7 @@
 ;; Author: Nicolas Goaziou <n.goaziou at gmail dot com>
 
 ;; Released under the GNU General Public License version 3
-;; see: http://www.gnu.org/licenses/gpl-3.0.html
+;; see: https://www.gnu.org/licenses/gpl-3.0.html
 
 ;;;; Comments
 
diff --git a/testing/lisp/test-org-colview.el b/testing/lisp/test-org-colview.el
index 7612074..64da561 100644
--- a/testing/lisp/test-org-colview.el
+++ b/testing/lisp/test-org-colview.el
@@ -15,7 +15,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
 
diff --git a/testing/lisp/test-org-datetree.el 
b/testing/lisp/test-org-datetree.el
index daebcaa..45604f0 100644
--- a/testing/lisp/test-org-datetree.el
+++ b/testing/lisp/test-org-datetree.el
@@ -17,7 +17,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
 
diff --git a/testing/lisp/test-org-duration.el 
b/testing/lisp/test-org-duration.el
index 981c00f..0a0d2b7 100644
--- a/testing/lisp/test-org-duration.el
+++ b/testing/lisp/test-org-duration.el
@@ -15,7 +15,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
 
diff --git a/testing/lisp/test-org-element.el b/testing/lisp/test-org-element.el
index 93dd3b1..ea9f97a 100644
--- a/testing/lisp/test-org-element.el
+++ b/testing/lisp/test-org-element.el
@@ -15,7 +15,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
 
@@ -519,6 +519,145 @@ Some other text
      (= (org-element-property :end (org-element-at-point)) (point-max)))))
 
 
+;;;; Citation
+
+(ert-deftest test-org-element/citation-parser ()
+  "Test `citation' parser"
+  ;; Parse citations.  They must contain at least a bare key.
+  (should
+   (eq 'citation
+       (org-test-with-temp-text "[cite:@key]"
+        (org-element-type (org-element-context)))))
+  (should-not
+   (eq 'citation
+       (org-test-with-temp-text "[cite:text]"
+        (org-element-type (org-element-context)))))
+  ;; Citation may contain a style.
+  (should
+   (eq 'citation
+       (org-test-with-temp-text "[cite/style:@key]"
+        (org-element-type (org-element-context)))))
+  (should
+   (equal "style"
+         (org-test-with-temp-text "[cite/style:@key]"
+           (org-element-property :style (org-element-context)))))
+  ;; Handle multi citations separated with semi-columns.
+  (should
+   (eq 'citation
+       (org-test-with-temp-text "[cite:@a;@b;@c]"
+        (org-element-type (org-element-context)))))
+  (should
+   (equal '("a" "b" "c")
+         (org-test-with-temp-text "[cite:@a;@b;@c]"
+           (org-element-map (org-element-parse-buffer) 'citation-reference
+             (lambda (r) (org-element-property :key r))))))
+  (should
+   (eq 'citation
+       (org-test-with-temp-text "[cite:@a;-@b]"
+        (org-element-type (org-element-context)))))
+  (should
+   (equal '("a" "b")
+         (org-test-with-temp-text "[cite:@a;-@b]"
+           (org-element-map (org-element-parse-buffer) 'citation-reference
+             (lambda (r) (org-element-property :key r))))))
+  ;; Multi citations accept `:prefix' and `:suffix' properties.
+  (should
+   (equal '("common-prefix")
+         (org-test-with-temp-text "[cite:common-prefix;@a]"
+           (org-element-property :prefix (org-element-context)))))
+  (should
+   (equal '("common-suffix")
+         (org-test-with-temp-text "[cite:@a;common-suffix]"
+           (org-element-property :suffix (org-element-context)))))
+  ;; White spaces right after "cite" tags are ignored. So are white
+  ;; spaces at the end of the citation.
+  (should
+   (equal '("common-prefix ")
+         (org-test-with-temp-text "[cite: common-prefix ;@a]"
+           (org-element-property :prefix (org-element-context)))))
+  (should
+   (equal '(" common-suffix")
+         (org-test-with-temp-text "[cite: @a; common-suffix ]"
+           (org-element-property :suffix (org-element-context)))))
+  ;; Allow citations in a table cell.
+  (should
+   (eq 'citation
+       (org-test-with-temp-text "| <point>[cite:@key] |"
+        (org-element-type (org-element-context))))))
+
+
+;;;; Citation Reference
+
+(ert-deftest test-org-element/citation-reference-parser ()
+  "Test `citation' reference parser."
+  ;; Parse bare keys.
+  (should
+   (eq 'citation-reference
+       (org-test-with-temp-text "[cite:<point>@key]"
+        (org-element-type (org-element-context)))))
+  ;; Bare keys can contain any word character, and some punctuation,
+  ;; but not semicolon, square brackets, and space.
+  (should
+   (equal "_key"
+         (org-test-with-temp-text "[cite:@_k<point>ey]"
+           (org-element-property :key (org-element-context)))))
+  (should
+   (eq 'citation-reference
+       (org-test-with-temp-text "[cite:<point>@a]"
+        (org-element-type (org-element-context)))))
+  (should
+   (eq 'citation-reference
+       (org-test-with-temp-text "[cite:<point>@รถ]"
+        (org-element-type (org-element-context)))))
+  (should
+   (eq 'citation-reference
+       (org-test-with-temp-text "[cite:<point>@_]"
+        (org-element-type (org-element-context)))))
+  (should
+   (equal "a:.#$%&-+?<>~/1"
+         (org-test-with-temp-text "[cite:<point>@a:.#$%&-+?<>~/1]"
+           (org-element-property :key (org-element-context)))))
+  (should-not
+   (eq 'citation-reference
+       (org-test-with-temp-text "[cite:<point>@;]"
+        (org-element-type (org-element-context)))))
+  (should-not
+   (equal "key"
+         (org-test-with-temp-text "[cite:<point>@[]]"
+           (org-element-property :key (org-element-context)))))
+  ;; References in citations accept optional `:prefix' and `:suffix'
+  ;; properties.
+  (should
+   (equal '("pre ")
+         (org-test-with-temp-text "[cite:pre <point>@key]"
+           (org-element-property :prefix (org-element-context)))))
+  (should
+   (equal '(" post")
+         (org-test-with-temp-text "[cite:<point>@key post]"
+           (org-element-property :suffix (org-element-context)))))
+  ;; White spaces between "cite" tag and prefix are ignored.
+  (should
+   (equal '("pre ")
+         (org-test-with-temp-text "[cite: pre <point>@key]"
+           (org-element-property :prefix (org-element-context)))))
+  ;; Semicolons do not belong to prefix or suffix.
+  (should
+   (equal '("pre ")
+         (org-test-with-temp-text "[cite:@key1;pre <point>@key2]"
+           (org-element-property :prefix (org-element-context)))))
+  (should
+   (equal '(" post")
+         (org-test-with-temp-text "[cite:@key1 <point>post;@key2]"
+           (org-element-property :suffix (org-element-context)))))
+  (should
+   (equal '("pre ")
+         (org-test-with-temp-text "[cite:global prefix;pre<point> @key1]"
+           (org-element-property :prefix (org-element-context)))))
+  (should
+   (equal '(" post")
+         (org-test-with-temp-text "[cite:@key1 <point>post; global suffix]"
+           (org-element-property :suffix (org-element-context))))))
+
 ;;;; Clock
 
 (ert-deftest test-org-element/clock-parser ()
@@ -3124,6 +3263,36 @@ DEADLINE: <2012-03-29 thu.> SCHEDULED: <2012-03-29 thu.> 
CLOSED: [2012-03-29 thu
   "Test bold interpreter."
   (should (equal (org-test-parse-and-interpret "*text*") "*text*\n")))
 
+(ert-deftest test-org-element/citation-interpreter ()
+  "Test citation interpreter."
+  (should
+   (equal "[cite:@key]\n"
+         (org-test-parse-and-interpret "[cite:@key]")))
+  (should
+   (equal "[cite:-@key]\n"
+         (org-test-parse-and-interpret "[cite:-@key]")))
+  (should
+   (equal "[cite/style:@key]\n"
+         (org-test-parse-and-interpret "[cite/style:@key]")))
+  (should
+   (equal "[cite:pre @key]\n"
+         (org-test-parse-and-interpret "[cite:pre @key]")))
+  (should
+   (equal "[cite:@key post]\n"
+         (org-test-parse-and-interpret "[cite:@key post]")))
+  (should
+   (equal "[cite:@a ;b]\n"
+         (org-test-parse-and-interpret "[cite: @a ;b]")))
+  (should
+   (equal "[cite:@a;@b;@c]\n"
+         (org-test-parse-and-interpret "[cite:@a;@b;@c]")))
+  (should
+   (equal "[cite:common-pre ; @a]\n"
+         (org-test-parse-and-interpret "[cite:common-pre ; @a]")))
+  (should
+   (equal "[cite:@a ; common-post]\n"
+         (org-test-parse-and-interpret "[cite:@a ; common-post]"))))
+
 (ert-deftest test-org-element/code-interpreter ()
   "Test code interpreter."
   (should (equal (org-test-parse-and-interpret "~text~") "~text~\n")))
@@ -3892,6 +4061,21 @@ Text
            :end (org-element-property :parent (org-element-at-point)))
           (+ parent-end 3))))))
 
+(ert-deftest test-org-element/cache-bugs ()
+  "Test basic expectations and common pitfalls for cache."
+  :expected-result :failed
+  ;; Unindented second row of the table should not be re-parented by
+  ;; inserted item.
+  (should
+   (eq 'table
+       (let ((org-element-use-cache t))
+        (org-test-with-temp-text
+         "#+begin_center\nP0\n\n<point>\n\n  P1\n  | a | b |\n| c | d 
|\n#+end_center"
+         (save-excursion (search-forward "| c |") (org-element-at-point))
+         (insert "- item")
+         (search-forward "| c |")
+         (beginning-of-line)
+         (org-element-type (org-element-at-point)))))))
 
 (provide 'test-org-element)
 
diff --git a/testing/lisp/test-org-feed.el b/testing/lisp/test-org-feed.el
index 49c6feb..83f7ccb 100644
--- a/testing/lisp/test-org-feed.el
+++ b/testing/lisp/test-org-feed.el
@@ -15,7 +15,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 
diff --git a/testing/lisp/test-org-footnote.el 
b/testing/lisp/test-org-footnote.el
index 5525626..6d8ba2f 100644
--- a/testing/lisp/test-org-footnote.el
+++ b/testing/lisp/test-org-footnote.el
@@ -15,7 +15,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
 
@@ -90,7 +90,7 @@
     (org-test-with-temp-text " *bold*<point>"
       (let ((org-footnote-auto-label t)) (org-footnote-new))
       (buffer-string))))
-  ;; Arrow new footnotes in empty cells.
+  ;; Arrow new footnotes in table cells.
   (should
    (string-match-p
     " \\[fn:1\\]"
@@ -109,6 +109,12 @@
     (org-test-with-temp-text "| <point>|"
       (let ((org-footnote-auto-label t)) (org-footnote-new))
       (buffer-string))))
+  (should
+   (string-match-p
+    " \\[fn:1\\]"
+    (org-test-with-temp-text "| contents   <point>|"
+      (let ((org-footnote-auto-label t)) (org-footnote-new))
+      (buffer-string))))
   ;; When creating a new footnote, move to its definition.
   (should
    (string=
diff --git a/testing/lisp/test-org-info.el b/testing/lisp/test-org-info.el
index fd56620..9492316 100644
--- a/testing/lisp/test-org-info.el
+++ b/testing/lisp/test-org-info.el
@@ -15,7 +15,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
 
diff --git a/testing/lisp/test-org-inlinetask.el 
b/testing/lisp/test-org-inlinetask.el
index 017369c..db46376 100644
--- a/testing/lisp/test-org-inlinetask.el
+++ b/testing/lisp/test-org-inlinetask.el
@@ -14,7 +14,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Comments:
 
diff --git a/testing/lisp/test-org-lint.el b/testing/lisp/test-org-lint.el
index 97fede1..e57993c 100644
--- a/testing/lisp/test-org-lint.el
+++ b/testing/lisp/test-org-lint.el
@@ -15,7 +15,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
 
@@ -339,6 +339,12 @@ This is not a node property
   (should-not
    (org-test-with-temp-text
        "#+macro: valid $1 $2\n{{{valid(1, 2)}}}"
+     (org-lint '(invalid-macro-argument-and-template))))
+  (should
+   (org-test-with-temp-text "{{{keyword}}}"
+     (org-lint '(invalid-macro-argument-and-template))))
+  (should
+   (org-test-with-temp-text "{{{keyword(one, too many)}}}"
      (org-lint '(invalid-macro-argument-and-template)))))
 
 (ert-deftest test-org-lint/undefined-footnote-reference ()
diff --git a/testing/lisp/test-org-list.el b/testing/lisp/test-org-list.el
index 078e596..3689a17 100644
--- a/testing/lisp/test-org-list.el
+++ b/testing/lisp/test-org-list.el
@@ -15,7 +15,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
 
diff --git a/testing/lisp/test-org-macro.el b/testing/lisp/test-org-macro.el
index 5ff37f1..1b4b791 100644
--- a/testing/lisp/test-org-macro.el
+++ b/testing/lisp/test-org-macro.el
@@ -15,7 +15,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
 
diff --git a/testing/lisp/test-org-macs.el b/testing/lisp/test-org-macs.el
index efa992a..214766c 100644
--- a/testing/lisp/test-org-macs.el
+++ b/testing/lisp/test-org-macs.el
@@ -15,7 +15,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
 
diff --git a/testing/lisp/test-org-pcomplete.el 
b/testing/lisp/test-org-pcomplete.el
index 2de4f49..34969f2 100644
--- a/testing/lisp/test-org-pcomplete.el
+++ b/testing/lisp/test-org-pcomplete.el
@@ -16,7 +16,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Comments:
 
diff --git a/testing/lisp/test-org-protocol.el 
b/testing/lisp/test-org-protocol.el
index 87df67a..95fc7f8 100644
--- a/testing/lisp/test-org-protocol.el
+++ b/testing/lisp/test-org-protocol.el
@@ -16,7 +16,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
 
@@ -76,7 +76,25 @@
   ;; New link style
   (let ((uri 
"/some/directory/org-protocol://store-link?url=URL3&title=TITLE3"))
     (should (null (org-protocol-check-filename-for-protocol uri (list uri) 
nil)))
-    (should (equal (car org-stored-links) '("URL3" "TITLE3")))))
+    (should (equal (car org-stored-links) '("URL3" "TITLE3"))))
+  ;; Do not decode "+" in old-style link
+  (let ((uri "/org-protocol:/store-link:/one+one/plus+preserved"))
+    (should (null (org-protocol-check-filename-for-protocol uri (list uri) 
nil)))
+    (should (equal (car org-stored-links) '("one+one" "plus+preserved"))))
+  ;; Decode "+" to space in new-style link
+  (let ((uri "/org-protocol:/store-link/?url=one+two&title=plus+is+space"))
+    (should (null (org-protocol-check-filename-for-protocol uri (list uri) 
nil)))
+    (should (equal (car org-stored-links) '("one two" "plus is space")))))
+
+(ert-deftest test-org-protocol/org-protocol-store-link-file ()
+  "store-link: `org-protocol-sanitize-uri' could distort URL."
+  :expected-result :failed
+  (let ((uri 
"/org-protocol:/store-link:/file%3A%2F%2F%2Fetc%2Fmailcap/Triple%20Slash"))
+    (should (null (org-protocol-check-filename-for-protocol uri (list uri) 
nil)))
+    (should (equal (car org-stored-links) '("file:///etc/mailcap" "Triple 
Slash"))))
+  (let ((uri 
"/org-protocol:/store-link?url=file%3A%2F%2F%2Fetc%2Fmailcap&title=Triple%20Slash"))
+    (should (null (org-protocol-check-filename-for-protocol uri (list uri) 
nil)))
+    (should (equal (car org-stored-links) '("file:///etc/mailcap" "Triple 
Slash")))))
 
 (ert-deftest test-org-protocol/org-protocol-capture ()
   "Test `org-protocol-capture' specifications."
@@ -123,6 +141,12 @@
            ;; - query parameters, not sure how to include them in template
            
("/some/directory/org-protocol:/capture?template=x&url=URL&title=TITLE&body=BODY&from=example"
             . "** SOMEDAY\n\nBODY\n\n[[URL][TITLE]]\n")
+            ;; - "+" is not decoded to space in old-style URIs
+            
("/org-protocol:/capture:/t/https%3A%2F%2Forgmode.org%2Fsome+thing/org+mode/Body+plus"
+             . "** 
TODO\n\nBody+plus\n\n[[https://orgmode.org/some+thing][org+mode]]\n";)
+            ;; - decode "+" to space
+            
("/org-protocol:/capture?template=t&url=URL&title=Mailing+list&body=Body+no+plus"
+             . "** TODO\n\nBody no plus\n\n[[URL][Mailing list]]\n")
            )))
     ;; Old link style
     (mapc
@@ -134,6 +158,20 @@
      test-urls)
     (delete-file temp-file-name)))
 
+(ert-deftest test-org-protocol/org-protocol-capture-file ()
+  "capture: `org-protocol-sanitize-uri' could distort URL."
+  :expected-result :failed
+  (let* ((org-protocol-default-template-key "t")
+        (temp-file-name (make-temp-file "org-protocol-test"))
+        (org-capture-templates
+         `(("t" "Test" plain (file ,temp-file-name) "%a\n%i\n" :kill-buffer 
t))))
+    (let ((uri 
"/org-protocol:/capture:/t/file%3A%2F%2F%2Fetc%2Fmailcap/Triple%20Slash/Body"))
+      (should (null (org-protocol-check-filename-for-protocol uri (list uri) 
nil)))
+      (should (string= (buffer-string) "[[file:///etc/mailcap][Triple 
Slash]]\nBody")))
+    (let ((uri 
"/org-protocol:/capture?template=t&url=file%3A%2F%2F%2Fetc%2Fmailcap&title=Triple%20Slash&body=Body"))
+      (should (null (org-protocol-check-filename-for-protocol uri (list uri) 
nil)))
+      (should (string= (buffer-string) "[[file:///etc/mailcap][Triple 
Slash]]\nBody")))))
+
 (ert-deftest test-org-protocol/org-protocol-open-source ()
   "Test org-protocol://open-source links."
   (let* ((temp-file-name1 (make-temp-file "org-protocol-test1"))
diff --git a/testing/lisp/test-org-src.el b/testing/lisp/test-org-src.el
index 2b1527a..16283b5 100644
--- a/testing/lisp/test-org-src.el
+++ b/testing/lisp/test-org-src.el
@@ -17,11 +17,11 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
 
-(require 'org-test)
+(require 'org-test "../testing/org-test")
 
 
 
diff --git a/testing/lisp/test-org-table.el b/testing/lisp/test-org-table.el
index fb9d83f..310844c 100644
--- a/testing/lisp/test-org-table.el
+++ b/testing/lisp/test-org-table.el
@@ -16,7 +16,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;;; Comments:
 
@@ -380,6 +380,18 @@ reference (with row).  Mode string N."
 "
      1 calc)))
 
+(ert-deftest test-org-table/mode-string-u ()
+  "Basic: verify that mode string u results in units
+simplification mode applied to Calc formulas."
+  (org-test-table-target-expect
+   "
+| 1.5 A/B | 2.0 B | |
+"
+   "
+| 1.5 A/B | 2.0 B | 3. A |
+"
+   1 "#+TBLFM: $3=$1*$2;u"))
+
 (ert-deftest test-org-table/lisp-return-value ()
   "Basic: Return value of Lisp formulas."
   (org-test-table-target-expect
diff --git a/testing/lisp/test-org-tempo.el b/testing/lisp/test-org-tempo.el
index cee5da8..e4c2b91 100644
--- a/testing/lisp/test-org-tempo.el
+++ b/testing/lisp/test-org-tempo.el
@@ -17,7 +17,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
 
diff --git a/testing/lisp/test-org-timer.el b/testing/lisp/test-org-timer.el
index 27156df..5d938f2 100644
--- a/testing/lisp/test-org-timer.el
+++ b/testing/lisp/test-org-timer.el
@@ -17,7 +17,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
 
diff --git a/testing/lisp/test-org.el b/testing/lisp/test-org.el
index 2383131..18d41a0 100644
--- a/testing/lisp/test-org.el
+++ b/testing/lisp/test-org.el
@@ -16,7 +16,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;; Template test file for Org tests
 
@@ -1604,6 +1604,21 @@
   ;; point.
   (should
    (equal
+    "* "
+    (org-test-with-temp-text ""
+      (let ((org-insert-heading-respect-content nil))
+       (org-insert-heading '(4)))
+      (buffer-string))))
+  (should
+   (equal
+    "entry
+* "
+    (org-test-with-temp-text "entry"
+      (let ((org-insert-heading-respect-content nil))
+       (org-insert-heading '(4)))
+      (buffer-string))))
+  (should
+   (equal
     "* H1\n** H2\n* "
     (org-test-with-temp-text "* H1\n** H2"
       (let ((org-insert-heading-respect-content nil))
@@ -1816,7 +1831,31 @@
                 (lambda (&rest args) "+1d")))
        (org-clone-subtree-with-time-shift 1))
       (buffer-substring-no-properties (line-beginning-position 2)
-                                     (line-end-position 2))))))
+                                     (line-end-position 2)))))
+  ;; Hour shift.
+  (should
+   (equal "\
+* H1\n<2015-06-21 20:00>
+* H1\n<2015-06-21 23:00>
+* H1\n<2015-06-22 02:00>
+"
+          (org-test-with-temp-text "* H1\n<2015-06-21 Sun 20:00>"
+            (org-clone-subtree-with-time-shift 2 "+3h")
+            (replace-regexp-in-string
+             "\\( [.A-Za-z]+\\)\\( [0-9][0-9]:[0-9][0-9]\\)?>" ""
+             (buffer-substring-no-properties (point-min) (point-max))
+             nil nil 1))))
+  (should
+   (equal "\
+* H1\n<2015-06-21 20:00>
+* H1\n<2015-06-21 18:00>
+"
+          (org-test-with-temp-text "* H1\n<2015-06-21 Sun 20:00>"
+            (org-clone-subtree-with-time-shift 1 "-2h")
+            (replace-regexp-in-string
+             "\\( [.A-Za-z]+\\)\\( [0-9][0-9]:[0-9][0-9]\\)?>" ""
+             (buffer-substring-no-properties (point-min) (point-max))
+             nil nil 1)))))
 
 
 ;;; Fixed-Width Areas
@@ -6945,8 +6984,8 @@ Paragraph<point>"
   (should
    (equal "* H1 :foo:"
          (org-test-with-temp-text "* H1"
-           (cl-letf (((symbol-function 'completing-read)
-                      (lambda (&rest args) ":foo:")))
+           (cl-letf (((symbol-function 'completing-read-multiple)
+                      (lambda (&rest args) '("foo"))))
              (let ((org-use-fast-tag-selection nil)
                    (org-tags-column 1))
                (org-set-tags-command)))
@@ -6955,8 +6994,8 @@ Paragraph<point>"
   (should
    (equal "* H1 :foo:\nContents"
          (org-test-with-temp-text "* H1\n<point>Contents"
-           (cl-letf (((symbol-function 'completing-read)
-                      (lambda (&rest args) ":foo:")))
+           (cl-letf (((symbol-function 'completing-read-multiple)
+                      (lambda (&rest args) '("foo"))))
              (let ((org-use-fast-tag-selection nil)
                    (org-tags-column 1))
                (org-set-tags-command)))
@@ -6964,30 +7003,20 @@ Paragraph<point>"
   (should-not
    (equal "* H1 :foo:\nContents2"
          (org-test-with-temp-text "* H1\n<point>Contents2"
-           (cl-letf (((symbol-function 'completing-read)
-                      (lambda (&rest args) ":foo:")))
+           (cl-letf (((symbol-function 'completing-read-multiple)
+                      (lambda (&rest args) '("foo"))))
              (let ((org-use-fast-tag-selection nil)
                    (org-tags-column 1))
                (org-set-tags-command)))
            (org-at-heading-p))))
-  ;; Strip all forbidden characters from user-entered tags.
-  (should
-   (equal "* H1 :foo:"
-         (org-test-with-temp-text "* H1"
-           (cl-letf (((symbol-function 'completing-read)
-                      (lambda (&rest args) ": foo *:")))
-             (let ((org-use-fast-tag-selection nil)
-                   (org-tags-column 1))
-               (org-set-tags-command)))
-           (buffer-string))))
   ;; When a region is active and
   ;; `org-loop-over-headlines-in-active-region' is non-nil, insert the
   ;; same value in all headlines in region.
   (should
    (equal "* H1 :foo:\nContents\n* H2 :foo:"
          (org-test-with-temp-text "* H1\nContents\n* H2"
-           (cl-letf (((symbol-function 'completing-read)
-                      (lambda (&rest args) ":foo:")))
+           (cl-letf (((symbol-function 'completing-read-multiple)
+                      (lambda (&rest args) '("foo"))))
              (let ((org-use-fast-tag-selection nil)
                    (org-loop-over-headlines-in-active-region t)
                    (org-tags-column 1))
@@ -6999,8 +7028,8 @@ Paragraph<point>"
   (should
    (equal "* H1\nContents\n* H2 :foo:"
          (org-test-with-temp-text "* H1\nContents\n* H2"
-           (cl-letf (((symbol-function 'completing-read)
-                      (lambda (&rest args) ":foo:")))
+           (cl-letf (((symbol-function 'completing-read-multiple)
+                      (lambda (&rest args) '("foo"))))
              (let ((org-use-fast-tag-selection nil)
                    (org-loop-over-headlines-in-active-region nil)
                    (org-tags-column 1))
@@ -7019,8 +7048,8 @@ Paragraph<point>"
   (should
    (equal ":foo:"
          (org-test-with-temp-text "* <point>"
-           (cl-letf (((symbol-function 'completing-read)
-                      (lambda (&rest args) ":foo:")))
+           (cl-letf (((symbol-function 'completing-read-multiple)
+                      (lambda (&rest args) '("foo"))))
              (let ((org-use-fast-tag-selection nil)
                    (org-tags-column 1))
                (org-set-tags-command)))
@@ -7029,8 +7058,8 @@ Paragraph<point>"
   (should
    (equal "* H1 :foo:"
          (org-test-with-temp-text "* H1"
-           (cl-letf (((symbol-function 'completing-read)
-                      (lambda (&rest args) ":foo:")))
+           (cl-letf (((symbol-function 'completing-read-multiple)
+                      (lambda (&rest args) '("foo"))))
              (let ((org-use-fast-tag-selection nil)
                    (org-tags-column 1))
                (org-set-tags-command)))
@@ -7039,8 +7068,8 @@ Paragraph<point>"
   (should
    (equal "* H1 :foo:"
          (org-test-with-temp-text "*<point>* H1"
-           (cl-letf (((symbol-function 'completing-read)
-                      (lambda (&rest args) ":foo:")))
+           (cl-letf (((symbol-function 'completing-read-multiple)
+                      (lambda (&rest args) '("foo"))))
              (let ((org-use-fast-tag-selection nil)
                    (org-tags-column 1))
                (org-set-tags-command)))
@@ -7049,8 +7078,8 @@ Paragraph<point>"
   (should
    (equal " b :foo:"
          (org-test-with-temp-text "* a<point> b"
-           (cl-letf (((symbol-function 'completing-read)
-                      (lambda (&rest args) ":foo:")))
+           (cl-letf (((symbol-function 'completing-read-multiple)
+                      (lambda (&rest args) '("foo"))))
              (let ((org-use-fast-tag-selection nil)
                    (org-tags-column 1))
                (org-set-tags-command)))
@@ -7059,9 +7088,9 @@ Paragraph<point>"
   (should
    (equal "b :foo:"
          (org-test-with-temp-text "* a :foo:\n** <point>b :foo:"
-           (cl-letf (((symbol-function 'completing-read)
+           (cl-letf (((symbol-function 'completing-read-multiple)
                       (lambda (prompt coll &optional pred req initial &rest 
args)
-                        initial)))
+                        (list initial))))
              (let ((org-use-fast-tag-selection nil)
                    (org-tags-column 1))
                (org-set-tags-command)))
@@ -7382,7 +7411,154 @@ Paragraph<point>"
 SCHEDULED: <2012-03-29 Thu +2y>
 CLOCK: [2012-03-29 Thu 10:00]--[2012-03-29 Thu 16:40] =>  6:40"
        (org-todo "DONE")
-       (buffer-string))))))
+       (buffer-string)))))
+  ;; Make sure that logbook state change record does not get
+  ;; duplicated when `org-log-repeat' `org-log-done' are non-nil.
+  (should
+   (string-match-p
+    (rx "* TODO Read book
+SCHEDULED: <2021-06-16 Wed +1d>
+:PROPERTIES:
+:LAST_REPEAT:" (1+ nonl) "
+:END:
+- State \"DONE\"       from \"TODO\"" (1+ nonl) buffer-end)
+    (let ((org-log-repeat 'time)
+         (org-todo-keywords '((sequence "TODO" "|" "DONE(d!)")))
+          (org-log-into-drawer nil))
+      (org-test-with-temp-text
+          "* TODO Read book
+SCHEDULED: <2021-06-15 Tue +1d>"
+        (org-todo "DONE")
+        (when (memq 'org-add-log-note post-command-hook)
+          (org-add-log-note))
+        (buffer-string))))))
+
+(ert-deftest test-org/org-log-done ()
+  "Test `org-log-done' specifications."
+  ;; nil value.
+  (should
+   (string=
+    "* DONE task"
+    (let ((org-log-done nil)
+          (org-todo-keywords '((sequence "TODO" "DONE"))))
+      (org-test-with-temp-text
+          "* TODO task"
+        (org-todo "DONE")
+        (when (memq 'org-add-log-note post-command-hook)
+          (org-add-log-note))
+        (buffer-string)))))
+  ;; `time' value.
+  (should
+   (string=
+    (format
+    "* DONE task
+CLOSED: %s"
+    (org-test-with-temp-text ""
+      (org-insert-time-stamp (current-time) t t)
+      (buffer-string)))
+    (let ((org-log-done 'time)
+          (org-log-done-with-time t)
+          (org-todo-keywords '((sequence "TODO" "DONE"))))
+      (org-test-with-temp-text
+          "* TODO task"
+        (org-todo "DONE")
+        (when (memq 'org-add-log-note post-command-hook)
+          (org-add-log-note))
+        (buffer-string)))))
+  (should
+   (string=
+    (format
+    "* DONE task
+CLOSED: %s"
+    (org-test-with-temp-text ""
+      (org-insert-time-stamp (current-time) nil t)
+      (buffer-string)))
+    (let ((org-log-done 'time)
+          (org-log-done-with-time nil)
+          (org-todo-keywords '((sequence "TODO" "DONE"))))
+      (org-test-with-temp-text
+          "* TODO task"
+        (org-todo "DONE")
+        (when (memq 'org-add-log-note post-command-hook)
+          (org-add-log-note))
+        (buffer-string)))))
+  ;; TODO: Test `note' value.
+  ;; Test startup overrides.
+  (should
+   (string=
+    "#+STARTUP: nologdone
+* DONE task"
+    (let ((org-log-done 'time)
+          (org-todo-keywords '((sequence "TODO" "DONE"))))
+      (org-test-with-temp-text
+          "#+STARTUP: nologdone
+<point>* TODO task"
+        (org-set-regexps-and-options)
+        (org-todo "DONE")
+        (when (memq 'org-add-log-note post-command-hook)
+          (org-add-log-note))
+        (buffer-string)))))
+  (should
+   (string=
+    (format
+    "#+STARTUP: logdone
+* DONE task
+CLOSED: %s"
+    (org-test-with-temp-text ""
+      (org-insert-time-stamp (current-time) t t)
+      (buffer-string)))
+    (let ((org-log-done nil)
+          (org-log-done-with-time t)
+          (org-todo-keywords '((sequence "TODO" "DONE"))))
+      (org-test-with-temp-text
+          "#+STARTUP: logdone
+<point>* TODO task"
+        (org-set-regexps-and-options)
+        (org-todo "DONE")
+        (when (memq 'org-add-log-note post-command-hook)
+          (org-add-log-note))
+        (buffer-string)))))
+  ;; Test local property overrides.
+  (should
+   (string=
+    "* DONE task
+:PROPERTIES:
+:LOGGING: nil
+:END:"
+    (let ((org-log-done 'time)
+          (org-todo-keywords '((sequence "TODO" "DONE"))))
+      (org-test-with-temp-text
+          "* TODO task
+:PROPERTIES:
+:LOGGING: nil
+:END:"
+        (org-todo "DONE")
+        (when (memq 'org-add-log-note post-command-hook)
+          (org-add-log-note))
+        (buffer-string)))))
+  (should
+   (string=
+    (format
+    "* DONE task
+CLOSED: %s
+:PROPERTIES:
+:LOGGING: logdone
+:END:"
+    (org-test-with-temp-text ""
+      (org-insert-time-stamp (current-time) t t)
+      (buffer-string)))
+    (let ((org-log-done nil)
+          (org-log-done-with-time t)
+          (org-todo-keywords '((sequence "TODO" "DONE"))))
+      (org-test-with-temp-text
+          "* TODO task
+:PROPERTIES:
+:LOGGING: logdone
+:END:"
+        (org-todo "DONE")
+        (when (memq 'org-add-log-note post-command-hook)
+          (org-add-log-note))
+        (buffer-string))))))
 
 
 ;;; Timestamps API
@@ -7963,6 +8139,10 @@ CLOCK: [2012-03-29 Thu 10:00]--[2012-03-29 Thu 16:40] => 
 6:40"
     (should (equal '(0 7 8 9) (funcall list-visible-lines 'local nil)))
     (should (equal '(0 3 7) (funcall list-visible-lines 'ancestors t)))
     (should (equal '(0 3 7 8) (funcall list-visible-lines 'ancestors nil)))
+    (should (equal '(0 3 7 8 9 10 11)
+                   (funcall list-visible-lines 'ancestors-full t)))
+    (should (equal '(0 3 7 8 9 10 11)
+                   (funcall list-visible-lines 'ancestors-full nil)))
     (should (equal '(0 3 5 7 12) (funcall list-visible-lines 'lineage t)))
     (should (equal '(0 3 5 7 8 9 12) (funcall list-visible-lines 'lineage 
nil)))
     (should (equal '(0 1 3 5 7 12 13) (funcall list-visible-lines 'tree t)))
diff --git a/testing/lisp/test-ox-publish.el b/testing/lisp/test-ox-publish.el
index ad55093..18e6f5e 100644
--- a/testing/lisp/test-ox-publish.el
+++ b/testing/lisp/test-ox-publish.el
@@ -15,19 +15,23 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
 
 
 ;;; Helper functions
 
-(defun org-test-publish (properties handler)
+(defun org-test-publish (properties handler &optional remove-prop)
   "Publish a project defined by PROPERTIES.
 Call HANDLER with the publishing directory as its sole argument.
 Unless set otherwise in PROPERTIES, `:base-directory' is set to
 \"examples/pub/\" sub-directory from test directory and
-`:publishing-function' is set to `org-publish-attachment'."
+`:publishing-function' is set to `org-publish-attachment'.
+Because `org-publish-property' uses `plist-member' to check the
+existence of a property, a property with a value nil is different
+from a non-existing property.  Properties in REMOVE-PROP will be
+removed from the final plist."
   (declare (indent 1))
   (let* ((org-publish-use-timestamps-flag nil)
         (org-publish-cache nil)
@@ -35,13 +39,15 @@ Unless set otherwise in PROPERTIES, `:base-directory' is 
set to
         (pub-dir (make-temp-file "org-test" t))
         (org-publish-timestamp-directory
          (expand-file-name ".org-timestamps/" pub-dir))
+         (props (org-plist-delete-all
+                 (org-combine-plists
+                  `(:base-directory ,base-dir
+                    :publishing-function org-publish-attachment)
+                  properties
+                  `(:publishing-directory ,pub-dir))
+                 remove-prop))
         (project
-         `("test" ,@(org-combine-plists
-                     `(:base-directory
-                       ,base-dir
-                       :publishing-function org-publish-attachment)
-                     properties
-                     `(:publishing-directory ,pub-dir)))))
+         `("test" ,@props)))
     (unwind-protect
        (progn
          (org-publish-projects (list project))
@@ -92,7 +98,19 @@ Unless set otherwise in PROPERTIES, `:base-directory' is set 
to
            (lambda (dir)
              (remove ".org-timestamps"
                      (cl-remove-if #'file-directory-p
-                                   (directory-files dir))))))))
+                                   (directory-files dir)))))))
+
+  ;; Check the default trasformation function,
+  ;; org-html-publish-to-html. Because org-test-publish uses
+  ;; org-publish-attachment by default, we must not just override with
+  ;; nil but tell it to remove the :publishing-function from the list.
+  (should
+   (let ((func (lambda (dir)
+                 (with-temp-buffer
+                   (insert-file-contents (expand-file-name "a.html" dir))
+                   (buffer-string)))))
+    (equal (org-test-publish nil func '(:publishing-function))
+           (org-test-publish '(:publishing-function org-html-publish-to-html) 
func)))))
 
 
 ;;; Site-map
diff --git a/testing/lisp/test-ox.el b/testing/lisp/test-ox.el
index 8b24ddd..5455804 100644
--- a/testing/lisp/test-ox.el
+++ b/testing/lisp/test-ox.el
@@ -17,7 +17,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
 
@@ -3812,6 +3812,17 @@ Another text. (ref:text)
            (org-export-data-with-backend paragraph backend nil)))))
 
 
+;;; Raw objects
+
+(ert-deftest test-org-export/raw-strings ()
+  "Test exporting raw objects."
+  (should
+   (equal "foo"
+          (let ((backend (org-export-create-backend))
+                (object (org-export-raw-string "foo")))
+            (org-export-data-with-backend object backend nil)))))
+
+
 ;;; Src-block and example-block
 
 (ert-deftest test-org-export/unravel-code ()
diff --git a/testing/lisp/test-property-inheritance.el 
b/testing/lisp/test-property-inheritance.el
index 1d0dcfb..c00ad6c 100644
--- a/testing/lisp/test-property-inheritance.el
+++ b/testing/lisp/test-property-inheritance.el
@@ -16,7 +16,7 @@
 ;; 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/>.
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Code:
 (defmacro test-org-in-property-buffer (&rest body)
diff --git a/testing/org-batch-test-init.el b/testing/org-batch-test-init.el
index 8638756..87216cf 100644
--- a/testing/org-batch-test-init.el
+++ b/testing/org-batch-test-init.el
@@ -5,9 +5,9 @@
 ;; clean load-path
 (setq load-path
       (delq nil (mapcar
-                (function (lambda (p)
-                            (unless (string-match "lisp\\(/packages\\)?/org$" 
p)
-                              p)))
+                (lambda (p)
+                  (unless (string-match "lisp\\(/packages\\)?/org$" p)
+                    p))
                 load-path)))
 ;; remove property list to defeat cus-load and remove autoloads
 (mapatoms (function  (lambda (s)
diff --git a/testing/org-test.el b/testing/org-test.el
index 27dd0dd..30adb97 100644
--- a/testing/org-test.el
+++ b/testing/org-test.el
@@ -7,7 +7,7 @@
 ;;     David Maus, Brunswick, Germany, dmaus ictsoc de
 
 ;; Released under the GNU General Public License version 3
-;; see: http://www.gnu.org/licenses/gpl-3.0.html
+;; see: https://www.gnu.org/licenses/gpl-3.0.html
 
 ;; Definition of `special-mode' copied from Emacs23's simple.el to be
 ;; provide a testing environment for Emacs22.
@@ -286,7 +286,15 @@ setting `pp-escape-newlines' to nil manually."
 
 
 ;;; Navigation Functions
-(when (featurep 'jump)
+
+(defmacro org--compile-when (test &rest body)
+  (declare (debug t) (indent 1))
+  (let ((exp `(progn ,@body)))
+    (if (eval test t)
+        exp
+      `(when ,test (eval exp t)))))
+
+(org--compile-when (featurep 'jump)
   (defjump org-test-jump
     (("lisp/\\1.el" . "testing/lisp/test-\\1.el")
      ("lisp/\\1.el" . "testing/lisp/\\1.el/test.*.el")
@@ -305,7 +313,7 @@ setting `pp-escape-newlines' to nil manually."
         " " user-full-name "\n"
         ";; Authors: " user-full-name "\n\n"
         ";; Released under the GNU General Public License version 3\n"
-        ";; see: http://www.gnu.org/licenses/gpl-3.0.html\n\n";
+        ";; see: https://www.gnu.org/licenses/gpl-3.0.html\n\n";
         ";;;; Comments:\n\n"
         ";; Template test file for Org tests\n\n"
         "\n"
@@ -323,7 +331,8 @@ setting `pp-escape-newlines' to nil manually."
         "  (should-not nil)\n"
         "  (should-error (error \"errr...\")))\n\n\n"
         "(provide '" name ")\n\n"
-        ";;; " file-name " ends here\n") full-path))
+        ";;; " file-name " ends here\n")
+       full-path))
     (lambda () ((lambda (res) (if (listp res) (car res) res)) 
(which-function)))))
 
 (define-key emacs-lisp-mode-map "\M-\C-j" 'org-test-jump)



reply via email to

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