]> code.delx.au - gnu-emacs/blobdiff - lisp/org/org-odt.el
lisp/org/ChangeLog: remove references to files that are not in the directory.
[gnu-emacs] / lisp / org / org-odt.el
index 886efa014f3455828ed079bc9b112d51654ab3a0..234272a378df2624de0bc0da60365e9857457367 100644 (file)
@@ -1,4 +1,4 @@
-;;; org-odt.el --- OpenDocumentText export for Org-mode
+;;; org-odt.el --- OpenDocument Text exporter for Org-mode
 
 ;; Copyright (C) 2010-2012 Free Software Foundation, Inc.
 
 (defgroup org-export-odt nil
   "Options specific for ODT export of Org-mode files."
   :tag "Org Export ODT"
-  :group 'org-export)
+  :group 'org-export
+  :version "24.1")
+
+(defvar org-lparse-dyn-first-heading-pos) ; let bound during org-do-lparse
+(defun org-odt-insert-toc ()
+  (goto-char (point-min))
+  (cond
+   ((re-search-forward
+     "\\(<text:p [^>]*>\\)?\\s-*\\[TABLE-OF-CONTENTS\\]\\s-*\\(</text:p>\\)?"
+     nil t)
+    (replace-match ""))
+   (t
+    (goto-char org-lparse-dyn-first-heading-pos)))
+  (insert (org-odt-format-toc)))
 
 (defun org-odt-end-export ()
+  (org-odt-insert-toc)
   (org-odt-fixup-label-references)
 
   ;; remove empty paragraphs
@@ -139,6 +153,7 @@ with GNU ELPA tar or standard Emacs distribution."
          (const :tag "Not set" nil)
          (directory :tag "Schema directory"))
   :group 'org-export-odt
