浏览代码

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

Carsten Dominik 14 年之前
父节点
当前提交
82ac473f43

+ 6 - 15
contrib/lisp/org-exp-bibtex.el

@@ -2,7 +2,7 @@
 
 ;; Copyright (C) 2009 Taru Karttunen
 
-;; Author: Taru Karttunen <taruti@taruti.net >
+;; Author: Taru Karttunen <taruti@taruti.net>
 
 ;; This file is not currently part of GNU Emacs.
 
@@ -72,13 +72,12 @@
 	    (opt   (org-exp-bibtex-options-to-plist (match-string 3))))
 	(replace-match
 	(cond
-	 (htmlp ;; We are exporting to HTML
+	 ((eq backend 'html) ;; We are exporting to HTML
 	  (let (extra-args cite-list end-hook tmp-files)
 	    (dolist (elt opt)
 	      (when (equal "option" (car elt))
 		(setq extra-args (cons (cdr elt) extra-args))))
 
-
 	    (when (assoc "limit" opt) ;; Limit is true - collect references
 	      (org-exp-bibtex-docites (lambda ()
 					(dolist (c (org-split-string (match-string 1) ","))
@@ -107,13 +106,12 @@
 	      (while (re-search-forward "<hr>" nil t)
 		(replace-match "<hr/>" t t))
 	      (concat "\n#+BEGIN_HTML\n<div id=\"bibliography\">\n" (buffer-string) "\n</div>\n#+END_HTML\n"))))
-	 (latexp ;; Latex export
+	 ((eq backend 'latex) ;; Latex export
 	  (concat "\n#+LATEX: \\bibliographystyle{" style "}"
 		  "\n#+LATEX: \\bibliography{" file "}\n"))) t t)))
-    
 
     ;; Convert cites to links in html
-    (when htmlp
+    (when (eq backend 'html)
       ;; Split citation commands with multiple keys
       (org-exp-bibtex-docites
        (lambda ()
@@ -126,28 +124,21 @@
        (lambda () (let* ((cn (match-string 1))
 			 (cv (assoc cn oebp-cite-plist)))
 ;;		    (message "L: %s" (concat "\[_{}[[" cn "][" (if cv (cdr cv) cn) "]]\]"))
-		    (replace-match (concat "\[_{}[[#" cn "][" (if cv (cdr cv) cn) "]]\]")) t t))))
-
-
-))
+		    (replace-match (concat "\[_{}[[#" cn "][" (if cv (cdr cv) cn) "]]\]")) t t))))))
 
 (defun org-exp-bibtex-docites (fun)
   (save-excursion
     (save-match-data
       (goto-char (point-min))
-      (when htmlp
+      (when (eq backend 'html)
 	(while (re-search-forward "\\\\cite{\\([^}\n]+\\)}" nil t)
 	  (apply fun nil))))))
 
-
 (defun org-exp-bibtex-options-to-plist (options)
   (save-match-data
     (flet ((f (o) (let ((s (split-string o ":"))) (cons (nth 0 s) (nth 1 s)))))
       (mapcar 'f (split-string options nil t)))))
 
-
-
-
 (add-hook 'org-export-preprocess-hook 'org-export-bibtex-preprocess)
 
 (provide 'org-exp-bibtex)

+ 30 - 22
doc/org.texi

@@ -1493,38 +1493,41 @@ visually indistinguishable from true headlines.  In short: even though
 as bullets.
 @item
 @vindex org-plain-list-ordered-item-terminator
+@vindex org-alphabetical-lists
 @emph{Ordered} list items start with a numeral followed by either a period or
 a right parenthesis@footnote{You can filter out any of them by configuring
 @code{org-plain-list-ordered-item-terminator}.}, such as @samp{1.} or
-@samp{1)}.  If you want a list to start with a different value (e.g.@: 20), start
-the text of the item with @code{[@@20]}@footnote{If there's a checkbox in the
-item, the cookie must be put @emph{before} the checkbox.}.  Those constructs
-can be used in any item of the list in order to enforce a particular
-numbering.
+@samp{1)}@footnote{You can also get @samp{a.}, @samp{A.}, @samp{a)} and
+@samp{A)} by configuring @code{org-alphabetical-lists}.  To minimize
+confusion with normal text, those are limited to one character only.  Beyond
+that limit, bullets will automatically fallback to numbers.}.  If you want a
+list to start with a different value (e.g.@: 20), start the text of the item
+with @code{[@@20]}@footnote{If there's a checkbox in the item, the cookie
+must be put @emph{before} the checkbox.  If you have activated alphabetical
+lists, you can also use counters like @code{[@@b]}.}.  Those constructs can
+be used in any item of the list in order to enforce a particular numbering.
 @item
 @emph{Description} list items are unordered list items, and contain the
-separator @samp{ :: } to separate the description @emph{term} from the
+separator @samp{ :: } to distinguish the description @emph{term} from the
 description.
 @end itemize
 
 Items belonging to the same list must have the same indentation on the first
 line.  In particular, if an ordered list reaches number @samp{10.}, then the
 2--digit numbers must be written left-aligned with the other numbers in the
-list.
+list.  An item ends before the next line that is less or equally indented
+than the bullet/number.
 
 @vindex org-list-ending-method
 @vindex org-list-end-regexp
 @vindex org-empty-line-terminates-plain-lists
 Two methods@footnote{To disable either of them, configure
 @code{org-list-ending-method}.} are provided to terminate lists.  A list ends
-before the next line that is indented like the bullet/number or less, or it
-ends before two blank lines@footnote{See also
-@code{org-empty-line-terminates-plain-lists}.}.  In both cases, all levels of
-the list are closed@footnote{So you cannot have a sublist, some text and then
-another sublist while still in the same top-level list item.  This used to be
-possible, but it was only supported in the HTML exporter and difficult to
-manage with automatic indentation.}.  For finer control, you can end lists
-with any pattern set in @code{org-list-end-regexp}.  Here is an example:
+whenever every item has ended, which means before any line less or equally
+indented than items at top level.  It also ends before two blank
+lines@footnote{See also @code{org-empty-line-terminates-plain-lists}.}.  In
+that case, all items are closed.  For finer control, you can end lists with
+any pattern set in @code{org-list-end-regexp}.  Here is an example:
 
 @example
 @group
@@ -1535,8 +1538,8 @@ with any pattern set in @code{org-list-end-regexp}.  Here is an example:
       + this was already my favorite scene in the book
       + I really like Miranda Otto.
    3. Peter Jackson being shot by Legolas
-      He makes a really funny face when it happens.
       - on DVD only
+      He makes a really funny face when it happens.
    But in the end, no individual scenes matter but the film as a whole.
    Important actors in this film are:
    - @b{Elijah Wood} :: He plays Frodo
@@ -1651,14 +1654,20 @@ depending on @code{org-plain-list-ordered-item-terminator}, the type of list,
 and its position@footnote{See @code{bullet} rule in
 @code{org-list-automatic-rules} for more information.}.  With a numeric
 prefix argument N, select the Nth bullet from this list.  If there is an
-active region when calling this, all lines will be converted to list items.
-If the first line already was a list item, any item markers will be removed
-from the list.  Finally, even without an active region, a normal line will be
+active region when calling this, selected text will be changed into an item.
+With a prefix argument, all lines will be converted to list items.  If the
+first line already was a list item, any item markers will be removed from the
+list.  Finally, even without an active region, a normal line will be
 converted into a list item.
 @kindex C-c *
 @item C-c *
 Turn a plain list item into a headline (so that it becomes a subheading at
 its location). @xref{Structure editing}, for a detailed explanation.
+@kindex C-c C-*
+@item C-c C-*
+Turn the whole plain list into a subtree of the current heading.  Checkboxes
+(@pxref{Checkboxes}) will become TODO (resp. DONE) keywords when unchecked
+(resp. checked).
 @kindex S-@key{left}
 @kindex S-@key{right}
 @item S-@key{left}/@key{right}
@@ -4282,9 +4291,8 @@ this headline and the next (so @emph{not} the entire subtree).
 If there is no active region, just toggle the checkbox at point.
 @end itemize
 @orgcmd{M-S-@key{RET},org-insert-todo-heading}
-Insert a new item with a checkbox.
-This works only if the cursor is already in a plain list item
-(@pxref{Plain lists}).
+Insert a new item with a checkbox.  This works only if the cursor is already
+in a plain list item (@pxref{Plain lists}).
 @orgcmd{C-c C-x o,org-toggle-ordered-property}
 @vindex org-track-ordered-property-with-tag
 @cindex property, ORDERED

+ 3 - 2
doc/orgguide.texi

@@ -494,8 +494,9 @@ description.
 @end itemize
 
 Items belonging to the same list must have the same indentation on the first
-line.  A list ends before the next line that is indented like the
-bullet/number, or less.  It also ends before two blank lines. An example:
+line.  An item ends before the next line that is indented like the
+bullet/number, or less.  A list ends when all items are closed, or before two
+blank lines. An example:
 
 @smallexample
 @group

+ 6 - 2
lisp/ob.el

@@ -76,7 +76,9 @@
 (declare-function org-in-item-p "org-list" ())
 (declare-function org-list-parse-list "org-list" (&optional delete))
 (declare-function org-list-to-generic "org-list" (LIST PARAMS))
-(declare-function org-list-bottom-point "org-list" ())
+(declare-function org-list-struct "org-list" ())
+(declare-function org-list-prevs-alist "org-list" (struct))
+(declare-function org-list-get-list-end "org-list" (item struct prevs))
 
 (defgroup org-babel nil
   "Code block evaluation and management in `org-mode' documents."
@@ -1582,7 +1584,9 @@ code ---- the results are extracted in the syntax of the source
   (save-excursion
     (cond
      ((org-at-table-p) (progn (goto-char (org-table-end)) (point)))
-     ((org-at-item-p) (- (org-list-bottom-point) 1))
+     ((org-at-item-p) (let* ((struct (org-list-struct))
+			     (prvs (org-list-prevs-alist struct)))
+			(1- (org-list-get-list-end (point-at-bol) struct prvs))))
      (t
       (let ((case-fold-search t)
 	    (blocks-re (regexp-opt

+ 9 - 2
lisp/org-agenda.el

@@ -2159,9 +2159,10 @@ Pressing `<' twice means to restrict to the current subtree or region
 	(move-marker org-agenda-restrict-end nil))
       ;; Delete old local properties
       (put 'org-agenda-redo-command 'org-lprops nil)
+      ;; Delete previously set last-arguments
+      (put 'org-agenda-redo-command 'last-args nil)
       ;; Remember where this call originated
       (setq org-agenda-last-dispatch-buffer (current-buffer))
-      (kill-local-variable 'org-agenda-current-span)
       (unless keys
 	(setq ans (org-agenda-get-restriction-and-command prefix-descriptions)
 	      keys (car ans)
@@ -2462,6 +2463,10 @@ s   Search for keywords                 C   Configure custom agenda commands
   (org-let (nth 1 series) '(org-prepare-agenda name))
   (let* ((org-agenda-multi t)
 	 (redo (list 'org-run-agenda-series name (list 'quote series)))
+	 (org-agenda-overriding-arguments 
+	  (or org-agenda-overriding-arguments
+	      (unless (null (delq nil (get 'org-agenda-redo-command 'last-args)))
+		(get 'org-agenda-redo-command 'last-args))))
 	 (cmds (car series))
 	 (gprops (nth 1 series))
 	 match ;; The byte compiler incorrectly complains about this.  Keep it!
@@ -2496,6 +2501,7 @@ s   Search for keywords                 C   Configure custom agenda commands
        (t (error "Invalid type in command series"))))
     (widen)
     (setq org-agenda-redo-command redo)
+    (put 'org-agenda-redo-command 'last-args org-agenda-last-arguments)
     (goto-char (point-min)))
   (org-fit-agenda-window)
   (org-let (nth 1 series) '(org-finalize-agenda)))
@@ -6292,7 +6298,8 @@ SPAN may be `day', `week', `month', `year'."
 		org-starting-day))
 	 (sd (org-agenda-compute-starting-span sd span n))
 	 (org-agenda-overriding-arguments
-	  (list (car org-agenda-last-arguments) sd span t)))
+	  (or org-agenda-overriding-arguments
+	      (list (car org-agenda-last-arguments) sd span t))))
     (org-agenda-redo)
     (org-agenda-find-same-or-today-or-agenda))
   (org-agenda-set-mode-name)

+ 2 - 2
lisp/org-ascii.el

@@ -577,8 +577,8 @@ publishing directory."
       (replace-match "\\1\\2")))
   ;; Remove list start counters
   (goto-char (point-min))
-  (while (org-search-forward-unenclosed
-	  "\\[@\\(?:start:\\)?[0-9]+\\][ \t]*" nil t)
+  (while (org-list-search-forward
+	  "\\[@\\(?:start:\\)?\\([0-9]+\\|[A-Za-z]\\)\\][ \t]*" nil t)
     (replace-match ""))
   (remove-text-properties
    (point-min) (point-max)

+ 2 - 2
lisp/org-capture.el

@@ -827,14 +827,14 @@ already gone.  Any prefix argument will be passed to the refile comand."
     (if (org-capture-get :prepend)
 	(progn
 	  (goto-char beg)
-	  (if (org-search-forward-unenclosed org-item-beginning-re end t)
+	  (if (org-list-search-forward (org-item-beginning-re) end t)
 	      (progn
 		(goto-char (match-beginning 0))
 		(setq ind (org-get-indentation)))
 	    (goto-char end)
 	    (setq ind 0)))
       (goto-char end)
-      (if (org-search-backward-unenclosed org-item-beginning-re beg t)
+      (if (org-list-search-backward (org-item-beginning-re) beg t)
 	  (progn
 	    (setq ind (org-get-indentation))
 	    (org-end-of-item))

+ 2 - 0
lisp/org-clock.el

@@ -29,6 +29,7 @@
 ;; This file contains the time clocking code for Org-mode
 
 (require 'org)
+(require 'org-exp)
 ;;; Code:
 
 (eval-when-compile
@@ -260,6 +261,7 @@ For more information, see `org-clocktable-write-default'."
 
 (defcustom org-clock-clocktable-language-setup
   '(("en" "File"     "L"  "Timestamp"  "Headline" "Time"  "ALL"   "Total time"   "File time")
+    ("es" "Archivo"  "N"  "Fecha y hora" "Tarea" "Tiempo" "TODO" "Tiempo total" "Tiempo archivo")
     ("fr" "Fichier"  "N"  "Horodatage" "En-tête"  "Durée" "TOUT"  "Durée totale" "Durée fichier")
     ("nl" "Bestand"  "N"  "Tijdstip"   "Hoofding" "Duur"  "ALLES" "Totale duur"  "Bestandstijd"))
   "Terms used in clocktable, translated to different languages."

+ 102 - 118
lisp/org-docbook.el

@@ -499,9 +499,6 @@ publishing directory."
 	 (inquote     nil)
 	 (infixed     nil)
 	 (inverse     nil)
-	 (in-local-list nil)
-	 (local-list-type nil)
-	 (local-list-indent nil)
 	 (llt org-plain-list-ordered-item-terminator)
 	 (email (plist-get opt-plist :email))
 	 (language (plist-get opt-plist :language))
@@ -671,22 +668,6 @@ publishing directory."
 	      (org-export-docbook-open-para))
 	    (throw 'nextline nil))
 
-	  ;; List ender: close every open list.
-	  (when (equal "ORG-LIST-END" line)
-	    (while local-list-type
-	      (let ((listtype (car local-list-type)))
-		(org-export-docbook-close-li listtype)
-		(insert (cond
-			 ((equal listtype "o") "</orderedlist>\n")
-			 ((equal listtype "u") "</itemizedlist>\n")
-			 ((equal listtype "d") "</variablelist>\n"))))
-	      (pop local-list-type))
-	    ;; We did close a list, normal text follows: need <para>
-	    (org-export-docbook-open-para)
-	    (setq local-list-indent nil
-		  in-local-list nil)
-	    (throw 'nextline nil))
-
 	  ;; Protected HTML
 	  (when (get-text-property 0 'org-protected line)
 	    (let (par (ind (get-text-property 0 'original-indentation line)))
@@ -1008,93 +989,15 @@ publishing directory."
 		       (org-format-table-html table-buffer table-orig-buffer
 					      'no-css)))))
 
+	   ;; Normal lines
 	   (t
-	    ;; Normal lines
-	    (when (string-match
-		   (cond
-		    ((eq llt t) "^\\([ \t]*\\)\\(\\([-+*] \\)\\|\\([0-9]+[.)]\\) \\)?\\( *[^ \t\n\r]\\|[ \t]*$\\)")
-		    ((= llt ?.) "^\\([ \t]*\\)\\(\\([-+*] \\)\\|\\([0-9]+\\.\\) \\)?\\( *[^ \t\n\r]\\|[ \t]*$\\)")
-		    ((= llt ?\)) "^\\([ \t]*\\)\\(\\([-+*] \\)\\|\\([0-9]+)\\) \\)?\\( *[^ \t\n\r]\\|[ \t]*$\\)")
-		    (t (error "Invalid value of `org-plain-list-ordered-item-terminator'")))
-		   line)
-	      (setq ind (or (get-text-property 0 'original-indentation line)
-			    (org-get-string-indentation line))
-		    item-type (if (match-beginning 4) "o" "u")
-		    starter (if (match-beginning 2)
-				(substring (match-string 2 line) 0 -1))
-		    line (substring line (match-beginning 5))
-		    item-tag nil
-		    item-number nil)
-	      (if (string-match "\\[@\\(?:start:\\)?\\([0-9]+\\)\\][ \t]?" line)
-		  (setq item-number (match-string 1 line)
-			line (replace-match "" t t line)))
-	      (if (and starter (string-match "\\(.*?\\) ::[ \t]*" line))
-		  (setq item-type "d"
-			item-tag (match-string 1 line)
-			line (substring line (match-end 0))))
-	      (cond
-	       ((and starter
-		     (or (not in-local-list)
-			 (> ind (car local-list-indent))))
-		;; Start new (level of) list
-		(org-export-docbook-close-para-maybe)
-		(insert (cond
-			 ((equal item-type "u") "<itemizedlist>\n<listitem>\n")
-			 ((and (equal item-type "o") item-number)
-			  ;; Check for a specific start number.  If it
-			  ;; is specified, we use the ``override''
-			  ;; attribute of element <listitem> to pass the
-			  ;; info to DocBook.  We could also use the
-			  ;; ``startingnumber'' attribute of element
-			  ;; <orderedlist>, but the former works on both
-			  ;; DocBook 5.0 and prior versions.
-			  (format "<orderedlist>\n<listitem override=\"%s\">\n" item-number))
-			 ((equal item-type "o") "<orderedlist>\n<listitem>\n")
-			 ((equal item-type "d")
-			  (format "<variablelist>\n<varlistentry><term>%s</term><listitem>\n" item-tag))))
-		;; For DocBook, we need to open a para right after tag
-		;; <listitem>.
-		(org-export-docbook-open-para)
-		(push item-type local-list-type)
-		(push ind local-list-indent)
-		(setq in-local-list t))
-		;; Continue current list
-	       (starter
-		;; terminate any previous sublist but first ensure
-		;; list is not ill-formed
-		(let ((min-ind (apply 'min local-list-indent)))
-		  (when (< ind min-ind) (setq ind min-ind)))
-		(while (< ind (car local-list-indent))
-		  (let ((listtype (car local-list-type)))
-		    (org-export-docbook-close-li listtype)
-		    (insert (cond
-			     ((equal listtype "o") "</orderedlist>\n")
-			     ((equal listtype "u") "</itemizedlist>\n")
-			     ((equal listtype "d") "</variablelist>\n"))))
-		  (pop local-list-type) (pop local-list-indent)
-		  (setq in-local-list local-list-indent))
-		;; insert new item
-		(let ((listtype (car local-list-type)))
-		  (org-export-docbook-close-li listtype)
-		  (insert (cond
-			   ((and (equal listtype "o") item-number)
-			    (format "<listitem override=\"%s\">" item-number))
-			   ((equal listtype "o") "<listitem>")
-			   ((equal listtype "u") "<listitem>")
-			   ((equal listtype "d") (format
-						  "<varlistentry><term>%s</term><listitem>"
-						  (or item-tag
-						      "???"))))))
-		;; For DocBook, we need to open a para right after tag
-		;; <listitem>.
-		(org-export-docbook-open-para)))
-	      ;; Checkboxes.
-	      (if (string-match "^[ \t]*\\(\\[[X -]\\]\\)" line)
-		  (setq line
-			(replace-match (concat checkbox-start
-					       (match-string 1 line)
-					       checkbox-end)
-				       t t line))))
+	    ;; This line either is list item or end a list.
+	    (when (when (get-text-property 0 'list-item line)
+	   	      (setq line (org-export-docbook-list-line
+			  line
+			  (get-text-property 0 'list-item line)
+			  (get-text-property 0 'list-struct line)
+			  (get-text-property 0 'list-prevs line)))))
 
 	    ;; Empty lines start a new paragraph.  If hand-formatted lists
 	    ;; are not fully interpreted, lines starting with "-", "+", "*"
@@ -1138,20 +1041,12 @@ publishing directory."
 	(if (eq major-mode (default-value 'major-mode))
 	    (nxml-mode)))
 
-      ;; Remove empty paragraphs and lists.  Replace them with a
-      ;; newline.
+      ;; Remove empty paragraphs. Replace them with a newline.
       (goto-char (point-min))
       (while (re-search-forward
 	      "[ \r\n\t]*\\(<para>\\)[ \r\n\t]*</para>[ \r\n\t]*" nil t)
 	(when (not (get-text-property (match-beginning 1) 'org-protected))
 	  (replace-match "\n")
-	  ;; Avoid empty <listitem></listitem> caused by inline tasks.
-	  ;; We should add an empty para to make everything valid.
-	  (when (and (looking-at "</listitem>")
-		     (save-excursion
-		       (backward-char (length "<listitem>\n"))
-		       (looking-at "<listitem>")))
-	    (insert "<para></para>"))
 	  (backward-char 1)))
       ;; Fill empty sections with <para></para>.  This is to make sure
       ;; that the DocBook document generated is valid and well-formed.
@@ -1193,10 +1088,6 @@ publishing directory."
       (insert "</listitem></varlistentry>\n")
     (insert "</listitem>\n")))
 
-(defvar in-local-list)
-(defvar local-list-indent)
-(defvar local-list-type)
-
 (defun org-export-docbook-level-start (level title)
   "Insert a new level in DocBook export.
 When TITLE is nil, just close all open levels."
@@ -1438,6 +1329,99 @@ that need to be preserved in later phase of DocBook exporting."
 	    line (substring line (match-end 0))))
     (concat replaced line)))
 
+(defun org-export-docbook-list-line (line pos struct prevs)
+  "Insert list syntax in export buffer. Return LINE, maybe modified.
+
+POS is the item position or line position the line had before
+modifications to buffer. STRUCT is the list structure. PREVS is
+the alist of previous items."
+  (let* ((get-type
+	  (function
+	   ;; Translate type of list containing POS to "ordered",
+	   ;; "variable" or "itemized".
+	   (lambda (pos struct prevs)
+	     (let ((type (org-list-get-list-type pos struct prevs)))
+	       (cond
+		((eq 'ordered type) "ordered")
+		((eq 'descriptive type) "variable")
+		(t "itemized"))))))
+	 (get-closings
+	  (function
+	   ;; Return list of all items and sublists ending at POS, in
+	   ;; reverse order.
+	   (lambda (pos)
+	     (let (out)
+	       (catch 'exit
+		 (mapc (lambda (e)
+			 (let ((end (nth 6 e))
+			       (item (car e)))
+			   (cond
+			    ((= end pos) (push item out))
+			    ((>= item pos) (throw 'exit nil)))))
+		       struct))
+	       out)))))
+    ;; First close any previous item, or list, ending at POS.
+    (mapc (lambda (e)
+	    (let* ((lastp (= (org-list-get-last-item e struct prevs) e))
+		   (first-item (org-list-get-list-begin e struct prevs))
+		   (type (funcall get-type first-item struct prevs)))
+	      ;; Ending for every item
+	      (org-export-docbook-close-para-maybe)
+	      (insert (if (equal type "variable")
+			  "</listitem></varlistentry>\n"
+			"</listitem>\n"))
+	      ;; We're ending last item of the list: end list.
+	      (when lastp (insert (format "</%slist>\n" type)))))
+	  (funcall get-closings pos))
+    (cond
+     ;; At an item: insert appropriate tags in export buffer.
+     ((assq pos struct)
+      (string-match (concat "[ \t]*\\(\\S-+[ \t]+\\)"
+			    "\\(?:\\[@\\(?:start:\\)?\\([0-9]+\\|[a-zA-Z]\\)\\]\\)?"
+			    "\\(?:\\(\\[[ X-]\\]\\)[ \t]+\\)?"
+			    "\\(?:\\(.*\\)[ \t]+::[ \t]+\\)?"
+			    "\\(.*\\)")
+		    line)
+      (let* ((checkbox (match-string 3 line))
+	     (desc-tag (or (match-string 4 line) "???"))
+	     (body (match-string 5 line))
+	     (list-beg (org-list-get-list-begin pos struct prevs))
+	     (firstp (= list-beg pos))
+	     ;; Always refer to first item to determine list type, in
+	     ;; case list is ill-formed.
+	     (type (funcall get-type list-beg struct prevs))
+	     ;; Special variables for ordered lists.
+	     (counter (let ((count-tmp (org-list-get-counter pos struct)))
+			(cond
+			 ((not count-tmp) nil)
+			 ((string-match "[A-Za-z]" count-tmp)
+			  (- (string-to-char (upcase count-tmp)) 64))
+			 ((string-match "[0-9]+" count-tmp)
+			  count-tmp)))))
+	;; When FIRSTP, a new list or sub-list is starting.
+	(when firstp
+	  (org-export-docbook-close-para-maybe)
+	  (insert (format "<%slist>\n" type)))
+	(insert (cond
+		 ((equal type "variable")
+		  (format "<varlistentry><term>%s</term><listitem>" desc-tag))
+		 ((and (equal type "ordered") counter)
+		  (format "<listitem override=\"%s\">" counter))
+		 (t "<listitem>")))
+	;; For DocBook, we need to open a para right after tag
+	;; <listitem>.
+	(org-export-docbook-open-para)
+	;; If line had a checkbox, some additional modification is required.
+	(when checkbox (setq body (concat checkbox " " body)))
+	;; Return modified line
+	body))
+     ;; At a list ender:  normal text follows: need <para>.
+     ((equal "ORG-LIST-END" line)
+      (org-export-docbook-open-para)
+      (throw 'nextline nil))
+     ;; Not at an item: return line unchanged (side-effects only).
+     (t line))))
+
 (provide 'org-docbook)
 
 ;; arch-tag: a24a127c-d365-4c2a-9e9b-f7dcb0ebfdc3

+ 3 - 8
lisp/org-exp-blocks.el

@@ -76,11 +76,6 @@
   (require 'cl))
 (require 'org)
 
-(defvar htmlp)
-(defvar latexp)
-(defvar docbookp)
-(defvar asciip)
-
 (defun org-export-blocks-set (var value)
   "Set the value of `org-export-blocks' and install fontification."
   (set var value)
@@ -247,7 +242,7 @@ passed to the ditaa utility as command line arguments."
 			    "\n")))
     (prog1
     (cond
-     ((or htmlp latexp docbookp)
+     ((member backend '(html latex docbook))
       (unless (file-exists-p out-file)
         (mapc ;; remove old hashed versions of this file
          (lambda (file)
@@ -306,7 +301,7 @@ digraph data_relationships {
 	 (out-file (concat (car out-file-parts) "_" hash "." (cdr out-file-parts))))
     (prog1
     (cond
-     ((or htmlp latexp docbookp)
+     ((member backend '(html latex docbook))
       (unless (file-exists-p out-file)
 	(mapc ;; remove old hashed versions of this file
 	 (lambda (file)
@@ -338,7 +333,7 @@ other backends, it converts the comment into an EXAMPLE segment."
   (let ((owner (if headers (car headers)))
 	(title (if (cdr headers) (mapconcat 'identity (cdr headers) " "))))
     (cond
-     (htmlp ;; We are exporting to HTML
+     ((eq backend 'html) ;; We are exporting to HTML
       (concat "#+BEGIN_HTML\n"
 	      "<div class=\"org-comment\""
 	      (if owner (format " id=\"org-comment-%s\" " owner))

+ 106 - 34
lisp/org-exp.el

@@ -1033,8 +1033,7 @@ to export.  It then creates a temporary buffer where it does its job.
 The result is then again returned as a string, and the exporter works
 on this string to produce the exported version."
   (interactive)
-  (let* ((docbookp (eq (plist-get parameters :for-backend) 'docbook))
-	 (backend (plist-get parameters :for-backend))
+  (let* ((backend (plist-get parameters :for-backend))
 	 (archived-trees (plist-get parameters :archived-trees))
 	 (inhibit-read-only t)
 	 (drawers org-drawers)
@@ -1090,12 +1089,16 @@ on this string to produce the exported version."
 				     (plist-get parameters :exclude-tags))
       (run-hooks 'org-export-preprocess-after-tree-selection-hook)
 
-      ;; Mark end of lists
-      (org-export-mark-list-ending backend)
+      ;; Change lists ending. Other parts of export may insert blank
+      ;; lines and lists' structure could be altered.
+      (org-export-mark-list-end backend)
 
       ;; Export code blocks
       (org-export-blocks-preprocess)
 
+      ;; Mark lists with properties
+      (org-export-mark-list-properties backend)
+
       ;; Handle source code snippets
       (org-export-replace-src-segments-and-examples backend)
 
@@ -1606,11 +1609,11 @@ from the buffer."
 	   (ascii "ASCII" "BEGIN_ASCII" "END_ASCII")
 	   (latex "LaTeX" "BEGIN_LaTeX" "END_LaTeX")))
 	(case-fold-search t)
-	fmt beg beg-content end end-content)
+	fmt beg beg-content end end-content ind)
 
     (while formatters
       (setq fmt (pop formatters))
-      ;; Handle #+Backend: stuff
+      ;; Handle #+backend: stuff
       (goto-char (point-min))
       (while (re-search-forward (concat "^\\([ \t]*\\)#\\+" (cadr fmt)
 					":[ \t]*\\(.*\\)") nil t)
@@ -1619,27 +1622,31 @@ from the buffer."
 	  (replace-match "\\1\\2" t)
 	  (add-text-properties
 	   (point-at-bol) (min (1+ (point-at-eol)) (point-max))
-	   '(org-protected t))))
+	   `(org-protected t original-indentation ,ind))))
       ;; Delete #+attr_Backend: stuff of another backend. Those
       ;; matching the current backend will be taken care of by
       ;; `org-export-attach-captions-and-attributes'
       (goto-char (point-min))
       (while (re-search-forward (concat "^\\([ \t]*\\)#\\+attr_" (cadr fmt)
 					":[ \t]*\\(.*\\)") nil t)
+	(setq ind (org-get-indentation))
 	(when (not (eq (car fmt) backend))
 	  (delete-region (point-at-bol) (min (1+ (point-at-eol)) (point-max)))))
-      ;; Handle #+begin_Backend and #+end_Backend stuff
+      ;; Handle #+begin_backend and #+end_backend stuff
       (goto-char (point-min))
       (while (re-search-forward (concat "^[ \t]*#\\+" (caddr fmt) "\\>.*\n?")
 				nil t)
 	(setq beg (match-beginning 0) beg-content (match-end 0))
+	(setq ind (save-excursion (goto-char beg) (org-get-indentation)))
 	(when (re-search-forward (concat "^[ \t]*#\\+" (cadddr fmt) "\\>.*\n?")
 				 nil t)
 	  (setq end (match-end 0) end-content (match-beginning 0))
 	  (if (eq (car fmt) backend)
 	      ;; yes, keep this
 	      (progn
-		(add-text-properties beg-content end-content '(org-protected t))
+		(add-text-properties
+		 beg-content end-content
+		 `(org-protected t original-indentation ,ind))
 		(delete-region (match-beginning 0) (match-end 0))
 		(save-excursion
 		  (goto-char beg)
@@ -1671,33 +1678,98 @@ These special cookies will later be interpreted by the backend."
 	(delete-region beg end)
 	(insert (org-add-props content nil 'original-indentation ind))))))
 
-(defun org-export-mark-list-ending (backend)
-  "Mark list endings with special cookies.
-These special cookies will later be interpreted by the backend.
-`org-list-end-re' is replaced by a blank line in the process."
-  (let ((process-buffer
-	 (lambda (end-list-marker)
-	   (goto-char (point-min))
-	   (while (org-search-forward-unenclosed org-item-beginning-re nil t)
-	     (goto-char (org-list-bottom-point))
+(defun org-export-mark-list-end (backend)
+  "Mark all list endings with a special string."
+  (unless (eq backend 'ascii)
+    (mapc
+     (lambda (e)
+       ;; For each type allowing list export, find every list, remove
+       ;; ending regexp if needed, and insert org-list-end.
+       (goto-char (point-min))
+       (while (re-search-forward (org-item-beginning-re) nil t)
+	 (when (eq (nth 2 (org-list-context)) e)
+	   (let* ((struct (org-list-struct))
+		  (bottom (org-list-get-bottom-point struct))
+		  (top (point-at-bol))
+		  (top-ind (org-list-get-ind top struct)))
+	     (goto-char bottom)
 	     (when (and (not (eq org-list-ending-method 'indent))
-			(looking-at (org-list-end-re)))
-	       (replace-match "\n"))
+			(looking-at org-list-end-re))
+	       (replace-match ""))
 	     (unless (bolp) (insert "\n"))
-	     (unless (looking-at end-list-marker)
-	       (insert end-list-marker))
-	     (unless (eolp) (insert "\n"))))))
-  ;; We need to divide backends into 3 categories.
-  (cond
-   ;; 1. Backends using `org-list-parse-list' do not need markers.
-   ((memq backend '(latex))
-    nil)
-   ;; 2. Line-processing backends need to be told where lists end.
-   ((memq backend '(html docbook))
-    (funcall process-buffer "ORG-LIST-END\n"))
-   ;; 3. Others backends do not need to know this: clean list enders.
-   (t
-    (funcall process-buffer "")))))
+	     ;; As org-list-end is inserted at column 0, it would end
+	     ;; by indentation any list. It can be problematic when
+	     ;; there are lists within lists: the inner list end would
+	     ;; also become the outer list end. To avoid this, text
+	     ;; property `original-indentation' is added, as
+	     ;; `org-list-struct' pays attention to it when reading a
+	     ;; list.
+	     (insert (org-add-props
+			 "ORG-LIST-END\n"
+			 (list 'original-indentation top-ind)))))))
+     (cons nil org-list-export-context))))
+
+(defun org-export-mark-list-properties (backend)
+  "Mark list with special properties.
+These special properties will later be interpreted by the backend."
+  (let ((mark-list
+	 (function
+	  ;; Mark a list with 3 properties: `list-item' which is
+	  ;; position at beginning of line, `list-struct' which is
+	  ;; list structure, and `list-prevs' which is the alist of
+	  ;; item and its predecessor. Leave point at list ending.
+	  (lambda (ctxt)
+	    (let* ((struct (org-list-struct))
+		   (top (org-list-get-top-point struct))
+		   (bottom (org-list-get-bottom-point struct))
+		   (prevs (org-list-prevs-alist struct))
+		   poi)
+	      ;; Get every item and ending position, without dups and
+	      ;; without bottom point of list.
+	      (mapc (lambda (e)
+		      (let ((pos (car e))
+			    (end (nth 6 e)))
+			(unless (memq pos poi)
+			  (push pos poi))
+			(unless (or (= end bottom) (memq end poi))
+			  (push end poi))))
+		    struct)
+	      (setq poi (sort poi '<))
+	      ;; For every point of interest, mark the whole line with
+	      ;; its position in list.
+	      (mapc
+	       (lambda (e)
+		 (goto-char e)
+		 (add-text-properties (point-at-bol) (point-at-eol)
+				      (list 'list-item (point-at-bol)
+					    'list-struct struct
+					    'list-prevs prevs)))
+	       poi)
+	      ;; Take care of bottom point. As babel may have inserted
+	      ;; a new list in buffer, list ending isn't always
+	      ;; marked. Now mark every list ending and add properties
+	      ;; useful to line processing exporters.
+	      (goto-char bottom)
+	      (when (or (looking-at "^ORG-LIST-END\n")
+			(and (not (eq org-list-ending-method 'indent))
+			     (looking-at org-list-end-re)))
+		(replace-match ""))
+	      (unless (bolp) (insert "\n"))
+	      (insert
+	       (org-add-props "ORG-LIST-END\n" (list 'list-item bottom
+						     'list-struct struct
+						     'list-prevs prevs)))
+	      ;; Following property is used by LaTeX exporter.
+	      (add-text-properties top (point) (list 'list-context ctxt)))))))
+    ;; Mark lists except for backends not interpreting them.
+    (unless (eq backend 'ascii)
+      (let ((org-list-end-re "^ORG-LIST-END\n"))
+	(mapc
+	 (lambda (e)
+	   (goto-char (point-min))
+	   (while (re-search-forward (org-item-beginning-re) nil t)
+	     (when (eq (nth 2 (org-list-context)) e) (funcall mark-list e))))
+	 (cons nil org-list-export-context))))))
 
 (defun org-export-attach-captions-and-attributes (backend target-alist)
   "Move #+CAPTION, #+ATTR_BACKEND, and #+LABEL text into text properties.

+ 122 - 103
lisp/org-html.el

@@ -1092,16 +1092,17 @@ PUB-DIR is set, use this as the publishing directory."
 	 (date (plist-get opt-plist :date))
 	 (author      (plist-get opt-plist :author))
 	 (html-validation-link (or org-export-html-validation-link ""))
-	 (title       (or (and subtree-p (org-export-get-title-from-subtree))
-			  (plist-get opt-plist :title)
-			  (and (not body-only)
-			       (not
-				(plist-get opt-plist :skip-before-1st-heading))
-			       (org-export-grab-title-from-buffer))
-			  (and buffer-file-name
-			       (file-name-sans-extension
-				(file-name-nondirectory buffer-file-name)))
-			  "UNTITLED"))
+	 (title       (org-html-expand
+		       (or (and subtree-p (org-export-get-title-from-subtree))
+			   (plist-get opt-plist :title)
+			   (and (not body-only)
+				(not
+				 (plist-get opt-plist :skip-before-1st-heading))
+				(org-export-grab-title-from-buffer))
+			   (and buffer-file-name
+				(file-name-sans-extension
+				 (file-name-nondirectory buffer-file-name)))
+			   "UNTITLED")))
 	 (link-up (and (plist-get opt-plist :link-up)
 		       (string-match "\\S-" (plist-get opt-plist :link-up))
 		       (plist-get opt-plist :link-up)))
@@ -1115,10 +1116,6 @@ PUB-DIR is set, use this as the publishing directory."
 	 (inquote     nil)
 	 (infixed     nil)
 	 (inverse     nil)
-	 (in-local-list nil)
-	 (local-list-type nil)
-	 (local-list-indent nil)
-	 (llt org-plain-list-ordered-item-terminator)
 	 (email       (plist-get opt-plist :email))
 	 (language    (plist-get opt-plist :language))
 	 (keywords    (plist-get opt-plist :keywords))
@@ -1176,8 +1173,9 @@ PUB-DIR is set, use this as the publishing directory."
 	    ""))
 	 table-open
 	 table-buffer table-orig-buffer
-	 ind item-type starter
-	 snumber item-tag item-number
+	 ind
+	 rpl path attr desc descp desc1 desc2 link
+	 snumber fnc
 	 footnotes footref-seen
 	 href
 	 )
@@ -1280,7 +1278,7 @@ lang=\"%s\" xml:lang=\"%s\">
 				     org-export-html-preamble-format))
 			(cadr (assoc "en" org-export-html-preamble-format))))))
 	    (insert (format-spec html-preamble-format
-				 `((?t . ,(org-html-expand title))
+				 `((?t . ,title)
 				   (?a . ,author) (?d . ,date) (?e . ,email)))))))
 
       (if (and org-export-with-toc (not body-only))
@@ -1403,17 +1401,6 @@ lang=\"%s\" xml:lang=\"%s\">
 	      (org-open-par))
 	    (throw 'nextline nil))
 
-	  ;; Explicit list closure
-	  (when (equal "ORG-LIST-END" line)
-	    (while local-list-indent
-	      (org-close-li (car local-list-type))
-	      (insert (format "</%sl>\n" (car local-list-type)))
-	      (pop local-list-type)
-	      (pop local-list-indent))
-	    (setq in-local-list nil)
-	    (org-open-par)
-	    (throw 'nextline nil))
-
 	  ;; Protected HTML
 	  (when (and (get-text-property 0 'org-protected line)
 		     ;; Make sure it is the entire line that is protected
@@ -1594,72 +1581,17 @@ lang=\"%s\" xml:lang=\"%s\">
 		    table-orig-buffer (nreverse table-orig-buffer))
 	      (org-close-par-maybe)
 	      (insert (org-format-table-html table-buffer table-orig-buffer))))
+
+	   ;; Normal lines
+
 	   (t
-	    ;; Normal lines
-	    (when (string-match
-		   (cond
-		    ((eq llt t) "^\\([ \t]*\\)\\(\\([-+*] \\)\\|\\([0-9]+[.)]\\) \\)?\\( *[^ \t\n\r]\\|[ \t]*$\\)")
-		    ((= llt ?.) "^\\([ \t]*\\)\\(\\([-+*] \\)\\|\\([0-9]+\\.\\) \\)?\\( *[^ \t\n\r]\\|[ \t]*$\\)")
-		    ((= llt ?\)) "^\\([ \t]*\\)\\(\\([-+*] \\)\\|\\([0-9]+)\\) \\)?\\( *[^ \t\n\r]\\|[ \t]*$\\)")
-		    (t (error "Invalid value of `org-plain-list-ordered-item-terminator'")))
-		   line)
-	      (setq ind (or (get-text-property 0 'original-indentation line)
-			    (org-get-string-indentation line))
-		    item-type (if (match-beginning 4) "o" "u")
-		    starter (if (match-beginning 2)
-				(substring (match-string 2 line) 0 -1))
-		    line (substring line (match-beginning 5))
-		    item-number nil
-		    item-tag nil)
-	      (if (string-match "\\[@\\(?:start:\\)?\\([0-9]+\\)\\][ \t]?" line)
-		  (setq item-number (match-string 1 line)
-			line (replace-match "" t t line)))
-	      (if (and starter (string-match "\\(.*?\\) ::[ \t]*" line))
-		  (setq item-type "d"
-			item-tag (match-string 1 line)
-			line (substring line (match-end 0))))
-	      (cond
-	       ((and starter
-		     (or (not in-local-list)
-			 (> ind (car local-list-indent))))
-		;; Start new (level of) list
-		(org-close-par-maybe)
-		(insert (cond
-			 ((equal item-type "u") "<ul>\n<li>\n")
-			 ((and (equal item-type "o") item-number)
-			  (format "<ol>\n<li value=\"%s\">\n" item-number))
-			 ((equal item-type "o") "<ol>\n<li>\n")
-			 ((equal item-type "d")
-			  (format "<dl>\n<dt>%s</dt><dd>\n" item-tag))))
-		(push item-type local-list-type)
-		(push ind local-list-indent)
-		(setq in-local-list t))
-	       ;; Continue list
-	       (starter
-		;; terminate any previous sublist but first ensure
-		;; list is not ill-formed.
-		(let ((min-ind (apply 'min local-list-indent)))
-		  (when (< ind min-ind) (setq ind min-ind)))
-		(while (< ind (car local-list-indent))
-		  (org-close-li (car local-list-type))
-		  (insert (format "</%sl>\n" (car local-list-type)))
-		  (pop local-list-type) (pop local-list-indent)
-		  (setq in-local-list local-list-indent))
-		;; insert new item
-		(org-close-li (car local-list-type))
-		(insert (cond
-			 ((equal (car local-list-type) "d")
-			  (format "<dt>%s</dt><dd>\n" (or item-tag "???")))
-			 ((and (equal item-type "o") item-number)
-			  (format "<li value=\"%s\">\n" item-number))
-			 (t "<li>\n")))))
-	      (if (string-match "^[ \t]*\\[\\([X ]\\)\\]" line)
-		  (setq line
-			(replace-match
-			 (if (equal (match-string 1 line) "X")
-			     "<b>[X]</b>"
-			   "<b>[<span style=\"visibility:hidden;\">X</span>]</b>")
-			 t t line))))
+	    ;; This line either is list item or end a list.
+	    (when (get-text-property 0 'list-item line)
+	      (setq line (org-html-export-list-line
+			  line
+			  (get-text-property 0 'list-item line)
+			  (get-text-property 0 'list-struct line)
+			  (get-text-property 0 'list-prevs line))))
 
 	    ;; Horizontal line
 	    (when (string-match "^[ \t]*-\\{5,\\}[ \t]*$" line)
@@ -1786,16 +1718,16 @@ lang=\"%s\" xml:lang=\"%s\">
 	    (goto-char (match-end 0))
 	    (insert "\n")))
 	(insert "<div id=\"table-of-contents\">\n")
-	(mapc 'insert thetoc)
-	(insert "</div>\n"))
-      ;; remove empty paragraphs and lists
+	(let ((beg (point)))
+	  (mapc 'insert thetoc)
+	  (insert "</div>\n")
+	  (while (re-search-backward "<li>[ \r\n\t]*</li>\n?" beg t)
+	    (replace-match ""))))
+      ;; remove empty paragraphs
       (goto-char (point-min))
       (while (re-search-forward "<p>[ \r\n\t]*</p>" nil t)
 	(replace-match ""))
       (goto-char (point-min))
-      (while (re-search-forward "<li>[ \r\n\t]*</li>\n?" nil t)
-	(replace-match ""))
-      (goto-char (point-min))
       ;; Convert whitespace place holders
       (goto-char (point-min))
       (let (beg end n)
@@ -2349,10 +2281,6 @@ If there are links in the string, don't modify these."
   (org-close-par-maybe)
   (insert (if (equal type "d") "</dd>\n" "</li>\n")))
 
-(defvar in-local-list)
-(defvar local-list-indent)
-(defvar local-list-type)
-
 (defvar body-only) ; dynamically scoped into this.
 (defun org-html-level-start (level title umax with-toc head-count)
   "Insert a new level in HTML export.
@@ -2458,6 +2386,97 @@ Replaces invalid characters with \"_\" and then prepends a prefix."
     (org-close-li)
     (insert "</ul>\n")))
 
+(defun org-html-export-list-line (line pos struct prevs)
+  "Insert list syntax in export buffer. Return LINE, maybe modified.
+
+POS is the item position or line position the line had before
+modifications to buffer. STRUCT is the list structure. PREVS is
+the alist of previous items."
+  (let* ((get-type
+	  (function
+	   ;; Translate type of list containing POS to "d", "o" or
+	   ;; "u".
+	   (lambda (pos struct prevs)
+	     (let ((type (org-list-get-list-type pos struct prevs)))
+	       (cond
+		((eq 'ordered type) "o")
+		((eq 'descriptive type) "d")
+		(t "u"))))))
+	 (get-closings
+	  (function
+	   ;; Return list of all items and sublists ending at POS, in
+	   ;; reverse order.
+	   (lambda (pos)
+	     (let (out)
+	       (catch 'exit
+		 (mapc (lambda (e)
+			 (let ((end (nth 6 e))
+			       (item (car e)))
+			   (cond
+			    ((= end pos) (push item out))
+			    ((>= item pos) (throw 'exit nil)))))
+		       struct))
+	       out)))))
+    ;; First close any previous item, or list, ending at POS.
+    (mapc (lambda (e)
+	    (let* ((lastp (= (org-list-get-last-item e struct prevs) e))
+		   (first-item (org-list-get-list-begin e struct prevs))
+		   (type (funcall get-type first-item struct prevs)))
+	      (org-close-par-maybe)
+	      ;; Ending for every item
+	      (org-close-li type)
+	      ;; We're ending last item of the list: end list.
+	      (when lastp (insert (format "</%sl>\n" type)))))
+	  (funcall get-closings pos))
+    (cond
+     ;; At an item: insert appropriate tags in export buffer.
+     ((assq pos struct)
+      (string-match
+       (concat "[ \t]*\\(\\S-+[ \t]+\\)"
+	       "\\(?:\\[@\\(?:start:\\)?\\([0-9]+\\|[A-Za-z]\\)\\]\\)?"
+	       "\\(?:\\(\\[[ X-]\\]\\)[ \t]+\\)?"
+	       "\\(?:\\(.*\\)[ \t]+::[ \t]+\\)?"
+	       "\\(.*\\)") line)
+      (let* ((checkbox (match-string 3 line))
+	     (desc-tag (or (match-string 4 line) "???"))
+	     (body (or (match-string 5 line) ""))
+	     (list-beg (org-list-get-list-begin pos struct prevs))
+	     (firstp (= list-beg pos))
+	     ;; Always refer to first item to determine list type, in
+	     ;; case list is ill-formed.
+	     (type (funcall get-type list-beg struct prevs))
+	     (counter (let ((count-tmp (org-list-get-counter pos struct)))
+			(cond
+			 ((not count-tmp) nil)
+			 ((string-match "[A-Za-z]" count-tmp)
+			  (- (string-to-char (upcase count-tmp)) 64))
+			 ((string-match "[0-9]+" count-tmp)
+			  count-tmp)))))
+	(when firstp
+	  (org-close-par-maybe)
+	  (insert (format "<%sl>\n" type)))
+	(insert (cond
+		 ((equal type "d")
+		  (format "<dt>%s</dt><dd>" desc-tag))
+		 ((and (equal type "o") counter)
+		  (format "<li value=\"%s\">" counter))
+		 (t "<li>")))
+	;; If line had a checkbox, some additional modification is required.
+	(when checkbox
+	  (setq body
+		(concat
+		 (cond
+		  ((string-match "X" checkbox) "<code>[X]</code> ")
+		  ((string-match " " checkbox) "<code>[&nbsp;]</code> ")
+		  (t "<code>[-]</code> "))
+		 body)))
+	;; Return modified line
+	body))
+     ;; At a list ender: go to next line (side-effects only).
+     ((equal "ORG-LIST-END" line) (throw 'nextline nil))
+     ;; Not at an item: return line unchanged (side-effects only).
+     (t line))))
+
 (provide 'org-html)
 
 ;; arch-tag: 8109d84d-eb8f-460b-b1a8-f45f3a6c7ea1

+ 43 - 13
lisp/org-inlinetask.el

@@ -42,7 +42,9 @@
 ;;
 ;; Export commands do not treat these nodes as part of the sectioning
 ;; structure, but as a special inline text that is either removed, or
-;; formatted in some special way.
+;; formatted in some special way.  This in handled by
+;; `org-inlinetask-export' and `org-inlinetask-export-templates'
+;; variables.
 ;;
 ;; Special fontification of inline tasks, so that they can be immediately
 ;; recognized.  From the stars of the headline, only the first and the
@@ -105,12 +107,12 @@ When nil, they will not be exported."
   :type 'boolean)
 
 (defvar org-inlinetask-export-templates
-  '((html "<pre class=\"inlinetask\"><b>%s%s</b><br>%s</pre>"
+  '((html "<pre class=\"inlinetask\"><b>%s%s</b><br />\n%s\n</pre>"
 	  '((unless (eq todo "")
 	      (format "<span class=\"%s %s\">%s%s</span> "
 		      class todo todo priority))
 	    heading content))
-    (latex "\\begin\{description\}\\item[%s%s]%s\\end\{description\}"
+    (latex "\\begin\{description\}\n\\item[%s%s]~\n%s\n\\end\{description\}"
 	   '((unless (eq todo "") (format "\\textsc\{%s%s\} " todo priority))
 	     heading content))
     (ascii "     -- %s%s%s"
@@ -197,6 +199,13 @@ The number of levels is controlled by `org-inlinetask-min-level'."
 		  org-inlinetask-min-level)))
     (format "^\\(\\*\\{%d,\\}\\)[ \t]+" nstars)))
 
+(defun org-inlinetask-at-task-p ()
+  "Return true if point is at beginning of an inline task."
+  (save-excursion
+    (beginning-of-line)
+    (and (looking-at (concat (org-inlinetask-outline-regexp)  "\\(.*\\)"))
+	 (not (string-match "^end[ \t]*$" (downcase (match-string 2)))))))
+
 (defun org-inlinetask-in-task-p ()
   "Return true if point is inside an inline task."
   (save-excursion
@@ -251,7 +260,7 @@ Either remove headline and meta data, or do special formatting."
   (let* ((nstars (if org-odd-levels-only
 		     (1- (* 2 (or org-inlinetask-min-level 200)))
 		   (or org-inlinetask-min-level 200)))
-	 (re1 (format "^\\(\\*\\{%d,\\}\\) .*\n" nstars))
+	 (re1 (format "^\\(\\*\\{%d,\\}\\)[ \t]+.*\n" nstars))
 	 (re2 (concat "^[ \t]*" org-keyword-time-regexp))
 	 headline beg end stars content)
     (while (re-search-forward re1 nil t)
@@ -266,7 +275,7 @@ Either remove headline and meta data, or do special formatting."
 	(if (re-search-forward org-property-end-re nil t)
 	    (delete-region beg (1+ (match-end 0)))))
       (setq beg (point))
-      (when (and (re-search-forward "^\\(\\*+\\) " nil t)
+      (when (and (re-search-forward "^\\(\\*+\\)[ \t]+" nil t)
 		 (= (length (match-string 1)) (length stars))
 		 (progn (goto-char (match-end 0))
 			(looking-at "END[ \t]*$")))
@@ -281,7 +290,10 @@ Either remove headline and meta data, or do special formatting."
 	      (if (string-match "[ \t\n]+\\'" content)
 		  (setq content (substring content 0 (match-beginning 0))))
 	      (setq content (org-remove-indentation content))))
-	(setq content (or content ""))
+	;; Prevent from protecting content if there's any
+	(setq content (or (and content
+			       (org-add-props content '(org-protected nil)))
+			  ""))
 	;; grab elements to export
 	(when (string-match org-complex-heading-regexp headline)
 	  (let* ((todo (or (match-string 2 headline) ""))
@@ -291,16 +303,18 @@ Either remove headline and meta data, or do special formatting."
 		 (heading (or (match-string 4 headline) ""))
 		 (tags (or (match-string 5 headline) ""))
 		 (backend-spec (assq backend org-inlinetask-export-templates))
-		 (format-str (nth 1 backend-spec))
+		 (format-str (org-add-props (nth 1 backend-spec)
+				 '(org-protected t)))
 		 (tokens (cadr (nth 2 backend-spec)))
-		 ;; change nil arguments into empty strings
-		 (nil-to-str (lambda (el) (or (eval el) "")))
-		 ;; build and protect export string
+		 (nil-to-str
+		  ;; Change nil arguments into empty strings
+		  (lambda (el) (or (eval el) "")))
+		 ;; Build and ensure export string will not break lists
 		 (export-str (org-add-props
 				 (eval (append '(format format-str)
 					       (mapcar nil-to-str tokens)))
-				 nil 'org-protected t)))
-	    ;; eventually insert it
+				 '(original-indentation 1000))))
+	    ;; Eventually insert it
 	    (insert export-str "\n")))))))
 
 (defun org-inlinetask-get-current-indentation ()
@@ -330,6 +344,22 @@ Either remove headline and meta data, or do special formatting."
       (add-text-properties (match-beginning 3) (match-end 3)
 			   '(face shadow font-lock-fontified t)))))
 
+(defun org-inlinetask-toggle-visibility ()
+  "Toggle visibility of inline task at point."
+  (let ((end (save-excursion
+	       (org-inlinetask-goto-end)
+	       (if (bolp) (1- (point)) (point))))
+	(start (save-excursion
+		 (org-inlinetask-goto-beginning)
+		 (point-at-eol))))
+    (cond
+     ;; Nothing to show/hide.
+     ((= end start))
+     ;; Inlinetask was folded: expand it.
+     ((get-char-property (1+ start) 'invisible)
+      (outline-flag-region start end nil))
+     (t (outline-flag-region start end t)))))
+
 (defun org-inlinetask-remove-END-maybe ()
   "Remove an END line when present."
   (when (looking-at (format "\\([ \t]*\n\\)*\\*\\{%d,\\}[ \t]+END[ \t]*$"
@@ -337,7 +367,7 @@ Either remove headline and meta data, or do special formatting."
     (replace-match "")))
 
 (eval-after-load "org-exp"
-  '(add-hook 'org-export-preprocess-after-tree-selection-hook
+  '(add-hook 'org-export-preprocess-before-backend-specifics-hook
 	     'org-inlinetask-export-handler))
 (eval-after-load "org"
   '(add-hook 'org-font-lock-hook 'org-inlinetask-fontify))

+ 53 - 41
lisp/org-latex.el

@@ -73,7 +73,6 @@
 	  org-closed-string"\\)")
   "Regexp matching special time planning keywords plus the time after it.")
 
-(defvar latexp)    ; dynamically scoped from org.el
 (defvar re-quote)  ; dynamically scoped from org.el
 (defvar commentsp) ; dynamically scoped from org.el
 
@@ -1442,31 +1441,32 @@ Don't perform conversions that are in EXCLUDE-LIST.  Recognized
 conversion types are: quotation-marks, emphasis, sub-superscript,
 links, keywords, lists, tables, fixed-width"
   (with-temp-buffer
-   (insert content)
-   (unless (memq 'timestamps exclude-list)
-     (org-export-latex-time-stamps))
-   (unless (memq 'quotation-marks exclude-list)
-     (org-export-latex-quotation-marks))
-   (unless (memq 'emphasis exclude-list)
-     (when (plist-get org-export-latex-options-plist :emphasize)
-       (org-export-latex-fontify)))
-   (unless (memq 'sub-superscript exclude-list)
-     (org-export-latex-special-chars
-      (plist-get org-export-latex-options-plist :sub-superscript)))
-   (unless (memq 'links exclude-list)
-     (org-export-latex-links))
-   (unless (memq 'keywords exclude-list)
-     (org-export-latex-keywords))
-   (unless (memq 'lists exclude-list)
-     (org-export-latex-lists))
-   (unless (memq 'tables exclude-list)
-     (org-export-latex-tables
-      (plist-get org-export-latex-options-plist :tables)))
-   (unless (memq 'fixed-width exclude-list)
-     (org-export-latex-fixed-width
-      (plist-get org-export-latex-options-plist :fixed-width)))
+    (org-install-letbind)
+    (insert content)
+    (unless (memq 'timestamps exclude-list)
+      (org-export-latex-time-stamps))
+    (unless (memq 'quotation-marks exclude-list)
+      (org-export-latex-quotation-marks))
+    (unless (memq 'emphasis exclude-list)
+      (when (plist-get org-export-latex-options-plist :emphasize)
+	(org-export-latex-fontify)))
+    (unless (memq 'sub-superscript exclude-list)
+      (org-export-latex-special-chars
+       (plist-get org-export-latex-options-plist :sub-superscript)))
+    (unless (memq 'links exclude-list)
+      (org-export-latex-links))
+    (unless (memq 'keywords exclude-list)
+      (org-export-latex-keywords))
+    (unless (memq 'lists exclude-list)
+      (org-export-latex-lists))
+    (unless (memq 'tables exclude-list)
+      (org-export-latex-tables
+       (plist-get org-export-latex-options-plist :tables)))
+    (unless (memq 'fixed-width exclude-list)
+      (org-export-latex-fixed-width
+       (plist-get org-export-latex-options-plist :fixed-width)))
    ;; return string
-   (buffer-substring (point-min) (point-max))))
+    (buffer-substring (point-min) (point-max))))
 
 (defun org-export-latex-protect-string (s)
   "Add the org-protected property to string S."
@@ -2460,22 +2460,34 @@ The conversion is made depending of STRING-BEFORE and STRING-AFTER."
 
 (defun org-export-latex-lists ()
   "Convert plain text lists in current buffer into LaTeX lists."
-  (let (res)
-    (goto-char (point-min))
-    (while (org-search-forward-unenclosed org-item-beginning-re nil t)
-      (beginning-of-line)
-      (setq res (org-list-to-latex (org-list-parse-list t)
-				   org-export-latex-list-parameters))
-      (while (string-match "^\\(\\\\item[ \t]+\\)\\[@\\(?:start:\\)?\\([0-9]+\\)\\]"
-			   res)
-	(setq res (replace-match
-		   (concat (format "\\setcounter{enumi}{%d}"
-				   (1- (string-to-number
-					(match-string 2 res))))
-			   "\n"
-			   (match-string 1 res))
-		   t t res)))
-      (insert res))))
+  (mapc
+   (lambda (e)
+     ;; For each type of context allowed for list export (E), find
+     ;; every list, parse it, delete it and insert resulting
+     ;; conversion to latex (RES).
+     (let (res)
+       (goto-char (point-min))
+       (while (re-search-forward (org-item-beginning-re) nil t)
+	 (when (and (eq (get-text-property (point) 'list-context) e)
+		    (not (get-text-property (point) 'org-example)))
+	   (beginning-of-line)
+	   (setq res
+		 (org-list-to-latex
+		  ;; Narrowing is needed because we're converting
+		  ;; from inner functions to outer ones.
+		  (save-restriction
+		    (narrow-to-region (point) (point-max))
+		    ;; `org-list-end-re' output has changed since
+		    ;; preprocess from org-exp.el.
+		    (let ((org-list-end-re "^ORG-LIST-END\n"))
+		      (org-list-parse-list t)))
+		  org-export-latex-list-parameters))
+	   ;; Extend previous value of original-indentation to the
+	   ;; whole string
+	   (insert (org-add-props res nil 'original-indentation
+				  (org-find-text-property-in-string
+				   'original-indentation res)))))))
+   (append org-list-export-context '(nil))))
 
 (defconst org-latex-entities
  '("\\!"

文件差异内容过多而无法显示
+ 994 - 1016
lisp/org-list.el


+ 8 - 1
lisp/org-macs.el

@@ -35,7 +35,14 @@
 
 (eval-and-compile
   (unless (fboundp 'declare-function)
-    (defmacro declare-function (fn file &optional arglist fileonly))))
+    (defmacro declare-function (fn file &optional arglist fileonly)))
+  (if (>= emacs-major-version 23)
+      (defsubst org-char-to-string(c)
+	"Defsubst to decode UTF-8 character values in emacs 23 and beyond."
+	(char-to-string c))
+    (defsubst org-char-to-string (c)
+      "Defsubst to decode UTF-8 character values in emacs 22."
+      (string (decode-char 'ucs c)))))
 
 (declare-function org-add-props "org-compat" (string plist &rest props))
 (declare-function org-string-match-p "org-compat" (&rest args))

+ 4 - 5
lisp/org-mobile.el

@@ -660,7 +660,7 @@ The table of checksums is written to the file mobile-checksums."
 	    (org-mobile-escape-olp (nth 4 (org-heading-components))))))
 
 (defun org-mobile-escape-olp (s)
-  (let  ((table '((?: . "%3a") (?\[ . "%5b") (?\] . "%5d") (?/ . "%2f"))))
+  (let  ((table '(?: ?/)))
     (org-link-escape s table)))
 
 ;;;###autoload
@@ -969,11 +969,10 @@ is currently a noop.")
     (if (not (string-match "\\`olp:\\(.*?\\):\\(.*\\)$" link))
 	nil
       (let ((file (match-string 1 link))
-	    (path (match-string 2 link))
-	    (table '((?: . "%3a") (?\[ . "%5b") (?\] . "%5d") (?/ . "%2f"))))
-	(setq file (org-link-unescape file table))
+	    (path (match-string 2 link)))
+	(setq file (org-link-unescape file))
 	(setq file (expand-file-name file org-directory))
-	(setq path (mapcar (lambda (x) (org-link-unescape x table))
+	(setq path (mapcar 'org-link-unescape
 			   (org-split-string path "/")))
 	(org-find-olp (cons file path))))))
 

+ 2 - 2
lisp/org-mouse.el

@@ -580,8 +580,8 @@ SCHEDULED: or DEADLINE: or ANYTHINGLIKETHIS:"
 (defun org-mouse-for-each-item (funct)
   ;; Functions called by `org-apply-on-list' need an argument
   (let ((wrap-fun (lambda (c) (funcall funct))))
-    (when (org-in-item-p)
-      (org-apply-on-list wrap-fun nil))))
+    (when (ignore-errors (goto-char (org-in-item-p)))
+      (save-excursion (org-apply-on-list wrap-fun nil)))))
 
 (defun org-mouse-bolp ()
   "Return true if there only spaces, tabs, and '*' before point.

+ 14 - 69
lisp/org-protocol.el

@@ -130,6 +130,18 @@
 		  (filename &optional up))
 (declare-function server-edit "server" (&optional arg))
 
+(define-obsolete-function-alias
+  'org-protocol-unhex-compound 'org-link-unescape-compound
+  "2011-02-17")
+
+(define-obsolete-function-alias
+  'org-protocol-unhex-string 'org-link-unescape
+  "2011-02-17")
+
+(define-obsolete-function-alias
+  'org-protocol-unhex-single-byte-sequence
+  'org-link-unescape-single-byte-sequence
+  "2011-02-17")
 
 (defgroup org-protocol nil
   "Intercept calls from emacsclient to trigger custom actions.
@@ -289,76 +301,9 @@ part."
     (if unhexify
 	(if (fboundp unhexify)
 	    (mapcar unhexify split-parts)
-	  (mapcar 'org-protocol-unhex-string split-parts))
+	  (mapcar 'org-link-unescape split-parts))
       split-parts)))
 
-;; This inline function is needed in org-protocol-unhex-compound to do
-;; the right thing to decode UTF-8 char integer values.
-(eval-when-compile
-  (if (>= emacs-major-version 23)
-      (defsubst org-protocol-char-to-string(c)
-	"Defsubst to decode UTF-8 character values in emacs 23 and beyond."
-	(char-to-string c))
-    (defsubst org-protocol-char-to-string (c)
-      "Defsubst to decode UTF-8 character values in emacs 22."
-      (string (decode-char 'ucs c)))))
-
-(defun org-protocol-unhex-string(str)
-  "Unhex hexified unicode strings as returned from the JavaScript function
-encodeURIComponent. E.g. `%C3%B6' is the german Umlaut `ü'."
-  (setq str (or str ""))
-  (let ((tmp "")
-	(case-fold-search t))
-    (while (string-match "\\(%[0-9a-f][0-9a-f]\\)+" str)
-      (let* ((start (match-beginning 0))
-	     (end (match-end 0))
-	     (hex (match-string 0 str))
-	     (replacement (org-protocol-unhex-compound (upcase hex))))
-	(setq tmp (concat tmp (substring str 0 start) replacement))
-	(setq str (substring str end))))
-    (setq tmp (concat tmp str))
-    tmp))
-
-
-(defun org-protocol-unhex-compound (hex)
-  "Unhexify unicode hex-chars. E.g. `%C3%B6' is the German Umlaut `ü'."
-  (let* ((bytes (remove "" (split-string hex "%")))
-	 (ret "")
-	 (eat 0)
-	 (sum 0))
-    (while bytes
-      (let* ((b (pop bytes))
-	     (a (elt b 0))
-	     (b (elt b 1))
-	     (c1 (if (> a ?9) (+ 10 (- a ?A)) (- a ?0)))
-	     (c2 (if (> b ?9) (+ 10 (- b ?A)) (- b ?0)))
-	     (val (+ (lsh c1 4) c2))
-	     (shift
-	      (if (= 0 eat) ;; new byte
-		  (if (>= val 252) 6
-		    (if (>= val 248) 5
-		      (if (>= val 240) 4
-			(if (>= val 224) 3
-			  (if (>= val 192) 2 0)))))
-		6))
-	     (xor
-	      (if (= 0 eat) ;; new byte
-		  (if (>= val 252) 252
-		    (if (>= val 248) 248
-		      (if (>= val 240) 240
-			(if (>= val 224) 224
-			  (if (>= val 192) 192 0)))))
-		128)))
-	(if (>= val 192) (setq eat shift))
-	(setq val (logxor val xor))
-	(setq sum (+ (lsh sum shift) val))
-	(if (> eat 0) (setq eat (- eat 1)))
-	(when (= 0 eat)
-	  (setq ret (concat ret (org-protocol-char-to-string sum)))
-	  (setq sum 0))
-	)) ;; end (while bytes
-    ret ))
-
 (defun org-protocol-flatten-greedy (param-list &optional strip-path replacement)
   "Greedy handlers might receive a list like this from emacsclient:
  '( (\"/dir/org-protocol:/greedy:/~/path1\" (23 . 12)) (\"/dir/param\")
@@ -531,7 +476,7 @@ The location for a browser's bookmark should look like this:
   ;; As we enter this function for a match on our protocol, the return value
   ;; defaults to nil.
   (let ((result nil)
-        (f (org-protocol-unhex-string fname)))
+        (f (org-link-unescape fname)))
     (catch 'result
       (dolist (prolist org-protocol-project-alist)
         (let* ((base-url (plist-get (cdr prolist) :base-url))

+ 4 - 6
lisp/org-publish.el

@@ -818,15 +818,15 @@ Default for SITEMAP-FILENAME is 'sitemap.org'."
 
 (defun org-publish-format-file-entry (fmt file project-plist)
   (format-spec fmt
-	     `((?t . ,(org-publish-find-title file))
+	     `((?t . ,(org-publish-find-title file t))
 	       (?d . ,(format-time-string sitemap-date-format 
 					  (org-publish-find-date file)))
 	       (?a . ,(or (plist-get project-plist :author) user-full-name)))))
 			    
-(defun org-publish-find-title (file)
+(defun org-publish-find-title (file &optional reset)
   "Find the title of FILE in project."
   (or
-   (org-publish-cache-get-file-property file :title nil t)
+   (and (not reset) (org-publish-cache-get-file-property file :title nil t))
    (let* ((visiting (find-buffer-visiting file))
 	 (buffer (or visiting (find-file-noselect file)))
 	 title)
@@ -1149,7 +1149,7 @@ Returns value on success, else nil."
   (puthash key value org-publish-cache))
 
 (defun org-publish-cache-ctime-of-src (filename)
-  "Get the files ctime as integer."
+  "Get the FILENAME ctime as an integer."
   (let ((src-attr (file-attributes (if (stringp (file-symlink-p filename))
 				       (file-symlink-p filename)
 				     filename))))
@@ -1157,8 +1157,6 @@ Returns value on success, else nil."
      (lsh (car (nth 5 src-attr)) 16)
      (cadr (nth 5 src-attr)))))
 
-
-
 (provide 'org-publish)
 
 ;; arch-tag: 72807f3c-8af0-4a6b-8dca-c3376eb25adb

+ 2 - 3
lisp/org-special-blocks.el

@@ -45,12 +45,11 @@
 by org-special-blocks.  These blocks will presumably be
 interpreted by other mechanisms.")
 
-(defvar htmlp)
-(defvar latexp)
+(defvar backend) ; dynamically scoped
 (defun org-special-blocks-make-special-cookies ()
   "Adds special cookies when #+begin_foo and #+end_foo tokens are
 seen.  This is run after a few special cases are taken care of."
-  (when (or htmlp latexp)
+  (when (or (eq backend 'html) (eq backend 'latex))
     (goto-char (point-min))
     (while (re-search-forward "^[ \t]*#\\+\\(begin\\|end\\)_\\(.*\\)$" nil t)
       (unless (org-string-match-p org-special-blocks-ignore-regexp (match-string 2))

+ 22 - 16
lisp/org-timer.el

@@ -207,22 +207,28 @@ it in the buffer."
 (defun org-timer-item (&optional arg)
   "Insert a description-type item with the current timer value."
   (interactive "P")
-  (cond
-   ;; In a timer list, insert with `org-list-insert-item-generic'.
-   ((and (org-in-item-p)
-	 (save-excursion (org-beginning-of-item) (org-at-item-timer-p)))
-    (org-list-insert-item-generic
-     (point) nil (concat (org-timer (when arg '(4)) t) ":: ")))
-   ;; In a list of another type, don't break anything: throw an error.
-   ((org-in-item-p)
-    (error "This is not a timer list"))
-   ;; Else, insert the timer correctly indented at bol.
-   (t
-    (beginning-of-line)
-    (org-indent-line-function)
-    (insert  "- ")
-    (org-timer (when arg '(4)))
-    (insert ":: "))))
+  (let ((itemp (org-in-item-p)))
+    (cond
+     ;; In a timer list, insert with `org-list-insert-item',
+     ;; then fix the list.
+     ((and itemp
+	   (save-excursion (goto-char itemp) (org-at-item-timer-p)))
+      (let* ((struct (org-list-struct))
+	     (prevs (org-list-prevs-alist struct))
+	     (s (concat (org-timer (when arg '(4)) t) ":: ")))
+	(setq struct (org-list-insert-item (point) struct prevs nil s))
+	(org-list-write-struct struct (org-list-parents-alist struct))
+	(looking-at org-list-full-item-re)
+	(goto-char (match-end 0))))
+     ;; In a list of another type, don't break anything: throw an error.
+     (itemp (error "This is not a timer list"))
+     ;; Else, start a new list.
+     (t
+      (beginning-of-line)
+      (org-indent-line-function)
+      (insert  "- ")
+      (org-timer (when arg '(4)))
+      (insert ":: ")))))
 
 (defun org-timer-fix-incomplete (hms)
   "If hms is a H:MM:SS string with missing hour or hour and minute, fix it."

+ 477 - 234
lisp/org.el

@@ -5455,14 +5455,10 @@ between words."
 This function assumes that the cursor is at the beginning of a line matched
 by `outline-regexp'.  Otherwise it returns garbage.
 If this is called at a normal headline, the level is the number of stars.
-Use `org-reduced-level' to remove the effect of `org-odd-levels'.
-For plain list items, if they are matched by `outline-regexp', this returns
-1000 plus the line indentation."
+Use `org-reduced-level' to remove the effect of `org-odd-levels'."
   (save-excursion
     (looking-at outline-regexp)
-    (if (match-beginning 1)
-	(+ (org-get-string-indentation (match-string 1)) 1000)
-      (1- (- (match-end 0) (match-beginning 0))))))
+    (1- (- (match-end 0) (match-beginning 0)))))
 
 (defvar org-font-lock-keywords nil)
 
@@ -5839,14 +5835,9 @@ in special contexts.
 			  (and limit-level (1- (* limit-level 2)))
 			limit-level)))
 	   (outline-regexp
-	    (cond
-	     ((not (org-mode-p)) outline-regexp)
-	     ((or (eq org-cycle-include-plain-lists 'integrate)
-		  (and org-cycle-include-plain-lists (org-at-item-p)))
-	      (concat "\\(?:\\*"
-		      (if nstars (format "\\{1,%d\\}" nstars) "+")
-		      " \\|\\([ \t]*\\)\\([-+*]\\|[0-9]+[.)]\\) \\)"))
-	     (t (concat "\\*" (if nstars (format "\\{1,%d\\} " nstars) "+ ")))))
+	    (if (not (org-mode-p))
+		outline-regexp
+	      (concat "\\*" (if nstars (format "\\{1,%d\\} " nstars) "+ "))))
 	   (bob-special (and org-cycle-global-at-bob (not arg) (bobp)
 			     (not (looking-at outline-regexp))))
 	   (org-cycle-hook
@@ -5871,8 +5862,8 @@ in special contexts.
 	(show-all)
 	(message "Entire buffer visible, including drawers"))
 
+       ;; Table: enter it or move to the next field.
        ((org-at-table-p 'any)
-	;; Enter the table or move to the next field in the table
 	(if (org-at-table.el-p)
 	    (message "Use C-c ' to edit table.el tables")
 	  (if arg (org-table-edit-field t)
@@ -5882,31 +5873,39 @@ in special contexts.
        ((run-hook-with-args-until-success
 	 'org-tab-after-check-for-table-hook))
 
-       ((eq arg t) ;; Global cycling
-	(org-cycle-internal-global))
+       ;; Global cycling: delegate to `org-cycle-internal-global'.
+       ((eq arg t) (org-cycle-internal-global))
 
+       ;; Drawers: delegate to `org-flag-drawer'.
        ((and org-drawers org-drawer-regexp
 	     (save-excursion
 	       (beginning-of-line 1)
 	       (looking-at org-drawer-regexp)))
-	;; Toggle block visibility
-	(org-flag-drawer
+	(org-flag-drawer ; toggle block visibility
 	 (not (get-char-property (match-end 0) 'invisible))))
 
+       ;; Show-subtree, ARG levels up from here.
        ((integerp arg)
-	;; Show-subtree, ARG levels up from here.
 	(save-excursion
 	  (org-back-to-heading)
 	  (outline-up-heading (if (< arg 0) (- arg)
 				(- (funcall outline-level) arg)))
 	  (org-show-subtree)))
 
-       ((and (save-excursion (beginning-of-line 1) (looking-at outline-regexp))
+       ;; Inline task: delegate to `org-inlinetask-toggle-visibility'.
+       ((and (featurep 'org-inlinetask)
+	     (org-inlinetask-at-task-p)
 	     (or (bolp) (not (eq org-cycle-emulate-tab 'exc-hl-bol))))
+	(org-inlinetask-toggle-visibility))
 
+       ;; At an item/headline: delegate to `org-cycle-internal-local'.
+       ((and (or (and org-cycle-include-plain-lists (org-at-item-p))
+		 (save-excursion (beginning-of-line 1)
+				 (looking-at outline-regexp)))
+	     (or (bolp) (not (eq org-cycle-emulate-tab 'exc-hl-bol))))
 	(org-cycle-internal-local))
 
-       ;; TAB emulation and template completion
+       ;; From there: TAB emulation and template completion.
        (buffer-read-only (org-back-to-heading))
 
        ((run-hook-with-args-until-success
@@ -5971,38 +5970,44 @@ in special contexts.
 
 (defun org-cycle-internal-local ()
   "Do the local cycling action."
-  (let ((goal-column 0) eoh eol eos level has-children children-skipped)
-    ;; First, some boundaries
+  (let ((goal-column 0) eoh eol eos has-children children-skipped struct)
+    ;; First, determine end of headline (EOH), end of subtree or item
+    ;; (EOS), and if item or heading has children (HAS-CHILDREN).
     (save-excursion
-      (org-back-to-heading)
-      (setq level (funcall outline-level))
-      (save-excursion
-	(beginning-of-line 2)
-	(if (or (featurep 'xemacs) (<= emacs-major-version 21))
-	    ; XEmacs does not have `next-single-char-property-change'
-	    ; I'm not sure about Emacs 21.
-	    (while (and (not (eobp)) ;; this is like `next-line'
-			(get-char-property (1- (point)) 'invisible))
-	      (beginning-of-line 2))
+      (if (org-at-item-p)
+	  (progn
+	    (beginning-of-line)
+	    (setq struct (org-list-struct))
+	    (setq eoh (point-at-eol))
+	    (setq eos (org-list-get-item-end-before-blank (point) struct))
+	    (setq has-children (org-list-has-child-p (point) struct)))
+	(org-back-to-heading)
+	(setq eoh (save-excursion (outline-end-of-heading) (point)))
+	(setq eos (save-excursion
+		    (org-end-of-subtree t)
+		    (unless (eobp)
+		      (skip-chars-forward " \t\n"))
+		    (if (eobp) (point) (1- (point)))))
+	(setq has-children
+	      (or (save-excursion
+		    (let ((level (funcall outline-level)))
+		      (outline-next-heading)
+		      (and (org-at-heading-p t)
+			   (> (funcall outline-level) level))))
+		  (save-excursion
+		    (org-list-search-forward (org-item-beginning-re) eos t)))))
+      ;; Determine end invisible part of buffer (EOL)
+      (beginning-of-line 2)
+      ;; XEmacs doesn't have `next-single-char-property-change'
+      (if (featurep 'xemacs)
 	  (while (and (not (eobp)) ;; this is like `next-line'
 		      (get-char-property (1- (point)) 'invisible))
-	    (goto-char (next-single-char-property-change (point) 'invisible))
-	    (and (eolp) (beginning-of-line 2))))
-	(setq eol (point)))
-      (outline-end-of-heading)   (setq eoh (point))
-      (save-excursion
-	(outline-next-heading)
-	(setq has-children (and (org-at-heading-p t)
-				(> (funcall outline-level) level))))
-      ;; if we're in a list, org-end-of-subtree is in fact org-end-of-item.
-      (if (org-at-item-p)
-	  (setq eos (if (and (org-end-of-item) (bolp))
-			(1- (point))
-		      (point)))
-	(org-end-of-subtree t)
-	(unless (eobp)
-	  (skip-chars-forward " \t\n"))
-	(setq eos (if (eobp) (point) (1- (point))))))
+	    (beginning-of-line 2))
+	(while (and (not (eobp)) ;; this is like `next-line'
+		    (get-char-property (1- (point)) 'invisible))
+	  (goto-char (next-single-char-property-change (point) 'invisible))
+	  (and (eolp) (beginning-of-line 2))))
+      (setq eol (point)))
     ;; Find out what to do next and set `this-command'
     (cond
      ((= eos eoh)
@@ -6021,8 +6026,22 @@ in special contexts.
 			  org-cycle-skip-children-state-if-no-children))))
       ;; Entire subtree is hidden in one line: children view
       (run-hook-with-args 'org-pre-cycle-hook 'children)
-      (org-show-entry)
-      (show-children)
+      (if (org-at-item-p)
+	  (org-list-set-item-visibility (point-at-bol) struct 'children)
+	(org-show-entry)
+	(show-children)
+	;; Fold every list in subtree to top-level items.
+	(when (eq org-cycle-include-plain-lists 'integrate)
+	  (save-excursion
+	    (org-back-to-heading)
+	    (while (org-list-search-forward (org-item-beginning-re) eos t)
+	      (beginning-of-line 1)
+	      (let* ((struct (org-list-struct))
+		     (prevs (org-list-prevs-alist struct))
+		     (end (org-list-get-bottom-point struct)))
+		(mapc (lambda (e) (org-list-set-item-visibility e struct 'folded))
+		      (org-list-get-all-items (point) struct prevs))
+		(goto-char end))))))
       (message "CHILDREN")
       (save-excursion
 	(goto-char eos)
@@ -8603,67 +8622,94 @@ according to FMT (default from `org-email-link-description-format')."
 	  "]"))
 
 (defconst org-link-escape-chars
-  '((?\    . "%20")
-    (?\[   . "%5B")
-    (?\]   . "%5D")
-    (?\340 . "%E0")  ; `a
-    (?\342 . "%E2")  ; ^a
-    (?\347 . "%E7")  ; ,c
-    (?\350 . "%E8")  ; `e
-    (?\351 . "%E9")  ; 'e
-    (?\352 . "%EA")  ; ^e
-    (?\356 . "%EE")  ; ^i
-    (?\364 . "%F4")  ; ^o
-    (?\371 . "%F9")  ; `u
-    (?\373 . "%FB")  ; ^u
-    (?\;   . "%3B")
-;;  (??    . "%3F")
-    (?=    . "%3D")
-    (?+    . "%2B")
-    )
-  "Association list of escapes for some characters problematic in links.
+  '(?\ ?\[ ?\] ?\; ?\= ?\+)
+  "List of characters that should be escaped in link.
 This is the list that is used for internal purposes.")
 
 (defvar org-url-encoding-use-url-hexify nil)
 
 (defconst org-link-escape-chars-browser
-  '((?\  . "%20")) ; 32 for the SPC char
-  "Association list of escapes for some characters problematic in links.
+  '(?\ )
+  "List of escapes for characters that are problematic in links.
 This is the list that is used before handing over to the browser.")
 
-(defun org-link-escape (text &optional table)
-  "Escape characters in TEXT that are problematic for links."
+(defun org-link-escape (text &optional table merge)
+  "Return percent escaped representation of TEXT.
+TEXT is a string with the text to escape.
+Optional argument TABLE is a list with characters that should be
+escaped.  When nil, `org-link-escape-chars' is used.
+If optional argument MERGE is set, merge TABLE into
+`org-link-escape-chars'."
   (if (and org-url-encoding-use-url-hexify (not table))
       (url-hexify-string text)
-    (setq table (or table org-link-escape-chars))
-    (when text
-      (let ((re (mapconcat (lambda (x) (regexp-quote
-					(char-to-string (car x))))
-			   table "\\|")))
-	(while (string-match re text)
-	  (setq text
-		(replace-match
-		 (cdr (assoc (string-to-char (match-string 0 text))
-			     table))
-	       t t text)))
-	text))))
-
-(defun org-link-unescape (text &optional table)
-  "Reverse the action of `org-link-escape'."
-  (if (and org-url-encoding-use-url-hexify (not table))
-      (url-unhex-string text)
-    (setq table (or table org-link-escape-chars))
-    (when text
-      (let ((case-fold-search t)
-	    (re (mapconcat (lambda (x) (regexp-quote (downcase (cdr x))))
-			   table "\\|")))
-	(while (string-match re text)
-	  (setq text
-		(replace-match
-		 (char-to-string (car (rassoc (upcase (match-string 0 text))
-					      table)))
-		 t t text)))
-	text))))
+    (cond
+     ((and table merge)
+      (mapc (lambda (defchr)
+	      (unless (member defchr table)
+		(setq table (cons defchr table)))) org-link-escape-chars))
+     ((null table)
+      (setq table org-link-escape-chars)))
+    (mapconcat
+     (lambda (char)
+       (if (or (member char table)
+	       (< char 32) (= char 37) (> char 126))
+	   (mapconcat (lambda (sequence-element)
+			(format "%%%.2X" sequence-element))
+		      (or (encode-coding-char char 'utf-8)
+			  (error "Unable to percent escape character: %s"
+				 (char-to-string char))) "")
+	 (char-to-string char))) text "")))
+
+(defun org-link-unescape (str)
+  "Unhex hexified unicode strings as returned from the JavaScript function
+encodeURIComponent. E.g. `%C3%B6' is the german Umlaut `ö'."
+  (unless (and (null str) (string= "" str))
+    (let ((pos 0) (case-fold-search t) unhexed)
+      (while (setq pos (string-match "\\(%[0-9a-f][0-9a-f]\\)+" str pos))
+	(setq unhexed (org-link-unescape-compound (match-string 0 str)))
+	(setq str (replace-match unhexed t t str))
+	(setq pos (+ pos (length unhexed))))))
+  str)
+
+(defun org-link-unescape-compound (hex)
+  "Unhexify unicode hex-chars. E.g. `%C3%B6' is the German Umlaut `ö'.
+Note: this function also decodes single byte encodings like
+`%E1' (\"á\") if not followed by another `%[A-F0-9]{2}' group."
+  (save-match-data
+    (let* ((bytes (cdr (split-string hex "%")))
+	   (ret "")
+	   (eat 0)
+	   (sum 0))
+      (while bytes
+	(let* ((val (string-to-number (pop bytes) 16))
+	       (shift-xor
+		(if (= 0 eat)
+		    (cond
+		     ((>= val 252) (cons 6 252))
+		     ((>= val 248) (cons 5 248))
+		     ((>= val 240) (cons 4 240))
+		     ((>= val 224) (cons 3 224))
+		     ((>= val 192) (cons 2 192))
+		     (t (cons 0 0)))
+		  (cons 6 128))))
+	  (if (>= val 192) (setq eat (car shift-xor)))
+	  (setq val (logxor val (cdr shift-xor)))
+	  (setq sum (+ (lsh sum (car shift-xor)) val))
+	  (if (> eat 0) (setq eat (- eat 1)))
+	  (cond
+	   ((= 0 eat)			;multi byte
+	    (setq ret (concat ret (org-char-to-string sum)))
+	    (setq sum 0))
+	   ((not bytes)			; single byte(s)
+	    (setq ret (org-link-unescape-single-byte-sequence hex))))
+	  )) ;; end (while bytes
+      ret )))
+
+(defun org-link-unescape-single-byte-sequence (hex)
+  "Unhexify hex-encoded single byte character sequences."
+  (mapconcat (lambda (byte)
+	       (char-to-string (string-to-number byte 16)))
+	     (cdr (split-string hex "%")) ""))
 
 (defun org-xor (a b)
   "Exclusive or."
@@ -11792,11 +11838,12 @@ EXTRA is additional text that will be inserted into the notes buffer."
 (defun org-skip-over-state-notes ()
   "Skip past the list of State notes in an entry."
   (if (looking-at "\n[ \t]*- State") (forward-char 1))
-  (when (org-in-item-p)
-    (let ((limit (org-list-bottom-point)))
+  (when (ignore-errors (goto-char (org-in-item-p)))
+    (let* ((struct (org-list-struct))
+	   (prevs (org-list-prevs-alist struct)))
       (while (looking-at "[ \t]*- State")
-	(goto-char (or (org-get-next-item (point) limit)
-		       (org-get-end-of-item limit)))))))
+	(goto-char (or (org-list-get-next-item (point) struct prevs)
+		       (org-list-get-item-end (point) struct)))))))
 
 (defun org-add-log-note (&optional purpose)
   "Pop up a window for taking a note, and add this note later at point."
@@ -11882,10 +11929,10 @@ EXTRA is additional text that will be inserted into the notes buffer."
 	  (end-of-line 1)
 	  (if (not (bolp)) (let ((inhibit-read-only t)) (insert "\n")))
 	  (setq ind (save-excursion
-		      (if (org-in-item-p)
-			  (progn
-			    (goto-char (org-list-top-point))
-			    (org-get-indentation))
+		      (if (ignore-errors (goto-char (org-in-item-p)))
+			  (let ((struct (org-list-struct)))
+			    (org-list-get-ind
+			     (org-list-get-top-point struct) struct))
 			(skip-chars-backward " \r\t\n")
 			(cond
 			 ((and (org-at-heading-p)
@@ -17036,7 +17083,7 @@ an outline or item heading and it has a folded subtree below it,
 this function returns t, nil otherwise."
   (let ((re (cond
 	     ((eq what 'headlines) (concat "^" org-outline-regexp))
-	     ((eq what 'items) (concat "^" (org-item-re t)))
+	     ((eq what 'items) (org-item-beginning-re))
 	     (t (error "This should not happen"))))
 	beg end)
     (save-excursion
@@ -17371,12 +17418,46 @@ This command does many different things, depending on context:
 	  (org-footnote-at-definition-p))
       (call-interactively 'org-footnote-action))
      ((org-at-item-checkbox-p)
-      (call-interactively 'org-list-repair)
-      (call-interactively 'org-toggle-checkbox)
+      ;; Use a light version of `org-toggle-checkbox' to avoid
+      ;; computing list structure twice.
+      (let* ((cbox (match-string 1))
+	     (struct (org-list-struct))
+	     (old-struct (mapcar (lambda (e) (copy-alist e)) struct))
+	     (parents (org-list-parents-alist struct))
+	     (prevs (org-list-prevs-alist struct))
+	     (orderedp (ignore-errors (org-entry-get nil "ORDERED")))
+	     block-item)
+	(org-list-set-checkbox (point-at-bol) struct
+			       (cond
+				((equal arg '(16)) "[-]")
+				((equal arg '(4)) nil)
+				((equal "[ ]" cbox) "[X]")
+				(t "[ ]")))
+	(org-list-struct-fix-ind struct parents)
+	(org-list-struct-fix-bul struct prevs)
+	(setq block-item
+	      (org-list-struct-fix-box struct parents prevs orderedp))
+	(when block-item
+	  (message
+	   "Checkboxes were removed due to unchecked box at line %d"
+	   (org-current-line block-item)))
+	(org-list-struct-apply-struct struct old-struct)
+	(org-update-checkbox-count-maybe))
       (org-list-send-list 'maybe))
      ((org-at-item-p)
-      (call-interactively 'org-list-repair)
-      (when arg (call-interactively 'org-toggle-checkbox))
+      ;; Do checkbox related actions only if function was called with
+      ;; an argument
+      (let* ((struct (org-list-struct))
+	     (old-struct (copy-tree struct))
+	     (parents (org-list-parents-alist struct))
+	     (prevs (org-list-prevs-alist struct)))
+	(org-list-struct-fix-ind struct parents)
+	(org-list-struct-fix-bul struct prevs)
+	(when arg
+	  (org-list-set-checkbox (point-at-bol) struct "[ ]")
+	  (org-list-struct-fix-box struct parents prevs))
+	(org-list-struct-apply-struct struct old-struct)
+	(when arg (org-update-checkbox-count-maybe)))
       (org-list-send-list 'maybe))
      ((save-excursion (beginning-of-line 1) (looking-at org-dblock-start-re))
       ;; Dynamic block
@@ -17428,6 +17509,18 @@ See the individual commands for more information."
    ((org-at-table-p)
     (org-table-justify-field-maybe)
     (call-interactively 'org-table-next-row))
+   ;; when `newline-and-indent' is called within a list, make sure
+   ;; text moved stays inside the item.
+   ((and (org-in-item-p) indent)
+    (if (and (org-at-item-p) (>= (point) (match-end 0)))
+	(progn
+	  (newline)
+	  (org-indent-line-to (length (match-string 0))))
+      (let ((ind (org-get-indentation)))
+	(newline)
+	(if (org-looking-back org-list-end-re)
+	    (org-indent-line-function)
+	  (org-indent-line-to ind)))))
    ((and org-return-follows-link
 	 (eq (get-text-property (point) 'face) 'org-link))
     (call-interactively 'org-open-at-point))
@@ -17474,60 +17567,97 @@ Calls `org-table-insert-hline', `org-toggle-item', or
    (t
     (call-interactively 'org-toggle-item))))
 
-(defun org-toggle-item ()
+(defun org-toggle-item (arg)
   "Convert headings or normal lines to items, items to normal lines.
 If there is no active region, only the current line is considered.
 
-If the first line in the region is a headline, convert all headlines to items.
+If the first non blank line in the region is an headline, convert
+all headlines to items.
 
-If the first line in the region is an item, convert all items to normal lines.
+If it is an item, convert all items to normal lines.
 
-If the first line is normal text, add an item bullet to each line."
-  (interactive)
+If it is normal text, change region into an item. With a prefix
+argument ARG, change each line in region into an item."
+  (interactive "P")
   (let (l2 l beg end)
     (if (org-region-active-p)
 	(setq beg (region-beginning) end (region-end))
       (setq beg (point-at-bol)
 	    end (min (1+ (point-at-eol)) (point-max))))
-    (save-excursion
-      (goto-char end)
-      (setq l2 (org-current-line))
-      (goto-char beg)
-      (beginning-of-line 1)
-      (setq l (1- (org-current-line)))
-      (if (org-at-item-p)
-	  ;; We already have items, de-itemize
-	  (while (< (setq l (1+ l)) l2)
-	    (when (org-at-item-p)
-	      (skip-chars-forward " \t")
-	      (delete-region (point) (match-end 0)))
-	    (beginning-of-line 2))
-	(if (org-on-heading-p)
-	    ;; Headings, convert to items
-	    (while (< (setq l (1+ l)) l2)
-	      (if (looking-at org-outline-regexp)
-		  (replace-match (org-list-bullet-string "-") t t))
-	      (beginning-of-line 2))
-	  ;; normal lines, turn them into items
-	  (while (< (setq l (1+ l)) l2)
-	    (unless (org-at-item-p)
-	      (if (looking-at "\\([ \t]*\\)\\(\\S-\\)")
-		  (replace-match
-		   (concat "\\1" (org-list-bullet-string "-") "\\2"))))
-	    (beginning-of-line 2)))))))
+    (org-with-limited-levels
+     (save-excursion
+       (goto-char end)
+       (setq l2 (org-current-line))
+       (goto-char beg)
+       (beginning-of-line 1)
+       ;; Ignore blank lines at beginning of region
+       (skip-chars-forward " \t\r\n")
+       (beginning-of-line 1)
+       (setq l (1- (org-current-line)))
+       (cond
+	;; Case 1. Start at an item: de-itemize.
+	((org-at-item-p)
+	 (while (< (setq l (1+ l)) l2)
+	   (when (org-at-item-p)
+	     (skip-chars-forward " \t")
+	     (delete-region (point) (match-end 0)))
+	   (beginning-of-line 2)))
+	;; Case 2. Start an an heading: convert to items.
+	((org-on-heading-p)
+	 (let* ((bul (org-list-bullet-string "-"))
+		(len (length bul))
+		(ind 0) (level 0))
+	   (while (< (setq l (1+ l)) l2)
+	     (cond
+	      ((looking-at outline-regexp)
+	       (let* ((lvl (org-reduced-level
+			    (- (length (match-string 0)) 2)))
+		      (s (concat (make-string (* len lvl) ? ) bul)))
+		 (replace-match s t t)
+		 (setq ind (length s) level lvl)))
+	      ;; Ignore blank lines and inline tasks.
+	      ((looking-at "^[ \t]*$"))
+	      ((looking-at "^\\*+ "))
+	      ;; Ensure normal text belongs to the new item.
+	      (t (org-indent-line-to (+ (max (- (org-get-indentation) level 2) 0)
+					ind))))
+	     (beginning-of-line 2))))
+	;; Case 3. Normal line with ARG: turn each of them into items
+	;;         unless they are already one.
+	(arg
+	 (while (< (setq l (1+ l)) l2)
+	   (unless (or (org-on-heading-p) (org-at-item-p))
+	     (if (looking-at "\\([ \t]*\\)\\(\\S-\\)")
+		 (replace-match
+		  (concat "\\1" (org-list-bullet-string "-") "\\2"))))
+	   (beginning-of-line 2)))
+	;; Case 4. Normal line without ARG: make the first line of
+	;;         region an item, and shift indentation of others
+	;;         lines to set them as item's body.
+	(t (let* ((bul (org-list-bullet-string "-"))
+		  (bul-len (length bul))
+		  (ref-ind (org-get-indentation)))
+	     (skip-chars-forward " \t")
+	     (insert bul)
+	     (beginning-of-line 2)
+	     (while (and (< (setq l (1+ l)) l2) (< (point) end))
+	       ;; Ensure that lines less indented than first one
+	       ;; still get included in item body.
+	       (org-indent-line-to (+ (max ref-ind (org-get-indentation))
+				      bul-len))
+	       (beginning-of-line 2)))))))))
 
 (defun org-toggle-heading (&optional nstars)
   "Convert headings to normal text, or items or text to headings.
 If there is no active region, only the current line is considered.
 
-If the first line is a heading, remove the stars from all headlines
-in the region.
+If the first non blank line is an headline, remove the stars from
+all headlines in the region.
 
-If the first line is a plain list item, turn all plain list items
-into headings.
+If it is a plain list item, turn all plain list items into headings.
 
-If the first line is a normal line, turn each and every line in the
-region into a heading.
+If it is a normal line, turn each and every normal line (i.e. not
+an heading or an item) in the region into a heading.
 
 When converting a line into a heading, the number of stars is chosen
 such that the lines become children of the current entry.  However,
@@ -17536,41 +17666,65 @@ stars to add."
   (interactive "P")
   (let (l2 l itemp beg end)
     (if (org-region-active-p)
-	(setq beg (region-beginning) end (region-end))
+	(setq beg (region-beginning) end (copy-marker (region-end)))
       (setq beg (point-at-bol)
 	    end (min (1+ (point-at-eol)) (point-max))))
-    (save-excursion
-      (goto-char end)
-      (setq l2 (org-current-line))
-      (goto-char beg)
-      (beginning-of-line 1)
-      (setq l (1- (org-current-line)))
-      (if (org-on-heading-p)
-	  ;; We already have headlines, de-star them
-	  (while (< (setq l (1+ l)) l2)
-	    (when (org-on-heading-p t)
-	      (and (looking-at outline-regexp) (replace-match "")))
-	    (beginning-of-line 2))
-	(setq itemp (org-at-item-p))
-	(let* ((stars
-		(if nstars
-		    (make-string (prefix-numeric-value current-prefix-arg)
-				 ?*)
-		  (save-excursion
-		    (if (re-search-backward org-complex-heading-regexp nil t)
-			(match-string 1) ""))))
-	       (add-stars (cond (nstars "")
-				((equal stars "") "*")
-				(org-odd-levels-only "**")
-				(t "*")))
-	       (rpl (concat stars add-stars " ")))
-	  (while (< (setq l (1+ l)) l2)
-	    (if itemp
-		(and (org-at-item-p) (replace-match rpl t t))
-	      (unless (org-on-heading-p)
-		(if (looking-at "\\([ \t]*\\)\\(\\S-\\)")
-		    (replace-match (concat rpl (match-string 2))))))
-	    (beginning-of-line 2)))))))
+    ;; Ensure inline tasks don't count as headings.
+    (org-with-limited-levels
+     (save-excursion
+       (goto-char end)
+       (setq l2 (org-current-line))
+       (goto-char beg)
+       (beginning-of-line 1)
+       ;; Ignore blank lines at beginning of region
+       (skip-chars-forward " \t\r\n")
+       (beginning-of-line 1)
+       (setq l (1- (org-current-line)))
+       (cond
+	;; Case 1. Started at an heading: de-star headings.
+	((org-on-heading-p)
+	 (while (< (setq l (1+ l)) l2)
+	   (when (org-on-heading-p t)
+	     (looking-at outline-regexp) (replace-match ""))
+	   (beginning-of-line 2)))
+	;; Case 2. Started at an item: change items into headlines.
+	((org-at-item-p)
+	 (let ((stars (make-string
+		       (if nstars
+			   (prefix-numeric-value current-prefix-arg)
+			 (or (org-current-level) 0))
+		       ?*)))
+	   (while (< (point) end)
+	     (when (org-at-item-p)
+	       ;; Pay attention to cases when region ends before list.
+	       (let* ((struct (org-list-struct))
+		      (list-end (min (org-list-get-bottom-point struct) end)))
+		 (save-restriction
+		   (narrow-to-region (point) list-end)
+		   (insert
+		    (org-list-to-subtree
+		     (org-list-parse-list t)
+		     '(:istart (concat stars (funcall get-stars depth))
+			       :icount (concat stars
+					       (funcall get-stars depth))))))))
+	     (beginning-of-line 2))))
+	;; Case 3. Started at normal text: make every line an heading,
+	;;         skipping headlines and items.
+	(t (let* ((stars (make-string
+			  (if nstars
+			      (prefix-numeric-value current-prefix-arg)
+			    (or (org-current-level) 0))
+			  ?*))
+		  (add-stars (cond (nstars "")
+				   ((equal stars "") "*")
+				   (org-odd-levels-only "**")
+				   (t "*")))
+		  (rpl (concat stars add-stars " ")))
+	     (while (< (setq l (1+ l)) l2)
+	       (unless (or (org-on-heading-p) (org-at-item-p))
+		 (when (looking-at "\\([ \t]*\\)\\(\\S-\\)")
+		   (replace-match (concat rpl (match-string 2)))))
+	       (beginning-of-line 2)))))))))
 
 (defun org-meta-return (&optional arg)
   "Insert a new heading or wrap a region in a table.
@@ -18126,6 +18280,17 @@ When LINE is given, assume it represents a line and compute its indentation."
       (skip-chars-forward " \t")
       (current-column))))
 
+(defun org-get-string-indentation (s)
+  "What indentation has S due to SPACE and TAB at the beginning of the string?"
+  (let ((n -1) (i 0) (w tab-width) c)
+    (catch 'exit
+      (while (< (setq n (1+ n)) (length s))
+	(setq c (aref s n))
+	(cond ((= c ?\ ) (setq i (1+ i)))
+	      ((= c ?\t) (setq i (* (/ (+ w i) w) w)))
+	      (t (throw 'exit t)))))
+    i))
+
 (defun org-remove-tabs (s &optional width)
   "Replace tabulators in S with spaces.
 Assumes that s is a single line, starting in column 0."
@@ -18724,7 +18889,9 @@ If point is in an inline task, mark that task instead."
 	 (org-drawer-regexp (or org-drawer-regexp "\000"))
 	 (inline-task-p (and (featurep 'org-inlinetask)
 			     (org-inlinetask-in-task-p)))
-	 column bpos bcol tpos tcol)
+	 (inline-re (and inline-task-p
+			 (org-inlinetask-outline-regexp)))
+	 column)
     (beginning-of-line 1)
     (cond
      ;; Comments
@@ -18756,30 +18923,31 @@ If point is in an inline task, mark that task instead."
 		(org-get-indentation)
 	      (org-get-indentation (match-string 0)))))
      ;; Lists
-     ((org-in-item-p)
-      (org-beginning-of-item)
-      (looking-at "[ \t]*\\(\\S-+\\)[ \t]*\\(\\(:?\\[@\\(:?start:\\)?[0-9]+\\][ \t]*\\)?\\[[- X]\\][ \t]*\\|.*? :: \\)?")
-      (setq bpos (match-beginning 1) tpos (match-end 0)
-	    bcol (progn (goto-char bpos) (current-column))
-	    tcol (progn (goto-char tpos) (current-column)))
-      (if (> tcol (+ bcol org-description-max-indent))
-	  (setq tcol (+ bcol 5)))
-      (goto-char pos)
-      (setq column (if itemp (org-get-indentation) tcol)))
+     ((ignore-errors (goto-char (org-in-item-p)))
+      (setq column (if itemp
+		       (org-get-indentation)
+		     (org-list-item-body-column (point))))
+      (goto-char pos))
      ;; This line has nothing special, look at the previous relevant
      ;; line to compute indentation
      (t
       (beginning-of-line 0)
       (while (and (not (bobp))
 		  (not (looking-at org-drawer-regexp))
-		  ;; skip comments, verbatim, empty lines, tables,
-		  ;; inline tasks, lists, drawers and blocks
+		  ;; When point started in an inline task, do not move
+		  ;; above task starting line.
+		  (not (and inline-task-p
+			    (looking-at inline-re)))
+		  ;; Skip comments, verbatim, empty lines, tables,
+		  ;; inline tasks, lists, drawers and blocks.
 		  (or (and (looking-at "[ \t]*:END:")
 			   (re-search-backward org-drawer-regexp nil t))
 		      (and (looking-at "[ \t]*#\\+end_")
 			   (re-search-backward "[ \t]*#\\+begin_"nil t))
 		      (looking-at "[ \t]*[\n:#|]")
-		      (and (org-in-item-p) (goto-char (org-list-top-point)))
+		      (and (ignore-errors (goto-char (org-in-item-p)))
+			   (goto-char
+			    (org-list-get-top-point (org-list-struct))))
 		      (and (not inline-task-p)
 			   (featurep 'org-inlinetask)
 			   (org-inlinetask-in-task-p)
@@ -18835,7 +19003,7 @@ the functionality can be provided as a fall-back.")
     "[ 	]*$" "\\|"
     "\\*+ " "\\|"
     "[ \t]*#" "\\|"
-    "[ \t]*\\([-+*][ \t]+\\|[0-9]+[.)][ \t]+\\)" "\\|"
+    (org-item-re) "\\|"
     "[ \t]*[:|]" "\\|"
     "\\$\\$" "\\|"
     "\\\\\\(begin\\|end\\|[][]\\)"))
@@ -18861,6 +19029,7 @@ the functionality can be provided as a fall-back.")
     (org-set-local 'org-adaptive-fill-regexp-backup
                    adaptive-fill-regexp))
   (org-set-local 'adaptive-fill-regexp "\000")
+  (org-set-local 'normal-auto-fill-function 'org-auto-fill-function)
   (org-set-local 'adaptive-fill-function
 		 'org-adaptive-fill-function)
   (org-set-local
@@ -18872,42 +19041,116 @@ the functionality can be provided as a fall-back.")
 (defun org-fill-paragraph (&optional justify)
   "Re-align a table, pass through to fill-paragraph if no table."
   (let ((table-p (org-at-table-p))
-	(table.el-p (org-at-table.el-p)))
+	(table.el-p (org-at-table.el-p))
+	(itemp (org-in-item-p)))
     (cond ((and (equal (char-after (point-at-bol)) ?*)
 		(save-excursion (goto-char (point-at-bol))
 				(looking-at outline-regexp)))
-	   t)					     ; skip headlines
-	  (table.el-p t)			     ; skip table.el tables
-	  (table-p (org-table-align) t)		     ; align org-mode tables
-	  (t nil))))				     ; call paragraph-fill
+	   t)				; skip headlines
+	  (table.el-p t)		; skip table.el tables
+	  (table-p (org-table-align) t)	; align Org tables
+	  (itemp			; align text in items
+	   (let* ((struct (save-excursion (goto-char itemp)
+					  (org-list-struct)))
+		  (parents (org-list-parents-alist struct))
+		  (children (org-list-get-children itemp struct parents))
+		  beg end prev next prefix)
+	     ;; Determine in which part of item point is: before
+	     ;; first child, after last child, between two
+	     ;; sub-lists, or simply in item if there's no child.
+	     (cond
+	      ((not children)
+	       (setq prefix (make-string (org-list-item-body-column itemp) ?\ )
+		     beg itemp
+		     end (org-list-get-item-end itemp struct)))
+	      ((< (point) (setq next (car children)))
+	       (setq prefix (make-string (org-list-item-body-column itemp) ?\ )
+		     beg itemp
+		     end next))
+	      ((> (point) (setq prev (car (last children))))
+	       (setq beg (org-list-get-item-end prev struct)
+		     end (org-list-get-item-end itemp struct)
+		     prefix (save-excursion
+			      (goto-char beg)
+			      (skip-chars-forward " \t")
+			      (make-string (current-column) ?\ ))))
+	      (t (catch 'exit
+		   (while (setq next (pop children))
+		     (if (> (point) next)
+			 (setq prev next)
+		       (setq beg (org-list-get-item-end prev struct)
+			     end next
+			     prefix (save-excursion
+				      (goto-char beg)
+				      (skip-chars-forward " \t")
+				      (make-string (current-column) ?\ )))
+		       (throw 'exit nil))))))
+	     ;; Use `fill-paragraph' with buffer narrowed to item
+	     ;; without any child, and with our computed PREFIX.
+	     (flet ((fill-context-prefix (from to &optional flr) prefix))
+	       (save-restriction
+		 (narrow-to-region beg end)
+		 (save-excursion (fill-paragraph justify)))) t))
+	  ;; Special case where point is not in a list but is on a
+	  ;; paragraph adjacent to a list: make sure this paragraph
+	  ;; doesn't get merged with the end of the list by narrowing
+	  ;; buffer first.
+	  ((save-excursion
+	     (fill-forward-paragraph -1)
+	     (setq itemp (org-in-item-p)))
+	   (save-excursion
+	     (goto-char itemp)
+	     (setq struct (org-list-struct)))
+	   (save-restriction
+	     (narrow-to-region (org-list-get-bottom-point struct)
+			       (save-excursion
+				 (fill-forward-paragraph 1)
+				 (point)))
+	     (fill-paragraph justify) t))
+	  (t nil))))			; call `fill-paragraph'
 
 ;; For reference, this is the default value of adaptive-fill-regexp
 ;;  "[ \t]*\\([-|#;>*]+[ \t]*\\|(?[0-9]+[.)][ \t]*\\)*"
 
 (defun org-adaptive-fill-function ()
-  "Return a fill prefix for org-mode files.
-In particular, this makes sure hanging paragraphs for hand-formatted lists
-work correctly."
-  (cond
-   ;; Comment line
-   ((looking-at "#[ \t]+")
-    (match-string-no-properties 0))
-   ;; Description list
-	((looking-at "[ \t]*\\([-*+] .*? :: \\)")
-	 (save-excursion
-	   (if (> (match-end 1) (+ (match-beginning 1)
-				   org-description-max-indent))
-	       (goto-char (+ (match-beginning 1) 5))
-	     (goto-char (match-end 0)))
-	   (make-string (current-column) ?\ )))
-    ;; Ordered or unordered list
-	((looking-at "[ \t]*\\([-*+] \\|[0-9]+[.)]  ?\\)")
-	 (save-excursion
-	   (goto-char (match-end 0))
-	   (make-string (current-column) ?\ )))
-    ;; Other text
-    ((looking-at org-adaptive-fill-regexp-backup)
-     (match-string-no-properties 0))))
+  "Return a fill prefix for org-mode files."
+  (let (itemp)
+    (save-excursion
+      (cond
+       ;; Comment line
+       ((looking-at "#[ \t]+")
+	(match-string-no-properties 0))
+       ;; Point is in a list after `backward-paragraph': original
+       ;; point wasn't in the list, or filling would have been taken
+       ;; care of by `org-auto-fill-function', but the list and the
+       ;; real paragraph are not separated by a blank line. Thus, move
+       ;; point after the list to go back to real paragraph and
+       ;; determine fill-prefix. If point is at an item, do not
+       ;; compute prefix and list structure, as first line of
+       ;; paragraph will be skipped anyway.
+       ((org-at-item-p) "")
+       ((setq itemp (org-in-item-p))
+	(goto-char itemp)
+	(let* ((struct (org-list-struct))
+	       (bottom (org-list-get-bottom-point struct)))
+	  (goto-char bottom)
+	  (make-string (org-get-indentation) ?\ )))
+       ;; Other text
+       ((looking-at org-adaptive-fill-regexp-backup)
+	(match-string-no-properties 0))))))
+
+(defun org-auto-fill-function ()
+  "Auto-fill function."
+  (let (itemp prefix)
+    ;; When in a list, compute an appropriate fill-prefix and make
+    ;; sure it will be used by `do-auto-fill'.
+    (if (setq itemp (org-in-item-p))
+	(progn
+	  (setq prefix (make-string (org-list-item-body-column itemp) ?\ ))
+	  (flet ((fill-context-prefix (from to &optional flr) prefix))
+	    (do-auto-fill)))
+      ;; Else just use `do-auto-fill'.
+      (do-auto-fill))))
 
 ;;; Other stuff.
 
@@ -19030,12 +19273,12 @@ beyond the end of the headline."
        ((org-at-item-p)
 	(goto-char
 	 (if (eq special t)
-	     (cond ((> pos (match-end 4)) (match-end 4))
-		   ((= pos (point)) (match-end 4))
+	     (cond ((> pos (match-end 0)) (match-end 0))
+		   ((= pos (point)) (match-end 0))
 		   (t (point)))
 	   (cond ((> pos (point)) (point))
 		 ((not (eq last-command this-command)) (point))
-		 (t (match-end 4))))))))
+		 (t (match-end 0))))))))
     (org-no-warnings
      (and (featurep 'xemacs) (setq zmacs-region-stays t)))))
 

部分文件因为文件数量过多而无法显示