Ver Fonte

Merge branch 'master' of orgmode.org:org-mode

Eric Schulte há 12 anos atrás
pai
commit
0202adb1c0

+ 5 - 9
UTILITIES/x11idle.c

@@ -8,7 +8,6 @@
  * path
  */
 main() {
-    Status querry = 0;
     XScreenSaverInfo *info = XScreenSaverAllocInfo();
     //open the display specified by the DISPLAY environment variable
     Display *display = XOpenDisplay(0);
@@ -18,15 +17,12 @@ main() {
     return -1;
     }
 
-    //X11 is running, retrieve and print idle time
-	querry = XScreenSaverQueryInfo(display, DefaultRootWindow(display), info);
-
-    if (querry == 0) {
-    return -1;
+    //X11 is running, try to retrieve info
+    if (XScreenSaverQueryInfo(display, DefaultRootWindow(display), info) == 0) {
+	return -1;
     }
 
-    //idle time was retrieved successfully, print it
-    printf("%u\n", info->idle);
+    //info was retrieved successfully, print idle time
+    printf("%lu\n", info->idle);
     return 0;
 }
-

+ 5 - 5
contrib/lisp/org-e-ascii.el

@@ -511,7 +511,8 @@ title."
 				   (mapconcat 'identity tag-list ":"))))))
 	 (priority
 	  (and (plist-get info :with-priority)
-	       (concat (org-element-property :priority element) " ")))
+	       (let ((char (org-element-property :priority element)))
+		 (and char (format "(#%c) " char)))))
 	 (first-part (concat numbers todo priority text)))
     (concat
      first-part
@@ -1736,10 +1737,9 @@ EXT-PLIST, when provided, is a property list with external
 parameters overriding Org default settings, but still inferior to
 file-local settings.
 
-When optional argument PUB-DIR is set, use it as the publishing
-directory.
-
-Return output file's name."
+Export is done in a buffer named \"*Org E-ASCII Export*\", which
+will be displayed when `org-export-show-temporary-export-buffer'
+is non-nil."
   (interactive)
   (let ((outbuf (org-export-to-buffer
 		 'e-ascii "*Org E-ASCII Export*"

+ 5 - 5
contrib/lisp/org-e-beamer.el

@@ -313,7 +313,7 @@ channel."
     (cond ((eq backend 'e-latex) value)
 	  ;; Ignore "e-beamer" snippets specifying overlays.
 	  ((and (eq backend 'e-beamer)
-		(or (org-export-get-previous-element export-snippet)
+		(or (org-export-get-previous-element export-snippet info)
 		    (not (string-match "\\`<.*>\\'" value))))
 	   value))))
 