+  :version "24.1"
   :set
   (lambda (var value)
     "Set `org-export-odt-schema-dir'.
@@ -258,7 +273,8 @@ The exporter embeds the exported content just before
 If unspecified, the file named \"OrgOdtContentTemplate.xml\"
 under `org-odt-styles-dir' is used."
   :type 'file
-  :group 'org-export-odt)
+  :group 'org-export-odt
+  :version "24.1")
 
 (defcustom org-export-odt-styles-file nil
   "Default styles file for use with ODT export.
@@ -284,7 +300,7 @@ FILE-MEMBERS.
 Use options 1, 2 or 3 only if styles.xml alone suffices for
 achieving the desired formatting.  Use option 4, if the styles.xml
 references additional files like header and footer images for
-achieving the desired formattting.
+achieving the desired formatting.
 
 Use \"#+ODT_STYLES_FILE: ...\" directive to set this variable on
 a per-file basis.  For example,
@@ -292,6 +308,7 @@ a per-file basis.  For example,
 #+ODT_STYLES_FILE: \"/path/to/styles.xml\" or
 #+ODT_STYLES_FILE: (\"/path/to/file.ott\" (\"styles.xml\" \"image/hdr.png\"))."
   :group 'org-export-odt
+  :version "24.1"
   :type
   '(choice
     (const :tag "Factory settings" nil)
@@ -313,20 +330,21 @@ a per-file basis.  For example,
 (defvar org-export-odt-embed-images t
   "Should the images be copied in to the odt file or just linked?")
 
-(defvar org-export-odt-inline-images 'maybe) ; counterpart of
-                                            ; `org-export-html-inline-images'
-
+(defvar org-export-odt-inline-images 'maybe)
 (defcustom org-export-odt-inline-image-extensions
   '("png" "jpeg" "jpg" "gif")
   "Extensions of image files that can be inlined into HTML."
   :type '(repeat (string :tag "Extension"))
-  :group 'org-export-odt)
+  :group 'org-export-odt
+  :version "24.1")
 
 (defcustom org-export-odt-pixels-per-inch display-pixels-per-inch
-  ;; FIXME add docstring
-  ""
+  "Scaling factor for converting images pixels to inches.
+Use this for sizing of embedded images.  See Info node `(org)
+Images in ODT export' for more information."
   :type 'float
-  :group 'org-export-odt)
+  :group 'org-export-odt
+  :version "24.1")
 
 (defcustom org-export-odt-create-custom-styles-for-srcblocks t
   "Whether custom styles for colorized source blocks be automatically created.
@@ -344,6 +362,7 @@ styles.xml already contains needed styles for colorizing to work.
 This variable is effective only if
 `org-export-odt-fontify-srcblocks' is turned on."
   :group 'org-export-odt
+  :version "24.1"
   :type 'boolean)
 
 (defvar org-export-odt-default-org-styles-alist
@@ -396,6 +415,7 @@ resulting document to this format.  During customization of this
 variable, the list of valid values are populated based on
 `org-export-odt-convert-capabilities'."
   :group 'org-export-odt
+  :version "24.1"
   :type '(choice :convert-widget
                 (lambda (w)
                   (apply 'widget-convert (widget-type w)
@@ -425,40 +445,6 @@ emacs   --batch
         --visit=MyFile --funcall org-export-as-odt-batch"
   (org-lparse-batch "odt"))
 
-;;;###autoload
-(defun org-export-as-odt-to-buffer (arg)
-  "Call `org-lparse-odt` with output to a temporary buffer.
-No file is created.  The prefix ARG is passed through to `org-lparse-to-buffer'."
-  (interactive "P")
-  (org-lparse-to-buffer "odt" arg))
-
-;;;###autoload
-(defun org-replace-region-by-odt (beg end)
-  "Assume the current region has org-mode syntax, and convert it to ODT.
-This can be used in any buffer.  For example, you could write an
-itemized list in org-mode syntax in an ODT buffer and then use this
-command to convert it."
-  (interactive "r")
-  (org-replace-region-by "odt" beg end))
-
-;;;###autoload
-(defun org-export-region-as-odt (beg end &optional body-only buffer)
-  "Convert region from BEG to END in org-mode buffer to ODT.
-If prefix arg BODY-ONLY is set, omit file header, footer, and table of
-contents, and only produce the region of converted text, useful for
-cut-and-paste operations.
-If BUFFER is a buffer or a string, use/create that buffer as a target
-of the converted ODT.  If BUFFER is the symbol `string', return the
-produced ODT as a string and leave not buffer behind.  For example,
-a Lisp program could call this function in the following way:
-
-  (setq odt (org-export-region-as-odt beg end t 'string))
-
-When called interactively, the output buffer is selected, and shown
-in a window.  A non-interactive call will only return the buffer."
-  (interactive "r\nP")
-  (org-lparse-region "odt" beg end body-only buffer))
-
 ;;; org-export-as-odt
 ;;;###autoload
 (defun org-export-as-odt (arg &optional hidden ext-plist
@@ -609,13 +595,12 @@ PUB-DIR is set, use this as the publishing directory."
          '("<text:date style:data-style-name=\"%s\" text:date-value=\"%s\">"
            . "</text:date>") date "N75" iso-date))
        ;; separator
-       "<text:p text:style-name=\"OrgSubtitle\"/>"))
-     ;; toc
-     (org-odt-format-toc))))
+       "<text:p text:style-name=\"OrgSubtitle\"/>")))))
 
 (defun org-odt-begin-document-body (opt-plist)
   (org-odt-begin-office-body)
-  (insert (org-odt-format-preamble opt-plist)))
+  (insert (org-odt-format-preamble opt-plist))
+  (setq org-lparse-dyn-first-heading-pos (point)))
 
 (defvar org-lparse-body-only)          ; let bound during org-do-lparse
 (defvar org-lparse-to-buffer)          ; let bound during org-do-lparse
@@ -646,6 +631,15 @@ PUB-DIR is set, use this as the publishing directory."
 (defun org-odt-end-outline-text ()
   (ignore))
 
+(defun org-odt-begin-section (style &optional name)
+  (let ((default-name (car (org-odt-add-automatic-style "Section"))))
+    (org-lparse-insert-tag
+     "<text:section text:style-name=\"%s\" text:name=\"%s\">"
+     style (or name default-name))))
+
+(defun org-odt-end-section ()
+  (org-lparse-insert-tag "</text:section>"))
+
 (defun org-odt-begin-paragraph (&optional style)
   (org-lparse-insert-tag
    "<text:p%s>" (org-odt-get-extra-attrs-for-paragraph-style style)))
@@ -729,13 +723,17 @@ PUB-DIR is set, use this as the publishing directory."
      (list))
     (t (error "Unknown environment %s" style))))
 
-(defvar org-lparse-list-level) ; dynamically bound in org-do-lparse
+(defvar org-lparse-list-stack) ; dynamically bound in org-do-lparse
+(defvar org-odt-list-stack-stashed)
 (defun org-odt-begin-list (ltype)
   (setq ltype (or (org-lparse-html-list-type-to-canonical-list-type ltype)
                  ltype))
   (let* ((style-name (org-odt-get-style-name-for-entity 'list ltype))
-        (extra (concat (when (= org-lparse-list-level 1)
-                         " text:continue-numbering=\"false\"")
+        (extra (concat (if (or org-lparse-list-table-p
+                               (and (= 1 (length org-lparse-list-stack))
+                                    (null org-odt-list-stack-stashed)))
+                           " text:continue-numbering=\"false\""
+                         " text:continue-numbering=\"true\"")
                        (when style-name
                          (format " text:style-name=\"%s\""  style-name)))))
     (case ltype
@@ -758,11 +756,15 @@ PUB-DIR is set, use this as the publishing directory."
     (ordered
      (assert (not headline) t)
      (let* ((counter arg) (extra ""))
-       (org-lparse-insert-tag "<text:list-item>")
+       (org-lparse-insert-tag (if (= (length org-lparse-list-stack)
+                                    (length org-odt-list-stack-stashed))
+                                 "<text:list-header>" "<text:list-item>"))
        (org-lparse-begin-paragraph)))
     (unordered
      (let* ((id arg) (extra ""))
-       (org-lparse-insert-tag "<text:list-item>")
+       (org-lparse-insert-tag (if (= (length org-lparse-list-stack)
+                                    (length org-odt-list-stack-stashed))
+                                 "<text:list-header>" "<text:list-item>"))
        (org-lparse-begin-paragraph)
        (insert (if headline (org-odt-format-target headline id)
                 (org-odt-format-bookmark "" id)))))
@@ -783,13 +785,30 @@ PUB-DIR is set, use this as the publishing directory."
                  ltype))
   (case ltype
     ((ordered unordered)
-     (org-lparse-insert-tag "</text:list-item>"))
+     (org-lparse-insert-tag (if (= (length org-lparse-list-stack)
+                                  (length org-odt-list-stack-stashed))
+                               (prog1 "</text:list-header>"
+                                 (setq org-odt-list-stack-stashed nil))
+                             "</text:list-item>")))
     (description
      (org-lparse-end-list-item-1)
      (org-lparse-end-list 'description)
      (org-lparse-end-list-item-1))
     (t (error "Unknown list type"))))
 
+(defun org-odt-discontinue-list ()
+  (let ((stashed-stack org-lparse-list-stack))
+    (loop for list-type in stashed-stack
+         do (org-lparse-end-list-item-1 list-type)
+         (org-lparse-end-list list-type))
+    (setq org-odt-list-stack-stashed stashed-stack)))
+
+(defun org-odt-continue-list ()
+  (setq org-odt-list-stack-stashed (nreverse org-odt-list-stack-stashed))
+  (loop for list-type in org-odt-list-stack-stashed
+       do (org-lparse-begin-list list-type)
+       (org-lparse-begin-list-item list-type)))
+
 ;; Following variables are let bound when table emission is in
 ;; progress. See org-lparse.el.
 (defvar org-lparse-table-begin-marker)
@@ -882,6 +901,7 @@ The TABLE-STYLE-NAME \"OrgEquation\" is used internally for
 formatting of numbered display equations.  Do not delete this
 style from the list."
   :group 'org-export-odt
+  :version "24.1"
   :type '(choice
           (const :tag "None" nil)
           (repeat :tag "Table Styles"
@@ -897,17 +917,100 @@ style from the list."
                               :key-type symbol
                               :value-type (const :tag "True" t))))))
 
+(defvar org-odt-table-style-format
+  "
+<style:style style:name=\"%s\" style:family=\"table\">
+  <style:table-properties style:rel-width=\"%d%%\" fo:margin-top=\"0cm\" fo:margin-bottom=\"0.20cm\" table:align=\"center\"/>
+</style:style>
+"
+  "Template for auto-generated Table styles.")
+
+(defvar org-odt-automatic-styles '()
+  "Registry of automatic styles for various OBJECT-TYPEs.
+The variable has the following form:
+\(\(OBJECT-TYPE-A
+  \(\(OBJECT-NAME-A.1 OBJECT-PROPS-A.1\)
+   \(OBJECT-NAME-A.2 OBJECT-PROPS-A.2\) ...\)\)
+ \(OBJECT-TYPE-B
+  \(\(OBJECT-NAME-B.1 OBJECT-PROPS-B.1\)
+   \(OBJECT-NAME-B.2 OBJECT-PROPS-B.2\) ...\)\)
+ ...\).
+
+OBJECT-TYPEs could be \"Section\", \"Table\", \"Figure\" etc.
+OBJECT-PROPS is (typically) a plist created by passing
+\"#+ATTR_ODT: \" option to `org-lparse-get-block-params'.
+
+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
+`org-odt-add-automatic-style'.")
+
+(defun org-odt-write-automatic-styles ()
+  "Write automatic styles to \"content.xml\"."
+  (with-current-buffer
+      (find-file-noselect (expand-file-name "content.xml") t)
+    ;; position the cursor
+    (goto-char (point-min))
+    (re-search-forward "  </office:automatic-styles>" nil t)
+    (goto-char (match-beginning 0))
+    ;; write automatic table styles
+    (loop for (style-name props) in
+         (plist-get org-odt-automatic-styles 'Table) do
+         (when (setq props (or (plist-get props :rel-width) 96))
+           (insert (format org-odt-table-style-format style-name props))))))
+
+(defun org-odt-add-automatic-style (object-type &optional object-props)
+  "Create an automatic style of type OBJECT-TYPE with param OBJECT-PROPS.
+OBJECT-PROPS is (typically) a plist created by passing
+\"#+ATTR_ODT: \" option of the object in question to
+`org-lparse-get-block-params'.
+
+Use `org-odt-object-counters' to generate an automatic
+OBJECT-NAME and STYLE-NAME.  If OBJECT-PROPS is non-nil, add a
+new entry in `org-odt-automatic-styles'.  Return (OBJECT-NAME
+. STYLE-NAME)."
+  (assert (stringp object-type))
+  (let* ((object (intern object-type))
+        (seqvar object)
+        (seqno (1+ (or (plist-get org-odt-object-counters seqvar) 0)))
+        (object-name (format "%s%d" object-type seqno)) style-name)
+    (setq org-odt-object-counters
+         (plist-put org-odt-object-counters seqvar seqno))
+    (when object-props
+      (setq style-name (format "Org%s" object-name))
+      (setq org-odt-automatic-styles
+           (plist-put org-odt-automatic-styles object
+                      (append (list (list style-name object-props))
+                              (plist-get org-odt-automatic-styles object)))))
+    (cons object-name style-name)))
+
+(defvar org-odt-table-indentedp nil)
 (defun org-odt-begin-table (caption label attributes)
-  (setq org-odt-table-style attributes)
+  (setq org-odt-table-indentedp (not (null org-lparse-list-stack)))
+  (when org-odt-table-indentedp
+    ;; Within the Org file, the table is appearing within a list item.
+    ;; OpenDocument doesn't allow table to appear within list items.
+    ;; Temporarily terminate the list, emit the table and then
+    ;; re-continue the list.
+    (org-odt-discontinue-list)
+    ;; Put the Table in an indented section.
+    (let ((level (length org-odt-list-stack-stashed)))
+      (org-odt-begin-section (format "OrgIndentedSection-Level-%d" level))))
+  (setq attributes (org-lparse-get-block-params attributes))
+  (setq org-odt-table-style (plist-get attributes :style))
   (setq org-odt-table-style-spec
        (assoc org-odt-table-style org-export-odt-table-styles))
-  (when label
+  (when (or label caption)
     (insert
      (org-odt-format-stylized-paragraph
       'table (org-odt-format-entity-caption label caption "__Table__"))))
-  (org-lparse-insert-tag
-   "<table:table table:name=\"%s\" table:style-name=\"%s\">"
-   (or label "") (or (nth 1 org-odt-table-style-spec) "OrgTable"))
+  (let ((name-and-style (org-odt-add-automatic-style "Table" attributes)))
+    (org-lparse-insert-tag
+     "<table:table table:name=\"%s\" table:style-name=\"%s\">"
+     (car name-and-style) (or (nth 1 org-odt-table-style-spec)
+                             (cdr name-and-style) "OrgTable")))
   (setq org-lparse-table-begin-marker (point)))
 
 (defvar org-lparse-table-colalign-info)
@@ -940,14 +1043,17 @@ style from the list."
         ((equal spec "table-cell:style-name")
          (replace-match table-cell-style t t))))))
   (goto-char (point-max))
-  (org-lparse-insert-tag "</table:table>"))
+  (org-lparse-insert-tag "</table:table>")
+  (when org-odt-table-indentedp
+    (org-odt-end-section)
+    (org-odt-continue-list)))
 
 (defun org-odt-begin-table-rowgroup (&optional is-header-row)
   (when org-lparse-table-rowgrp-open
     (org-lparse-end 'TABLE-ROWGROUP))
   (org-lparse-insert-tag (if is-header-row
-                          "<table:table-header-rows>"
-                        "<table:table-rows>"))
+                            "<table:table-header-rows>"
+                          "<table:table-rows>"))
   (setq org-lparse-table-rowgrp-open t)
   (setq org-lparse-table-cur-rowgrp-is-hdr is-header-row))
 
