]> code.delx.au - gnu-emacs/blobdiff - lisp/org/org-table.el
Merge from emacs-24; up to 2014-07-17T10:18:19Z!dmantipov@yandex.ru
[gnu-emacs] / lisp / org / org-table.el
index 08981b57e498762183c6f2978d7086205e9b47c8..f28e96c694e29b5e881cc5fa0c2e9df8bfb8ed6c 100644 (file)
@@ -1,6 +1,6 @@
 ;;; org-table.el --- The table editor for Org-mode
 
-;; Copyright (C) 2004-2012 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2014 Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <carsten at orgmode dot org>
 ;; Keywords: outlines, hypermedia, calendar, wp
   (require 'cl))
 (require 'org)
 
-(declare-function org-table-clean-before-export "org-exp"
-                 (lines &optional maybe-quoted))
-(declare-function org-format-org-table-html "org-html" (lines &optional splice))
+(declare-function org-export-string-as "ox"
+                 (string backend &optional body-only ext-plist))
+(declare-function aa2u "ext:ascii-art-to-unicode" ())
 (defvar orgtbl-mode) ; defined below
 (defvar orgtbl-mode-menu) ; defined when orgtbl mode get initialized
-(defvar org-export-html-table-tag) ; defined in org-exp.el
 (defvar constants-unit-system)
 (defvar org-table-follow-field-mode)
 
@@ -53,6 +52,8 @@ This can be used to add additional functionality after the table is sent
 to the receiver position, otherwise, if table is not sent, the functions
 are not run.")
 
+(defvar org-table-TBLFM-begin-regexp "|\n[ \t]*#\\+TBLFM: ")
+
 (defcustom orgtbl-optimized (eq org-enable-table-editor 'optimized)
   "Non-nil means use the optimized table editor version for `orgtbl-mode'.
 In the optimized version, the table editor takes over all simple keys that
@@ -85,8 +86,30 @@ this variable requires a restart of Emacs to become effective."
 <!--
 #+ORGTBL: SEND %n orgtbl-to-html :splice nil :skip 0
 | | |
--->\n"))
+-->\n")
+    (org-mode "#+ BEGIN RECEIVE ORGTBL %n
+#+ END RECEIVE ORGTBL %n
+
+#+ORGTBL: SEND %n orgtbl-to-orgtbl :splice nil :skip 0
+| | |
+"))
   "Templates for radio tables in different major modes.
+Each template must define lines that will be treated as a comment and that
+must contain the \"BEGIN RECEIVE ORGTBL %n\" and \"END RECEIVE ORGTBL\"
+lines where \"%n\" will be replaced with the name of the table during
+insertion of the template.  The transformed table will later be inserted
+between these lines.
+
+The template should also contain a minimal table in a multiline comment.
+If multiline comments are not possible in the buffer language,
+you can pack it into a string that will not be used when the code
+is compiled or executed.  Above the table will you need a line with
+the fixed string \"#+ORGTBL: SEND\", followed by instruction on how to
+convert the table into a data structure useful in the
+language of the buffer.  Check the manual for the section on
+\"Translator functions\", and more generally check out
+http://orgmode.org/manual/Tables-in-arbitrary-syntax.html#Tables-in-arbitrary-syntax
+
 All occurrences of %n in a template will be replaced with the name of the
 table, obtained by prompting the user."
   :group 'org-table
@@ -102,10 +125,10 @@ table, obtained by prompting the user."
 (defcustom org-table-default-size "5x2"
   "The default size for newly created tables, Columns x Rows."
   :group 'org-table-settings
-   :type 'string)
+  :type 'string)
 
 (defcustom org-table-number-regexp
-  "^\\([<>]?[-+^.0-9]*[0-9][-+^.0-9eEdDx()%:]*\\|\\(0[xX]\\)[0-9a-fA-F]+\\|nan\\)$"
+  "^\\([<>]?[-+^.0-9]*[0-9][-+^.0-9eEdDx()%:]*\\|[<>]?[-+]?0[xX][0-9a-fA-F.]+\\|[<>]?[-+]?[0-9]+#[0-9a-zA-Z.]+\\|nan\\|[-+u]?inf\\)$"
   "Regular expression for recognizing numbers in table columns.
 If a table column contains mostly numbers, it will be aligned to the
 right.  If not, it will be aligned to the left.
@@ -129,14 +152,16 @@ Other options offered by the customize interface are more restrictive."
                 "^[-+]?\\([0-9]*\\.[0-9]+\\|[0-9]+\\.?[0-9]*\\)$")
          (const :tag "Exponential, Floating point, Integer"
                 "^[-+]?[0-9.]+\\([eEdD][-+0-9]+\\)?$")
-         (const :tag "Very General Number-Like, including hex"
-                "^\\([<>]?[-+^.0-9]*[0-9][-+^.0-9eEdDx()%]*\\|\\(0[xX]\\)[0-9a-fA-F]+\\|nan\\)$")
+         (const :tag "Very General Number-Like, including hex and Calc radix"
+                "^\\([<>]?[-+^.0-9]*[0-9][-+^.0-9eEdDx()%]*\\|[<>]?[-+]?0[xX][0-9a-fA-F.]+\\|[<>]?[-+]?[0-9]+#[0-9a-zA-Z.]+\\|nan\\|[-+u]?inf\\)$")
+         (const :tag "Very General Number-Like, including hex and Calc radix, allows comma as decimal mark"
+                "^\\([<>]?[-+^.,0-9]*[0-9][-+^.0-9eEdDx()%]*\\|[<>]?[-+]?0[xX][0-9a-fA-F.]+\\|[<>]?[-+]?[0-9]+#[0-9a-zA-Z.]+\\|nan\\|[-+u]?inf\\)$")
          (string :tag "Regexp:")))
 
 (defcustom org-table-number-fraction 0.5
   "Fraction of numbers in a column required to make the column align right.
-In a column all non-white fields are considered.  If at least this
-fraction of fields is matched by `org-table-number-fraction',
+In a column all non-white fields are considered.  If at least
+this fraction of fields is matched by `org-table-number-regexp',
 alignment to the right border applies."
   :group 'org-table-settings
   :type 'number)
@@ -217,13 +242,13 @@ t       accept as input and present for editing"
 
 (defcustom org-calc-default-modes
   '(calc-internal-prec 12
-    calc-float-format  (float 8)
-    calc-angle-mode    deg
-    calc-prefer-frac   nil
-    calc-symbolic-mode nil
-    calc-date-format (YYYY "-" MM "-" DD " " Www (" " hh ":" mm))
-    calc-display-working-message t
-    )
+                      calc-float-format  (float 8)
+                      calc-angle-mode    deg
+                      calc-prefer-frac   nil
+                      calc-symbolic-mode nil
+                      calc-date-format (YYYY "-" MM "-" DD " " Www (" " hh ":" mm))
+                      calc-display-working-message t
+                      )
   "List with Calc mode settings for use in `calc-eval' for table formulas.
 The list must contain alternating symbols (Calc modes variables and values).
 Don't remove any of the default settings, just change the values.  Org-mode
@@ -368,8 +393,8 @@ available parameters."
   "Vector of hline line numbers in the current table.")
 
 (defconst org-table-range-regexp
-   "@\\([-+]?I*[-+]?[0-9]*\\)?\\(\\$[-+]?[0-9]+\\)?\\(\\.\\.@?\\([-+]?I*[-+]?[0-9]*\\)?\\(\\$[-+]?[0-9]+\\)?\\)?"
-   ;;   1                        2                    3          4                        5
+  "@\\([-+]?I*[-+]?[0-9]*\\)?\\(\\$[-+]?[0-9]+\\)?\\(\\.\\.@?\\([-+]?I*[-+]?[0-9]*\\)?\\(\\$[-+]?[0-9]+\\)?\\)?"
+  ;;   1                        2                    3          4                        5
   "Regular expression for matching ranges in formulas.")
 
 (defconst org-table-range-regexp2
@@ -410,10 +435,45 @@ available parameters."
                         (org-split-string (match-string 1 line)
                                           "[ \t]*|[ \t]*")))))))
 
+(defvar org-table-clean-did-remove-column nil) ; dynamically scoped
+(defun org-table-clean-before-export (lines &optional maybe-quoted)
+  "Check if the table has a marking column.
+If yes remove the column and the special lines."
+  (let ((special (if maybe-quoted
+                    "^[ \t]*| *\\\\?[\#!$*_^/ ] *|"
+                  "^[ \t]*| *[\#!$*_^/ ] *|"))
+       (ignore  (if maybe-quoted
+                    "^[ \t]*| *\\\\?[!$_^/] *|"
+                  "^[ \t]*| *[!$_^/] *|")))
+    (setq org-table-clean-did-remove-column
+         (not (memq nil
+                    (mapcar
+                     (lambda (line)
+                       (or (string-match org-table-hline-regexp line)
+                           (string-match special                line)))
+                     lines))))
+    (delq nil
+         (mapcar
+          (lambda (line)
+            (cond
+             ((or (org-table-colgroup-line-p line)  ;; colgroup info
+                  (org-table-cookie-line-p line)    ;; formatting cookies
+                  (and org-table-clean-did-remove-column
+                       (string-match ignore line))) ;; non-exportable data
+              nil)
+             ((and org-table-clean-did-remove-column
+                   (or (string-match "^\\([ \t]*\\)|-+\\+" line)
+                       (string-match "^\\([ \t]*\\)|[^|]*|" line)))
+              ;; remove the first column
+              (replace-match "\\1|" t nil line))
+             (t line)))
+          lines))))
+
 (defconst org-table-translate-regexp
   (concat "\\(" "@[-0-9I$]+" "\\|" "[a-zA-Z]\\{1,2\\}\\([0-9]+\\|&\\)" "\\)")
   "Match a reference that needs translation, for reference display.")
 
