]> code.delx.au - gnu-emacs/commitdiff
2009-01-31 Carsten Dominik <carsten.dominik@gmail.com>
authorCarsten Dominik <dominik@science.uva.nl>
Sat, 31 Jan 2009 05:28:36 +0000 (05:28 +0000)
committerCarsten Dominik <dominik@science.uva.nl>
Sat, 31 Jan 2009 05:28:36 +0000 (05:28 +0000)
* org.el (org-enforce-todo-checkbox-dependencies): New option.
(org-block-todo-from-checkboxes): New function.
(org-todo): Make tripple prefix arg circumvent blocking.

34 files changed:
lisp/org/ChangeLog
lisp/org/org-agenda.el
lisp/org/org-archive.el
lisp/org/org-attach.el
lisp/org/org-bbdb.el
lisp/org/org-bibtex.el
lisp/org/org-clock.el
lisp/org/org-colview.el
lisp/org/org-compat.el
lisp/org/org-exp.el
lisp/org/org-export-latex.el
lisp/org/org-faces.el
lisp/org/org-footnote.el
lisp/org/org-gnus.el
lisp/org/org-id.el
lisp/org/org-info.el
lisp/org/org-irc.el
lisp/org/org-jsinfo.el
lisp/org/org-list.el
lisp/org/org-mac-message.el
lisp/org/org-macs.el
lisp/org/org-mew.el
lisp/org/org-mhe.el
lisp/org/org-mouse.el
lisp/org/org-plot.el
lisp/org/org-publish.el
lisp/org/org-remember.el
lisp/org/org-rmail.el
lisp/org/org-table.el
lisp/org/org-timer.el
lisp/org/org-vm.el
lisp/org/org-w3m.el
lisp/org/org-wl.el
lisp/org/org.el

index 150234e1be6e2b66ff31fc752246285947664b85..ed9864385e1e0959ec6bb3aafb8133cd631ec249 100644 (file)
@@ -1,3 +1,9 @@
+2009-01-31  Carsten Dominik  <carsten.dominik@gmail.com>
+
+       * org.el (org-enforce-todo-checkbox-dependencies): New option.
+       (org-block-todo-from-checkboxes): New function.
+       (org-todo): Make tripple prefix arg circumvent blocking.
+
 2009-01-30  Glenn Morris  <rgm@gnu.org>
 
        * org-list.el (org-empty-line-terminates-plain-lists)
index c84c7a72f0b4a504e7745eafc4d67180e4d687c7..26821803198346635029661a287544a9756c8a26 100644 (file)
@@ -6,7 +6,7 @@
 ;; Author: Carsten Dominik <carsten at orgmode dot org>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: http://orgmode.org
-;; Version: 6.20g
+;; Version: 6.20h
 ;;
 ;; This file is part of GNU Emacs.
 ;;
index bee2fa09f89f3a70c546e7fc80880115977e9088..680d17102a980657b1ef68b472e137ae69a2a26d 100644 (file)
@@ -6,7 +6,7 @@
 ;; Author: Carsten Dominik <carsten at orgmode dot org>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: http://orgmode.org
-;; Version: 6.20g
+;; Version: 6.20h
 ;;
 ;; This file is part of GNU Emacs.
 ;;
index 2d4229b09dc131ace0c4ce28ee7ae491cd94636e..28c1df021ead32a80ef5ceed277d2426e2657adb 100644 (file)
@@ -4,7 +4,7 @@
 
 ;; Author: John Wiegley <johnw@newartisans.com>
 ;; Keywords: org data task
-;; Version: 6.20g
+;; Version: 6.20h
 
 ;; This file is part of GNU Emacs.
 ;;
index 58fc0dd019cc658878de0b2f3a5b083eb309a8f7..5a816d34c021c86619d33bd246b9209a98e79634 100644 (file)
@@ -7,7 +7,7 @@
 ;;         Thomas Baumann <thomas dot baumann at ch dot tum dot de>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: http://orgmode.org
-;; Version: 6.20g
+;; Version: 6.20h
 ;;
 ;; This file is part of GNU Emacs.
 ;;
index 0392cfeaaa2a8bfc1df8615099cdf092ab9fe852..7f63b839d0d21023291ccf315a5dbaaf44ccdf54 100644 (file)
@@ -5,7 +5,7 @@
 ;; Author: Bastien Guerry <bzg at altern dot org>
 ;;         Carsten Dominik <carsten dot dominik at gmail dot com>
 ;; Keywords: org, wp, remember
-;; Version: 6.20g
+;; Version: 6.20h
 ;;
 ;; This file is part of GNU Emacs.
 ;;
index 170cb53a1283a7462d1b0ec28339b83b2ef8337e..e1decc08b99a8a7491a09851b0f15e55f6e37a9a 100644 (file)
@@ -6,7 +6,7 @@
 ;; Author: Carsten Dominik <carsten at orgmode dot org>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: http://orgmode.org
-;; Version: 6.20g
+;; Version: 6.20h
 ;;
 ;; This file is part of GNU Emacs.
 ;;
index 94785ce776516d7205a86eea2230e9c2eb1ebf9a..e60fd8cd6b256c7cc16ae3f09adc8adfff46b739 100644 (file)
@@ -6,7 +6,7 @@
 ;; Author: Carsten Dominik <carsten at orgmode dot org>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: http://orgmode.org
-;; Version: 6.20g
+;; Version: 6.20h
 ;;
 ;; This file is part of GNU Emacs.
 ;;
index 6c5acbbec3b2f847dd618fba8d6cc8731e143e75..09ee0ee230d11c86c599271e1a9d639175cb5319 100644 (file)
@@ -6,7 +6,7 @@
 ;; Author: Carsten Dominik <carsten at orgmode dot org>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: http://orgmode.org
-;; Version: 6.20g
+;; Version: 6.20h
 ;;
 ;; This file is part of GNU Emacs.
 ;;
index a9fb6ecda5e2b6c8797222fa10d29a36840934b5..47406fd35256693327346ac4a3d3b853c0ff5def 100644 (file)
@@ -6,7 +6,7 @@
 ;; Author: Carsten Dominik <carsten at orgmode dot org>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: http://orgmode.org
-;; Version: 6.20g
+;; Version: 6.20h
 ;;
 ;; This file is part of GNU Emacs.
 ;;
index 7e0c929ca4b83fdbbf4243daf7334aa0de4c5988..eef75c5b69e6e10791888c57fbf9d4b35b9c04cf 100644 (file)
@@ -4,7 +4,7 @@
 ;;
 ;; Emacs Lisp Archive Entry
 ;; Filename: org-export-latex.el
-;; Version: 6.20g
+;; Version: 6.20h
 ;; Author: Bastien Guerry <bzg AT altern DOT org>
 ;; Maintainer: Bastien Guerry <bzg AT altern DOT org>
 ;; Keywords: org, wp, tex
index f6548d03580af649272b4f83eb830059dc2ecd39..64bc5590684303e4ad3e9edbb5e4f30353e85fa5 100644 (file)
@@ -6,7 +6,7 @@
 ;; Author: Carsten Dominik <carsten at orgmode dot org>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: http://orgmode.org
-;; Version: 6.20g
+;; Version: 6.20h
 ;;
 ;; This file is part of GNU Emacs.
 ;;
index 7ea076db4b36f75279ea6de2df8fb6840a4fd7dd..89bc2ea64df3321df213bbc380c461026921cee9 100644 (file)
@@ -5,7 +5,7 @@
 ;; Author: Carsten Dominik <carsten at orgmode dot org>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: http://orgmode.org
-;; Version: 6.20g
+;; Version: 6.20h
 ;;
 ;; This file is part of GNU Emacs.
 ;;
index 2a6aa0f34fcc4250be7ba54ea8faa0d5ae2016af..61fa15cff0149825ebf63e4e1960ca79404dd1fc 100644 (file)
@@ -7,7 +7,7 @@
 ;;         Tassilo Horn <tassilo at member dot fsf dot org>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: http://orgmode.org
-;; Version: 6.20g
+;; Version: 6.20h
 ;;
 ;; This file is part of GNU Emacs.
 ;;
index 6ab4a54628943237c90ec3945e32f2291fdcc6ed..16ffe8cf7a4b4b92439499fcfec497b457f55f95 100644 (file)
@@ -5,7 +5,7 @@
 ;; Author: Carsten Dominik <carsten at orgmode dot org>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: http://orgmode.org
-;; Version: 6.20g
+;; Version: 6.20h
 ;;
 ;; This file is part of GNU Emacs.
 ;;
index 025145942bc6f67f5bf0d940a8cf0586c708791c..32699314af5ce78f38bed41105e0fa12144893dc 100644 (file)
@@ -6,7 +6,7 @@
 ;; Author: Carsten Dominik <carsten at orgmode dot org>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: http://orgmode.org
-;; Version: 6.20g
+;; Version: 6.20h
 ;;
 ;; This file is part of GNU Emacs.
 ;;