@@ -1078,6 +1184,16 @@ styles congruent with the ODF-1.2 specification."
   (org-lparse-end-paragraph))
 
 (defun org-odt-begin-toc (lang-specific-heading max-level)
+  ;; Strings in `org-export-language-setup' can contain named html
+  ;; entities.  Replace those with utf-8 equivalents.
+  (let ((i 0) entity rpl)
+    (while (string-match "&\\([^#].*?\\);" lang-specific-heading i)
+      (setq entity (match-string 1 lang-specific-heading))
+      (if (not (setq rpl (org-entity-get-representation entity 'utf8)))
+         (setq i (match-end 0))
+       (setq i (+ (match-beginning 0) (length rpl)))
+       (setq lang-specific-heading
+             (replace-match rpl t t lang-specific-heading)))))
   (insert
    (format "
     <text:table-of-content text:style-name=\"Sect2\" text:protected=\"true\" text:name=\"Table of Contents1\">
@@ -1117,9 +1233,9 @@ styles congruent with the ODF-1.2 specification."
                       (concat snumber ". "))
                  headline
                  (and tags
-                   (concat
-                    (org-lparse-format 'SPACES 3)
-                    (org-lparse-format 'FONTIFY tags "tag")))))
+                      (concat
+                       (org-lparse-format 'SPACES 3)
+                       (org-lparse-format 'FONTIFY tags "tag")))))
   (when todo
     (setq headline (org-lparse-format 'FONTIFY headline "todo")))
 
@@ -1137,10 +1253,13 @@ styles congruent with the ODF-1.2 specification."
 (defun org-odt-format-link (desc href &optional attr)
   (cond
    ((and (= (string-to-char href) ?#) (not org-odt-suppress-xref))
-    (setq href (concat org-export-odt-bookmark-prefix (substring href 1)))
+    (setq href (substring href 1))
     (let ((xref-format "text"))
       (when (numberp desc)
        (setq desc (format "%d" desc) xref-format "number"))
+      (when (listp desc)
+       (setq desc (mapconcat 'identity desc ".") xref-format "chapter"))
+      (setq href (concat org-export-odt-bookmark-prefix href))
       (org-odt-format-tags
        '("<text:bookmark-ref text:reference-format=\"%s\" text:ref-name=\"%s\">" .
         "</text:bookmark-ref>")
@@ -1204,7 +1323,8 @@ Turn this option on if you want to colorize the source code
 blocks in the exported file.  For colorization to work, you need
 to make available an enhanced version of `htmlfontify' library."
   :type 'boolean
-  :group 'org-export-odt)
+  :group 'org-export-odt
+  :version "24.1")
 
 (defun org-odt-format-source-line-with-line-number-and-label
   (line rpllbl num fontifier par-style)
@@ -1415,15 +1535,27 @@ value of `org-export-odt-fontify-srcblocks."
               (org-odt-copy-image-file thefile) thelink))))
     (org-export-odt-format-image thefile href)))
 
-(defun org-export-odt-format-formula (src href &optional embed-as)
-  "Create image tag with source and attributes."
+(defvar org-odt-entity-labels-alist nil
+  "Associate Labels with the Labeled entities.
+Each element of the alist is of the form (LABEL-NAME
+CATEGORY-NAME SEQNO LABEL-STYLE-NAME).  LABEL-NAME is same as
+that specified by \"#+LABEL: ...\" line.  CATEGORY-NAME is the
+type of the entity that LABEL-NAME is attached to.  CATEGORY-NAME
+can be one of \"Table\", \"Figure\" or \"Equation\".  SEQNO is
+the unique number assigned to the referenced entity on a
+per-CATEGORY basis.  It is generated sequentially and is 1-based.
+LABEL-STYLE-NAME is a key `org-odt-label-styles'.
+
+See `org-odt-add-label-definition' and
+`org-odt-fixup-label-references'.")
+
+(defun org-export-odt-format-formula (src href)
   (save-match-data
     (let* ((caption (org-find-text-property-in-string 'org-caption src))
           (caption (and caption (org-xml-format-desc caption)))
           (label (org-find-text-property-in-string 'org-label src))
           (latex-frag (org-find-text-property-in-string 'org-latex-src src))
-          (embed-as (or embed-as
-                        (and latex-frag
+          (embed-as (or (and latex-frag
                              (org-find-text-property-in-string
                               'org-latex-src-embed-type src))
                         (if (or caption label) 'paragraph 'character)))
@@ -1438,11 +1570,15 @@ value of `org-export-odt-fontify-srcblocks."
        (org-lparse-end-paragraph)
        (org-lparse-insert-list-table
         `((,(org-odt-format-entity
-             (if caption "CaptionedDisplayFormula" "DisplayFormula")
-             href width height :caption caption :label nil)
-           ,(if (not label) ""
-              (org-odt-format-entity-caption label nil "__MathFormula__"))))
-        nil nil nil "OrgEquation" nil '((1 "c" 8) (2 "c" 1)))
+             (if (not (or caption label)) "DisplayFormula"
+               "CaptionedDisplayFormula")
+             href width height :caption caption :label label)
+           ,(if (not (or caption label)) ""
+              (let* ((label-props (car org-odt-entity-labels-alist)))
+                (setcar (last label-props) "math-label")
+                (apply 'org-odt-format-label-definition
+                       caption label-props)))))
+        nil nil nil ":style \"OrgEquation\"" nil '((1 "c" 8) (2 "c" 1)))
        (throw 'nextline nil))))))
 
 (defvar org-odt-embedded-formulas-count 0)
@@ -1457,19 +1593,19 @@ value of `org-export-odt-fontify-srcblocks."
       (message "Embedding %s as %s ..."
               (substring-no-properties path) target-file)
 
-       (make-directory target-dir)
-       (org-odt-create-manifest-file-entry
-        "application/vnd.oasis.opendocument.formula" target-dir "1.2")
-
-       (case (org-odt-is-formula-link-p src-file)
-         (mathml
-          (copy-file src-file target-file 'overwrite))
-         (odf
-          (org-odt-zip-extract-one src-file "content.xml" target-dir))
-         (t
-          (error "%s is not a formula file" src-file)))
-
-       (org-odt-create-manifest-file-entry "text/xml" target-file))
+      (make-directory target-dir)
+      (org-odt-create-manifest-file-entry
+       "application/vnd.oasis.opendocument.formula" target-dir "1.2")
+
+      (case (org-odt-is-formula-link-p src-file)
+       (mathml
+        (copy-file src-file target-file 'overwrite))
+       (odf
+        (org-odt-zip-extract-one src-file "content.xml" target-dir))
+       (t
+        (error "%s is not a formula file" src-file)))
+
+      (org-odt-create-manifest-file-entry "text/xml" target-file))
     target-file))
 
 (defun org-odt-format-inline-formula (thefile)
@@ -1508,7 +1644,8 @@ ATTR is a string of other attributes of the a element."
                 (not fragment)))
           (type (if (equal type-1 "id") "file" type-1))
           (filename path)
-          (thefile path))
+          (thefile path)
+          sec-frag sec-nos)
       (cond
        ;; check for inlined images
        ((and (member type '("file"))
@@ -1524,6 +1661,7 @@ ATTR is a string of other attributes of the a element."
             (org-odt-is-formula-link-p filename)
             (or (not descp)))
        (org-odt-format-inline-formula thefile))
+       ;; code references
        ((string= type "coderef")
        (let* ((ref fragment)
               (lineno-or-ref (cdr (assoc ref org-export-code-refs)))
@@ -1546,6 +1684,23 @@ ATTR is a string of other attributes of the a element."
                          (or desc "%s"))
                        lineno-or-ref))
            (org-odt-format-link (org-xml-format-desc desc) href)))))
+       ;; links to headlines
+       ((and (string= type "")
+            (or (not thefile) (string= thefile ""))
+            (plist-get org-lparse-opt-plist :section-numbers)
+            (setq sec-frag fragment)
+            (org-find-text-property-in-string 'org-no-description fragment)
+            (or (string-match  "\\`sec\\(\\(-[0-9]+\\)+\\)" sec-frag)
+                (and (setq sec-frag
+                           (loop for alias in org-export-target-aliases do
+                                 (when (member fragment (cdr alias))
+                                   (return (car alias)))))
+                     (string-match  "\\`sec\\(\\(-[0-9]+\\)+\\)" sec-frag)))
+            (setq sec-nos (org-split-string (match-string 1 sec-frag) "-"))
+            (<= (length sec-nos) (plist-get org-lparse-opt-plist
+                                            :headline-levels)))
+       (let ((org-odt-suppress-xref nil))
+         (org-odt-format-link sec-nos (concat "#" sec-frag) attr)))
        (t
        (when (string= type "file")
          (setq thefile
@@ -1574,7 +1729,7 @@ ATTR is a string of other attributes of the a element."
        "</text:h>") text level level)))
 
 (defun org-odt-format-headline (title extra-targets tags
-                                           &optional snumber level)
+                                     &optional snumber level)
   (concat
    (org-lparse-format 'EXTRA-TARGETS extra-targets)
 
@@ -1654,9 +1809,7 @@ ATTR is a string of other attributes of the a element."
           (attr-plist (org-lparse-get-block-params attr))
           (user-frame-anchor
            (car (assoc-string (plist-get attr-plist :anchor)
-                              (if (or caption label)
-                                  '(("paragraph") ("page"))
-                                '(("character") ("paragraph") ("page"))) t)))
+                              '(("as-char") ("paragraph") ("page")) t)))
           (user-frame-style
            (and user-frame-anchor (plist-get attr-plist :style)))
           (user-frame-attrs
@@ -1666,8 +1819,10 @@ ATTR is a string of other attributes of the a element."
           (embed-as (cond
                      (latex-frag
                       (symbol-name
-                       (or (org-find-text-property-in-string
-                            'org-latex-src-embed-type src) 'character)))
+                       (case (org-find-text-property-in-string
+                              'org-latex-src-embed-type src)
+                         (paragraph 'paragraph)
+                         (t 'as-char))))
                      (user-frame-anchor)
                      (t "paragraph")))
           (size (org-odt-image-size-from-file
@@ -1714,7 +1869,8 @@ ATTR is a string of other attributes of the a element."
    (org-odt-format-tags
     '("<draw:text-box %s>" . "</draw:text-box>")
     text (concat (format " fo:min-height=\"%0.2fcm\"" (or height .2))
-                (format " fo:min-width=\"%0.2fcm\"" (or width .2))))
+                (unless width
+                  (format " fo:min-width=\"%0.2fcm\"" (or width .2)))))
    width nil style extra anchor-type))
 
 (defun org-odt-format-inlinetask (heading content
@@ -1729,9 +1885,13 @@ ATTR is a string of other attributes of the a element."
                content) nil nil "OrgInlineTaskFrame" " style:rel-width=\"100%\"")))
 
 (defvar org-odt-entity-frame-styles
-  '(("CharacterImage" "__Figure__" ("OrgInlineImage" nil "as-char"))
+  '(("As-CharImage" "__Figure__" ("OrgInlineImage" nil "as-char"))
     ("ParagraphImage" "__Figure__" ("OrgDisplayImage" nil "paragraph"))
     ("PageImage" "__Figure__" ("OrgPageImage" nil "page"))
+    ("CaptionedAs-CharImage" "__Figure__"
+     ("OrgCaptionedImage"
+      " style:rel-width=\"100%\" style:rel-height=\"scale\"" "paragraph")
+     ("OrgInlineImage" nil "as-char"))
     ("CaptionedParagraphImage" "__Figure__"
      ("OrgCaptionedImage"
       " style:rel-width=\"100%\" style:rel-height=\"scale\"" "paragraph")
@@ -1803,12 +1963,12 @@ ATTR is a string of other attributes of the a element."
     target-file))
 
 (defvar org-export-odt-image-size-probe-method
-  '(emacs imagemagick force)
-  "Ordered list of methods by for determining size of an embedded
-  image.")
+  (append (and (executable-find "identify") '(imagemagick)) ; See Bug#10675
+         '(emacs fixed))
+  "Ordered list of methods for determining image sizes.")
 
 (defvar org-export-odt-default-image-sizes-alist
-  '(("character" . (5 . 0.4))
+  '(("as-char" . (5 . 0.4))
     ("paragraph" . (5 . 5)))
   "Hardcoded image dimensions one for each of the anchor
   methods.")
@@ -1832,7 +1992,9 @@ ATTR is a string of other attributes of the a element."
                                   (pixels-to-cms (cdr size-in-pixels)))))))
     (case probe-method
       (emacs
-       (size-in-cms (ignore-errors (image-size (create-image file) 'pixels))))
+       (size-in-cms (ignore-errors     ; Emacs could be in batch mode
+                     (clear-image-cache)
+                     (image-size (create-image file) 'pixels))))
       (imagemagick
        (size-in-cms
        (let ((dim (shell-command-to-string
@@ -1877,27 +2039,15 @@ ATTR is a string of other attributes of the a element."
          (setq width (* scale width) height (* scale height)))))
     (cons width height)))
 
-(defvar org-odt-entity-labels-alist nil
-  "Associate Labels with the Labelled entities.
-Each element of the alist is of the form (LABEL-NAME
-CATEGORY-NAME SEQNO LABEL-STYLE-NAME).  LABEL-NAME is same as
-that specified by \"#+LABEL: ...\" line.  CATEGORY-NAME is the
-type of the entity that LABEL-NAME is attached to.  CATEGORY-NAME
-can be one of \"Table\", \"Figure\" or \"Equation\".  SEQNO is
-the unique number assigned to the referenced entity on a
-per-CATEGORY basis.  It is generated sequentially and is 1-based.
-LABEL-STYLE-NAME is a key `org-odt-label-styles'.
-
-See `org-odt-add-label-definition' and
-`org-odt-fixup-label-references'.")
-
 (defvar org-odt-entity-counts-plist nil
   "Plist of running counters of SEQNOs for each of the CATEGORY-NAMEs.
 See `org-odt-entity-labels-alist' for known CATEGORY-NAMEs.")
 
 (defvar org-odt-label-styles
-  '(("text" "(%n)" "text" "(%n)")
-    ("category-and-value" "%e %n%c" "category-and-value" "%e %n"))
+  '(("math-formula" "%c" "text" "(%n)")
+    ("math-label" "(%n)" "text" "(%n)")
+    ("category-and-value" "%e %n: %c" "category-and-value" "%e %n")
+    ("value" "%e %n: %c" "value" "%n"))
   "Specify how labels are applied and referenced.
 This is an alist where each element is of the
 form (LABEL-STYLE-NAME LABEL-ATTACH-FMT LABEL-REF-MODE
@@ -1918,89 +2068,105 @@ specifiers - %e and %n.  %e is replaced with the CATEGORY-NAME.
 %n is replaced with SEQNO. See
 `org-odt-format-label-reference'.")
 
+(defcustom org-export-odt-category-strings
+  '(("en" "Table" "Figure" "Equation" "Equation"))
+  "Specify category strings for various captionable entities.
+Captionable entity can be one of a Table, an Embedded Image, a
+LaTeX fragment (generated with dvipng) or a Math Formula.
+
+For example, when `org-export-default-language' is \"en\", an
+embedded image will be captioned as \"Figure 1: Orgmode Logo\".
+If you want the images to be captioned instead as \"Illustration
+1: Orgmode Logo\", then modify the entry for \"en\" as shown
+below.
+
+  \(setq org-export-odt-category-strings
+       '\(\(\"en\" \"Table\" \"Illustration\"
+          \"Equation\" \"Equation\"\)\)\)"
+  :group 'org-export-odt
+  :version "24.1"
+  :type '(repeat (list (string :tag "Language tag")
+                      (choice :tag "Table"
+                              (const :tag "Use Default" nil)
+                              (string :tag "Category string"))
+                      (choice :tag "Figure"
+                              (const :tag "Use Default" nil)
+                              (string :tag "Category string"))
+                      (choice :tag "Math Formula"
+                              (const :tag "Use Default" nil)
+                              (string :tag "Category string"))
+                      (choice :tag "Dvipng Image"
+                              (const :tag "Use Default" nil)
+                              (string :tag "Category string")))))
+
 (defvar org-odt-category-map-alist
-  '(("__Table__" "Table" "category-and-value")
-    ("__Figure__" "Figure" "category-and-value")
-    ("__MathFormula__" "Equation" "text")
-    ("__DvipngImage__" "Equation" "category-and-value"))
-  "Map a CATEGORY-HANDLE to CATEGORY-NAME and LABEL-STYLE.
-This is an alist where each element is of the form
-\\(CATEGORY-HANDLE CATEGORY-NAME LABEL-STYLE\\).  CATEGORY_HANDLE
-could either be one of the internal handles (as seen above) or be
-derived from the \"#+LABEL:<label-name>\" specification.  See
-`org-export-odt-get-category-from-label'.  CATEGORY-NAME and
-LABEL-STYLE are used for generating ODT labels.  See
-`org-odt-label-styles'.")
-
-(defvar org-export-odt-user-categories
-  '("Illustration" "Table" "Text" "Drawing" "Equation" "Figure"))
-
-(defvar org-export-odt-get-category-from-label nil
-  "Should category of label be inferred from label itself.
-When this option is non-nil, a label is parsed in to two
-component parts delimited by a \":\" (colon) as shown here -
-#+LABEL:[CATEGORY-HANDLE:]EXTRA.  The CATEGORY-HANDLE is mapped
-to a CATEGORY-NAME and LABEL-STYLE using
-`org-odt-category-map-alist'.  (If no such map is provided and
-CATEGORY-NAME is set to CATEGORY-HANDLE and LABEL-STYLE is set to
-\"category-and-value\").  If CATEGORY-NAME so obtained is listed
-under `org-export-odt-user-categories' then the user specified
-styles are used.  Otherwise styles as determined by the internal
-CATEGORY-HANDLE is used.  See
-`org-odt-get-label-category-and-style' for details.")
-
-(defun org-odt-get-label-category-and-style (label default-category)
-  "See `org-export-odt-get-category-from-label'."
-  (let ((default-category-map
-         (assoc default-category org-odt-category-map-alist))
-       user-category user-category-map category)
-    (cond
-     ((not org-export-odt-get-category-from-label)
-      default-category-map)
-     ((not (setq user-category
-                (save-match-data
-                  (and (string-match "\\`\\(.*\\):.+" label)
-                       (match-string 1 label)))))
-      default-category-map)
-     (t
-      (setq user-category-map
-           (or (assoc user-category org-odt-category-map-alist)
-               (list nil user-category "category-and-value"))
-           category (nth 1 user-category-map))
-      (if (member category org-export-odt-user-categories)
-         user-category-map
-       default-category-map)))))
+  '(("__Table__" "Table" "value")
+    ("__Figure__" "Illustration" "value")
+    ("__MathFormula__" "Text" "math-formula")
+    ("__DvipngImage__" "Equation" "value")
+    ;; ("__Table__" "Table" "category-and-value")
+    ;; ("__Figure__" "Figure" "category-and-value")
+    ;; ("__DvipngImage__" "Equation" "category-and-value")
+    )
+  "Map a CATEGORY-HANDLE to OD-VARIABLE and LABEL-STYLE.
+This is a list where each entry is of the form \\(CATEGORY-HANDLE
+OD-VARIABLE LABEL-STYLE\\).  CATEGORY_HANDLE identifies the
+captionable entity in question.  OD-VARIABLE is the OpenDocument
+sequence counter associated with the entity.  These counters are
+declared within
+\"<text:sequence-decls>...</text:sequence-decls>\" block of
+`org-export-odt-content-template-file'.  LABEL-STYLE is a key
+into `org-odt-label-styles' and specifies how a given entity
+should be captioned and referenced.
+
+The position of a CATEGORY-HANDLE in this list is used as an
+index in to per-language entry for
+`org-export-odt-category-strings' to retrieve a CATEGORY-NAME.
+This CATEGORY-NAME is then used for qualifying the user-specified
+captions on export.")
 
 (defun org-odt-add-label-definition (label default-category)
   "Create an entry in `org-odt-entity-labels-alist' and return it."
-  (setq label (substring-no-properties label))
-  (let* ((label-props (org-odt-get-label-category-and-style
-                      label default-category))
-        (category (nth 1 label-props))
-        (counter category)
-        (label-style (nth 2 label-props))
-        (sequence-var (intern (mapconcat
-                               'downcase
-                               (org-split-string counter) "-")))
+  (let* ((label-props (assoc default-category org-odt-category-map-alist))
+        ;; identify the sequence number
+        (counter (nth 1 label-props))
+        (sequence-var (intern counter))
         (seqno (1+ (or (plist-get org-odt-entity-counts-plist sequence-var)
                        0)))
-        (label-props (list label category seqno label-style)))
+        ;; assign an internal label, if user has not provided one
+        (label (if label (substring-no-properties label)
+                 (format  "%s-%s" default-category seqno)))
+        ;; identify label style
+        (label-style (nth 2 label-props))
+        ;; grok language setting
+        (en-strings (assoc-default "en" org-export-odt-category-strings))
+        (lang (plist-get org-lparse-opt-plist :language))
+        (lang-strings (assoc-default lang org-export-odt-category-strings))
+        ;; retrieve localized category sting
+        (pos (- (length org-odt-category-map-alist)
+                (length (memq label-props org-odt-category-map-alist))))
+        (category (or (nth pos lang-strings) (nth pos en-strings)))
+        (label-props (list label category counter seqno label-style)))
+    ;; synchronize internal counters
     (setq org-odt-entity-counts-plist
          (plist-put org-odt-entity-counts-plist sequence-var seqno))
+    ;; stash label properties for later retrieval
     (push label-props org-odt-entity-labels-alist)
     label-props))
 
-(defun org-odt-format-label-definition (caption label category seqno label-style)
+(defun org-odt-format-label-definition (caption label category counter
+                                               seqno label-style)
   (assert label)
   (format-spec
    (cadr (assoc-string label-style org-odt-label-styles t))
    `((?e . ,category)
      (?n . ,(org-odt-format-tags
             '("<text:sequence text:ref-name=\"%s\" text:name=\"%s\" text:formula=\"ooow:%s+1\" style:num-format=\"1\">" . "</text:sequence>")
-            (format "%d" seqno) label category category))
-     (?c . ,(or (and caption (concat ": " caption)) "")))))
+            (format "%d" seqno) label counter counter))
+     (?c . ,(or caption "")))))
 
-(defun org-odt-format-label-reference (label category seqno label-style)
+(defun org-odt-format-label-reference (label category counter
+                                            seqno label-style)
   (assert label)
   (save-match-data
     (let* ((fmt (cddr (assoc-string label-style org-odt-label-styles t)))
@@ -2026,10 +2192,9 @@ CATEGORY-HANDLE is used.  See
         (format "Unable to resolve reference to label \"%s\"" label))))))
 
 (defun org-odt-format-entity-caption (label caption category)
-  (or (and label
-          (apply 'org-odt-format-label-definition
-                 caption (org-odt-add-label-definition label category)))
-      caption ""))
+  (if (not (or label caption)) ""
+    (apply 'org-odt-format-label-definition caption
+          (org-odt-add-label-definition label category))))
 
 (defun org-odt-format-tags (tag text &rest args)
   (let ((prefix (when org-lparse-encode-pending "@"))
@@ -2054,6 +2219,9 @@ CATEGORY-HANDLE is used.  See
          org-odt-embedded-images-count 0
          org-odt-embedded-formulas-count 0
          org-odt-entity-labels-alist nil
+         org-odt-list-stack-stashed nil
+         org-odt-automatic-styles nil
+         org-odt-object-counters nil
          org-odt-entity-counts-plist nil)
     content-file))
 
@@ -2064,10 +2232,14 @@ component xml buffers before they are saved.  Turn this off for
 regular use.  Turn this on if you need to examine the xml
 visually."
   :group 'org-export-odt
+  :version "24.1"
   :type 'boolean)
 
 (defvar hfy-user-sheet-assoc)          ; bound during org-do-lparse
 (defun org-odt-save-as-outfile (target opt-plist)
+  ;; write automatic styles
+  (org-odt-write-automatic-styles)
+
   ;; write meta file
   (org-odt-update-meta-file opt-plist)
 
@@ -2183,21 +2355,21 @@ visually."
          xmlns:ooo=\"http://openoffice.org/2004/office\"
          office:version=\"1.2\">
        <office:meta>" "\n"
-      (org-odt-format-author)
-      (org-odt-format-tags
-       '("\n<meta:initial-creator>" . "</meta:initial-creator>") author)
-      (org-odt-format-tags '("\n<dc:date>" . "</dc:date>") date)
-      (org-odt-format-tags
-       '("\n<meta:creation-date>" . "</meta:creation-date>") date)
-      (org-odt-format-tags '("\n<meta:generator>" . "</meta:generator>")
-                          (when org-export-creator-info
-                            (format "Org-%s/Emacs-%s"
-                                    org-version emacs-version)))
-      (org-odt-format-tags '("\n<meta:keyword>" . "</meta:keyword>") keywords)
-      (org-odt-format-tags '("\n<dc:subject>" . "</dc:subject>") description)
-      (org-odt-format-tags '("\n<dc:title>" . "</dc:title>") title)
-      "\n"
-      "  </office:meta>" "</office:document-meta>")
+       (org-odt-format-author)
+       (org-odt-format-tags
+       '("\n<meta:initial-creator>" . "</meta:initial-creator>") author)
+       (org-odt-format-tags '("\n<dc:date>" . "</dc:date>") date)
+       (org-odt-format-tags
+       '("\n<meta:creation-date>" . "</meta:creation-date>") date)
+       (org-odt-format-tags '("\n<meta:generator>" . "</meta:generator>")
+                           (when org-export-creator-info
+                             (format "Org-%s/Emacs-%s"
+                                     org-version emacs-version)))
+       (org-odt-format-tags '("\n<meta:keyword>" . "</meta:keyword>") keywords)
+       (org-odt-format-tags '("\n<dc:subject>" . "</dc:subject>") description)
+       (org-odt-format-tags '("\n<dc:title>" . "</dc:title>") title)
+       "\n"
+       "  </office:meta>" "</office:document-meta>")
      nil (expand-file-name "meta.xml")))
 
   ;; create a manifest entry for meta.xml
@@ -2213,7 +2385,7 @@ visually."
   (with-current-buffer
       (find-file-noselect (expand-file-name "styles.xml") t)
     ;; Don't make automatic backup of styles.xml file. This setting
-    ;; prevents the backedup styles.xml file from being zipped in to
+    ;; prevents the backed-up styles.xml file from being zipped in to
     ;; odt file. This is more of a hackish fix. Better alternative
     ;; would be to fix the zip command so that the output odt file
     ;; includes only the needed files and excludes any auto-generated
@@ -2228,7 +2400,7 @@ visually."
     (org-odt-configure-outline-numbering
      (if org-export-with-section-numbers org-export-headline-levels 0)))
 
-  ;; Write custom stlyes for source blocks
+  ;; Write custom styles for source blocks
   (org-odt-insert-custom-styles-for-srcblocks
    (mapconcat
     (lambda (style)
@@ -2256,23 +2428,19 @@ visually."
       (replace-match ""))))
 
 (defcustom org-export-odt-convert-processes
-  '(("BasicODConverter"
-     ("soffice" "-norestore" "-invisible" "-headless"
-      "\"macro:///BasicODConverter.Main.Convert(%I,%f,%O)\""))
+  '(("LibreOffice"
+     "soffice --headless --convert-to %f%x --outdir %d %i")
     ("unoconv"
-     ("unoconv" "-f" "%f" "-o" "%d" "%i")))
+     "unoconv -f %f -o %d %i"))
   "Specify a list of document converters and their usage.
 The converters in this list are offered as choices while
 customizing `org-export-odt-convert-process'.
 
-This variable is an alist where each element is of the
-form (CONVERTER-NAME CONVERTER-PROCESS).  CONVERTER-NAME is name
-of the converter.  CONVERTER-PROCESS specifies the command-line
-syntax of the converter and is of the form (CONVERTER-PROGRAM
-ARG1 ARG2 ...).  CONVERTER-PROGRAM is the name of the executable.
-ARG1, ARG2 etc are command line options that are passed to
-CONVERTER-PROGRAM.  Format specifiers can be used in the ARGs and
-they are interpreted as below:
+This variable is a list where each element is of the
+form (CONVERTER-NAME CONVERTER-CMD).  CONVERTER-NAME is the name
+of the converter.  CONVERTER-CMD is the shell command for the
+converter and can contain format specifiers.  These format
+specifiers are interpreted as below:
 
 %i input file name in full
 %I input file name as a URL
@@ -2280,21 +2448,23 @@ they are interpreted as below:
 %o output file name in full
 %O output file name as a URL
 %d output dir in full
-%D output dir as a URL."
+%D output dir as a URL.
+%x extra options as set in `org-export-odt-convert-capabilities'."
   :group 'org-export-odt
+  :version "24.1"
   :type
   '(choice
     (const :tag "None" nil)
     (alist :tag "Converters"
           :key-type (string :tag "Converter Name")
-          :value-type (group (cons (string :tag "Executable")
-                                   (repeat (string :tag "Command line args")))))))
+          :value-type (group (string :tag "Command line")))))
 
-(defcustom org-export-odt-convert-process nil
+(defcustom org-export-odt-convert-process "LibreOffice"
   "Use this converter to convert from \"odt\" format to other formats.
 During customization, the list of converter names are populated
 from `org-export-odt-convert-processes'."
   :group 'org-export-odt
+  :version "24.1"
   :type '(choice :convert-widget
                 (lambda (w)
                   (apply 'widget-convert (widget-type w)
@@ -2306,19 +2476,20 @@ from `org-export-odt-convert-processes'."
 
 (defcustom org-export-odt-convert-capabilities
   '(("Text"
-     ("odt" "ott" "doc" "rtf")
-     (("pdf" "pdf") ("odt" "odt") ("xhtml" "html") ("rtf" "rtf")
-      ("ott" "ott") ("doc" "doc") ("ooxml" "xml") ("html" "html")))
+     ("odt" "ott" "doc" "rtf" "docx")
+     (("pdf" "pdf") ("odt" "odt") ("rtf" "rtf") ("ott" "ott")
+      ("doc" "doc" ":\"MS Word 97\"") ("docx" "docx") ("html" "html")))
     ("Web"
-     ("html" "xhtml") (("pdf" "pdf") ("odt" "txt") ("html" "html")))
+     ("html")
+     (("pdf" "pdf") ("odt" "odt") ("html" "html")))
     ("Spreadsheet"
-     ("ods" "ots" "xls" "csv")
-     (("pdf" "pdf") ("ots" "ots") ("html" "html") ("csv" "csv")
-      ("ods" "ods") ("xls" "xls") ("xhtml" "xhtml") ("ooxml" "xml")))
+     ("ods" "ots" "xls" "csv" "xlsx")
+     (("pdf" "pdf") ("ots" "ots") ("html" "html") ("csv" "csv") ("ods" "ods")
+      ("xls" "xls") ("xlsx" "xlsx")))
     ("Presentation"
-     ("odp" "otp" "ppt")
-     (("pdf" "pdf") ("swf" "swf") ("odp" "odp") ("xhtml" "xml")
-      ("otp" "otp") ("ppt" "ppt") ("odg" "odg") ("html" "html"))))
+     ("odp" "otp" "ppt" "pptx")
+     (("pdf" "pdf") ("swf" "swf") ("odp" "odp") ("otp" "otp") ("ppt" "ppt")
+      ("pptx" "pptx") ("odg" "odg"))))
   "Specify input and output formats of `org-export-odt-convert-process'.
 More correctly, specify the set of input and output formats that
 the user is actually interested in.
@@ -2327,7 +2498,7 @@ This variable is an alist where each element is of the
 form (DOCUMENT-CLASS INPUT-FMT-LIST OUTPUT-FMT-ALIST).
 INPUT-FMT-LIST is a list of INPUT-FMTs.  OUTPUT-FMT-ALIST is an
 alist where each element is of the form (OUTPUT-FMT
-OUTPUT-FILE-EXTENSION).
+OUTPUT-FILE-EXTENSION EXTRA-OPTIONS).
 
 The variable is interpreted as follows:
 `org-export-odt-convert-process' can take any document that is in
@@ -2340,6 +2511,9 @@ serves dual purposes:
 - It is used as the value of \"%f\" specifier in
   `org-export-odt-convert-process'.
 
+EXTRA-OPTIONS is used as the value of \"%x\" specifier in
+`org-export-odt-convert-process'.
+
 DOCUMENT-CLASS is used to group a set of file formats in
 INPUT-FMT-LIST in to a single class.
 
@@ -2353,16 +2527,21 @@ with that class.
 See default setting of this variable for an typical
 configuration."
   :group 'org-export-odt
+  :version "24.1"
   :type
   '(choice
     (const :tag "None" nil)
-    (alist :key-type (string :tag "Document Class")
+    (alist :tag "Capabilities"
+          :key-type (string :tag "Document Class")
           :value-type
           (group (repeat :tag "Input formats" (string :tag "Input format"))
                  (alist :tag "Output formats"
                         :key-type (string :tag "Output format")
                         :value-type
-                        (group (string :tag "Output file extension")))))))
+                        (group (string :tag "Output file extension")
+                               (choice
+                                (const :tag "None" nil)
+                                (string :tag "Extra options"))))))))
 
 (declare-function org-create-math-formula "org"
                  (latex-frag &optional mathml-file))
@@ -2479,7 +2658,7 @@ Do this when translation to MathML fails."
 ;; `org-export-preprocess-after-blockquote-hook'. Note that this hook
 ;; is the one that is closest and well before the call to
 ;; `org-export-attach-captions-and-attributes' in
-;; `org-export-preprocess-stirng'.  The above arrangement permits
+;; `org-export-preprocess-string'.  The above arrangement permits
 ;; captions, labels and attributes to be attached to png images
 ;; generated out of latex equations.
 (add-hook 'org-export-preprocess-after-blockquote-hook
@@ -2544,10 +2723,6 @@ Do this when translation to MathML fails."
   ;; create a manifest entry for styles.xml
   (org-odt-create-manifest-file-entry "text/xml" "styles.xml"))
 
-(defvar org-export-odt-factory-settings
-  "d4328fb9d1b6cb211d4320ff546829f26700dc5e"
-  "SHA1 hash of OrgOdtStyles.xml.")
-
 (defun org-odt-configure-outline-numbering (level)
   "Outline numbering is retained only upto LEVEL.
 To disable outline numbering pass a LEVEL of 0."
@@ -2585,7 +2760,6 @@ non-nil."
                             (or (file-name-nondirectory buffer-file-name)))
                            "." "odf")
                           (file-name-directory buffer-file-name))))
-       (message "default val is %s"  odf-filename)
        (read-file-name "ODF filename: " nil odf-filename nil
                        (file-name-nondirectory odf-filename)))))
   (let* ((org-lparse-backend 'odf)
@@ -2612,7 +2786,7 @@ non-nil."
 
 ;;;###autoload
 (defun org-export-as-odf-and-open ()
- "Export LaTeX fragment as OpenDocument formula and immediately open it.
 "Export LaTeX fragment as OpenDocument formula and immediately open it.
 Use `org-export-as-odf' to read LaTeX fragment and OpenDocument
 formula file."
   (interactive)