+;;;###autoload
 (defun org-table-create-with-table.el ()
   "Use the table.el package to insert a new table.
 If there is already a table at point, convert between Org-mode tables
@@ -430,6 +490,7 @@ and table.el tables."
       (org-table-convert)))
    (t (call-interactively 'table-insert))))
 
+;;;###autoload
 (defun org-table-create-or-convert-from-region (arg)
   "Convert region to table, or create an empty table.
 If there is an active region, convert it to a table, using the function
@@ -442,6 +503,7 @@ If there is no such region, create an empty table with `org-table-create'."
       (org-table-convert-region (region-beginning) (region-end) arg)
     (org-table-create arg)))
 
+;;;###autoload
 (defun org-table-create (&optional size)
   "Query for a size and insert a table skeleton.
 SIZE is a string Columns x Rows like for example \"3x2\"."
@@ -474,6 +536,7 @@ SIZE is a string Columns x Rows like for example \"3x2\"."
          (goto-char pos)))
     (org-table-align)))
 
+;;;###autoload
 (defun org-table-convert-region (beg0 end0 &optional separator)
   "Convert region to a table.
 The region goes from BEG0 to END0, but these borders will be moved
@@ -490,16 +553,16 @@ nil      When nil, the command tries to be smart and figure out the
          - when each line contains a TAB, assume TAB-separated material
          - when each line contains a comma, assume CSV material
          - else, assume one or more SPACE characters as separator."
-  (interactive "rP")
+  (interactive "r\nP")
   (let* ((beg (min beg0 end0))
         (end (max beg0 end0))
         re)
     (goto-char beg)
     (beginning-of-line 1)
-    (setq beg (move-marker (make-marker) (point)))
+    (setq beg (point-marker))
     (goto-char end)
     (if (bolp) (backward-char 1) (end-of-line 1))
-    (setq end (move-marker (make-marker) (point)))
+    (setq end (point-marker))
     ;; Get the right field separator
     (unless separator
       (goto-char beg)
@@ -526,7 +589,7 @@ nil      When nil, the command tries to be smart and figure out the
                ((equal separator '(16)) "^\\|\t")
                ((integerp separator)
                 (if (< separator 1)
-                    (error "Number of spaces in separator must be >= 1")
+                    (user-error "Number of spaces in separator must be >= 1")
                   (format "^ *\\| *\t *\\| \\{%d,\\}" separator)))
                (t (error "This should not happen"))))
       (while (re-search-forward re end t)
@@ -534,6 +597,7 @@ nil      When nil, the command tries to be smart and figure out the
     (goto-char beg)
     (org-table-align)))
 
+;;;###autoload
 (defun org-table-import (file arg)
   "Import FILE as a table.
 The file is assumed to be tab-separated.  Such files can be produced by most
@@ -549,53 +613,56 @@ are found, lines will be split on whitespace into fields."
 
 (defvar org-table-last-alignment)
 (defvar org-table-last-column-widths)
+;;;###autoload
 (defun org-table-export (&optional file format)
   "Export table to a file, with configurable format.
-Such a file can be imported into a spreadsheet program like Excel.
-FILE can be the output file name.  If not given, it will be taken from
-a TABLE_EXPORT_FILE property in the current entry or higher up in the
-hierarchy, or the user will be prompted for a file name.
-FORMAT can be an export format, of the same kind as it used when
-`orgtbl-mode' sends a table in a different format.  The default format can
-be found in the variable `org-table-export-default-format', but the function
-first checks if there is an export format specified in a TABLE_EXPORT_FORMAT
-property, locally or anywhere up in the hierarchy."
+Such a file can be imported into usual spreadsheet programs.
+
+FILE can be the output file name.  If not given, it will be taken
+from a TABLE_EXPORT_FILE property in the current entry or higher
+up in the hierarchy, or the user will be prompted for a file
+name.  FORMAT can be an export format, of the same kind as it
+used when `orgtbl-mode' sends a table in a different format.
+
+The command suggests a format depending on TABLE_EXPORT_FORMAT,
+whether it is set locally or up in the hierarchy, then on the
+extension of the given file name, and finally on the variable
+`org-table-export-default-format'."
   (interactive)
-  (unless (org-at-table-p)
-    (error "No table at point"))
-  (require 'org-exp)
+  (unless (org-at-table-p) (user-error "No table at point"))
   (org-table-align) ;; make sure we have everything we need
   (let* ((beg (org-table-begin))
         (end (org-table-end))
         (txt (buffer-substring-no-properties beg end))
         (file (or file (org-entry-get beg "TABLE_EXPORT_FILE" t)))
+        (formats '("orgtbl-to-tsv" "orgtbl-to-csv"
+                   "orgtbl-to-latex" "orgtbl-to-html"
+                   "orgtbl-to-generic" "orgtbl-to-texinfo"
+                   "orgtbl-to-orgtbl"))
         (format (or format
                     (org-entry-get beg "TABLE_EXPORT_FORMAT" t)))
-        buf deffmt-readable)
+        buf deffmt-readable fileext)
     (unless file
       (setq file (read-file-name "Export table to: "))
       (unless (or (not (file-exists-p file))
                  (y-or-n-p (format "Overwrite file %s? " file)))
-       (error "Abort")))
+       (user-error "File not written")))
     (if (file-directory-p file)
-       (error "This is a directory path, not a file"))
+       (user-error "This is a directory path, not a file"))
     (if (and (buffer-file-name)
             (equal (file-truename file)
                    (file-truename (buffer-file-name))))
-       (error "Please specify a file name that is different from current"))
+       (user-error "Please specify a file name that is different from current"))
+    (setq fileext (concat (file-name-extension file) "$"))
     (unless format
-      (setq deffmt-readable org-table-export-default-format)
+      (setq deffmt-readable
+           (or (car (delq nil (mapcar (lambda(f) (if (string-match fileext f) f)) formats)))
+               org-table-export-default-format))
       (while (string-match "\t" deffmt-readable)
        (setq deffmt-readable (replace-match "\\t" t t deffmt-readable)))
       (while (string-match "\n" deffmt-readable)
        (setq deffmt-readable (replace-match "\\n" t t deffmt-readable)))
-      (setq format (org-completing-read
-                   "Format: "
-                   '("orgtbl-to-tsv" "orgtbl-to-csv"
-                     "orgtbl-to-latex" "orgtbl-to-html"
-                     "orgtbl-to-generic" "orgtbl-to-texinfo"
-                     "orgtbl-to-orgtbl") nil nil
-                     deffmt-readable)))
+      (setq format (org-completing-read "Format: " formats nil nil deffmt-readable)))
     (if (string-match "\\([^ \t\r\n]+\\)\\( +.*\\)?" format)
        (let* ((transform (intern (match-string 1 format)))
               (params (if (match-end 2)
@@ -622,7 +689,7 @@ property, locally or anywhere up in the hierarchy."
                                     skipcols i0)))
 
          (unless (fboundp transform)
-           (error "No such transformation function %s" transform))
+           (user-error "No such transformation function %s" transform))
          (setq txt (funcall transform table params))
 
          (with-current-buffer (find-file-noselect file)
@@ -633,7 +700,7 @@ property, locally or anywhere up in the hierarchy."
            (save-buffer))
          (kill-buffer buf)
          (message "Export done."))
-      (error "TABLE_EXPORT_FORMAT invalid"))))
+      (user-error "TABLE_EXPORT_FORMAT invalid"))))
 
 (defvar org-table-aligned-begin-marker (make-marker)
   "Marker at the beginning of the table last aligned.
@@ -660,6 +727,7 @@ When nil, simply write \"#ERROR\" in corrupted fields.")
 (defconst org-narrow-column-arrow "=>"
   "Used as display property in narrowed table columns.")
 
+;;;###autoload
 (defun org-table-align ()
   "Align the table at point by aligning all vertical bars."
   (interactive)
@@ -695,7 +763,7 @@ When nil, simply write \"#ERROR\" in corrupted fields.")
                    (re-search-forward org-emph-re end t)))
     (goto-char beg)
     (setq raise (and org-use-sub-superscripts
-                   (re-search-forward org-match-substring-regexp end t)))
+                    (re-search-forward org-match-substring-regexp end t)))
     (goto-char beg)
     (setq dates (and org-display-custom-times
                     (re-search-forward org-ts-regexp-both end t)))
@@ -732,7 +800,7 @@ When nil, simply write \"#ERROR\" in corrupted fields.")
     ;; Get the data fields by splitting the lines.
     (setq fields (mapcar
                  (lambda (l)
-                     (org-split-string l " *| *"))
+                   (org-split-string l " *| *"))
                  (delq nil (copy-sequence lines))))
     ;; How many fields in the longest line?
     (condition-case nil
@@ -740,7 +808,7 @@ When nil, simply write \"#ERROR\" in corrupted fields.")
       (error
        (kill-region beg end)
        (org-table-create org-table-default-size)
-       (error "Empty table - created default table")))
+       (user-error "Empty table - created default table")))
     ;; A list of empty strings to fill any short rows on output
     (setq emptystrings (make-list maxfields ""))
     ;; Check for special formatting.
@@ -764,10 +832,10 @@ When nil, simply write \"#ERROR\" in corrupted fields.")
                           (> (org-string-width xx) fmax))
                  (org-add-props xx nil
                    'help-echo
-                   (concat "Clipped table field, use C-c ` to edit. Full value is:\n" (org-no-properties (copy-sequence xx))))
+                   (concat "Clipped table field, use C-c ` to edit.  Full value is:\n" (org-no-properties (copy-sequence xx))))
                  (setq f1 (min fmax (or (string-match org-bracket-link-regexp xx) fmax)))
                  (unless (> f1 1)
-                   (error "Cannot narrow field starting with wide link \"%s\""
+                   (user-error "Cannot narrow field starting with wide link \"%s\""
                           (match-string 0 xx)))
                  (add-text-properties f1 (length xx) (list 'org-cwidth t) xx)
                  (add-text-properties (- f1 2) f1
@@ -833,19 +901,21 @@ When nil, simply write \"#ERROR\" in corrupted fields.")
     (delete-region (point) end)
     (move-marker end nil)
     (move-marker org-table-aligned-end-marker (point))
-    (when (and orgtbl-mode (not (eq major-mode 'org-mode)))
+    (when (and orgtbl-mode (not (derived-mode-p 'org-mode)))
       (goto-char org-table-aligned-begin-marker)
       (while (org-hide-wide-columns org-table-aligned-end-marker)))
     ;; Try to move to the old location
     (org-goto-line winstartline)
     (setq winstart (point-at-bol))
     (org-goto-line linepos)
-    (set-window-start (selected-window) winstart 'noforce)
+    (when (eq (window-buffer (selected-window)) (current-buffer))
+      (set-window-start (selected-window) winstart 'noforce))
     (org-table-goto-column colpos)
     (and org-table-overlay-coordinates (org-table-overlay-coordinates))
     (setq org-table-may-need-update nil)
     ))
 
+;;;###autoload
 (defun org-table-begin (&optional table-type)
   "Find the beginning of the table and return its position.
 With argument TABLE-TYPE, go to the beginning of a table.el-type table."
@@ -859,6 +929,7 @@ With argument TABLE-TYPE, go to the beginning of a table.el-type table."
       (beginning-of-line 2)
       (point))))
 
+;;;###autoload
 (defun org-table-end (&optional table-type)
   "Find the end of the table and return its position.
 With argument TABLE-TYPE, go to the end of a table.el-type table."
@@ -871,6 +942,7 @@ With argument TABLE-TYPE, go to the end of a table.el-type table."
       (goto-char (match-beginning 0)))
     (point-marker)))
 
+;;;###autoload
 (defun org-table-justify-field-maybe (&optional new)
   "Justify the current field, text to left, number to right.
 Optional argument NEW may specify text to replace the current field content."
@@ -911,6 +983,7 @@ Optional argument NEW may specify text to replace the current field content."
          (setq org-table-may-need-update t))
        (goto-char pos))))))
 
+;;;###autoload
 (defun org-table-next-field ()
   "Go to the next field in the current table, creating new lines as needed.
 Before doing so, re-align the table if necessary."
@@ -940,6 +1013,7 @@ Before doing so, re-align the table if necessary."
       (error
        (org-table-insert-row 'below)))))
 
+;;;###autoload
 (defun org-table-previous-field ()
   "Go to the previous field in the table.
 Before doing so, re-align the table if necessary."
@@ -955,7 +1029,7 @@ Before doing so, re-align the table if necessary."
       (progn
        (re-search-backward "|" (org-table-begin))
        (re-search-backward "|" (org-table-begin)))
-    (error (error "Cannot move to previous table field")))
+    (error (user-error "Cannot move to previous table field")))
   (while (looking-at "|\\(-\\|[ \t]*$\\)")
     (re-search-backward "|" (org-table-begin)))
   (if (looking-at "| ?")
@@ -971,7 +1045,7 @@ With numeric argument N, move N-1 fields forward first."
       (setq n (1- n))
       (org-table-previous-field))
     (if (not (re-search-backward "|" (point-at-bol 0) t))
-       (error "No more table fields before the current")
+       (user-error "No more table fields before the current")
       (goto-char (match-end 0))
       (and (looking-at " ") (forward-char 1)))
     (if (>= (point) pos) (org-table-beginning-of-field 2))))
@@ -993,6 +1067,7 @@ With numeric argument N, move N-1 fields backward first."
          (forward-char 1)))
     (if (<= (point) pos) (org-table-end-of-field 2))))
 
+;;;###autoload
 (defun org-table-next-row ()
   "Go to the next row (same column) in the current table.
 Before doing so, re-align the table if necessary."
@@ -1016,6 +1091,7 @@ Before doing so, re-align the table if necessary."
       (skip-chars-backward "^|\n\r")
       (if (looking-at " ") (forward-char 1)))))
 
+;;;###autoload
 (defun org-table-copy-down (n)
   "Copy a field down in the current column.
 If the field at the cursor is empty, copy into it the content of
@@ -1030,7 +1106,7 @@ copying.  In the case of a timestamp, increment by one day."
   (interactive "p")
   (let* ((colpos (org-table-current-column))
         (col (current-column))
-        (field (org-table-get-field))
+        (field (save-excursion (org-table-get-field)))
         (non-empty (string-match "[^ \t]" field))
         (beg (org-table-begin))
         (orig-n n)
@@ -1066,7 +1142,7 @@ copying.  In the case of a timestamp, increment by one day."
            (org-table-maybe-recalculate-line))
          (org-table-align)
          (org-move-to-column col))
-      (error "No non-empty field found"))))
+      (user-error "No non-empty field found"))))
 
 (defun org-table-check-inside-data-field (&optional noerror)
   "Is point inside a table data field?
@@ -1078,7 +1154,7 @@ This actually throws an error, so it aborts the current command."
          (looking-at "[ \t]*$"))
       (if noerror
          nil
-       (error "Not in table data field"))
+       (user-error "Not in table data field"))
     t))
 
 (defvar org-table-clip nil
@@ -1125,6 +1201,7 @@ Return t when the line exists, nil if it does not exist."
                (< (setq cnt (1+ cnt)) N)))
     (= cnt N)))
 
+;;;###autoload
 (defun org-table-blank-field ()
   "Blank the current table field or active region."
   (interactive)
@@ -1160,9 +1237,11 @@ is always the old value."
        val)
     (forward-char 1) ""))
 
+;;;###autoload
 (defun org-table-field-info (arg)
   "Show info about the current field, and highlight any reference at point."
   (interactive "P")
+  (unless (org-at-table-p) (user-error "Not at a table"))
   (org-table-get-specials)
   (save-excursion
     (let* ((pos (point))
@@ -1215,6 +1294,7 @@ is always the old value."
        (message "In table column %d" cnt))
       cnt)))
 
+;;;###autoload
 (defun org-table-current-dline ()
   "Find out what table data line we are in.
 Only data lines count for this."
@@ -1231,6 +1311,7 @@ Only data lines count for this."
        (message "This is table line %d" cnt))
       cnt)))
 
+;;;###autoload
 (defun org-table-goto-column (n &optional on-delim force)
   "Move the cursor to the Nth column in the current table line.
 With optional argument ON-DELIM, stop with point before the left delimiter
@@ -1253,11 +1334,12 @@ However, when FORCE is non-nil, create new columns if necessary."
        (backward-char 1)
       (if (looking-at " ") (forward-char 1)))))
 
+;;;###autoload
 (defun org-table-insert-column ()
   "Insert a new column into the table."
   (interactive)
   (if (not (org-at-table-p))
-      (error "Not at a table"))
+      (user-error "Not at a table"))
   (org-table-find-dataline)
   (let* ((col (max 1 (org-table-current-column)))
         (beg (org-table-begin))
@@ -1297,7 +1379,7 @@ However, when FORCE is non-nil, create new columns if necessary."
       (if (and (org-at-table-p)
               (not (org-at-table-hline-p)))
          t
-       (error
+       (user-error
         "Please position cursor in a data line for column operations")))))
 
 (defun org-table-line-to-dline (line &optional above)
@@ -1319,14 +1401,15 @@ first dline below it is used.  When ABOVE is non-nil, the one above is used."
        (while (< i ll)
          (if (>= (aref org-table-dlines i) line)
              (throw 'exit i))
-       (setq i (1+ i)))))
-      nil))
+         (setq i (1+ i)))))
+    nil))
 
+;;;###autoload
 (defun org-table-delete-column ()
   "Delete a column from the table."
   (interactive)
   (if (not (org-at-table-p))
-      (error "Not at a table"))
+      (user-error "Not at a table"))
   (org-table-find-dataline)
   (org-table-check-inside-data-field)
   (let* ((col (org-table-current-column))
@@ -1354,20 +1437,23 @@ first dline below it is used.  When ABOVE is non-nil, the one above is used."
       (org-table-fix-formulas "$LR" (list (cons (number-to-string col) "INVALID"))
                              col -1 col))))
 
+;;;###autoload
 (defun org-table-move-column-right ()
   "Move column to the right."
   (interactive)
   (org-table-move-column nil))
+;;;###autoload
 (defun org-table-move-column-left ()
   "Move column to the left."
   (interactive)
   (org-table-move-column 'left))
 
+;;;###autoload
 (defun org-table-move-column (&optional left)
   "Move the current column to the right.  With arg LEFT, move to the left."
   (interactive "P")
   (if (not (org-at-table-p))
-      (error "Not at a table"))
+      (user-error "Not at a table"))
   (org-table-find-dataline)
   (org-table-check-inside-data-field)
   (let* ((col (org-table-current-column))
@@ -1378,9 +1464,9 @@ first dline below it is used.  When ABOVE is non-nil, the one above is used."
         (linepos (org-current-line))
         (colpos (if left (1- col) (1+ col))))
     (if (and left (= col 1))
-       (error "Cannot move column further left"))
+       (user-error "Cannot move column further left"))
     (if (and (not left) (looking-at "[^|\n]*|[^|\n]*$"))
-       (error "Cannot move column further right"))
+       (user-error "Cannot move column further right"))
     (goto-char beg)
     (while (< (point) end)
       (if (org-at-table-hline-p)
@@ -1402,15 +1488,18 @@ first dline below it is used.  When ABOVE is non-nil, the one above is used."
        "$LR" (list (cons (number-to-string col) (number-to-string colpos))
                   (cons (number-to-string colpos) (number-to-string col)))))))
 