@@ -457,18 +457,18 @@ used as a communication channel."
 	 ;; a BEAMER_column property.
 	 (start-columns-p
 	  (and column-width
-	       (or (org-export-first-sibling-p headline)
+	       (or (org-export-first-sibling-p headline info)
 		   (not (org-element-property
 			 :beamer-col
-			 (org-export-get-previous-element headline))))))
+			 (org-export-get-previous-element headline info))))))
 	 ;; Ends a columns environment when there is no next headline
 	 ;; or the next headline do not have a BEAMER_column property.
 	 (end-columns-p
 	  (and column-width
-	       (or (org-export-last-sibling-p headline)
+	       (or (org-export-last-sibling-p headline info)
 		   (not (org-element-property
 			 :beamer-col
-			 (org-export-get-next-element headline)))))))
+			 (org-export-get-next-element headline info)))))))
     (concat
      (when start-columns-p "\\begin{columns}\n")
      (when column-width

+ 2079 - 0
contrib/lisp/org-e-groff.el

@@ -0,0 +1,2079 @@
+                                        ; org-e-groff.el --- GRoff Back-End For Org Export Engine
+
+;; Copyright (C) 2011-2012  Free Software Foundation, Inc.
+
+;; Author: Nicolas Goaziou <n.goaziou at gmail dot com>
+;; Author: Luis R Anaya <papoanaya aroba hot mail punto com>
+;; Keywords: outlines, hypermedia, calendar, wp
+;; 
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;; This library implements a Groff Memorandum Macro  back-end for 
+;; Org generic exporter.
+;;
+;; To test it, run
+;;
+;;   M-: (org-export-to-buffer 'e-groff "*Test e-Groff*") RET
+;;
+;; in an org-mode buffer then switch to the buffer to see the Groff
+;; export.  See contrib/lisp/org-export.el for more details on how
+;; this exporter works.
+;;
+;; It introduces two new buffer keywords: "GROFF_CLASS" and
+;; "GROFF_CLASS_OPTIONS".
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+
+(defvar org-export-groff-default-packages-alist)
+(defvar org-export-groff-packages-alist)
+
+(require 'org-export)
+
+
+;;; Define Back-End
+
+(defvar org-e-groff-translate-alist
+  '((babel-call . org-e-groff-babel-call)
+    (bold . org-e-groff-bold)
+    (center-block . org-e-groff-center-block)
+    (clock . org-e-groff-clock)
+    (code . org-e-groff-code)
+    (comment . org-e-groff-comment)
+    (comment-block . org-e-groff-comment-block)
+    (drawer . org-e-groff-drawer)
+    (dynamic-block . org-e-groff-dynamic-block)
+    (entity . org-e-groff-entity)
+    (example-block . org-e-groff-example-block)
+    (export-block . org-e-groff-export-block)
+    (export-snippet . org-e-groff-export-snippet)
+    (fixed-width . org-e-groff-fixed-width)
+    (footnote-definition . org-e-groff-footnote-definition)
+    (footnote-reference . org-e-groff-footnote-reference)
+    (headline . org-e-groff-headline)
+    (horizontal-rule . org-e-groff-horizontal-rule)
+    (inline-babel-call . org-e-groff-inline-babel-call)
+    (inline-src-block . org-e-groff-inline-src-block)
+    (inlinetask . org-e-groff-inlinetask)
+    (italic . org-e-groff-italic)
+    (item . org-e-groff-item)
+    (keyword . org-e-groff-keyword)
+    (groff-environment . org-e-groff-groff-environment)
+    (groff-fragment . org-e-groff-groff-fragment)
+    (line-break . org-e-groff-line-break)
+    (link . org-e-groff-link)
+    (macro . org-e-groff-macro)
+    (paragraph . org-e-groff-paragraph)
+    (plain-list . org-e-groff-plain-list)
+    (plain-text . org-e-groff-plain-text)
+    (planning . org-e-groff-planning)
+    (property-drawer . org-e-groff-property-drawer)
+    (quote-block . org-e-groff-quote-block)
+    (quote-section . org-e-groff-quote-section)
+    (radio-target . org-e-groff-radio-target)
+    (section . org-e-groff-section)
+    (special-block . org-e-groff-special-block)
+    (src-block . org-e-groff-src-block)
+    (statistics-cookie . org-e-groff-statistics-cookie)
+    (strike-through . org-e-groff-strike-through)
+    (subscript . org-e-groff-subscript)
+    (superscript . org-e-groff-superscript)
+    (table . org-e-groff-table)
+    (table-cell . org-e-groff-table-cell)
+    (table-row . org-e-groff-table-row)
+    (target . org-e-groff-target)
+    (template . org-e-groff-template)
+    (timestamp . org-e-groff-timestamp)
+    (underline . org-e-groff-underline)
+    (verbatim . org-e-groff-verbatim)
+    (verse-block . org-e-groff-verse-block))
+  "Alist between element or object types and translators.")
+
+(defconst org-e-groff-options-alist
+  '((:date "DATE" nil org-e-groff-date-format t)
+    (:groff-class "GROFF_CLASS" nil org-e-groff-default-class t)
+    (:groff-class-options "GROFF_CLASS_OPTIONS" nil nil t)
+    (:groff-header-extra "GROFF_HEADER" nil nil newline))
+  "Alist between Groff export properties and ways to set them.
+See `org-export-options-alist' for more information on the
+structure of the values.")
+
+
+
+;;; User Configurable Variables
+
+(defgroup org-export-e-groff nil
+  "Options for exporting Org mode files to Groff."
+  :tag "Org Export Groff"
+  :group 'org-export)
+
+
+;;;; Preamble
+
+(defcustom org-e-groff-default-class "internal"
+  "The default Groff class."
+  :group 'org-export-e-groff
+  :type '(string :tag "Groff class"))
+
+(defcustom org-e-groff-classes
+  '(("file" ".MT 1"  
+     (:heading 'default :type "memo" :last-section "toc"))
+    ("internal" ".MT 0" 
+     (:heading 'default :type "memo" :last-section "toc"))
+    ("programmer" ".MT 2" 
+     (:heading 'default :type "memo" :last-section "toc"))
+    ("engineer" ".MT 3" 
+     (:heading 'default :type "memo" :last-section "toc"))
+    ("external" ".MT 4" 
+     (:heading 'default :type "memo" :last-section "toc"))
+    ("letter" ".MT 5" 
+     (:heading 'default :type "memo" :last-section "sign"))
+    ("custom" ".so file" 
+     (:heading custom-function :type "custom" :last-section "toc")  ) 
+    ("dummy" "" 
+     (:heading 'default :type "memo"))
+    ("ms" "ms" 
+     (:heading 'default :type "cover" :last-section "toc"))
+    ("se_ms" "se_ms" 
+     (:heading 'default :type "cover" :last-section "toc"))
+    ("none" "" '(:heading 'default :type "custom")))
+
+  ;; none means, no Cover or Memorandum Type and no calls to AU, AT, ND and TL
+  ;; This is to facilitate the creation of custom pages. 
+
+  ;; dummy means, no Cover or Memorandum Type but calls to AU, AT, ND and TL 
+  ;; are made. This is to facilitate Abstract Insertion. 
+
+  "This list describes the attributes for the documents being created.
+   It allows for the creation of new "
+  :group 'org-export-e-groff
+  :type '(repeat
+          (list (string :tag "Document Type")
+                (string :tag "Header")
+                (repeat :tag "Options" :inline t
+                        (choice
+                         (list :tag "Heading")
+                         (function :tag "Hook computing sectioning"))))))
+
+
+(defcustom org-e-groff-date-format
+  (format-time-string "%Y-%m-%d")
+  "Format string for .ND "
+  :group 'org-export-e-groff
+  :type 'boolean)
+
+
+;;;; Headline
+
+
+(defcustom org-e-groff-format-headline-function nil
+  "Function to format headline text.
+
+This function will be called with 5 arguments:
+TODO      the todo keyword (string or nil).
+TODO-TYPE the type of todo (symbol: `todo', `done', nil)
+PRIORITY  the priority of the headline (integer or nil)
+TEXT      the main headline text (string).
+TAGS      the tags as a list of strings (list of strings or nil).
+
+The function result will be used in the section format string.
+
+As an example, one could set the variable to the following, in
+order to reproduce the default set-up:
+
+\(defun org-e-groff-format-headline (todo todo-type priority text tags)
+  \"Default format function for an headline.\"
+  \(concat (when todo
+            \(format \"\\fB%s\\fP \" todo))
+	  \(when priority
+            \(format \"[\\#%c] \" priority))
+	  text
+	  \(when tags
+            \(format \" %s \"
+              \(mapconcat 'identity tags \":\"))))"
+  :group 'org-export-e-groff
+  :type 'function)
+
+
+;;;; Timestamps
+
+(defcustom org-e-groff-active-timestamp-format "\\fI%s\\fP"
+  "A printf format string to be applied to active timestamps."
+  :group 'org-export-e-groff
+  :type 'string)
+
+(defcustom org-e-groff-inactive-timestamp-format "\\fI%s\\fP"
+  "A printf format string to be applied to inactive timestamps."
+  :group 'org-export-e-groff
+  :type 'string)
+
+(defcustom org-e-groff-diary-timestamp-format "\\fI%s\\fP"
+  "A printf format string to be applied to diary timestamps."
+  :group 'org-export-e-groff
+  :type 'string)
+
+
+;;;; Links
+
+
+(defcustom org-e-groff-inline-image-rules
+  '(
+    ("file" . "\\.\\(pdf\\|ps\\|eps\\|pic\\)\\'")
+    ("fuzzy" . "\\.\\(pdf\\|ps\\|eps\\|pic\\)\\'"))
+  "Rules characterizing image files that can be inlined into Groff.
+
+A rule consists in an association whose key is the type of link
+to consider, and value is a regexp that will be matched against
+link's path.
+
+Note that, by default, the image extension *actually* allowed
+depend on the way the Groff file is processed.  When used with
+pdfgroff, pdf, jpg and png images are OK.  When processing
+through dvi to Postscript, only ps and eps are allowed.  The
+default we use here encompasses both."
+  :group 'org-export-e-groff
+  :type '(alist :key-type (string :tag "Type")
+                :value-type (regexp :tag "Path")))
+
+(defcustom org-e-groff-link-with-unknown-path-format "\\fI%s\\fP"
+  "Format string for links with unknown path type."
+  :group 'org-export-groff
+  :type 'string)
+
+
+;;;; Tables
+
+
+(defcustom org-e-groff-tables-centered t
+  "When non-nil, tables are exported in a center environment."
+  :group 'org-export-e-groff
+  :type 'boolean)
+
+(defcustom org-e-groff-tables-verbatim nil
+  "When non-nil, tables are exported verbatim."
+  :group 'org-export-e-groff
+  :type 'boolean)
+
+
+(defcustom org-e-groff-table-scientific-notation "%sE%s"
+  "Format string to display numbers in scientific notation.
+The format should have \"%s\" twice, for mantissa and exponent
+\(i.e. \"%s\\\\times10^{%s}\").
+
+When nil, no transformation is made."
+  :group 'org-export-e-groff
+  :type '(choice
+          (string :tag "Format string")
+          (const :tag "No formatting")))
+
+
+;;;; Text markup
+
+(defcustom org-e-groff-text-markup-alist '((bold . "\\fB%s\\fP")
+                                           ;; from "verb"
+                                           (code . "\\fC%s\\fP") 
+                                           (italic . "\\fI%s\\fP")
+
+                                           ;;
+                                           ;; Strike through
+                                           ;; and underline need to be revised.
+
+                                           (strike-through . "\\fC%s\\fP")
+                                           (underline . "\\fI%s\\fP")
+                                           (verbatim .   "protectedtexttt"))
+  "Alist of Groff expressions to convert text markup.
+
+The key must be a symbol among `bold', `code', `italic',
+`strike-through', `underline' and `verbatim'.  The value is
+a formatting string to wrap fontified text with it. 
+
+If no association can be found for a given markup, text will be
+returned as-is."
+  :group 'org-export-e-groff
+  :type 'alist
+  :options '(bold code italic strike-through underline verbatim))
+
+
+;;;; Drawers
+
+(defcustom org-e-groff-format-drawer-function nil
+  "Function called to format a drawer in Groff code.
+
+The function must accept two parameters:
+  NAME      the drawer name, like \"LOGBOOK\"
+  CONTENTS  the contents of the drawer.
+
+The function should return the string to be exported.
+
+For example, the variable could be set to the following function
+in order to mimic default behaviour:
+
+\(defun org-e-groff-format-drawer-default \(name contents\)
+  \"Format a drawer element for Groff export.\"
+  contents\)"
+  :group 'org-export-e-groff
+  :type 'function)
+
+
+;;;; Inlinetasks
+
+(defcustom org-e-groff-format-inlinetask-function nil
+  "Function called to format an inlinetask in Groff code.
+
+The function must accept six parameters:
+  TODO      the todo keyword, as a string
+  TODO-TYPE the todo type, a symbol among `todo', `done' and nil.
+  PRIORITY  the inlinetask priority, as a string
+  NAME      the inlinetask name, as a string.
+  TAGS      the inlinetask tags, as a list of strings.
+  CONTENTS  the contents of the inlinetask, as a string.
+
+The function should return the string to be exported.
+
+For example, the variable could be set to the following function
+in order to mimic default behaviour:
+
+\(defun org-e-groff-format-inlinetask \(todo type priority name tags contents\)
+\"Format an inline task element for Groff export.\"
+  \(let ((full-title
+	 \(concat
+	  \(when todo
+            \(format \"\\fB%s\\fP \" todo))
+	  \(when priority (format \"[\\#%c] \" priority))
+	  title
+	  \(when tags
+            \(format \":%s:\"
+                    \(mapconcat 'identity tags \":\")))))
+    \(format (concat \".DS L\\n\"
+		    \"%s\\n\\n\"
+		    \"%s\"
+		    \".DE\")
+	    full-title contents))"
+  :group 'org-export-e-groff
+  :type 'function)
+
+
+;; Src blocks
+
+(defcustom org-e-groff-source-highlight nil
+  "Use GNU source highlight to embellish source blocks " 
+  :group 'org-export-e-groff
+  :type 'boolean)
+
+
+(defcustom org-e-groff-source-highlight-langs
+  '((emacs-lisp "lisp") (lisp "lisp") (clojure "lisp") 
+    (scheme "scheme")
+    (c "c") (cc "cpp") (csharp "csharp") (d "d") 
+    (fortran "fortran") (cobol "cobol") (pascal "pascal")
+    (ada "ada") (asm "asm")
+    (perl "perl") (cperl "perl") 
+    (python "python") (ruby "ruby") (tcl "tcl") (lua "lua")
+    (java "java") (javascript "javascript")
+    (tex "latex") 
+    (shell-script "sh") (awk "awk") (diff "diff") (m4 "m4")
+    (ocaml "caml") (caml "caml")
+    (sql "sql") (sqlite "sql")
+    (html "html") (css "css") (xml "xml")
+    (bat "bat") (bison "bison") (clipper "clipper")
+    (ldap "ldap") (opa "opa")
+    (php "php") (postscript "postscript") (prolog "prolog") 
+    (properties "properties") (makefile "makefile")
+    (tml "tml") (vala "vala") (vbscript "vbscript") (xorg "xorg")
+    )
+  "Alist mapping languages to their listing language counterpart.
+The key is a symbol, the major mode symbol without the \"-mode\".
+The value is the string that should be inserted as the language
+parameter for the listings package.  If the mode name and the
+listings name are the same, the language does not need an entry
+in this list - but it does not hurt if it is present."
+  :group 'org-export-e-groff
+  :type '(repeat
+          (list
+           (symbol :tag "Major mode       ")
+           (string :tag "Listings language"))))
+
+(defcustom org-e-groff-source-highlight-options nil
+  "Association list of options for the groff listings package.
+
+These options are supplied as a comma-separated list to the
+\\lstset command.  Each element of the association list should be
+a list containing two strings: the name of the option, and the
+value.  For example,
+
+  (setq org-e-groff-source-highlight-options
+    '((\"basicstyle\" \"\\small\")
+      (\"keywordstyle\" \"\\color{black}\\bfseries\\underbar\")))
+
+will typeset the code in a small size font with underlined, bold
+black keywords.
+
+Note that the same options will be applied to blocks of all
+languages."
+  :group 'org-export-e-groff
+  :type '(repeat
+          (list
+           (string :tag "Listings option name ")
+           (string :tag "Listings option value"))))
+
+
+
+(defvar org-e-groff-custom-lang-environments nil
+  "Alist mapping languages to language-specific Groff environments.
+
+It is used during export of src blocks by the listings and 
+groff packages.  For example,
+
+  \(setq org-e-groff-custom-lang-environments
+     '\(\(python \"pythoncode\"\)\)\)
+
+would have the effect that if org encounters begin_src python
+during groff export it will use pythoncode as the source-highlight
+language.")
+
+
+
+;;;; Plain text
+
+(defcustom org-e-groff-quotes
+  '(("fr"
+     ("\\(\\s-\\|[[(]\\|^\\)\"" . "«~")
+     ("\\(\\S-\\)\"" . "~»")
+     ("\\(\\s-\\|(\\|^\\)'" . "'"))
+    ("en"
+     ("\\(\\s-\\|[[(]\\|^\\)\"" . "``")
+     ("\\(\\S-\\)\"" . "''")
+     ("\\(\\s-\\|(\\|^\\)'" . "`")))
+  "Alist for quotes to use when converting english double-quotes.
+
+The CAR of each item in this alist is the language code.
+The CDR of each item in this alist is a list of three CONS:
+- the first CONS defines the opening quote;
+- the second CONS defines the closing quote;
+- the last CONS defines single quotes.
+
+For each item in a CONS, the first string is a regexp
+for allowed characters before/after the quote, the second
+string defines the replacement string for this quote."
+  :group 'org-export-e-groff
+  :type '(list
+          (cons :tag "Opening quote"
+                (string :tag "Regexp for char before")
+                (string :tag "Replacement quote     "))
+          (cons :tag "Closing quote"
+                (string :tag "Regexp for char after ")
+                (string :tag "Replacement quote     "))
+          (cons :tag "Single quote"
+                (string :tag "Regexp for char before")
+                (string :tag "Replacement quote     "))))
+
+
+;;;; Compilation
+
+(defcustom org-e-groff-pdf-process
+  '("pic %f | tbl | eqn | groff -mm | ps2pdf - > %b.pdf"
+    "pic %f | tbl | eqn | groff -mm | ps2pdf - > %b.pdf"
+    "pic %f | tbl | eqn | groff -mm | ps2pdf - > %b.pdf"
+    )
+
+  "Commands to process a Groff file to a PDF file.
+This is a list of strings, each of them will be given to the
+shell as a command.  %f in the command will be replaced by the
+full file name, %b by the file base name \(i.e. without
+extension) and %o by the base directory of the file."
+
+  :group 'org-export-pdf
+  :type '(choice
+          (repeat :tag "Shell command sequence"
+                  (string :tag "Shell command"))
+          (const :tag "2 runs of pdfgroff"
+                 ("pic %f | tbl | eqn | groff -mm | ps2pdf - > %b.pdf"
+                  "pic %f | tbl | eqn | groff -mm | ps2pdf - > %b.pdf" ))
+          (const :tag "3 runs of pdfgroff"
+                 ("pic %f | tbl | eqn | groff -mm | ps2pdf - > %b.pdf"
+                  "pic %f | tbl | eqn | groff -mm | ps2pdf - > %b.pdf"
+                  "pic %f | tbl | eqn | groff -mm | ps2pdf - > %b.pdf"))
+          (function)))
+
+(defcustom org-e-groff-logfiles-extensions
+  '("aux" "idx" "log" "out" "toc" "nav" "snm" "vrb")
+  "The list of file extensions to consider as Groff logfiles."
+  :group 'org-export-e-groff
+  :type '(repeat (string :tag "Extension")))
+
+(defcustom org-e-groff-remove-logfiles t
+  "Non-nil means remove the logfiles produced by PDF production.
+These are the .aux, .log, .out, and .toc files."
+  :group 'org-export-e-groff
+  :type 'boolean)
+
+
+(defcustom org-e-groff-organization "Org User"
+  "Name of the organization used to populate the .AF command."
+  :group 'org-export-e-groff
+  :type 'string)
+
+
+;; Preamble
+
+;; Adding GROFF as a block parser to make sure that its contents
+;; does not execute
+
+(add-to-list 'org-element-block-name-alist
+             '("GROFF" . org-element-export-block-parser))
+
+
+
+;;; Internal Functions
+
+
+(defun org-e-groff--caption/label-string (caption label info)
+  "Return caption and label Groff string for floats.
+
+CAPTION is a cons cell of secondary strings, the car being the
+standard caption and the cdr its short form.  LABEL is a string
+representing the label.  INFO is a plist holding contextual
+information.
+
+If there's no caption nor label, return the empty string.
+
+For non-floats, see `org-e-groff--wrap-label'."
+  (let ((label-str "" ))
+    (cond
+     ((and (not caption) (not label)) "")
+     ((not caption) (format "\\fI%s\\fP" label))
+     ;; Option caption format with short name.
+     ((cdr caption)
+      (format "%s\n.br\n%s - %s\n"
+              (org-export-data (cdr caption) info)
+              label-str
+              (org-export-data (car caption) info)))
+     ;; Standard caption format.
+     (t (format "\\fR%s\\fP"
+                (org-export-data (car caption) info)))))
+
+  )
+
+
+(defun org-e-groff--quotation-marks (text info)
+  "Export quotation marks depending on language conventions.
+TEXT is a string containing quotation marks to be replaced.  INFO
+is a plist used as a communication channel."
+  (mapc (lambda(l)
+          (let ((start 0))
+            (while (setq start (string-match (car l) text start))
+              (let ((new-quote (concat (match-string 1 text) (cdr l))))
+                (setq text (replace-match new-quote  t t text))))))
+        (cdr (or (assoc (plist-get info :language) org-e-groff-quotes)
+                 ;; Falls back on English.
+                 (assoc "en" org-e-groff-quotes))))
+  text)
+
+(defun org-e-groff--wrap-label (element output)
+  "Wrap label associated to ELEMENT around OUTPUT, if appropriate.
+This function shouldn't be used for floats.  See
+`org-e-groff--caption/label-string'."
+  (let ((label (org-element-property :name element)))
+    (if (or (not output) (not label) (string= output "") (string= label ""))
+        output
+      (concat (format "%s\n.br\n" label) output))))
+
+(defun org-e-groff--text-markup (text markup)
+  "Format TEXT depending on MARKUP text markup.
+See `org-e-groff-text-markup-alist' for details."
+  (let ((fmt (cdr (assq markup org-e-groff-text-markup-alist))))
+    (cond
+     ;; No format string: Return raw text.
+     ((not fmt) text)
+     ((string= "protectedtexttt" fmt)
+      (let ((start 0)
+            (trans '(("\\" . "\\")))
+            (rtn "")
+            char)
+        (while (string-match "[\\{}$%&_#~^]" text)
+          (setq char (match-string 0 text))
+          (if (> (match-beginning 0) 0)
+              (setq rtn (concat rtn (substring text 0 (match-beginning 0)))))
+          (setq text (substring text (1+ (match-beginning 0))))
+          (setq char (or (cdr (assoc char trans)) (concat "\\" char))
+                rtn (concat rtn char)))
+        (setq text (concat rtn text) )
+        (format "\\fC%s\\fP" text)))
+     ;; Else use format string.
+     (t (format fmt text)))))
+
+
+;;; Template
+
+(defun org-e-groff-template (contents info)
+  "Return complete document string after Groff conversion.
+CONTENTS is the transcoded contents string.  INFO is a plist
+holding export options."
+  (let* ((title (org-export-data (plist-get info :title) info))
+         (attr (read
+                (format "(%s)"
+                        (mapconcat
+                         #'identity
+                         (list (plist-get info :groff-class-options))
+                         " "))))
+         (class (plist-get info :groff-class))
+         (class-options (plist-get info :groff-class-options))
+         (classes (assoc class org-e-groff-classes))
+         (classes-options (car (last classes)) )
+         (heading-option (plist-get classes-options :heading ) )
+         (type-option (plist-get classes-options :type ) )
+         (last-option (plist-get classes-options :last-section ) )
+         (document-class-string
+          (let ()
+            (org-element-normalize-string
+             (let* ((header (nth 1 (assoc class org-e-groff-classes)))
+                    (document-class-item (if (stringp header) header "") )) 
+               document-class-item)))))
+    (concat
+     (unless (string= type-option "custom")
+       (let ()
+         (concat
+          (when (and (stringp document-class-string)
+                     (string= type-option "cover"))
+            (format ".COVER %s\n" document-class-string))
+          ;; 1. Insert Organization
+          (let ((firm-option (plist-get attr :firm)))
+            (cond 
+             ((stringp firm-option)
+              (format ".AF \"%s\" \n" firm-option))
+             (t (format ".AF \"%s\" \n" (or org-e-groff-organization "")) )))
+          ;; 2. Title
+          (let ((subtitle1 (plist-get attr :subtitle1))
+                (subtitle2 (plist-get attr :subtitle2)))
+
+            (cond 
+             ((string= "" title)
+              (format ".TL \"%s\" \"%s\" \n%s\n" 
+                      (or subtitle1 "")
+                      (or subtitle2 "") " ")
+              )
+             ((not (or subtitle1 subtitle2))
+              (format ".TL\n%s\n" 
+                      (or title "" )) )
+             (t
+              (format ".TL \"%s\" \"%s \" \n%s\n" 
+                      (or subtitle1 "")
+                      (or subtitle2 "") title)  )))
+
+          ;; 3. Author.
+          ;; In Groff, .AU *MUST* be placed after .TL
+          (let ((author (and (plist-get info :with-author)
+                             (let ((auth (plist-get info :author)))
+                               (and auth (org-export-data auth info)))))
+                (email (and (plist-get info :with-email)
+                            (org-export-data (plist-get info :email) info))))
+            (cond ((and author email (not (string= "" email)))
+                   (format ".AU \"%s\" \"%s\"\n" author email))
+                  (author (format ".AU \"%s\"\n" author))
+                  (t ".AU \"\" \n")))
+          
+          ;; 4. Author Title, if present
+          (let ((at-item (plist-get attr :author-title)  ))
+            (if (and at-item (stringp at-item))
+                (format ".AT \"%s\" \n" at-item )
+              ""))
+
+          ;; 5. Date.
+          (let ((date (org-export-data (plist-get info :date) info)))
+            (and date (format ".ND \"%s\"\n" date)))
+
+          (when (string= type-option "cover")
+            ".COVEND\n"
+            ) )))
+
+     ;;6. Hyphenation and Right Justification
+     (let ()
+       (set 'hyphenate (plist-get attr :hyphenate))
+       (set 'justify-right (plist-get attr :justify-right))
+       (concat 
+        (if justify-right
+            (case justify-right
+              ('yes ".SA 1 \n")
+              ('no ".SA 0 \n")
+              (t ""))
+          "")
+        (if hyphenate
+            (case hyphenate 
+              ('yes ".nr Hy 1 \n")
+              ('no ".nr Hy 0 \n")
+              (t "")
+              )
+          "") ))
+
+     (when (string= type-option "memo")
+       document-class-string)
+
+     ;; 7. Document's body.
+     
+     contents
+
+     ;; 8. Table of Content must be placed at the end being
+     ;; that it gets collected from all the headers. 
+     ;; In the case of letters, signature will be placed instead.
+
+
+     (cond 
+      ((string= last-option "toc")
+       ".TC")
+      ((string= last-option "sign")
+       (let ((fc-item (plist-get attr :closing)))
+         (concat (if (stringp fc-item)
+                     (format ".FC \"%s\" \n" fc-item)
+                   ".FC\n")
+                 ".SG")))
+
+      (t ""))
+     )
+    ))
+
+
+
+;;; Transcode Functions
+
+;;;; Babel Call
+;;
+;; Babel Calls are ignored.
+
+
+;;;; Bold
+
+(defun org-e-groff-bold (bold contents info)
+  "Transcode BOLD from Org to Groff.
+CONTENTS is the text with bold markup.  INFO is a plist holding
+contextual information."
+  (org-e-groff--text-markup contents 'bold))
+
+
+;;;; Center Block
+
+(defun org-e-groff-center-block (center-block contents info)
+  "Transcode a CENTER-BLOCK element from Org to Groff.
+CONTENTS holds the contents of the center block.  INFO is a plist
+holding contextual information."
+  (org-e-groff--wrap-label
+   center-block
+   (format ".DS C \n%s\n.DE" contents)))
+
+
+;;;; Clock
+
+(defun org-e-groff-clock (clock contents info)
+  "Transcode a CLOCK element from Org to Groff.
+CONTENTS is nil.  INFO is a plist holding contextual
+information."
+  (concat
+   (format "\\fB%s\\fP " org-clock-string)
+   (format org-e-groff-inactive-timestamp-format
+           (concat (org-translate-time (org-element-property :value clock))
+                   (let ((time (org-element-property :time clock)))
+                     (and time (format " (%s)" time)))))))
+
+
+;;;; Code
+
+(defun org-e-groff-code (code contents info)
+  "Transcode a CODE object from Org to Groff.
+CONTENTS is nil.  INFO is a plist used as a communication
+channel."
+  (org-e-groff--text-markup (org-element-property :value code) 'code))
+
+
+;;;; Comment
+;;
+;; Comments are ignored.
+
+
+;;;; Comment Block
+;;
+;; Comment Blocks are ignored.
+
+
+;;;; Drawer
+
+(defun org-e-groff-drawer (drawer contents info)
+  "Transcode a DRAWER element from Org to Groff.
+CONTENTS holds the contents of the block.  INFO is a plist
+holding contextual information."
+  (let* ((name (org-element-property :drawer-name drawer))
+         (output (if (functionp org-e-groff-format-drawer-function)
+                     (funcall org-e-groff-format-drawer-function
+                              name contents)
+                   ;; If there's no user defined function: simply
+                   ;; display contents of the drawer.
+                   contents)))
+    (org-e-groff--wrap-label drawer output)))
+
+
+;;;; Dynamic Block
+
+(defun org-e-groff-dynamic-block (dynamic-block contents info)
+  "Transcode a DYNAMIC-BLOCK element from Org to Groff.
+CONTENTS holds the contents of the block.  INFO is a plist
+holding contextual information.  See `org-export-data'."
+  (org-e-groff--wrap-label dynamic-block contents))
+
+
+;;;; Entity
+
+(defun org-e-groff-entity (entity contents info)
+  "Transcode an ENTITY object from Org to Groff.
+CONTENTS are the definition itself.  INFO is a plist holding
+contextual information."
+  (let ((ent (org-element-property :utf8 entity)))
+    ent))
+
+
+;;;; Example Block
+
+(defun org-e-groff-example-block (example-block contents info)
+  "Transcode an EXAMPLE-BLOCK element from Org to Groff.
+CONTENTS is nil.  INFO is a plist holding contextual
+information."
+  (org-e-groff--wrap-label
+   example-block
+   (format ".DS L\n%s\n.DE"
+           (org-export-format-code-default example-block info))))
+
+
+;;;; Export Block
+
+(defun org-e-groff-export-block (export-block contents info)
+  "Transcode a EXPORT-BLOCK element from Org to Groff.
+CONTENTS is nil.  INFO is a plist holding contextual information."
+  (when (string= (org-element-property :type export-block) "GROFF")
+    (org-remove-indentation (org-element-property :value export-block))))
+
+
+;;;; Export Snippet
+
+(defun org-e-groff-export-snippet (export-snippet contents info)
+  "Transcode a EXPORT-SNIPPET object from Org to Groff.
+CONTENTS is nil.  INFO is a plist holding contextual information."
+  (when (eq (org-export-snippet-backend export-snippet) 'e-groff)
+    (org-element-property :value export-snippet)))
+
+
+;;;; Fixed Width
+
+(defun org-e-groff-fixed-width (fixed-width contents info)
+  "Transcode a FIXED-WIDTH element from Org to Groff.
+CONTENTS is nil.  INFO is a plist holding contextual information."
+  (org-e-groff--wrap-label
+   fixed-width
+   (format "\\fC\n%s\\fP"
+           (org-remove-indentation
+            (org-element-property :value fixed-width)))))
+
+
+;;;; Footnote Definition
+;;
+;; Footnote Definitions are ignored.
+
+;; 
+;; Footnotes are handled automatically in GROFF. Although
+;; manual references can be added, not really required.
+;; 
+
+(defun org-e-groff-footnote-reference (footnote-reference contents info)
+  ;; Changing from info to footnote-reference
+  (let* (( raw (org-export-get-footnote-definition footnote-reference info))
+		 (n (org-export-get-footnote-number footnote-reference info))
+		 (data (org-trim (org-export-data raw info))))
+	(format "\\u\\s-2%s\\d\\s+2\n.FS %s\n%s\n.FE\n" n n data)
+	))
+
+;;;; Headline
+
+(defun org-e-groff-headline (headline contents info)
+  "Transcode an HEADLINE element from Org to Groff.
+CONTENTS holds the contents of the headline.  INFO is a plist
+holding contextual information."
+  (let* ((class (plist-get info :groff-class))
+         (level (org-export-get-relative-level headline info))
+         (numberedp (org-export-numbered-headline-p headline info))
+         ;; Section formatting will set two placeholders: one for the
+         ;; title and the other for the contents.
+         (classes (assoc class org-e-groff-classes))
+         (classes-options (car (last classes)) )
+         (heading-option (plist-get classes-options :heading ) )
+         (section-fmt
+          (let ()
+            (cond
+             ((and (symbolp heading-option)
+                   (fboundp heading-option))
+              (funcall heading-option level numberedp))
+             ((> level 7) nil)
+             (t (if numberedp
+                    (concat ".H " (number-to-string level) " \"%s\"\n%s")
+                  ".HU \"%s\"\n%s")))))
+         ;; End of section-fmt
+         (text (org-export-data (org-element-property :title headline) info))
+         (todo
+          (and (plist-get info :with-todo-keywords)
+               (let ((todo (org-element-property :todo-keyword headline)))
+                 (and todo (org-export-data todo info)))))
+         (todo-type (and todo (org-element-property :todo-type headline)))
+         (tags (and (plist-get info :with-tags)
+                    (org-export-get-tags headline info)))
+         (priority (and (plist-get info :with-priority)
+                        (org-element-property :priority headline)))
+         ;; Create the headline text along with a no-tag version.  The
+         ;; latter is required to remove tags from table of contents.
+         (full-text (if (functionp org-e-groff-format-headline-function)
+                        ;; User-defined formatting function.
+                        (funcall org-e-groff-format-headline-function
+                                 todo todo-type priority text tags)
+                      ;; Default formatting.
+                      (concat
+                       (when todo
+                         (format "\\fB%s\\fP " todo))
+                       (when priority (format " [\\#%c] " priority))
+                       text
+                       (when tags
+                         (format " \\fC:%s:\\fP "
+                                 (mapconcat 'identity tags ":"))))))
+         (full-text-no-tag
+          (if (functionp org-e-groff-format-headline-function)
+              ;; User-defined formatting function.
+              (funcall org-e-groff-format-headline-function
+                       todo todo-type priority text nil)
+            ;; Default formatting.
+            (concat
+             (when todo (format "\\fB%s\\fP " todo))
+             (when priority (format " [\\#%c] " priority))
+             text)))
+         ;; Associate some \label to the headline for internal links.
+         ;; 	 (headline-label 
+         ;; 	  (format "\\label{sec-%s}\n"
+         ;; 		  (mapconcat 'number-to-string
+         ;; 			     (org-export-get-headline-number headline info)
+         ;; 			     "-")))
+         (headline-label "")
+         (pre-blanks
+          (make-string (org-element-property :pre-blank headline) 10)))
+    
+    (cond
+     ;; Case 1: This is a footnote section: ignore it.
+     ((org-element-property :footnote-section-p headline) nil)
+     ;; Case 2. This is a deep sub-tree: export it as a list item.
+     ;;         Also export as items headlines for which no section
+     ;;         format has been found.
+     ((or (not section-fmt) (org-export-low-level-p headline info))
+      ;; Build the real contents of the sub-tree.
+      (let ((low-level-body
+             (concat
+              ;; If the headline is the first sibling, start a list.
+              (when (org-export-first-sibling-p headline)
+                (format "%s\n" (if numberedp ".AL 1\n" ".DL \n")))
+              ;; Itemize headline
+              ".LI\n" full-text "\n" headline-label pre-blanks contents)))
+        ;; If headline is not the last sibling simply return
+        ;; LOW-LEVEL-BODY.  Otherwise, also close the list, before any
+        ;; blank line.
+        (if (not (org-export-last-sibling-p headline)) low-level-body
+          (replace-regexp-in-string
+           "[ \t\n]*\\'"
+           (concat "\n.LE" )
+           low-level-body))))
+     ;; Case 3. Standard headline.  Export it as a section.
+     (t
+      (format section-fmt full-text
+              (concat headline-label pre-blanks contents)) ))))
+
+
+;;;; Horizontal Rule
+;; Not supported
+
+
+;;;; Inline Babel Call
+;;
+;; Inline Babel Calls are ignored.
+
+;;;; Inline Src Block
+
+(defun org-e-groff-inline-src-block (inline-src-block contents info)
+  "Transcode an INLINE-SRC-BLOCK element from Org to Groff.
+CONTENTS holds the contents of the item.  INFO is a plist holding
+contextual information."
+  (let* ((code (org-element-property :value inline-src-block)))
+    (cond
+     (org-e-groff-source-highlight
+      (let* ((tmpdir (if (featurep 'xemacs)
+                         temp-directory 
+                       temporary-file-directory ))
+             (in-file  (make-temp-name 
+                        (expand-file-name "srchilite" tmpdir))  )
+             (out-file (make-temp-name 
+                        (expand-file-name "reshilite" tmpdir)) )
+             (org-lang (org-element-property :language inline-src-block))
+             (lst-lang (cadr (assq (intern org-lang)
+                                   org-e-groff-source-highlight-langs)))
+             
+             (cmd (concat (expand-file-name "source-highlight")
+                          " -s " lst-lang
+                          " -f groff_mm_color "
+                          " -i " in-file
+                          " -o " out-file
+                          )
+                  ))
+
+        (if lst-lang
+            (let ((code-block "" ))
+              (with-temp-file in-file (insert code))
+              (shell-command cmd)
+              (setq code-block  (org-file-contents out-file) )
+              (delete-file in-file)
+              (delete-file out-file)
+              code-block)
+          (format ".DS I\n\\fC\\m[black]%s\\m[]\\fP\n.DE\n"
+                  code))
+
+        ))
+
+     ;; Do not use a special package: transcode it verbatim.
+     (t
+      (concat ".DS I\n" "\\fC" code "\\fP\n.DE\n"))
+     )))
+
+
+;;;; Inlinetask
+
+
+(defun org-e-groff-inlinetask (inlinetask contents info)
+  "Transcode an INLINETASK element from Org to Groff.
+CONTENTS holds the contents of the block.  INFO is a plist
+holding contextual information."
+  (let ((title (org-export-data (org-element-property :title inlinetask) info))
+        (todo (and (plist-get info :with-todo-keywords)
+                   (let ((todo (org-element-property :todo-keyword inlinetask)))
+                     (and todo (org-export-data todo info)))))
+        (todo-type (org-element-property :todo-type inlinetask))
+        (tags (and (plist-get info :with-tags)
+                   (org-export-get-tags inlinetask info)))
+        (priority (and (plist-get info :with-priority)
+                       (org-element-property :priority inlinetask))))
+    ;; If `org-e-groff-format-inlinetask-function' is provided, call it
+    ;; with appropriate arguments.
+    (if (functionp org-e-groff-format-inlinetask-function)
+        (funcall org-e-groff-format-inlinetask-function
+                 todo todo-type priority title tags contents)
+      ;; Otherwise, use a default template.
+      (org-e-groff--wrap-label
+       inlinetask
+       (let ((full-title
+              (concat
+               (when todo (format "\\fB%s\\fP " todo))
+               (when priority (format " [\\#%c] " priority))
+               title
+               (when tags (format " \\fC:%s:\\fP "
+                                  (mapconcat 'identity tags ":"))))))
+         (format (concat "\n.DS I\n"
+                         "%s\n"
+                         ".sp"
+                         "%s\n"
+                         ".DE")
+                 full-title contents))))))
+
+
+;;;; Italic
+
+(defun org-e-groff-italic (italic contents info)
+  "Transcode ITALIC from Org to Groff.
+CONTENTS is the text with italic markup.  INFO is a plist holding
+contextual information."
+  (org-e-groff--text-markup contents 'italic))
+
+
+;;;; Item
+
+
+(defun org-e-groff-item (item contents info)
+  "Transcode an ITEM element from Org to Groff.
+CONTENTS holds the contents of the item.  INFO is a plist holding
+contextual information."
+  (let* ((counter
+          (let ((count (org-element-property :counter item))
+                (level
+                 (loop for parent in (org-export-get-genealogy item)
+                       count (eq (org-element-type parent) 'plain-list)
+                       until (eq (org-element-type parent) 'headline))))))
+
+
+		 (bullet (org-element-property :bullet item))
+		 (type (org-element-property :type (org-element-property :parent item)))
+
+         (checkbox (case (org-element-property :checkbox item)
+                     (on "\\o'\\(sq\\(mu'")			
+                     (off "\\(sq ")					
+                     (trans "\\o'\\(sq\\(mi'"   )))
+
+         (tag (let ((tag (org-element-property :tag item)))
+                ;; Check-boxes must belong to the tag.
+                (and tag (format "[%s]"
+                                 (concat checkbox
+                                         (org-export-data tag info)))))))
+
+	(cond 
+	 ((or checkbox tag)
+	  (concat ".LI " "\"" (or tag (concat " " checkbox)) "\""
+              "\n"
+              (org-trim (or contents " " ) ))  )
+     ((eq type 'ordered)
+      (concat ".LI"
+              "\n"
+              (org-trim (or contents " " ) )))
+     (t 
+      (let* ((bullet (org-trim bullet))
+             (marker (cond  ((string= "-" bullet) "\\(em")
+                            ((string= "*" bullet) "\\(bu")
+                            (t "\\(dg") ) ))
+        (concat ".LI " marker "\n"  
+                (org-trim (or contents " " ) )))))
+    ))
+
+
+
+;;;; Keyword
+
+
+(defun org-e-groff-keyword (keyword contents info)
+  "Transcode a KEYWORD element from Org to Groff.
+CONTENTS is nil.  INFO is a plist holding contextual information."
+  (let ((key (org-element-property :key keyword))
+        (value (org-element-property :value keyword)))
+    (cond
+     ((string= key "GROFF") value)
+     (t nil))))
+
+
+;;;; Groff Environment
+
+(defun org-e-groff-groff-environment (groff-environment contents info)
+  "Transcode a GROFF-ENVIRONMENT element from Org to Groff.
+CONTENTS is nil.  INFO is a plist holding contextual information."
+  (let ((label (org-element-property :name groff-environment))
+        (value (org-remove-indentation
+                (org-element-property :value groff-environment))))
+    (if (not (org-string-nw-p label)) value
+      ;; Environment is labelled: label must be within the environment
+      ;; (otherwise, a reference pointing to that element will count
+      ;; the section instead).
+      (with-temp-buffer
+        (insert value)
+        (goto-char (point-min))
+        (forward-line)
+        (insert (format "%s\n" label))
+        (buffer-string)))))
+
+
+;;;; Groff Fragment
+
+(defun org-e-groff-groff-fragment (groff-fragment contents info)
+  "Transcode a GROFF-FRAGMENT object from Org to Groff.
+CONTENTS is nil.  INFO is a plist holding contextual information."
+  (org-element-property :value groff-fragment))
+
+
+;;;; Line Break
+
+(defun org-e-groff-line-break (line-break contents info)
+  "Transcode a LINE-BREAK object from Org to Groff.
+CONTENTS is nil.  INFO is a plist holding contextual information."
+  ".br\n")
+
+
+;;;; Link
+;;;;
+;;;; Inline images just place a call to .PSPIC or .PS/.PE
+;;;  and load the graph.
+;;;;
+
+
+(defun org-e-groff-link--inline-image (link info)
+  "Return Groff code for an inline image.
+LINK is the link pointing to the inline image.  INFO is a plist
+used as a communication channel."
+  (let* ((parent (org-export-get-parent-element link))
+         (path (let ((raw-path (org-element-property :path link)))
+                 (if (not (file-name-absolute-p raw-path)) raw-path
+                   (expand-file-name raw-path))))
+         
+         (attr
+          (read
+           (format
+            "(%s)"
+            (mapconcat
+             #'identity
+             (org-element-property :attr_groff parent)
+             " "))))
+
+         ;; Retrieve groff attributes from the element around.
+
+         ;; Attributes are going to be
+         ;; :position (left|center|right)
+         ;; :width id
+         ;; :height id
+
+         )
+
+    ;; Now clear ATTR from any special keyword and set a default
+    ;; value if nothing is left.
+
+    (setq placement
+          (case (plist-get attr :position)
+            ('center "")
+            ('left "-L")
+            ('right "-R")
+            (t "")))
+
+    (setq width  (or  (plist-get attr :width) "")  )
+    (setq height  (or  (plist-get attr :height) "" )  )
+
+    (setq caption 
+          (org-e-groff--caption/label-string
+           (org-element-property :caption parent)
+           (org-element-property :name parent)
+           info)
+          )
+
+    ;; Return proper string, depending on DISPOSITION.
+    ;;
+    ;; TODO Needs to be expanded with attributes
+    ;; Caption needs to be added
+    ;; by adding .FG "caption"
+
+    (cond
+     ((string-match ".\.pic$" raw-path) 
+      (format "\n.PS\ncopy \"%s\"\n.PE\n.FG \"%s\" " raw-path caption))
+     (t (format "\n.DS L F\n.PSPIC %s \"%s\" %s %s\n.FG \"%s\"\n.DE " 
+                placement raw-path width height caption)))))
+
+(defun org-e-groff-link (link desc info)
+  "Transcode a LINK object from Org to Groff.
+
+DESC is the description part of the link, or the empty string.
+INFO is a plist holding contextual information.  See
+`org-export-data'."
+  
+  (let* ((type (org-element-property :type link))
+         (raw-path (org-element-property :path link))
+         ;; Ensure DESC really exists, or set it to nil.
+         (desc (and (not (string= desc "")) desc))
+         (imagep (org-export-inline-image-p
+                  link org-e-groff-inline-image-rules))
+         (path (cond
+                ((member type '("http" "https" "ftp" "mailto"))
+                 (concat type ":" raw-path))
+                ((string= type "file")
+                 (when (string-match "\\(.+\\)::.+" raw-path)
+                   (setq raw-path (match-string 1 raw-path)))
+                 (if (file-name-absolute-p raw-path)
+                     (concat "file://" (expand-file-name raw-path))
+                   (concat "file://" raw-path)))
+                (t raw-path)))
+         protocol)
+    (cond
+     ;; Image file.
+     (imagep (org-e-groff-link--inline-image link info))
+     ;; import groff files
+     ((and (string= type "file") 
+           (string-match ".\.groff$" raw-path))
+      (concat ".so " raw-path "\n"))
+     ;; Radio link: Transcode target's contents and use them as link's
+     ;; description.
+     ((string= type "radio")
+      (let ((destination (org-export-resolve-radio-link link info)))
+        (when destination
+          (format "\\fI [%s] \\fP"
+                  (org-export-solidify-link-text path) ))))
+     ;; Links pointing to an headline: Find destination and build
+     ;; appropriate referencing command.
+     ((member type '("custom-id" "fuzzy" "id"))
+      (let ((destination (if (string= type "fuzzy")
+                             (org-export-resolve-fuzzy-link link info)
+                           (org-export-resolve-id-link link info))))
+        (case (org-element-type destination)
+          ;; Id link points to an external file.
+          (plain-text
+           (if desc (format "%s \\fBat\\fP \\fIfile://%s\\fP" desc destination)
+             (format "\\fI file://%s \\fP" destination)))
+          ;; Fuzzy link points nowhere.
+          ('nil
+           (format org-e-groff-link-with-unknown-path-format
+                   (or desc
+                       (org-export-data
+                        (org-element-property :raw-link link) info))))
+          ;; Fuzzy link points to an invisible target.
+          (keyword nil)
+          ;; LINK points to an headline.  If headlines are numbered
+          ;; and the link has no description, display headline's
+          ;; number.  Otherwise, display description or headline's
+          ;; title.
+          (headline
+           (let ((label ""))
+             (if (and (plist-get info :section-numbers) (not desc))
+                 (format "\\fI%s\\fP" label)
+               (format "\\fI%s\\fP"
+                       (or desc
+                           (org-export-data
+                            (org-element-property :title destination) info))))))
+          ;; Fuzzy link points to a target.  Do as above.
+          (otherwise
+           (let ((path (org-export-solidify-link-text path)))
+             (if (not desc) (format "\\fI%s\\fP" path)
+               (format "%s \\fBat\\fP \\fI%s\\fP" desc path)))))))
+     ;; External link with a description part.
+     ((and path desc) (format "%s \\fBat\\fP \\fI%s\\fP" path desc))
+     ;; External link without a description part.
+     (path (format "\\fI%s\\fP" path))
+     ;; No path, only description.  Try to do something useful.
+     (t (format org-e-groff-link-with-unknown-path-format desc)))))
+
+
+;;;; Macro
+
+(defun org-e-groff-macro (macro contents info)
+  "Transcode a MACRO element from Org to Groff.
+CONTENTS is nil.  INFO is a plist holding contextual information."
+  ;; Use available tools.
+  (org-export-expand-macro macro info))
+
+
+;;;; Paragraph
+
+(defun org-e-groff-paragraph (paragraph contents info)
+  "Transcode a PARAGRAPH element from Org to Groff.
+CONTENTS is the contents of the paragraph, as a string.  INFO is
+the plist used as a communication channel."
+  (setq parent (plist-get (nth 1 paragraph) :parent))
+  (when parent
+    (let ((parent-type (car parent)) 
+          (fixed-paragraph ""))
+      (cond ((and (eq parent-type 'item)
+                  (plist-get (nth 1 parent) :bullet ) )
+             (setq fixed-paragraph (concat "" contents)) )
+            ((eq parent-type 'section)
+             (setq fixed-paragraph (concat ".P\n" contents) ) )
+            ((eq parent-type 'footnote-definition)
+             (setq fixed-paragraph (concat "" contents) ))
+            (t (setq fixed-paragraph (concat "" contents)) ) 
+            )
+      fixed-paragraph)
+    )
+  )
+
+
+;;;; Plain List
+
+(defun org-e-groff-plain-list (plain-list contents info)
+  "Transcode a PLAIN-LIST element from Org to Groff.
+CONTENTS is the contents of the list.  INFO is a plist holding
+contextual information."
+  (let* ((type (org-element-property :type plain-list))
+         (attr (mapconcat #'identity
+                          (org-element-property :attr_groff plain-list)
+                          " "))
+         (groff-type (cond
+                      ((eq type 'ordered) ".AL")
+                      ((eq type 'unordered) ".BL")
+                      ((eq type 'descriptive) ".VL 2.0i"))))
+    (org-e-groff--wrap-label
+     plain-list
+     (format "%s\n%s\n.LE"
+             groff-type
+             contents ))))
+
+
+;;;; Plain Text
+
+(defun org-e-groff-plain-text (text info)
+  "Transcode a TEXT string from Org to Groff.
+TEXT is the string to transcode.  INFO is a plist holding
+contextual information."
+  ;; Protect 
+  (setq text (replace-regexp-in-string
+              "\\(?:[^\\]\\|^\\)\\(\\\\\\)\\(?:[^%$#&{}~^_\\]\\|$\\)"
+              "$\\" text nil t 1))
+
+
+  ;; Handle quotation marks
+  (setq text (org-e-groff--quotation-marks text info))
+
+  ;; Handle break preservation if required.
+  (when (plist-get info :preserve-breaks)
+    (setq text (replace-regexp-in-string "\\(\\\\\\\\\\)?[ \t]*\n" " \\\\\\\\\n"
+                                         text)))
+  ;; Return value.
+  text)
+
+
+
+;;;; Planning
+
+(defun org-e-groff-planning (planning contents info)
+  "Transcode a PLANNING element from Org to Groff.
+CONTENTS is nil.  INFO is a plist holding contextual
+information."
+  (concat
+   (mapconcat
+    'identity
+    (delq nil
+          (list
+           (let ((closed (org-element-property :closed planning)))
+             (when closed
+               (concat
+                (format "\\fR %s \\fP" org-closed-string)
+                (format org-e-groff-inactive-timestamp-format
+                        (org-translate-time closed)))))
+           (let ((deadline (org-element-property :deadline planning)))
+             (when deadline
+               (concat
+                (format "\\fB %s \\fP" org-deadline-string)
+                (format org-e-groff-active-timestamp-format
+                        (org-translate-time deadline)))))
+           (let ((scheduled (org-element-property :scheduled planning)))
+             (when scheduled
+               (concat
+                (format "\\fR %s \\fP" org-scheduled-string)
+                (format org-e-groff-active-timestamp-format
+                        (org-translate-time scheduled)))))))
+    "")
+   ""))
+
+
+;;;; Property Drawer
+
+(defun org-e-groff-property-drawer (property-drawer contents info)
+  "Transcode a PROPERTY-DRAWER element from Org to Groff.
+CONTENTS is nil.  INFO is a plist holding contextual
+information."
+  ;; The property drawer isn't exported but we want separating blank
+  ;; lines nonetheless.
+  "")
+
+
+;;;; Quote Block
+
+(defun org-e-groff-quote-block (quote-block contents info)
+  "Transcode a QUOTE-BLOCK element from Org to Groff.
+CONTENTS holds the contents of the block.  INFO is a plist
+holding contextual information."
+  (org-e-groff--wrap-label
+   quote-block
+   (format ".DS I\n.I\n%s\n.R\n.DE" contents)))
+
+
+;;;; Quote Section
+
+(defun org-e-groff-quote-section (quote-section contents info)
+  "Transcode a QUOTE-SECTION element from Org to Groff.
+CONTENTS is nil.  INFO is a plist holding contextual information."
+  (let ((value (org-remove-indentation
+                (org-element-property :value quote-section))))
+    (when value (format ".DS L\n\\fI%s\\fP\n.DE\n" value))))
+
+
+;;;; Radio Target
+
+(defun org-e-groff-radio-target (radio-target text info)
+  "Transcode a RADIO-TARGET object from Org to Groff.
+TEXT is the text of the target.  INFO is a plist holding
+contextual information."
+  (format "%s - %s"
+          (org-export-solidify-link-text
+           (org-element-property :value radio-target))
+          text))
+
+
+;;;; Section
+
+(defun org-e-groff-section (section contents info)
+  "Transcode a SECTION element from Org to Groff.
+CONTENTS holds the contents of the section.  INFO is a plist
+holding contextual information."
+  contents)
+
+
+;;;; Special Block
+
+(defun org-e-groff-special-block (special-block contents info)
+  "Transcode a SPECIAL-BLOCK element from Org to Groff.
+CONTENTS holds the contents of the block.  INFO is a plist
+holding contextual information."
+  (let ((type (downcase (org-element-property :type special-block))))
+    (org-e-groff--wrap-label
+     special-block
+     (format "%s\n" contents))))
+
+
+;;;; Src Block
+
+(defun org-e-groff-src-block (src-block contents info)
+  "Transcode a SRC-BLOCK element from Org to Groff.
+CONTENTS holds the contents of the item.  INFO is a plist holding
+contextual information."
+
+  (let* ((lang (org-element-property :language src-block))
+         (caption (org-element-property :caption src-block))
+         (label (org-element-property :name src-block))
+         (code (org-element-property :value src-block))
+         (custom-env (and lang
+                          (cadr (assq (intern lang)
+                                      org-e-groff-custom-lang-environments))))
+         (num-start (case (org-element-property :number-lines src-block)
+                      (continued (org-export-get-loc src-block info))
+                      (new 0)))
+         (retain-labels (org-element-property :retain-labels src-block)))
+    (cond
+     ;; Case 1.  No source fontification.
+     ((not org-e-groff-source-highlight)
+      (let ((caption-str (org-e-groff--caption/label-string caption label info))
+            (float-env (when caption ".DS I\n\\fC%s\\fP\n.DE\n")))
+        (format
+         (or float-env "%s")
+         (concat 
+          (format ".DS I\n\\fC%s\\fP\n.DE\n.EX \"%s\"\n"
+                  (org-export-format-code-default src-block info) 
+                  (or caption-str ""))))))
+     ( (and org-e-groff-source-highlight) 
+       (let* ((tmpdir (if (featurep 'xemacs)
+                          temp-directory 
+                        temporary-file-directory ))
+              
+              (in-file  (make-temp-name 
+                         (expand-file-name "srchilite" tmpdir))  )
+              (out-file (make-temp-name 
+                         (expand-file-name "reshilite" tmpdir)) )
+
+              (org-lang (org-element-property :language src-block))
+              (lst-lang (cadr (assq (intern org-lang)
+                                    org-e-groff-source-highlight-langs)) )
+              
+              (cmd (concat "source-highlight"
+                           " -s " lst-lang
+                           " -f groff_mm_color "
+                           " -i " in-file
+                           " -o " out-file
+                           )
+                   ))
+         
+         (if lst-lang
+             (let ((code-block "" ))
+               (with-temp-file in-file (insert code))
+               (shell-command cmd)
+               (setq code-block  (org-file-contents out-file) )
+               (delete-file in-file)
+               (delete-file out-file)
+               code-block)
+           (format ".DS I\n\\fC\\m[black]%s\\m[]\\fP\n.DE"
+                   code))
+
+         )
+       )
+
+     (custom-env (format ".DS I\n\\fC%s\\fP\n.DE"
+                         custom-env
+                         (src-block)
+                         custom-env))
+
+     )))
+
+
+;;;; Statistics Cookie
+
+(defun org-e-groff-statistics-cookie (statistics-cookie contents info)
+  "Transcode a STATISTICS-COOKIE object from Org to Groff.
+CONTENTS is nil.  INFO is a plist holding contextual information."
+  (org-element-property :value statistics-cookie))
+
+
+;;;; Strike-Through
+
+(defun org-e-groff-strike-through (strike-through contents info)
+  "Transcode STRIKE-THROUGH from Org to Groff.
+CONTENTS is the text with strike-through markup.  INFO is a plist
+holding contextual information."
+  (org-e-groff--text-markup contents 'strike-through))
+
+;;;; Subscript
+
+(defun org-e-groff-subscript (subscript contents info)
+  "Transcode a SUBSCRIPT object from Org to Groff.
+CONTENTS is the contents of the object.  INFO is a plist holding
+contextual information."
+  (format  "\\d\\s-2%s\\s+2\\u" contents))
+
+;;;; Superscript "^_%s$
+
+(defun org-e-groff-superscript (superscript contents info)
+  "Transcode a SUPERSCRIPT object from Org to Groff.
+CONTENTS is the contents of the object.  INFO is a plist holding
+contextual information."
+  (format  "\\u\\s-2%s\\s+2\\d" contents))
+
+
+;;;; Table
+;;
+;; `org-e-groff-table' is the entry point for table transcoding.  It
+;; takes care of tables with a "verbatim" attribute.  Otherwise, it
+;; delegates the job to  `org-e-groff-table--org-table' function, 
+;; depending of the type of the table.
+;;
+;; `org-e-groff-table--align-string' is a subroutine used to build
+;; alignment string for Org tables.
+
+(defun org-e-groff-table (table contents info)
+  "Transcode a TABLE element from Org to Groff.
+CONTENTS is the contents of the table.  INFO is a plist holding
+contextual information."
+  (cond
+   ;; Case 1: verbatim table.
+   ((or org-e-groff-tables-verbatim
+        (let ((attr
+               (read
+                (format
+                 "(%s)"
+                 (mapconcat
+                  #'identity
+                  (org-element-property :attr_groff table)
+                  " ")))) )
+
+          (and attr (plist-get attr :verbatim))))
+
+    (format ".DS L\n\\fC%s\\fP\n.DE"
+            ;; Re-create table, without affiliated keywords.
+            (org-trim
+             (org-element-interpret-data
+              `(table nil ,@(org-element-contents table))))))
+   ;; Case 2: Standard table.
+   (t (org-e-groff-table--org-table table contents info))))
+
+(defun org-e-groff-table--align-string (divider table info)
+  "Return an appropriate Groff alignment string.
+TABLE is the considered table.  INFO is a plist used as
+a communication channel."
+  (let ((attr
+         (read
+          (format
+           "(%s)"
+           (mapconcat
+            #'identity
+            (org-element-property :attr_groff table)
+            " ")))))
+
+    (setq align 	
+          (case (plist-get  attr :align)
+            ('center "c")
+            ('left "l")
+            ('right "r")))
+
+    (let (alignment)
+      ;; Extract column groups and alignment from first (non-rule)
+      ;; row.
+      (org-element-map
+       (org-element-map
+        table 'table-row
+        (lambda (row)
+          (and (eq (org-element-property :type row) 'standard) row))
+        info 'first-match)
+       'table-cell
+       (lambda (cell)
+         (let* ((borders (org-export-table-cell-borders cell info))
+                (raw-width (org-export-table-cell-width cell info))
+                (width-cm (when raw-width (/ raw-width 5)))
+                (width (if raw-width (format "w(%dc)" (if (< width-cm 1) 1 width-cm)) "") ))
+           ;; Check left border for the first cell only.
+           (when (and (memq 'left borders) (not alignment))
+             (push "|" alignment))
+           (push 
+            (if (not align)
+                (case (org-export-table-cell-alignment cell info)
+                  (left (concat "l" width divider) )
+                  (right (concat "r" width divider))
+                  (center (concat "c" width divider)))
+              (concat align divider))
+            alignment)
+           (when (memq 'right borders) (push "|" alignment))))
+       info)
+      (apply 'concat (reverse alignment)))
+
+    ))
+
+(defun org-e-groff-table--org-table (table contents info)
+  "Return appropriate Groff code for an Org table.
+
+TABLE is the table type element to transcode.  CONTENTS is its
+contents, as a string.  INFO is a plist used as a communication
+channel.
+
+This function assumes TABLE has `org' as its `:type' attribute."
+  (let* ((label (org-element-property :name table))
+         (caption (org-e-groff--caption/label-string
+                   (org-element-property :caption table) label info))
+         (attr
+          (read
+           (format
+            "(%s)"
+            (mapconcat
+             #'identity
+             (org-element-property :attr_groff table)
+             " "))))
+
+         (divider (if (plist-get attr :divider)
+                      "|"
+                    " "))
+
+         ;; Determine alignment string.
+         (alignment (org-e-groff-table--align-string divider table info))
+         ;; Extract others display options.
+
+         )
+    ;; Prepare the final format string for the table.
+
+    (setq lines (org-split-string contents "\n"))
+
+    (setq attr-list
+          (let ((result-list '()))
+            (dolist (attr-item 
+                     (list 
+                      (if (plist-get attr :expand) 
+                          "expand"
+                        nil
+                        )
+
+                      (case (plist-get attr :placement)
+                        ('center "center")
+                        ('left nil)
+                        (t 
+                         (if org-e-groff-tables-centered  
+                             "center" 
+                           "" )))
+
+                      (case (plist-get attr :boxtype)
+                        ('box "box")
+                        ('doublebox "doublebox")
+                        ('allbox "allbox")
+                        ('none nil)
+                        (t "box"))
+                      ))
+
+              (if (not (null attr-item))
+                  (add-to-list 'result-list attr-item)
+                ))
+            result-list ))
+
+
+    (setq title-line  (plist-get attr :title-line))
+    (setq disable-caption (plist-get attr :disable-caption)) 
+
+    (setq table-format (concat 
+                        (format "%s"
+                                (or (car attr-list) "" ))
+                        (or 
+                         (let ((output-list '()))
+                           (when (cdr attr-list)
+                             (dolist (attr-item (cdr attr-list))
+                               (setq output-list (concat output-list  (format ",%s" attr-item )) ) ))
+                           output-list)
+                         "") ))
+
+    
+    (when lines
+      (setq first-line (org-split-string (car lines) "\t")))
+
+    (cond
+     ;; Others.
+     (lines (concat ".TS\n " table-format ";\n" 
+                    
+                    (format "%s.\n"
+                            (let ((final-line ""))
+
+                              (when title-line
+                                (dotimes (i (length first-line))
+                                  (setq final-line (concat final-line "cb" divider))
+                                  ))
+
+                              (setq final-line (concat final-line "\n"))
+                              (if alignment
+                                  (setq final-line (concat final-line alignment))
+                                (dotimes (i (length first-line))
+                                  (setq final-line (concat final-line "c" divider))))
+                              final-line ))
+
+                    (format "%s.TE\n"
+                            (let ((final-line ""))
+                              (dolist (line-item lines)
+                                (cond 
+                                 (t	
+                                  (setq lines (org-split-string contents "\n"))
+
+                                  (setq final-line (concat final-line 
+                                                           (car (org-split-string line-item "\\\\")) "\n"))
+                                  )
+                                 )
+                                
+                                )  final-line))
+
+                    (if (not disable-caption)
+                        (format ".TB \"%s\""
+                                caption)
+                      "") )))))
+
+;;;; Table Cell
+
+(defun org-e-groff-table-cell (table-cell contents info)
+  "Transcode a TABLE-CELL element from Org to Groff
+CONTENTS is the cell contents.  INFO is a plist used as
+a communication channel."
+  (concat (if (and contents
+                   org-e-groff-table-scientific-notation
+                   (string-match orgtbl-exp-regexp contents))
+              ;; Use appropriate format string for scientific
+              ;; notation.
+              (format org-e-groff-table-scientific-notation
+                      (match-string 1 contents)
+                      (match-string 2 contents))
+            contents)
+          (when (org-export-get-next-element table-cell) " \t ")))
+
+
+;;;; Table Row
+
+(defun org-e-groff-table-row (table-row contents info)
+  "Transcode a TABLE-ROW element from Org to Groff
+CONTENTS is the contents of the row.  INFO is a plist used as
+a communication channel."
+  ;; Rules are ignored since table separators are deduced from
+  ;; borders of the current row.
+  (when (eq (org-element-property :type table-row) 'standard)
+    (let* ((attr (mapconcat 'identity
+                            (org-element-property
+                             :attr_groff (org-export-get-parent table-row))
+                            " "))
+           ;; TABLE-ROW's borders are extracted from its first cell.
+           (borders
+            (org-export-table-cell-borders
+             (car (org-element-contents table-row)) info)))
+      (concat
+       ;; Mark "hline" for horizontal lines.
+       (cond  ((and (memq 'top borders) (memq 'above borders)) "_\n"))
+       contents "\\\\\n"
+       (cond
+        ;; When BOOKTABS are activated enforce bottom rule even when
+        ;; no hline was specifically marked.
+        ((and (memq 'bottom borders) (memq 'below borders)) "_\n")
+        ((memq 'below borders) "_"))))))
+
+
+
+
+;;;; Target
+
+(defun org-e-groff-target (target contents info)
+  "Transcode a TARGET object from Org to Groff.
+CONTENTS is nil.  INFO is a plist holding contextual
+information."
+  (format "\\fI%s\\fP"
+          (org-export-solidify-link-text (org-element-property :value target))))
+
+
+;;;; Timestamp
+
+(defun org-e-groff-timestamp (timestamp contents info)
+  "Transcode a TIMESTAMP object from Org to Groff.
+CONTENTS is nil.  INFO is a plist holding contextual
+information."
+  (let ((value (org-translate-time (org-element-property :value timestamp)))
+        (type (org-element-property :type timestamp)))
+    (cond ((memq type '(active active-range))
+           (format org-e-groff-active-timestamp-format value))
+          ((memq type '(inactive inactive-range))
+           (format org-e-groff-inactive-timestamp-format value))
+          (t (format org-e-groff-diary-timestamp-format value)))))
+
+
+;;;; Underline
+
+(defun org-e-groff-underline (underline contents info)
+  "Transcode UNDERLINE from Org to Groff.
+CONTENTS is the text with underline markup.  INFO is a plist
+holding contextual information."
+  (org-e-groff--text-markup contents 'underline))
+
+
+;;;; Verbatim
+
+(defun org-e-groff-verbatim (verbatim contents info)
+  "Transcode a VERBATIM object from Org to Groff.
+CONTENTS is nil.  INFO is a plist used as a communication
+channel."
+  (org-e-groff--text-markup (org-element-property :value verbatim) 'verbatim))
+
+
+;;;; Verse Block
+
+(defun org-e-groff-verse-block (verse-block contents info)
+  "Transcode a VERSE-BLOCK element from Org to Groff.
+CONTENTS is verse block contents. INFO is a plist holding
+contextual information."
+  (format ".DS C\n.ft HI\n%s\n.ft\n.DE" contents))
+
+
+
+;;; Interactive functions
+
+(defun org-e-groff-export-to-groff
+  (&optional subtreep visible-only body-only ext-plist pub-dir)
+  "Export current buffer to a Groff file.
+
+If narrowing is active in the current buffer, only export its
+narrowed part.
+
+If a region is active, export that region.
+
+When optional argument SUBTREEP is non-nil, export the sub-tree
+at point, extracting information from the headline properties
+first.
+
+When optional argument VISIBLE-ONLY is non-nil, don't export
+contents of hidden elements.
+
+When optional argument BODY-ONLY is non-nil, only write code
+between \"\\begin{document}\" and \"\\end{document}\".
+
+EXT-PLIST, when provided, is a property list with external
+parameters overriding Org default settings, but still inferior to
+file-local settings.
+
+When optional argument PUB-DIR is set, use it as the publishing
+directory.
+
+Return output file's name."
+  (interactive)
+  (let ((outfile (org-export-output-file-name ".groff" subtreep pub-dir)))
+    (org-export-to-file
+     'e-groff outfile subtreep visible-only body-only ext-plist)))
+
+(defun org-e-groff-export-to-pdf
+  (&optional subtreep visible-only body-only ext-plist pub-dir)
+  "Export current buffer to Groff then process through to PDF.
+
+If narrowing is active in the current buffer, only export its
+narrowed part.
+
+If a region is active, export that region.
+
+When optional argument SUBTREEP is non-nil, export the sub-tree
+at point, extracting information from the headline properties
+first.
+
+When optional argument VISIBLE-ONLY is non-nil, don't export
+contents of hidden elements.
+
+When optional argument BODY-ONLY is non-nil, only write code
+between \"\\begin{document}\" and \"\\end{document}\".
+
+EXT-PLIST, when provided, is a property list with external
+parameters overriding Org default settings, but still inferior to
+file-local settings.
+
+When optional argument PUB-DIR is set, use it as the publishing
+directory.
+
+Return PDF file's name."
+  (interactive)
+  (org-e-groff-compile
+   (org-e-groff-export-to-groff
+    subtreep visible-only body-only ext-plist pub-dir)))
+
+(defun org-e-groff-compile (grofffile)
+  "Compile a Groff file.
+
+GROFFFILE is the name of the file being compiled.  Processing is
+done through the command specified in `org-e-groff-pdf-process'.
+
+Return PDF file name or an error if it couldn't be produced."
+  (let* ((wconfig (current-window-configuration))
+         (grofffile (file-truename grofffile))
+         (base (file-name-sans-extension grofffile))
+         errors)
+    (message (format "Processing Groff file %s ..." grofffile))
+    (unwind-protect
+        (progn
+          (cond
+           ;; A function is provided: Apply it.
+           ((functionp org-e-groff-pdf-process)
+            (funcall org-e-groff-pdf-process (shell-quote-argument grofffile)))
+           ;; A list is provided: Replace %b, %f and %o with appropriate
+           ;; values in each command before applying it.  Output is
+           ;; redirected to "*Org PDF Groff Output*" buffer.
+           ((consp org-e-groff-pdf-process)
+            (let* ((out-dir (or (file-name-directory grofffile) "./"))
+                   (outbuf (get-buffer-create "*Org PDF Groff Output*")))
+              (mapc
+               (lambda (command)
+                 (shell-command
+                  (replace-regexp-in-string
+                   "%b" (shell-quote-argument base)
+                   (replace-regexp-in-string
+                    "%f" (shell-quote-argument grofffile)
+                    (replace-regexp-in-string
+                     "%o" (shell-quote-argument out-dir) command t t) t t) t t)
+                  outbuf))
+               org-e-groff-pdf-process)
+              ;; Collect standard errors from output buffer.
+              (setq errors (org-e-groff-collect-errors outbuf))))
+           (t (error "No valid command to process to PDF")))
+          (let ((pdffile (concat base ".pdf")))
+            ;; Check for process failure.  Provide collected errors if
+            ;; possible.
+            (if (not (file-exists-p pdffile))
+                (error (concat (format "PDF file %s wasn't produced" pdffile)
+                               (when errors (concat ": " errors))))
+              ;; Else remove log files, when specified, and signal end of
+              ;; process to user, along with any error encountered.
+              (when org-e-groff-remove-logfiles
+                (dolist (ext org-e-groff-logfiles-extensions)
+                  (let ((file (concat base "." ext)))
+                    (when (file-exists-p file) (delete-file file)))))
+              (message (concat "Process completed"
+                               (if (not errors) "."
+                                 (concat " with errors: " errors)))))
+            ;; Return output file name.
+            pdffile))
+      (set-window-configuration wconfig))))
+
+(defun org-e-groff-collect-errors (buffer)
+  "Collect some kind of errors from \"groff\" output
+BUFFER is the buffer containing output.
+Return collected error types as a string, or nil if there was
+none."
+  (with-current-buffer buffer
+    (save-excursion
+      (goto-char (point-max))
+      ;; Find final run
+      nil )))
+
+
+(provide 'org-e-groff)
+;;; org-e-groff.el ends here

+ 3 - 3
contrib/lisp/org-e-html.el

@@ -1823,7 +1823,7 @@ CONTENTS is nil.  INFO is a plist holding contextual information."
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (concat
    ;; Insert separator between two footnotes in a row.
-   (let ((prev (org-export-get-previous-element footnote-reference)))
+   (let ((prev (org-export-get-previous-element footnote-reference info)))
      (when (eq (org-element-type prev) 'footnote-reference)
        org-e-html-footnote-separator))
    (cond
@@ -1917,10 +1917,10 @@ holding contextual information."
 	     (itemized-body (org-e-html-format-list-item
 			     contents type nil nil full-text)))
 	(concat
-	 (and (org-export-first-sibling-p headline)
+	 (and (org-export-first-sibling-p headline info)
 	      (org-e-html-begin-plain-list type))
 	 itemized-body
-	 (and (org-export-last-sibling-p headline)
+	 (and (org-export-last-sibling-p headline info)
 	      (org-e-html-end-plain-list type)))))
      ;; Case 3. Standard headline.  Export it as a section.
      (t

+ 4 - 4
contrib/lisp/org-e-latex.el

@@ -1279,7 +1279,7 @@ INFO is a plist used as a communication channel."
 CONTENTS is nil.  INFO is a plist holding contextual information."
   (concat
    ;; Insert separator between two footnotes in a row.
-   (let ((prev (org-export-get-previous-element footnote-reference)))
+   (let ((prev (org-export-get-previous-element footnote-reference info)))
      (when (eq (org-element-type prev) 'footnote-reference)
        org-e-latex-footnote-separator))
    (cond
@@ -1406,14 +1406,14 @@ holding contextual information."
       (let ((low-level-body
 	     (concat
 	      ;; If the headline is the first sibling, start a list.
-	      (when (org-export-first-sibling-p headline)
+	      (when (org-export-first-sibling-p headline info)
 		(format "\\begin{%s}\n" (if numberedp 'enumerate 'itemize)))
 	      ;; Itemize headline
 	      "\\item " full-text "\n" headline-label pre-blanks contents)))
 	;; If headline is not the last sibling simply return
 	;; LOW-LEVEL-BODY.  Otherwise, also close the list, before any
 	;; blank line.
-	(if (not (org-export-last-sibling-p headline)) low-level-body
+	(if (not (org-export-last-sibling-p headline info)) low-level-body
 	  (replace-regexp-in-string
 	   "[ \t\n]*\\'"
 	   (format "\n\\\\end{%s}" (if numberedp 'enumerate 'itemize))
@@ -2392,7 +2392,7 @@ a communication channel."
 		      (match-string 1 contents)
 		      (match-string 2 contents))
 	    contents)
-	  (when (org-export-get-next-element table-cell) " & ")))
+	  (when (org-export-get-next-element table-cell info) " & ")))
 
 
 ;;;; Table Row

+ 1438 - 0
contrib/lisp/org-e-man.el

@@ -0,0 +1,1438 @@
+;; org-e-man.el --- Man Back-End For Org Export Engine
+
+;; Copyright (C) 2011-2012  Free Software Foundation, Inc.
+
+;; Author: Nicolas Goaziou <n.goaziou at gmail dot com>
+;; Author: Luis R Anaya <papoanaya aroba hot mail punto com>
+;; Keywords: outlines, hypermedia, calendar, wp
+;; 
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;; This library implements a Man back-end for Org generic exporter.
+;;
+;; To test it, run
+;;
+;;   M-: (org-export-to-buffer 'e-man "*Test e-Man*") RET
+;;
+;; in an org-mode buffer then switch to the buffer to see the Man
+;; export.  See contrib/lisp/org-export.el for more details on how
+;; this exporter works.
+;;
+;; It introduces one new buffer keywords: 
+;; "MAN_CLASS_OPTIONS". 
+
+;;; Code:
+
+(require 'org-export)
+
+(eval-when-compile (require 'cl))
+
+(defvar org-export-man-default-packages-alist)
+(defvar org-export-man-packages-alist)
+
+
+
+
+;;; Define Back-End
+
+(defvar org-e-man-translate-alist
+  '((babel-call . org-e-man-babel-call)
+    (bold . org-e-man-bold)
+    (center-block . org-e-man-center-block)
+    (clock . org-e-man-clock)
+    (code . org-e-man-code)
+    (comment . org-e-man-comment)
+    (comment-block . org-e-man-comment-block)
+    (drawer . org-e-man-drawer)
+    (dynamic-block . org-e-man-dynamic-block)
+    (entity . org-e-man-entity)
+    (example-block . org-e-man-example-block)
+    (export-block . org-e-man-export-block)
+    (export-snippet . org-e-man-export-snippet)
+    (fixed-width . org-e-man-fixed-width)
+    (footnote-definition . org-e-man-footnote-definition)
+    (footnote-reference . org-e-man-footnote-reference)
+    (headline . org-e-man-headline)
+    (horizontal-rule . org-e-man-horizontal-rule)
+    (inline-babel-call . org-e-man-inline-babel-call)
+    (inline-src-block . org-e-man-inline-src-block)
+    (inlinetask . org-e-man-inlinetask)
+    (italic . org-e-man-italic)
+    (item . org-e-man-item)
+    (keyword . org-e-man-keyword)
+    (man-environment . org-e-man-man-environment)
+    (man-fragment . org-e-man-man-fragment)
+    (line-break . org-e-man-line-break)
+    (link . org-e-man-link)
+    (macro . org-e-man-macro)
+    (paragraph . org-e-man-paragraph)
+    (plain-list . org-e-man-plain-list)
+    (plain-text . org-e-man-plain-text)
+    (planning . org-e-man-planning)
+    (property-drawer . org-e-man-property-drawer)
+    (quote-block . org-e-man-quote-block)
+    (quote-section . org-e-man-quote-section)
+    (radio-target . org-e-man-radio-target)
+    (section . org-e-man-section)
+    (special-block . org-e-man-special-block)
+    (src-block . org-e-man-src-block)
+    (statistics-cookie . org-e-man-statistics-cookie)
+    (strike-through . org-e-man-strike-through)
+    (subscript . org-e-man-subscript)
+    (superscript . org-e-man-superscript)
+    (table . org-e-man-table)
+    (table-cell . org-e-man-table-cell)
+    (table-row . org-e-man-table-row)
+    (target . org-e-man-target)
+    (template . org-e-man-template)
+    (timestamp . org-e-man-timestamp)
+    (underline . org-e-man-underline)
+    (verbatim . org-e-man-verbatim)
+    (verse-block . org-e-man-verse-block))
+  "Alist between element or object types and translators.")
+
+(defconst org-e-man-options-alist
+  '((:date "DATE" nil nil t)
+    (:man-class "MAN_CLASS" nil nil t)
+    (:man-class-options "MAN_CLASS_OPTIONS" nil nil t)
+    (:man-header-extra "MAN_HEADER" nil nil newline))
+  "Alist between Man export properties and ways to set them.
+See `org-export-options-alist' for more information on the
+structure of the values.")
+
+
+
+;;; User Configurable Variables
+
+(defgroup org-export-e-man nil
+  "Options for exporting Org mode files to Man."
+  :tag "Org Export Man"
+  :group 'org-export)
+
+;;;; Tables
+
+
+(defcustom org-e-man-tables-centered t
+  "When non-nil, tables are exported in a center environment."
+  :group 'org-export-e-man
+  :type 'boolean)
+
+(defcustom org-e-man-tables-verbatim nil
+  "When non-nil, tables are exported verbatim."
+  :group 'org-export-e-man
+  :type 'boolean)
+
+
+
+(defcustom org-e-man-table-scientific-notation "%sE%s"
+  "Format string to display numbers in scientific notation.
+The format should have \"%s\" twice, for mantissa and exponent
+\(i.e. \"%s\\\\times10^{%s}\").
+
+When nil, no transformation is made."
+  :group 'org-export-e-man
+  :type '(choice
+          (string :tag "Format string")
+          (const :tag "No formatting")))
+
+
+;;;; Inlinetasks
+;; Src blocks
+
+(defcustom org-e-man-source-highlight nil
+  "Use GNU source highlight to embellish source blocks " 
+  :group 'org-export-e-man
+  :type 'boolean)
+
+
+(defcustom org-e-man-source-highlight-langs
+  '(
+    (emacs-lisp "lisp") (lisp "lisp") (clojure "lisp") 
+    (scheme "scheme")
+    (c "c") (cc "cpp") (csharp "csharp") (d "d") 
+    (fortran "fortran") (cobol "cobol") (pascal "pascal")
+    (ada "ada") (asm "asm")
+    (perl "perl") (cperl "perl") 
+    (python "python") (ruby "ruby") (tcl "tcl") (lua "lua")
+    (java "java") (javascript "javascript")
+    (tex "latex") 
+    (shell-script "sh") (awk "awk") (diff "diff") (m4 "m4")
+    (ocaml "caml") (caml "caml")
+    (sql "sql") (sqlite "sql")
+    (html "html") (css "css") (xml "xml")
+    (bat "bat") (bison "bison") (clipper "clipper")
+    (ldap "ldap") (opa "opa")
+    (php "php") (postscript "postscript") (prolog "prolog") 
+    (properties "properties") (makefile "makefile")
+    (tml "tml") (vala "vala") (vbscript "vbscript") (xorg "xorg")
+    )
+  "Alist mapping languages to their listing language counterpart.
+The key is a symbol, the major mode symbol without the \"-mode\".
+The value is the string that should be inserted as the language
+parameter for the listings package.  If the mode name and the
+listings name are the same, the language does not need an entry
+in this list - but it does not hurt if it is present."
+  :group 'org-export-e-man
+  :type '(repeat
+          (list
+           (symbol :tag "Major mode       ")
+           (string :tag "Listings language"))))
+
+
+
+(defvar org-e-man-custom-lang-environments nil
+  "Alist mapping languages to language-specific Man environments.
+
+It is used during export of src blocks by the listings and 
+man packages.  For example,
+
+  \(setq org-e-man-custom-lang-environments
+     '\(\(python \"pythoncode\"\)\)\)
+
+would have the effect that if org encounters begin_src python
+during man export."
+  )
+
+
+
+
+;;;; Plain text
+
+(defcustom org-e-man-quotes
+  '(("fr"
+     ("\\(\\s-\\|[[(]\\|^\\)\"" . "«~")
+     ("\\(\\S-\\)\"" . "~»")
+     ("\\(\\s-\\|(\\|^\\)'" . "'"))
+    ("en"
+     ("\\(\\s-\\|[[(]\\|^\\)\"" . "``")
+     ("\\(\\S-\\)\"" . "''")
+     ("\\(\\s-\\|(\\|^\\)'" . "`")))
+
+  "Alist for quotes to use when converting english double-quotes.
+
+The CAR of each item in this alist is the language code.
+The CDR of each item in this alist is a list of three CONS:
+- the first CONS defines the opening quote;
+- the second CONS defines the closing quote;
+- the last CONS defines single quotes.
+
+For each item in a CONS, the first string is a regexp
+for allowed characters before/after the quote, the second
+string defines the replacement string for this quote."
+  :group 'org-export-e-man
+  :type '(list
+          (cons :tag "Opening quote"
+                (string :tag "Regexp for char before")
+                (string :tag "Replacement quote     "))
+          (cons :tag "Closing quote"
+                (string :tag "Regexp for char after ")
+                (string :tag "Replacement quote     "))
+          (cons :tag "Single quote"
+                (string :tag "Regexp for char before")
+                (string :tag "Replacement quote     "))))
+
+
+;;;; Compilation
+
+(defcustom org-e-man-pdf-process
+  '("tbl %f | eqn | groff -man | ps2pdf - > %b.pdf"
+    "tbl %f | eqn | groff -man | ps2pdf - > %b.pdf"
+    "tbl %f | eqn | groff -man | ps2pdf - > %b.pdf"
+    )
+
+  "Commands to process a Man file to a PDF file.
+This is a list of strings, each of them will be given to the
+shell as a command.  %f in the command will be replaced by the
+full file name, %b by the file base name \(i.e. without
+extension) and %o by the base directory of the file.
+
+
+By default, Org uses 3 runs of to do the processing.
+
+Alternatively, this may be a Lisp function that does the
+processing.  This function should accept the file name as 
+its single argument."
+  :group 'org-export-pdf
+  :type '(choice
+          (repeat :tag "Shell command sequence"
+                  (string :tag "Shell command"))
+          (const :tag "2 runs of pdfgroff"
+                 ("tbl %f | eqn | groff -mm | ps2pdf - > %b.pdf"
+                  "tbl %f | eqn | groff -mm | ps2pdf - > %b.pdf" ))
+          (const :tag "3 runs of pdfgroff"
+                 ("tbl %f | eqn | groff -mm | ps2pdf - > %b.pdf"
+                  "tbl %f | eqn | groff -mm | ps2pdf - > %b.pdf"
+                  "tbl %f | eqn | groff -mm | ps2pdf - > %b.pdf"))
+          (function)))
+
+(defcustom org-e-man-logfiles-extensions
+  '("log" "out" "toc")
+  "The list of file extensions to consider as Man logfiles."
+  :group 'org-export-e-man
+  :type '(repeat (string :tag "Extension")))
+
+(defcustom org-e-man-remove-logfiles t
+  "Non-nil means remove the logfiles produced by PDF production.
+These are the .aux, .log, .out, and .toc files."
+  :group 'org-export-e-man
+  :type 'boolean)
+
+
+
+;; Preamble
+
+;; Adding MAN as a block parser to make sure that its contents
+;; does not execute
+
+(add-to-list 'org-element-block-name-alist
+             '("MAN" . org-element-export-block-parser))
+
+
+
+;;; Internal Functions
+
+
+(defun org-e-man--caption/label-string (caption label info)
+  "Return caption and label Man string for floats.
+
+CAPTION is a cons cell of secondary strings, the car being the
+standard caption and the cdr its short form.  LABEL is a string
+representing the label.  INFO is a plist holding contextual
+information.
+
+If there's no caption nor label, return the empty string.
+
+For non-floats, see `org-e-man--wrap-label'."
+  (let ((label-str "" ))
+    (cond
+     ((and (not caption) (not label)) "")
+     ((not caption) (format "\\fI%s\\fP" label))
+     ;; Option caption format with short name.
+     ((cdr caption)
+      (format "\\fR%s\\fP - \\fI%s\\P - %s\n"
+              (org-export-data (cdr caption) info)
+              label-str
+              (org-export-data (car caption) info)))
+     ;; Standard caption format.
+     (t (format "\\fR%s\\fP"
+                (org-export-data (car caption) info)))))
+
+  )
+
+
+
+(defun org-e-man--quotation-marks (text info)
+  "Export quotation marks depending on language conventions.
+TEXT is a string containing quotation marks to be replaced.  INFO
+is a plist used as a communication channel."
+  (mapc (lambda(l)
+          (let ((start 0))
+            (while (setq start (string-match (car l) text start))
+              (let ((new-quote (concat (match-string 1 text) (cdr l))))
+                (setq text (replace-match new-quote  t t text))))))
+        (cdr (or (assoc (plist-get info :language) org-e-man-quotes)
+                 ;; Falls back on English.
+                 (assoc "en" org-e-man-quotes))))
+  text)
+
+(defun org-e-man--wrap-label (element output)
+  "Wrap label associated to ELEMENT around OUTPUT, if appropriate.
+This function shouldn't be used for floats.  See
+`org-e-man--caption/label-string'."
+  (let ((label (org-element-property :name element)))
+    (if (or (not output) (not label) (string= output "") (string= label ""))
+        output
+      (concat (format "%s\n.br\n" label) output))))
+
+
+;;; Template
+
+(defun org-e-man-template (contents info)
+  "Return complete document string after Man conversion.
+CONTENTS is the transcoded contents string.  INFO is a plist
+holding export options."
+  (let ((title (org-export-data (plist-get info :title) info))
+        (attr
+         (read
+          (format
+           "(%s)"
+           (mapconcat
+            #'identity
+            (list (plist-get info :man-class-options))
+            " ")))) )
+
+    (setq section-item (plist-get attr :section-id))
+
+    (concat
+
+     (cond 
+      ((and title (stringp section-item))
+       (format ".TH \"%s\" \"%s\" \n" title section-item )
+       )
+      ((and (string= "" title) (stringp section-item))
+       (format ".TH \"%s\" \"%s\" \n" " " section-item )
+       )
+      (title
+       (format ".TH \"%s\" \"1\" \n" title )
+       )
+      (t
+       ".TH \" \" \"1\" "))
+
+     contents )))
+
+
+;;; Transcode Functions
+
+;;;; Babel Call
+;;
+;; Babel Calls are ignored.
+
+
+;;;; Bold
+
+(defun org-e-man-bold (bold contents info)
+  "Transcode BOLD from Org to Man.
+CONTENTS is the text with bold markup.  INFO is a plist holding
+contextual information."
+  (format "\\fB%s\\fP" contents) )
+
+
+;;;; Center Block
+
+(defun org-e-man-center-block (center-block contents info)
+  "Transcode a CENTER-BLOCK element from Org to Man.
+CONTENTS holds the contents of the center block.  INFO is a plist
+holding contextual information."
+  (org-e-man--wrap-label
+   center-block
+   (format ".ce %d\n.nf\n%s\n.fi" 
+           (- (length (split-string contents "\n")) 1 ) 
+           contents)))
+
+
+;;;; Clock
+
+(defun org-e-man-clock (clock contents info)
+  "Transcode a CLOCK element from Org to Man.
+CONTENTS is nil.  INFO is a plist holding contextual
+information."
+  "" )
+
+
+;;;; Code
+
+(defun org-e-man-code (code contents info)
+  "Transcode a CODE object from Org to Man.
+CONTENTS is nil.  INFO is a plist used as a communication
+channel."
+  (format "\\fC%s\\fP" code) )
+
+
+;;;; Comment
+;;
+;; Comments are ignored.
+
+
+;;;; Comment Block
+;;
+;; Comment Blocks are ignored.
+
+
+;;;; Drawer
+
+(defun org-e-man-drawer (drawer contents info)
+  "Transcode a DRAWER element from Org to Man.
+   DRAWER holds the drawer information
+   CONTENTS holds the contents of the block.  
+   INFO is a plist holding contextual information. "
+  contents)
+
+
+;;;; Dynamic Block
+
+(defun org-e-man-dynamic-block (dynamic-block contents info)
+  "Transcode a DYNAMIC-BLOCK element from Org to Man.
+CONTENTS holds the contents of the block.  INFO is a plist
+holding contextual information.  See `org-export-data'."
+  (org-e-man--wrap-label dynamic-block contents))
+
+
+;;;; Entity
+
+(defun org-e-man-entity (entity contents info)
+  "Transcode an ENTITY object from Org to Man.
+CONTENTS are the definition itself.  INFO is a plist holding
+contextual information."
+  (let ((ent (org-element-property :utf8 entity))) ent))
+
+
+;;;; Example Block
+
+(defun org-e-man-example-block (example-block contents info)
+  "Transcode an EXAMPLE-BLOCK element from Org to Man.
+CONTENTS is nil.  INFO is a plist holding contextual
+information."
+  (org-e-man--wrap-label
+   example-block
+   (format ".RS\n.nf\n%s\n.fi\n.RE"
+           (org-export-format-code-default example-block info))))
+
+
+;;;; Export Block
+
+(defun org-e-man-export-block (export-block contents info)
+  "Transcode a EXPORT-BLOCK element from Org to Man.
+CONTENTS is nil.  INFO is a plist holding contextual information."
+  (when (string= (org-element-property :type export-block) "MAN")
+    (org-remove-indentation (org-element-property :value export-block))))
+
+
+;;;; Export Snippet
+
+(defun org-e-man-export-snippet (export-snippet contents info)
+  "Transcode a EXPORT-SNIPPET object from Org to Man.
+CONTENTS is nil.  INFO is a plist holding contextual information."
+  (when (eq (org-export-snippet-backend export-snippet) 'e-man)
+    (org-element-property :value export-snippet)))
+
+
+;;;; Fixed Width
+
+(defun org-e-man-fixed-width (fixed-width contents info)
+  "Transcode a FIXED-WIDTH element from Org to Man.
+CONTENTS is nil.  INFO is a plist holding contextual information."
+  (org-e-man--wrap-label
+   fixed-width
+   (format "\\fC\n%s\\fP"
+           (org-remove-indentation
+            (org-element-property :value fixed-width)))))
+
+
+;;;; Footnote Definition
+;;
+;; Footnote Definitions are ignored.
+
+;;;; Footnote References
+;;
+;; Footnote References are Ignored
+
+
+;;;; Headline
+
+(defun org-e-man-headline (headline contents info)
+  "Transcode an HEADLINE element from Org to Man.
+CONTENTS holds the contents of the headline.  INFO is a plist
+holding contextual information."
+  (let* ((level (org-export-get-relative-level headline info))
+		 (numberedp (org-export-numbered-headline-p headline info))
+		 ;; Section formatting will set two placeholders: one for the
+		 ;; title and the other for the contents.
+		 (section-fmt
+		  (case level
+			(1 ".SH \"%s\"\n%s")
+			(2 ".SS \"%s\"\n%s")
+			(3 ".SS \"%s\"\n%s") 
+			(t nil)) )
+		 (text (org-export-data (org-element-property :title headline) info)) )
+
+    (cond
+     ;; Case 1: This is a footnote section: ignore it.
+     ((org-element-property :footnote-section-p headline) nil)
+     ;; Case 2. This is a deep sub-tree: export it as a list item.
+     ;;         Also export as items headlines for which no section
+     ;;         format has been found.
+     ((or (not section-fmt) (org-export-low-level-p headline info))
+      ;; Build the real contents of the sub-tree.
+      (let ((low-level-body
+			 (concat
+			  ;; If the headline is the first sibling, start a list.
+			  (when (org-export-first-sibling-p headline)
+				(format "%s\n" ".RS"))
+			  ;; Itemize headline
+			  ".TP\n.ft I\n" text "\n.ft\n" 
+			  contents ".RE")))
+		;; If headline is not the last sibling simply return
+		;; LOW-LEVEL-BODY.  Otherwise, also close the list, before any
+		;; blank line.
+		(if (not (org-export-last-sibling-p headline)) low-level-body
+		  (replace-regexp-in-string
+		   "[ \t\n]*\\'" ""
+		   low-level-body))))
+     ;; Case 3. Standard headline.  Export it as a section.
+     (t (format section-fmt text contents )))))
+
+;;;; Horizontal Rule
+;; Not supported
+
+;;;; Inline Babel Call
+;;
+;; Inline Babel Calls are ignored.
+
+;;;; Inline Src Block
+
+(defun org-e-man-inline-src-block (inline-src-block contents info)
+  "Transcode an INLINE-SRC-BLOCK element from Org to Man.
+CONTENTS holds the contents of the item.  INFO is a plist holding
+contextual information."
+  (let* ((code (org-element-property :value inline-src-block)))
+    (cond
+     (org-e-man-source-highlight
+      (let* ((tmpdir (if (featurep 'xemacs)
+                         temp-directory 
+                       temporary-file-directory ))
+             (in-file  (make-temp-name 
+                        (expand-file-name "srchilite" tmpdir))  )
+             (out-file (make-temp-name 
+                        (expand-file-name "reshilite" tmpdir)) )
+             (org-lang (org-element-property :language inline-src-block))
+             (lst-lang (cadr (assq (intern org-lang)
+                                   org-e-man-source-highlight-langs)))
+             
+             (cmd (concat (expand-file-name "source-highlight")
+                          " -s " lst-lang
+                          " -f groff_man"
+                          " -i " in-file
+                          " -o " out-file
+                          )
+                  ))
+
+        (if lst-lang
+            (let ((code-block "" ))
+              (with-temp-file in-file (insert code))
+              (shell-command cmd)
+              (setq code-block  (org-file-contents out-file) )
+              (delete-file in-file)
+              (delete-file out-file)
+              code-block)
+          (format ".RS\n.nf\n\\fC\\m[black]%s\\m[]\\fP\n.fi\n.RE\n"
+                  code))
+
+        ))
+
+     ;; Do not use a special package: transcode it verbatim.
+     (t
+      (concat ".RS\n.nf\n" "\\fC" "\n" code "\n"
+              "\\fP\n.fi\n.RE\n"))
+     )))
+
+
+;;;; Inlinetask
+;;;; Italic
+
+(defun org-e-man-italic (italic contents info)
+  "Transcode ITALIC from Org to Man.
+CONTENTS is the text with italic markup.  INFO is a plist holding
+contextual information."
+  (format "\\fI%s\\fP" contents))
+
+
+;;;; Item
+
+
+(defun org-e-man-item (item contents info)
+
+
+  "Transcode an ITEM element from Org to Man.
+CONTENTS holds the contents of the item.  INFO is a plist holding
+contextual information."
+
+  (let* ((counter
+          (let ((count (org-element-property :counter item))
+                (level
+                 (loop for parent in (org-export-get-genealogy item)
+                       count (eq (org-element-type parent) 'plain-list)
+                       until (eq (org-element-type parent) 'headline))))
+            (and count
+                 (< level 5)
+                 (concat ""))))
+         (bullet (org-element-property :bullet item))
+         (type (org-element-property :type (org-element-property :parent item)))
+         (checkbox (case (org-element-property :checkbox item)
+                     (on "\\o'\\(sq\\(mu'")			;; 
+                     (off "\\(sq ")					;;
+                     (trans "\\o'\\(sq\\(mi'"   ))) ;;
+
+         (tag (let ((tag (org-element-property :tag item)))
+                ;; Check-boxes must belong to the tag.
+                (and tag (format "\\fB%s\\fP"
+                                 (concat checkbox
+                                         (org-export-data tag info)))))))
+
+    (if (and (null tag )
+			 (null checkbox)) 
+		(let* ((bullet (org-trim bullet))
+			   (marker (cond  ((string= "-" bullet) "\\(em")
+							  ((string= "*" bullet) "\\(bu")
+							  ((eq type 'ordered)  
+							   (format "%s " (org-trim bullet)))
+							  (t "\\(dg") ) ))
+		  (concat ".IP " marker " 4\n"
+				  (org-trim (or contents " " ) )))
+                                        ; else
+      (concat ".TP\n" (or tag (concat " " checkbox)) "\n"
+              (org-trim (or contents " " ) )
+              ;; If there are footnotes references in tag, be sure to
+              ;; add their definition at the end of the item.  This
+              )) ))
+
+
+
+;;;; Keyword
+
+
+(defun org-e-man-keyword (keyword contents info)
+  "Transcode a KEYWORD element from Org to Man.
+CONTENTS is nil.  INFO is a plist holding contextual information."
+  (let ((key (org-element-property :key keyword))
+        (value (org-element-property :value keyword)))
+    (cond
+     ((string= key "MAN") value)
+     ((string= key "INDEX") nil)
+     ;; Invisible targets.
+     ((string= key "TARGET") nil)
+     ((string= key "TOC"   ) nil))))
+
+
+;;;; Man Environment
+
+(defun org-e-man-man-environment (man-environment contents info)
+  "Transcode a MAN-ENVIRONMENT element from Org to Man.
+CONTENTS is nil.  INFO is a plist holding contextual information."
+  (let ((label (org-element-property :name man-environment))
+        (value (org-remove-indentation
+                (org-element-property :value man-environment))))
+    (if (not (org-string-nw-p label)) value
+      ;; Environment is labelled: label must be within the environment
+      ;; (otherwise, a reference pointing to that element will count
+      ;; the section instead).
+      (with-temp-buffer
+        (insert value)
+        (goto-char (point-min))
+        (forward-line)
+        (insert (format "%s\n" label))
+        (buffer-string)))))
+
+
+;;;; Man Fragment
+
+(defun org-e-man-man-fragment (man-fragment contents info)
+  "Transcode a MAN-FRAGMENT object from Org to Man.
+CONTENTS is nil.  INFO is a plist holding contextual information."
+  (org-element-property :value man-fragment))
+
+
+;;;; Line Break
+
+(defun org-e-man-line-break (line-break contents info)
+  "Transcode a LINE-BREAK object from Org to Man.
+CONTENTS is nil.  INFO is a plist holding contextual information."
+  ".br\n")
+
+
+;;;; Link
+
+
+(defun org-e-man-link (link desc info)
+  "Transcode a LINK object from Org to Man.
+
+DESC is the description part of the link, or the empty string.
+INFO is a plist holding contextual information.  See
+`org-export-data'."
+  
+  (let* ((type (org-element-property :type link))
+         (raw-path (org-element-property :path link))
+         ;; Ensure DESC really exists, or set it to nil.
+         (desc (and (not (string= desc "")) desc))
+
+         (path (cond
+                ((member type '("http" "https" "ftp" "mailto"))
+                 (concat type ":" raw-path))
+                ((string= type "file")
+                 (when (string-match "\\(.+\\)::.+" raw-path)
+                   (setq raw-path (match-string 1 raw-path)))
+                 (if (file-name-absolute-p raw-path)
+                     (concat "file://" (expand-file-name raw-path))
+                   (concat "file://" raw-path)))
+                (t raw-path)))
+         protocol)
+    (cond
+     ;; Coderef: replace link with the reference name or the
+     ;; equivalent line number.
+     ;; External link with a description part.
+     ((and path desc) (format "%s \\fBat\\fP \\fI%s\\fP" path desc))
+     ;; External link without a description part.
+     (path (format "\\fI%s\\fP" path))
+     ;; No path, only description.  Try to do something useful.
+     (t (format "\\fI%s\\fP" desc)))))
+
+
+;;;; Macro
+
+(defun org-e-man-macro (macro contents info)
+  "Transcode a MACRO element from Org to Man.
+CONTENTS is nil.  INFO is a plist holding contextual information."
+  ;; Use available tools.
+  (org-export-expand-macro macro info))
+
+
+;;;; Paragraph
+
+(defun org-e-man-paragraph (paragraph contents info)
+  "Transcode a PARAGRAPH element from Org to Man.
+CONTENTS is the contents of the paragraph, as a string.  INFO is
+the plist used as a communication channel."
+  (setq parent (plist-get (nth 1 paragraph) :parent))
+  (when parent
+    (let ((parent-type (car parent)) 
+          (fixed-paragraph ""))
+      (cond ((and (eq parent-type 'item)
+                  (plist-get (nth 1 parent) :bullet ) )
+             (setq fixed-paragraph (concat "" contents)) )
+            ((eq parent-type 'section)
+             (setq fixed-paragraph (concat ".PP\n" contents) ) )
+            ((eq parent-type 'footnote-definition)
+             (setq fixed-paragraph contents))
+            (t (setq fixed-paragraph (concat "" contents) ) ) 
+            )
+      fixed-paragraph)
+    )
+  )
+
+
+;;;; Plain List
+
+(defun org-e-man-plain-list (plain-list contents info)
+  "Transcode a PLAIN-LIST element from Org to Man.
+CONTENTS is the contents of the list.  INFO is a plist holding
+contextual information."
+  contents)
+
+
+
+;;;; Plain Text
+
+(defun org-e-man-plain-text (text info)
+  "Transcode a TEXT string from Org to Man.
+TEXT is the string to transcode.  INFO is a plist holding
+contextual information."
+  ;; Protect 
+  (setq text (replace-regexp-in-string
+              "\\(?:[^\\]\\|^\\)\\(\\\\\\)\\(?:[^%$#&{}~^_\\]\\|$\\)"
+              "$\\" text nil t 1))
+
+  ;; Handle quotation marks
+  (setq text (org-e-man--quotation-marks text info))
+
+  ;; Handle break preservation if required.
+
+  (when (plist-get info :preserve-breaks)
+    (setq text (replace-regexp-in-string "\\(\\\\\\\\\\)?[ \t]*\n" " \\\\\\\\\n"
+                                         text)))
+  ;; Return value.
+  text)
+
+
+
+;;;; Planning
+
+
+;;;; Property Drawer
+
+
+;;;; Quote Block
+
+(defun org-e-man-quote-block (quote-block contents info)
+  "Transcode a QUOTE-BLOCK element from Org to Man.
+CONTENTS holds the contents of the block.  INFO is a plist
+holding contextual information."
+  (org-e-man--wrap-label
+   quote-block
+   (format ".RS\n%s\n.RE" contents)))
+
+;;;; Quote Section
+
+(defun org-e-man-quote-section (quote-section contents info)
+  "Transcode a QUOTE-SECTION element from Org to Man.
+CONTENTS is nil.  INFO is a plist holding contextual information."
+  (let ((value (org-remove-indentation
+                (org-element-property :value quote-section))))
+    (when value (format ".RS\\fI%s\\fP\n.RE\n" value))))
+
+
+;;;; Radio Target
+
+(defun org-e-man-radio-target (radio-target text info)
+  "Transcode a RADIO-TARGET object from Org to Man.
+TEXT is the text of the target.  INFO is a plist holding
+contextual information."
+  text )
+
+
+;;;; Section
+
+(defun org-e-man-section (section contents info)
+  "Transcode a SECTION element from Org to Man.
+CONTENTS holds the contents of the section.  INFO is a plist
+holding contextual information."
+  contents)
+
+
+;;;; Special Block
+
+(defun org-e-man-special-block (special-block contents info)
+  "Transcode a SPECIAL-BLOCK element from Org to Man.
+CONTENTS holds the contents of the block.  INFO is a plist
+holding contextual information."
+  (let ((type (downcase (org-element-property :type special-block))))
+    (org-e-man--wrap-label
+     special-block
+     (format "%s\n" contents))))
+
+
+;;;; Src Block
+
+(defun org-e-man-src-block (src-block contents info)
+  "Transcode a SRC-BLOCK element from Org to Man.
+CONTENTS holds the contents of the item.  INFO is a plist holding
+contextual information."
+
+  (let* ((lang (org-element-property :language src-block))
+         (caption (org-element-property :caption src-block))
+         (label (org-element-property :name src-block))
+         (code (org-element-property :value src-block))
+         (custom-env (and lang
+                          (cadr (assq (intern lang)
+                                      org-e-man-custom-lang-environments))))
+         (num-start (case (org-element-property :number-lines src-block)
+                      (continued (org-export-get-loc src-block info))
+                      (new 0)))
+         (retain-labels (org-element-property :retain-labels src-block)))
+    (cond
+     ;; Case 1.  No source fontification.
+     ((not org-e-man-source-highlight)
+      (let ((caption-str (org-e-man--caption/label-string caption label info))
+            (float-env (when caption ".RS\n.nf\\fC%s\\fP\n.fi.RE\n")))
+        (format
+         (or float-env "%s")
+         (concat 
+          (format ".RS\n.nf\n\\fC%s\\fP\n.fi\n.RE\n\n"
+                  (org-export-format-code-default src-block info) 
+                  )))))
+     ( (and org-e-man-source-highlight) 
+       (let* ((tmpdir (if (featurep 'xemacs)
+                          temp-directory 
+                        temporary-file-directory ))
+              
+              (in-file  (make-temp-name 
+                         (expand-file-name "srchilite" tmpdir))  )
+              (out-file (make-temp-name 
+                         (expand-file-name "reshilite" tmpdir)) )
+
+              (org-lang (org-element-property :language src-block))
+              (lst-lang (cadr (assq (intern org-lang)
+                                    org-e-man-source-highlight-langs)) )
+              
+              (cmd (concat "source-highlight"
+                           " -s " lst-lang
+                           " -f groff_man "
+                           " -i " in-file
+                           " -o " out-file
+                           )
+                   ))
+         
+         (if lst-lang
+             (let ((code-block "" ))
+               (with-temp-file in-file (insert code))
+               (shell-command cmd)
+               (setq code-block  (org-file-contents out-file) )
+               (delete-file in-file)
+               (delete-file out-file)
+               code-block)
+           (format ".RS\n.nf\n\\fC\\m[black]%s\\m[]\\fP\n.fi\n.RE"
+                   code))
+
+         )
+       )
+     )))
+
+
+;;;; Statistics Cookie
+
+(defun org-e-man-statistics-cookie (statistics-cookie contents info)
+  "Transcode a STATISTICS-COOKIE object from Org to Man.
+CONTENTS is nil.  INFO is a plist holding contextual information."
+  (org-element-property :value statistics-cookie))
+
+
+;;;; Strike-Through
+
+(defun org-e-man-strike-through (strike-through contents info)
+  "Transcode STRIKE-THROUGH from Org to Man.
+CONTENTS is the text with strike-through markup.  INFO is a plist
+holding contextual information."
+  (format "\\fI%s\\fP" contents))
+
+;;;; Subscript
+
+(defun org-e-man-subscript (subscript contents info)
+  "Transcode a SUBSCRIPT object from Org to Man.
+CONTENTS is the contents of the object.  INFO is a plist holding
+contextual information."
+  (format  "\\d\\s-2%s\\s+2\\u" contents))
+
+;;;; Superscript "^_%s$
+
+(defun org-e-man-superscript (superscript contents info)
+  "Transcode a SUPERSCRIPT object from Org to Man.
+CONTENTS is the contents of the object.  INFO is a plist holding
+contextual information."
+  (format  "\\u\\s-2%s\\s+2\\d" contents))
+
+
+;;;; Table
+;;
+;; `org-e-man-table' is the entry point for table transcoding.  It
+;; takes care of tables with a "verbatim" attribute.  Otherwise, it
+;; delegates the job to either `org-e-man-table--table.el-table' or
+;; `org-e-man-table--org-table' functions, depending of the type of
+;; the table.
+;;
+;; `org-e-man-table--align-string' is a subroutine used to build
+;; alignment string for Org tables.
+
+(defun org-e-man-table (table contents info)
+  "Transcode a TABLE element from Org to Man.
+CONTENTS is the contents of the table.  INFO is a plist holding
+contextual information."
+  (cond
+   ;; Case 1: verbatim table.
+   ((or org-e-man-tables-verbatim
+        (let ((attr
+               (read
+                (format
+                 "(%s)"
+                 (mapconcat
+                  #'identity
+                  (org-element-property :attr_man table)
+                  " ")))) )
+
+          (and attr (plist-get attr :verbatim))))
+
+    (format ".nf\n\\fC%s\\fP\n.fi"
+            ;; Re-create table, without affiliated keywords.
+            (org-trim
+             (org-element-interpret-data
+              `(table nil ,@(org-element-contents table))))))
+   ;; Case 2: Standard table.
+   (t (org-e-man-table--org-table table contents info))))
+
+(defun org-e-man-table--align-string (divider table info)
+  "Return an appropriate Man alignment string.
+TABLE is the considered table.  INFO is a plist used as
+a communication channel."
+  (let ((attr
+         (read
+          (format
+           "(%s)"
+           (mapconcat
+            #'identity
+            (org-element-property :attr_man table)
+            " ")))))
+
+    (setq align 	
+          (case (plist-get  attr :align)
+            ('center "c")
+            ('left "l")
+            ('right "r")))
+
+    (let (alignment)
+      ;; Extract column groups and alignment from first (non-rule)
+      ;; row.
+      (org-element-map
+       (org-element-map
+        table 'table-row
+        (lambda (row)
+          (and (eq (org-element-property :type row) 'standard) row))
+        info 'first-match)
+       'table-cell
+       (lambda (cell)
+         (let* ((borders (org-export-table-cell-borders cell info))
+                (raw-width (org-export-table-cell-width cell info))
+                (width-cm (when raw-width (/ raw-width 5)))
+                (width (if raw-width (format "w(%dc)" (if (< width-cm 1) 1 width-cm)) "") ))
+           ;; Check left border for the first cell only.
+           (when (and (memq 'left borders) (not alignment))
+             (push "|" alignment))
+           (push 
+            (if (not align)
+                (case (org-export-table-cell-alignment cell info)
+                  (left (concat "l" width divider) )
+                  (right (concat "r" width divider))
+                  (center (concat "c" width divider)))
+              (concat align divider))
+            alignment)
+           (when (memq 'right borders) (push "|" alignment))))
+       info)
+      (apply 'concat (reverse alignment)))
+
+    ))
+
+(defun org-e-man-table--org-table (table contents info)
+  "Return appropriate Man code for an Org table.
+
+TABLE is the table type element to transcode.  CONTENTS is its
+contents, as a string.  INFO is a plist used as a communication
+channel.
+
+This function assumes TABLE has `org' as its `:type' attribute."
+  (let* ((label (org-element-property :name table))
+         (caption (org-e-man--caption/label-string
+                   (org-element-property :caption table) label info))
+         (attr
+          (read
+           (format
+            "(%s)"
+            (mapconcat
+             #'identity
+             (org-element-property :attr_man table)
+             " "))))
+
+         (divider (if (plist-get attr :divider)
+                      "|"
+                    " "))
+
+         ;; Determine alignment string.
+         (alignment (org-e-man-table--align-string divider table info))
+         ;; Extract others display options.
+
+         )
+    ;; Prepare the final format string for the table.
+
+    (setq lines (org-split-string contents "\n"))
+
+    (setq attr-list
+          (let ((result-list '()))
+            (dolist (attr-item 
+                     (list 
+                      (if (plist-get attr :expand) 
+                          "expand"
+                        nil
+                        )
+
+                      (case (plist-get attr :placement)
+                        ('center "center")
+                        ('left nil)
+                        (t 
+                         (if org-e-man-tables-centered  
+                             "center" 
+                           "" )))
+
+                      (case (plist-get attr :boxtype)
+                        ('box "box")
+                        ('doublebox "doublebox")
+                        ('allbox "allbox")
+                        ('none nil)
+                        (t "box"))
+                      ))
+
+              (if attr-item
+                  (add-to-list 'result-list attr-item)
+                ))
+            result-list ))
+
+
+    (setq title-line  (plist-get attr :title-line))
+
+    (setq table-format (concat 
+                        (format "%s"
+                                (or (car attr-list) "" ))
+                        (or 
+                         (let ((output-list '()))
+                           (when (cdr attr-list)
+                             (dolist (attr-item (cdr attr-list))
+                               (setq output-list (concat output-list  (format ",%s" attr-item )) ) ))
+                           output-list)
+                         "") ))
+
+    
+    (when lines
+      (setq first-line (org-split-string (car lines) "\t")))
+
+    (cond
+     ;; Others.
+     (lines (concat ".TS\n " table-format ";\n" 
+                    
+                    (format "%s.\n"
+                            (let ((final-line ""))
+
+                              (when title-line
+                                (dotimes (i (length first-line))
+                                  (setq final-line (concat final-line "cb" divider))
+                                  ))
+
+                              (setq final-line (concat final-line "\n"))
+                              (if alignment
+                                  (setq final-line (concat final-line alignment))
+                                (dotimes (i (length first-line))
+                                  (setq final-line (concat final-line "c" divider))))
+                              final-line ))
+                    (format "%s.TE"
+                            (let ((final-line ""))
+                              (dolist (line-item lines)
+                                (cond 
+                                 (t	
+                                  (setq lines (org-split-string contents "\n"))
+
+                                  (setq final-line (concat final-line 
+                                                           (car (org-split-string line-item "\\\\")) "\n"))
+                                  )
+                                 )
+                                
+                                )  final-line) )
+
+                    )))))
+
+;;;; Table Cell
+
+(defun org-e-man-table-cell (table-cell contents info)
+  "Transcode a TABLE-CELL element from Org to Man
+CONTENTS is the cell contents.  INFO is a plist used as
+a communication channel."
+  (concat (if (and contents
+                   org-e-man-table-scientific-notation
+                   (string-match orgtbl-exp-regexp contents))
+              ;; Use appropriate format string for scientific
+              ;; notation.
+              (format org-e-man-table-scientific-notation
+                      (match-string 1 contents)
+                      (match-string 2 contents))
+            contents)
+          (when (org-export-get-next-element table-cell) " \t ")))
+
+
+;;;; Table Row
+
+(defun org-e-man-table-row (table-row contents info)
+  "Transcode a TABLE-ROW element from Org to Man
+CONTENTS is the contents of the row.  INFO is a plist used as
+a communication channel."
+  ;; Rules are ignored since table separators are deduced from
+  ;; borders of the current row.
+  (when (eq (org-element-property :type table-row) 'standard)
+    (let* ((attr (mapconcat 'identity
+                            (org-element-property
+                             :attr_man (org-export-get-parent table-row))
+                            " "))
+           ;; TABLE-ROW's borders are extracted from its first cell.
+           (borders
+            (org-export-table-cell-borders
+             (car (org-element-contents table-row)) info)))
+      (concat
+       ;; Mark "hline" for horizontal lines.
+       (cond  ((and (memq 'top borders) (memq 'above borders)) "_\n"))
+       contents "\\\\\n"
+       (cond
+        ;; When BOOKTABS are activated enforce bottom rule even when
+        ;; no hline was specifically marked.
+        ((and (memq 'bottom borders) (memq 'below borders)) "_\n")
+        ((memq 'below borders) "_"))))))
+
+
+;;;; Target
+
+(defun org-e-man-target (target contents info)
+  "Transcode a TARGET object from Org to Man.
+CONTENTS is nil.  INFO is a plist holding contextual
+information."
+  (format "\\fI%s\\fP"
+          (org-export-solidify-link-text (org-element-property :value target))))
+
+
+;;;; Timestamp
+
+(defun org-e-man-timestamp (timestamp contents info)
+  "Transcode a TIMESTAMP object from Org to Man.
+  CONTENTS is nil.  INFO is a plist holding contextual
+  information."
+  "" )
+
+
+;;;; Underline
+
+(defun org-e-man-underline (underline contents info)
+  "Transcode UNDERLINE from Org to Man.
+CONTENTS is the text with underline markup.  INFO is a plist
+holding contextual information."
+  (format "\\fI%s\\fP" contents))
+
+
+;;;; Verbatim
+
+(defun org-e-man-verbatim (verbatim contents info)
+  "Transcode a VERBATIM object from Org to Man.
+CONTENTS is nil.  INFO is a plist used as a communication
+channel."
+  (format ".nf\n%s\n.fi" contents))
+
+
+;;;; Verse Block
+
+(defun org-e-man-verse-block (verse-block contents info)
+  "Transcode a VERSE-BLOCK element from Org to Man.
+CONTENTS is verse block contents. INFO is a plist holding
+contextual information."
+  (format ".RS\n.ft I\n%s\n.ft\n.RE" contents))
+
+
+
+;;; Interactive functions
+
+(defun org-e-man-export-to-man
+  (&optional subtreep visible-only body-only ext-plist pub-dir)
+  "Export current buffer to a Man file.
+
+If narrowing is active in the current buffer, only export its
+narrowed part.
+
+If a region is active, export that region.
+
+When optional argument SUBTREEP is non-nil, export the sub-tree
+at point, extracting information from the headline properties
+first.
+
+When optional argument VISIBLE-ONLY is non-nil, don't export
+contents of hidden elements.
+
+When optional argument BODY-ONLY is non-nil, only the body 
+without any markers.
+
+EXT-PLIST, when provided, is a property list with external
+parameters overriding Org default settings, but still inferior to
+file-local settings.
+
+When optional argument PUB-DIR is set, use it as the publishing
+directory.
+
+Return output file's name."
+  (interactive)
+  (let ((outfile (org-export-output-file-name ".man"  subtreep pub-dir)))
+    (org-export-to-file
+     'e-man outfile subtreep visible-only body-only ext-plist)))
+
+(defun org-e-man-export-to-pdf
+  (&optional subtreep visible-only body-only ext-plist pub-dir)
+  "Export current buffer to Groff then process through to PDF.
+
+If narrowing is active in the current buffer, only export its
+narrowed part.
+
+If a region is active, export that region.
+
+When optional argument SUBTREEP is non-nil, export the sub-tree
+at point, extracting information from the headline properties
+first.
+
+When optional argument VISIBLE-ONLY is non-nil, don't export
+contents of hidden elements.
+
+When optional argument BODY-ONLY is non-nil, only write between
+markers. 
+
+EXT-PLIST, when provided, is a property list with external
+parameters overriding Org default settings, but still inferior to
+file-local settings.
+
+When optional argument PUB-DIR is set, use it as the publishing
+directory.
+
+Return PDF file's name."
+  (interactive)
+  (org-e-man-compile
+   (org-e-man-export-to-man
+    subtreep visible-only body-only ext-plist pub-dir)))
+
+(defun org-e-man-compile (grofffile)
+  "Compile a Groff file.
+
+GROFFFILE is the name of the file being compiled.  Processing is
+done through the command specified in `org-e-man-pdf-process'.
+
+Return PDF file name or an error if it couldn't be produced."
+  (let* ((wconfig (current-window-configuration))
+         (grofffile (file-truename grofffile))
+         (base (file-name-sans-extension grofffile))
+         errors)
+    (message (format "Processing Groff file %s ..." grofffile))
+    (unwind-protect
+        (progn
+          (cond
+           ;; A function is provided: Apply it.
+           ((functionp org-e-man-pdf-process)
+            (funcall org-e-man-pdf-process (shell-quote-argument grofffile)))
+           ;; A list is provided: Replace %b, %f and %o with appropriate
+           ;; values in each command before applying it.  Output is
+           ;; redirected to "*Org PDF Groff Output*" buffer.
+           ((consp org-e-man-pdf-process)
+            (let* ((out-dir (or (file-name-directory grofffile) "./"))
+                   (outbuf (get-buffer-create "*Org PDF Groff Output*")))
+              (mapc
+               (lambda (command)
+                 (shell-command
+                  (replace-regexp-in-string
+                   "%b" (shell-quote-argument base)
+                   (replace-regexp-in-string
+                    "%f" (shell-quote-argument grofffile)
+                    (replace-regexp-in-string
+                     "%o" (shell-quote-argument out-dir) command t t) t t) t t)
+                  outbuf))
+               org-e-man-pdf-process)
+              ;; Collect standard errors from output buffer.
+              (setq errors (org-e-man-collect-errors outbuf))))
+           (t (error "No valid command to process to PDF")))
+          (let ((pdffile (concat base ".pdf")))
+            ;; Check for process failure.  Provide collected errors if
+            ;; possible.
+            (if (not (file-exists-p pdffile))
+                (error (concat (format "PDF file %s wasn't produced" pdffile)
+                               (when errors (concat ": " errors))))
+              ;; Else remove log files, when specified, and signal end of
+              ;; process to user, along with any error encountered.
+              (when org-e-man-remove-logfiles
+                (dolist (ext org-e-man-logfiles-extensions)
+                  (let ((file (concat base "." ext)))
+                    (when (file-exists-p file) (delete-file file)))))
+              (message (concat "Process completed"
+                               (if (not errors) "."
+                                 (concat " with errors: " errors)))))
+            ;; Return output file name.
+            pdffile))
+      (set-window-configuration wconfig))))
+
+(defun org-e-man-collect-errors (buffer)
+  "Collect some kind of errors from \"groff\" output
+BUFFER is the buffer containing output.
+Return collected error types as a string, or nil if there was
+none."
+  (with-current-buffer buffer
+    (save-excursion
+      (goto-char (point-max))
+      ;; Find final run
+      nil )))
+
+
+(provide 'org-e-man)
+;;; org-e-man.el ends here

+ 3 - 3
contrib/lisp/org-e-odt.el

@@ -1588,7 +1588,7 @@ CONTENTS is nil.  INFO is a plist holding contextual information."
 		       note-class ref-format ref-name n)))))))
     (concat
      ;; Insert separator between two footnotes in a row.
-     (let ((prev (org-export-get-previous-element footnote-reference)))
+     (let ((prev (org-export-get-previous-element footnote-reference info)))
        (and (eq (org-element-type prev) 'footnote-reference)
 	    (format "<text:span text:style-name=\"%s\">%s</text:span>"
 		    "OrgSuperscript" ",")))
@@ -1699,10 +1699,10 @@ holding contextual information."
      ;; 	     (itemized-body (org-e-odt-format-list-item
      ;; 			     contents type nil nil full-text)))
      ;; 	(concat
-     ;; 	 (and (org-export-first-sibling-p headline)
+     ;; 	 (and (org-export-first-sibling-p headline info)
      ;; 	      (org-e-odt-begin-plain-list type))
      ;; 	 itemized-body
-     ;; 	 (and (org-export-last-sibling-p headline)
+     ;; 	 (and (org-export-last-sibling-p headline info)
      ;; 	      "</text:list>"))))
      ;; Case 3. Standard headline.  Export it as a section.
      (t

+ 31 - 18
contrib/lisp/org-export.el

@@ -1841,7 +1841,7 @@ tag."
     (table-cell
      (and (org-export-table-has-special-column-p
 	   (org-export-get-parent-table blob))
-	  (not (org-export-get-previous-element blob))))
+	  (not (org-export-get-previous-element blob options))))
     ;; Check clock.
     (clock (not (plist-get options :with-clocks)))
     ;; Check planning.
@@ -3126,14 +3126,16 @@ Any tag belonging to this list will also be removed."
 			      (member tag tags)))
 		 (org-element-property :tags element)))
 
-(defun org-export-first-sibling-p (headline)
-  "Non-nil when HEADLINE is the first sibling in its sub-tree."
-  (not (eq (org-element-type (org-export-get-previous-element headline))
+(defun org-export-first-sibling-p (headline info)
+  "Non-nil when HEADLINE is the first sibling in its sub-tree.
+INFO is a plist used as a communication channel."
+  (not (eq (org-element-type (org-export-get-previous-element headline info))
 	   'headline)))
 
-(defun org-export-last-sibling-p (headline)
-  "Non-nil when HEADLINE is the last sibling in its sub-tree."
-  (not (org-export-get-next-element headline)))
+(defun org-export-last-sibling-p (headline info)
+  "Non-nil when HEADLINE is the last sibling in its sub-tree.
+INFO is a plist used as a communication channel."
+  (not (org-export-get-next-element headline info)))
 
 
 ;;;; For Links
@@ -4188,19 +4190,30 @@ OBJECT is either a `table-cell' or `table-element' type object."
 		(not (eq (org-element-type parent) 'table))))
     parent))
 
-(defun org-export-get-previous-element (blob)
+(defun org-export-get-previous-element (blob info)
   "Return previous element or object.
-BLOB is an element or object.  Return previous element or object,
-a string, or nil."
-  (let ((parent (org-export-get-parent blob)))
-    (cadr (memq blob (reverse (org-element-contents parent))))))
+BLOB is an element or object.  INFO is a plist used as
+a communication channel.  Return previous exportable element or
+object, a string, or nil."
+  (let (prev)
+    (catch 'exit
+      (mapc (lambda (obj)
+	      (cond ((eq obj blob) (throw 'exit prev))
+		    ((memq obj (plist-get info :ignore-list)))
+		    (t (setq prev obj))))
+	    (org-element-contents (org-export-get-parent blob))))))
 
-(defun org-export-get-next-element (blob)
+(defun org-export-get-next-element (blob info)
   "Return next element or object.
-BLOB is an element or object.  Return next element or object,
-a string, or nil."
-  (let ((parent (org-export-get-parent blob)))
-    (cadr (memq blob (org-element-contents parent)))))
+BLOB is an element or object.  INFO is a plist used as
+a communication channel.  Return next exportable element or
+object, a string, or nil."
+  (catch 'found
+    (mapc (lambda (obj)
+	    (unless (memq obj (plist-get info :ignore-list))
+	      (throw 'found obj)))
+	  (cdr (memq blob (org-element-contents (org-export-get-parent blob)))))
+    nil))
 
 
 ;;;; Translation
@@ -4288,7 +4301,7 @@ entry.")
   "Translate string S according to language specification.
 
 ENCODING is a symbol among `:ascii', `:html', `:latex', `:latin1'
-and `:utf8'.  INFO is a plist used as a communication channel.
+and `:utf-8'.  INFO is a plist used as a communication channel.
 
 Translation depends on `:language' property.  Return the
 translated string.  If no translation is found return S."

+ 461 - 0
contrib/lisp/org-md.el

@@ -0,0 +1,461 @@
+;;; org-md.el --- Markdown Back-End for Org Export Engine
+
+;; Copyright (C) 2012  Free Software Foundation, Inc.
+
+;; Author: Nicolas Goaziou <n.goaziou@gmail.com>
+;; Keywords: org, wp, tex
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This library implements a Markdown back-end (vanilla flavour) for
+;; Org exporter, based on `e-html'.
+;;
+;; It provides two commands for export, depending on the desired
+;; output: `org-md-export-as-markdown' (temporary buffer) and
+;; `org-md-export-to-markdown' ("md" file).
+
+;;; Code:
+
+(require 'org-e-html)
+
+
+
+;;; User-Configurable Variables
+
+(defgroup org-export-md nil
+  "Options specific to Markdown export back-end."
+  :tag "Org Markdown"
+  :group 'org-export
+  :version "24.2")
+
+(defcustom org-md-headline-style 'atx
+  "Style used to format headlines.
+This variable can be set to either `atx' or `setext'."
+  :group 'org-export-md
+  :type '(choice
+	  (const :tag "Use \"atx\" style" atx)
+	  (const :tag "Use \"Setext\" style" setext)))
+
+
+
+;;; Define Back-End
+
+(org-export-define-derived-backend md e-html
+  :export-block ("MD" "MARKDOWN")
+  :filters-alist ((:filter-parse-tree . org-md-separate-elements))
+  :translate-alist ((bold . org-md-bold)
+		    (code . org-md-verbatim)
+		    (example-block . org-md-example-block)
+		    (footnote-definition . ignore)
+		    (footnote-reference . ignore)
+		    (headline . org-md-headline)
+		    (horizontal-rule . org-md-horizontal-rule)
+		    (inline-src-block . org-md-verbatim)
+		    (italic . org-md-italic)
+		    (item . org-md-item)
+		    (line-break . org-md-line-break)
+		    (link . org-md-link)
+		    (paragraph . org-md-paragraph)
+		    (plain-list . org-md-plain-list)
+		    (plain-text . org-md-plain-text)
+		    (quote-block . org-md-quote-block)
+		    (quote-section . org-md-example-block)
+		    (section . org-md-section)
+		    (src-block . org-md-example-block)
+		    (template . org-md-template)
+		    (verbatim . org-md-verbatim)))
+
+
+
+;;; Filters
+
+(defun org-md-separate-elements (tree backend info)
+  "Make sure elements are separated by at least one blank line.
+
+TREE is the parse tree being exported.  BACKEND is the export
+back-end used.  INFO is a plist used as a communication channel.
+
+Assume BACKEND is `md'."
+  (org-element-map
+   tree org-element-all-elements
+   (lambda (elem)
+     (unless (eq (org-element-type elem) 'org-data)
+       (org-element-put-property
+	elem :post-blank
+	(let ((post-blank (org-element-property :post-blank elem)))
+	  (if (not post-blank) 1 (max 1 post-blank)))))))
+  ;; Return updated tree.
+  tree)
+
+
+
+;;; Transcode Functions
+
+;;;; Bold
+
+(defun org-md-bold (bold contents info)
+  "Transcode BOLD object into Markdown format.
+CONTENTS is the text within bold markup.  INFO is a plist used as
+a communication channel."
+  (format "**%s**" contents))
+
+
+;;;; Code and Verbatim
+
+(defun org-md-verbatim (verbatim contents info)
+  "Transcode VERBATIM object into Markdown format.
+CONTENTS is nil.  INFO is a plist used as a communication
+channel."
+  (let ((value (org-element-property :value verbatim)))
+    (format (cond ((not (string-match "`" value)) "`%s`")
+		  ((or (string-match "\\``" value)
+		       (string-match "`\\'" value))
+		   "`` %s ``")
+		  (t "``%s``"))
+	    value)))
+
+
+;;;; Example Block and Src Block
+
+(defun org-md-example-block (example-block contents info)
+  "Transcode EXAMPLE-BLOCK element into Markdown format.
+CONTENTS is nil.  INFO is a plist used as a communication
+channel."
+  (replace-regexp-in-string
+   "^" "    "
+   (org-remove-indentation
+    (org-element-property :value example-block))))
+
+
+;;;; Headline
+
+(defun org-md-headline (headline contents info)
+  "Transcode HEADLINE element into Markdown format.
+CONTENTS is the headline contents.  INFO is a plist used as
+a communication channel."
+  (unless (org-element-property :footnote-section-p headline)
+    (let* ((level (org-export-get-relative-level headline info))
+	   (title (org-export-data (org-element-property :title headline) info))
+	   (todo (and (plist-get info :with-todo-keywords)
+		      (let ((todo (org-element-property :todo-keyword
+							headline)))
+			(and todo (concat (org-export-data todo info) " ")))))
+	   (tags (and (plist-get info :with-tags)
+		      (let ((tag-list (org-export-get-tags headline info)))
+			(and tag-list
+			     (format "     :%s:"
+				     (mapconcat 'identity tag-list ":"))))))
+	   (priority
+	    (and (plist-get info :with-priority)
+		 (let ((char (org-element-property :priority headline)))
+		   (and char (format "[#%c] " char)))))
+	   ;; Headline text without tags.
+	   (heading (concat todo priority title)))
+      (cond
+       ;; Cannot create an headline.  Fall-back to a list.
+       ((or (org-export-low-level-p headline info)
+	    (not (memq org-md-headline-style '(atx setext)))
+	    (and (eq org-md-headline-style 'atx) (> level 6))
+	    (and (eq org-md-headline-style 'setext) (> level 2)))
+	(let ((bullet
+	       (if (not (org-export-numbered-headline-p headline info)) "-"
+		 (concat (number-to-string
+			  (car (last (org-export-get-headline-number
+				      headline info))))
+			 "."))))
+	  (concat bullet (make-string (- 4 (length bullet)) ? ) heading tags
+		  "\n\n"
+		  (and contents
+		       (replace-regexp-in-string "^" "    " contents)))))
+       ;; Use "Setext" style.
+       ((eq org-md-headline-style 'setext)
+	(concat heading tags "\n"
+		(make-string (length heading) (if (= level 1) ?= ?-))
+		"\n\n"
+		contents))
+       ;; Use "atx" style.
+       (t (concat (make-string level ?#) " " heading tags "\n\n" contents))))))
+
+
+;;;; Horizontal Rule
+
+(defun org-md-horizontal-rule (horizontal-rule contents info)
+  "Transcode HORIZONTAL-RULE element into Markdown format.
+CONTENTS is the horizontal rule contents.  INFO is a plist used
+as a communication channel."
+  "---")
+
+
+;;;; Italic
+
+(defun org-md-italic (italic contents info)
+  "Transcode ITALIC object into Markdown format.
+CONTENTS is the text within italic markup.  INFO is a plist used
+as a communication channel."
+  (format "*%s*" contents))
+
+
+;;;; Item
+
+(defun org-md-item (item contents info)
+  "Transcode ITEM element into Markdown format.
+CONTENTS is the item contents.  INFO is a plist used as
+a communication channel."
+  (let* ((type (org-element-property :type (org-export-get-parent item)))
+	 (struct (org-element-property :structure item))
+	 (bullet (if (not (eq type 'ordered)) "-"
+		   (concat (number-to-string
+			    (car (last (org-list-get-item-number
+					(org-element-property :begin item)
+					struct
+					(org-list-prevs-alist struct)
+					(org-list-parents-alist struct)))))
+			   "."))))
+    (concat bullet
+	    (make-string (- 4 (length bullet)) ? )
+	    (case (org-element-property :checkbox item)
+	      (on "[X] ")
+	      (trans "[-] ")
+	      (off "[ ] "))
+	    (let ((tag (org-element-property :tag item)))
+	      (and tag (format "**%s:** "(org-export-data tag info))))
+	    (org-trim (replace-regexp-in-string "^" "    " contents)))))
+
+
+;;;; Line Break
+
+(defun org-md-line-break (line-break contents info)
+  "Transcode LINE-BREAK object into Markdown format.
+CONTENTS is nil.  INFO is a plist used as a communication
+channel."
+  "  ")
+
+
+;;;; Link
+
+(defun org-md-link (link contents info)
+  "Transcode LINE-BREAK object into Markdown format.
+CONTENTS is the link's description.  INFO is a plist used as
+a communication channel."
+  (let ((--link-org-files-as-html-maybe
+	 (function
+	  (lambda (raw-path info)
+	    ;; Treat links to `file.org' as links to `file.html', if
+            ;; needed.  See `org-e-html-link-org-files-as-html'.
+	    (cond
+	     ((and org-e-html-link-org-files-as-html
+		   (string= ".org"
+			    (downcase (file-name-extension raw-path "."))))
+	      (concat (file-name-sans-extension raw-path) "."
+		      (plist-get info :html-extension)))
+	     (t raw-path)))))
+	(type (org-element-property :type link)))
+    (cond ((member type '("custom-id" "id"))
+	   (let ((destination (org-export-resolve-id-link link info)))
+	     (if (stringp destination)	; External file.
+		 (let ((path (funcall --link-org-files-as-html-maybe
+				      destination info)))
+		   (if (not contents) (format "<%s>" path)
+		     (format "[%s](%s)" contents path)))
+	       (concat
+		(and contents (concat contents " "))
+		(format "(%s)"
+			(format (org-export-translate "See section %s" :html info)
+				(mapconcat 'number-to-string
+					   (org-export-get-headline-number
+					    destination info)
+					   ".")))))))
+	  ((org-export-inline-image-p link org-e-html-inline-image-rules)
+	   (format "![%s](%s)"
+		   (let ((caption
+			  (org-element-property
+			   :caption (org-export-get-parent-element link))))
+		     (when caption (org-export-data (car caption) info)))
+		   path))
+	  ((string= type "coderef")
+	   (let ((ref (org-element-property :path link)))
+	     (format (org-export-get-coderef-format ref contents)
+		     (org-export-resolve-coderef ref info))))
+	  ((equal type "radio")
+	   (let ((destination (org-export-resolve-radio-link link info)))
+	     (org-export-data (org-element-contents destination) info)))
+	  ((equal type "fuzzy")
+	   (let ((destination (org-export-resolve-fuzzy-link link info)))
+	     ;; Ignore invisible "#+TARGET: path".
+	     (unless (eq (org-element-type destination) 'keyword)
+	       (if (org-string-nw-p contents) contents
+		 (when destination
+		   (let ((number (org-export-get-ordinal destination info)))
+		     (when number
+		       (if (atom number) (number-to-string number)
+			 (mapconcat 'number-to-string number ".")))))))))
+	  (t (let* ((raw-path (org-element-property :path link))
+		    (path (cond
+			   ((member type '("http" "https" "ftp"))
+			    (concat type ":" raw-path))
+			   ((equal type "file")
+			    ;; Extract just the file path and strip
+			    ;; all other components.
+			    (when (string-match "\\(.+\\)::.+" raw-path)
+			      (setq raw-path (match-string 1 raw-path)))
+			    ;; Treat links to ".org" files as ".html",
+			    ;; if needed.
+			    (setq raw-path
+				  (funcall --link-org-files-as-html-maybe
+					   raw-path info))
+			    ;; If file path is absolute, prepend it
+			    ;; with protocol component - "file://".
+			    (if (not (file-name-absolute-p raw-path)) raw-path
+			      (concat "file://" (expand-file-name raw-path))))
+			   (t raw-path))))
+	       (if (not contents) (format "<%s>" path)
+		 (format "[%s](%s)" contents path)))))))
+
+
+;;;; Paragraph
+
+(defun org-md-paragraph (paragraph contents info)
+  "Transcode PARAGRAPH element into Markdown format.
+CONTENTS is the paragraph contents.  INFO is a plist used as
+a communication channel."
+  (let ((first-object (car (org-element-contents paragraph))))
+    ;; If paragraph starts with a #, protect it.
+    (if (and (stringp first-object) (string-match "\\`#" first-object))
+	(replace-match "\\#" nil t first-object)
+      contents)))
+
+
+;;;; Plain List
+
+(defun org-md-plain-list (plain-list contents info)
+  "Transcode PLAIN-LIST element into Markdown format.
+CONTENTS is the plain-list contents.  INFO is a plist used as
+a communication channel."
+  contents)
+
+
+;;;; Plain Text
+
+(defun org-md-plain-text (text info)
+  "Transcode a TEXT string into Markdown format.
+TEXT is the string to transcode.  INFO is a plist holding
+contextual information."
+  ;; Protect ambiguous #.  This will protect # at the beginning of
+  ;; a line, but not at the beginning of a paragraph.  See
+  ;; `org-md-paragraph'.
+  (setq text (replace-regexp-in-string "\n#" "\n\\\\#" text))
+  ;; Protect ambiguous !
+  (setq text (replace-regexp-in-string "\\(!\\)\\[" "\\\\!" text nil nil 1))
+  ;; Protect `, *, _ and \
+  (setq text
+	(replace-regexp-in-string
+	 "[`*_\\]" (lambda (rep) (concat "\\\\" (match-string 1 rep))) text))
+  ;; Handle special strings, if required.
+  (when (plist-get info :with-special-strings)
+    (setq text (org-e-html-convert-special-strings text)))
+  ;; Handle break preservation, if required.
+  (when (plist-get info :preserve-breaks)
+    (setq text (replace-regexp-in-string "[ \t]*\n" "  \n" text)))
+  ;; Return value.
+  text)
+
+
+;;;; Quote Block
+
+(defun org-md-quote-block (quote-block contents info)
+  "Transcode QUOTE-BLOCK element into Markdown format.
+CONTENTS is the quote-block contents.  INFO is a plist used as
+a communication channel."
+  (replace-regexp-in-string
+   "^" "> "
+   (replace-regexp-in-string "\n\\'" "" contents)))
+
+
+;;;; Section
+
+(defun org-md-section (section contents info)
+  "Transcode SECTION element into Markdown format.
+CONTENTS is the section contents.  INFO is a plist used as
+a communication channel."
+  contents)
+
+
+;;;; Template
+
+(defun org-md-template (contents info)
+  "Return complete document string after Markdown conversion.
+CONTENTS is the transcoded contents string.  INFO is a plist used
+as a communication channel."
+  contents)
+
+
+
+;;; Interactive function
+
+;;;###autoload
+(defun org-md-export-as-markdown (&optional subtreep visible-only)
+  "Export current buffer to a text buffer.
+
+If narrowing is active in the current buffer, only export its
+narrowed part.
+
+If a region is active, export that region.
+
+When optional argument SUBTREEP is non-nil, export the sub-tree
+at point, extracting information from the headline properties
+first.
+
+When optional argument VISIBLE-ONLY is non-nil, don't export
+contents of hidden elements.
+
+Export is done in a buffer named \"*Org MD Export*\", which will
+be displayed when `org-export-show-temporary-export-buffer' is
+non-nil."
+  (interactive)
+  (let ((outbuf (org-export-to-buffer
+		 'md "*Org MD Export*" subtreep visible-only)))
+    (with-current-buffer outbuf (text-mode))
+    (when org-export-show-temporary-export-buffer
+      (switch-to-buffer-other-window outbuf))))
+
+
+;;;###autoload
+(defun org-md-export-to-markdown (&optional subtreep visible-only pub-dir)
+  "Export current buffer to a Markdown file.
+
+If narrowing is active in the current buffer, only export its
+narrowed part.
+
+If a region is active, export that region.
+
+When optional argument SUBTREEP is non-nil, export the sub-tree
+at point, extracting information from the headline properties
+first.
+
+When optional argument VISIBLE-ONLY is non-nil, don't export
+contents of hidden elements.
+
+When optional argument PUB-DIR is set, use it as the publishing
+directory.
+
+Return output file's name."
+  (interactive)
+  (let ((outfile (org-export-output-file-name ".md" subtreep pub-dir)))
+    (org-export-to-file 'md outfile subtreep visible-only)))
+
+
+(provide 'org-md)
+;;; org-md.el ends here

+ 11 - 5
doc/org.texi

@@ -6080,8 +6080,14 @@ Recompute the time interval after changing one of the timestamps.  This
 is only necessary if you edit the timestamps directly.  If you change
 them with @kbd{S-@key{cursor}} keys, the update is automatic.
 @orgcmd{C-S-@key{up/down},org-clock-timestamps-up/down}
-On @code{CLOCK} log lines, increase/decrease both timestamps at the same
-time so that duration keeps the same.
+On @code{CLOCK} log lines, increase/decrease both timestamps so that the
+clock duration keeps the same. 
+@orgcmd{S-M-@key{up/down},org-timestamp-up/down}
+On @code{CLOCK} log lines, increase/decrease the timestamp at point and
+the one of the previous (or the next clock) timestamp by the same duration.
+For example, if you hit @kbd{S-M-@key{up}} to increase a clocked-out timestamp
+by five minutes, then the clocked-in timestamp of the next clock will be
+increased by five minutes.
 @orgcmd{C-c C-t,org-todo}
 Changing the TODO state of an item to DONE automatically stops the clock
 if it is running in this same item.
@@ -6313,7 +6319,7 @@ identical to dealing with away time due to idleness; it is just happening due
 to a recovery event rather than a set amount of idle time.
 
 You can also check all the files visited by your Org agenda for dangling
-clocks at any time using @kbd{M-x org-resolve-clocks}.
+clocks at any time using @kbd{M-x org-resolve-clocks RET} (or @kbd{C-c C-x C-z}).
 
 @subsubheading Continuous clocking
 @cindex continuous clocking
@@ -16459,8 +16465,8 @@ rely on outline paths, in the hope that these will be unique enough.}.
 Finally, Org writes the file @file{index.org}, containing links to all other
 files.  @i{MobileOrg} first reads this file from the server, and then
 downloads all agendas and Org files listed in it.  To speed up the download,
-MobileOrg will only read files whose checksums@footnote{stored automatically
-in the file @file{checksums.dat}} have changed.
+MobileOrg will only read files whose checksums@footnote{Checksums are stored 
+automatically in the file @file{checksums.dat}} have changed.
 
 @node Pulling from MobileOrg,  , Pushing to MobileOrg, MobileOrg
 @section Pulling from MobileOrg

+ 1 - 1
lisp/ob-R.el

@@ -145,7 +145,7 @@ This function is called by `org-babel-execute-src-block'."
 ;; helper functions
 
 (defun org-babel-variable-assignments:R (params)
-  "Return list of R statements assigning the block's variables"
+  "Return list of R statements assigning the block's variables."
   (let ((vars (mapcar #'cdr (org-babel-get-header params :var))))
     (mapcar
      (lambda (pair)

+ 1 - 1
lisp/ob-asymptote.el

@@ -88,7 +88,7 @@ Asymptote does not support sessions"
   (error "Asymptote does not support sessions"))
 
 (defun org-babel-variable-assignments:asymptote (params)
-  "Return list of asymptote statements assigning the block's variables"
+  "Return list of asymptote statements assigning the block's variables."
   (mapcar #'org-babel-asymptote-var-to-asymptote
 	  (mapcar #'cdr (org-babel-get-header params :var))))
 

+ 9 - 1
lisp/ob-exp.el

@@ -32,10 +32,18 @@
 (defvar org-current-export-file)
 (defvar org-babel-lob-one-liner-regexp)
 (defvar org-babel-ref-split-regexp)
+(defvar org-list-forbidden-blocks)
+
 (declare-function org-babel-lob-get-info "ob-lob" ())
 (declare-function org-babel-eval-wipe-error-buffer "ob-eval" ())
-(add-to-list 'org-export-interblocks '(src org-babel-exp-non-block-elements))
+(declare-function org-heading-components "org" ())
+(declare-function org-link-search "org" (s &optional type avoid-pos stealth))
+(declare-function org-fill-template "org" (template alist))
+(declare-function org-in-verbatim-emphasis "org" ())
+(declare-function org-in-block-p "org" (names))
+(declare-function org-between-regexps-p "org" (start-re end-re &optional lim-up lim-down))
 
+(add-to-list 'org-export-interblocks '(src org-babel-exp-non-block-elements))
 (org-export-blocks-add-block '(src org-babel-exp-src-block nil))
 
 (defcustom org-export-babel-evaluate t

+ 1 - 1
lisp/ob-gnuplot.el

@@ -183,7 +183,7 @@ This function is called by `org-babel-execute-src-block'."
       buffer)))
 
 (defun org-babel-variable-assignments:gnuplot (params)
-  "Return list of gnuplot statements assigning the block's variables"
+  "Return list of gnuplot statements assigning the block's variables."
   (mapcar
    (lambda (pair) (format "%s = \"%s\"" (car pair) (cdr pair)))
    (org-babel-gnuplot-process-vars params)))

+ 1 - 1
lisp/ob-haskell.el

@@ -125,7 +125,7 @@ then create one.  Return the initialized session."
       (current-buffer))))
 
 (defun org-babel-variable-assignments:haskell (params)
-  "Return list of haskell statements assigning the block's variables"
+  "Return list of haskell statements assigning the block's variables."
   (mapcar (lambda (pair)
 	    (format "let %s = %s"
 		    (car pair)

+ 1 - 1
lisp/ob-js.el

@@ -130,7 +130,7 @@ specifying a variable of the same value."
     session))
 
 (defun org-babel-variable-assignments:js (params)
-  "Return list of Javascript statements assigning the block's variables"
+  "Return list of Javascript statements assigning the block's variables."
   (mapcar
    (lambda (pair) (format "var %s=%s;"
 			  (car pair) (org-babel-js-var-to-js (cdr pair))))

+ 11 - 39
lisp/ob-lilypond.el

@@ -107,7 +107,6 @@ blocks")
 
 (defun org-babel-expand-body:lilypond (body params)
   "Expand BODY according to PARAMS, return the expanded body."
-
   (let ((vars (mapcar #'cdr (org-babel-get-header params :var))))
     (mapc
      (lambda (pair)
@@ -127,7 +126,6 @@ Depending on whether we are in arrange mode either:
 1. Attempt to execute lilypond block according to header settings
   (This is the default basic mode)
 2. Tangle all lilypond blocks and process the result (arrange mode)"
-
   (ly-set-header-args ly-arrange-mode)
   (if ly-arrange-mode
       (ly-tangle)
@@ -137,14 +135,12 @@ Depending on whether we are in arrange mode either:
   "ob-lilypond specific tangle, attempts to invoke
 =ly-execute-tangled-ly= if tangle is successful. Also passes
 specific arguments to =org-babel-tangle="
-
   (interactive)
   (if (org-babel-tangle nil "yes" "lilypond")
       (ly-execute-tangled-ly) nil))
 
 (defun ly-process-basic (body params)
-  "Execute a lilypond block in basic mode"
-
+  "Execute a lilypond block in basic mode."
   (let* ((result-params (cdr (assoc :result-params params)))
 	 (out-file (cdr (assoc :file params)))
 	 (cmdline (or (cdr (assoc :cmdline params))
@@ -153,7 +149,6 @@ specific arguments to =org-babel-tangle="
 
     (with-temp-file in-file
       (insert (org-babel-expand-body:generic body params)))
-
     (org-babel-eval
      (concat
       (ly-determine-ly-path)
@@ -165,18 +160,15 @@ specific arguments to =org-babel-tangle="
       (file-name-sans-extension out-file)
       " "
       cmdline
-      in-file) "")
-    ) nil)
+      in-file) "")) nil)
 
 (defun org-babel-prep-session:lilypond (session params)
   "Return an error because LilyPond exporter does not support sessions."
-
   (error "Sorry, LilyPond does not currently support sessions!"))
 
 (defun ly-execute-tangled-ly ()
   "Compile result of block tangle with lilypond.
 If error in compilation, attempt to mark the error in lilypond org file"
-
   (when ly-compile-post-tangle
     (let ((ly-tangled-file (ly-switch-extension
                             (buffer-file-name) ".lilypond"))
@@ -203,7 +195,6 @@ If error in compilation, attempt to mark the error in lilypond org file"
 (defun ly-compile-lilyfile (file-name &optional test)
   "Compile lilypond file and check for compile errors
 FILE-NAME is full path to lilypond (.ly) file"
-
   (message "Compiling LilyPond...")
   (let ((arg-1 (ly-determine-ly-path)) ;program
         (arg-2 nil)                    ;infile
@@ -241,7 +232,6 @@ nil as file-name since it is unused in this context"
 (defun ly-process-compile-error (file-name)
   "Process the compilation error that has occurred.
 FILE-NAME is full path to lilypond file"
-
   (let ((line-num (ly-parse-line-num)))
     (let ((error-lines (ly-parse-error-line file-name line-num)))
       (ly-mark-error-line file-name error-lines)
@@ -251,7 +241,6 @@ FILE-NAME is full path to lilypond file"
   "Mark the erroneous lines in the lilypond org buffer.
 FILE-NAME is full path to lilypond file.
 LINE is the erroneous line"
-
   (switch-to-buffer-other-window
    (concat (file-name-nondirectory
             (ly-switch-extension file-name ".org"))))
@@ -267,7 +256,6 @@ LINE is the erroneous line"
 
 (defun ly-parse-line-num (&optional buffer)
   "Extract error line number."
-
   (when buffer
     (set-buffer buffer))
   (let ((start
@@ -292,7 +280,6 @@ LINE is the erroneous line"
   "Extract the erroneous line from the tangled .ly file
 FILE-NAME is full path to lilypond file.
 LINENO is the number of the erroneous line"
-
   (with-temp-buffer
     (insert-file-contents (ly-switch-extension file-name ".ly")
 			  nil nil nil t)
@@ -307,7 +294,6 @@ LINENO is the number of the erroneous line"
   "Attempt to display the generated pdf file
 FILE-NAME is full path to lilypond file
 If TEST is non-nil, the shell command is returned and is not run"
-
   (when ly-display-pdf-post-tangle
     (let ((pdf-file (ly-switch-extension file-name ".pdf")))
       (if (file-exists-p pdf-file)
@@ -326,7 +312,6 @@ If TEST is non-nil, the shell command is returned and is not run"
   "Attempt to play the generated MIDI file
 FILE-NAME is full path to lilypond file
 If TEST is non-nil, the shell command is returned and is not run"
-
   (when ly-play-midi-post-tangle
     (let ((midi-file (ly-switch-extension file-name ".midi")))
       (if (file-exists-p midi-file)
@@ -344,7 +329,6 @@ If TEST is non-nil, the shell command is returned and is not run"
 (defun ly-determine-ly-path (&optional test)
   "Return correct path to ly binary depending on OS
 If TEST is non-nil, it contains a simulation of the OS for test purposes"
-
   (let ((sys-type
          (or test system-type)))
     (cond ((string= sys-type  "darwin")
@@ -356,7 +340,6 @@ If TEST is non-nil, it contains a simulation of the OS for test purposes"
 (defun ly-determine-pdf-path (&optional test)
   "Return correct path to pdf viewer depending on OS
 If TEST is non-nil, it contains a simulation of the OS for test purposes"
-
   (let ((sys-type
          (or test system-type)))
     (cond ((string= sys-type  "darwin")
@@ -368,7 +351,6 @@ If TEST is non-nil, it contains a simulation of the OS for test purposes"
 (defun ly-determine-midi-path (&optional test)
   "Return correct path to midi player depending on OS
 If TEST is non-nil, it contains a simulation of the OS for test purposes"
-
   (let ((sys-type
          (or test test system-type)))
     (cond ((string= sys-type  "darwin")
@@ -378,8 +360,7 @@ If TEST is non-nil, it contains a simulation of the OS for test purposes"
           (t ly-nix-midi-path))))
 
 (defun ly-toggle-midi-play ()
-  "Toggle whether midi will be played following a successful compilation"
-
+  "Toggle whether midi will be played following a successful compilation."
   (interactive)
   (setq ly-play-midi-post-tangle
         (not ly-play-midi-post-tangle))
@@ -388,8 +369,7 @@ If TEST is non-nil, it contains a simulation of the OS for test purposes"
                        "ENABLED." "DISABLED."))))
 
 (defun ly-toggle-pdf-display ()
-  "Toggle whether pdf will be displayed following a successful compilation"
-
+  "Toggle whether pdf will be displayed following a successful compilation."
   (interactive)
   (setq ly-display-pdf-post-tangle
         (not ly-display-pdf-post-tangle))
@@ -398,35 +378,28 @@ If TEST is non-nil, it contains a simulation of the OS for test purposes"
                        "ENABLED." "DISABLED."))))
 
 (defun ly-toggle-png-generation ()
-  "Toggle whether png image will be generated by compilation"
-
+  "Toggle whether png image will be generated by compilation."
   (interactive)
-  (setq ly-gen-png
-        (not ly-gen-png))
+  (setq ly-gen-png (not ly-gen-png))
   (message (concat "PNG image generation has been "
                    (if ly-gen-png "ENABLED." "DISABLED."))))
 
 (defun ly-toggle-html-generation ()
-  "Toggle whether html will be generated by compilation"
-
+  "Toggle whether html will be generated by compilation."
   (interactive)
-  (setq ly-gen-html
-        (not ly-gen-html))
+  (setq ly-gen-html (not ly-gen-html))
   (message (concat "HTML generation has been "
                    (if ly-gen-html "ENABLED." "DISABLED."))))
 
 (defun ly-toggle-pdf-generation ()
-  "Toggle whether pdf will be generated by compilation"
-
+  "Toggle whether pdf will be generated by compilation."
   (interactive)
-  (setq ly-gen-pdf
-        (not ly-gen-pdf))
+  (setq ly-gen-pdf (not ly-gen-pdf))
   (message (concat "PDF generation has been "
                    (if ly-gen-pdf "ENABLED." "DISABLED."))))
 
 (defun ly-toggle-arrange-mode ()
-  "Toggle whether in Arrange mode or Basic mode"
-
+  "Toggle whether in Arrange mode or Basic mode."
   (interactive)
   (setq ly-arrange-mode
         (not ly-arrange-mode))
@@ -435,7 +408,6 @@ If TEST is non-nil, it contains a simulation of the OS for test purposes"
 
 (defun ly-switch-extension (file-name ext)
   "Utility command to swap current FILE-NAME extension with EXT"
-
   (concat (file-name-sans-extension
            file-name) ext))
 

+ 1 - 1
lisp/ob-ocaml.el

@@ -93,7 +93,7 @@
                            (get-buffer tuareg-interactive-buffer-name))))
 
 (defun org-babel-variable-assignments:ocaml (params)
-  "Return list of ocaml statements assigning the block's variables"
+  "Return list of ocaml statements assigning the block's variables."
   (mapcar
    (lambda (pair) (format "let %s = %s;;" (car pair)
 			  (org-babel-ocaml-elisp-to-ocaml (cdr pair))))

+ 2 - 2
lisp/ob-octave.el

@@ -110,7 +110,7 @@ end")
   (org-babel-prep-session:octave session params 'matlab))
 
 (defun org-babel-variable-assignments:octave (params)
-  "Return list of octave statements assigning the block's variables"
+  "Return list of octave statements assigning the block's variables."
   (mapcar
    (lambda (pair)
      (format "%s=%s;"
@@ -265,7 +265,7 @@ This removes initial blank and comment lines and then calls
     (org-babel-import-elisp-from-file temp-file '(16))))
 
 (defun org-babel-octave-read-string (string)
-  "Strip \\\"s from around octave string"
+  "Strip \\\"s from around octave string."
   (if (string-match "^\"\\([^\000]+\\)\"$" string)
       (match-string 1 string)
     string))

+ 2 - 2
lisp/ob-perl.el

@@ -60,7 +60,7 @@ This function is called by `org-babel-execute-src-block'."
   (error "Sessions are not supported for Perl."))
 
 (defun org-babel-variable-assignments:perl (params)
-  "Return list of perl statements assigning the block's variables"
+  "Return list of perl statements assigning the block's variables."
   (mapcar
    (lambda (pair)
      (format "$%s=%s;"
@@ -81,7 +81,7 @@ specifying a var of the same value."
 (defvar org-babel-perl-buffers '(:default . nil))
 
 (defun org-babel-perl-initiate-session (&optional session params)
-  "Return nil because sessions are not supported by perl"
+  "Return nil because sessions are not supported by perl."
 nil)
 
 (defvar org-babel-perl-wrapper-method

+ 2 - 2
lisp/ob-python.el

@@ -99,7 +99,7 @@ VARS contains resolved variable references"
 ;; helper functions
 
 (defun org-babel-variable-assignments:python (params)
-  "Return list of python statements assigning the block's variables"
+  "Return list of python statements assigning the block's variables."
   (mapcar
    (lambda (pair)
      (format "%s=%s"
@@ -287,7 +287,7 @@ last statement in BODY, as elisp."
 	  (org-babel-eval-read-file tmp-file)))))))
 
 (defun org-babel-python-read-string (string)
-  "Strip 's from around python string"
+  "Strip 's from around python string."
   (if (string-match "^'\\([^\000]+\\)'$" string)
       (match-string 1 string)
     string))

+ 1 - 1
lisp/ob-ruby.el

@@ -102,7 +102,7 @@ This function is called by `org-babel-execute-src-block'."
 ;; helper functions
 
 (defun org-babel-variable-assignments:ruby (params)
-  "Return list of ruby statements assigning the block's variables"
+  "Return list of ruby statements assigning the block's variables."
   (mapcar
    (lambda (pair)
      (format "%s=%s"

+ 1 - 1
lisp/ob-sh.el

@@ -90,7 +90,7 @@ This function is called by `org-babel-execute-src-block'."
 ;; helper functions
 
 (defun org-babel-variable-assignments:sh (params)
-  "Return list of shell statements assigning the block's variables"
+  "Return list of shell statements assigning the block's variables."
   (let ((sep (cdr (assoc :separator params))))
     (mapcar
      (lambda (pair)

+ 2 - 2
lisp/ob.el

@@ -1636,7 +1636,7 @@ With optional prefix argument ARG, jump backward ARG many source blocks."
 
 ;;;###autoload
 (defun org-babel-mark-block ()
-  "Mark current src block"
+  "Mark current src block."
   (interactive)
   ((lambda (head)
      (when head
@@ -2021,7 +2021,7 @@ code ---- the results are extracted in the syntax of the source
         (delete-region start (org-babel-result-end))))))
 
 (defun org-babel-result-end ()
-  "Return the point at the end of the current set of results"
+  "Return the point at the end of the current set of results."
   (save-excursion
     (cond
      ((org-at-table-p) (progn (goto-char (org-table-end)) (point)))

+ 27 - 22
lisp/org-agenda.el

@@ -1221,10 +1221,18 @@ agenda display."
   :type 'boolean)
 
 (defcustom org-agenda-start-with-log-mode nil
-  "The initial value of log-mode in a newly created agenda window."
+  "The initial value of log-mode in a newly created agenda window.
+See `org-agenda-log-mode' and `org-agenda-log-mode-items' for further
+explanations on the possible values."
   :group 'org-agenda-startup
   :group 'org-agenda-daily/weekly
-  :type 'boolean)
+  :type '(choice (const :tag "Don't show log items" nil)
+		 (const :tag "Show only log items" 'only)
+		 (const :tag "Show all possible log items" 'clockcheck)
+		 (repeat :tag "Choose among possible values for `org-agenda-log-mode-items'"
+			 (choice (const :tag "Show closed log items" 'closed)
+				 (const :tag "Show clocked log items" 'clock)
+				 (const :tag "Show all logged state changes" 'state)))))
 
 (defcustom org-agenda-start-with-clockreport-mode nil
   "The initial value of clockreport-mode in a newly created agenda window."
@@ -1793,10 +1801,6 @@ Note that functions in this alist don't need to be quoted."
   :version "24.1"
   :group 'org-agenda)
 
-(eval-when-compile
-  (require 'cl))
-(require 'org)
-
 (defmacro org-agenda-with-point-at-orig-entry (string &rest body)
   "Execute BODY with point at location given by `org-hd-marker' property.
 If STRING is non-nil, the text property will be fetched from position 0
@@ -2880,7 +2884,6 @@ This ensures the export commands can easily use it."
       (setq res (replace-match ";" t t res)))
     (org-trim res)))
 
-
 ;;;###autoload
 (defun org-store-agenda-views (&rest parameters)
   (interactive)
@@ -2893,11 +2896,13 @@ This ensures the export commands can easily use it."
 	(pop-up-frames nil)
 	(dir default-directory)
 	(pars (org-make-parameter-alist parameters))
-	cmd thiscmdkey files opts cmd-or-set)
+	cmd thiscmdkey files opts cmd-or-set bufname)
     (save-window-excursion
       (while cmds
 	(setq cmd (pop cmds)
 	      thiscmdkey (car cmd)
+	      bufname (if org-agenda-sticky (format "*Org Agenda(%s)*" thiscmdkey)
+			org-agenda-buffer-name)
 	      cmd-or-set (nth 2 cmd)
 	      opts (nth (if (listp cmd-or-set) 3 4) cmd)
 	      files (nth (if (listp cmd-or-set) 4 5) cmd))
@@ -2906,13 +2911,13 @@ This ensures the export commands can easily use it."
 	  (org-eval-in-environment (append org-agenda-exporter-settings
 					   opts pars)
 	    (org-agenda nil thiscmdkey))
-	  (set-buffer org-agenda-buffer-name)
+	  (set-buffer bufname)
 	  (while files
 	    (org-eval-in-environment (append org-agenda-exporter-settings
 					     opts pars)
-	      (org-agenda-write (expand-file-name (pop files) dir) nil t)))
-	  (and (get-buffer org-agenda-buffer-name)
-	       (kill-buffer org-agenda-buffer-name)))))))
+	      (org-agenda-write (expand-file-name (pop files) dir) nil t bufname)))
+	  (and (get-buffer bufname)
+	       (kill-buffer bufname)))))))
 (def-edebug-spec org-batch-store-agenda-views (&rest sexp))
 
 (defun org-agenda-mark-header-line (pos)
@@ -2927,7 +2932,7 @@ This ensures the export commands can easily use it."
 
 (defvar org-mobile-creating-agendas)
 (defvar org-agenda-write-buffer-name "Agenda View")
-(defun org-agenda-write (file &optional open nosettings)
+(defun org-agenda-write (file &optional open nosettings agenda-bufname)
   "Write the current buffer (an agenda view) as a file.
 Depending on the extension of the file name, plain text (.txt),
 HTML (.html or .htm) or Postscript (.ps) is produced.
@@ -2938,7 +2943,8 @@ With prefix argument OPEN, open the new file immediately.
 If NOSETTINGS is given, do not scope the settings of
 `org-agenda-exporter-settings' into the export commands.  This is used when
 the settings have already been scoped and we do not wish to overrule other,
-higher priority settings."
+higher priority settings.
+If AGENDA-BUFFER-NAME, use this as the buffer name for the agenda to write."
   (interactive "FWrite agenda to file: \nP")
   (if (not (file-writable-p file))
       (error "Cannot write agenda to file %s" file))
@@ -2965,7 +2971,6 @@ higher priority settings."
 	      ((string-match "\\.html?\\'" file)
 	       (require 'htmlize)
 	       (set-buffer (htmlize-buffer (current-buffer)))
-
 	       (when (and org-agenda-export-html-style
 			  (string-match "<style>" org-agenda-export-html-style))
 		 ;; replace <style> section with org-agenda-export-html-style
@@ -3007,7 +3012,7 @@ higher priority settings."
 		 (save-buffer 0)
 		 (kill-buffer (current-buffer))
 		 (message "Plain text written to %s" file))))))))
-    (set-buffer org-agenda-buffer-name))
+    (set-buffer (or agenda-bufname org-agenda-buffer-name)))
   (when open (org-open-file file)))
 
 (defvar org-agenda-tag-filter-overlays nil)
@@ -3232,9 +3237,9 @@ the global options and expect it to be applied to the entire view.")
 
 
 (defun org-agenda-use-sticky-p ()
-  "Return non-NIL if existing agenda buffer named
-`org-agenda-buffer-name' exists, and should be shown instead of
-generating a new one"
+  "Return non-nil if an agenda buffer named
+`org-agenda-buffer-name' exists and should be shown instead of
+generating a new one."
   (and
    ;; turned off by user
    org-agenda-sticky
@@ -3253,7 +3258,7 @@ generating a new one"
       org-agenda-this-buffer-is-sticky))))
 
 (defun org-prepare-agenda-window (abuf)
-  "Setup agenda buffer in the window"
+  "Setup agenda buffer in the window."
   (let* ((awin (get-buffer-window abuf))
 	 wconf)
     (cond
@@ -6381,7 +6386,7 @@ If ERROR is non-nil, throw an error, otherwise just return nil."
       nil)))
 
 (defun org-agenda-Quit (&optional arg)
-  "Exit agenda by removing the window or the buffer"
+  "Exit agenda by removing the window or the buffer."
   (interactive)
   (if org-agenda-columns-active
       (org-columns-quit)
@@ -9032,7 +9037,7 @@ details and examples."
     (eq date today)))
 
 (defun org-agenda-todo-yesterday (&optional arg)
-  "Like `org-agenda-todo' but the time of change will be 23:59 of yesterday"
+  "Like `org-agenda-todo' but the time of change will be 23:59 of yesterday."
   (interactive "P")
   (let* ((hour (third (decode-time
                        (org-current-time))))

+ 1 - 1
lisp/org-bibtex.el

@@ -386,7 +386,7 @@ This variable is relevant only if `org-bibtex-export-tags-as-keywords` is t."
        (read-from-minibuffer (format "%s: " name))))))
 
 (defun org-bibtex-autokey ()
-  "Generate an autokey for the current headline"
+  "Generate an autokey for the current headline."
   (org-bibtex-put org-bibtex-key-property
                   (if org-bibtex-autogen-keys
                       (let* ((entry (org-bibtex-headline))

+ 1 - 1
lisp/org-capture.el

@@ -1255,7 +1255,7 @@ Use PREFIX as a prefix for the name of the indirect buffer."
 	 buf)))))
 
 (defun org-capture-verify-tree (tree)
-  "Throw error if TREE is not a valid tree"
+  "Throw error if TREE is not a valid tree."
   (unless (org-kill-is-subtree-p tree)
     (error "Template is not a valid Org entry or tree")))
 

+ 13 - 8
lisp/org-clock.el

@@ -26,7 +26,6 @@
 
 ;; This file contains the time clocking code for Org-mode
 
-(require 'org)
 (require 'org-exp)
 ;;; Code:
 
@@ -1000,6 +999,12 @@ If `only-dangling-p' is non-nil, only ask to resolve dangling
   "Return the current Mac idle time in seconds."
   (string-to-number (shell-command-to-string "ioreg -c IOHIDSystem | perl -ane 'if (/Idle/) {$idle=(pop @F)/1000000000; print $idle; last}'")))
 
+(defvar org-x11idle-exists-p
+  ;; Check that x11idle exists
+  (and (eq (call-process-shell-command "command" nil nil nil "-v" "x11idle") 0)
+       ;; Check that x11idle can retrieve the idle time
+       (eq (call-process-shell-command "x11idle" nil nil nil) 0)))
+
 (defun org-x11-idle-seconds ()
   "Return the current X11 idle time in seconds."
   (/ (string-to-number (shell-command-to-string "x11idle")) 1000))
@@ -1010,12 +1015,7 @@ This routine returns a floating point number."
   (cond
    ((eq system-type 'darwin)
     (org-mac-idle-seconds))
-   ((and
-     (eq window-system 'x)
-     ;; Check that x11idle exists
-     (eq (call-process-shell-command "command" nil nil nil "-v" "x11idle") 0)
-     ;; Check that x11idle can retrieve the idle time
-     (eq (call-process-shell-command "x11idle" nil nil nil ) 0))
+   ((and (eq window-system 'x) org-x11idle-exists-p)
     (org-x11-idle-seconds))
    (t
     (org-emacs-idle-seconds))))
@@ -1146,7 +1146,12 @@ clock in by using the last clock-out time as the start time
 	    (goto-char target-pos)
 	    (org-back-to-heading t)
 	    (or interrupting (move-marker org-clock-interrupted-task nil))
-	    (org-clock-history-push)
+	    (save-excursion
+	      (forward-char) ;; make sure the marker is not at the
+			     ;; beginning of the heading, since the
+			     ;; user is liking to insert stuff here
+			     ;; manually
+	      (org-clock-history-push))
 	    (org-clock-set-current)
 	    (cond ((functionp org-clock-in-switch-to-state)
 		   (looking-at org-complex-heading-regexp)

+ 1 - 1
lisp/org-crypt.el

@@ -75,7 +75,7 @@
 		  (context plain recipients &optional sign always-trust))
 
 (defgroup org-crypt nil
-  "Org Crypt"
+  "Org Crypt."
   :tag "Org Crypt"
   :group 'org)
 

+ 228 - 258
contrib/lisp/org-element.el → lisp/org-element.el

@@ -108,9 +108,8 @@
 
 ;;; Code:
 
-(eval-when-compile (require 'cl))
-(require 'org)
-(declare-function org-inlinetask-goto-end "org-inlinetask" ())
+(eval-when-compile
+  (require 'cl))
 
 
 
@@ -124,7 +123,7 @@
 ;; process.
 
 (defconst org-element-paragraph-separate
-  (concat "\f" "\\|" "^[ \t]*$" "\\|"
+  (concat "^[ \t]*$" "\\|"
 	  ;; Headlines and inlinetasks.
 	  org-outline-regexp-bol "\\|"
 	  ;; Comments, blocks (any type), keywords and babel calls.
@@ -140,11 +139,7 @@
 	  ;; LaTeX environments.
 	  "^[ \t]*\\\\\\(begin\\|end\\)" "\\|"
 	  ;; Planning and Clock lines.
-	  "^[ \t]*\\(?:"
-	  org-clock-string "\\|"
-	  org-closed-string "\\|"
-	  org-deadline-string "\\|"
-	  org-scheduled-string "\\)")
+	  org-planning-or-clock-line-re)
   "Regexp to separate paragraphs in an Org buffer.")
 
 (defconst org-element-all-elements
@@ -466,28 +461,31 @@ Assume point is at the beginning of the block."
   (let ((case-fold-search t))
     (if (not (save-excursion
 	       (re-search-forward "^[ \t]*#\\+END_CENTER" limit t)))
-	;; Incomplete-block: parse it as a comment.
+	;; Incomplete block: parse it as a comment.
 	(org-element-comment-parser limit)
-      (let ((contents-end (match-beginning 0)))
-	(save-excursion
-	  (let* ((keywords (org-element--collect-affiliated-keywords))
-		 (begin (car keywords))
-		 (contents-begin (progn (forward-line) (point)))
-		 (hidden (org-invisible-p2))
-		 (pos-before-blank (progn (goto-char contents-end)
-					  (forward-line)
-					  (point)))
-		 (end (progn (org-skip-whitespace)
-			     (if (eobp) (point) (point-at-bol)))))
-	    (list 'center-block
-		  (nconc
-		   (list :begin begin
-			 :end end
-			 :hiddenp hidden
-			 :contents-begin contents-begin
-			 :contents-end contents-end
-			 :post-blank (count-lines pos-before-blank end))
-		   (cadr keywords)))))))))
+      (let ((block-end-line (match-beginning 0)))
+	(let* ((keywords (org-element--collect-affiliated-keywords))
+	       (begin (car keywords))
+	       ;; Empty blocks have no contents.
+	       (contents-begin (progn (forward-line)
+				      (and (< (point) block-end-line)
+					   (point))))
+	       (contents-end (and contents-begin block-end-line))
+	       (hidden (org-invisible-p2))
+	       (pos-before-blank (progn (goto-char block-end-line)
+					(forward-line)
+					(point)))
+	       (end (save-excursion (skip-chars-forward " \r\t\n" limit)
+				    (if (eobp) (point) (point-at-bol)))))
+	  (list 'center-block
+		(nconc
+		 (list :begin begin
+		       :end end
+		       :hiddenp hidden
+		       :contents-begin contents-begin
+		       :contents-end contents-end
+		       :post-blank (count-lines pos-before-blank end))
+		 (cadr keywords))))))))
 
 (defun org-element-center-block-interpreter (center-block contents)
   "Interpret CENTER-BLOCK element as Org syntax.
@@ -507,29 +505,38 @@ Return a list whose CAR is `drawer' and CDR is a plist containing
 `:contents-end' and `:post-blank' keywords.
 
 Assume point is at beginning of drawer."
-  (save-excursion
-    (let* ((case-fold-search t)
-	   (name (progn (looking-at org-drawer-regexp)
-			(org-match-string-no-properties 1)))
-	   (keywords (org-element--collect-affiliated-keywords))
-	   (begin (car keywords))
-	   (contents-begin (progn (forward-line) (point)))
-	   (hidden (org-invisible-p2))
-	   (contents-end (progn (re-search-forward "^[ \t]*:END:" limit t)
-				(point-at-bol)))
-	   (pos-before-blank (progn (forward-line) (point)))
-	   (end (progn (org-skip-whitespace)
-		       (if (eobp) (point) (point-at-bol)))))
-      (list 'drawer
-	    (nconc
-	     (list :begin begin
-		   :end end
-		   :drawer-name name
-		   :hiddenp hidden
-		   :contents-begin contents-begin
-		   :contents-end contents-end
-		   :post-blank (count-lines pos-before-blank end))
-	     (cadr keywords))))))
+  (let ((case-fold-search t))
+    (if (not (save-excursion (re-search-forward "^[ \t]*:END:" limit t)))
+	;; Incomplete drawer: parse it as a paragraph.
+	(org-element-paragraph-parser limit)
+      (let ((drawer-end-line (match-beginning 0)))
+	(save-excursion
+	  (let* ((case-fold-search t)
+		 (name (progn (looking-at org-drawer-regexp)
+			      (org-match-string-no-properties 1)))
+		 (keywords (org-element--collect-affiliated-keywords))
+		 (begin (car keywords))
+		 ;; Empty drawers have no contents.
+		 (contents-begin (progn (forward-line)
+					(and (< (point) drawer-end-line)
+					     (point))))
+		 (contents-end (and contents-begin drawer-end-line))
+		 (hidden (org-invisible-p2))
+		 (pos-before-blank (progn (goto-char drawer-end-line)
+					  (forward-line)
+					  (point)))
+		 (end (progn (skip-chars-forward " \r\t\n" limit)
+			     (if (eobp) (point) (point-at-bol)))))
+	    (list 'drawer
+		  (nconc
+		   (list :begin begin
+			 :end end
+			 :drawer-name name
+			 :hiddenp hidden
+			 :contents-begin contents-begin
+			 :contents-end contents-end
+			 :post-blank (count-lines pos-before-blank end))
+		   (cadr keywords)))))))))
 
 (defun org-element-drawer-interpreter (drawer contents)
   "Interpret DRAWER element as Org syntax.
@@ -556,19 +563,23 @@ Assume point is at beginning of dynamic block."
     (if (not (save-excursion (re-search-forward org-dblock-end-re limit t)))
 	;; Incomplete block: parse it as a comment.
 	(org-element-comment-parser limit)
-      (let ((contents-end (match-beginning 0)))
+      (let ((block-end-line (match-beginning 0)))
 	(save-excursion
 	  (let* ((name (progn (looking-at org-dblock-start-re)
 			      (org-match-string-no-properties 1)))
 		 (arguments (org-match-string-no-properties 3))
 		 (keywords (org-element--collect-affiliated-keywords))
 		 (begin (car keywords))
-		 (contents-begin (progn (forward-line) (point)))
+		 ;; Empty blocks have no contents.
+		 (contents-begin (progn (forward-line)
+					(and (< (point) block-end-line)
+					     (point))))
+		 (contents-end (and contents-begin block-end-line))
 		 (hidden (org-invisible-p2))
-		 (pos-before-blank (progn (goto-char contents-end)
+		 (pos-before-blank (progn (goto-char block-end-line)
 					  (forward-line)
 					  (point)))
-		 (end (progn (org-skip-whitespace)
+		 (end (progn (skip-chars-forward " \r\t\n" limit)
 			     (if (eobp) (point) (point-at-bol)))))
 	    (list 'dynamic-block
 		  (nconc
@@ -605,22 +616,25 @@ a plist containing `:label', `:begin' `:end', `:contents-begin',
 
 Assume point is at the beginning of the footnote definition."
   (save-excursion
-    (looking-at org-footnote-definition-re)
-    (let* ((label (org-match-string-no-properties 1))
+    (let* ((label (progn (looking-at org-footnote-definition-re)
+			 (org-match-string-no-properties 1)))
 	   (keywords (org-element--collect-affiliated-keywords))
 	   (begin (car keywords))
+	   (ending (save-excursion
+		     (if (progn
+			   (end-of-line)
+			   (re-search-forward
+			    (concat org-outline-regexp-bol "\\|"
+				    org-footnote-definition-re "\\|"
+				    "^[ \t]*$") limit 'move))
+			 (match-beginning 0)
+		       (point))))
 	   (contents-begin (progn (search-forward "]")
-				  (org-skip-whitespace)
-				  (point)))
-	   (contents-end (if (progn
-			       (end-of-line)
-			       (re-search-forward
-				(concat org-outline-regexp-bol "\\|"
-					org-footnote-definition-re "\\|"
-					"^[ \t]*$") limit 'move))
-			     (match-beginning 0)
-			   (point)))
-	   (end (progn (org-skip-whitespace)
+				  (skip-chars-forward " \r\t\n" ending)
+				  (and (/= (point) ending) (point))))
+	   (contents-end (and contents-begin ending))
+	   (end (progn (goto-char ending)
+		       (skip-chars-forward " \r\t\n" limit)
 		       (if (eobp) (point) (point-at-bol)))))
       (list 'footnote-definition
 	    (nconc
@@ -629,7 +643,7 @@ Assume point is at the beginning of the footnote definition."
 		   :end end
 		   :contents-begin contents-begin
 		   :contents-end contents-end
-		   :post-blank (count-lines contents-end end))
+		   :post-blank (count-lines ending end))
 	     (cadr keywords))))))
 
 (defun org-element-footnote-definition-interpreter (footnote-definition contents)
@@ -679,6 +693,8 @@ Assume point is at beginning of the headline."
 	   (archivedp (member org-archive-tag tags))
 	   (footnote-section-p (and org-footnote-section
 				    (string= org-footnote-section raw-value)))
+	   ;; Normalize property names: ":SOME_PROP:" becomes
+	   ;; ":some-prop".
 	   (standard-props (let (plist)
 			     (mapc
 			      (lambda (p)
@@ -697,15 +713,17 @@ Assume point is at beginning of the headline."
 	   (clock (cdr (assoc "CLOCK" time-props)))
 	   (timestamp (cdr (assoc "TIMESTAMP" time-props)))
 	   (begin (point))
-	   (pos-after-head (save-excursion (forward-line) (point)))
-	   (contents-begin (save-excursion (forward-line)
-					   (org-skip-whitespace)
-					   (if (eobp) (point) (point-at-bol))))
-	   (hidden (save-excursion (forward-line) (org-invisible-p2)))
-	   (end (progn (goto-char (org-end-of-subtree t t))))
-	   (contents-end (progn (skip-chars-backward " \r\t\n")
-				(forward-line)
-				(point))))
+	   (end (save-excursion (goto-char (org-end-of-subtree t t))))
+	   (pos-after-head (progn (forward-line) (point)))
+	   (contents-begin (save-excursion
+			     (skip-chars-forward " \r\t\n" end)
+			     (and (/= (point) end) (line-beginning-position))))
+	   (hidden (org-invisible-p2))
+	   (contents-end (and contents-begin
+			      (progn (goto-char end)
+				     (skip-chars-backward " \r\t\n")
+				     (forward-line)
+				     (point)))))
       ;; Clean RAW-VALUE from any quote or comment string.
       (when (or quotedp commentedp)
 	(setq raw-value
@@ -721,7 +739,9 @@ Assume point is at beginning of the headline."
 		    (list :raw-value raw-value
 			  :begin begin
 			  :end end
-			  :pre-blank (count-lines pos-after-head contents-begin)
+			  :pre-blank
+			  (if (not contents-begin) 0
+			    (count-lines pos-after-head contents-begin))
 			  :hiddenp hidden
 			  :contents-begin contents-begin
 			  :contents-end contents-end
@@ -734,7 +754,12 @@ Assume point is at beginning of the headline."
 			  :deadline deadline
 			  :timestamp timestamp
 			  :clock clock
-			  :post-blank (count-lines contents-end end)
+			  :post-blank (count-lines
+				       (if (not contents-end) pos-after-head
+					 (goto-char contents-end)
+					 (forward-line)
+					 (point))
+				       end)
 			  :footnote-section-p footnote-section-p
 			  :archivedp archivedp
 			  :commentedp commentedp
@@ -822,6 +847,8 @@ Assume point is at beginning of the inline task."
 			   (if (member todo org-done-keywords) 'done 'todo)))
 	   (tags (let ((raw-tags (nth 5 components)))
 		   (and raw-tags (org-split-string raw-tags ":"))))
+	   ;; Normalize property names: ":SOME_PROP:" becomes
+	   ;; ":some-prop".
 	   (standard-props (let (plist)
 			     (mapc
 			      (lambda (p)
@@ -839,22 +866,26 @@ Assume point is at beginning of the inline task."
 	   (deadline (cdr (assoc "DEADLINE" time-props)))
 	   (clock (cdr (assoc "CLOCK" time-props)))
 	   (timestamp (cdr (assoc "TIMESTAMP" time-props)))
-	   (contents-begin (save-excursion (forward-line) (point)))
-	   (hidden (org-invisible-p2))
-	   (pos-before-blank (org-inlinetask-goto-end))
-	   ;; In the case of a single line task, CONTENTS-BEGIN and
-	   ;; CONTENTS-END might overlap.
-	   (contents-end (max contents-begin
-			      (if (not (bolp)) (point-at-bol)
-				(save-excursion (forward-line -1) (point)))))
-	   (end (progn (org-skip-whitespace)
+	   (task-end (save-excursion
+		       (end-of-line)
+		       (and (re-search-forward "^\\*+ END" limit t)
+			    (match-beginning 0))))
+	   (contents-begin (progn (forward-line)
+				  (and task-end (< (point) task-end) (point))))
+	   (hidden (and contents-begin (org-invisible-p2)))
+	   (contents-end (and contents-begin task-end))
+	   (before-blank (if (not task-end) (point)
+			   (goto-char task-end)
+			   (forward-line)
+			   (point)))
+	   (end (progn (skip-chars-forward " \r\t\n" limit)
 		       (if (eobp) (point) (point-at-bol))))
 	   (inlinetask
 	    (list 'inlinetask
 		  (nconc
 		   (list :begin begin
 			 :end end
-			 :hiddenp (and (> contents-end contents-begin) hidden)
+			 :hiddenp hidden
 			 :contents-begin contents-begin
 			 :contents-end contents-end
 			 :level (nth 1 components)
@@ -866,7 +897,7 @@ Assume point is at beginning of the inline task."
 			 :deadline deadline
 			 :timestamp timestamp
 			 :clock clock
-			 :post-blank (count-lines pos-before-blank end))
+			 :post-blank (count-lines before-blank end))
 		   standard-props
 		   (cadr keywords)))))
       (org-element-put-property
@@ -1061,7 +1092,7 @@ Assume point is at the beginning of the list."
       ;; Blank lines below list belong to the top-level list only.
       (unless (= (org-list-get-top-point struct) contents-begin)
 	(setq end (min (org-list-get-bottom-point struct)
-		       (progn (org-skip-whitespace)
+		       (progn (skip-chars-forward " \r\t\n" limit)
 			      (if (eobp) (point) (point-at-bol))))))
       ;; Return value.
       (list 'plain-list
@@ -1098,16 +1129,20 @@ Assume point is at the beginning of the block."
 	       (re-search-forward "^[ \t]*#\\+END_QUOTE" limit t)))
 	;; Incomplete block: parse it as a comment.
 	(org-element-comment-parser limit)
-      (let ((contents-end (match-beginning 0)))
+      (let ((block-end-line (match-beginning 0)))
 	(save-excursion
 	  (let* ((keywords (org-element--collect-affiliated-keywords))
 		 (begin (car keywords))
-		 (contents-begin (progn (forward-line) (point)))
+		 ;; Empty blocks have no contents.
+		 (contents-begin (progn (forward-line)
+					(and (< (point) block-end-line)
+					     (point))))
+		 (contents-end (and contents-begin block-end-line))
 		 (hidden (org-invisible-p2))
-		 (pos-before-blank (progn (goto-char contents-end)
+		 (pos-before-blank (progn (goto-char block-end-line)
 					  (forward-line)
 					  (point)))
-		 (end (progn (org-skip-whitespace)
+		 (end (progn (skip-chars-forward " \r\t\n" limit)
 			     (if (eobp) (point) (point-at-bol)))))
 	    (list 'quote-block
 		  (nconc
@@ -1176,13 +1211,17 @@ Assume point is at the beginning of the block."
 	       (re-search-forward (concat "^[ \t]*#\\+END_" type) limit t)))
 	;; Incomplete block: parse it as a comment.
 	(org-element-comment-parser limit)
-      (let ((contents-end (match-beginning 0)))
+      (let ((block-end-line (match-beginning 0)))
 	(save-excursion
 	  (let* ((keywords (org-element--collect-affiliated-keywords))
 		 (begin (car keywords))
-		 (contents-begin (progn (forward-line) (point)))
+		 ;; Empty blocks have no contents.
+		 (contents-begin (progn (forward-line)
+					(and (< (point) block-end-line)
+					     (point))))
+		 (contents-end (and contents-begin block-end-line))
 		 (hidden (org-invisible-p2))
-		 (pos-before-blank (progn (goto-char contents-end)
+		 (pos-before-blank (progn (goto-char block-end-line)
 					  (forward-line)
 					  (point)))
 		 (end (progn (org-skip-whitespace)
@@ -1236,7 +1275,7 @@ keywords."
 		       (org-babel-lob-get-info)))
 	  (begin (point-at-bol))
 	  (pos-before-blank (progn (forward-line) (point)))
-	  (end (progn (org-skip-whitespace)
+	  (end (progn (skip-chars-forward " \r\t\n" limit)
 		      (if (eobp) (point) (point-at-bol)))))
       (list 'babel-call
 	    (list :begin begin
@@ -1279,7 +1318,7 @@ as keywords."
 		      (org-match-string-no-properties 1)))
 	   (status (if time 'closed 'running))
 	   (post-blank (let ((before-blank (progn (forward-line) (point))))
-			 (org-skip-whitespace)
+			 (skip-chars-forward " \r\t\n" limit)
 			 (unless (eobp) (beginning-of-line))
 			 (count-lines before-blank (point))))
 	   (end (point)))
@@ -1339,7 +1378,7 @@ Assume point is at comment beginning."
 			       (progn (forward-line) (point))))))
 	      (point)))
 	   (end (progn (goto-char com-end)
-		       (org-skip-whitespace)
+		       (skip-chars-forward " \r\t\n" limit)
 		       (if (eobp) (point) (point-at-bol)))))
       (list 'comment
 	    (nconc
@@ -1381,7 +1420,7 @@ Assume point is at comment block beginning."
 		 (pos-before-blank (progn (goto-char contents-end)
 					  (forward-line)
 					  (point)))
-		 (end (progn (org-skip-whitespace)
+		 (end (progn (skip-chars-forward " \r\t\n" limit)
 			     (if (eobp) (point) (point-at-bol))))
 		 (value (buffer-substring-no-properties
 			 contents-begin contents-end)))
@@ -1450,7 +1489,7 @@ containing `:begin', `:end', `:number-lines', `:preserve-indent',
 		 (pos-before-blank (progn (goto-char contents-end)
 					  (forward-line)
 					  (point)))
-		 (end (progn (org-skip-whitespace)
+		 (end (progn (skip-chars-forward " \r\t\n" limit)
 			     (if (eobp) (point) (point-at-bol)))))
 	    (list 'example-block
 		  (nconc
@@ -1505,7 +1544,7 @@ Assume point is at export-block beginning."
 		 (pos-before-blank (progn (goto-char contents-end)
 					  (forward-line)
 					  (point)))
-		 (end (progn (org-skip-whitespace)
+		 (end (progn (skip-chars-forward " \r\t\n" limit)
 			     (if (eobp) (point) (point-at-bol))))
 		 (value (buffer-substring-no-properties contents-begin
 							contents-end)))
@@ -1555,7 +1594,7 @@ Assume point is at the beginning of the fixed-width area."
 			      "\n"))
 		(forward-line))
 	      (point)))
-	   (end (progn (org-skip-whitespace)
+	   (end (progn (skip-chars-forward " \r\t\n" limit)
 		       (if (eobp) (point) (point-at-bol)))))
       (list 'fixed-width
 	    (nconc
@@ -1585,7 +1624,7 @@ containing `:begin', `:end' and `:post-blank' keywords."
     (let* ((keywords (org-element--collect-affiliated-keywords))
 	   (begin (car keywords))
 	   (post-hr (progn (forward-line) (point)))
-	   (end (progn (org-skip-whitespace)
+	   (end (progn (skip-chars-forward " \r\t\n" limit)
 		       (if (eobp) (point) (point-at-bol)))))
       (list 'horizontal-rule
 	    (nconc
@@ -1618,7 +1657,7 @@ keywords."
 	   (value (org-trim (buffer-substring-no-properties
 			     (match-end 0) (point-at-eol))))
 	   (pos-before-blank (progn (forward-line) (point)))
-	   (end (progn (org-skip-whitespace)
+	   (end (progn (skip-chars-forward " \r\t\n" limit)
 		       (if (eobp) (point) (point-at-bol)))))
       (list 'keyword
 	    (list :key key
@@ -1659,7 +1698,7 @@ Assume point is at the beginning of the latex environment."
 		   (forward-line)
 		   (point)))
 	   (value (buffer-substring-no-properties code-begin code-end))
-	   (end (progn (org-skip-whitespace)
+	   (end (progn (skip-chars-forward " \r\t\n" limit)
 		       (if (eobp) (point) (point-at-bol)))))
       (list 'latex-environment
 	    (nconc
@@ -1691,15 +1730,17 @@ Assume point is at the beginning of the paragraph."
     (let* ((contents-begin (point))
 	   (keywords (org-element--collect-affiliated-keywords))
 	   (begin (car keywords))
-	   (contents-end
+	   (before-blank
 	    (progn (end-of-line)
 		   (if (re-search-forward org-element-paragraph-separate
 					  limit
 					  'm)
-		       (progn (forward-line -1) (end-of-line) (point))
+		       (goto-char (match-beginning 0))
 		     (point))))
-	   (pos-before-blank (progn (forward-line) (point)))
-	   (end (progn (org-skip-whitespace)
+	   (contents-end (progn (skip-chars-backward " \r\t\n" contents-begin)
+				(forward-line)
+				(point)))
+	   (end (progn (skip-chars-forward " \r\t\n" limit)
 		       (if (eobp) (point) (point-at-bol)))))
       (list 'paragraph
 	    ;; If paragraph has no affiliated keywords, it may not begin
@@ -1709,7 +1750,7 @@ Assume point is at the beginning of the paragraph."
 		   :end end
 		   :contents-begin contents-begin
 		   :contents-end contents-end
-		   :post-blank (count-lines pos-before-blank end))
+		   :post-blank (count-lines before-blank end))
 	     (cadr keywords))))))
 
 (defun org-element-paragraph-interpreter (paragraph contents)
@@ -1732,7 +1773,7 @@ and `:post-blank' keywords."
     (let* ((case-fold-search nil)
 	   (begin (point))
 	   (post-blank (let ((before-blank (progn (forward-line) (point))))
-			 (org-skip-whitespace)
+			 (skip-chars-forward " \r\t\n" limit)
 			 (unless (eobp) (beginning-of-line))
 			 (count-lines before-blank (point))))
 	   (end (point))
@@ -1803,7 +1844,7 @@ Assume point is at the beginning of the property drawer."
 	  (prop-end (progn (re-search-forward "^[ \t]*:END:" limit t)
 			   (point-at-bol)))
 	  (pos-before-blank (progn (forward-line) (point)))
-	  (end (progn (org-skip-whitespace)
+	  (end (progn (skip-chars-forward " \r\t\n" limit)
 		      (if (eobp) (point) (point-at-bol)))))
       (list 'property-drawer
 	    (list :begin begin
@@ -1918,7 +1959,7 @@ Assume point is at the beginning of the block."
 					  (forward-line)
 					  (point)))
 		 ;; Get position after ending blank lines.
-		 (end (progn (org-skip-whitespace)
+		 (end (progn (skip-chars-forward " \r\t\n" limit)
 			     (if (eobp) (point) (point-at-bol)))))
 	    (list 'src-block
 		  (nconc
@@ -1990,7 +2031,7 @@ Assume point is at the beginning of the table."
 		      (forward-line))
 		    acc))
 	   (pos-before-blank (point))
-	   (end (progn (org-skip-whitespace)
+	   (end (progn (skip-chars-forward " \r\t\n" limit)
 		       (if (eobp) (point) (point-at-bol)))))
       (list 'table
 	    (nconc
@@ -2087,7 +2128,7 @@ Assume point is at beginning of the block."
 		 (pos-before-blank (progn (goto-char contents-end)
 					  (forward-line)
 					  (point)))
-		 (end (progn (org-skip-whitespace)
+		 (end (progn (skip-chars-forward " \r\t\n" limit)
 			     (if (eobp) (point) (point-at-bol)))))
 	    (list 'verse-block
 		  (nconc
@@ -4001,8 +4042,11 @@ indentation is not done with TAB characters."
 
 Return value is a list like (TYPE PROPS) where TYPE is the type
 of the element and PROPS a plist of properties associated to the
-element.  Possible types are defined in
-`org-element-all-elements'.
+element.
+
+Possible types are defined in `org-element-all-elements'.
+Properties depend on element or object type, but always
+include :begin, :end, :parent and :post-blank properties.
 
 As a special case, if point is at the very beginning of a list or
 sub-list, returned element will be that list instead of the first
@@ -4027,10 +4071,12 @@ first element of current section."
      ;; Otherwise move at the beginning of the section containing
      ;; point.
      (let ((origin (point))
-	   (end (save-excursion (outline-next-heading) (point)))
-	   element type special-flag trail struct prevs)
+	   (end (save-excursion
+		  (org-with-limited-levels (outline-next-heading)) (point)))
+	   element type special-flag trail struct prevs parent)
        (org-with-limited-levels
-	(if (org-before-first-heading-p) (goto-char (point-min))
+	(if (org-with-limited-levels (org-before-first-heading-p))
+	    (goto-char (point-min))
 	  (org-back-to-heading)
 	  (forward-line)))
        (org-skip-whitespace)
@@ -4042,11 +4088,16 @@ first element of current section."
            (setq element
 		 (org-element--current-element end 'element special-flag struct)
                  type (car element))
-	   (push element trail)
+	   (org-element-put-property element :parent parent)
+	   (when keep-trail (push element trail))
            (cond
-	    ;; 1. Skip any element ending before point or at point.
+	    ;; 1. Skip any element ending before point or at point
+	    ;;    because the following element has started.  On the
+	    ;;    other hand, if the element ends at point and that
+	    ;;    point is also the end of the buffer, do not skip it.
 	    ((let ((end (org-element-property :end element)))
-	       (when (<= end origin)
+	       (when (or (< end origin)
+			 (and (= end origin) (/= (point-max) end)))
 		 (if (> (point-max) end) (goto-char end)
 		   (throw 'exit (if keep-trail trail element))))))
 	    ;; 2. An element containing point is always the element at
@@ -4055,13 +4106,18 @@ first element of current section."
 	     (throw 'exit (if keep-trail trail element)))
 	    ;; 3. At any other greater element type, if point is
 	    ;;    within contents, move into it.  Otherwise, return
-	    ;;    that element.
+	    ;;    that element.  As a special case, when ORIGIN is
+	    ;;    contents end and is also the end of the buffer, try
+	    ;;    to move inside the greater element to find the end
+	    ;;    of the innermost element.
 	    (t
 	     (let ((cbeg (org-element-property :contents-begin element))
 		   (cend (org-element-property :contents-end element)))
-	       (if (or (not cbeg) (not cend) (> cbeg origin) (<= cend origin)
+	       (if (or (not cbeg) (not cend) (> cbeg origin) (< cend origin)
+		       (and (= cend origin) (/= (point-max) origin))
 		       (and (= cbeg origin) (memq type '(plain-list table))))
 		   (throw 'exit (if keep-trail trail element))
+		 (setq parent element)
 		 (case type
 		   (plain-list
 		    (setq special-flag 'item
@@ -4072,25 +4128,21 @@ first element of current section."
 		 (goto-char cbeg)))))))))))
 
 (defun org-element-context ()
-  "Return list of all elements and objects around point.
+  "Return closest element or object around point.
 
 Return value is a list like (TYPE PROPS) where TYPE is the type
 of the element or object and PROPS a plist of properties
-associated to it.  Possible types are defined in
-`org-element-all-elements' and `org-element-all-objects'.
+associated to it.
 
-All elements and objects returned belong to the current section
-and are ordered from closest to farthest."
+Possible types are defined in `org-element-all-elements' and
+`org-element-all-objects'.  Properties depend on element or
+object type, but always include :begin, :end, :parent
+and :post-blank properties."
   (org-with-wide-buffer
    (let* ((origin (point))
-	  ;; Remove elements not containing point from trail.
-	  (elements (org-remove-if
-		     (lambda (el)
-		       (or (> (org-element-property :begin el) origin)
-			   (< (org-element-property :end el) origin)))
-		     (org-element-at-point 'keep-trail)))
-	  (element (car elements))
-	  (type (car element)) end)
+	  (element (org-element-at-point))
+	  (type (car element))
+	  end)
      ;; Check if point is inside an element containing objects or at
      ;; a secondary string.  In that case, move to beginning of the
      ;; element or secondary string and set END to the other side.
@@ -4111,7 +4163,7 @@ and are ordered from closest to farthest."
 		       (progn (beginning-of-line)
 			      (skip-chars-forward "* ")
 			      (setq end (point-at-eol))))
-		  (and (memq (car element) '(paragraph table-cell verse-block))
+		  (and (memq type '(paragraph table-cell verse-block))
 		       (let ((cbeg (org-element-property
 				    :contents-begin element))
 			     (cend (org-element-property
@@ -4119,8 +4171,10 @@ and are ordered from closest to farthest."
 			 (and (>= origin cbeg)
 			      (<= origin cend)
 			      (progn (goto-char cbeg) (setq end cend)))))))
-	 elements
-       (let ((restriction (org-element-restriction element)) candidates)
+	 element
+       (let ((restriction (org-element-restriction element))
+	     (parent element)
+	     candidates)
 	 (catch 'exit
 	   (while (setq candidates (org-element--get-next-object-candidates
 				    end restriction candidates))
@@ -4128,7 +4182,7 @@ and are ordered from closest to farthest."
 					candidates)))
 	       ;; If ORIGIN is before next object in element, there's
 	       ;; no point in looking further.
-	       (if (> (cdr closest-cand) origin) (throw 'exit elements)
+	       (if (> (cdr closest-cand) origin) (throw 'exit element)
 		 (let* ((object
 			 (progn (goto-char (cdr closest-cand))
 				(funcall (intern (format "org-element-%s-parser"
@@ -4142,13 +4196,14 @@ and are ordered from closest to farthest."
 		    ;; ORIGIN is within a non-recursive object or at an
 		    ;; object boundaries: Return that object.
 		    ((or (not cbeg) (> cbeg origin) (< cend origin))
-		     (throw 'exit (cons object elements)))
+		     (throw 'exit
+			    (org-element-put-property object :parent parent)))
 		    ;; Otherwise, move within current object and restrict
 		    ;; search to the end of its contents.
 		    (t (goto-char cbeg)
-		       (setq end cend)
-		       (push object elements)))))))
-	   elements))))))
+		       (org-element-put-property object :parent parent)
+		       (setq parent object end cend)))))))
+	   parent))))))
 
 
 ;; Once the local structure around point is well understood, it's easy
@@ -4249,23 +4304,20 @@ end of ELEM-A."
   "Move forward by one element.
 Move to the next element at the same level, when possible."
   (interactive)
-  (if (org-with-limited-levels (org-at-heading-p))
-      (let ((origin (point)))
-	(org-forward-same-level 1)
-	(unless (org-with-limited-levels (org-at-heading-p))
-	  (goto-char origin)
-	  (error "Cannot move further down")))
-    (let* ((trail (org-element-at-point 'keep-trail))
-	   (elem (pop trail))
-	   (end (org-element-property :end elem))
-	   (parent (loop for prev in trail
-			 when (>= (org-element-property :end prev) end)
-			 return prev)))
-      (cond
-       ((eobp) (error "Cannot move further down"))
-       ((and parent (= (org-element-property :contents-end parent) end))
-	(goto-char (org-element-property :end parent)))
-       (t (goto-char end))))))
+  (cond ((eobp) (error "Cannot move further down"))
+	((org-with-limited-levels (org-at-heading-p))
+	 (let ((origin (point)))
+	   (org-forward-same-level 1)
+	   (unless (org-with-limited-levels (org-at-heading-p))
+	     (goto-char origin)
+	     (error "Cannot move further down"))))
+	(t
+	 (let* ((elem (org-element-at-point))
+		(end (org-element-property :end elem))
+		(parent (org-element-property :parent elem)))
+	   (if (and parent (= (org-element-property :contents-end parent) end))
+	       (goto-char (org-element-property :end parent))
+	     (goto-char end))))))
 
 (defun org-element-backward ()
   "Move backward by one element.
@@ -4294,18 +4346,13 @@ Move to the previous element at the same level, when possible."
   "Move to upper element."
   (interactive)
   (if (org-with-limited-levels (org-at-heading-p))
-      (unless (org-up-heading-safe)
-	(error "No surrounding element"))
-    (let* ((trail (org-element-at-point 'keep-trail))
-	   (elem (pop trail))
-	   (end (org-element-property :end elem))
-	   (parent (loop for prev in trail
-			 when (>= (org-element-property :end prev) end)
-			 return prev)))
-      (cond
-       (parent (goto-char (org-element-property :begin parent)))
-       ((org-before-first-heading-p) (error "No surrounding element"))
-       (t (org-back-to-heading))))))
+      (unless (org-up-heading-safe) (error "No surrounding element"))
+    (let* ((elem (org-element-at-point))
+	   (parent (org-element-property :parent elem)))
+      (if parent (goto-char (org-element-property :begin parent))
+	(if (org-with-limited-levels (org-before-first-heading-p))
+	    (error "No surrounding element")
+	  (org-with-limited-levels (org-back-to-heading)))))))
 
 (defun org-element-down ()
   "Move to inner element."
@@ -4442,83 +4489,6 @@ modified."
 	      (reverse contents))))))
     (funcall unindent-tree (org-element-contents parse-tree))))
 
-(defun org-element-fill-paragraph (&optional justify)
-  "Fill element at point, when applicable.
-
-This function only applies to paragraph, comment blocks, example
-blocks and fixed-width areas.  Also, as a special case, re-align
-table when point is at one.
-
-If JUSTIFY is non-nil (interactively, with prefix argument),
-justify as well.  If `sentence-end-double-space' is non-nil, then
-period followed by one space does not end a sentence, so don't
-break a line there.  The variable `fill-column' controls the
-width for filling."
-  (let ((element (org-element-at-point)))
-    (case (org-element-type element)
-      ;; Align Org tables, leave table.el tables as-is.
-      (table-row (org-table-align) t)
-      (table
-       (when (eq (org-element-property :type element) 'org) (org-table-align))
-       t)
-      ;; Elements that may contain `line-break' type objects.
-      ((paragraph verse-block)
-       (let ((beg (org-element-property :contents-begin element))
-             (end (org-element-property :contents-end element)))
-         ;; Do nothing if point is at an affiliated keyword or at
-         ;; verse block markers.
-         (if (or (< (point) beg) (>= (point) end)) t
-           ;; At a verse block, first narrow to current "paragraph"
-           ;; and set current element to that paragraph.
-           (save-restriction
-             (when (eq (org-element-type element) 'verse-block)
-               (narrow-to-region beg end)
-               (save-excursion
-                 (end-of-line)
-                 (let ((bol-pos (point-at-bol)))
-                   (re-search-backward org-element-paragraph-separate nil 'move)
-                   (unless (or (bobp) (= (point-at-bol) bol-pos))
-                     (forward-line))
-                   (setq element (org-element-paragraph-parser end)
-                         beg (org-element-property :contents-begin element)
-                         end (org-element-property :contents-end element)))))
-             ;; Fill paragraph, taking line breaks into consideration.
-             ;; For that, slice the paragraph using line breaks as
-             ;; separators, and fill the parts in reverse order to
-             ;; avoid messing with markers.
-             (save-excursion
-               (goto-char end)
-               (mapc
-                (lambda (pos)
-                  (fill-region-as-paragraph pos (point) justify)
-                  (goto-char pos))
-                ;; Find the list of ending positions for line breaks
-                ;; in the current paragraph.  Add paragraph beginning
-                ;; to include first slice.
-                (nreverse
-                 (cons beg
-                       (org-element-map
-                        (org-element--parse-objects
-                         beg end nil org-element-all-objects)
-                        'line-break
-                        (lambda (lb) (org-element-property :end lb)))))))) t)))
-      ;; Elements whose contents should be filled as plain text.
-      ((comment-block example-block)
-       (save-restriction
-         (narrow-to-region
-          (save-excursion
-            (goto-char (org-element-property :begin element))
-            (while (looking-at org-element--affiliated-re) (forward-line))
-	    (forward-line)
-            (point))
-          (save-excursion
-	    (goto-char (org-element-property :end element))
-	    (if (bolp) (forward-line -1) (beginning-of-line))
-	    (point)))
-         (fill-paragraph justify) t))
-      ;; Ignore every other element.
-      (otherwise t))))
-
 
 (provide 'org-element)
 ;;; org-element.el ends here

+ 5 - 2
lisp/org-exp-blocks.el

@@ -72,9 +72,13 @@
 
 (eval-when-compile
   (require 'cl))
-(require 'org)
 (require 'find-func)
 
+(declare-function org-split-string "org" (string &optional separators))
+(declare-function org-remove-indentation "org" (code &optional n))
+
+(defvar org-protecting-blocks nil) ; From org.el
+
 (defun org-export-blocks-set (var value)
   "Set the value of `org-export-blocks' and install fontification."
   (set var value)
@@ -142,7 +146,6 @@ export function should accept three arguments."
 (defun org-export-blocks-html-quote (body &optional open close)
   "Protect BODY from org html export.
 The optional OPEN and CLOSE tags will be inserted around BODY."
-
   (concat
    "\n#+BEGIN_HTML\n"
    (or open "")

+ 2 - 3
lisp/org-exp.el

@@ -2579,7 +2579,7 @@ in the list) and remove property and value from the list in LISTVAR."
 (defvar org-export-latex-minted-options) ;; defined in org-latex.el
 
 (defun org-remove-formatting-on-newlines-in-region (beg end)
-  "Remove formatting on newline characters"
+  "Remove formatting on newline characters."
   (interactive "r")
   (save-excursion
     (goto-char beg)
@@ -3233,8 +3233,7 @@ Does include HTML export options as well as TODO and CATEGORY stuff."
 		  (or org-tag-alist (org-get-buffer-tags)) " ") "")
    (mapconcat 'identity org-file-tags " ")
    org-archive-location
-   "org file:~/org/%s.org"
-   ))
+   "org file:~/org/%s.org"))
 
 ;;;###autoload
 (defun org-insert-export-options-template ()

+ 4 - 4
lisp/org-faces.el

@@ -419,7 +419,7 @@ determines if it is a foreground or a background color."
 (defface org-checkbox
   (org-compatible-face 'bold
     '((t (:bold t))))
-  "Face for checkboxes"
+  "Face for checkboxes."
   :group 'org-faces)
 
 
@@ -491,9 +491,9 @@ changes."
   :version "22.1")
 
 (defface org-document-title
-  '((((class color) (background light)) (:foreground "midnight blue" :weight bold :height 1.44))
-    (((class color) (background dark)) (:foreground "pale turquoise" :weight bold :height 1.44))
-    (t (:weight bold :height 1.44)))
+  '((((class color) (background light)) (:foreground "midnight blue" :weight bold))
+    (((class color) (background dark)) (:foreground "pale turquoise" :weight bold))
+    (t (:weight bold)))
   "Face for document title, i.e. that which follows the #+TITLE: keyword."
   :group 'org-faces)
 

+ 4 - 8
lisp/org-freemind.el

@@ -455,8 +455,7 @@ DRAWERS-REGEXP are converted to freemind notes."
                         note-res
                         "</body>\n"
                         "</html>\n"
-                        "</richcontent>\n"))
-        )
+                        "</richcontent>\n")))
 
       ;; There is always an LF char:
       (when (> (length text) 1)
@@ -1085,11 +1084,9 @@ PATH should be a list of steps, where each step has the form
           ;;(a (setq is-link t) )
           ((h1 h2 h3 h4 h5 h6 p)
            ;;(setq ntxt (concat "\n" ntxt))
-           (setq lf-after 2)
-           )
+           (setq lf-after 2))
           (br
-           (setq lf-after 1)
-           )
+           (setq lf-after 1))
           (t
            (cond
             ((stringp n)
@@ -1106,8 +1103,7 @@ PATH should be a list of steps, where each step has the form
                  (let ((att (car att-val))
                        (val (cdr att-val)))
                    (when (eq att 'href)
-                     (setq link val)))))
-             )))))
+                     (setq link val))))))))))
       (if lf-after
           (setq ntxt (concat ntxt (make-string lf-after ?\n)))
         (setq ntxt (concat ntxt " ")))

+ 1 - 1
lisp/org-mac-message.el

@@ -47,7 +47,7 @@
 (require 'org)
 
 (defgroup org-mac-flagged-mail nil
-  "Options concerning linking to flagged Mail.app messages"
+  "Options concerning linking to flagged Mail.app messages."
   :tag "Org Mail.app"
   :group 'org-link)
 

+ 2 - 2
lisp/org-macs.el

@@ -376,7 +376,7 @@ point nowhere."
   `(let* ((org-called-with-limited-levels t)
 	  (org-outline-regexp (org-get-limited-outline-regexp))
 	  (outline-regexp org-outline-regexp)
-	  (org-outline-regexp-at-bol (concat "^" org-outline-regexp)))
+	  (org-outline-regexp-bol (concat "^" org-outline-regexp)))
      ,@body))
 (def-edebug-spec org-with-limited-levels (body))
 
@@ -393,7 +393,7 @@ The number of levels is controlled by `org-inlinetask-min-level'"
       (format "\\*\\{1,%d\\} " nstars))))
 
 (defun org-format-seconds (string seconds)
-  "Compatibility function replacing format-seconds"
+  "Compatibility function replacing format-seconds."
   (if (fboundp 'format-seconds)
       (format-seconds string seconds)
     (format-time-string string (seconds-to-time seconds))))

+ 1 - 1
lisp/org-mobile.el

@@ -236,7 +236,7 @@ by the mobile device, this hook should be used to copy the capture file
 directory `org-mobile-directory'.")
 
 (defvar org-mobile-post-pull-hook nil
-  "Hook run after running `org-mobile-pull'.
+  "Hook run after running `org-mobile-pull', only if new items were found.
 If Emacs does not have direct write access to the WebDAV directory used
 by the mobile device, this hook should be used to copy the emptied
 capture file `mobileorg.org' back to the WebDAV directory, for example

+ 2 - 2
lisp/org-pcomplete.el

@@ -175,7 +175,7 @@ When completing for #+STARTUP, for example, this function returns
 	    opts))))
 
 (defun pcomplete/org-mode/file-option/bind ()
-  "Complete arguments for the #+BIND file option, which are variable names"
+  "Complete arguments for the #+BIND file option, which are variable names."
   (let (vars)
     (mapatoms
      (lambda (a) (if (boundp a) (setq vars (cons (symbol-name a) vars)))))
@@ -288,7 +288,7 @@ Complete a language in the first field, the header arguments and switches."
 	    ":session" ":shebang" ":tangle" ":var"))))
 
 (defun pcomplete/org-mode/block-option/clocktable ()
-  "Complete keywords in a clocktable line"
+  "Complete keywords in a clocktable line."
   (while (pcomplete-here '(":maxlevel" ":scope"
 			   ":tstart" ":tend" ":block" ":step"
 			   ":stepskip0" ":fileskip0"

+ 2 - 0
lisp/org-timer.el

@@ -130,6 +130,7 @@ the region 0:00:00."
 	       (org-timer-secs-to-hms (or delta 0)))
       (run-hooks 'org-timer-start-hook))))
 
+;;;###autoload
 (defun org-timer-pause-or-continue (&optional stop)
   "Pause or continue the relative timer.
 With prefix arg STOP, stop it entirely."
@@ -156,6 +157,7 @@ With prefix arg STOP, stop it entirely."
     (org-timer-set-mode-line 'pause)
     (message "Timer paused at %s" (org-timer-value-string)))))
 
+;;;###autoload
 (defun org-timer-stop ()
   "Stop the relative timer."
   (interactive)

+ 1 - 1
lisp/org-vm.el

@@ -139,7 +139,7 @@
       (org-vm-select-message (org-add-angle-brackets article)))))
 
 (defun org-vm-imap-open (path)
-  "Follow a VM link to an IMAP folder"
+  "Follow a VM link to an IMAP folder."
   (require 'vm-imap)
   (when (string-match "\\([^:]+\\):\\([^#]+\\)#?\\(.+\\)?" path)
     (let* ((account-name (match-string 1 path))

Diff do ficheiro suprimidas por serem muito extensas
+ 388 - 290
lisp/org.el


+ 54 - 58
testing/lisp/test-org-element.el

@@ -1119,6 +1119,24 @@ e^{i\\pi}+1=0
      (org-element-map (org-element-parse-buffer) 'macro 'identity))))
 
 
+;;;; Paragraph
+
+(ert-deftest test-org-element/paragraph-parser ()
+  "Test `paragraph' parser."
+  ;; Standard test.
+  (should
+   (org-test-with-temp-text "Paragraph"
+     (org-element-map (org-element-parse-buffer) 'paragraph 'identity nil t)))
+  ;; Property find end of a paragraph stuck to another element.
+  (should
+   (eq ?#
+       (org-test-with-temp-text "Paragraph\n# Comment"
+	 (org-element-map
+	  (org-element-parse-buffer) 'paragraph
+	  (lambda (p) (char-after (org-element-property :end p)))
+	  nil t)))))
+
+
 ;;;; Plain List
 
 (ert-deftest test-org-element/plain-list-parser ()
@@ -2207,6 +2225,19 @@ Paragraph \\alpha."
 
 (ert-deftest test-org-element/at-point ()
   "Test `org-element-at-point' specifications."
+  ;; Return closest element containing point.
+  (should
+   (eq 'paragraph
+       (org-test-with-temp-text "#+BEGIN_CENTER\nA\n#+END_CENTER"
+	 (progn (search-forward "A")
+		(org-element-type (org-element-at-point))))))
+  ;; Correctly set `:parent' property.
+  (should
+   (eq 'center-block
+       (org-test-with-temp-text "#+BEGIN_CENTER\nA\n#+END_CENTER"
+	 (progn (search-forward "A")
+		(org-element-type
+		 (org-element-property :parent (org-element-at-point)))))))
   ;; Special case: at the very beginning of a table, return `table'
   ;; object instead of `table-row'.
   (should
@@ -2218,26 +2249,35 @@ Paragraph \\alpha."
   (should
    (eq 'plain-list
        (org-test-with-temp-text "- item"
-	 (org-element-type (org-element-at-point))))))
+	 (org-element-type (org-element-at-point)))))
+  ;; With an optional argument, return trail.
+  (should
+   (equal '(paragraph center-block)
+	  (org-test-with-temp-text "#+BEGIN_CENTER\nA\n#+END_CENTER\nZ"
+	    (progn (search-forward "Z")
+		   (mapcar 'org-element-type (org-element-at-point t)))))))
 
 (ert-deftest test-org-element/context ()
   "Test `org-element-context' specifications."
-  ;; List all objects and elements containing point.
+  ;; Return closest object containing point.
   (should
-   (equal
-    '(subscript bold paragraph)
-    (mapcar 'car
-	    (org-test-with-temp-text "Some *text with _underline_*"
-	      (progn (search-forward "under")
-		     (org-element-context))))))
+   (eq 'underline
+       (org-test-with-temp-text "Some *text with _underline_ text*"
+	 (progn (search-forward "under")
+		(org-element-type (org-element-context))))))
   ;; Find objects in secondary strings.
   (should
-   (equal
-    '(underline headline)
-    (mapcar 'car
-	    (org-test-with-temp-text "* Headline _with_ underlining"
-	      (progn (search-forward "w")
-		     (org-element-context)))))))
+   (eq 'underline
+       (org-test-with-temp-text "* Headline _with_ underlining"
+	 (progn (search-forward "w")
+		(org-element-type (org-element-context))))))
+  ;; Correctly set `:parent' property.
+  (should
+   (eq 'paragraph
+       (org-test-with-temp-text "Some *bold* text"
+	 (progn (search-forward "bold")
+		(org-element-type
+		 (org-element-property :parent (org-element-context))))))))
 
 (ert-deftest test-org-element/forward ()
   "Test `org-element-forward' specifications."
@@ -2549,50 +2589,6 @@ Text.
       (mapcar (lambda (ov) (cons (overlay-start ov) (overlay-end ov)))
 	      (overlays-in (point-min) (point-max)))))))
 
-(ert-deftest test-org-element/fill-paragraph ()
-  "Test `org-element-fill-paragraph' specifications."
-  ;; At an Org table, align it.
-  (org-test-with-temp-text "|a|"
-    (org-element-fill-paragraph)
-    (should (equal (buffer-string) "| a |\n")))
-  ;; At a paragraph, preserve line breaks.
-  (org-test-with-temp-text "some \\\\\nlong\ntext"
-    (let ((fill-column 20))
-      (org-element-fill-paragraph)
-      (should (equal (buffer-string) "some \\\\\nlong text"))))
-  ;; At a verse block, fill paragraph at point, also preserving line
-  ;; breaks.  Though, do nothing when point is at the block
-  ;; boundaries.
-  (org-test-with-temp-text "#+BEGIN_VERSE\nSome \\\\\nlong\ntext\n#+END_VERSE"
-    (forward-line)
-    (let ((fill-column 20))
-      (org-element-fill-paragraph)
-      (should (equal (buffer-string)
-		     "#+BEGIN_VERSE\nSome \\\\\nlong text\n#+END_VERSE"))))
-  (org-test-with-temp-text "#+BEGIN_VERSE\nSome \\\\\nlong\ntext\n#+END_VERSE"
-    (let ((fill-column 20))
-      (org-element-fill-paragraph)
-      (should (equal (buffer-string)
-		     "#+BEGIN_VERSE\nSome \\\\\nlong\ntext\n#+END_VERSE"))))
-  ;; Fill contents of `comment-block' and `example-block' elements.
-  (org-test-with-temp-text "#+BEGIN_COMMENT\nSome\ntext\n#+END_COMMENT"
-    (let ((fill-column 20))
-      (forward-line)
-      (org-element-fill-paragraph)
-      (should (equal (buffer-string)
-		     "#+BEGIN_COMMENT\nSome text\n#+END_COMMENT"))))
-  (org-test-with-temp-text "#+BEGIN_EXAMPLE\nSome\ntext\n#+END_EXAMPLE"
-    (let ((fill-column 20))
-      (forward-line)
-      (org-element-fill-paragraph)
-      (should (equal (buffer-string)
-		     "#+BEGIN_EXAMPLE\nSome text\n#+END_EXAMPLE"))))
-  ;; Do nothing at affiliated keywords.
-  (org-test-with-temp-text "#+NAME: para\nSome\ntext."
-    (let ((fill-column 20))
-      (org-element-fill-paragraph)
-      (should (equal (buffer-string) "#+NAME: para\nSome\ntext.")))))
-
 
 (provide 'test-org-element)
 ;;; test-org-element.el ends here

+ 51 - 15
testing/lisp/test-org-export.el

@@ -444,11 +444,11 @@ body\n")))
   (let ((org-footnote-section nil)
 	(org-export-with-footnotes t))
     ;; 1. Read every type of footnote.
-    (org-test-with-parsed-data
-	"Text[fn:1] [1] [fn:label:C] [fn::D]\n\n[fn:1] A\n\n[1] B"
-      (should
-       (equal
-	'((1 . "A") (2 . "B") (3 . "C") (4 . "D"))
+    (should
+     (equal
+      '((1 . "A\n") (2 . "B") (3 . "C") (4 . "D"))
+      (org-test-with-parsed-data
+	  "Text[fn:1] [1] [fn:label:C] [fn::D]\n\n[fn:1] A\n\n[1] B"
 	(org-element-map
 	 tree 'footnote-reference
 	 (lambda (ref)
@@ -634,23 +634,47 @@ Paragraph[fn:1]"
 
 (ert-deftest test-org-export/first-sibling-p ()
   "Test `org-export-first-sibling-p' specifications."
+  ;; Standard test.
   (should
    (equal
     '(yes yes no)
-    (org-test-with-temp-text "* Headline\n** Headline 2\n** Headline 3"
+    (org-test-with-parsed-data "* Headline\n** Headline 2\n** Headline 3"
       (org-element-map
-       (org-element-parse-buffer) 'headline
-       (lambda (h) (if (org-export-first-sibling-p h) 'yes 'no)))))))
+       tree 'headline
+       (lambda (h) (if (org-export-first-sibling-p h info) 'yes 'no))
+       info))))
+  ;; Ignore headlines not exported.
+  (should
+   (equal
+    '(yes)
+    (let ((org-export-exclude-tags '("ignore")))
+      (org-test-with-parsed-data "* Headline :ignore:\n* Headline 2"
+	(org-element-map
+	 tree 'headline
+	 (lambda (h) (if (org-export-first-sibling-p h info) 'yes 'no))
+	 info))))))
 
 (ert-deftest test-org-export/last-sibling-p ()
   "Test `org-export-last-sibling-p' specifications."
+  ;; Standard test.
   (should
    (equal
     '(yes no yes)
-    (org-test-with-temp-text "* Headline\n** Headline 2\n** Headline 3"
+    (org-test-with-parsed-data "* Headline\n** Headline 2\n** Headline 3"
       (org-element-map
-       (org-element-parse-buffer) 'headline
-       (lambda (h) (if (org-export-last-sibling-p h) 'yes 'no)))))))
+       tree 'headline
+       (lambda (h) (if (org-export-last-sibling-p h info) 'yes 'no))
+       info))))
+  ;; Ignore headlines not exported.
+  (should
+   (equal
+    '(yes)
+    (let ((org-export-exclude-tags '("ignore")))
+      (org-test-with-parsed-data "* Headline\n* Headline 2 :ignore:"
+	(org-element-map
+	 tree 'headline
+	 (lambda (h) (if (org-export-last-sibling-p h info) 'yes 'no))
+	 info))))))
 
 
 
@@ -1595,12 +1619,18 @@ Another text. (ref:text)
    (equal "b"
 	  (org-test-with-parsed-data "* Headline\n*a* b"
 	    (org-export-get-next-element
-	     (org-element-map tree 'bold 'identity info t)))))
+	     (org-element-map tree 'bold 'identity info t) info))))
   ;; Return nil when no previous element.
   (should-not
    (org-test-with-parsed-data "* Headline\na *b*"
      (org-export-get-next-element
-      (org-element-map tree 'bold 'identity info t)))))
+      (org-element-map tree 'bold 'identity info t) info)))
+  ;; Non-exportable elements are ignored.
+  (should-not
+   (let ((org-export-with-timestamps nil))
+     (org-test-with-parsed-data "\alpha <2012-03-29 Thu>"
+       (org-export-get-next-element
+	(org-element-map tree 'entity 'identity info t) info)))))
 
 (ert-deftest test-org-export/get-previous-element ()
   "Test `org-export-get-previous-element' specifications."
@@ -1609,12 +1639,18 @@ Another text. (ref:text)
    (equal "a "
 	  (org-test-with-parsed-data "* Headline\na *b*"
 	    (org-export-get-previous-element
-	     (org-element-map tree 'bold 'identity info t)))))
+	     (org-element-map tree 'bold 'identity info t) info))))
   ;; Return nil when no previous element.
   (should-not
    (org-test-with-parsed-data "* Headline\n*a* b"
      (org-export-get-previous-element
-      (org-element-map tree 'bold 'identity info t)))))
+      (org-element-map tree 'bold 'identity info t) info)))
+  ;; Non-exportable elements are ignored.
+  (should-not
+   (let ((org-export-with-timestamps nil))
+     (org-test-with-parsed-data "<2012-03-29 Thu> \alpha"
+       (org-export-get-previous-element
+	(org-element-map tree 'entity 'identity info t) info)))))
 
 
 (provide 'test-org-export)

+ 133 - 1
testing/lisp/test-org.el

@@ -98,7 +98,7 @@ http://article.gmane.org/gmane.emacs.orgmode/21459/"
 ;; a target keyword (aka an invisible target: #+TARGET: text), to
 ;; a named element (#+name: text) and to headlines (* Text).
 
-(ert-deftest test-org-export/fuzzy-links ()
+(ert-deftest test-org/fuzzy-links ()
   "Test fuzzy links specifications."
   ;; 1. Fuzzy link goes in priority to a matching target.
   (org-test-with-temp-text
@@ -129,6 +129,138 @@ http://article.gmane.org/gmane.emacs.orgmode/21459/"
     (should (looking-at "\\* Test"))))
 
 
+
+;;; Filling
+
+(ert-deftest test-org/fill-paragraph ()
+  "Test `org-fill-paragraph' specifications."
+  ;; At an Org table, align it.
+  (org-test-with-temp-text "|a|"
+    (org-fill-paragraph)
+    (should (equal (buffer-string) "| a |\n")))
+  ;; At a paragraph, preserve line breaks.
+  (org-test-with-temp-text "some \\\\\nlong\ntext"
+    (let ((fill-column 20))
+      (org-fill-paragraph)
+      (should (equal (buffer-string) "some \\\\\nlong text"))))
+  ;; At a verse block, fill paragraph at point, also preserving line
+  ;; breaks.  Though, do nothing when point is at the block
+  ;; boundaries.
+  (org-test-with-temp-text "#+BEGIN_VERSE\nSome \\\\\nlong\ntext\n#+END_VERSE"
+    (forward-line)
+    (let ((fill-column 20))
+      (org-fill-paragraph)
+      (should (equal (buffer-string)
+		     "#+BEGIN_VERSE\nSome \\\\\nlong text\n#+END_VERSE"))))
+  (org-test-with-temp-text "#+BEGIN_VERSE\nSome \\\\\nlong\ntext\n#+END_VERSE"
+    (let ((fill-column 20))
+      (org-fill-paragraph)
+      (should (equal (buffer-string)
+		     "#+BEGIN_VERSE\nSome \\\\\nlong\ntext\n#+END_VERSE"))))
+  ;; Fill contents of `comment-block' elements.
+  (should
+   (equal
+    (org-test-with-temp-text "#+BEGIN_COMMENT\nSome\ntext\n#+END_COMMENT"
+      (let ((fill-column 20))
+	(forward-line)
+	(org-fill-paragraph)
+	(buffer-string)))
+    "#+BEGIN_COMMENT\nSome text\n#+END_COMMENT"))
+  ;; Fill `comment' elements, indented or not.
+  (should
+   (equal "# A B"
+	  (org-test-with-temp-text "# A\n#B"
+	    (let ((fill-column 20))
+	      (org-fill-paragraph)
+	      (buffer-string)))))
+  (should
+   (equal "  #+ A B"
+	  (org-test-with-temp-text "  #+ A\n  #+ B"
+	    (let ((fill-column 20))
+	      (org-fill-paragraph)
+	      (buffer-string)))))
+  ;; Do nothing at affiliated keywords.
+  (org-test-with-temp-text "#+NAME: para\nSome\ntext."
+    (let ((fill-column 20))
+      (org-fill-paragraph)
+      (should (equal (buffer-string) "#+NAME: para\nSome\ntext.")))))
+
+(ert-deftest test-org/auto-fill-function ()
+  "Test auto-filling features."
+  ;; Auto fill paragraph.
+  (should
+   (equal "12345\n7890"
+	  (org-test-with-temp-text "12345 7890"
+	    (let ((fill-column 5))
+	      (end-of-line)
+	      (org-auto-fill-function)
+	      (buffer-string)))))
+  ;; Auto fill first paragraph in an item.
+  (should
+   (equal "- 12345\n  7890"
+	  (org-test-with-temp-text "- 12345 7890"
+	    (let ((fill-column 7))
+	      (end-of-line)
+	      (org-auto-fill-function)
+	      (buffer-string)))))
+  ;; Auto fill comments, indented or not.
+  (should
+   (equal "# 12345\n# 7890"
+	  (org-test-with-temp-text "# 12345 7890"
+	    (let ((fill-column 7))
+	      (end-of-line)
+	      (org-auto-fill-function)
+	      (buffer-string)))))
+  (should
+   (equal "  #+ 12345\n  #+ 7890"
+	  (org-test-with-temp-text "  #+ 12345 7890"
+	    (let ((fill-column 10))
+	      (end-of-line)
+	      (org-auto-fill-function)
+	      (buffer-string)))))
+  ;; Verse and comment block: auto fill contents.
+  (should
+   (equal "#+BEGIN_VERSE\n12345\n7890\n#+END_VERSE"
+	  (org-test-with-temp-text "#+BEGIN_VERSE\n12345 7890\n#+END_VERSE"
+	    (let ((fill-column 5))
+	      (forward-line)
+	      (end-of-line)
+	      (org-auto-fill-function)
+	      (buffer-string)))))
+  (should
+   (equal "#+BEGIN_COMMENT\n12345\n7890\n#+END_COMMENT"
+	  (org-test-with-temp-text "#+BEGIN_COMMENT\n12345 7890\n#+END_COMMENT"
+	    (let ((fill-column 5))
+	      (forward-line)
+	      (end-of-line)
+	      (org-auto-fill-function)
+	      (buffer-string)))))
+  ;; Do not fill if a new item could be created.
+  (should-not
+   (equal "12345\n- 90"
+	  (org-test-with-temp-text "12345 - 90"
+	    (let ((fill-column 5))
+	      (end-of-line)
+	      (org-auto-fill-function)
+	      (buffer-string)))))
+  ;; Do not fill if a line break could be introduced.
+  (should-not
+   (equal "123\\\\\n7890"
+	  (org-test-with-temp-text "123\\\\ 7890"
+	    (let ((fill-column 6))
+	      (end-of-line)
+	      (org-auto-fill-function)
+	      (buffer-string)))))
+  ;; Do not fill affiliated keywords.
+  (should-not
+   (equal "#+ATTR_LATEX: ABC\nDEFGHIJKL"
+	  (org-test-with-temp-text "#+ATTR_LATEX: ABC DEFGHIJKL"
+	    (let ((fill-column 20))
+	      (end-of-line)
+	      (org-auto-fill-function)
+	      (buffer-string))))))
+
+
 (provide 'test-org)
 
 ;;; test-org.el ends here

Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff