changeset 101702:832fdb28f500

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.
author Carsten Dominik <dominik@science.uva.nl>
date Sat, 31 Jan 2009 05:28:36 +0000
parents ba9c16ff3497
children 1e9411498c8f
files 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
diffstat 34 files changed, 257 insertions(+), 197 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/org/ChangeLog	Sat Jan 31 03:15:35 2009 +0000
+++ b/lisp/org/ChangeLog	Sat Jan 31 05:28:36 2009 +0000
@@ -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)
--- a/lisp/org/org-agenda.el	Sat Jan 31 03:15:35 2009 +0000
+++ b/lisp/org/org-agenda.el	Sat Jan 31 05:28:36 2009 +0000
@@ -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.
 ;;
--- a/lisp/org/org-archive.el	Sat Jan 31 03:15:35 2009 +0000
+++ b/lisp/org/org-archive.el	Sat Jan 31 05:28:36 2009 +0000
@@ -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.
 ;;
--- a/lisp/org/org-attach.el	Sat Jan 31 03:15:35 2009 +0000
+++ b/lisp/org/org-attach.el	Sat Jan 31 05:28:36 2009 +0000
@@ -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.
 ;;
--- a/lisp/org/org-bbdb.el	Sat Jan 31 03:15:35 2009 +0000
+++ b/lisp/org/org-bbdb.el	Sat Jan 31 05:28:36 2009 +0000
@@ -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.
 ;;
--- a/lisp/org/org-bibtex.el	Sat Jan 31 03:15:35 2009 +0000
+++ b/lisp/org/org-bibtex.el	Sat Jan 31 05:28:36 2009 +0000
@@ -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.
 ;;
--- a/lisp/org/org-clock.el	Sat Jan 31 03:15:35 2009 +0000
+++ b/lisp/org/org-clock.el	Sat Jan 31 05:28:36 2009 +0000
@@ -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.
 ;;
--- a/lisp/org/org-colview.el	Sat Jan 31 03:15:35 2009 +0000
+++ b/lisp/org/org-colview.el	Sat Jan 31 05:28:36 2009 +0000
@@ -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.
 ;;
--- a/lisp/org/org-compat.el	Sat Jan 31 03:15:35 2009 +0000
+++ b/lisp/org/org-compat.el	Sat Jan 31 05:28:36 2009 +0000
@@ -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.
 ;;
--- a/lisp/org/org-exp.el	Sat Jan 31 03:15:35 2009 +0000
+++ b/lisp/org/org-exp.el	Sat Jan 31 05:28:36 2009 +0000
@@ -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.
 ;;
--- a/lisp/org/org-export-latex.el	Sat Jan 31 03:15:35 2009 +0000
+++ b/lisp/org/org-export-latex.el	Sat Jan 31 05:28:36 2009 +0000
@@ -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
--- a/lisp/org/org-faces.el	Sat Jan 31 03:15:35 2009 +0000
+++ b/lisp/org/org-faces.el	Sat Jan 31 05:28:36 2009 +0000
@@ -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.
 ;;
--- a/lisp/org/org-footnote.el	Sat Jan 31 03:15:35 2009 +0000
+++ b/lisp/org/org-footnote.el	Sat Jan 31 05:28:36 2009 +0000
@@ -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.
 ;;
--- a/lisp/org/org-gnus.el	Sat Jan 31 03:15:35 2009 +0000
+++ b/lisp/org/org-gnus.el	Sat Jan 31 05:28:36 2009 +0000
@@ -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.
 ;;
--- a/lisp/org/org-id.el	Sat Jan 31 03:15:35 2009 +0000
+++ b/lisp/org/org-id.el	Sat Jan 31 05:28:36 2009 +0000
@@ -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.
 ;;
--- a/lisp/org/org-info.el	Sat Jan 31 03:15:35 2009 +0000
+++ b/lisp/org/org-info.el	Sat Jan 31 05:28:36 2009 +0000
@@ -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.
 ;;
--- a/lisp/org/org-irc.el	Sat Jan 31 03:15:35 2009 +0000
+++ b/lisp/org/org-irc.el	Sat Jan 31 05:28:36 2009 +0000
@@ -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.
 ;;