+;;;###autoload
 (defun org-table-move-row-down ()
   "Move table row down."
   (interactive)
   (org-table-move-row nil))
+;;;###autoload
 (defun org-table-move-row-up ()
   "Move table row up."
   (interactive)
   (org-table-move-row 'up))
 
+;;;###autoload
 (defun org-table-move-row (&optional up)
   "Move the current table line down.  With arg UP, move it up."
   (interactive "P")
@@ -1425,7 +1514,7 @@ first dline below it is used.  When ABOVE is non-nil, the one above is used."
     (beginning-of-line tonew)
     (unless (org-at-table-p)
       (goto-char pos)
-      (error "Cannot move row further"))
+      (user-error "Cannot move row further"))
     (setq hline2p (looking-at org-table-hline-regexp))
     (goto-char pos)
     (beginning-of-line 1)
@@ -1444,12 +1533,13 @@ first dline below it is used.  When ABOVE is non-nil, the one above is used."
        "@" (list (cons (number-to-string dline1) (number-to-string dline2))
                 (cons (number-to-string dline2) (number-to-string dline1)))))))
 
+;;;###autoload
 (defun org-table-insert-row (&optional arg)
   "Insert a new row above the current line into the table.
 With prefix ARG, insert below the current line."
   (interactive "P")
   (if (not (org-at-table-p))
-      (error "Not at a table"))
+      (user-error "Not at a table"))
   (let* ((line (buffer-substring (point-at-bol) (point-at-eol)))
         (new (org-table-clean-line line)))
     ;; Fix the first field if necessary
@@ -1465,12 +1555,13 @@ With prefix ARG, insert below the current line."
              (funcall org-table-fix-formulas-confirm "Fix formulas? "))
       (org-table-fix-formulas "@" nil (1- (org-table-current-dline)) 1))))
 
+;;;###autoload
 (defun org-table-insert-hline (&optional above)
   "Insert a horizontal-line below the current line into the table.
 With prefix ABOVE, insert above the current line."
   (interactive "P")
   (if (not (org-at-table-p))
-      (error "Not at a table"))
+      (user-error "Not at a table"))
   (when (eobp) (insert "\n") (backward-char 1))
   (if (not (string-match "|[ \t]*$" (org-current-line-string)))
       (org-table-align))
@@ -1488,6 +1579,7 @@ With prefix ABOVE, insert above the current line."
     (org-move-to-column col)
     (and org-table-overlay-coordinates (org-table-align))))
 
+;;;###autoload
 (defun org-table-hline-and-move (&optional same-column)
   "Insert a hline and move to the row below that line."
   (interactive "P")
@@ -1514,11 +1606,12 @@ In particular, this does handle wide and invisible characters."
               t t s)))
     s))
 
+;;;###autoload
 (defun org-table-kill-row ()
   "Delete the current row or horizontal line from the table."
   (interactive)
   (if (not (org-at-table-p))
-      (error "Not at a table"))
+      (user-error "Not at a table"))
   (let ((col (current-column))
        (dline (org-table-current-dline)))
     (kill-region (point-at-bol) (min (1+ (point-at-eol)) (point-max)))
@@ -1529,6 +1622,7 @@ In particular, this does handle wide and invisible characters."
       (org-table-fix-formulas "@" (list (cons (number-to-string dline) "INVALID"))
                              dline -1 dline))))
 
+;;;###autoload
 (defun org-table-sort-lines (with-case &optional sorting-type)
   "Sort table lines according to the column at point.
 
@@ -1553,6 +1647,7 @@ should be done in reverse order."
   (interactive "P")
   (let* ((thisline (org-current-line))
         (thiscol (org-table-current-column))
+        (otc org-table-overlay-coordinates)
         beg end bcol ecol tend tbeg column lns pos)
     (when (equal thiscol 0)
       (if (org-called-interactively-p 'any)
@@ -1601,15 +1696,18 @@ should be done in reverse order."
                                  x))
                      (org-split-string (buffer-substring beg end) "\n")))
     (setq lns (org-do-sort lns "Table" with-case sorting-type))
+    (when org-table-overlay-coordinates
+      (org-table-toggle-coordinate-overlays))
     (delete-region beg end)
     (move-marker beg nil)
     (move-marker end nil)
     (insert (mapconcat 'cdr lns "\n") "\n")
     (org-goto-line thisline)
     (org-table-goto-column thiscol)
+    (when otc (org-table-toggle-coordinate-overlays))
     (message "%d lines sorted, based on column %d" (length lns) column)))
 
-
+;;;###autoload
 (defun org-table-cut-region (beg end)
   "Copy region in table to the clipboard and blank all relevant fields.
 If there is no active region, use just the field at point."
@@ -1618,6 +1716,7 @@ If there is no active region, use just the field at point."
                (if (org-region-active-p) (region-end) (point))))
   (org-table-copy-region beg end 'cut))
 
+;;;###autoload
 (defun org-table-copy-region (beg end &optional cut)
   "Copy rectangular region in table to clipboard.
 A special clipboard is used which can only be accessed
@@ -1627,8 +1726,8 @@ with `org-table-paste-rectangle'."
                (if (org-region-active-p) (region-end) (point))
                current-prefix-arg))
   (let* (l01 c01 l02 c02 l1 c1 l2 c2 ic1 ic2
-        region cols
-        (rpl (if cut "  " nil)))
+            region cols
+            (rpl (if cut "  " nil)))
     (goto-char beg)
     (org-table-check-inside-data-field)
     (setq l01 (org-current-line)
@@ -1655,6 +1754,7 @@ with `org-table-paste-rectangle'."
     (if cut (org-table-align))
     org-table-clip))
 
+;;;###autoload
 (defun org-table-paste-rectangle ()
   "Paste a rectangular region into a table.
 The upper right corner ends up in the current field.  All involved fields
@@ -1663,7 +1763,7 @@ the table is enlarged as needed.  The process ignores horizontal separator
 lines."
   (interactive)
   (unless (and org-table-clip (listp org-table-clip))
-    (error "First cut/copy a region to paste!"))
+    (user-error "First cut/copy a region to paste!"))
   (org-table-check-inside-data-field)
   (let* ((clip org-table-clip)
         (line (org-current-line))
@@ -1685,6 +1785,7 @@ lines."
     (org-table-goto-column col)
     (org-table-align)))
 
+;;;###autoload
 (defun org-table-convert ()
   "Convert from `org-mode' table to table.el and back.
 Obviously, this only works within limits.  When an Org-mode table is
@@ -1748,16 +1849,22 @@ will be transposed as
 
 Note that horizontal lines disappeared."
   (interactive)
-  (let ((contents
-         (apply #'mapcar* #'list
-                ;; remove 'hline from list
-               (delq nil (mapcar (lambda (x) (when (listp x) x))
-                                 (org-table-to-lisp))))))
+  (let* ((table (delete 'hline (org-table-to-lisp)))
+        (contents (mapcar (lambda (p)
+                            (let ((tp table))
+                              (mapcar
+                               (lambda (rown)
+                                 (prog1
+                                     (pop (car tp))
+                                   (setq tp (cdr tp))))
+                               table)))
+                          (car table))))
     (delete-region (org-table-begin) (org-table-end))
     (insert (mapconcat (lambda(x) (concat "| " (mapconcat 'identity x " | " ) "  |\n" ))
                        contents ""))
     (org-table-align)))
 
+;;;###autoload
 (defun org-table-wrap-region (arg)
   "Wrap several fields in a column like a paragraph.
 This is useful if you'd like to spread the contents of a field over several
@@ -1790,7 +1897,7 @@ blank, and the content is appended to the field above."
             nlines)
        (org-table-cut-region (region-beginning) (region-end))
        (if (> (length (car org-table-clip)) 1)
-           (error "Region must be limited to single column"))
+           (user-error "Region must be limited to single column"))
        (setq nlines (if arg
                         (if (< arg 1)
                             (+ (length org-table-clip) arg)
@@ -1828,6 +1935,7 @@ blank, and the content is appended to the field above."
 
 (defvar org-field-marker nil)
 
+;;;###autoload
 (defun org-table-edit-field (arg)
   "Edit table field in a different window.
 This is mainly useful for fields that contain hidden parts.
@@ -1845,7 +1953,7 @@ it can be edited in place."
       (if (and (boundp 'font-lock-mode) font-lock-mode)
          (font-lock-fontify-block))))
    (t
-    (let ((pos (move-marker (make-marker) (point)))
+    (let ((pos (point-marker))
          (coord
           (if (eq org-table-use-standard-references t)
               (concat (org-number-to-letters (org-table-current-column))
@@ -1931,6 +2039,7 @@ table (but see `org-table-exit-follow-field-mode-when-leaving-table')."
 
 (defvar org-timecnt) ; dynamically scoped parameter
 
+;;;###autoload
 (defun org-table-sum (&optional beg end nlast)
   "Sum numbers in region of current table column.
 The result will be displayed in the echo area, and will be available
@@ -1957,12 +2066,12 @@ If NLAST is a number, only the NLAST fields will actually be summed."
        (setq col (org-table-current-column))
        (goto-char (org-table-begin))
        (unless (re-search-forward "^[ \t]*|[^-]" nil t)
-         (error "No table data"))
+         (user-error "No table data"))
        (org-table-goto-column col)
        (setq beg (point))
        (goto-char (org-table-end))
        (unless (re-search-backward "^[ \t]*|[^-]" nil t)
-         (error "No table data"))
+         (user-error "No table data"))
        (org-table-goto-column col)
        (setq end (point))))
       (let* ((items (apply 'append (org-table-copy-region beg end)))
@@ -1980,7 +2089,7 @@ If NLAST is a number, only the NLAST fields will actually be summed."
                           h (floor (/ diff 3600)) diff (mod diff 3600)
                           m (floor (/ diff 60)) diff (mod diff 60)
                           s diff)
-                    (format "%d:%02d:%02d" h m s))))
+                    (format "%.0f:%02.0f:%02.0f" h m s))))
        (kill-new sres)
        (if (org-called-interactively-p 'interactive)
            (message "%s"
@@ -2047,7 +2156,7 @@ When NAMED is non-nil, look for a named equation."
                 (int-to-string (org-table-current-column))))
         (dummy (and (or nameass refass) (not named)
                     (not (y-or-n-p "Replace existing field formula with column formula? " ))
-                    (error "Abort")))
+                    (message "Formula not replaced")))
         (name (or name ref))
         (org-table-may-need-update nil)
         (stored (cdr (assoc scol stored-list)))
@@ -2071,7 +2180,7 @@ When NAMED is non-nil, look for a named equation."
       ;; remove formula
       (setq stored-list (delq (assoc scol stored-list) stored-list))
       (org-table-store-formulas stored-list)
-      (error "Formula removed"))
+      (user-error "Formula removed"))
     (if (string-match "^ *=?" eq) (setq eq (replace-match "" t t eq)))
     (if (string-match " *$" eq) (setq eq (replace-match "" t t eq)))
     (if (and name (not named))
@@ -2088,22 +2197,23 @@ When NAMED is non-nil, look for a named equation."
 (defun org-table-store-formulas (alist)
   "Store the list of formulas below the current table."
   (setq alist (sort alist 'org-table-formula-less-p))
-  (save-excursion
-    (goto-char (org-table-end))
-    (if (looking-at "\\([ \t]*\n\\)*[ \t]*#\\+TBLFM:\\(.*\n?\\)")
-       (progn
-         ;; don't overwrite TBLFM, we might use text properties to store stuff
-         (goto-char (match-beginning 2))
-         (delete-region (match-beginning 2) (match-end 0)))
-      (org-indent-line-function)
-      (insert "#+TBLFM:"))
-    (insert " "
-           (mapconcat (lambda (x)
-                        (concat
-                         (if (equal (string-to-char (car x)) ?@) "" "$")
-                         (car x) "=" (cdr x)))
-                      alist "::")
-           "\n")))
+  (let ((case-fold-search t))
+    (save-excursion
+      (goto-char (org-table-end))
+      (if (looking-at "\\([ \t]*\n\\)*[ \t]*\\(#\\+tblfm:\\)\\(.*\n?\\)")
+         (progn
+           ;; don't overwrite TBLFM, we might use text properties to store stuff
+           (goto-char (match-beginning 3))
+           (delete-region (match-beginning 3) (match-end 0)))
+       (org-indent-line)
+       (insert (or (match-string 2) "#+TBLFM:")))
+      (insert " "
+             (mapconcat (lambda (x)
+                          (concat
+                           (if (equal (string-to-char (car x)) ?@) "" "$")
+                           (car x) "=" (cdr x)))
+                        alist "::")
+             "\n"))))
 
 (defsubst org-table-formula-make-cmp-string (a)
   (when (string-match "\\`$[<>]" a)
@@ -2130,13 +2240,14 @@ When NAMED is non-nil, look for a named equation."
        (bs (org-table-formula-make-cmp-string (car b))))
     (and as bs (string< as bs))))
 
+;;;###autoload
 (defun org-table-get-stored-formulas (&optional noerror)
   "Return an alist with the stored formulas directly after current table."
-  (interactive)
-  (let (scol eq eq-alist strings string seen)
+  (interactive) ;; FIXME interactive?
+  (let ((case-fold-search t) scol eq eq-alist strings string seen)
     (save-excursion
       (goto-char (org-table-end))
-      (when (looking-at "\\([ \t]*\n\\)*[ \t]*#\\+TBLFM: *\\(.*\\)")
+      (when (looking-at "\\([ \t]*\n\\)*[ \t]*#\\+tblfm: *\\(.*\\)")
        (setq strings (org-split-string (org-match-string-no-properties 2)
                                        " *:: *"))
        (while (setq string (pop strings))
@@ -2154,7 +2265,7 @@ When NAMED is non-nil, look for a named equation."
                      (message "Double definition `$%s=' in TBLFM line, please fix by hand" scol)
                      (ding)
                      (sit-for 2))
-                 (error "Double definition `$%s=' in TBLFM line, please fix by hand" scol))
+                 (user-error "Double definition `$%s=' in TBLFM line, please fix by hand" scol))
              (push scol seen))))))
     (nreverse eq-alist)))
 
@@ -2164,8 +2275,9 @@ KEY is \"@\" or \"$\".  REPLACE is an alist of numbers to replace.
 For all numbers larger than LIMIT, shift them by DELTA."
   (save-excursion
     (goto-char (org-table-end))
-    (when (looking-at "[ \t]*#\\+TBLFM:")
-      (let ((re (concat key "\\([0-9]+\\)"))
+    (while (let ((case-fold-search t)) (looking-at "[ \t]*#\\+tblfm:"))
+      (let ((msg "The formulas in #+TBLFM have been updated")
+           (re (concat key "\\([0-9]+\\)"))
            (re2
             (when remove
               (if (or (equal key "$") (equal key "$LR"))
@@ -2177,18 +2289,21 @@ For all numbers larger than LIMIT, shift them by DELTA."
          (while (re-search-forward re2 (point-at-eol) t)
            (unless (save-match-data (org-in-regexp "remote([^)]+?)"))
              (if (equal (char-before (match-beginning 0)) ?.)
-                 (error "Change makes TBLFM term %s invalid.  Use undo to recover."
-                        (match-string 0))
+                 (user-error
+                  "Change makes TBLFM term %s invalid, use undo to recover"
+                  (match-string 0))
                (replace-match "")))))
        (while (re-search-forward re (point-at-eol) t)
          (unless (save-match-data (org-in-regexp "remote([^)]+?)"))
            (setq s (match-string 1) n (string-to-number s))
            (cond
             ((setq a (assoc s replace))
-             (replace-match (concat key (cdr a)) t t))
+             (replace-match (concat key (cdr a)) t t)
+             (message msg))
             ((and limit (> n limit))
-             (replace-match (concat key (int-to-string (+ n delta)))
-                            t t)))))))))
+             (replace-match (concat key (int-to-string (+ n delta))) t t)
+             (message msg))))))
+      (forward-line))))
 
 (defun org-table-get-specials ()
   "Get the column names and local parameters for this table."
@@ -2234,8 +2349,8 @@ For all numbers larger than LIMIT, shift them by DELTA."
          (setq v (pop fields1) col (1+ col))
          (when (and (stringp field) (stringp v)
                     (string-match "^[a-zA-Z][_a-zA-Z0-9]*$" field))
-             (push (cons field v) org-table-local-parameters)
-             (push (list field line col) org-table-named-field-locations))))
+           (push (cons field v) org-table-local-parameters)
+           (push (list field line col) org-table-named-field-locations))))
       ;; Analyse the line types
       (goto-char beg)
       (setq org-table-current-begin-line (org-current-line)
@@ -2267,6 +2382,7 @@ For all numbers larger than LIMIT, shift them by DELTA."
        (setq org-table-local-parameters
              (append org-table-local-parameters al2))))))
 
+;;;###autoload
 (defun org-table-maybe-eval-formula ()
   "Check if the current field starts with \"=\" or \":=\".
 If yes, store the formula and apply it."
@@ -2275,14 +2391,14 @@ If yes, store the formula and apply it."
   (when org-table-formula-evaluate-inline
     (let* ((field (org-trim (or (org-table-get-field) "")))
           named eq)
-      (when (string-match "^:?=\\(.*\\)" field)
+      (when (string-match "^:?=\\(.*[^=]\\)$" field)
        (setq named (equal (string-to-char field) ?:)
              eq (match-string 1 field))
        (if (or (fboundp 'calc-eval)
                (equal (substring eq 0 (min 2 (length eq))) "'("))
            (org-table-eval-formula (if named '(4) nil)
                                    (org-table-formula-from-user eq))
-         (error "Calc does not seem to be installed, and is needed to evaluate the formula"))))))
+         (user-error "Calc does not seem to be installed, and is needed to evaluate the formula"))))))
 
 (defvar org-recalc-commands nil
   "List of commands triggering the recalculation of a line.
@@ -2292,11 +2408,12 @@ Will be filled automatically during use.")
   '((" " . "Unmarked: no special line, no automatic recalculation")
     ("#" . "Automatically recalculate this line upon TAB, RET, and C-c C-c in the line")
     ("*" . "Recalculate only when entire table is recalculated with `C-u C-c *'")
-    ("!" . "Column name definition line. Reference in formula as $name.")
-    ("$" . "Parameter definition line name=value. Reference in formula as $name.")
+    ("!" . "Column name definition line.  Reference in formula as $name.")
+    ("$" . "Parameter definition line name=value.  Reference in formula as $name.")
     ("_" . "Names for values in row below this one.")
     ("^" . "Names for values in row above this one.")))
 