index cd3b02fd9c902bcbd0f2fae6675e56993ca63d15..0d4fc4e9bdcf882bb582e3d0c44d7b61b4799769 100644 (file)
@@ -4,7 +4,7 @@
 ;;
 ;; Author: Philip Jackson <emacs@shellarchive.co.uk>
 ;; Keywords: erc, irc, link, org
-;; Version: 6.20g
+;; Version: 6.20h
 ;;
 ;; This file is part of GNU Emacs.
 ;;
index 172592be42d2c916a54c5b303e1e27f09c54ce91..748e54ca1dd754188269a035e8b37b36e91d23a0 100644 (file)
@@ -6,7 +6,7 @@
 ;; Author: Carsten Dominik <carsten at orgmode dot org>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: http://orgmode.org
-;; Version: 6.20g
+;; Version: 6.20h
 ;;
 ;; This file is part of GNU Emacs.
 ;;
index 60378e55b3311e626c30663c242d9b47ce58cc8d..b3efae6a55da38f6bada0ed8c948997f4f540374 100644 (file)
@@ -7,7 +7,7 @@
 ;;        Bastien Guerry <bzg AT altern DOT org>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: http://orgmode.org
-;; Version: 6.20g
+;; Version: 6.20h
 ;;
 ;; This file is part of GNU Emacs.
 ;;
index 6b068382e82cf2e283c75f81279d55e109a42764..5e05899f32f30fa6e3f7a0a8a89e18c2d70983d4 100644 (file)
@@ -3,7 +3,7 @@
 ;; Copyright (C) 2008, 2009 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
-;; Version: 6.20g
+;; Version: 6.20h
 ;; Keywords: outlines, hypermedia, calendar, wp
 
 ;; This file is part of GNU Emacs.
index 87f44c6b095dd7336b5423c5777686317039423c..1042a88f8f19bd9d72a087e781f9fed8c17e103d 100644 (file)
@@ -6,7 +6,7 @@
 ;; Author: Carsten Dominik <carsten at orgmode dot org>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: http://orgmode.org
-;; Version: 6.20g
+;; Version: 6.20h
 ;;
 ;; This file is part of GNU Emacs.
 ;;
index 329a47f84c1fd4c4b60f1bafd18120f2f28a8653..79a1279498e4585dbc72b33cd34e1674b9a9d053 100644 (file)
@@ -5,7 +5,7 @@
 ;; Author: Tokuya Kameshima <kames at fa2 dot so-net dot ne dot jp>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: http://orgmode.org
-;; Version: 6.20g
+;; Version: 6.20h
 
 ;; This file is part of GNU Emacs.
 
index b8faeb34751dbd73ff40ecafb0f5ce77a31e0456..a654fb5767c51367070829aec26bb010ae8906ab 100644 (file)
@@ -6,7 +6,7 @@
 ;; Author: Thomas Baumann <thomas dot baumann at ch dot tum dot de>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: http://orgmode.org
-;; Version: 6.20g
+;; Version: 6.20h
 ;;
 ;; This file is part of GNU Emacs.
 ;;
index c291fa36a5aa8b70e1db45343c45777bd7397361..4927fff4284a4fefcac350651042e421c990c68c 100644 (file)
@@ -4,7 +4,7 @@
 ;;
 ;; Author: Piotr Zielinski <piotr dot zielinski at gmail dot com>
 ;; Maintainer: Carsten Dominik <carsten at orgmode dot org>
-;; Version: 6.20g
+;; Version: 6.20h
 ;;
 ;; This file is part of GNU Emacs.
 ;;
index 392f0b2eac6c6f0e79099abae0aa99311d43df6e..5da3bcaaa176b0109023fa9792edf6b6a815fe6e 100644 (file)
@@ -5,7 +5,7 @@
 ;; Author: Eric Schulte <schulte dot eric at gmail dot com>
 ;; Keywords: tables, plotting
 ;; Homepage: http://orgmode.org
-;; Version: 6.20g
+;; Version: 6.20h
 ;;
 ;; This file is part of GNU Emacs.
 ;;
index 8d44521ebae674a84d8582ae42c84e1af7bcf244..2a70e1062cb85db4892773047a8054ac201ceec7 100644 (file)
@@ -4,7 +4,7 @@
 ;; Author: David O'Toole <dto@gnu.org>
 ;; Maintainer: Bastien Guerry <bzg AT altern DOT org>
 ;; Keywords: hypermedia, outlines, wp
-;; Version: 6.20g
+;; Version: 6.20h
 
 ;; This file is part of GNU Emacs.
 ;;
index f6d07691eb3349aeedd17915b3023db0109acb12..13f746cdfba3d89abf1e2aaccafa5fe22e751074 100644 (file)
@@ -6,7 +6,7 @@
 ;; Author: Carsten Dominik <carsten at orgmode dot org>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: http://orgmode.org
-;; Version: 6.20g
+;; Version: 6.20h
 ;;
 ;; This file is part of GNU Emacs.
 ;;
index 068f4fe9707c9846d61f1a6f18deb60d20ac167a..e57114f4cb2d00cd7a9ff4ae7d22a50ce93c5941 100644 (file)
@@ -6,7 +6,7 @@
 ;; Author: Carsten Dominik <carsten at orgmode dot org>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: http://orgmode.org
-;; Version: 6.20g
+;; Version: 6.20h
 ;;
 ;; This file is part of GNU Emacs.
 ;;
index 458be555fdca1bb3888476513582237acef6b32c..20080aeca39c6ff3847cf5940402a9769703c53b 100644 (file)
@@ -6,7 +6,7 @@
 ;; Author: Carsten Dominik <carsten at orgmode dot org>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: http://orgmode.org
-;; Version: 6.20g
+;; Version: 6.20h
 ;;
 ;; This file is part of GNU Emacs.
 ;;
index a06a157dc14c339ad68e58109e67b2d5582bcb3b..c70563762d4213221bd6e46af01fe336408b1995 100644 (file)
@@ -5,7 +5,7 @@
 ;; Author: Carsten Dominik <carsten at orgmode dot org>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: http://orgmode.org
-;; Version: 6.20g
+;; Version: 6.20h
 ;;
 ;; This file is part of GNU Emacs.
 ;;
index 191e4006612b74d43e3c2a69238f2c776900e196..74c42fc8f9629b31a7ae067a9d661917339a3d0f 100644 (file)
@@ -6,7 +6,7 @@
 ;; Author: Carsten Dominik <carsten at orgmode dot org>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: http://orgmode.org
-;; Version: 6.20g
+;; Version: 6.20h
 ;;
 ;; This file is part of GNU Emacs.
 ;;
index d6ab9185b87fd7e6e125a152ba4d9edebbfd260c..beded70fd91010bb1ef427bddd590190599e3ba9 100644 (file)
@@ -5,7 +5,7 @@
 ;; Author: Andy Stewart <lazycat dot manatee at gmail dot com>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: http://orgmode.org
-;; Version: 6.20g
+;; Version: 6.20h
 ;;
 ;; This file is part of GNU Emacs.
 ;;
index 1de5c3a621607bdbb45a693863cc9900c8fd47cf..83b4ef54eb5c9575a704c4c7bd23eb5502e415f0 100644 (file)
@@ -6,7 +6,7 @@
 ;; Author: Tokuya Kameshima <kames at fa2 dot so-net dot ne dot jp>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: http://orgmode.org
-;; Version: 6.20g
+;; Version: 6.20h
 ;;
 ;; This file is part of GNU Emacs.
 ;;
index 956a4f529c71a7a36c7f24bc8f807f02e1946e9f..ff0451f377611357627271713d69100124b89008 100644 (file)
@@ -6,7 +6,7 @@
 ;; Author: Carsten Dominik <carsten at orgmode dot org>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: http://orgmode.org
-;; Version: 6.20g
+;; Version: 6.20h
 ;;
 ;; This file is part of GNU Emacs.
 ;;
@@ -94,7 +94,7 @@
 
 ;;; Version
 