--- a/lisp/org/org-jsinfo.el	Sat Jan 31 03:15:35 2009 +0000
+++ b/lisp/org/org-jsinfo.el	Sat Jan 31 05:28:36 2009 +0000
@@ -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.
 ;;
--- a/lisp/org/org-list.el	Sat Jan 31 03:15:35 2009 +0000
+++ b/lisp/org/org-list.el	Sat Jan 31 05:28:36 2009 +0000
@@ -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.
 ;;
--- a/lisp/org/org-mac-message.el	Sat Jan 31 03:15:35 2009 +0000
+++ b/lisp/org/org-mac-message.el	Sat Jan 31 05:28:36 2009 +0000
@@ -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.
--- a/lisp/org/org-macs.el	Sat Jan 31 03:15:35 2009 +0000
+++ b/lisp/org/org-macs.el	Sat Jan 31 05:28:36 2009 +0000
@@ -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.
 ;;
--- a/lisp/org/org-mew.el	Sat Jan 31 03:15:35 2009 +0000
+++ b/lisp/org/org-mew.el	Sat Jan 31 05:28:36 2009 +0000
@@ -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.
 
--- a/lisp/org/org-mhe.el	Sat Jan 31 03:15:35 2009 +0000
+++ b/lisp/org/org-mhe.el	Sat Jan 31 05:28:36 2009 +0000
@@ -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.
 ;;
--- a/lisp/org/org-mouse.el	Sat Jan 31 03:15:35 2009 +0000
+++ b/lisp/org/org-mouse.el	Sat Jan 31 05:28:36 2009 +0000
@@ -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.
 ;;
--- a/lisp/org/org-plot.el	Sat Jan 31 03:15:35 2009 +0000
+++ b/lisp/org/org-plot.el	Sat Jan 31 05:28:36 2009 +0000
@@ -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.
 ;;
--- a/lisp/org/org-publish.el	Sat Jan 31 03:15:35 2009 +0000
+++ b/lisp/org/org-publish.el	Sat Jan 31 05:28:36 2009 +0000
@@ -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.
 ;;
--- a/lisp/org/org-remember.el	Sat Jan 31 03:15:35 2009 +0000
+++ b/lisp/org/org-remember.el	Sat Jan 31 05:28:36 2009 +0000
@@ -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.
 ;;
--- a/lisp/org/org-rmail.el	Sat Jan 31 03:15:35 2009 +0000
+++ b/lisp/org/org-rmail.el	Sat Jan 31 05:28:36 2009 +0000
@@ -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.
 ;;
--- a/lisp/org/org-table.el	Sat Jan 31 03:15:35 2009 +0000
+++ b/lisp/org/org-table.el	Sat Jan 31 05:28:36 2009 +0000
@@ -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.
 ;;
--- a/lisp/org/org-timer.el	Sat Jan 31 03:15:35 2009 +0000
+++ b/lisp/org/org-timer.el	Sat Jan 31 05:28:36 2009 +0000
@@ -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.
 ;;
--- a/lisp/org/org-vm.el	Sat Jan 31 03:15:35 2009 +0000
+++ b/lisp/org/org-vm.el	Sat Jan 31 05:28:36 2009 +0000
@@ -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.
 ;;
--- a/lisp/org/org-w3m.el	Sat Jan 31 03:15:35 2009 +0000
+++ b/lisp/org/org-w3m.el	Sat Jan 31 05:28:36 2009 +0000
@@ -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.
 ;;
--- a/lisp/org/org-wl.el	Sat Jan 31 03:15:35 2009 +0000
+++ b/lisp/org/org-wl.el	Sat Jan 31 05:28:36 2009 +0000
@@ -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.
 ;;
--- a/lisp/org/org.el	Sat Jan 31 03:15:35 2009 +0000
+++ b/lisp/org/org.el	Sat Jan 31 05:28:36 2009 +0000
@@ -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 @@
   :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 @@
 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 @@
                      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 @@
     ;; 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 @@
       (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)