+;;;###autoload
 (defun org-table-rotate-recalc-marks (&optional newchar)
   "Rotate the recalculation mark in the first column.
 If in any row, the first field is not consistent with a mark,
@@ -2306,7 +2423,7 @@ after prompting for the marking character.
 After each change, a message will be displayed indicating the meaning
 of the new mark."
   (interactive)
-  (unless (org-at-table-p) (error "Not at a table"))
+  (unless (org-at-table-p) (user-error "Not at a table"))
   (let* ((marks (append (mapcar 'car org-recalc-marks) '(" ")))
         (beg (org-table-begin))
         (end (org-table-end))
@@ -2325,13 +2442,13 @@ of the new mark."
       (setq newchar (char-to-string (read-char-exclusive))
            forcenew (car (assoc newchar org-recalc-marks))))
     (if (and newchar (not forcenew))
-       (error "Invalid NEWCHAR `%s' in `org-table-rotate-recalc-marks'"
+       (user-error "Invalid NEWCHAR `%s' in `org-table-rotate-recalc-marks'"
               newchar))
     (if l1 (org-goto-line l1))
     (save-excursion
       (beginning-of-line 1)
       (unless (looking-at org-table-dataline-regexp)
-       (error "Not at a table data line")))
+       (user-error "Not at a table data line")))
     (unless have-col
       (org-table-goto-column 1)
       (org-table-insert-column)
@@ -2358,6 +2475,7 @@ of the new mark."
     (and (org-called-interactively-p 'interactive)
         (message "%s" (cdr (assoc new org-recalc-marks))))))
 
+;;;###autoload
 (defun org-table-maybe-recalculate-line ()
   "Recompute the current line if marked for it, and if we haven't just done it."
   (interactive)
@@ -2368,7 +2486,7 @@ of the new mark."
                       (looking-at org-table-auto-recalculate-regexp))
        (org-table-recalculate) t))
 
-(defvar org-table-modes)
+(defvar org-tbl-calc-modes) ;; Dynamically bound in `org-table-eval-formula'
 (defsubst org-set-calc-mode (var &optional value)
   (if (stringp var)
       (setq var (assoc var '(("D" calc-angle-mode deg)
@@ -2376,11 +2494,12 @@ of the new mark."
                             ("F" calc-prefer-frac t)
                             ("S" calc-symbolic-mode t)))
            value (nth 2 var) var (nth 1 var)))
-  (if (memq var org-table-modes)
-      (setcar (cdr (memq var org-table-modes)) value)
-    (cons var (cons value org-table-modes)))
-  org-table-modes)
+  (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)
 
+;;;###autoload
 (defun org-table-eval-formula (&optional arg equation
                                         suppress-align suppress-const
                                         suppress-store suppress-analysis)
@@ -2424,7 +2543,7 @@ not overwrite the stored one."
   (or suppress-analysis (org-table-get-specials))
   (if (equal arg '(16))
       (let ((eq (org-table-current-field-formula)))
-       (or eq (error "No equation active for current field"))
+       (or eq (user-error "No equation active for current field"))
        (org-table-get-field nil eq)
        (org-table-align)
        (setq org-table-may-need-update t))
@@ -2437,7 +2556,7 @@ not overwrite the stored one."
                        equation
                      (org-table-get-formula equation (equal arg '(4)))))
           (n0 (org-table-current-column))
-          (modes (copy-sequence org-calc-default-modes))
+          (org-tbl-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
@@ -2453,12 +2572,13 @@ not overwrite the stored one."
              (setq c (string-to-char (match-string 1 fmt))
                    n (string-to-number (match-string 2 fmt)))
              (if (= c ?p)
-                 (setq modes (org-set-calc-mode 'calc-internal-prec n))
-               (setq modes (org-set-calc-mode
-                            'calc-float-format
-                            (list (cdr (assoc c '((?n . float) (?f . fix)
-                                                  (?s . sci) (?e . eng))))
-                                  n))))
+                 (setq org-tbl-calc-modes (org-set-calc-mode 'calc-internal-prec n))
+               (setq org-tbl-calc-modes
+                     (org-set-calc-mode
+                      'calc-float-format
+                      (list (cdr (assoc c '((?n . float) (?f . fix)
+                                            (?s . sci) (?e . eng))))
+                            n))))
              (setq fmt (replace-match "" t t fmt)))
            (if (string-match "T" fmt)
                (setq duration t numbers t
@@ -2479,7 +2599,7 @@ not overwrite the stored one."
                (setq keep-empty t
                      fmt (replace-match "" t t fmt)))
            (while (string-match "[DRFS]" fmt)
-             (setq modes (org-set-calc-mode (match-string 0 fmt)))
+             (setq org-tbl-calc-modes (org-set-calc-mode (match-string 0 fmt)))
              (setq fmt (replace-match "" t t fmt)))
            (unless (string-match "\\S-" fmt)
              (setq fmt nil))))
@@ -2488,8 +2608,7 @@ not overwrite the stored one."
       (setq orig (or (get-text-property 1 :orig-formula formula) "?"))
       (while (> ndown 0)
        (setq fields (org-split-string
-                     (org-no-properties
-                      (buffer-substring (point-at-bol) (point-at-eol)))
+                     (buffer-substring-no-properties (point-at-bol) (point-at-eol))
                      " *| *"))
        ;; replace fields with duration values if relevant
        (if duration
@@ -2498,7 +2617,10 @@ not overwrite the stored one."
                          fields)))
        (if (eq numbers t)
            (setq fields (mapcar
-                         (lambda (x) (number-to-string (string-to-number x)))
+                         (lambda (x)
+                           (if (string-match "\\S-" x)
+                               (number-to-string (string-to-number x))
+                             x))
                          fields)))
        (setq ndown (1- ndown))
        (setq form (copy-sequence formula)
@@ -2553,7 +2675,7 @@ not overwrite the stored one."
          (if (not (save-match-data
                     (string-match (regexp-quote form) formrpl)))
              (setq form (replace-match formrpl t t form))
-           (error "Spreadsheet error: invalid reference \"%s\"" form)))
+           (user-error "Spreadsheet error: invalid reference \"%s\"" form)))
        ;; Insert simple ranges
        (while (string-match "\\$\\([0-9]+\\)\\.\\.\\$\\([0-9]+\\)"  form)
          (setq form
@@ -2571,11 +2693,12 @@ not overwrite the stored one."
          (setq n (+ (string-to-number (match-string 1 form))
                     (if (match-end 2) n0 0))
                x (nth (1- (if (= n 0) n0 (max n 1))) fields))
-         (unless x (error "Invalid field specifier \"%s\""
+         (unless x (user-error "Invalid field specifier \"%s\""
                           (match-string 0 form)))
          (setq form (replace-match
                      (save-match-data
-                       (org-table-make-reference x nil numbers lispp))
+                       (org-table-make-reference
+                        x keep-empty numbers lispp))
                      t t form)))
 
        (if lispp
@@ -2587,11 +2710,30 @@ not overwrite the stored one."
                                   (string-to-number ev)
                                   duration-output-format) ev))
          (or (fboundp 'calc-eval)
-             (error "Calc does not seem to be installed, and is needed to evaluate the formula"))
-         (setq ev (calc-eval (cons form modes) (if numbers 'num))
+             (user-error "Calc does not seem to be installed, and is needed to evaluate the formula"))
+         ;; Use <...> time-stamps so that Calc can handle them
+         (while (string-match (concat "\\[" org-ts-regexp1 "\\]") form)
+           (setq form (replace-match "<\\1>" nil nil form)))
+         ;; I18n-ize local time-stamps by setting (system-time-locale "C")
+         (when (string-match org-ts-regexp2 form)
+           (let* ((ts (match-string 0 form))
+                  (tsp (apply 'encode-time (save-match-data (org-parse-time-string ts))))
+                  (system-time-locale "C")
+                  (tf (or (and (save-match-data (string-match "[0-9]\\{1,2\\}:[0-9]\\{2\\}" ts))
+                               (cdr org-time-stamp-formats))
+                          (car org-time-stamp-formats))))
+             (setq form (replace-match (format-time-string tf tsp) t t form))))
+
+         (setq ev (if (and duration (string-match "^[0-9]+:[0-9]+\\(?::[0-9]+\\)?$" form))
+                      form
+                    (calc-eval (cons form org-tbl-calc-modes)
+                               (when (and (not keep-empty) numbers) 'num)))
                ev (if duration (org-table-time-seconds-to-string
-                                (string-to-number ev)
-                                duration-output-format) ev)))
+                                (if (string-match "^[0-9]+:[0-9]+\\(?::[0-9]+\\)?$" ev)
+                                    (string-to-number (org-table-time-string-to-seconds ev))
+                                  (string-to-number ev))
+                                duration-output-format)
+                    ev)))
 
        (when org-table-formula-debug
          (with-output-to-temp-buffer "*Substitution History*"
@@ -2601,7 +2743,7 @@ $xyz->  %s
 @r$c->  %s
 $1->    %s\n" orig formula form0 form))
            (if (listp ev)
-               (princ (format "       %s^\nError:  %s"
+               (princ (format "        %s^\nError:  %s"
                               (make-string (car ev) ?\-) (nth 1 ev)))
              (princ (format "Result: %s\nFormat: %s\nFinal:  %s"
                             ev (or fmt "NONE")
@@ -2612,7 +2754,7 @@ $1->    %s\n" orig formula form0 form))
            (unless (let (inhibit-redisplay)
                      (y-or-n-p "Debugging Formula.  Continue to next? "))
              (org-table-align)
-             (error "Abort"))
+             (user-error "Abort"))
            (delete-window bw)
            (message "")))
        (if (listp ev) (setq fmt nil ev "#ERROR"))
@@ -2650,7 +2792,7 @@ in the buffer and column1 and column2 are table column numbers."
     (let ((thisline (org-current-line))
          beg end c1 c2 r1 r2 rangep tmp)
       (unless (string-match org-table-range-regexp desc)
-       (error "Invalid table range specifier `%s'" desc))
+       (user-error "Invalid table range specifier `%s'" desc))
       (setq rangep (match-end 3)
            r1 (and (match-end 1) (match-string 1 desc))
            r2 (and (match-end 4) (match-string 4 desc))
@@ -2665,7 +2807,7 @@ in the buffer and column1 and column2 are table column numbers."
       (if (equal r2 "") (setq r2 nil))
       (if r1 (setq r1 (org-table-get-descriptor-line r1)))
       (if r2 (setq r2 (org-table-get-descriptor-line r2)))
-;      (setq r2 (or r2 r1) c2 (or c2 c1))
+                                       ;      (setq r2 (or r2 r1) c2 (or c2 c1))
       (if (not r1) (setq r1 thisline))
       (if (not r2) (setq r2 thisline))
       (if (or (not c1) (= 0 c1)) (setq c1 col))
@@ -2718,7 +2860,7 @@ and TABLE is a vector with line types."
         ;;                     1  2          3           4  5          6
         (and (not (match-end 3)) (not (match-end 6)))
         (and (match-end 3) (match-end 6) (not (match-end 5))))