-(defconst org-version "6.20g"
+(defconst org-version "6.20h"
   "The version number of the file org.el.")
 
 (defun org-version (&optional here)
@@ -1641,8 +1641,27 @@ restart emacs after changing the value."
   :set (lambda (var val)
         (set var val)
         (if val
-            (add-hook 'org-blocker-hook 'org-block-todo-from-children-or-siblings)
-          (remove-hook 'org-blocker-hook 'org-block-todo-from-children-or-siblings)))
+            (add-hook 'org-blocker-hook
+                      'org-block-todo-from-children-or-siblings)
+          (remove-hook 'org-blocker-hook
+                       'org-block-todo-from-children-or-siblings)))
+  :group 'org-todo
+  :type 'boolean)
+
+(defcustom org-enforce-todo-checkbox-dependencies nil
+  "Non-nil means, unchecked boxes will block switching the parent to DONE.
+When this is nil, checkboxes have no influence on switching TODO states.
+When non-nil, you first need to check off all check boxes before the TODO
+entry can be switched to DONE.
+You need to set this variable through the customize interface, or to
+restart emacs after changing the value."
+  :set (lambda (var val)
+        (set var val)
+        (if val
+            (add-hook 'org-blocker-hook
+                      'org-block-todo-from-checkboxes)
+          (remove-hook 'org-blocker-hook
+                       'org-block-todo-from-checkboxes)))
   :group 'org-todo
   :type 'boolean)
 
@@ -8332,6 +8351,7 @@ DONE are present, add TODO at the beginning of the heading.
 With C-u prefix arg, use completion to determine the new state.
 With numeric prefix arg, switch to that state.
 With a double C-u prefix, switch to the next set of TODO keywords (nextset).
+With a tripple C-u prefix, circumvent any state blocking.
 
 For calling through lisp, arg is also interpreted in the following way:
 'none             -> empty state
@@ -8343,169 +8363,176 @@ For calling through lisp, arg is also interpreted in the following way:
                      really is a member of `org-todo-keywords'."
   (interactive "P")
   (if (equal arg '(16)) (setq arg 'nextset))
-  (save-excursion
-    (catch 'exit
-      (org-back-to-heading)
-      (if (looking-at outline-regexp) (goto-char (1- (match-end 0))))
-      (or (looking-at (concat " +" org-todo-regexp " *"))
-         (looking-at " *"))
-      (let* ((match-data (match-data))
-            (startpos (point-at-bol))
-            (logging (save-match-data (org-entry-get nil "LOGGING" t)))
-            (org-log-done org-log-done)
-            (org-log-repeat org-log-repeat)
-            (org-todo-log-states org-todo-log-states)
-            (this (match-string 1))
-            (hl-pos (match-beginning 0))
-            (head (org-get-todo-sequence-head this))
-            (ass (assoc head org-todo-kwd-alist))
-            (interpret (nth 1 ass))
-            (done-word (nth 3 ass))
-            (final-done-word (nth 4 ass))
-            (last-state (or this ""))
-            (completion-ignore-case t)
-            (member (member this org-todo-keywords-1))
-            (tail (cdr member))
-            (state (cond
-                    ((and org-todo-key-trigger
-                          (or (and (equal arg '(4)) (eq org-use-fast-todo-selection 'prefix))
-                              (and (not arg) org-use-fast-todo-selection
-                                   (not (eq org-use-fast-todo-selection 'prefix)))))
-                     ;; Use fast selection
-                     (org-fast-todo-selection))
-                    ((and (equal arg '(4))
-                          (or (not org-use-fast-todo-selection)
-                              (not org-todo-key-trigger)))
-                     ;; Read a state with completion
-                     (org-ido-completing-read "State: " (mapcar (lambda(x) (list x))
-                                                        org-todo-keywords-1)
-                                      nil t))
-                    ((eq arg 'right)
-                     (if this
-                         (if tail (car tail) nil)
-                       (car org-todo-keywords-1)))
-                    ((eq arg 'left)
-                     (if (equal member org-todo-keywords-1)
-                         nil
+  (let ((org-blocker-hook org-blocker-hook))
+    (when (equal arg '(64))
+      (setq arg nil org-blocker-hook nil))
+    (save-excursion
+      (catch 'exit
+       (org-back-to-heading)
+       (if (looking-at outline-regexp) (goto-char (1- (match-end 0))))
+       (or (looking-at (concat " +" org-todo-regexp " *"))
+           (looking-at " *"))
+       (let* ((match-data (match-data))
+              (startpos (point-at-bol))
+              (logging (save-match-data (org-entry-get nil "LOGGING" t)))
+              (org-log-done org-log-done)
+              (org-log-repeat org-log-repeat)
+              (org-todo-log-states org-todo-log-states)
+              (this (match-string 1))
+              (hl-pos (match-beginning 0))
+              (head (org-get-todo-sequence-head this))
+              (ass (assoc head org-todo-kwd-alist))
+              (interpret (nth 1 ass))
+              (done-word (nth 3 ass))
+              (final-done-word (nth 4 ass))
+              (last-state (or this ""))
+              (completion-ignore-case t)
+              (member (member this org-todo-keywords-1))
+              (tail (cdr member))
+              (state (cond
+                      ((and org-todo-key-trigger
+                            (or (and (equal arg '(4))
+                                     (eq org-use-fast-todo-selection 'prefix))
+                                (and (not arg) org-use-fast-todo-selection
+                                     (not (eq org-use-fast-todo-selection
+                                              'prefix)))))
+                       ;; Use fast selection
+                       (org-fast-todo-selection))
+                      ((and (equal arg '(4))
+                            (or (not org-use-fast-todo-selection)
+                                (not org-todo-key-trigger)))
+                       ;; Read a state with completion
+                       (org-ido-completing-read
+                        "State: " (mapcar (lambda(x) (list x))
+                                          org-todo-keywords-1)
+                        nil t))
+                      ((eq arg 'right)
                        (if this
-                           (nth (- (length org-todo-keywords-1) (length tail) 2)
-                                org-todo-keywords-1)
-                         (org-last org-todo-keywords-1))))
-                    ((and (eq org-use-fast-todo-selection t) (equal arg '(4))
-                          (setq arg nil))) ; hack to fall back to cycling
-                    (arg
-                     ;; user or caller requests a specific state
-                     (cond
-                      ((equal arg "") nil)
-                      ((eq arg 'none) nil)
-                      ((eq arg 'done) (or done-word (car org-done-keywords)))
-                      ((eq arg 'nextset)
-                       (or (car (cdr (member head org-todo-heads)))
-                           (car org-todo-heads)))
-                      ((eq arg 'previousset)
-                       (let ((org-todo-heads (reverse org-todo-heads)))
+                           (if tail (car tail) nil)
+                         (car org-todo-keywords-1)))
+                      ((eq arg 'left)
+                       (if (equal member org-todo-keywords-1)
+                           nil
+                         (if this
+                             (nth (- (length org-todo-keywords-1)
+                                     (length tail) 2)
+                                  org-todo-keywords-1)
+                           (org-last org-todo-keywords-1))))
+                      ((and (eq org-use-fast-todo-selection t) (equal arg '(4))
+                            (setq arg nil))) ; hack to fall back to cycling
+                      (arg
+                       ;; user or caller requests a specific state
+                       (cond
+                        ((equal arg "") nil)
+                        ((eq arg 'none) nil)
+                        ((eq arg 'done) (or done-word (car org-done-keywords)))
+                        ((eq arg 'nextset)
                          (or (car (cdr (member head org-todo-heads)))
-                             (car org-todo-heads))))
-                      ((car (member arg org-todo-keywords-1)))
-                      ((nth (1- (prefix-numeric-value arg))
-                            org-todo-keywords-1))))
-                    ((null member) (or head (car org-todo-keywords-1)))
-                    ((equal this final-done-word) nil) ;; -> make empty
-                    ((null tail) nil) ;; -> first entry
-                    ((eq interpret 'sequence)
-                     (car tail))
-                    ((memq interpret '(type priority))
-                     (if (eq this-command last-command)
-                         (car tail)
-                       (if (> (length tail) 0)
-                           (or done-word (car org-done-keywords))
-                         nil)))
-                    (t nil)))
-            (next (if state (concat " " state " ") " "))
-            (change-plist (list :type 'todo-state-change :from this :to state
-                                :position startpos))
-            dolog now-done-p)
-       (when org-blocker-hook
+                             (car org-todo-heads)))
+                        ((eq arg 'previousset)
+                         (let ((org-todo-heads (reverse org-todo-heads)))
+                           (or (car (cdr (member head org-todo-heads)))
+                               (car org-todo-heads))))
+                        ((car (member arg org-todo-keywords-1)))
+                        ((nth (1- (prefix-numeric-value arg))
+                              org-todo-keywords-1))))
+                      ((null member) (or head (car org-todo-keywords-1)))
+                      ((equal this final-done-word) nil) ;; -> make empty
+                      ((null tail) nil) ;; -> first entry
+                      ((eq interpret 'sequence)
+                       (car tail))
+                      ((memq interpret '(type priority))
+                       (if (eq this-command last-command)
+                           (car tail)
+                         (if (> (length tail) 0)
+                             (or done-word (car org-done-keywords))
+                           nil)))
+                      (t nil)))
+              (next (if state (concat " " state " ") " "))
+              (change-plist (list :type 'todo-state-change :from this :to state
+                                  :position startpos))
+              dolog now-done-p)
+         (when org-blocker-hook
+           (setq org-last-todo-state-is-todo
+                 (not (member this org-done-keywords)))
+           (unless (save-excursion
+                     (save-match-data
+                       (run-hook-with-args-until-failure
+                        'org-blocker-hook change-plist)))
+             (if (interactive-p)
+                 (error "TODO state change from %s to %s blocked" this state)
+               ;; fail silently
+               (message "TODO state change from %s to %s blocked" this state)
+               (throw 'exit nil))))
+         (store-match-data match-data)
+         (replace-match next t t)
+         (unless (pos-visible-in-window-p hl-pos)
+           (message "TODO state changed to %s" (org-trim next)))
+         (unless head
+           (setq head (org-get-todo-sequence-head state)
+                 ass (assoc head org-todo-kwd-alist)
+                 interpret (nth 1 ass)
+                 done-word (nth 3 ass)
+                 final-done-word (nth 4 ass)))
+         (when (memq arg '(nextset previousset))
+           (message "Keyword-Set %d/%d: %s"
+                    (- (length org-todo-sets) -1
+                       (length (memq (assoc state org-todo-sets) org-todo-sets)))
+                    (length org-todo-sets)
+                    (mapconcat 'identity (assoc state org-todo-sets) " ")))
          (setq org-last-todo-state-is-todo
-               (not (member this org-done-keywords)))
-         (unless (save-excursion
-                   (save-match-data
-                     (run-hook-with-args-until-failure
-                      'org-blocker-hook change-plist)))
-           (if (interactive-p)
-               (error "TODO state change from %s to %s blocked" this state)
-             ;; fail silently
-             (message "TODO state change from %s to %s blocked" this state)
-             (throw 'exit nil))))
-       (store-match-data match-data)
-       (replace-match next t t)
-       (unless (pos-visible-in-window-p hl-pos)
-         (message "TODO state changed to %s" (org-trim next)))
-       (unless head
-         (setq head (org-get-todo-sequence-head state)
-               ass (assoc head org-todo-kwd-alist)
-               interpret (nth 1 ass)
-               done-word (nth 3 ass)
-               final-done-word (nth 4 ass)))
-       (when (memq arg '(nextset previousset))
-         (message "Keyword-Set %d/%d: %s"
-                  (- (length org-todo-sets) -1
-                     (length (memq (assoc state org-todo-sets) org-todo-sets)))
-                  (length org-todo-sets)
-                  (mapconcat 'identity (assoc state org-todo-sets) " ")))
-       (setq org-last-todo-state-is-todo
-             (not (member state org-done-keywords)))
-       (setq now-done-p (and (member state org-done-keywords)
-                             (not (member this org-done-keywords))))
-       (and logging (org-local-logging logging))
-       (when (and (or org-todo-log-states org-log-done)
-                  (not (memq arg '(nextset previousset))))
-         ;; we need to look at recording a time and note
-         (setq dolog (or (nth 1 (assoc state org-todo-log-states))
-                         (nth 2 (assoc this org-todo-log-states))))
-         (when (and state
-                    (member state org-not-done-keywords)
-                    (not (member this org-not-done-keywords)))
-           ;; This is now a todo state and was not one before
-           ;; If there was a CLOSED time stamp, get rid of it.
-           (org-add-planning-info nil nil 'closed))
-         (when (and now-done-p org-log-done)
-           ;; It is now done, and it was not done before
-           (org-add-planning-info 'closed (org-current-time))
-           (if (and (not dolog) (eq 'note org-log-done))
-               (org-add-log-setup 'done state 'findpos 'note)))
-         (when (and state dolog)
-           ;; This is a non-nil state, and we need to log it
-           (org-add-log-setup 'state state 'findpos dolog)))
-       ;; Fixup tag positioning
-       (org-todo-trigger-tag-changes state)
-       (and org-auto-align-tags (not org-setting-tags) (org-set-tags nil t))
-       (when org-provide-todo-statistics
-         (org-update-parent-todo-statistics))
-       (run-hooks 'org-after-todo-state-change-hook)
-       (if (and arg (not (member state org-done-keywords)))
-           (setq head (org-get-todo-sequence-head state)))
-       (put-text-property (point-at-bol) (point-at-eol) 'org-todo-head head)
-       ;; Do we need to trigger a repeat?
-       (when now-done-p
-         (when (boundp 'org-agenda-headline-snapshot-before-repeat)
-           ;; This is for the agenda, take a snapshot of the headline.
-           (save-match-data
-             (setq org-agenda-headline-snapshot-before-repeat
-                   (org-get-heading))))
-         (org-auto-repeat-maybe state))
-       ;; Fixup cursor location if close to the keyword
-       (if (and (outline-on-heading-p)
-                (not (bolp))
-                (save-excursion (beginning-of-line 1)
-                                (looking-at org-todo-line-regexp))
-                (< (point) (+ 2 (or (match-end 2) (match-end 1)))))
-           (progn
-             (goto-char (or (match-end 2) (match-end 1)))
-             (just-one-space)))
-       (when org-trigger-hook
-         (save-excursion
-           (run-hook-with-args 'org-trigger-hook change-plist)))))))
+               (not (member state org-done-keywords)))
+         (setq now-done-p (and (member state org-done-keywords)
+                               (not (member this org-done-keywords))))
+         (and logging (org-local-logging logging))
+         (when (and (or org-todo-log-states org-log-done)
+                    (not (memq arg '(nextset previousset))))
+           ;; we need to look at recording a time and note
+           (setq dolog (or (nth 1 (assoc state org-todo-log-states))
+                           (nth 2 (assoc this org-todo-log-states))))
+           (when (and state
+                      (member state org-not-done-keywords)
+                      (not (member this org-not-done-keywords)))
+             ;; This is now a todo state and was not one before
+             ;; If there was a CLOSED time stamp, get rid of it.
+             (org-add-planning-info nil nil 'closed))
+           (when (and now-done-p org-log-done)
+             ;; It is now done, and it was not done before
+             (org-add-planning-info 'closed (org-current-time))
+             (if (and (not dolog) (eq 'note org-log-done))
+                 (org-add-log-setup 'done state 'findpos 'note)))
+           (when (and state dolog)
+             ;; This is a non-nil state, and we need to log it
+             (org-add-log-setup 'state state 'findpos dolog)))
+         ;; Fixup tag positioning
+         (org-todo-trigger-tag-changes state)
+         (and org-auto-align-tags (not org-setting-tags) (org-set-tags nil t))
+         (when org-provide-todo-statistics
+           (org-update-parent-todo-statistics))
+         (run-hooks 'org-after-todo-state-change-hook)
+         (if (and arg (not (member state org-done-keywords)))
+             (setq head (org-get-todo-sequence-head state)))
+         (put-text-property (point-at-bol) (point-at-eol) 'org-todo-head head)
+         ;; Do we need to trigger a repeat?
+         (when now-done-p
+           (when (boundp 'org-agenda-headline-snapshot-before-repeat)
+             ;; This is for the agenda, take a snapshot of the headline.
+             (save-match-data
+               (setq org-agenda-headline-snapshot-before-repeat
+                     (org-get-heading))))
+           (org-auto-repeat-maybe state))
+         ;; Fixup cursor location if close to the keyword
+         (if (and (outline-on-heading-p)
+                  (not (bolp))
+                  (save-excursion (beginning-of-line 1)
+                                  (looking-at org-todo-line-regexp))
+                  (< (point) (+ 2 (or (match-end 2) (match-end 1)))))
+             (progn
+               (goto-char (or (match-end 2) (match-end 1)))
+               (just-one-space)))
+         (when org-trigger-hook
+           (save-excursion
+             (run-hook-with-args 'org-trigger-hook change-plist))))))))
 
 (defun org-block-todo-from-children-or-siblings (change-plist)
   "Block turning an entry into a TODO, using the hierarchy.
@@ -8522,7 +8549,9 @@ changes.  Such blocking occurs when:
     ;; do not block
     (when (or (not (eq (plist-get change-plist :type) 'todo-state-change))
              (member (plist-get change-plist :from)
-                     (cons 'done org-done-keywords)))
+                     (cons 'done org-done-keywords))
+             (member (plist-get change-plist :to)
+                     (cons 'todo org-not-done-keywords)))
       (throw 'dont-block t))
     ;; If this task has children, and any are undone, it's blocked
     (save-excursion
@@ -8573,6 +8602,31 @@ changes.  Such blocking occurs when:
       (org-entry-put nil "ORDERED" "t")
       (message "Subtasks must be completed in sequence"))))
 
+(defun org-block-todo-from-checkboxes (change-plist)
+  "Block turning an entry into a TODO, using checkboxes.
+This checks whether the current task should be blocked from state
+changes because there are uncheckd boxes in this entry."
+  (catch 'dont-block
+    ;; If this is not a todo state change, or if this entry is already DONE,
+    ;; do not block
+    (when (or (not (eq (plist-get change-plist :type) 'todo-state-change))
+             (member (plist-get change-plist :from)
+                     (cons 'done org-done-keywords))
+             (member (plist-get change-plist :to)
+                     (cons 'todo org-not-done-keywords)))
+      (throw 'dont-block t))
+    ;; If this task has checkboxes that are not checked, it's blocked
+    (save-excursion
+      (org-back-to-heading t)
+      (let ((beg (point)) end)
+       (outline-next-heading)
+       (setq end (point))
+       (goto-char beg)
+       (if (re-search-forward "^[ \t]*\\([-+*]\\|[0-9]+[.)]\\)[ \t]+\\[[- ]\\]"
+                              end t)
+           (throw 'dont-block nil))))
+    t)) ; do not block
+
 (defun org-update-parent-todo-statistics ()
   "Update any statistics cookie in the parent of the current headline."
   (interactive)