-       (error "Invalid row descriptor `%s'" desc))
+       (user-error "Invalid row descriptor `%s'" desc))
     (let* ((hdir (and (match-end 2) (match-string 2 desc)))
           (hn (if (match-end 3) (- (match-end 3) (match-beginning 3)) nil))
           (odir (and (match-end 5) (match-string 5 desc)))
@@ -2732,7 +2874,7 @@ and TABLE is a vector with line types."
            (setq i 0 hdir "+")
            (if (eq (aref table 0) 'hline) (setq hn (1- hn)))))
       (if (and (not hn) on (not odir))
-         (error "Should never happen");;(aref org-table-dlines on)
+         (user-error "Should never happen");;(aref org-table-dlines on)
        (if (and hn (> hn 0))
            (setq i (org-table-find-row-type table i 'hline (equal hdir "-")
                                             nil hn cline desc)))
@@ -2752,41 +2894,56 @@ and TABLE is a vector with line types."
                      (cond
                       ((eq org-table-relative-ref-may-cross-hline t) t)
                       ((eq org-table-relative-ref-may-cross-hline 'error)
-                       (error "Row descriptor %s used in line %d crosses hline" desc cline))
+                       (user-error "Row descriptor %s used in line %d crosses hline" desc cline))
                       (t (setq i (- i (if backwards -1 1))
                                n 1)
                          nil))
                    t)))
       (setq n (1- n)))
     (if (or (< i 0) (>= i l))
-       (error "Row descriptor %s used in line %d leads outside table"
+       (user-error "Row descriptor %s used in line %d leads outside table"
               desc cline)
       i)))
 
 (defun org-table-rewrite-old-row-references (s)
   (if (string-match "&[-+0-9I]" s)
-      (error "Formula contains old &row reference, please rewrite using @-syntax")
+      (user-error "Formula contains old &row reference, please rewrite using @-syntax")
     s))
 
 (defun org-table-make-reference (elements keep-empty numbers lispp)
   "Convert list ELEMENTS to something appropriate to insert into formula.
 KEEP-EMPTY indicated to keep empty fields, default is to skip them.
 NUMBERS indicates that everything should be converted to numbers.
-LISPP means to return something appropriate for a Lisp list."
-  (if (stringp elements) ; just a single val
+LISPP non-nil means to return something appropriate for a Lisp
+list, 'literal is for the format specifier L."
+  ;; Calc nan (not a number) is used for the conversion of the empty
+  ;; field to a reference for several reasons: (i) It is accepted in a
+  ;; Calc formula (e. g. "" or "()" would result in a Calc error).
+  ;; (ii) In a single field (not in range) it can be distinguished
+  ;; from "(nan)" which is the reference made from a single field
+  ;; containing "nan".
+  (if (stringp elements)
+      ;; field reference
       (if lispp
          (if (eq lispp 'literal)
              elements
-           (prin1-to-string (if numbers (string-to-number elements) elements)))
-       (if (equal elements "") (setq elements "0"))
-       (if numbers (setq elements (number-to-string (string-to-number elements))))
-       (concat "(" elements ")"))
+           (if (and (eq elements "") (not keep-empty))
+               ""
+             (prin1-to-string
+              (if numbers (string-to-number elements) elements))))
+       (if (string-match "\\S-" elements)
+           (progn
+             (when numbers (setq elements (number-to-string
+                                           (string-to-number elements))))
+             (concat "(" elements ")"))
+         (if (or (not keep-empty) numbers) "(0)" "nan")))
+    ;; range reference
     (unless keep-empty
       (setq elements
            (delq nil
                  (mapcar (lambda (x) (if (string-match "\\S-" x) x nil))
                          elements))))
-    (setq elements (or elements '("0")))
+    (setq elements (or elements '()))  ; if delq returns nil then we need '()
     (if lispp
        (mapconcat
         (lambda (x)
@@ -2796,10 +2953,33 @@ LISPP means to return something appropriate for a Lisp list."
         elements " ")
       (concat "[" (mapconcat
                   (lambda (x)
-                    (if numbers (number-to-string (string-to-number x)) x))
+                    (if (string-match "\\S-" x)
+                        (if numbers
+                            (number-to-string (string-to-number x))
+                          x)
+                      (if (or (not keep-empty) numbers) "0" "nan")))
                   elements
                   ",") "]"))))
 
+;;;###autoload
+(defun org-table-set-constants ()
+  "Set `org-table-formula-constants-local' in the current buffer."
+  (let (cst consts const-str)
+    (save-excursion
+      (goto-char (point-min))
+      (while (re-search-forward "^[ \t]*#\\+CONSTANTS: \\(.*\\)" nil t)
+       (setq const-str (substring-no-properties (match-string 1)))
+       (setq consts (append consts (org-split-string const-str "[ \t]+")))
+       (when consts
+         (let (e)
+           (while (setq e (pop consts))
+             (when (string-match "^\\([a-zA-Z0][_a-zA-Z0-9]*\\)=\\(.*\\)" e)
+               (if (assoc-string (match-string 1 e) cst)
+                   (setq cst (delete (assoc-string (match-string 1 e) cst) cst)))
+               (push (cons (match-string 1 e) (match-string 2 e)) cst)))
+           (setq org-table-formula-constants-local cst)))))))
+
+;;;###autoload
 (defun org-table-recalculate (&optional all noalign)
   "Recalculate the current table line by applying all stored formulas.
 With prefix arg ALL, do this for all lines in the table.
@@ -2812,7 +2992,7 @@ known that the table will be realigned a little later anyway."
   (interactive "P")
   (or (memq this-command org-recalc-commands)
       (setq org-recalc-commands (cons this-command org-recalc-commands)))
-  (unless (org-at-table-p) (error "Not at a table"))
+  (unless (org-at-table-p) (user-error "Not at a table"))
   (if (or (eq all 'iterate) (equal all '(16)))
       (org-table-iterate)
     (org-table-get-specials)
@@ -2835,7 +3015,7 @@ known that the table will be realigned a little later anyway."
                                        (car x)) 1)
                                      (cdr x)))
                        (if (assoc (car x) eqlist1)
-                           (error "\"%s=\" formula tries to overwrite existing formula for column %s"
+                           (user-error "\"%s=\" formula tries to overwrite existing formula for column %s"
                                   lhs1 (car x))))
                      (cons
                       (org-table-formula-handle-first/last-rc (car x))
@@ -2880,7 +3060,7 @@ known that the table will be realigned a little later anyway."
        (if a (setq name1 (format "@%d$%d" (org-table-line-to-dline (nth 1 a))
                                  (nth 2 a))))
        (when (member name1 seen-fields)
-             (error "Several field/range formulas try to set %s" name1))
+         (user-error "Several field/range formulas try to set %s" name1))
        (push name1 seen-fields)
 
        (and (not a)
@@ -2889,7 +3069,7 @@ known that the table will be realigned a little later anyway."
                           (condition-case nil
                               (aref org-table-dlines
                                     (string-to-number (match-string 1 name)))
-                            (error (error "Invalid row number in %s"
+                            (error (user-error "Invalid row number in %s"
                                           name)))
                           (string-to-number (match-string 2 name)))))
        (when (and a (or all (equal (nth 1 a) thisline)))
@@ -2938,6 +3118,7 @@ known that the table will be realigned a little later anyway."
       (or noalign (and org-table-may-need-update (org-table-align))
          (and all (message "Re-applying formulas...done"))))))
 
+;;;###autoload
 (defun org-table-iterate (&optional arg)
   "Recalculate the table until it does not change anymore.
 The maximum number of iterations is 10, but you can choose a different value
@@ -2958,8 +3139,9 @@ with the prefix ARG."
              (message "Convergence after %d iterations" i)
            (message "Table was already stable"))
          (throw 'exit t)))
-      (error "No convergence after %d iterations" i))))
+      (user-error "No convergence after %d iterations" i))))
 
+;;;###autoload
 (defun org-table-recalculate-buffer-tables ()
   "Recalculate all tables in the current buffer."
   (interactive)
@@ -2968,27 +3150,60 @@ with the prefix ARG."
       (widen)
       (org-table-map-tables (lambda () (org-table-recalculate t)) t))))
 
+;;;###autoload
 (defun org-table-iterate-buffer-tables ()
   "Iterate all tables in the buffer, to converge inter-table dependencies."
- (interactive)
- (let* ((imax 10)
-        (checksum (md5 (buffer-string)))
-
-        c1
-        (i imax))
-   (save-excursion
-     (save-restriction
-       (widen)
-       (catch 'exit
-        (while (> i 0)
-          (setq i (1- i))
-          (org-table-map-tables (lambda () (org-table-recalculate t)) t)
-          (if (equal checksum (setq c1 (md5 (buffer-string))))
-              (progn
-                (message "Convergence after %d iterations" (- imax i))
-                (throw 'exit t))
-            (setq checksum c1)))
-        (error "No convergence after %d iterations" imax))))))
+  (interactive)
+  (let* ((imax 10)
+        (i imax)
+        (checksum (md5 (buffer-string)))
+        c1)
+    (save-excursion
+      (save-restriction
+       (widen)
+       (catch 'exit
+         (while (> i 0)
+           (setq i (1- i))
+           (org-table-map-tables (lambda () (org-table-recalculate t)) t)
+           (if (equal checksum (setq c1 (md5 (buffer-string))))
+               (progn
+                 (message "Convergence after %d iterations" (- imax i))
+                 (throw 'exit t))
+             (setq checksum c1)))
+         (user-error "No convergence after %d iterations" imax))))))
+
+(defun org-table-calc-current-TBLFM (&optional arg)
+  "Apply the #+TBLFM in the line at point to the table."
+  (interactive "P")
+  (unless (org-at-TBLFM-p) (user-error "Not at a #+TBLFM line"))
+  (let ((formula (buffer-substring
+                 (point-at-bol)
+                 (point-at-eol)))
+       s e)
+    (save-excursion
+      ;; Insert a temporary formula at right after the table
+      (goto-char (org-table-TBLFM-begin))
+      (setq s (point-marker))
+      (insert (concat formula "\n"))
+      (setq e (point-marker))
+      ;; Recalculate the table
+      (beginning-of-line 0)            ; move to the inserted line
+      (skip-chars-backward " \r\n\t")
+      (if (org-at-table-p)
+         (unwind-protect
+             (org-call-with-arg 'org-table-recalculate (or arg t))
+           ;; delete the formula inserted temporarily
+           (delete-region s e))))))
+
+(defun org-table-TBLFM-begin ()
+  "Find the beginning of the TBLFM lines and return its position.
+Return nil when the beginning of TBLFM line was not found."
+  (save-excursion
+    (when (progn (forward-line 1)
+             (re-search-backward
+              org-table-TBLFM-begin-regexp
+              nil t))
+         (point-at-bol 2))))
 
 (defun org-table-expand-lhs-ranges (equations)
   "Expand list of formulas.
@@ -2998,7 +3213,7 @@ them to individual field equations for each field."
     (while (setq e (pop equations))
       (setq lhs (car e) rhs (cdr e))
       (cond
-       ((string-match "^@-?[-+I0-9]+\\$-?[0-9]+$" lhs)
+       ((string-match "^@-?[-+0-9]+\\$-?[0-9]+$" lhs)
        ;; This just refers to one fixed field
        (push e res))
        ((string-match "^[a-zA-Z][_a-zA-Z0-9]*$" lhs)
@@ -3046,7 +3261,7 @@ borders of the table using the @< @> $< $> makers."
                    len
                  (- nmax len -1)))
        (if (or (< n 1) (> n nmax))
-           (error "Reference \"%s\" in expression \"%s\" points outside table"
+           (user-error "Reference \"%s\" in expression \"%s\" points outside table"
                   (match-string 0 s) s))
        (setq start (match-beginning 0))
        (setq s (replace-match (format "%s%d" (match-string 1 s) n) t t s)))))
@@ -3139,17 +3354,18 @@ Parameters get priority."
 
 (defvar org-pos)
 
+;;;###autoload
 (defun org-table-edit-formulas ()
   "Edit the formulas of the current table in a separate buffer."
   (interactive)
-  (when (save-excursion (beginning-of-line 1) (looking-at "[ \t]*#\\+TBLFM"))
+  (when (save-excursion (beginning-of-line 1) (let ((case-fold-search t)) (looking-at "[ \t]*#\\+TBLFM")))
     (beginning-of-line 0))
-  (unless (org-at-table-p) (error "Not at a table"))
+  (unless (org-at-table-p) (user-error "Not at a table"))
   (org-table-get-specials)
   (let ((key (org-table-current-field-formula 'key 'noerror))
        (eql (sort (org-table-get-stored-formulas 'noerror)
                   'org-table-formula-less-p))
-       (pos (move-marker (make-marker) (point)))
+       (pos (point-marker))
        (startline 1)
        (wc (current-window-configuration))
        (sel-win (selected-window))
@@ -3216,7 +3432,7 @@ Parameters get priority."
 Works for single references, but also for entire formulas and even the
 full TBLFM line."
   (let ((start 0))
-    (while (string-match "\\<\\([a-zA-Z]+\\)\\([0-9]+\\>\\|&\\)\\|\\(;[^\r\n:]+\\|\\<remote([^)]*)\\)" s start)
+    (while (string-match "\\<\\([a-zA-Z]+\\)\\([0-9]+\\>\\|&\\)\\|\\(;[^\r\n:]+\\|\\<remote([^,)]*)\\)" s start)
       (cond
        ((match-end 3)
        ;; format match, just advance
@@ -3267,8 +3483,8 @@ For example:  AB -> 28."
   (let ((n 0))
     (setq s (upcase s))
     (while (> (length s) 0)
-         (setq n (+ (* n 26) (string-to-char s) (- ?A) 1)
-               s (substring s 1)))
+      (setq n (+ (* n 26) (string-to-char s) (- ?A) 1)
+           s (substring s 1)))
     n))
 
 (defun org-number-to-letters (n)
@@ -3284,40 +3500,45 @@ For example:  28 -> AB."
   "Convert a time string into numerical duration in seconds.
 S can be a string matching either -?HH:MM:SS or -?HH:MM.
 If S is a string representing a number, keep this number."
-  (let (hour minus min sec res)
-    (cond
-     ((and (string-match "\\(-?\\)\\([0-9]+\\):\\([0-9]+\\):\\([0-9]+\\)" s))
-      (setq minus (< 0 (length (match-string 1 s)))
-           hour (string-to-number (match-string 2 s))
-           min (string-to-number (match-string 3 s))
-           sec (string-to-number (match-string 4 s)))
-      (if minus
-         (setq res (- (+ (* hour 3600) (* min 60) sec)))
-       (setq res (+ (* hour 3600) (* min 60) sec))))
-     ((and (not (string-match org-ts-regexp-both s))
-          (string-match "\\(-?\\)\\([0-9]+\\):\\([0-9]+\\)" s))
-      (setq minus (< 0 (length (match-string 1 s)))
-           hour (string-to-number (match-string 2 s))
-           min (string-to-number (match-string 3 s)))
-      (if minus
-         (setq res (- (+ (* hour 3600) (* min 60))))
-       (setq res (+ (* hour 3600) (* min 60)))))
-     (t (setq res (string-to-number s))))
-    (number-to-string res)))
+  (if (equal s "")
+      s
+    (let (hour minus min sec res)
+      (cond
+       ((and (string-match "\\(-?\\)\\([0-9]+\\):\\([0-9]+\\):\\([0-9]+\\)" s))
+       (setq minus (< 0 (length (match-string 1 s)))
+             hour (string-to-number (match-string 2 s))
+             min (string-to-number (match-string 3 s))
+             sec (string-to-number (match-string 4 s)))
+       (if minus
+           (setq res (- (+ (* hour 3600) (* min 60) sec)))
+         (setq res (+ (* hour 3600) (* min 60) sec))))
+       ((and (not (string-match org-ts-regexp-both s))
+            (string-match "\\(-?\\)\\([0-9]+\\):\\([0-9]+\\)" s))
+       (setq minus (< 0 (length (match-string 1 s)))
+             hour (string-to-number (match-string 2 s))
+             min (string-to-number (match-string 3 s)))
+       (if minus
+           (setq res (- (+ (* hour 3600) (* min 60))))
+         (setq res (+ (* hour 3600) (* min 60)))))
+       (t (setq res (string-to-number s))))
+      (number-to-string res))))
 
 (defun org-table-time-seconds-to-string (secs &optional output-format)
   "Convert a number of seconds to a time string.
 If OUTPUT-FORMAT is non-nil, return a number of days, hours,
 minutes or seconds."
-  (cond ((eq output-format 'days)
-        (format "%.3f" (/ (float secs) 86400)))
-       ((eq output-format 'hours)
-        (format "%.2f" (/ (float secs) 3600)))
-       ((eq output-format 'minutes)
-        (format "%.1f" (/ (float secs) 60)))
-       ((eq output-format 'seconds)
-        (format "%d" secs))
-       (t (org-format-seconds "%.2h:%.2m:%.2s" secs))))
+  (let* ((secs0 (abs secs))
+        (res
+         (cond ((eq output-format 'days)
+                (format "%.3f" (/ (float secs0) 86400)))
+               ((eq output-format 'hours)
+                (format "%.2f" (/ (float secs0) 3600)))
+               ((eq output-format 'minutes)
+                (format "%.1f" (/ (float secs0) 60)))
+               ((eq output-format 'seconds)
+                (format "%d" secs0))
+               (t (org-format-seconds "%.2h:%.2m:%.2s" secs0)))))
+    (if (< secs 0) (concat "-" res) res)))
 
 (defun org-table-fedit-convert-buffer (function)
   "Convert all references in this buffer, using FUNCTION."
@@ -3361,7 +3582,7 @@ minutes or seconds."
    ((org-at-regexp-p "\\(\\<[a-zA-Z]\\)&")
     (if (memq dir '(left right))
        (org-rematch-and-replace 1 (eq dir 'left))
-      (error "Cannot shift reference in this direction")))
+      (user-error "Cannot shift reference in this direction")))
    ((org-at-regexp-p "\\(\\<[a-zA-Z]\\{1,2\\}\\)\\([0-9]+\\)")
     ;; A B3-like reference
     (if (memq dir '(up down))
@@ -3376,7 +3597,7 @@ minutes or seconds."
 
 (defun org-rematch-and-replace (n &optional decr hline)
   "Re-match the group N, and replace it with the shifted reference."
-  (or (match-end n) (error "Cannot shift reference in this direction"))
+  (or (match-end n) (user-error "Cannot shift reference in this direction"))
   (goto-char (match-beginning n))
   (and (looking-at (regexp-quote (match-string n)))
        (replace-match (org-table-shift-refpart (match-string 0) decr hline)
@@ -3412,7 +3633,7 @@ a translation reference."
        (org-number-to-letters
         (max 1 (+ (org-letters-to-number ref) (if decr -1 1)))))
 
-       (t (error "Cannot shift reference"))))))
+       (t (user-error "Cannot shift reference"))))))
 
 (defun org-table-fedit-toggle-coordinates ()
   "Toggle the display of coordinates in the referenced table."
@@ -3444,14 +3665,14 @@ With prefix ARG, apply the new formulas to the table."
        (while (string-match "[ \t]*\n[ \t]*" form)
          (setq form (replace-match " " t t form)))
        (when (assoc var eql)
-         (error "Double formulas for %s" var))
+         (user-error "Double formulas for %s" var))
        (push (cons var form) eql)))
     (setq org-pos nil)
     (set-window-configuration org-window-configuration)
     (select-window sel-win)
     (goto-char pos)
     (unless (org-at-table-p)
-      (error "Lost table position - cannot install formulas"))
+      (user-error "Lost table position - cannot install formulas"))
     (org-table-store-formulas eql)
     (move-marker pos nil)
     (kill-buffer "*Edit Formulas*")
@@ -3481,14 +3702,14 @@ With prefix ARG, apply the new formulas to the table."
       (call-interactively 'lisp-indent-line))
      ((looking-at "[$&@0-9a-zA-Z]+ *= *[^ \t\n']") (goto-char pos))
      ((not (fboundp 'pp-buffer))
-      (error "Cannot pretty-print.  Command `pp-buffer' is not available"))
+      (user-error "Cannot pretty-print.  Command `pp-buffer' is not available"))
      ((looking-at "[$&@0-9a-zA-Z]+ *= *'(")
       (goto-char (- (match-end 0) 2))
       (setq beg (point))
       (setq ind (make-string (current-column) ?\ ))
       (condition-case nil (forward-sexp 1)
        (error
-        (error "Cannot pretty-print Lisp expression: Unbalanced parenthesis")))
+        (user-error "Cannot pretty-print Lisp expression: Unbalanced parenthesis")))
       (setq end (point))
       (save-restriction
        (narrow-to-region beg end)
@@ -3505,7 +3726,7 @@ With prefix ARG, apply the new formulas to the table."
            (beginning-of-line 1)
            (insert ind))
          (goto-char (point-max))
-         (backward-delete-char 1)))
+         (org-delete-backward-char 1)))
       (goto-char beg))
      (t nil))))
 
@@ -3540,7 +3761,7 @@ With prefix ARG, apply the new formulas to the table."
                  ((org-at-regexp-p "\\$[a-zA-Z][a-zA-Z0-9]*") 'name)
                  ((org-at-regexp-p "\\$[0-9]+") 'column)
                  ((not local) nil)
-                 (t (error "No reference at point")))
+                 (t (user-error "No reference at point")))
            match (and what (or match (match-string 0))))
       (when (and  match (not (equal (match-beginning 0) (point-at-bol))))
        (org-table-add-rectangle-overlay (match-beginning 0) (match-end 0)
@@ -3566,7 +3787,7 @@ With prefix ARG, apply the new formulas to the table."
          (if (get-buffer-window (marker-buffer pos))
              (select-window (get-buffer-window (marker-buffer pos)))
            (org-switch-to-buffer-other-window (get-buffer-window
-                                           (marker-buffer pos)))))
+                                               (marker-buffer pos)))))
       (goto-char pos)
       (org-table-force-dataline)
       (when dest
@@ -3607,7 +3828,7 @@ With prefix ARG, apply the new formulas to the table."
              (goto-char (match-beginning 1))
              (org-table-highlight-rectangle)
              (message "Named column (column %s)" (cdr e)))
-         (error "Column name not found")))
+         (user-error "Column name not found")))
        ((eq what 'column)
        ;; column number
        (org-table-goto-column (string-to-number (substring match 1)))
@@ -3620,10 +3841,10 @@ With prefix ARG, apply the new formulas to the table."
              (goto-char (match-beginning 1))
              (org-table-highlight-rectangle)
              (message "Local parameter."))
-         (error "Parameter not found")))
+         (user-error "Parameter not found")))
        (t
        (cond
-        ((not var) (error "No reference at point"))
+        ((not var) (user-error "No reference at point"))
         ((setq e (assoc var org-table-formula-constants-local))
          (message "Local Constant: $%s=%s in #+CONSTANTS line."
                   var (cdr e)))
@@ -3633,7 +3854,7 @@ With prefix ARG, apply the new formulas to the table."
         ((setq e (and (fboundp 'constants-get) (constants-get var)))
          (message "Constant: $%s=%s, from `constants.el'%s."
                   var e (format " (%s units)" constants-unit-system)))
-        (t (error "Undefined name $%s" var)))))
+        (t (user-error "Undefined name $%s" var)))))
       (goto-char pos)
       (when (and org-show-positions
                 (not (memq this-command '(org-table-fedit-scroll
@@ -3642,9 +3863,10 @@ With prefix ARG, apply the new formulas to the table."
        (push org-table-current-begin-pos org-show-positions)
        (let ((min (apply 'min org-show-positions))
              (max (apply 'max org-show-positions)))
-         (goto-char min) (recenter 0)
+         (set-window-start (selected-window) min)
          (goto-char max)
-         (or (pos-visible-in-window-p max) (recenter -1))))
+         (or (pos-visible-in-window-p max)
+             (set-window-start (selected-window) max))))
       (select-window win))))
 
 (defun org-table-force-dataline ()
@@ -3659,7 +3881,7 @@ With prefix ARG, apply the new formulas to the table."
             (goto-char (if (< (abs (- p1 (point))) (abs (- p2 (point))))
                            p1 p2)))
            ((or p1 p2) (goto-char (or p1 p2)))
-           (t (error "No table dataline around here"))))))
+           (t (user-error "No table dataline around here"))))))
 
 (defun org-table-fedit-line-up ()
   "Move cursor one line up in the window showing the table."
@@ -3771,11 +3993,12 @@ Use COMMAND to do the motion, repeat if necessary to end up in a data line."
            (org-overlay-display ov str 'org-special-keyword 'evaporate)))
        (beginning-of-line 2)))))
 
+;;;###autoload
 (defun org-table-toggle-coordinate-overlays ()
   "Toggle the display of Row/Column numbers in tables."
   (interactive)
   (setq org-table-overlay-coordinates (not org-table-overlay-coordinates))
-  (message "Row/Column number display turned %s"
+  (message "Tables Row/Column numbers display turned %s"
           (if org-table-overlay-coordinates "on" "off"))
   (if (and (org-at-table-p) org-table-overlay-coordinates)
       (org-table-align))
@@ -3783,6 +4006,7 @@ Use COMMAND to do the motion, repeat if necessary to end up in a data line."
     (mapc 'delete-overlay org-table-coordinate-overlays)
     (setq org-table-coordinate-overlays nil)))
 
+;;;###autoload
 (defun org-table-toggle-formula-debugger ()
   "Toggle the formula debugger in tables."
   (interactive)
@@ -3822,16 +4046,11 @@ Use COMMAND to do the motion, repeat if necessary to end up in a data line."
 (defvar orgtbl-mode-map (make-keymap)
   "Keymap for `orgtbl-mode'.")
 
-;;;###autoload
-(defun turn-on-orgtbl ()
-  "Unconditionally turn on `orgtbl-mode'."
-  (orgtbl-mode 1))
-
 (defvar org-old-auto-fill-inhibit-regexp nil
   "Local variable used by `orgtbl-mode'.")
 
 (defconst orgtbl-line-start-regexp
-  "[ \t]*\\(|\\|#\\+\\(TBLFM\\|ORGTBL\\|TBLNAME\\):\\)"
+  "[ \t]*\\(|\\|#\\+\\(tblfm\\|orgtbl\\|tblname\\):\\)"
   "Matches a line belonging to an orgtbl.")
 
 (defconst orgtbl-extra-font-lock-keywords
@@ -3849,7 +4068,7 @@ Use COMMAND to do the motion, repeat if necessary to end up in a data line."
   :lighter " OrgTbl" :keymap orgtbl-mode-map
   (org-load-modules-maybe)
   (cond
-   ((eq major-mode 'org-mode)
+   ((derived-mode-p 'org-mode)
     ;; Exit without error, in case some hook functions calls this
     ;; by accident in org-mode.
     (message "Orgtbl-mode is not useful in org-mode, command ignored"))
@@ -3910,7 +4129,7 @@ to execute outside of tables."
         '(arg)
         (concat "In tables, run `" (symbol-name fun) "'.\n"
                 "Outside of tables, run the binding of `"
-                (mapconcat (lambda (x) (format "%s" x)) keys "' or `")
+                (mapconcat #'key-description keys "' or `")
                 "'.")
         '(interactive "p")
         (list 'if
@@ -3927,7 +4146,7 @@ to execute outside of tables."
 (defun orgtbl-error ()
   "Error when there is no default binding for a table key."
   (interactive)
-  (error "This key has no function outside tables"))
+  (user-error "This key has no function outside tables"))
 
 (defun orgtbl-setup ()
   "Setup orgtbl keymaps."
@@ -3971,37 +4190,37 @@ to execute outside of tables."
 
     ;; Special treatment needed for TAB and RET
     (org-defkey orgtbl-mode-map [(return)]
-      (orgtbl-make-binding 'orgtbl-ret 100 [(return)] "\C-m"))
+               (orgtbl-make-binding 'orgtbl-ret 100 [(return)] "\C-m"))
     (org-defkey orgtbl-mode-map "\C-m"
-      (orgtbl-make-binding 'orgtbl-ret 101 "\C-m" [(return)]))
+               (orgtbl-make-binding 'orgtbl-ret 101 "\C-m" [(return)]))
 
     (org-defkey orgtbl-mode-map [(tab)]
-      (orgtbl-make-binding 'orgtbl-tab 102 [(tab)] "\C-i"))
+               (orgtbl-make-binding 'orgtbl-tab 102 [(tab)] "\C-i"))
     (org-defkey orgtbl-mode-map "\C-i"
-      (orgtbl-make-binding 'orgtbl-tab 103 "\C-i" [(tab)]))
+               (orgtbl-make-binding 'orgtbl-tab 103 "\C-i" [(tab)]))
 
     (org-defkey orgtbl-mode-map [(shift tab)]
-      (orgtbl-make-binding 'org-table-previous-field 104
-                          [(shift tab)] [(tab)] "\C-i"))
+               (orgtbl-make-binding 'org-table-previous-field 104
+                                    [(shift tab)] [(tab)] "\C-i"))
 
 
     (unless (featurep 'xemacs)
       (org-defkey orgtbl-mode-map [S-iso-lefttab]
-         (orgtbl-make-binding 'org-table-previous-field 107
-                             [S-iso-lefttab] [backtab] [(shift tab)]
-                             [(tab)] "\C-i")))
+                 (orgtbl-make-binding 'org-table-previous-field 107
+                                      [S-iso-lefttab] [backtab] [(shift tab)]
+                                      [(tab)] "\C-i")))
 
     (org-defkey orgtbl-mode-map [backtab]
-      (orgtbl-make-binding 'org-table-previous-field 108
-                          [backtab] [S-iso-lefttab] [(shift tab)]
-                          [(tab)] "\C-i"))
+               (orgtbl-make-binding 'org-table-previous-field 108
+                                    [backtab] [S-iso-lefttab] [(shift tab)]
+                                    [(tab)] "\C-i"))
 
     (org-defkey orgtbl-mode-map "\M-\C-m"
-      (orgtbl-make-binding 'org-table-wrap-region 105
-                          "\M-\C-m" [(meta return)]))
+               (orgtbl-make-binding 'org-table-wrap-region 105
+                                    "\M-\C-m" [(meta return)]))
     (org-defkey orgtbl-mode-map [(meta return)]
-      (orgtbl-make-binding 'org-table-wrap-region 106
-                          [(meta return)] "\M-\C-m"))
+               (orgtbl-make-binding 'org-table-wrap-region 106
+                                    [(meta return)] "\M-\C-m"))
 
     (org-defkey orgtbl-mode-map "\C-c\C-c" 'orgtbl-ctrl-c-ctrl-c)
     (org-defkey orgtbl-mode-map "\C-c|" 'orgtbl-create-or-convert-from-region)
@@ -4079,13 +4298,13 @@ to execute outside of tables."
 If it is a table to be sent away to a receiver, do it.
 With prefix arg, also recompute table."
   (interactive "P")
-  (let ((pos (point)) action consts-str consts cst const-str)
+  (let ((case-fold-search t) (pos (point)) action)
     (save-excursion
       (beginning-of-line 1)
       (setq action (cond
                    ((looking-at "[ \t]*#\\+ORGTBL:.*\n[ \t]*|") (match-end 0))
                    ((looking-at "[ \t]*|") pos)
-                   ((looking-at "[ \t]*#\\+TBLFM:") 'recalc))))
+                   ((looking-at "[ \t]*#\\+tblfm:") 'recalc))))
     (cond
      ((integerp action)
       (goto-char action)
@@ -4097,17 +4316,7 @@ With prefix arg, also recompute table."
       (when (orgtbl-send-table 'maybe)
        (run-hooks 'orgtbl-after-send-table-hook)))
      ((eq action 'recalc)
-      (save-excursion
-       (goto-char (point-min))
-       (while (re-search-forward "^[ \t]*#\\+CONSTANTS: \\(.*\\)" nil t)
-         (setq const-str (substring-no-properties (match-string 1)))
-         (setq consts (append consts (org-split-string const-str "[ \t]+")))
-         (when consts
-           (let (e)
-             (while (setq e (pop consts))
-               (if (string-match "^\\([a-zA-Z0][_a-zA-Z0-9]*\\)=\\(.*\\)" e)
-                   (push (cons (match-string 1 e) (match-string 2 e)) cst)))
-             (setq org-table-formula-constants-local cst)))))
+      (org-table-set-constants)
       (save-excursion
        (beginning-of-line 1)
        (skip-chars-backward " \r\n\t")
@@ -4163,7 +4372,7 @@ overwritten, and the table is not marked as requiring realignment."
           (looking-at "[^|\n]*  +|"))
       (let (org-table-may-need-update)
        (goto-char (1- (match-end 0)))
-       (backward-delete-char 1)
+       (org-delete-backward-char 1)
        (goto-char (match-beginning 0))
        (self-insert-command N))
     (setq org-table-may-need-update t)
@@ -4174,7 +4383,7 @@ overwritten, and the table is not marked as requiring realignment."
                              (setq a (assoc last-input-event function-key-map))
                              (cdr a))
                         (vector last-input-event)))
-          'self-insert-command)))
+                   'self-insert-command)))
       (call-interactively cmd)
       (if (and org-self-insert-cluster-for-undo
               (eq cmd 'self-insert-command))
@@ -4192,31 +4401,6 @@ overwritten, and the table is not marked as requiring realignment."
 (defvar orgtbl-exp-regexp "^\\([-+]?[0-9][0-9.]*\\)[eE]\\([-+]?[0-9]+\\)$"
   "Regular expression matching exponentials as produced by calc.")
 
-(defun orgtbl-export (table target)
-  (require 'org-exp)
-  (let ((func (intern (concat "orgtbl-to-" (symbol-name target))))
-       (lines (org-split-string table "[ \t]*\n[ \t]*"))
-       org-table-last-alignment org-table-last-column-widths
-       maxcol column)
-    (if (not (fboundp func))
-       (error "Cannot export orgtbl table to %s" target))
-    (setq lines (org-table-clean-before-export lines))
-    (setq table
-         (mapcar
-          (lambda (x)
-            (if (string-match org-table-hline-regexp x)
-                'hline
-              (org-split-string (org-trim x) "\\s-*|\\s-*")))
-          lines))
-    (setq maxcol (apply 'max (mapcar (lambda (x) (if (listp x) (length x) 0))
-                                    table)))
-    (loop for i from (1- maxcol) downto 0 do
-         (setq column (mapcar (lambda (x) (if (listp x) (nth i x) nil)) table))
-         (setq column (delq nil column))
-         (push (apply 'max (mapcar 'string-width column)) org-table-last-column-widths)
-         (push (> (/ (apply '+ (mapcar (lambda (x) (if (string-match org-table-number-regexp x) 1 0)) column)) maxcol) org-table-number-fraction) org-table-last-alignment))
-    (funcall func table nil)))
-
 (defun orgtbl-gather-send-defs ()
   "Gather a plist of :name, :transform, :params for each destination before
 a radio table."
@@ -4239,15 +4423,15 @@ a radio table."
   (save-excursion
     (goto-char (point-min))
     (unless (re-search-forward
-            (concat "BEGIN RECEIVE ORGTBL +" name "\\([ \t]\\|$\\)") nil t)
-      (error "Don't know where to insert translated table"))
+            (concat "BEGIN +RECEIVE +ORGTBL +" name "\\([ \t]\\|$\\)") nil t)
+      (user-error "Don't know where to insert translated table"))
     (goto-char (match-beginning 0))
     (beginning-of-line 2)
     (save-excursion
       (let ((beg (point)))
        (unless (re-search-forward
-                (concat "END RECEIVE ORGTBL +" name) nil t)
-         (error "Cannot find end of insertion region"))
+                (concat "END +RECEIVE +ORGTBL +" name) nil t)
+         (user-error "Cannot find end of insertion region"))
        (beginning-of-line 1)
        (delete-region beg (point))))
     (insert txt "\n")))
@@ -4260,7 +4444,7 @@ for a horizontal separator line, or a list of field values as strings.
 The table is taken from the parameter TXT, or from the buffer at point."
   (unless txt
     (unless (org-at-table-p)
-      (error "No table at point")))
+      (user-error "No table at point")))
   (let* ((txt (or txt
                  (buffer-substring-no-properties (org-table-begin)
                                                  (org-table-end))))
@@ -4279,7 +4463,7 @@ With argument MAYBE, fail quietly if no transformation is defined for
 this table."
   (interactive)
   (catch 'exit
-    (unless (org-at-table-p) (error "Not at a table"))
+    (unless (org-at-table-p) (user-error "Not at a table"))
     ;; when non-interactive, we assume align has just happened.
     (when (org-called-interactively-p 'any) (org-table-align))
     (let ((dests (orgtbl-gather-send-defs))
@@ -4287,18 +4471,22 @@ this table."
                                               (org-table-end)))
          (ntbl 0))
       (unless dests (if maybe (throw 'exit nil)
-                     (error "Don't know how to transform this table")))
+                     (user-error "Don't know how to transform this table")))
       (dolist (dest dests)
        (let* ((name (plist-get dest :name))
               (transform (plist-get dest :transform))
               (params (plist-get dest :params))
               (skip (plist-get params :skip))
               (skipcols (plist-get params :skipcols))
+              (no-escape (plist-get params :no-escape))
               beg
               (lines (org-table-clean-before-export
                       (nthcdr (or skip 0)
                               (org-split-string txt "[ \t]*\n[ \t]*"))))
               (i0 (if org-table-clean-did-remove-column 2 1))
+              (lines (if no-escape lines
+                       (mapcar (lambda(l) (replace-regexp-in-string
+                                           "\\([&%#_^]\\)" "\\\\\\1{}" l)) lines)))
               (table (mapcar
                       (lambda (x)
                         (if (string-match org-table-hline-regexp x)
@@ -4316,11 +4504,11 @@ this table."
                                     skipcols i0))
               (txt (if (fboundp transform)
                        (funcall transform table params)
-                     (error "No such transformation function %s" transform))))
+                     (user-error "No such transformation function %s" transform))))
          (orgtbl-send-replace-tbl name txt))
        (setq ntbl (1+ ntbl)))
       (message "Table converted and installed at %d receiver location%s"
-                          ntbl (if (> ntbl 1) "s" ""))
+              ntbl (if (> ntbl 1) "s" ""))
       (if (> ntbl 0)
          ntbl
        nil))))
@@ -4340,12 +4528,13 @@ First element has index 0, or I0 if given."
 (defun orgtbl-toggle-comment ()
   "Comment or uncomment the orgtbl at point."
   (interactive)
-  (let* ((re1 (concat "^" (regexp-quote comment-start) orgtbl-line-start-regexp))
+  (let* ((case-fold-search t)
+        (re1 (concat "^" (regexp-quote comment-start) orgtbl-line-start-regexp))
         (re2 (concat "^" orgtbl-line-start-regexp))
         (commented (save-excursion (beginning-of-line 1)
-                            (cond ((looking-at re1) t)
-                                  ((looking-at re2) nil)
-                                  (t (error "Not at an org table")))))
+                                   (cond ((looking-at re1) t)
+                                         ((looking-at re2) nil)
+                                         (t (user-error "Not at an org table")))))
         (re (if commented re1 re2))
         beg end)
     (save-excursion
@@ -4363,7 +4552,7 @@ First element has index 0, or I0 if given."
   (let* ((e (assq major-mode orgtbl-radio-table-templates))
         (txt (nth 1 e))
         name pos)
-    (unless e (error "No radio table setup defined for %s" major-mode))
+    (unless e (user-error "No radio table setup defined for %s" major-mode))
     (setq name (read-string "Table name: "))
     (while (string-match "%n" txt)
       (setq txt (replace-match name t t txt)))
@@ -4397,7 +4586,8 @@ First element has index 0, or I0 if given."
     fmt))
 
 (defsubst orgtbl-apply-fmt (fmt &rest args)
-  "Apply format FMT to the arguments.  NIL FMTs return the first argument."
+  "Apply format FMT to arguments ARGS.
+When FMT is nil, return the first argument from ARGS."
   (cond ((functionp fmt) (apply fmt args))
        (fmt (apply 'format fmt args))
        (args (car args))
@@ -4427,7 +4617,7 @@ First element has index 0, or I0 if given."
                                   f)))
             line)))
       (push (if *orgtbl-lfmt*
-               (orgtbl-apply-fmt *orgtbl-lfmt* line)
+               (apply #'orgtbl-apply-fmt *orgtbl-lfmt* line)
              (concat (orgtbl-eval-str *orgtbl-lstart*)
                      (mapconcat 'identity line *orgtbl-sep*)
                      (orgtbl-eval-str *orgtbl-lend*)))
@@ -4445,16 +4635,20 @@ First element has index 0, or I0 if given."
                         (*orgtbl-lfmt* *orgtbl-llfmt*))
                     (orgtbl-format-line prevline))))))
 
-(defun orgtbl-to-generic (table params)
+;;;###autoload
+(defun orgtbl-to-generic (table params &optional backend)
   "Convert the orgtbl-mode TABLE to some other format.
 This generic routine can be used for many standard cases.
 TABLE is a list, each entry either the symbol `hline' for a horizontal
 separator line, or a list of fields for that line.
 PARAMS is a property list of parameters that can influence the conversion.
+A third optional argument BACKEND can be used to convert the content of
+the cells using a specific export back-end.
+
 For the generic converter, some parameters are obligatory: you need to
 specify either :lfmt, or all of (:lstart :lend :sep).
 
-Valid parameters are
+Valid parameters are:
 
 :splice     When set to t, return only table body lines, don't wrap
             them into :tstart and :tend.  Default is nil.  When :splice
@@ -4467,9 +4661,9 @@ Valid parameters are
 :sep        Separator between two fields
 :remove-nil-lines Do not include lines that evaluate to nil.
 
-
 Each in the following group may be either a string or a function
 of no arguments returning a string:
+
 :tstart     String to start the table.  Ignored when :splice is t.
 :tend       String to end the table.  Ignored when :splice is t.
 :lstart     String to start a new table line.
@@ -4480,6 +4674,7 @@ of no arguments returning a string:
 Each in the following group may be a string, a function of one
 argument (the field or line) returning a string, or a plist
 mapping columns to either of the above:
+
 :lfmt       Format for entire line, with enough %s to capture all fields.
             If this is present, :lstart, :lend, and :sep are ignored.
 :llfmt      Format for the entire last line, defaults to :lfmt.
@@ -4487,14 +4682,14 @@ mapping columns to either of the above:
             %s for the original field value.  For example, to wrap
             everything in dollars, you could use :fmt \"$%s$\".
             This may also be a property list with column numbers and
-            formats. For example :fmt (2 \"$%s$\" 4 \"%s%%\")
-
+            formats.  For example :fmt (2 \"$%s$\" 4 \"%s%%\")
 :hlstart :hllstart :hlend :hllend :hlsep :hlfmt :hllfmt :hfmt
             Same as above, specific for the header lines in the table.
             All lines before the first hline are treated as header.
             If any of these is not present, the data line value is used.
 
 This may be either a string or a function of two arguments:
+
 :efmt       Use this format to print numbers with exponentials.
             The format should have %s twice for inserting mantissa
             and exponent, for example \"%s\\\\times10^{%s}\".  This
@@ -4503,10 +4698,9 @@ This may be either a string or a function of two arguments:
 
 In addition to this, the parameters :skip and :skipcols are always handled
 directly by `orgtbl-send-table'.  See manual."
-  (interactive)
-
   (let* ((splicep (plist-get params :splice))
         (hline (plist-get params :hline))
+        (skipheadrule (plist-get params :skipheadrule))
         (remove-nil-linesp (plist-get params :remove-nil-lines))
         (remove-newlines (plist-get params :remove-newlines))
         (*orgtbl-hline* hline)
@@ -4521,22 +4715,31 @@ directly by `orgtbl-send-table'.  See manual."
         (*orgtbl-llfmt* (or (plist-get params :llfmt) *orgtbl-lfmt*))
         (*orgtbl-fmt* (plist-get params :fmt))
         *orgtbl-rtn*)
-
+    ;; Convert cells content to backend BACKEND
+    (when backend
+      (setq *orgtbl-table*
+           (mapcar
+            (lambda(r)
+              (if (listp r)
+                  (mapcar
+                   (lambda (c)
+                     (org-trim (org-export-string-as c backend t '(:with-tables t))))
+                   r)
+                r))
+            *orgtbl-table*)))
     ;; Put header
     (unless splicep
       (when (plist-member params :tstart)
        (let ((tstart (orgtbl-eval-str (plist-get params :tstart))))
          (if tstart (push tstart *orgtbl-rtn*)))))
-
-    ;; Do we have a heading section?  If so, format it and handle the
-    ;; trailing hline.
+    ;; If we have a heading, format it and handle the trailing hline.
     (if (and (not splicep)
             (or (consp (car *orgtbl-table*))
                 (consp (nth 1 *orgtbl-table*)))
             (memq 'hline (cdr *orgtbl-table*)))
        (progn
          (when (eq 'hline (car *orgtbl-table*))
-           ;; there is a hline before the first data line
+           ;; There is a hline before the first data line
            (and hline (push hline *orgtbl-rtn*))
            (pop *orgtbl-table*))
          (let* ((*orgtbl-lstart* (or (plist-get params :hlstart)
@@ -4552,17 +4755,14 @@ directly by `orgtbl-send-table'.  See manual."
                 (*orgtbl-sep* (or (plist-get params :hlsep) *orgtbl-sep*))
                 (*orgtbl-fmt* (or (plist-get params :hfmt) *orgtbl-fmt*)))
            (orgtbl-format-section 'hline))
-         (if hline (push hline *orgtbl-rtn*))
+         (if (and hline (not skipheadrule)) (push hline *orgtbl-rtn*))
          (pop *orgtbl-table*)))
-
     ;; Now format the main section.
     (orgtbl-format-section nil)
-
     (unless splicep
       (when (plist-member params :tend)
        (let ((tend (orgtbl-eval-str (plist-get params :tend))))
          (if tend (push tend *orgtbl-rtn*)))))
-
     (mapconcat (if remove-newlines
                   (lambda (tend)
                     (replace-regexp-in-string "[\n\r\t\f]" "\\\\n" tend))
@@ -4571,9 +4771,11 @@ directly by `orgtbl-send-table'.  See manual."
                             (remq nil *orgtbl-rtn*)
                           *orgtbl-rtn*)) "\n")))
 
+;;;###autoload
 (defun orgtbl-to-tsv (table params)
   "Convert the orgtbl-mode table to TAB separated material."
   (orgtbl-to-generic table (org-combine-plists '(:sep "\t") params)))
+;;;###autoload
 (defun orgtbl-to-csv (table params)
   "Convert the orgtbl-mode table to CSV material.
 This does take care of the proper quoting of fields with comma or quotes."
@@ -4581,6 +4783,7 @@ This does take care of the proper quoting of fields with comma or quotes."
                            '(:sep "," :fmt org-quote-csv-field)
                            params)))
 
+;;;###autoload
 (defun orgtbl-to-latex (table params)
   "Convert the orgtbl-mode TABLE to LaTeX.
 TABLE is a list, each entry either the symbol `hline' for a horizontal
@@ -4617,8 +4820,10 @@ this function is called."
           :tend "\\end{tabular}"
           :lstart "" :lend " \\\\" :sep " & "
           :efmt "%s\\,(%s)" :hline "\\hline")))
-    (orgtbl-to-generic table (org-combine-plists params2 params))))
+    (require 'ox-latex)
+    (orgtbl-to-generic table (org-combine-plists params2 params) 'latex)))
 
+;;;###autoload
 (defun orgtbl-to-html (table params)
   "Convert the orgtbl-mode TABLE to HTML.
 TABLE is a list, each entry either the symbol `hline' for a horizontal
@@ -4632,23 +4837,16 @@ Currently this function recognizes the following parameters:
 The general parameters :skip and :skipcols have already been applied when
 this function is called.  The function does *not* use `orgtbl-to-generic',
 so you cannot specify parameters for it."
-  (let* ((splicep (plist-get params :splice))
-        (html-table-tag org-export-html-table-tag)
-        html)
-    ;; Just call the formatter we already have
-    ;; We need to make text lines for it, so put the fields back together.
-    (setq html (org-format-org-table-html
-               (mapcar
-                (lambda (x)
-                  (if (eq x 'hline)
-                      "|----+----|"
-                    (concat "| " (mapconcat 'org-html-expand x " | ") " |")))
-                table)
-               splicep))
-    (if (string-match "\n+\\'" html)
-       (setq html (replace-match "" t t html)))
-    html))
+  (require 'ox-html)
+  (let ((output (org-export-string-as
+                (orgtbl-to-orgtbl table nil) 'html t '(:with-tables t))))
+    (if (not (plist-get params :splice)) output
+      (org-trim
+       (replace-regexp-in-string
+       "\\`<table .*>\n" ""
+       (replace-regexp-in-string "</table>\n*\\'" "" output))))))
 
+;;;###autoload
 (defun orgtbl-to-texinfo (table params)
   "Convert the orgtbl-mode TABLE to TeXInfo.
 TABLE is a list, each entry either the symbol `hline' for a horizontal
@@ -4685,8 +4883,10 @@ this function is called."
           :tend "@end multitable"
           :lstart "@item " :lend "" :sep " @tab "
           :hlstart "@headitem ")))
-    (orgtbl-to-generic table (org-combine-plists params2 params))))
+    (require 'ox-texinfo)
+    (orgtbl-to-generic table (org-combine-plists params2 params) 'texinfo)))
 
+;;;###autoload
 (defun orgtbl-to-orgtbl (table params)
   "Convert the orgtbl-mode TABLE into another orgtbl-mode table.
 Useful when slicing one table into many.  The :hline, :sep,
@@ -4702,23 +4902,53 @@ provide ORGTBL directives for the generated table."
           :lstart "| "
           :lend " |"))
         (params (org-combine-plists params2 params)))
-    (orgtbl-to-generic table params)))
+    (with-temp-buffer
+      (insert (orgtbl-to-generic table params))
+      (goto-char (point-min))
+      (while (re-search-forward org-table-hline-regexp nil t)
+       (org-table-align))
+      (buffer-substring 1 (buffer-size)))))
+
+(defun orgtbl-to-table.el (table params)
+  "Convert the orgtbl-mode TABLE into a table.el table."
+  (with-temp-buffer
+    (insert (orgtbl-to-orgtbl table params))
+    (org-table-align)
+    (replace-regexp-in-string
+     "-|" "-+"
+     (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.
+You need the ascii-art-to-unicode.el package for this.  You can download
+it here: http://gnuvola.org/software/j/aa2u/ascii-art-to-unicode.el."
+  (with-temp-buffer
+    (insert (orgtbl-to-table.el table params))
+    (goto-char (point-min))
+    (if (or (featurep 'ascii-art-to-unicode)
+           (require 'ascii-art-to-unicode nil t))
+       (aa2u)
+      (unless (delq nil (mapcar (lambda (l) (string-match "aa2u" (car l))) org-stored-links))
+       (push '("http://gnuvola.org/software/j/aa2u/ascii-art-to-unicode.el"
+               "Link to ascii-art-to-unicode.el") org-stored-links))
+      (user-error "Please download ascii-art-to-unicode.el (use C-c C-l to insert the link to it)"))
+    (buffer-string)))
 
 (defun org-table-get-remote-range (name-or-id form)
   "Get a field value or a list of values in a range from table at ID.
 
-NAME-OR-ID may be the name of a table in the current file as set by
-a \"#+TBLNAME:\" directive.  The first table following this line
+NAME-OR-ID may be the name of a table in the current file as set
+by a \"#+NAME:\" directive.  The first table following this line
 will then be used.  Alternatively, it may be an ID referring to
-any entry, also in a different file.  In this case, the first table
-in that entry will be referenced.
+any entry, also in a different file.  In this case, the first
+table in that entry will be referenced.
 FORM is a field or range descriptor like \"@2$3\" or \"B3\" or
 \"@I$2..@II$2\".  All the references must be absolute, not relative.
 
 The return value is either a single string for a single field, or a
-list of the fields in the rectangle ."
+list of the fields in the rectangle."
   (save-match-data
-    (let ((id-loc nil)
+    (let ((case-fold-search t) (id-loc nil)
          ;; Protect a bunch of variables from being overwritten
          ;; by the context of the remote table
          org-table-column-names org-table-column-name-regexp
@@ -4737,12 +4967,13 @@ list of the fields in the rectangle ."
          (save-excursion
            (goto-char (point-min))
            (if (re-search-forward
-                (concat "^[ \t]*#\\+TBLNAME:[ \t]*" (regexp-quote name-or-id) "[ \t]*$")
+                (concat "^[ \t]*#\\+\\(tbl\\)?name:[ \t]*"
+                        (regexp-quote name-or-id) "[ \t]*$")
                 nil t)
                (setq buffer (current-buffer) loc (match-beginning 0))
              (setq id-loc (org-id-find name-or-id 'marker))
              (unless (and id-loc (markerp id-loc))
-               (error "Can't find remote table \"%s\"" name-or-id))
+               (user-error "Can't find remote table \"%s\"" name-or-id))
              (setq buffer (marker-buffer id-loc)
                    loc (marker-position id-loc))
              (move-marker id-loc nil)))
@@ -4754,7 +4985,7 @@ list of the fields in the rectangle ."
                (forward-char 1)
                (unless (and (re-search-forward "^\\(\\*+ \\)\\|[ \t]*|" nil t)
                             (not (match-beginning 1)))
-                 (error "Cannot find a table at NAME or ID %s" name-or-id))
+                 (user-error "Cannot find a table at NAME or ID %s" name-or-id))
                (setq tbeg (point-at-bol))
                (org-table-get-specials)
                (setq form (org-table-formula-substitute-names
@@ -4765,6 +4996,42 @@ list of the fields in the rectangle ."
                      (org-table-get-range (match-string 0 form) tbeg 1))
                  form)))))))))
 
+(defmacro org-define-lookup-function (mode)
+  (let ((mode-str (symbol-name mode))
+       (first-p (equal mode 'first))
+       (all-p (equal mode 'all)))
+    (let ((plural-str (if all-p "s" "")))
+      `(defun ,(intern (format "org-lookup-%s" mode-str)) (val s-list r-list &optional predicate)
+        ,(format "Find %s occurrence%s of VAL in S-LIST; return corresponding element%s of R-LIST.
+If R-LIST is nil, return matching element%s of S-LIST.
+If PREDICATE is not nil, use it instead of `equal' to match VAL.
+Matching is done by (PREDICATE VAL S), where S is an element of S-LIST.
+This function is generated by a call to the macro `org-define-lookup-function'."
+                 mode-str plural-str plural-str plural-str)
+        (let ,(let ((lvars '((p (or predicate 'equal))
+                             (sl s-list)
+                             (rl (or r-list s-list))
+                             (ret nil))))
+                (if first-p (add-to-list 'lvars '(match-p nil)))
+                lvars)
+          (while ,(if first-p '(and (not match-p) sl) 'sl)
+            (progn
+              (if (funcall p val (car sl))
+                  (progn
+                    ,(if first-p '(setq match-p t))
+                    (let ((rval (car rl)))
+                      (setq ret ,(if all-p '(append ret (list rval)) 'rval)))))
+              (setq sl (cdr sl) rl (cdr rl))))
+          ret)))))
+
+(org-define-lookup-function first)
+(org-define-lookup-function last)
+(org-define-lookup-function all)
+
 (provide 'org-table)
 
+;; Local variables:
+;; generated-autoload-file: "org-loaddefs.el"
+;; End:
+
 ;;; org-table.el ends here