Merge from emacs-24; up to 2012-04-22T13:58:00Z!cyd@gnu.org
[bpt/emacs.git] / lisp / org / org-agenda.el
index b054dc1..ddb56ca 100644 (file)
@@ -1,12 +1,10 @@
 ;;; org-agenda.el --- Dynamic task and appointment lists for Org
 
-;; Copyright (C) 2004-2011
-;;   Free Software Foundation, Inc.
+;; Copyright (C) 2004-2012 Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <carsten at orgmode dot org>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: http://orgmode.org
-;; Version: 7.4
 ;;
 ;; This file is part of GNU Emacs.
 ;;
 ;;; Commentary:
 
 ;; This file contains the code for creating and using the Agenda for Org-mode.
+;;
+;; The functions `org-batch-agenda', `org-batch-agenda-csv', and
+;; `org-batch-store-agenda-views' are implemented as macros to provide
+;; a convenient way for extracting agenda information from the command
+;; line. The Lisp does not evaluate parameters of a macro call; thus
+;; it is not necessary to quote the parameters passed to one of those
+;; functions. E.g. you can write:
+;;
+;;   emacs -batch -l ~/.emacs -eval '(org-batch-agenda "a" org-agenda-span 7)'
+;;
+;; To export an agenda spanning 7 days. If `org-batch-agenda' would
+;; have been implemented as a regular function you'd have to quote the
+;; symbol org-agenda-span. Moreover: To use a symbol as parameter
+;; value you would have to double quote the symbol.
+;;
+;; This is a hack, but it works even when running Org byte-compiled.
+;;
 
 ;;; Code:
 
@@ -51,6 +66,8 @@
 (declare-function calendar-julian-date-string   "cal-julian" (&optional date))
 (declare-function calendar-mayan-date-string    "cal-mayan"  (&optional date))
 (declare-function calendar-persian-date-string  "cal-persia" (&optional date))
+(declare-function calendar-check-holidays       "holidays" (date))
+
 (declare-function org-datetree-find-date-create "org-datetree"
                  (date &optional keep-restriction))
 (declare-function org-columns-quit              "org-colview" ())
@@ -61,6 +78,9 @@
 (declare-function org-is-habit-p "org-habit" (&optional pom))
 (declare-function org-habit-parse-todo "org-habit" (&optional pom))
 (declare-function org-habit-get-priority "org-habit" (habit &optional moment))
+(declare-function org-pop-to-buffer-same-window "org-compat"
+                 (&optional buffer-or-name norecord label))
+
 (defvar calendar-mode-map)
 (defvar org-clock-current-task) ; defined in org-clock.el
 (defvar org-mobile-force-id-on-agenda-items) ; defined in org-mobile.el
@@ -89,16 +109,20 @@ only needed when the text to be killed contains more than N non-white lines."
 
 (defcustom org-agenda-compact-blocks nil
   "Non-nil means make the block agenda more compact.
-This is done by leaving out unnecessary lines."
+This is done globally by leaving out lines like the agenda span
+name and week number or the separator lines."
   :group 'org-agenda
   :type 'boolean)
 
 (defcustom org-agenda-block-separator ?=
   "The separator between blocks in the agenda.
 If this is a string, it will be used as the separator, with a newline added.
-If it is a character, it will be repeated to fill the window width."
+If it is a character, it will be repeated to fill the window width.
+If nil the separator is disabled.  In `org-agenda-custom-commands' this
+addresses the separator between the current and the previous block."
   :group 'org-agenda
   :type '(choice
+         (const :tag "Disabled" nil)
          (character)
          (string)))
 
@@ -221,6 +245,10 @@ you can \"misuse\" it to also add other text to the header.  However,
     (const user-defined-up) (const user-defined-down))
   "Sorting choices.")
 
+;; Keep custom values for `org-agenda-filter-preset' compatible with
+;; the new variable `org-agenda-tag-filter-preset'.
+(defvaralias 'org-agenda-filter-preset 'org-agenda-tag-filter-preset)
+
 (defconst org-agenda-custom-commands-local-options
   `(repeat :tag "Local settings for this command. Remember to quote values"
           (choice :tag "Setting"
@@ -262,19 +290,27 @@ you can \"misuse\" it to also add other text to the header.  However,
            (list :tag "Deadline Warning days"
                  (const org-deadline-warning-days)
                  (integer :value 1))
+           (list :tag "Category filter preset"
+                 (const org-agenda-category-filter-preset)
+                 (list
+                  (const :format "" quote)
+                  (repeat
+                   (string :tag "+category or -category"))))
            (list :tag "Tags filter preset"
-                 (const org-agenda-filter-preset)
+                 (const org-agenda-tag-filter-preset)
                  (list
                   (const :format "" quote)
                   (repeat
                    (string :tag "+tag or -tag"))))
            (list :tag "Set daily/weekly entry types"
                  (const org-agenda-entry-types)
-                 (set :greedy t :value (:deadline :scheduled :timestamp :sexp)
-                      (const :deadline)
-                      (const :scheduled)
-                      (const :timestamp)
-                      (const :sexp)))
+                 (list
+                  (const :format "" quote)
+                  (set :greedy t :value (:deadline :scheduled :timestamp :sexp)
+                       (const :deadline)
+                       (const :scheduled)
+                       (const :timestamp)
+                       (const :sexp))))
            (list :tag "Standard skipping condition"
                  :value (org-agenda-skip-function '(org-agenda-skip-entry-if))
                  (const org-agenda-skip-function)
@@ -326,7 +362,8 @@ This will be spliced into the custom type of
 `org-agenda-custom-commands'.")
 
 
-(defcustom org-agenda-custom-commands nil
+(defcustom org-agenda-custom-commands '(("n" "Agenda and all TODO's"
+                                        ((agenda "") (alltodo))))
   "Custom commands for the agenda.
 These commands will be offered on the splash screen displayed by the
 agenda dispatcher \\[org-agenda].  Each entry is a list like this:
@@ -371,7 +408,7 @@ where
 
 desc   A description string to be displayed in the dispatcher menu.
 cmd    An agenda command, similar to the above.  However, tree commands
-       are no allowed, but instead you can get agenda and global todo list.
+       are not allowed, but instead you can get agenda and global todo list.
        So valid commands for a set are:
        (agenda \"\" settings)
        (alltodo \"\" settings)
@@ -516,6 +553,23 @@ this one will be used."
  "Options concerning skipping parts of agenda files."
  :tag "Org Agenda Skip"
  :group 'org-agenda)
+
+(defcustom org-agenda-skip-function-global nil
+  "Function to be called at each match during agenda construction.
+If this function returns nil, the current match should not be skipped.
+If the function decided to skip an agenda match, is must return the
+buffer position from which the search should be continued.
+This may also be a Lisp form, which will be evaluated.
+
+This variable will be applied to every agenda match, including
+tags/property searches and TODO lists.  So try to make the test function
+do its checking as efficiently as possible.  To implement a skipping
+condition just for specific agenda commands, use the variable
+`org-agenda-skip-function' which can be set in the options section
+of custom agenda commands."
+  :group 'org-agenda-skip
+  :type 'sexp)
+
 (defgroup org-agenda-daily/weekly nil
   "Options concerning the daily/weekly agenda."
   :tag "Org Agenda Daily/Weekly"
@@ -582,16 +636,26 @@ all      Don't show any entries with a timestamp in the global todo list.
          The idea behind this is that by setting a timestamp, you
          have already \"taken care\" of this item.
 
+This variable can also have an integer as a value. If positive (N),
+todos with a timestamp N or more days in the future will be ignored. If
+negative (-N), todos with a timestamp N or more days in the past will be
+ignored. If 0, todos with a timestamp either today or in the future will
+be ignored. For example, a value of -1 will exclude todos with a
+timestamp in the past (yesterday or earlier), while a value of 7 will
+exclude todos with a timestamp a week or more in the future.
+
 See also `org-agenda-todo-ignore-with-date'.
 See also the variable `org-agenda-tags-todo-honor-ignore-options' if you want
 to make his option also apply to the tags-todo list."
   :group 'org-agenda-skip
   :group 'org-agenda-todo-list
+  :version "24.1"
   :type '(choice
          (const :tag "Ignore future timestamp todos" future)
          (const :tag "Ignore past or present timestamp todos" past)
          (const :tag "Ignore all timestamp todos" all)
-         (const :tag "Show timestamp todos" nil)))
+         (const :tag "Show timestamp todos" nil)
+         (integer :tag "Ignore if N or more days in past(-) or future(+).")))
 
 (defcustom org-agenda-todo-ignore-scheduled nil
   "Non-nil means, ignore some scheduled TODO items when making TODO list.
@@ -610,6 +674,9 @@ all      Don't show any scheduled entries in the global todo list.
 
 t        Same as `all', for backward compatibility.
 
+This variable can also have an integer as a value. See
+`org-agenda-todo-ignore-timestamp' for more details.
+
 See also `org-agenda-todo-ignore-with-date'.
 See also the variable `org-agenda-tags-todo-honor-ignore-options' if you want
 to make his option also apply to the tags-todo list."
@@ -620,7 +687,8 @@ to make his option also apply to the tags-todo list."
          (const :tag "Ignore past- or present-scheduled todos" past)
          (const :tag "Ignore all scheduled todos" all)
          (const :tag "Ignore all scheduled todos (compatibility)" t)
-         (const :tag "Show scheduled todos" nil)))
+         (const :tag "Show scheduled todos" nil)
+         (integer :tag "Ignore if N or more days in past(-) or future(+).")))
 
 (defcustom org-agenda-todo-ignore-deadlines nil
   "Non-nil means ignore some deadlined TODO items when making TODO list.
@@ -647,6 +715,9 @@ all     Ignore all TODO entries that do have a deadline.
 
 t       Same as `near', for backward compatibility.
 
+This variable can also have an integer as a value. See
+`org-agenda-todo-ignore-timestamp' for more details.
+
 See also `org-agenda-todo-ignore-with-date'.
 See also the variable `org-agenda-tags-todo-honor-ignore-options' if you want
 to make his option also apply to the tags-todo list."
@@ -657,7 +728,8 @@ to make his option also apply to the tags-todo list."
          (const :tag "Ignore near deadlines (compatibility)" t)
          (const :tag "Ignore far deadlines" far)
          (const :tag "Ignore all TODOs with a deadlines" all)
-         (const :tag "Show all TODOs, even if they have a deadline" nil)))
+         (const :tag "Show all TODOs, even if they have a deadline" nil)
+         (integer :tag "Ignore if N or more days in past(-) or future(+).")))
 
 (defcustom org-agenda-tags-todo-honor-ignore-options nil
   "Non-nil means honor todo-list ...ignore options also in tags-todo search.
@@ -725,12 +797,13 @@ trigger you to schedule it, and then you don't want to be reminded of it
 because you will take care of it on the day when scheduled."
   :group 'org-agenda-skip
   :group 'org-agenda-daily/weekly
+  :version "24.1"
   :type '(choice
          (const :tag "Alwas show prewarning" nil)
          (const :tag "Remove prewarning if entry is scheduled" t)
          (integer :tag "Restart prewarning N days before deadline")))
 
-(defcustom org-agenda-skip-additional-timestamps-same-entry t
+(defcustom org-agenda-skip-additional-timestamps-same-entry nil
   "When nil, multiple same-day timestamps in entry make multiple agenda lines.
 When non-nil, after the search for timestamps has matched once in an
 entry, the rest of the entry will not be searched."
@@ -762,7 +835,7 @@ will only be dimmed."
   :group 'org-agenda-todo-list
   :type '(choice
          (const :tag "Do not dim" nil)
-         (const :tag "Dim to a grey face" t)
+         (const :tag "Dim to a gray face" t)
          (const :tag "Make invisible" invisible)))
 
 (defcustom org-timeline-show-empty-dates 3
@@ -783,12 +856,13 @@ N days, just insert a special line indicating the size of the gap."
   :group 'org-agenda)
 
 (defcustom org-agenda-menu-show-matcher t
-  "Non-nil menas show the match string in the agenda dispatcher menu.
+  "Non-nil means show the match string in the agenda dispatcher menu.
 When nil, the matcher string is not shown, but is put into the help-echo
 property so than moving the mouse over the command shows it.
 Setting it to nil is good if matcher strings are very long and/or if
-you wnat to use two-column display (see `org-agenda-menu-two-column')."
+you want to use two-column display (see `org-agenda-menu-two-column')."
   :group 'org-agenda
+  :version "24.1"
   :type 'boolean)
 
 (defcustom org-agenda-menu-two-column nil
@@ -796,6 +870,7 @@ you wnat to use two-column display (see `org-agenda-menu-two-column')."
 If you use this, you probably want to set `org-agenda-menu-show-matcher'
 to nil."
   :group 'org-agenda
+  :version "24.1"
   :type 'boolean)
 
 (defcustom org-finalize-agenda-hook nil
@@ -815,6 +890,13 @@ Needs to be set before org.el is loaded."
   :group 'org-agenda-startup
   :type 'boolean)
 
+(defcustom org-agenda-follow-indirect nil
+  "Non-nil means `org-agenda-follow-mode' displays only the
+current item's tree, in an indirect buffer."
+  :group 'org-agenda
+  :version "24.1"
+  :type 'boolean)
+
 (defcustom org-agenda-show-outline-path t
   "Non-nil means show outline path in echo area after line motion."
   :group 'org-agenda-startup
@@ -883,7 +965,7 @@ It only matters if `org-agenda-window-setup' is `reorganize-frame'."
   :type '(cons (number :tag "Minimum") (number :tag "Maximum")))
 
 (defcustom org-agenda-restore-windows-after-quit nil
-  "Non-nil means restore window configuration open exiting agenda.
+  "Non-nil means restore window configuration upon exiting agenda.
 Before the window configuration is changed for displaying the agenda,
 the current status is recorded.  When the agenda is exited with
 `q' or `x' and this option is set, the old state is restored.  If
@@ -965,11 +1047,13 @@ This function makes sure that dates are aligned for easy reading."
   "Non-nil means use leading zero for military times in agenda.
 For example, 9:30am would become 09:30 rather than  9:30."
   :group 'org-agenda-daily/weekly
+  :version "24.1"
   :type 'boolean)
 
 (defcustom org-agenda-timegrid-use-ampm nil
   "When set, show AM/PM style timestamps on the timegrid."
   :group 'org-agenda
+  :version "24.1"
   :type 'boolean)
 
 (defun org-agenda-time-of-day-to-ampm (time)
@@ -1010,6 +1094,16 @@ and timeline buffers."
              (const :tag "Saturday" 6)
              (const :tag "Sunday" 0)))
 
+(defcustom org-agenda-move-date-from-past-immediately-to-today t
+  "Non-nil means jump to today when moving a past date forward in time.
+When using S-right in the agenda to move a a date forward, and the date
+stamp currently points to the past, the first key press will move it
+to today.  WHen nil, just move one day forward even if the date stays
+in the past."
+  :group 'org-agenda-daily/weekly
+  :version "24.1"
+  :type 'boolean)
+
 (defcustom org-agenda-include-diary nil
   "If non-nil, include in the agenda entries from the Emacs Calendar's diary.
 Custom commands can set this variable in the options section."
@@ -1020,22 +1114,20 @@ Custom commands can set this variable in the options section."
   "If non-nil, include entries within their deadline warning period.
 Custom commands can set this variable in the options section."
   :group 'org-agenda-daily/weekly
-  :type 'boolean)
-
-(defcustom org-agenda-include-all-todo nil
-  "Set  means weekly/daily agenda will always contain all TODO entries.
-The TODO entries will be listed at the top of the agenda, before
-the entries for specific days.
-This option is deprecated, it is better to define a block agenda instead."
-  :group 'org-agenda-daily/weekly
+  :version "24.1"
   :type 'boolean)
 
 (defcustom org-agenda-repeating-timestamp-show-all t
   "Non-nil means show all occurrences of a repeating stamp in the agenda.
-When nil, only one occurrence is shown, either today or the
-nearest into the future."
+When set to a list of strings, only show occurrences of repeating
+stamps for these TODO keywords.  When nil, only one occurrence is
+shown, either today or the nearest into the future."
   :group 'org-agenda-daily/weekly
-  :type 'boolean)
+  :type '(choice
+         (const :tag "Show repeating stamps" t)
+         (repeat :tag "Show repeating stamps for these TODO keywords"
+                 (string :tag "TODO Keyword"))
+         (const :tag "Don't show repeating stamps" nil)))
 
 (defcustom org-scheduled-past-days 10000
   "No. of days to continue listing scheduled items that are not marked DONE.
@@ -1057,6 +1149,50 @@ the agenda to display all available LOG items temporarily."
   :group 'org-agenda-daily/weekly
   :type '(set :greedy t (const closed) (const clock) (const state)))
 
+(defcustom org-agenda-clock-consistency-checks
+  '(:max-duration "10:00" :min-duration 0 :max-gap "0:05"
+                 :gap-ok-around ("4:00")
+                 :default-face ((:background "DarkRed") (:foreground "white"))
+                 :overlap-face nil :gap-face nil :no-end-time-face nil
+                 :long-face nil :short-face nil)
+  "This is a property list, with the following keys:
+
+:max-duration    Mark clocking chunks that are longer than this time.
+                 This is a time string like \"HH:MM\", or the number
+                 of minutes as an integer.
+
+:min-duration    Mark clocking chunks that are shorter that this.
+                 This is a time string like \"HH:MM\", or the number
+                 of minutes as an integer.
+
+:max-gap         Mark gaps between clocking chunks that are longer than
+                 this duration.  A number of minutes, or a string
+                 like \"HH:MM\".
+
+:gap-ok-around   List of times during the day which are usually not working
+                 times.  When a gap is detected, but the gap contains any
+                 of these times, the gap is *not* reported.  For example,
+                 if this is (\"4:00\" \"13:00\") then gaps that contain
+                 4:00 in the morning (i.e. the night) and 13:00
+                 (i.e. a typical lunch time) do not cause a warning.
+                 You should have at least one time during the night in this
+                 list, or otherwise the first task each morning will trigger
+                 a warning because it follows a long gap.
+
+Furthermore, the following properties can be used to define faces for
+issue display.
+
+:default-face         the default face, if the specific face is undefined
+:overlap-face         face for overlapping clocks
+:gap-face             face for gaps between clocks
+:no-end-time-face     face for incomplete clocks
+:long-face            face for clock intervals that are too long
+:short-face           face for clock intervals that are too short"
+  :group 'org-agenda-daily/weekly
+  :group 'org-clock
+  :version "24.1"
+  :type 'plist)
+
 (defcustom org-agenda-log-mode-add-notes t
   "Non-nil means add first line of notes to log entries in agenda views.
 If a log item like a state change or a clock entry is associated with
@@ -1113,6 +1249,7 @@ by preceding the first snippet with \"+\" or \"-\".  If the first snippet
 is a regexp marked with braces like \"{abc}\", this will also switch to
 boolean search."
   :group 'org-agenda-search-view
+  :version "24.1"
   :type 'boolean)
 
 (if (fboundp 'defvaralias)
@@ -1123,6 +1260,7 @@ boolean search."
   "Non-nil means, search words must be matches as complete words.
 When nil, they may also match part of a word."
   :group 'org-agenda-search-view
+  :version "24.1"
   :type 'boolean)
 
 (defgroup org-agenda-time-grid nil
@@ -1183,6 +1321,19 @@ a grid line."
     (string :tag "Grid String")
     (repeat :tag "Grid Times" (integer :tag "Time"))))
 
+(defcustom org-agenda-show-current-time-in-grid t
+  "Non-nil means show the current time in the time grid."
+  :group 'org-agenda-time-grid
+  :version "24.1"
+  :type 'boolean)
+
+(defcustom org-agenda-current-time-string
+  "now - - - - - - - - - - - - - - - - - - - - - - - - -"
+  "The string for the current time marker in the agenda."
+  :group 'org-agenda-time-grid
+  :version "24.1"
+  :type 'string)
+
 (defgroup org-agenda-sorting nil
   "Options concerning sorting in the Org-mode Agenda."
   :tag "Org Agenda Sorting"
@@ -1291,32 +1442,32 @@ When nil, such items are sorted as 0 minutes effort."
     (tags  . " %i %-12:c")
     (search . " %i %-12:c"))
   "Format specifications for the prefix of items in the agenda views.
-An alist with four entries, for the different agenda types.  The keys to the
-sublists are `agenda', `timeline', `todo', and `tags'.  The values
-are format strings.
+An alist with five entries, each for the different agenda types.  The
+keys of the sublists are `agenda', `timeline', `todo', `search' and `tags'.
+The values are format strings.
+
 This format works similar to a printf format, with the following meaning:
 
-  %c   the category of the item, \"Diary\" for entries from the diary, or
-       as given by the CATEGORY keyword or derived from the file name.
-  %i   the icon category of the item, as give in
-       `org-agenda-category-icon-alist'.
-  %T   the *last* tag of the item.  Last because inherited tags come
-       first in the list.
-  %t   the time-of-day specification if one applies to the entry, in the
-       format HH:MM
+  %c   the category of the item, \"Diary\" for entries from the diary,
+       or as given by the CATEGORY keyword or derived from the file name
+  %e   the effort required by the item
+  %i   the icon category of the item, see `org-agenda-category-icon-alist'
+  %T   the last tag of the item (ignore inherited tags, which come first)
+  %t   the HH:MM time-of-day specification if one applies to the entry
   %s   Scheduling/Deadline information, a short string
+  %(expression) Eval EXPRESSION and replace the control string
+                by the result
 
 All specifiers work basically like the standard `%s' of printf, but may
-contain two additional characters:  A question mark just after the `%' and
-a whitespace/punctuation character just before the final letter.
+contain two additional characters:  a question mark just after the `%'
+and a whitespace/punctuation character just before the final letter.
 
 If the first character after `%' is a question mark, the entire field
-will only be included if the corresponding value applies to the
-current entry.  This is useful for fields which should have fixed
-width when present, but zero width when absent.  For example,
-\"%?-12t\" will result in a 12 character time field if a time of the
-day is specified, but will completely disappear in entries which do
-not contain a time.
+will only be included if the corresponding value applies to the current
+entry.  This is useful for fields which should have fixed width when
+present, but zero width when absent.  For example, \"%?-12t\" will
+result in a 12 character time field if a time of the day is specified,
+but will completely disappear in entries which do not contain a time.
 
 If there is punctuation or whitespace character just before the final
 format letter, this character will be appended to the field value if
@@ -1324,19 +1475,16 @@ the value is not empty.  For example, the format \"%-12:c\" leads to
 \"Diary: \" if the category is \"Diary\".  If the category were be
 empty, no additional colon would be inserted.
 
-The default value of this option is \"  %-12:c%?-12t% s\", meaning:
+The default value for the agenda sublist is \"  %-12:c%?-12t% s\",
+which means:
+
 - Indent the line with two space characters
-- Give the category in a 12 chars wide field, padded with whitespace on
+- Give the category a 12 chars wide field, padded with whitespace on
   the right (because of `-').  Append a colon if there is a category
   (because of `:').
 - If there is a time-of-day, put it into a 12 chars wide field.  If no
   time, don't put in an empty field, just skip it (because of '?').
-- Finally, put the scheduling information and append a whitespace.
-
-As another example, if you don't want the time-of-day of entries in
-the prefix, you could use:
-
-  (setq org-agenda-prefix-format \"  %-11:c% s\")
+- Finally, put the scheduling information.
 
 See also the variables `org-agenda-remove-times-when-in-prefix' and
 `org-agenda-remove-tags'.
@@ -1394,6 +1542,7 @@ that passed since this item was scheduled first."
   "Text preceding item pulled into the agenda by inactive time stamps.
 These entries are added to the agenda when pressing \"[\"."
   :group 'org-agenda-line-format
+  :version "24.1"
   :type '(list
          (string :tag "Scheduled today     ")
          (string :tag "Scheduled previously")))
@@ -1432,6 +1581,7 @@ the headline/diary entry."
   "Non-nil means remove time ranges specifications in agenda
 items that span on several days."
   :group 'org-agenda-line-format
+  :version "24.1"
   :type 'boolean)
 
 (defcustom org-agenda-default-appointment-duration nil
@@ -1513,6 +1663,7 @@ The only argument passed to that function is the day. It should
 returns a face, or nil if does not want to specify a face and let
 the normal rules apply."
   :group 'org-agenda-line-format
+  :version "24.1"
   :type 'function)
 
 (defcustom org-agenda-category-icon-alist nil
@@ -1526,7 +1677,7 @@ Where CATEGORY-REGEXP is a regexp matching the categories where
 the icon should be displayed.
 FILE-OR-DATA either a file path or a string containing image data.
 
-The other fields can be ommited safely if not needed:
+The other fields can be omitted safely if not needed:
 TYPE indicates the image type.
 DATA-P is a boolean indicating whether the FILE-OR-DATA string is
 image data.
@@ -1545,6 +1696,7 @@ category, you can use:
 
   (\"Emacs\" '(space . (:width (16))))"
   :group 'org-agenda-line-format
+  :version "24.1"
   :type '(alist :key-type (string :tag "Regexp matching category")
                :value-type (choice (list :tag "Icon"
                                          (string :tag "File or data")
@@ -1563,16 +1715,6 @@ category, you can use:
   :group 'org-agenda-column-view
   :type 'boolean)
 
-(defcustom org-agenda-columns-remove-prefix-from-item t
-  "Non-nil means remove the prefix from a headline for agenda column view.
-The special ITEM field in the columns format contains the current line, with
-all information shown in other columns (like the TODO state or a tag).
-When this variable is non-nil, also the agenda prefix will be removed from
-the content of the ITEM field, to make sure as much as possible of the
-headline can be shown in the limited width of the field."
-  :group 'org-agenda
-  :type 'boolean)
-
 (defcustom org-agenda-columns-compute-summary-properties t
   "Non-nil means recompute all summary properties before column view.
 When column view in the agenda is listing properties that have a summary
@@ -1606,6 +1748,20 @@ the lower-case version of all tags."
   :group 'org-agenda
   :type 'function)
 
+(defcustom org-agenda-bulk-custom-functions nil
+  "Alist of characters and custom functions for bulk actions.
+For example, this value makes those two functions available:
+
+  '((?R set-category)
+    (?C bulk-cut))
+
+With selected entries in an agenda buffer, `B R' will call
+the custom function `set-category' on the selected entries.
+Note that functions in this alist don't need to be quoted."
+  :type 'alist
+  :version "24.1"
+  :group 'org-agenda)
+
 (eval-when-compile
   (require 'cl))
 (require 'org)
@@ -1615,12 +1771,14 @@ the lower-case version of all tags."
 If STRING is non-nil, the text property will be fetched from position 0
 in that string.  If STRING is nil, it will be fetched from the beginning
 of the current line."
-  `(let ((marker (get-text-property (if string 0 (point-at-bol))
-                                   'org-hd-marker string)))
-     (with-current-buffer (marker-buffer marker)
-       (save-excursion
-        (goto-char marker)
-        ,@body))))
+  (org-with-gensyms (marker)
+    `(let ((,marker (get-text-property (if string 0 (point-at-bol))
+                                      'org-hd-marker ,string)))
+       (with-current-buffer (marker-buffer ,marker)
+        (save-excursion
+          (goto-char ,marker)
+          ,@body)))))
+(def-edebug-spec org-agenda-with-point-at-orig-entry (form body))
 
 (defun org-add-agenda-custom-command (entry)
   "Replace or add a command in `org-agenda-custom-commands'.
@@ -1710,8 +1868,10 @@ The following commands are available:
 (org-defkey org-agenda-mode-map "\C-k"     'org-agenda-kill)
 (org-defkey org-agenda-mode-map "\C-c\C-w" 'org-agenda-refile)
 (org-defkey org-agenda-mode-map "m"        'org-agenda-bulk-mark)
+(org-defkey org-agenda-mode-map "%"        'org-agenda-bulk-mark-regexp)
 (org-defkey org-agenda-mode-map "u"        'org-agenda-bulk-unmark)
 (org-defkey org-agenda-mode-map "U"        'org-agenda-bulk-remove-all-marks)
+(org-defkey org-agenda-mode-map "A"        'org-agenda-append-agenda)
 (org-defkey org-agenda-mode-map "B"        'org-agenda-bulk-action)
 (org-defkey org-agenda-mode-map "\C-c\C-x!" 'org-reload)
 (org-defkey org-agenda-mode-map "\C-c\C-x\C-a" 'org-agenda-archive-default)
@@ -1772,7 +1932,7 @@ The following commands are available:
 (org-defkey org-agenda-mode-map "\C-c\C-xp" 'org-agenda-set-property)
 (org-defkey org-agenda-mode-map "q" 'org-agenda-quit)
 (org-defkey org-agenda-mode-map "x" 'org-agenda-exit)
-(org-defkey org-agenda-mode-map "\C-x\C-w" 'org-write-agenda)
+(org-defkey org-agenda-mode-map "\C-x\C-w" 'org-agenda-write)
 (org-defkey org-agenda-mode-map "\C-x\C-s" 'org-save-all-org-buffers)
 (org-defkey org-agenda-mode-map "s" 'org-save-all-org-buffers)
 (org-defkey org-agenda-mode-map "P" 'org-agenda-show-priority)
@@ -1820,6 +1980,7 @@ The following commands are available:
 (org-defkey org-agenda-mode-map "}" 'org-agenda-manipulate-query-subtract-re)
 (org-defkey org-agenda-mode-map "/" 'org-agenda-filter-by-tag)
 (org-defkey org-agenda-mode-map "\\" 'org-agenda-filter-by-tag-refine)
+(org-defkey org-agenda-mode-map "<" 'org-agenda-filter-by-category)
 (org-defkey org-agenda-mode-map ";" 'org-timer-set-timer)
 (define-key org-agenda-mode-map "?" 'org-agenda-show-the-flagging-note)
 (org-defkey org-agenda-mode-map "\C-c\C-x\C-mg"    'org-mobile-pull)
@@ -1886,7 +2047,7 @@ The following commands are available:
       :keys "v A"]
      "--"
      ["Remove Restriction" org-agenda-remove-restriction-lock org-agenda-restrict])
-    ["Write view to file" org-write-agenda t]
+    ["Write view to file" org-agenda-write t]
     ["Rebuild buffer" org-agenda-redo t]
     ["Save all Org-mode Buffers" org-save-all-org-buffers t]
     "--"
@@ -1914,9 +2075,10 @@ The following commands are available:
      ["Delete subtree" org-agenda-kill t])
     ("Bulk action"
      ["Mark entry" org-agenda-bulk-mark t]
+     ["Mark matching regexp" org-agenda-bulk-mark-regexp t]
      ["Unmark entry" org-agenda-bulk-unmark t]
-     ["Act on all marked" org-agenda-bulk-action t]
      ["Unmark all entries" org-agenda-bulk-remove-all-marks :active t :keys "C-u s"])
+     ["Act on all marked" org-agenda-bulk-action t]
     "--"
     ("Tags and Properties"
      ["Show all Tags" org-agenda-show-tags t]
@@ -1989,7 +2151,6 @@ The following commands are available:
 (defvar org-agenda-pending-undo-list nil
   "In a series of undo commands, this is the list of remaining undo items.")
 
-
 (defun org-agenda-undo ()
   "Undo a remote editing step in the agenda.
 This undoes changes both in the agenda buffer and in the remote buffer
@@ -2105,6 +2266,8 @@ 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))
       (unless keys
@@ -2157,7 +2320,7 @@ Pressing `<' twice means to restrict to the current subtree or region
               ((eq type 'todo-tree)
                (org-check-for-org-mode)
                (org-let lprops
-                 '(org-occur (concat "^" outline-regexp "[ \t]*"
+                 '(org-occur (concat "^" org-outline-regexp "[ \t]*"
                                      (regexp-quote match) "\\>"))))
               ((eq type 'occur-tree)
                (org-check-for-org-mode)
@@ -2167,7 +2330,7 @@ Pressing `<' twice means to restrict to the current subtree or region
               ((fboundp type)
                (org-let lprops '(funcall type match)))
               (t (error "Invalid custom agenda command type %s" type))))
-         (org-run-agenda-series (nth 1 entry) (cddr entry))))
+         (org-agenda-run-series (nth 1 entry) (cddr entry))))
        ((equal keys "C")
        (setq org-agenda-custom-commands org-agenda-custom-commands-orig)
        (customize-variable 'org-agenda-custom-commands))
@@ -2195,7 +2358,7 @@ Pressing `<' twice means to restrict to the current subtree or region
                               nil 'face 'org-warning)))))))
         t t))
        ((equal keys "L")
-       (unless (org-mode-p)
+       (unless (eq major-mode 'org-mode)
          (error "This is not an Org-mode file"))
        (unless restriction
          (put 'org-agenda-files 'org-restrict (list bfn))
@@ -2205,6 +2368,17 @@ Pressing `<' twice means to restrict to the current subtree or region
        ((equal keys "!") (customize-variable 'org-stuck-projects))
        (t (error "Invalid agenda key"))))))
 
+(defun org-agenda-append-agenda ()
+  "Append another agenda view to the current one.
+This function allows interactive building of block agendas.
+Agenda views are separated by `org-agenda-block-separator'."
+  (interactive)
+  (unless (string= (buffer-name) org-agenda-buffer-name)
+    (error "Can only append from within agenda buffer"))
+  (let ((org-agenda-multi t))
+    (org-agenda)
+    (widen)))
+
 (defun org-agenda-normalize-custom-commands (cmds)
   (delq nil
        (mapcar
@@ -2219,7 +2393,7 @@ Pressing `<' twice means to restrict to the current subtree or region
   "The user interface for selecting an agenda command."
   (catch 'exit
     (let* ((bfn (buffer-file-name (buffer-base-buffer)))
-          (restrict-ok (and bfn (org-mode-p)))
+          (restrict-ok (and bfn (eq major-mode 'org-mode)))
           (region-p (org-region-active-p))
           (custom org-agenda-custom-commands)
           (selstring "")
@@ -2403,10 +2577,17 @@ s   Search for keywords                 C   Configure custom agenda commands
           ((equal c ?q) (error "Abort"))
           (t (error "Invalid key %c" c))))))))
 
-(defun org-run-agenda-series (name series)
+(defvar org-agenda-overriding-arguments nil) ; dynamically scoped parameter
+(defvar org-agenda-last-arguments nil
+  "The arguments of the previous call to `org-agenda'.")
+(defun org-agenda-run-series (name series)
   (org-let (nth 1 series) '(org-prepare-agenda name))
   (let* ((org-agenda-multi t)
-        (redo (list 'org-run-agenda-series name (list 'quote series)))
+        (redo (list 'org-agenda-run-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!
@@ -2441,6 +2622,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)))
@@ -2453,23 +2635,13 @@ If CMD-KEY is a string of length 1, it is used as a key in
 longer string it is used as a tags/todo match string.
 Parameters are alternating variable names and values that will be bound
 before running the agenda command."
-  (let (pars)
-    (while parameters
-      (push (list (pop parameters) (if parameters (pop parameters))) pars))
+  (org-eval-in-environment (org-make-parameter-alist parameters)
     (if (> (length cmd-key) 2)
-       (eval (list 'let (nreverse pars)
-                   (list 'org-tags-view nil cmd-key)))
-      (eval (list 'let (nreverse pars) (list 'org-agenda nil cmd-key))))
-    (set-buffer org-agenda-buffer-name)
-    (princ (org-encode-for-stdout (buffer-string)))))
-
-;(defun org-encode-for-stdout (string)
-;  (if (fboundp 'encode-coding-string)
-;      (encode-coding-string string buffer-file-coding-system)
-;    string))
-
-(defun org-encode-for-stdout (string)
-  string)
+       (org-tags-view nil cmd-key)
+      (org-agenda nil cmd-key)))
+  (set-buffer org-agenda-buffer-name)
+  (princ (buffer-string)))
+(def-edebug-spec org-batch-agenda (form &rest sexp))
 
 (defvar org-agenda-info nil)
 
@@ -2508,30 +2680,26 @@ extra        Sting with extra planning info
 priority-l   The priority letter if any was given
 priority-n   The computed numerical priority
 agenda-day   The day in the agenda where this is listed"
-
-  (let (pars)
-    (while parameters
-      (push (list (pop parameters) (if parameters (pop parameters))) pars))
-    (push (list 'org-agenda-remove-tags t) pars)
+  (org-eval-in-environment (append '((org-agenda-remove-tags t))
+                                  (org-make-parameter-alist parameters))
     (if (> (length cmd-key) 2)
-       (eval (list 'let (nreverse pars)
-                   (list 'org-tags-view nil cmd-key)))
-      (eval (list 'let (nreverse pars) (list 'org-agenda nil cmd-key))))
-    (set-buffer org-agenda-buffer-name)
-    (let* ((lines (org-split-string (buffer-string) "\n"))
-          line)
-      (while (setq line (pop lines))
-       (catch 'next
-         (if (not (get-text-property 0 'org-category line)) (throw 'next nil))
-         (setq org-agenda-info
-               (org-fix-agenda-info (text-properties-at 0 line)))
-         (princ
-          (org-encode-for-stdout
-           (mapconcat 'org-agenda-export-csv-mapper
-                      '(org-category txt type todo tags date time extra
-                                     priority-letter priority agenda-day)
-                     ",")))
-         (princ "\n"))))))
+       (org-tags-view nil cmd-key)
+      (org-agenda nil cmd-key)))
+  (set-buffer org-agenda-buffer-name)
+  (let* ((lines (org-split-string (buffer-string) "\n"))
+        line)
+    (while (setq line (pop lines))
+      (catch 'next
+       (if (not (get-text-property 0 'org-category line)) (throw 'next nil))
+       (setq org-agenda-info
+             (org-fix-agenda-info (text-properties-at 0 line)))
+       (princ
+        (mapconcat 'org-agenda-export-csv-mapper
+                   '(org-category txt type todo tags date time extra
+                                  priority-letter priority agenda-day)
+                   ","))
+       (princ "\n")))))
+(def-edebug-spec org-batch-agenda-csv (form &rest sexp))
 
 (defun org-fix-agenda-info (props)
   "Make sure all properties on an agenda item have a canonical form.
@@ -2581,17 +2749,14 @@ This ensures the export commands can easily use it."
   (interactive)
   (eval (list 'org-batch-store-agenda-views)))
 
-;; FIXME, why is this a macro?????
 ;;;###autoload
 (defmacro org-batch-store-agenda-views (&rest parameters)
   "Run all custom agenda commands that have a file argument."
   (let ((cmds (org-agenda-normalize-custom-commands org-agenda-custom-commands))
        (pop-up-frames nil)
        (dir default-directory)
-       pars cmd thiscmdkey files opts cmd-or-set)
-    (while parameters
-      (push (list (pop parameters) (if parameters (pop parameters))) pars))
-    (setq pars (reverse pars))
+       (pars (org-make-parameter-alist parameters))
+       cmd thiscmdkey files opts cmd-or-set)
     (save-window-excursion
       (while cmds
        (setq cmd (pop cmds)
@@ -2601,15 +2766,17 @@ This ensures the export commands can easily use it."
              files (nth (if (listp cmd-or-set) 4 5) cmd))
        (if (stringp files) (setq files (list files)))
        (when files
-         (eval (list 'let (append org-agenda-exporter-settings opts pars)
-                     (list 'org-agenda nil thiscmdkey)))
+         (org-eval-in-environment (append org-agenda-exporter-settings
+                                          opts pars)
+           (org-agenda nil thiscmdkey))
          (set-buffer org-agenda-buffer-name)
          (while files
-           (eval (list 'let (append org-agenda-exporter-settings opts pars)
-                       (list 'org-write-agenda
-                             (expand-file-name (pop files) dir) nil t))))
+           (org-eval-in-environment (append org-agenda-exporter-settings
+                                            opts pars)
+             (org-agenda-write (expand-file-name (pop files) dir) nil t)))
          (and (get-buffer org-agenda-buffer-name)
               (kill-buffer org-agenda-buffer-name)))))))
+(def-edebug-spec org-batch-store-agenda-views (&rest sexp))
 
 (defun org-agenda-mark-header-line (pos)
   "Mark the line at POS as an agenda structure header."
@@ -2622,7 +2789,8 @@ This ensures the export commands can easily use it."
                         'org-agenda-title-append org-agenda-title-append))))
 
 (defvar org-mobile-creating-agendas)
-(defun org-write-agenda (file &optional open nosettings)
+(defvar org-agenda-write-buffer-name "Agenda View")
+(defun org-agenda-write (file &optional open nosettings)
   "Write the current buffer (an agenda view) as a file.
 Depending on the extension of the file name, plain text (.txt),
 HTML (.html or .htm) or Postscript (.ps) is produced.
@@ -2644,7 +2812,7 @@ higher priority settings."
         (let ((bs (copy-sequence (buffer-string))) beg)
           (org-agenda-unmark-filtered-text)
           (with-temp-buffer
-            (rename-buffer "Agenda View" t)
+            (rename-buffer org-agenda-write-buffer-name t)
             (set-buffer-modified-p nil)
             (insert bs)
             (org-agenda-remove-marked-text 'org-filtered)
@@ -2705,7 +2873,8 @@ higher priority settings."
     (set-buffer org-agenda-buffer-name))
   (when open (org-open-file file)))
 
-(defvar org-agenda-filter-overlays nil)
+(defvar org-agenda-tag-filter-overlays nil)
+(defvar org-agenda-cat-filter-overlays nil)
 
 (defun org-agenda-mark-filtered-text ()
   "Mark all text hidden by filtering with a text property."
@@ -2716,7 +2885,8 @@ higher priority settings."
         (put-text-property
          (overlay-start o) (overlay-end o)
          'org-filtered t)))
-     org-agenda-filter-overlays)))
+     (append org-agenda-tag-filter-overlays
+            org-agenda-cat-filter-overlays))))
 
 (defun org-agenda-unmark-filtered-text ()
   "Remove the filtering text property."
@@ -2763,7 +2933,7 @@ removed from the entry content.  Currently only `planning' is allowed here."
   (let (txt drawer-re kwd-time-re ind)
     (save-excursion
       (with-current-buffer (marker-buffer marker)
-       (if (not (org-mode-p))
+       (if (not (eq major-mode 'org-mode))
            (setq txt "")
          (save-excursion
            (save-restriction
@@ -2879,7 +3049,7 @@ removed from the entry content.  Currently only `planning' is allowed here."
 
 (defun org-check-for-org-mode ()
   "Make sure current buffer is in org-mode.  Error if not."
-  (or (org-mode-p)
+  (or (eq major-mode 'org-mode)
       (error "Cannot execute org-mode agenda command on buffer in %s"
             major-mode)))
 
@@ -2899,9 +3069,10 @@ removed from the entry content.  Currently only `planning' is allowed here."
 (defvar org-pre-agenda-window-conf nil)
 (defvar org-agenda-columns-active nil)
 (defvar org-agenda-name nil)
-(defvar org-agenda-filter nil)
-(defvar org-agenda-filter-while-redo nil)
-(defvar org-agenda-filter-preset nil
+(defvar org-agenda-tag-filter nil)
+(defvar org-agenda-category-filter nil)
+(defvar org-agenda-tag-filter-while-redo nil)
+(defvar org-agenda-tag-filter-preset nil
   "A preset of the tags filter used for secondary agenda filtering.
 This must be a list of strings, each string must be a single tag preceded
 by \"+\" or \"-\".
@@ -2911,24 +3082,37 @@ the entire agenda view.  In a block agenda, it will not work reliably to
 define a filter for one of the individual blocks.  You need to set it in
 the global options and expect it to be applied to the entire view.")
 
+(defvar org-agenda-category-filter-preset nil
+  "A preset of the category filter used for secondary agenda filtering.
+This must be a list of strings, each string must be a single category
+preceded by \"+\" or \"-\".
+This variable should not be set directly, but agenda custom commands can
+bind it in the options section.  The preset filter is a global property of
+the entire agenda view.  In a block agenda, it will not work reliably to
+define a filter for one of the individual blocks.  You need to set it in
+the global options and expect it to be applied to the entire view.")
+
 (defun org-prepare-agenda (&optional name)
   (setq org-todo-keywords-for-agenda nil)
-  (setq org-done-keywords-for-agenda nil)
   (setq org-drawers-for-agenda nil)
   (unless org-agenda-persistent-filter
-    (setq org-agenda-filter nil))
-  (put 'org-agenda-filter :preset-filter org-agenda-filter-preset)
+    (setq org-agenda-tag-filter nil
+          org-agenda-category-filter nil))
+  (put 'org-agenda-tag-filter :preset-filter org-agenda-tag-filter-preset)
+  (put 'org-agenda-category-filter :preset-filter org-agenda-category-filter-preset)
   (if org-agenda-multi
       (progn
        (setq buffer-read-only nil)
        (goto-char (point-max))
-       (unless (or (bobp) org-agenda-compact-blocks)
+       (unless (or (bobp) org-agenda-compact-blocks
+                   (not org-agenda-block-separator))
          (insert "\n"
                  (if (stringp org-agenda-block-separator)
                      org-agenda-block-separator
                    (make-string (window-width) org-agenda-block-separator))
                  "\n"))
        (narrow-to-region (point) (point-max)))
+    (setq org-done-keywords-for-agenda nil)
     (org-agenda-reset-markers)
     (setq org-agenda-contributing-files nil)
     (setq org-agenda-columns-active nil)
@@ -2945,7 +3129,7 @@ the global options and expect it to be applied to the entire view.")
        (awin (select-window awin))
        ((not (setq org-pre-agenda-window-conf (current-window-configuration))))
        ((equal org-agenda-window-setup 'current-window)
-       (switch-to-buffer abuf))
+       (org-pop-to-buffer-same-window abuf))
        ((equal org-agenda-window-setup 'other-window)
        (org-switch-to-buffer-other-window abuf))
        ((equal org-agenda-window-setup 'other-frame)
@@ -2956,7 +3140,7 @@ the global options and expect it to be applied to the entire view.")
       ;; additional test in case agenda is invoked from within agenda
       ;; buffer via elisp link
       (unless (equal (current-buffer) abuf)
-       (switch-to-buffer abuf)))
+       (org-pop-to-buffer-same-window abuf)))
     (setq buffer-read-only nil)
     (let ((inhibit-read-only t)) (erase-buffer))
     (org-agenda-mode)
@@ -2995,8 +3179,10 @@ the global options and expect it to be applied to the entire view.")
          (org-habit-insert-consistency-graphs))
       (run-hooks 'org-finalize-agenda-hook)
       (setq org-agenda-type (org-get-at-bol 'org-agenda-type))
-      (when (or org-agenda-filter (get 'org-agenda-filter :preset-filter))
-       (org-agenda-filter-apply org-agenda-filter))
+      (when (or org-agenda-tag-filter (get 'org-agenda-tag-filter :preset-filter))
+       (org-agenda-filter-apply org-agenda-tag-filter 'tag))
+      (when (or org-agenda-category-filter (get 'org-agenda-category-filter :preset-filter))
+       (org-agenda-filter-apply org-agenda-category-filter 'category))
       )))
 
 (defun org-agenda-mark-clocking-task ()
@@ -3070,17 +3256,9 @@ the global options and expect it to be applied to the entire view.")
        (setq org-blocked-by-checkboxes nil invis1 invis)
        (let ((marker (org-get-at-bol 'org-hd-marker)))
          (when (and marker
-                    (not (with-current-buffer (marker-buffer marker)
-                           (save-excursion
-                             (goto-char marker)
-                             (if (org-entry-get nil "NOBLOCKING")
-                                 t ;; Never block this entry
-                               (run-hook-with-args-until-failure
-                                'org-blocker-hook
-                                (list :type 'todo-state-change
-                                      :position marker
-                                      :from 'todo
-                                      :to 'done)))))))
+                    (with-current-buffer (marker-buffer marker)
+                      (save-excursion (goto-char marker)
+                                      (org-entry-blocked-p))))
            (if org-blocked-by-checkboxes (setq invis1 nil))
            (setq b (if invis1
                        (max (point-min) (1- (point-at-bol)))
@@ -3099,15 +3277,17 @@ Otherwise, the function must return a position from where the search
 should be continued.
 This may also be a Lisp form, it will be evaluated.
 Never set this variable using `setq' or so, because then it will apply
-to all future agenda commands.  Instead, bind it with `let' to scope
-it dynamically into the agenda-constructing command.  A good way to set
-it is through options in `org-agenda-custom-commands'.")
+to all future agenda commands.  If you do want a global skipping condition,
+use the option `org-agenda-skip-function-global' instead.
+The correct usage for `org-agenda-skip-function' is to bind it with
+`let' to scope it dynamically into the agenda-constructing command.
+A good way to set it is through options in `org-agenda-custom-commands'.")
 
 (defun org-agenda-skip ()
   "Throw to `:skip' in places that should be skipped.
 Also moves point to the end of the skipped region, so that search can
 continue from there."
-  (let ((p (point-at-bol)) to fp)
+  (let ((p (point-at-bol)) to)
     (and org-agenda-skip-archived-trees (not org-agenda-archives-mode)
         (get-text-property p :org-archived)
         (org-end-of-subtree t)
@@ -3117,16 +3297,26 @@ continue from there."
         (org-end-of-subtree t)
         (throw :skip t))
     (if (equal (char-after p) ?#) (throw :skip t))
-    (when (and (or (setq fp (functionp org-agenda-skip-function))
-                  (consp org-agenda-skip-function))
-              (setq to (save-excursion
-                         (save-match-data
-                           (if fp
-                               (funcall org-agenda-skip-function)
-                             (eval org-agenda-skip-function))))))
+    (when (setq to (or (org-agenda-skip-eval org-agenda-skip-function-global)
+                      (org-agenda-skip-eval org-agenda-skip-function)))
       (goto-char to)
       (throw :skip t))))
 
+(defun org-agenda-skip-eval (form)
+  "If FORM is a function or a list, call (or eval) is and return result.
+`save-excursion' and `save-match-data' are wrapped around the call, so point
+and match data are returned to the previous state no matter what these
+functions do."
+  (let (fp)
+    (and form
+        (or (setq fp (functionp form))
+            (consp form))
+        (save-excursion
+          (save-match-data
+            (if fp
+                (funcall form)
+              (eval form)))))))
+
 (defvar org-agenda-markers nil
   "List of all currently active markers created by `org-agenda'.")
 (defvar org-agenda-last-marker-time (org-float-time)
@@ -3202,7 +3392,7 @@ no longer in use."
 
 (defvar org-agenda-only-exact-dates nil) ; dynamically scoped
 
-(defun org-timeline (&optional include-all)
+(defun org-timeline (&optional dotodo)
   "Show a time-sorted view of the entries in the current org file.
 Only entries with a time stamp of today or later will be listed.  With
 \\[universal-argument] prefix, all unfinished TODO items will also be shown,
@@ -3213,7 +3403,6 @@ dates."
   (org-compile-prefix-format 'timeline)
   (org-set-sorting-strategy 'timeline)
   (let* ((dopast t)
-        (dotodo include-all)
         (doclosed org-agenda-show-log)
         (entry (buffer-file-name (or (buffer-base-buffer (current-buffer))
                                      (current-buffer))))
@@ -3232,7 +3421,7 @@ dates."
     (setq org-agenda-redo-command
          (list 'progn
                (list 'org-switch-to-buffer-other-window (current-buffer))
-               (list 'org-timeline (list 'quote include-all))))
+               (list 'org-timeline (list 'quote dotodo))))
     (if (not dopast)
        ;; Remove past dates from the list of dates.
        (setq day-numbers (delq nil (mapcar (lambda(x)
@@ -3300,22 +3489,26 @@ When EMPTY is non-nil, also include days without any entries."
   (let ((re (concat
             (if pre-re pre-re "")
             (if inactive org-ts-regexp-both org-ts-regexp)))
-        dates dates1 date day day1 day2 ts1 ts2)
+        dates dates1 date day day1 day2 ts1 ts2 pos)
     (if force-today
        (setq dates (list (org-today))))
     (save-excursion
       (goto-char beg)
       (while (re-search-forward re end t)
        (setq day (time-to-days (org-time-string-to-time
-                                (substring (match-string 1) 0 10))))
+                                (substring (match-string 1) 0 10)
+                                (current-buffer) (match-beginning 0))))
        (or (memq day dates) (push day dates)))
       (unless no-ranges
        (goto-char beg)
        (while (re-search-forward org-tr-regexp end t)
+         (setq pos (match-beginning 0))
          (setq ts1 (substring (match-string 1) 0 10)
                ts2 (substring (match-string 2) 0 10)
-               day1 (time-to-days (org-time-string-to-time ts1))
-               day2 (time-to-days (org-time-string-to-time ts2)))
+               day1 (time-to-days (org-time-string-to-time
+                                   ts1 (current-buffer) pos))
+               day2 (time-to-days (org-time-string-to-time
+                                   ts2  (current-buffer) pos)))
          (while (< (setq day1 (1+ day1)) day2)
            (or (memq day1 dates) (push day1 dates)))))
       (setq dates (sort dates '<))
@@ -3334,15 +3527,13 @@ When EMPTY is non-nil, also include days without any entries."
 
 ;;; Agenda Daily/Weekly
 
-(defvar org-agenda-overriding-arguments nil) ; dynamically scoped parameter
 (defvar org-agenda-start-day nil  ; dynamically scoped parameter
-"Custom commands can set this variable in the options section.")
-(defvar org-agenda-last-arguments nil
-  "The arguments of the previous call to `org-agenda'.")
+"Start day for the agenda view.
+Custom commands can set this variable in the options section.")
 (defvar org-starting-day nil) ; local variable in the agenda buffer
 (defvar org-agenda-current-span nil
   "The current span used in the agenda view.") ; local variable in the agenda buffer
-(defvar org-include-all-loc nil) ; local variable
+(defvar org-arg-loc nil) ; local variable
 
 (defvar org-agenda-entry-types '(:deadline :scheduled :timestamp :sexp)
   "List of types searched for when creating the daily/weekly agenda.
@@ -3371,44 +3562,40 @@ By default, all four types are turned on.
 
 Never set this variable globally using `setq', because then it
 will apply to all future agenda commands.  Instead, bind it with
-`let' to scope it dynamically into the the agenda-constructing
+`let' to scope it dynamically into the agenda-constructing
 command.  A good way to set it is through options in
 `org-agenda-custom-commands'.  For a more flexible (though
 somewhat less efficient) way of determining what is included in
 the daily/weekly agenda, see `org-agenda-skip-function'.")
 
 ;;;###autoload
-(defun org-agenda-list (&optional include-all start-day span)
+(defun org-agenda-list (&optional arg start-day span)
   "Produce a daily/weekly view from all files in variable `org-agenda-files'.
 The view will be for the current day or week, but from the overview buffer
 you will be able to go to other days/weeks.
 
-With one \\[universal-argument] prefix argument INCLUDE-ALL,
-all unfinished TODO items will also be shown, before the agenda.
-This feature is considered obsolete, please use the TODO list or a block
-agenda instead.
-
 With a numeric prefix argument in an interactive call, the agenda will
-span INCLUDE-ALL days.  Lisp programs should instead specify SPAN to change
+span ARG days.  Lisp programs should instead specify SPAN to change
 the number of days.  SPAN defaults to `org-agenda-span'.
 
 START-DAY defaults to TODAY, or to the most recent match for the weekday
 given in `org-agenda-start-on-weekday'."
   (interactive "P")
-  (if (and (integerp include-all) (> include-all 0))
-      (setq span include-all include-all nil))
+  (if (and (integerp arg) (> arg 0))
+      (setq span arg arg nil))
   (setq start-day (or start-day org-agenda-start-day))
   (if org-agenda-overriding-arguments
-      (setq include-all (car org-agenda-overriding-arguments)
+      (setq arg (car org-agenda-overriding-arguments)
            start-day (nth 1 org-agenda-overriding-arguments)
            span (nth 2 org-agenda-overriding-arguments)))
   (if (stringp start-day)
       ;; Convert to an absolute day number
       (setq start-day (time-to-days (org-read-date nil t start-day))))
-  (setq org-agenda-last-arguments (list include-all start-day span))
+  (setq org-agenda-last-arguments (list arg start-day span))
   (org-compile-prefix-format 'agenda)
   (org-set-sorting-strategy 'agenda)
-  (let* ((span (org-agenda-ndays-to-span (or span org-agenda-ndays org-agenda-span)))
+  (let* ((span (org-agenda-ndays-to-span
+               (or span org-agenda-ndays org-agenda-span)))
         (today (org-today))
         (sd (or start-day today))
         (ndays (org-agenda-span-to-ndays span sd))
@@ -3431,7 +3618,7 @@ given in `org-agenda-start-on-weekday'."
         s e rtn rtnall file date d start-pos end-pos todayp
         clocktable-start clocktable-end filter)
     (setq org-agenda-redo-command
-         (list 'org-agenda-list (list 'quote include-all) start-day (list 'quote span)))
+         (list 'org-agenda-list (list 'quote arg) start-day (list 'quote span)))
     (dotimes (n (1- ndays))
       (push (1+ (car day-numbers)) day-numbers))
     (setq day-numbers (nreverse day-numbers))
@@ -3439,26 +3626,8 @@ given in `org-agenda-start-on-weekday'."
          clocktable-end (1+ (or (org-last day-numbers) 0)))
     (org-prepare-agenda "Day/Week")
     (org-set-local 'org-starting-day (car day-numbers))
-    (org-set-local 'org-include-all-loc include-all)
+    (org-set-local 'org-arg-loc arg)
     (org-set-local 'org-agenda-current-span (org-agenda-ndays-to-span span))
-    (when (and (or include-all org-agenda-include-all-todo)
-              (member today day-numbers))
-      (setq files thefiles
-           rtnall nil)
-      (while (setq file (pop files))
-       (catch 'nextfile
-         (org-check-agenda-file file)
-         (setq date (calendar-gregorian-from-absolute today)
-               rtn (org-agenda-get-day-entries
-                    file date :todo))
-         (setq rtnall (append rtnall rtn))))
-      (when rtnall
-       (insert "All currently open TODO items:\n")
-       (add-text-properties (point-min) (1- (point))
-                            (list 'face 'org-agenda-structure
-                                  'short-heading "All TODO items"))
-       (org-agenda-mark-header-line (point-min))
-       (insert (org-finalize-agenda-entries rtnall) "\n")))
     (unless org-agenda-compact-blocks
       (let* ((d1 (car day-numbers))
             (d2 (org-last day-numbers))
@@ -3497,7 +3666,7 @@ given in `org-agenda-start-on-weekday'."
              (setq org-agenda-entry-types
                    (delq :deadline org-agenda-entry-types)))
            (cond
-            ((eq org-agenda-show-log 'only)
+            ((memq org-agenda-show-log '(only clockcheck))
              (setq rtn (org-agenda-get-day-entries
                         file date :closed)))
             (org-agenda-show-log
@@ -3508,7 +3677,7 @@ given in `org-agenda-start-on-weekday'."
              (setq rtn (apply 'org-agenda-get-day-entries
                               file date
                               org-agenda-entry-types)))))
-         (setq rtnall (append rtnall rtn))))
+         (setq rtnall (append rtnall rtn)))) ;; all entries
       (if org-agenda-include-diary
          (let ((org-agenda-search-headline-for-time t))
            (require 'diary-lib)
@@ -3530,7 +3699,7 @@ given in `org-agenda-start-on-weekday'."
            (put-text-property s (1- (point)) 'org-day-cnt day-cnt)
            (when todayp
              (put-text-property s (1- (point)) 'org-today t))
-           (if rtnall (insert
+           (if rtnall (insert ;; all entries
                        (org-finalize-agenda-entries
                         (org-agenda-add-time-grid-maybe
                          rtnall ndays todayp))
@@ -3540,21 +3709,20 @@ given in `org-agenda-start-on-weekday'."
     (when (and org-agenda-clockreport-mode clocktable-start)
       (let ((org-agenda-files (org-agenda-files nil 'ifmode))
            ;; the above line is to ensure the restricted range!
-           (p org-agenda-clockreport-parameter-plist)
+           (p (copy-sequence org-agenda-clockreport-parameter-plist))
            tbl)
        (setq p (org-plist-delete p :block))
        (setq p (plist-put p :tstart clocktable-start))
        (setq p (plist-put p :tend clocktable-end))
        (setq p (plist-put p :scope 'agenda))
        (when (and (eq org-agenda-clockreport-mode 'with-filter)
-                  (setq filter (or org-agenda-filter-while-redo
-                                   (get 'org-agenda-filter :preset-filter))))
+                  (setq filter (or org-agenda-tag-filter-while-redo
+                                   (get 'org-agenda-tag-filter :preset-filter))))
          (setq p (plist-put p :tags (mapconcat (lambda (x)
                                                  (if (string-match "[<>=]" x)
                                                      ""
                                                    x))
                                                filter ""))))
-       (message "%s" (plist-get p :tags)) (sit-for 2)
        (setq tbl (apply 'org-get-clocktable p))
        (insert tbl)))
     (goto-char (point-min))
@@ -3569,6 +3737,8 @@ given in `org-agenda-start-on-weekday'."
            (recenter 1))))
     (goto-char (or start-pos 1))
     (add-text-properties (point-min) (point-max) '(org-agenda-type agenda))
+    (if (eq org-agenda-show-log 'clockcheck)
+       (org-agenda-show-clocking-issues))
     (org-finalize-agenda)
     (setq buffer-read-only t)
     (message "")))
@@ -3677,7 +3847,7 @@ in `org-agenda-text-search-extra-files'."
         (full-words org-agenda-search-view-force-full-words)
         (org-agenda-text-search-extra-files org-agenda-text-search-extra-files)
         regexp rtn rtnall files file pos
-        marker category tags c neg re boolean
+        marker category org-category-pos tags c neg re boolean
         ee txt beg end words regexps+ regexps- hdl-only buffer beg1 str)
     (unless (and (not edit-at)
                 (stringp string)
@@ -3758,9 +3928,9 @@ in `org-agenda-text-search-extra-files'."
            regexps+))
     (setq regexps+ (sort regexps+ (lambda (a b) (> (length a) (length b)))))
     (if (not regexps+)
-       (setq regexp (concat "^" org-outline-regexp))
+       (setq regexp org-outline-regexp-bol)
       (setq regexp (pop regexps+))
-      (if hdl-only (setq regexp (concat "^" org-outline-regexp ".*?"
+      (if hdl-only (setq regexp (concat org-outline-regexp-bol ".*?"
                                        regexp))))
     (setq files (org-agenda-files nil 'ifmode))
     (when (eq (car org-agenda-text-search-extra-files) 'agenda-archives)
@@ -3781,7 +3951,7 @@ in `org-agenda-text-search-extra-files'."
                                    file))))
        (with-current-buffer buffer
          (with-syntax-table (org-search-syntax-table)
-           (unless (org-mode-p)
+           (unless (eq major-mode 'org-mode)
              (error "Agenda file %s is not in `org-mode'" file))
            (let ((case-fold-search t))
              (save-excursion
@@ -3791,7 +3961,7 @@ in `org-agenda-text-search-extra-files'."
                                        org-agenda-restrict-end)
                    (widen))
                  (goto-char (point-min))
-                 (unless (or (org-on-heading-p)
+                 (unless (or (org-at-heading-p)
                              (outline-next-heading))
                    (throw 'nextfile t))
                  (goto-char (max (point-min) (1- (point))))
@@ -3821,8 +3991,9 @@ in `org-agenda-text-search-extra-files'."
                      (goto-char beg)
                      (setq marker (org-agenda-new-marker (point))
                            category (org-get-category)
+                           org-category-pos (get-text-property (point) 'org-category-position)
                            tags (org-get-tags-at (point))
-                           txt (org-format-agenda-item
+                           txt (org-agenda-format-item
                                 ""
                                 (buffer-substring-no-properties
                                  beg1 (point-at-eol))
@@ -3832,6 +4003,7 @@ in `org-agenda-text-search-extra-files'."
                        'org-todo-regexp org-todo-regexp
                        'org-complex-heading-regexp org-complex-heading-regexp
                        'priority 1000 'org-category category
+                       'org-category-position org-category-pos
                        'type "search")
                      (push txt ee)
                      (goto-char (1- end))))))))))
@@ -3972,7 +4144,7 @@ The prefix arg TODO-ONLY limits the search to TODO entries."
                       (format "ORG-AGENDA-ERROR: No such org-file %s" file))
                  rtnall (append rtnall rtn))
          (with-current-buffer buffer
-           (unless (org-mode-p)
+           (unless (eq major-mode 'org-mode)
              (error "Agenda file %s is not in `org-mode'" file))
            (save-excursion
              (save-restriction
@@ -4014,7 +4186,7 @@ This is basically a temporary global variable that can be set and then
 used by user-defined selections using `org-agenda-skip-function'.")
 
 (defvar org-agenda-overriding-header nil
-  "When this is set during todo and tags searches, will replace header.
+  "When set during agenda, todo and tags searches it replaces the header.
 This variable should not be set directly, but custom commands can bind it
 in the options section.")
 
@@ -4068,7 +4240,7 @@ See `org-agenda-skip-if' for details."
 (defun org-agenda-skip-if (subtree conditions)
   "Checks current entity for CONDITIONS.
 If SUBTREE is non-nil, the entire subtree is checked.  Otherwise, only
-the entry, i.e. the text before the next heading is checked.
+the entry (i.e. the text before the next heading) is checked.
 
 CONDITIONS is a list of symbols, boolean OR is used to combine the results
 from different tests.  Valid conditions are:
@@ -4094,12 +4266,12 @@ keywords, which may include \"*\" to match any todo keyword.
 
 would skip all entries with \"TODO\" or \"WAITING\" keywords.
 
-Instead of a list a keyword class may be given
+Instead of a list, a keyword class may be given.  For example:
 
     (org-agenda-skip-entry-if 'nottodo 'done)
 
 would skip entries that haven't been marked with any of \"DONE\"
-keywords. Possible classes are: `todo', `done', `any'.
+keywords.  Possible classes are: `todo', `done', `any'.
 
 If any of these conditions is met, this function returns the end point of
 the entity, causing the search to continue from there.  This is a function
@@ -4132,8 +4304,8 @@ that can be put into `org-agenda-skip-function' for the duration of a command."
           (stringp (nth 1 m))
           (not (re-search-forward (nth 1 m) end t)))
       (and (or
-           (setq m (memq 'todo conditions))
-           (setq m (memq 'nottodo conditions)))
+           (setq m (memq 'nottodo conditions))
+           (setq m (memq 'todo conditions)))
           (org-agenda-skip-if-todo m end)))
      end)))
 
@@ -4196,9 +4368,11 @@ of what a project is and how to check if it stuck, customize the variable
                          "\\)\\>"))
         (tags (nth 2 org-stuck-projects))
         (tags-re (if (member "*" tags)
-                     (org-re "^\\*+ .*:[[:alnum:]_@#%]+:[ \t]*$")
+                     (concat org-outline-regexp-bol
+                             (org-re ".*:[[:alnum:]_@#%]+:[ \t]*$"))
                    (if tags
-                       (concat "^\\*+ .*:\\("
+                       (concat org-outline-regexp-bol
+                               ".*:\\("
                                (mapconcat 'identity tags "\\|")
                                (org-re "\\):[[:alnum:]_@#%:]*[ \t]*$")))))
         (gen-re (nth 3 org-stuck-projects))
@@ -4223,7 +4397,7 @@ of what a project is and how to check if it stuck, customize the variable
 
 (defvar org-disable-agenda-to-diary nil)          ;Dynamically-scoped param.
 (defvar list-diary-entries-hook)
-
+(defvar diary-time-regexp)
 (defun org-get-entries-from-diary (date)
   "Get the (Emacs Calendar) diary entries for DATE."
   (require 'diary-lib)
@@ -4254,7 +4428,14 @@ of what a project is and how to check if it stuck, customize the variable
          ;; Add prefix to each line and extend the text properties
          (if (zerop (buffer-size))
              (setq entries nil)
-           (setq entries (buffer-substring (point-min) (- (point-max) 1)))))
+           (setq entries (buffer-substring (point-min) (- (point-max) 1)))
+           (setq entries
+                 (with-temp-buffer
+                   (insert entries) (goto-char (point-min))
+                   (while (re-search-forward "\n[ \t]+\\(.+\\)$" nil t)
+                     (unless (save-match-data (string-match diary-time-regexp (match-string 1)))
+                       (replace-match (concat "; " (match-string 1)))))
+                   (buffer-string)))))
        (set-buffer-modified-p nil)
        (kill-buffer diary-fancy-buffer)))
     (when entries
@@ -4262,7 +4443,7 @@ of what a project is and how to check if it stuck, customize the variable
       (setq entries
            (mapcar
             (lambda (x)
-              (setq x (org-format-agenda-item "" x "Diary" nil 'time))
+              (setq x (org-agenda-format-item "" x "Diary" nil 'time))
               ;; Extend the text properties to the beginning of the line
               (org-add-props x (text-properties-at (1- (length x)) x)
                 'type "diary" 'date date 'face 'org-agenda-diary))
@@ -4407,7 +4588,7 @@ the documentation of `org-diary'."
        ;; If file does not exist, make sure an error message ends up in diary
        (list (format "ORG-AGENDA-ERROR: No such org-file %s" file))
       (with-current-buffer buffer
-       (unless (org-mode-p)
+       (unless (eq major-mode 'org-mode)
          (error "Agenda file %s is not in `org-mode'" file))
        (let ((case-fold-search nil))
          (save-excursion
@@ -4420,7 +4601,8 @@ the documentation of `org-diary'."
              (while (setq arg (pop args))
                (cond
                 ((and (eq arg :todo)
-                      (equal date (calendar-current-date)))
+                      (equal date (calendar-gregorian-from-absolute
+                                   (org-today))))
                  (setq rtn (org-agenda-get-todos))
                  (setq results (append results rtn)))
                 ((eq arg :timestamp)
@@ -4443,6 +4625,7 @@ the documentation of `org-diary'."
                  (setq results (append results rtn))))))))
        results))))
 
+(defvar org-heading-keyword-regexp-format) ; defined in org.el
 (defun org-agenda-get-todos ()
   "Return the TODO information for agenda display."
   (let* ((props (list 'face nil
@@ -4454,47 +4637,63 @@ the documentation of `org-diary'."
                      'help-echo
                      (format "mouse-2 or RET jump to org file %s"
                              (abbreviate-file-name buffer-file-name))))
-        (regexp (concat "^\\*+[ \t]+\\("
-                        (if org-select-this-todo-keyword
-                            (if (equal org-select-this-todo-keyword "*")
-                                org-todo-regexp
-                              (concat "\\<\\("
-                                      (mapconcat 'identity (org-split-string org-select-this-todo-keyword "|") "\\|")
-                                    "\\)\\>"))
-                          org-not-done-regexp)
-                        "[^\n\r]*\\)"))
-        marker priority category tags todo-state
+        (regexp (format org-heading-keyword-regexp-format
+                        (cond
+                         ((and org-select-this-todo-keyword
+                               (equal org-select-this-todo-keyword "*"))
+                          org-todo-regexp)
+                         (org-select-this-todo-keyword
+                          (concat "\\("
+                                  (mapconcat 'identity
+                                             (org-split-string
+                                              org-select-this-todo-keyword
+                                              "|")
+                                             "\\|") "\\)"))
+                         (t org-not-done-regexp))))
+        marker priority category org-category-pos tags todo-state
         ee txt beg end)
     (goto-char (point-min))
     (while (re-search-forward regexp nil t)
       (catch :skip
        (save-match-data
          (beginning-of-line)
+         (org-agenda-skip)
          (setq beg (point) end (save-excursion (outline-next-heading) (point)))
          (when (org-agenda-check-for-timestamp-as-reason-to-ignore-todo-item end)
            (goto-char (1+ beg))
            (or org-agenda-todo-list-sublevels (org-end-of-subtree 'invisible))
            (throw :skip nil)))
-       (goto-char beg)
-       (org-agenda-skip)
-       (goto-char (match-beginning 1))
+       (goto-char (match-beginning 2))
        (setq marker (org-agenda-new-marker (match-beginning 0))
              category (org-get-category)
-             txt (match-string 1)
+             org-category-pos (get-text-property (point) 'org-category-position)
+             txt (org-trim
+                  (buffer-substring (match-beginning 2) (match-end 0)))
              tags (org-get-tags-at (point))
-             txt (org-format-agenda-item "" txt category tags)
+             txt (org-agenda-format-item "" txt category tags)
              priority (1+ (org-get-priority txt))
              todo-state (org-get-todo-state))
        (org-add-props txt props
          'org-marker marker 'org-hd-marker marker
          'priority priority 'org-category category
+         'org-category-position org-category-pos
          'type "todo" 'todo-state todo-state)
        (push txt ee)
        (if org-agenda-todo-list-sublevels
-           (goto-char (match-end 1))
+           (goto-char (match-end 2))
          (org-end-of-subtree 'invisible))))
     (nreverse ee)))
 
+(defun org-agenda-todo-custom-ignore-p (time n)
+  "Check whether timestamp is farther away then n number of days.
+This function is invoked if `org-agenda-todo-ignore-deadlines',
+`org-agenda-todo-ignore-scheduled' or
+`org-agenda-todo-ignore-timestamp' is set to an integer."
+  (let ((days (org-days-to-time time)))
+    (if (>= n 0)
+       (>= days n)
+      (<= days n))))
+
 ;;;###autoload
 (defun org-agenda-check-for-timestamp-as-reason-to-ignore-todo-item
   (&optional end)
@@ -4514,6 +4713,9 @@ the documentation of `org-diary'."
                 (> (org-days-to-time (match-string 1)) 0))
                ((eq org-agenda-todo-ignore-scheduled 'past)
                 (<= (org-days-to-time (match-string 1)) 0))
+               ((numberp org-agenda-todo-ignore-scheduled)
+                (org-agenda-todo-custom-ignore-p
+                 (match-string 1) org-agenda-todo-ignore-scheduled))
                (t)))
          (and org-agenda-todo-ignore-deadlines
               (re-search-forward org-deadline-time-regexp end t)
@@ -4525,6 +4727,9 @@ the documentation of `org-diary'."
                 (> (org-days-to-time (match-string 1)) 0))
                ((eq org-agenda-todo-ignore-deadlines 'past)
                 (<= (org-days-to-time (match-string 1)) 0))
+               ((numberp org-agenda-todo-ignore-deadlines)
+                (org-agenda-todo-custom-ignore-p
+                 (match-string 1) org-agenda-todo-ignore-deadlines))
                (t (org-deadline-close (match-string 1)))))
          (and org-agenda-todo-ignore-timestamp
               (let ((buffer (current-buffer))
@@ -4547,6 +4752,9 @@ the documentation of `org-diary'."
                       (> (org-days-to-time (match-string 1)) 0))
                      ((eq org-agenda-todo-ignore-timestamp 'past)
                       (<= (org-days-to-time (match-string 1)) 0))
+                     ((numberp org-agenda-todo-ignore-timestamp)
+                      (org-agenda-todo-custom-ignore-p
+                       (match-string 1) org-agenda-todo-ignore-timestamp))
                      (t))))))))))
 
 (defconst org-agenda-no-heading-message
@@ -4554,7 +4762,7 @@ the documentation of `org-diary'."
 
 (defun org-agenda-get-timestamps ()
   "Return the date stamp information for agenda display."
-  (let* ((props (list 'face nil
+  (let* ((props (list 'face 'org-agenda-calendar-event
                      'org-not-done-regexp org-not-done-regexp
                      'org-todo-regexp org-todo-regexp
                      'org-complex-heading-regexp org-complex-heading-regexp
@@ -4583,19 +4791,23 @@ the documentation of `org-diary'."
           "\\|\\(<[0-9]+-[0-9]+-[0-9]+[^>\n]+?\\+[0-9]+[dwmy]>\\)"
           "\\|\\(<%%\\(([^>\n]+)\\)>\\)"))
         marker hdmarker deadlinep scheduledp clockp closedp inactivep
-        donep tmp priority category ee txt timestr tags b0 b3 e3 head
-        todo-state end-of-match)
+        donep tmp priority category org-category-pos ee txt timestr tags
+        b0 b3 e3 head todo-state end-of-match show-all)
     (goto-char (point-min))
     (while (setq end-of-match (re-search-forward regexp nil t))
       (setq b0 (match-beginning 0)
-           b3 (match-beginning 3) e3 (match-end 3))
+           b3 (match-beginning 3) e3 (match-end 3)
+           todo-state (save-match-data (ignore-errors (org-get-todo-state)))
+           show-all (or (eq org-agenda-repeating-timestamp-show-all t)
+                        (member todo-state
+                                org-agenda-repeating-timestamp-show-all)))
       (catch :skip
        (and (org-at-date-range-p) (throw :skip nil))
        (org-agenda-skip)
        (if (and (match-end 1)
                 (not (= d1 (org-time-string-to-absolute
-                            (match-string 1) d1 nil
-                            org-agenda-repeating-timestamp-show-all))))
+                            (match-string 1) d1 nil show-all
+                            (current-buffer) b0))))
            (throw :skip nil))
        (if (and e3
                 (not (org-diary-sexp-entry (buffer-substring b3 e3) "" date)))
@@ -4612,7 +4824,6 @@ the documentation of `org-diary'."
              clockp (and org-agenda-include-inactive-timestamps
                          (or (string-match org-clock-string tmp)
                              (string-match "]-+\\'" tmp)))
-             todo-state (ignore-errors (org-get-todo-state))
              donep (member todo-state org-done-keywords))
        (if (or scheduledp deadlinep closedp clockp
                (and donep org-agenda-skip-timestamp-if-done))
@@ -4621,24 +4832,26 @@ the documentation of `org-diary'."
            ;; substring should only run to end of time stamp
            (setq timestr (substring timestr 0 (match-end 0))))
        (setq marker (org-agenda-new-marker b0)
-             category (org-get-category b0))
+             category (org-get-category b0)
+             org-category-pos (get-text-property b0 'org-category-position))
        (save-excursion
-         (if (not (re-search-backward "^\\*+ " nil t))
+         (if (not (re-search-backward org-outline-regexp-bol nil t))
              (setq txt org-agenda-no-heading-message)
            (goto-char (match-beginning 0))
            (setq hdmarker (org-agenda-new-marker)
                  tags (org-get-tags-at))
            (looking-at "\\*+[ \t]+\\([^\r\n]+\\)")
-           (setq head (match-string 1))
-           (setq txt (org-format-agenda-item
+           (setq head (or (match-string 1) ""))
+           (setq txt (org-agenda-format-item
                       (if inactivep org-agenda-inactive-leader nil)
-                      head category tags timestr nil
+                      head category tags timestr
                       remove-re)))
          (setq priority (org-get-priority txt))
          (org-add-props txt props
            'org-marker marker 'org-hd-marker hdmarker)
          (org-add-props txt nil 'priority priority
                         'org-category category 'date date
+                        'org-category-position org-category-pos
                         'todo-state todo-state
                         'type "timestamp")
          (push txt ee))
@@ -4650,14 +4863,14 @@ the documentation of `org-diary'."
 (defun org-agenda-get-sexps ()
   "Return the sexp information for agenda display."
   (require 'diary-lib)
-  (let* ((props (list 'face nil
+  (let* ((props (list 'face 'org-agenda-calendar-sexp
                      'mouse-face 'highlight
                      'help-echo
                      (format "mouse-2 or RET jump to org file %s"
                              (abbreviate-file-name buffer-file-name))))
         (regexp "^&?%%(")
-        marker category ee txt tags entry result beg b sexp sexp-entry
-        todo-state)
+        marker category org-category-pos ee txt tags entry
+        result beg b sexp sexp-entry todo-state)
     (goto-char (point-min))
     (while (re-search-forward regexp nil t)
       (catch :skip
@@ -4674,6 +4887,7 @@ the documentation of `org-diary'."
        (when result
          (setq marker (org-agenda-new-marker beg)
                category (org-get-category beg)
+               org-category-pos (get-text-property beg 'org-category-position)
                todo-state (org-get-todo-state))
 
          (dolist (r (if (stringp result)
@@ -4683,28 +4897,53 @@ the documentation of `org-diary'."
                (setq txt r)
              (setq txt "SEXP entry returned empty string"))
 
-           (setq txt (org-format-agenda-item
+           (setq txt (org-agenda-format-item
                       "" txt category tags 'time))
            (org-add-props txt props 'org-marker marker)
            (org-add-props txt nil
              'org-category category 'date date 'todo-state todo-state
+             'org-category-position org-category-pos
              'type "sexp")
            (push txt ee)))))
     (nreverse ee)))
 
-(defun org-diary-class (m1 d1 y1 m2 d2 y2 dayname &rest skip-weeks)
+;; Calendar sanity: define some functions that are independent of
+;; `calendar-date-style'.
+;; Normally I would like to use ISO format when calling the diary functions,
+;; but to make sure we still have Emacs 22 compatibility we bind
+;; also `european-calendar-style' and use european format
+(defun org-anniversary (year month day &optional mark)
+  "Like `diary-anniversary', but with fixed (ISO) order of arguments."
+  (org-no-warnings
+   (let ((calendar-date-style 'european) (european-calendar-style t))
+     (diary-anniversary day month year mark))))
+(defun org-cyclic (N year month day &optional mark)
+  "Like `diary-cyclic', but with fixed (ISO) order of arguments."
+  (org-no-warnings
+   (let ((calendar-date-style 'european)       (european-calendar-style t))
+     (diary-cyclic N day month year mark))))
+(defun org-block (Y1 M1 D1 Y2 M2 D2 &optional mark)
+  "Like `diary-block', but with fixed (ISO) order of arguments."
+  (org-no-warnings
+   (let ((calendar-date-style 'european)       (european-calendar-style t))
+     (diary-block D1 M1 Y1 D2 M2 Y2 mark))))
+(defun org-date (year month day &optional mark)
+  "Like `diary-date', but with fixed (ISO) order of arguments."
+  (org-no-warnings
+   (let ((calendar-date-style 'european)       (european-calendar-style t))
+     (diary-date day month year mark))))
+(defalias 'org-float 'diary-float)
+
+;; Define the` org-class' function
+(defun org-class (y1 m1 d1 y2 m2 d2 dayname &rest skip-weeks)
   "Entry applies if date is between dates on DAYNAME, but skips SKIP-WEEKS.
-The order of the first 2 times 3 arguments depends on the variable
-`calendar-date-style' or, if that is not defined, on `european-calendar-style'.
-So for American calendars, give this as MONTH DAY YEAR, for European as
-DAY MONTH YEAR, and for ISO as YEAR MONTH DAY.
-DAYNAME is a number between 0 (Sunday) and 6 (Saturday).  SKIP-WEEKS
-is any number of ISO weeks in the block period for which the item should
-be skipped."
-  (let* ((date1 (calendar-absolute-from-gregorian
-                (org-order-calendar-date-args m1 d1 y1)))
-        (date2 (calendar-absolute-from-gregorian
-                (org-order-calendar-date-args m2 d2 y2)))
+DAYNAME is a number between 0 (Sunday) and 6 (Saturday).
+SKIP-WEEKS is any number of ISO weeks in the block period for which the
+item should be skipped.  If any of the SKIP-WEEKS arguments is the symbol
+`holidays', then any date that is known by the Emacs calendar to be a
+holiday will also be skipped."
+  (let* ((date1 (calendar-absolute-from-gregorian (list m1 d1 y1)))
+        (date2 (calendar-absolute-from-gregorian (list m2 d2 y2)))
         (d (calendar-absolute-from-gregorian date)))
     (and
      (<= date1 d)
@@ -4714,8 +4953,30 @@ be skipped."
         (progn
           (require 'cal-iso)
           (not (member (car (calendar-iso-from-absolute d)) skip-weeks))))
+     (not (and (memq 'holidays skip-weeks)
+              (calendar-check-holidays date)))
      entry)))
 
+(defun org-diary-class (m1 d1 y1 m2 d2 y2 dayname &rest skip-weeks)
+  "Like `org-class', but honor `calendar-date-style'.
+The order of the first 2 times 3 arguments depends on the variable
+`calendar-date-style' or, if that is not defined, on `european-calendar-style'.
+So for American calendars, give this as MONTH DAY YEAR, for European as
+DAY MONTH YEAR, and for ISO as YEAR MONTH DAY.
+DAYNAME is a number between 0 (Sunday) and 6 (Saturday).  SKIP-WEEKS
+is any number of ISO weeks in the block period for which the item should
+be skipped.
+
+This function is here only for backward compatibility and it is deprecated,
+please use `org-class' instead."
+  (let* ((date1 (org-order-calendar-date-args m1 d1 y1))
+        (date2 (org-order-calendar-date-args m2 d2 y2)))
+    (org-class
+     (nth 2 date1) (car date1) (nth 1 date1)
+     (nth 2 date2) (car date2) (nth 1 date2)
+     dayname skip-weeks)))
+(make-obsolete 'org-diary-class 'org-class "")
+
 (defalias 'org-get-closed 'org-agenda-get-progress)
 (defun org-agenda-get-progress ()
   "Return the logged TODO entries for agenda display."
@@ -4728,7 +4989,9 @@ be skipped."
                              (abbreviate-file-name buffer-file-name))))
         (items (if (consp org-agenda-show-log)
                    org-agenda-show-log
-                 org-agenda-log-mode-items))
+                 (if (eq org-agenda-show-log 'clockcheck)
+                     '(clock)
+                   org-agenda-log-mode-items)))
         (parts
          (delq nil
                (list
@@ -4748,8 +5011,8 @@ be skipped."
                            (list 0 0 0 (nth 1 date) (car date) (nth 2 date))))
                    1 11))))
         (org-agenda-search-headline-for-time nil)
-        marker hdmarker priority category tags closedp statep clockp state
-        ee txt extra timestr rest clocked)
+        marker hdmarker priority category org-category-pos tags closedp
+        statep clockp state ee txt extra timestr rest clocked)
     (goto-char (point-min))
     (while (re-search-forward regexp nil t)
       (catch :skip
@@ -4760,29 +5023,30 @@ be skipped."
              clockp (not (or closedp statep))
              state (and statep (match-string 2))
              category (org-get-category (match-beginning 0))
-             timestr (buffer-substring (match-beginning 0) (point-at-eol))
-             )
+             org-category-pos (get-text-property (match-beginning 0) 'org-category-position)
+             timestr (buffer-substring (match-beginning 0) (point-at-eol)))
        (when (string-match "\\]" timestr)
          ;; substring should only run to end of time stamp
          (setq rest (substring timestr (match-end 0))
                timestr (substring timestr 0 (match-end 0)))
          (if (and (not closedp) (not statep)
-                  (string-match "\\([0-9]\\{1,2\\}:[0-9]\\{2\\}\\)\\].*?\\([0-9]\\{1,2\\}:[0-9]\\{2\\}\\)" rest))
+                  (string-match "\\([0-9]\\{1,2\\}:[0-9]\\{2\\}\\)\\].*?\\([0-9]\\{1,2\\}:[0-9]\\{2\\}\\)"
+                                rest))
              (progn (setq timestr (concat (substring timestr 0 -1)
                                           "-" (match-string 1 rest) "]"))
                     (setq clocked (match-string 2 rest)))
            (setq clocked "-")))
        (save-excursion
-         (setq extra nil)
-         (cond
-          ((not org-agenda-log-mode-add-notes))
-          (statep
-           (and (looking-at ".*\n[ \t]*\\([^-\n \t].*?\\)[ \t]*$")
-                (setq extra (match-string 1))))
-          (clockp
-           (and (looking-at ".*\n[ \t]*-[ \t]+\\([^-\n \t].*?\\)[ \t]*$")
-                (setq extra (match-string 1)))))
-         (if (not (re-search-backward "^\\*+ " nil t))
+         (setq extra
+               (cond
+                ((not org-agenda-log-mode-add-notes) nil)
+                (statep
+                 (and (looking-at ".*\\\\\n[ \t]*\\([^-\n \t].*?\\)[ \t]*$")
+                      (match-string 1)))
+                (clockp
+                 (and (looking-at ".*\n[ \t]*-[ \t]+\\([^-\n \t].*?\\)[ \t]*$")
+                      (match-string 1)))))
+         (if (not (re-search-backward org-outline-regexp-bol nil t))
              (setq txt org-agenda-no-heading-message)
            (goto-char (match-beginning 0))
            (setq hdmarker (org-agenda-new-marker)
@@ -4794,7 +5058,7 @@ be skipped."
                  (setq txt (concat (substring txt 0 (match-beginning 1))
                                    " - " extra " " (match-string 2 txt)))
                (setq txt (concat txt " - " extra))))
-           (setq txt (org-format-agenda-item
+           (setq txt (org-agenda-format-item
                       (cond
                        (closedp "Closed:    ")
                            (statep (concat "State:     (" state ")"))
@@ -4804,12 +5068,132 @@ be skipped."
          (org-add-props txt props
            'org-marker marker 'org-hd-marker hdmarker 'face 'org-agenda-done
            'priority priority 'org-category category
+           'org-category-position org-category-pos
            'type "closed" 'date date
            'undone-face 'org-warning 'done-face 'org-agenda-done)
          (push txt ee))
        (goto-char (point-at-eol))))
     (nreverse ee)))
 
+(defun org-agenda-show-clocking-issues ()
+  "Add overlays, showing issues with clocking.
+See also the user option `org-agenda-clock-consistency-checks'."
+  (interactive)
+  (let* ((pl org-agenda-clock-consistency-checks)
+        (re (concat "^[ \t]*"
+                    org-clock-string
+                    "[ \t]+"
+                    "\\(\\[.*?\\]\\)" ; group 1 is first stamp
+                    "\\(-\\{1,3\\}\\(\\[.*?\\]\\)\\)?")) ; group 3 is second
+        (tlstart 0.)
+        (tlend 0.)
+        (maxtime (org-hh:mm-string-to-minutes
+                  (or (plist-get pl :max-duration) "24:00")))
+        (mintime (org-hh:mm-string-to-minutes
+                  (or (plist-get pl :min-duration) 0)))
+        (maxgap  (org-hh:mm-string-to-minutes
+                  ;; default 30:00 means never complain
+                  (or (plist-get pl :max-gap) "30:00")))
+        (gapok (mapcar 'org-hh:mm-string-to-minutes
+                       (plist-get pl :gap-ok-around)))
+        (def-face (or (plist-get pl :default-face)
+                      '((:background "DarkRed") (:foreground "white"))))
+        issue face m te ts dt ov)
+    (goto-char (point-min))
+    (while (re-search-forward " Clocked: +(-\\|\\([0-9]+:[0-9]+\\))" nil t)
+      (setq issue nil face def-face)
+      (catch 'next
+       (setq m (org-get-at-bol 'org-marker)
+             te nil ts nil)
+       (unless (and m (markerp m))
+         (setq issue "No valid clock line") (throw 'next t))
+       (org-with-point-at m
+         (save-excursion
+           (goto-char (point-at-bol))
+           (unless (looking-at re)
+             (error "No valid Clock line")
+             (throw 'next t))
+           (unless (match-end 3)
+             (setq issue "No end time"
+                   face (or (plist-get pl :no-end-time-face) face))
+             (throw 'next t))
+           (setq ts (match-string 1)
+                 te (match-string 3)
+                 ts (org-float-time
+                     (apply 'encode-time (org-parse-time-string ts)))
+                 te (org-float-time
+                     (apply 'encode-time (org-parse-time-string te)))
+                 dt (- te ts))))
+       (cond
+        ((> dt (* 60 maxtime))
+         ;; a very long clocking chunk
+         (setq issue (format "Clocking interval is very long: %s"
+                             (org-minutes-to-hh:mm-string
+                              (floor (/ (float dt) 60.))))
+               face (or (plist-get pl :long-face) face)))
+        ((< dt (* 60 mintime))
+         ;; a very short clocking chunk
+         (setq issue (format "Clocking interval is very short: %s"
+                             (org-minutes-to-hh:mm-string
+                              (floor (/ (float dt) 60.))))
+               face (or (plist-get pl :short-face) face)))
+        ((and (> tlend 0) (< ts tlend))
+         ;; Two clock entries are overlapping
+         (setq issue (format "Clocking overlap: %d minutes"
+                             (/ (- tlend ts) 60))
+               face (or (plist-get pl :overlap-face) face)))
+        ((and (> tlend 0) (> ts (+ tlend (* 60 maxgap))))
+         ;; There is a gap, lets see if we need to report it
+         (unless (org-agenda-check-clock-gap tlend ts gapok)
+           (setq issue (format "Clocking gap: %d minutes"
+                                 (/ (- ts tlend) 60))
+                 face (or (plist-get pl :gap-face) face))))
+        (t nil)))
+      (setq tlend (or te tlend) tlstart (or ts tlstart))
+      (when issue
+       ;; OK, there was some issue, add an overlay to show the issue
+       (setq ov (make-overlay (point-at-bol) (point-at-eol)))
+       (overlay-put ov 'before-string
+                    (concat
+                     (org-add-props
+                         (format "%-43s" (concat " " issue))
+                         nil
+                       'face face)
+                     "\n"))
+       (overlay-put ov 'evaporate t)))))
+
+(defun org-agenda-check-clock-gap (t1 t2 ok-list)
+  "Check if gap T1 -> T2 contains one of the OK-LIST time-of-day values."
+  (catch 'exit
+    (unless ok-list
+      ;; there are no OK times for gaps...
+      (throw 'exit nil))
+    (if (> (- (/ t2 36000) (/ t1 36000)) 24)
+       ;; This is more than 24 hours, so it is OK.
+       ;; because we have at least one OK time, that must be in the
+       ;; 24 hour interval.
+       (throw 'exit t))
+    ;; We have a shorter gap.
+    ;; Now we have to get the minute of the day when these times are
+    (let* ((t1dec (decode-time (seconds-to-time t1)))
+          (t2dec (decode-time (seconds-to-time t2)))
+          ;; compute the minute on the day
+          (min1 (+ (nth 1 t1dec) (* 60 (nth 2 t1dec))))
+          (min2 (+ (nth 1 t2dec) (* 60 (nth 2 t2dec)))))
+      (when (< min2 min1)
+       ;; if min2 is smaller than min1, this means it is on the next day.
+       ;; Wrap it to after midnight.
+       (setq min2 (+ min2 1440)))
+      ;; Now check if any of the OK times is in the gap
+      (mapc (lambda (x)
+             ;; Wrap the time to after midnight if necessary
+             (if (< x min1) (setq x (+ x 1440)))
+             ;; Check if in interval
+             (and (<= min1 x) (>= min2 x) (throw 'exit t)))
+           ok-list)
+      ;; Nope, this gap is not OK
+      nil)))
+
 (defun org-agenda-get-deadlines ()
   "Return the deadline information for agenda display."
   (let* ((props (list 'mouse-face 'highlight
@@ -4822,9 +5206,9 @@ be skipped."
         (regexp org-deadline-time-regexp)
         (todayp (org-agenda-todayp date)) ; DATE bound by calendar
         (d1 (calendar-absolute-from-gregorian date))  ; DATE bound by calendar
-        d2 diff dfrac wdays pos pos1 category tags
-        suppress-prewarning
-        ee txt head face s todo-state upcomingp donep timestr)
+        d2 diff dfrac wdays pos pos1 category org-category-pos
+        tags suppress-prewarning ee txt head face s todo-state
+        show-all upcomingp donep timestr)
     (goto-char (point-min))
     (while (re-search-forward regexp nil t)
       (setq suppress-prewarning nil)
@@ -4842,15 +5226,19 @@ be skipped."
        (setq s (match-string 1)
              txt nil
              pos (1- (match-beginning 1))
+             todo-state (save-match-data (org-get-todo-state))
+             show-all (or (eq org-agenda-repeating-timestamp-show-all t)
+                          (member todo-state
+                                   org-agenda-repeating-timestamp-show-all))
              d2 (org-time-string-to-absolute
-                 (match-string 1) d1 'past
-                 org-agenda-repeating-timestamp-show-all)
+                 (match-string 1) d1 'past show-all
+                 (current-buffer) pos)
              diff (- d2 d1)
              wdays (if suppress-prewarning
                        (let ((org-deadline-warning-days suppress-prewarning))
                          (org-get-wdays s))
                      (org-get-wdays s))
-             dfrac (/ (* 1.0 (- wdays diff)) (max wdays 1))
+             dfrac (- 1 (/ (* 1.0 diff) (max wdays 1)))
              upcomingp (and todayp (> diff 0)))
        ;; When to show a deadline in the calendar:
        ;; If the expiration is within wdays warning time.
@@ -4859,13 +5247,14 @@ be skipped."
                          (and todayp (not org-agenda-only-exact-dates)))
                     (= diff 0)))
            (save-excursion
-             (setq todo-state (org-get-todo-state))
+             ;; (setq todo-state (org-get-todo-state))
              (setq donep (member todo-state org-done-keywords))
              (if (and donep
                       (or org-agenda-skip-deadline-if-done
                           (not (= diff 0))))
                  (setq txt nil)
-               (setq category (org-get-category))
+               (setq category (org-get-category)
+                     org-category-pos (get-text-property (point) 'org-category-position))
                (if (not (re-search-backward "^\\*+[ \t]+" nil t))
                    (setq txt org-agenda-no-heading-message)
                  (goto-char (match-end 0))
@@ -4879,7 +5268,7 @@ be skipped."
                      (setq timestr
                            (concat (substring s (match-beginning 1)) " "))
                    (setq timestr 'time))
-                 (setq txt (org-format-agenda-item
+                 (setq txt (org-agenda-format-item
                             (if (= diff 0)
                                 (car org-agenda-deadline-leaders)
                               (if (functionp
@@ -4892,13 +5281,14 @@ be skipped."
                             head category tags
                             (if (not (= diff 0)) nil timestr)))))
              (when txt
-               (setq face (org-agenda-deadline-face dfrac wdays))
+               (setq face (org-agenda-deadline-face dfrac))
                (org-add-props txt props
                  'org-marker (org-agenda-new-marker pos)
                  'org-hd-marker (org-agenda-new-marker pos1)
                  'priority (+ (- diff)
                               (org-get-priority txt))
                  'org-category category
+                 'org-category-position org-category-pos
                  'todo-state todo-state
                  'type (if upcomingp "upcoming-deadline" "deadline")
                  'date (if upcomingp date d2)
@@ -4907,10 +5297,9 @@ be skipped."
                (push txt ee))))))
     (nreverse ee)))
 
-(defun org-agenda-deadline-face (fraction &optional wdays)
+(defun org-agenda-deadline-face (fraction)
   "Return the face to displaying a deadline item.
 FRACTION is what fraction of the head-warning time has passed."
-  (if (equal wdays 0) (setq fraction 1.))
   (let ((faces org-agenda-deadline-faces) f)
     (catch 'exit
       (while (setq f (pop faces))
@@ -4935,8 +5324,8 @@ FRACTION is what fraction of the head-warning time has passed."
                                        0 'org-hd-marker a))
                              (cons (marker-position mm) a)))
                  deadline-results))
-        d2 diff pos pos1 category tags donep
-        ee txt head pastschedp todo-state face timestr s habitp)
+        d2 diff pos pos1 category org-category-pos tags donep
+        ee txt head pastschedp todo-state face timestr s habitp show-all)
     (goto-char (point-min))
     (while (re-search-forward regexp nil t)
       (catch :skip
@@ -4944,9 +5333,13 @@ FRACTION is what fraction of the head-warning time has passed."
        (setq s (match-string 1)
              txt nil
              pos (1- (match-beginning 1))
+             todo-state (save-match-data (org-get-todo-state))
+             show-all (or (eq org-agenda-repeating-timestamp-show-all t)
+                          (member todo-state
+                                  org-agenda-repeating-timestamp-show-all))
              d2 (org-time-string-to-absolute
-                 (match-string 1) d1 'past
-                 org-agenda-repeating-timestamp-show-all)
+                 (match-string 1) d1 'past show-all
+                 (current-buffer) pos)
              diff (- d2 d1))
        (setq pastschedp (and todayp (< diff 0)))
        ;; When to show a scheduled item in the calendar:
@@ -4956,15 +5349,17 @@ FRACTION is what fraction of the head-warning time has passed."
                       (and todayp (not org-agenda-only-exact-dates)))
                  (= diff 0))
          (save-excursion
-           (setq todo-state (org-get-todo-state))
            (setq donep (member todo-state org-done-keywords))
-           (setq habitp (and (functionp 'org-is-habit-p)
-                             (org-is-habit-p)))
            (if (and donep
-                    (or habitp org-agenda-skip-scheduled-if-done
-                        (not (= diff 0))))
+                    (or org-agenda-skip-scheduled-if-done
+                        (not (= diff 0))
+                        (and (functionp 'org-is-habit-p)
+                             (org-is-habit-p))))
                (setq txt nil)
-             (setq category (org-get-category))
+             (setq habitp (and (functionp 'org-is-habit-p)
+                               (org-is-habit-p)))
+             (setq category (org-get-category)
+                   org-category-pos (get-text-property (point) 'org-category-position))
              (if (not (re-search-backward "^\\*+[ \t]+" nil t))
                  (setq txt org-agenda-no-heading-message)
                (goto-char (match-end 0))
@@ -4988,14 +5383,14 @@ FRACTION is what fraction of the head-warning time has passed."
                    (setq timestr
                          (concat (substring s (match-beginning 1)) " "))
                  (setq timestr 'time))
-               (setq txt (org-format-agenda-item
+               (setq txt (org-agenda-format-item
                           (if (= diff 0)
                               (car org-agenda-scheduled-leaders)
                             (format (nth 1 org-agenda-scheduled-leaders)
                                     (- 1 diff)))
                           head category tags
                           (if (not (= diff 0)) nil timestr)
-                          nil nil habitp))))
+                          nil habitp))))
            (when txt
              (setq face
                    (cond
@@ -5015,6 +5410,7 @@ FRACTION is what fraction of the head-warning time has passed."
                              (org-habit-get-priority habitp)
                            (+ 94 (- 5 diff) (org-get-priority txt)))
                'org-category category
+               'org-category-position org-category-pos
                'org-habit-p habitp
                'todo-state todo-state)
              (push txt ee))))))
@@ -5032,55 +5428,65 @@ FRACTION is what fraction of the head-warning time has passed."
                              (abbreviate-file-name buffer-file-name))))
         (regexp org-tr-regexp)
         (d0 (calendar-absolute-from-gregorian date))
-        marker hdmarker ee txt d1 d2 s1 s2 timestr category todo-state tags pos
-        head donep)
+        marker hdmarker ee txt d1 d2 s1 s2 category org-category-pos
+        todo-state tags pos head donep)
     (goto-char (point-min))
     (while (re-search-forward regexp nil t)
       (catch :skip
        (org-agenda-skip)
        (setq pos (point))
-       (setq timestr (match-string 0)
-             s1 (match-string 1)
-             s2 (match-string 2)
-             d1 (time-to-days (org-time-string-to-time s1))
-             d2 (time-to-days (org-time-string-to-time s2)))
-       (if (and (> (- d0 d1) -1) (> (- d2 d0) -1))
-           ;; Only allow days between the limits, because the normal
-           ;; date stamps will catch the limits.
-           (save-excursion
-             (setq todo-state (org-get-todo-state))
-             (setq donep (member todo-state org-done-keywords))
-             (if (and donep org-agenda-skip-timestamp-if-done)
-                 (throw :skip t))
-             (setq marker (org-agenda-new-marker (point)))
-             (setq category (org-get-category))
-             (if (not (re-search-backward "^\\*+ " nil t))
-                 (setq txt org-agenda-no-heading-message)
-               (goto-char (match-beginning 0))
-               (setq hdmarker (org-agenda-new-marker (point)))
-               (setq tags (org-get-tags-at))
-               (looking-at "\\*+[ \t]+\\([^\r\n]+\\)")
-               (setq head (match-string 1))
-               (let ((remove-re
-                      (if org-agenda-remove-timeranges-from-blocks
-                          (concat
-                           "<" (regexp-quote s1) ".*?>"
-                           "--"
-                           "<" (regexp-quote s2) ".*?>")
-                        nil)))
-                 (setq txt (org-format-agenda-item
-                            (format
-                             (nth (if (= d1 d2) 0 1)
-                                  org-agenda-timerange-leaders)
-                             (1+ (- d0 d1)) (1+ (- d2 d1)))
-                            head category tags
-                            timestr nil remove-re))))
-             (org-add-props txt props
-               'org-marker marker 'org-hd-marker hdmarker
-               'type "block" 'date date
-               'todo-state todo-state
-               'priority (org-get-priority txt) 'org-category category)
-             (push txt ee)))
+       (let ((start-time (match-string 1))
+             (end-time (match-string 2)))
+         (setq s1 (match-string 1)
+               s2 (match-string 2)
+               d1 (time-to-days (org-time-string-to-time s1 (current-buffer) pos))
+               d2 (time-to-days (org-time-string-to-time s2 (current-buffer) pos)))
+         (if (and (> (- d0 d1) -1) (> (- d2 d0) -1))
+             ;; Only allow days between the limits, because the normal
+             ;; date stamps will catch the limits.
+             (save-excursion
+               (setq todo-state (org-get-todo-state))
+               (setq donep (member todo-state org-done-keywords))
+               (if (and donep org-agenda-skip-timestamp-if-done)
+                   (throw :skip t))
+               (setq marker (org-agenda-new-marker (point)))
+               (setq category (org-get-category)
+                     org-category-pos (get-text-property (point) 'org-category-position))
+               (if (not (re-search-backward org-outline-regexp-bol nil t))
+                   (setq txt org-agenda-no-heading-message)
+                 (goto-char (match-beginning 0))
+                 (setq hdmarker (org-agenda-new-marker (point)))
+                 (setq tags (org-get-tags-at))
+                 (looking-at "\\*+[ \t]+\\([^\r\n]+\\)")
+                 (setq head (match-string 1))
+                 (let ((remove-re
+                        (if org-agenda-remove-timeranges-from-blocks
+                            (concat
+                             "<" (regexp-quote s1) ".*?>"
+                             "--"
+                             "<" (regexp-quote s2) ".*?>")
+                          nil)))
+                   (setq txt (org-agenda-format-item
+                              (format
+                               (nth (if (= d1 d2) 0 1)
+                                    org-agenda-timerange-leaders)
+                               (1+ (- d0 d1)) (1+ (- d2 d1)))
+                              head category tags
+                              (cond ((and (= d1 d0) (= d2 d0))
+                                     (concat "<" start-time ">--<" end-time ">"))
+                                     ((= d1 d0)
+                                     (concat "<" start-time ">"))
+                                    ((= d2 d0)
+                                     (concat "<" end-time ">"))
+                                    (t nil))
+                              remove-re))))
+               (org-add-props txt props
+                 'org-marker marker 'org-hd-marker hdmarker
+                 'type "block" 'date date
+                 'todo-state todo-state
+                 'priority (org-get-priority txt) 'org-category category
+                 'org-category-position org-category-pos)
+               (push txt ee))))
        (goto-char pos)))
     ;; Sort the entries by expiration date.
     (nreverse ee)))
@@ -5109,8 +5515,8 @@ The flag is set if the currently compiled format contains a `%e'.")
          (return (cadr entry))
       (return (apply 'create-image (cdr entry)))))))
 
-(defun org-format-agenda-item (extra txt &optional category tags dotime
-                                    noprefix remove-re habitp)
+(defun org-agenda-format-item (extra txt &optional category tags dotime
+                                    remove-re habitp)
   "Format TXT to be inserted into the agenda buffer.
 In particular, it adds the prefix and corresponding text properties.  EXTRA
 must be a string and replaces the `%s' specifier in the prefix format.
@@ -5119,9 +5525,7 @@ category taken from local variable or file name.  It will replace the `%c'
 specifier in the format.  DOTIME, when non-nil, indicates that a
 time-of-day should be extracted from TXT for sorting of this entry, and for
 the `%t' specifier in the format.  When DOTIME is a string, this string is
-searched for a time before TXT is.  NOPREFIX is a flag and indicates that
-only the correctly processes TXT should be returned - this is used by
-`org-agenda-change-all-lines'.  TAGS can be the tags of the headline.
+searched for a time before TXT is.  TAGS can be the tags of the headline.
 Any match of REMOVE-RE will be removed from TXT."
   (save-match-data
     ;; Diary entries sometimes have extra whitespace at the beginning
@@ -5151,9 +5555,9 @@ Any match of REMOVE-RE will be removed from TXT."
                           (if (stringp dotime) dotime "")
                           (and org-agenda-search-headline-for-time txt))))
           (time-of-day (and dotime (org-get-time-of-day ts)))
-          stamp plain s0 s1 s2 t1 t2 rtn srp l
+          stamp plain s0 s1 s2 rtn srp l
           duration thecategory)
-      (and (org-mode-p) buffer-file-name
+      (and (eq major-mode 'org-mode) buffer-file-name
           (add-to-list 'org-agenda-contributing-files buffer-file-name))
       (when (and dotime time-of-day)
        ;; Extract starting and ending time and move them to prefix
@@ -5178,26 +5582,17 @@ Any match of REMOVE-RE will be removed from TXT."
        ;; Normalize the time(s) to 24 hour
        (if s1 (setq s1 (org-get-time-of-day s1 'string t)))
        (if s2 (setq s2 (org-get-time-of-day s2 'string t)))
+
+       ;; Try to set s2 if s1 and `org-agenda-default-appointment-duration' are set
+       (when (and s1 (not s2) org-agenda-default-appointment-duration)
+         (setq s2
+               (org-minutes-to-hh:mm-string
+                (+ (org-hh:mm-string-to-minutes s1) org-agenda-default-appointment-duration))))
+
        ;; Compute the duration
-       (when s1
-         (setq t1 (+ (* 60 (string-to-number (substring s1 0 2)))
-                     (string-to-number (substring s1 3)))
-               t2 (cond
-                   (s2 (+ (* 60 (string-to-number (substring s2 0 2)))
-                          (string-to-number (substring s2 3))))
-                   (org-agenda-default-appointment-duration
-                    (+ t1 org-agenda-default-appointment-duration))
-                   (t nil)))
-         (setq duration (if t2 (- t2 t1)))))
-
-      (when (and s1 (not s2) org-agenda-default-appointment-duration
-                (string-match "\\([0-9]+\\):\\([0-9]+\\)" s1))
-       (let ((m (+ (string-to-number (match-string 2 s1))
-                   (* 60 (string-to-number (match-string 1 s1)))
-                   org-agenda-default-appointment-duration))
-             h)
-         (setq h (/ m 60) m (- m (* h 60)))
-         (setq s2 (format "%02d:%02d" h m))))
+       (when s2
+         (setq duration (- (org-hh:mm-string-to-minutes s2)
+                           (org-hh:mm-string-to-minutes s1)))))
 
       (when (string-match (org-re "\\([ \t]+\\)\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$")
                          txt)
@@ -5210,7 +5605,7 @@ Any match of REMOVE-RE will be removed from TXT."
                     (concat (make-string (max (- 50 (length txt)) 1) ?\ )
                             (match-string 2 txt))
                     t t txt))))
-      (when (org-mode-p)
+      (when (eq major-mode 'org-mode)
        (setq effort
              (condition-case nil
                  (org-get-effort
@@ -5218,45 +5613,48 @@ Any match of REMOVE-RE will be removed from TXT."
                       (get-text-property 0 'org-marker txt)))
                (error nil)))
        (when effort
-         (setq neffort (org-hh:mm-string-to-minutes effort)
-               effort (setq effort (concat "[" effort "]" )))))
+         (setq neffort (org-duration-string-to-minutes effort)
+               effort (setq effort (concat "[" effort "]")))))
+      ;; prevent erroring out with %e format when there is no effort
+      (or effort (setq effort ""))
 
       (when remove-re
        (while (string-match remove-re txt)
          (setq txt (replace-match "" t t txt))))
 
-      ;; Create the final string
-      (if noprefix
-         (setq rtn txt)
-       ;; Prepare the variables needed in the eval of the compiled format
-       (setq time (cond (s2 (concat
-                             (org-agenda-time-of-day-to-ampm-maybe s1)
-                             "-" (org-agenda-time-of-day-to-ampm-maybe s2)
-                             (if org-agenda-timegrid-use-ampm " ")))
-                        (s1 (concat
-                             (org-agenda-time-of-day-to-ampm-maybe s1)
-                             (if org-agenda-timegrid-use-ampm
-                                 "........ "
-                               "......")))
-                        (t ""))
-             extra (or (and (not habitp) extra) "")
-             category (if (symbolp category) (symbol-name category) category)
-             thecategory (copy-sequence category))
-       (if (string-match org-bracket-link-regexp category)
-           (progn
-             (setq l (if (match-end 3)
-                         (- (match-end 3) (match-beginning 3))
-                       (- (match-end 1) (match-beginning 1))))
-             (when (< l (or org-prefix-category-length 0))
-               (setq category (copy-sequence category))
-               (org-add-props category nil
-                 'extra-space (make-string
-                               (- org-prefix-category-length l 1) ?\ ))))
-         (if (and org-prefix-category-max-length
-                  (>= (length category) org-prefix-category-max-length))
-             (setq category (substring category 0 (1- org-prefix-category-max-length)))))
-       ;; Evaluate the compiled format
-       (setq rtn (concat (eval org-prefix-format-compiled) txt)))
+      ;; Set org-heading property on `txt' to mark the start of the
+      ;; heading.
+      (add-text-properties 0 (length txt) '(org-heading t) txt)
+
+      ;; Prepare the variables needed in the eval of the compiled format
+      (setq time (cond (s2 (concat
+                           (org-agenda-time-of-day-to-ampm-maybe s1)
+                           "-" (org-agenda-time-of-day-to-ampm-maybe s2)
+                           (if org-agenda-timegrid-use-ampm " ")))
+                      (s1 (concat
+                           (org-agenda-time-of-day-to-ampm-maybe s1)
+                           (if org-agenda-timegrid-use-ampm
+                               "........ "
+                             "......")))
+                      (t ""))
+           extra (or (and (not habitp) extra) "")
+           category (if (symbolp category) (symbol-name category) category)
+           thecategory (copy-sequence category))
+      (if (string-match org-bracket-link-regexp category)
+         (progn
+           (setq l (if (match-end 3)
+                       (- (match-end 3) (match-beginning 3))
+                     (- (match-end 1) (match-beginning 1))))
+           (when (< l (or org-prefix-category-length 0))
+             (setq category (copy-sequence category))
+             (org-add-props category nil
+               'extra-space (make-string
+                             (- org-prefix-category-length l 1) ?\ ))))
+       (if (and org-prefix-category-max-length
+                (>= (length category) org-prefix-category-max-length))
+           (setq category (substring category 0 (1- org-prefix-category-max-length)))))
+      ;; Evaluate the compiled format
+      (setq rtn (concat (eval org-prefix-format-compiled) txt))
 
       ;; And finally add the text properties
       (remove-text-properties 0 (length rtn) '(line-prefix t wrap-prefix t) rtn)
@@ -5265,7 +5663,6 @@ Any match of REMOVE-RE will be removed from TXT."
        'tags (mapcar 'org-downcase-keep-props tags)
        'org-highest-priority org-highest-priority
        'org-lowest-priority org-lowest-priority
-       'prefix-length (- (length rtn) (length txt))
        'time-of-day time-of-day
        'duration duration
        'effort effort
@@ -5273,6 +5670,7 @@ Any match of REMOVE-RE will be removed from TXT."
        'txt txt
        'time time
        'extra extra
+       'format org-prefix-format-compiled
        'dotime dotime))))
 
 (defun org-agenda-fix-displayed-tags (txt tags add-inherited hide-re)
@@ -5337,12 +5735,22 @@ The modified list may contain inherited tags, and tags matched by
       (while (setq time (pop gridtimes))
        (unless (and remove (member time have))
          (setq time (replace-regexp-in-string " " "0" (format "%04s" time)))
-         (push (org-format-agenda-item
+         (push (org-agenda-format-item
                 nil string "" nil
                 (concat (substring time 0 -2) ":" (substring time -2)))
                new)
          (put-text-property
           2 (length (car new)) 'face 'org-time-grid (car new))))
+      (when (and todayp org-agenda-show-current-time-in-grid)
+       (push (org-agenda-format-item
+              nil
+              org-agenda-current-time-string
+              "" nil
+              (format-time-string "%H:%M "))
+             new)
+       (put-text-property
+        2 (length (car new)) 'face 'org-agenda-current-time (car new)))
+
       (if (member 'time-up org-agenda-sorting-strategy-selected)
          (append new list)
        (append list new)))))
@@ -5352,7 +5760,8 @@ The modified list may contain inherited tags, and tags matched by
 The resulting form is returned and stored in the variable
 `org-prefix-format-compiled'."
   (setq org-prefix-has-time nil org-prefix-has-tag nil
-       org-prefix-category-length nil  org-prefix-has-effort nil)
+       org-prefix-category-length nil
+       org-prefix-has-effort nil)
   (let ((s (cond
            ((stringp org-agenda-prefix-format)
             org-agenda-prefix-format)
@@ -5361,11 +5770,12 @@ The resulting form is returned and stored in the variable
            (t "  %-12:c%?-12t% s")))
        (start 0)
        varform vars var e c f opt)
-    (while (string-match "%\\(\\?\\)?\\([-+]?[0-9.]*\\)\\([ .;,:!?=|/<>]?\\)\\([ctsei]\\)"
+    (while (string-match "%\\(\\?\\)?\\([-+]?[0-9.]*\\)\\([ .;,:!?=|/<>]?\\)\\([ctsei]\\|(.+)\\)"
                         s start)
-      (setq var (cdr (assoc (match-string 4 s)
-                           '(("c" . category) ("t" . time) ("s" . extra)
-                             ("i" . category-icon) ("T" . tag) ("e" . effort))))
+      (setq var (or (cdr (assoc (match-string 4 s)
+                               '(("c" . category) ("t" . time) ("s" . extra)
+                                 ("i" . category-icon) ("T" . tag) ("e" . effort))))
+                   'eval)
            c (or (match-string 3 s) "")
            opt (match-beginning 1)
            start (1+ (match-beginning 0)))
@@ -5381,12 +5791,14 @@ The resulting form is returned and stored in the variable
                (save-match-data
                  (if (string-match "\\.[0-9]+" x)
                      (string-to-number (substring (match-string 0 x) 1)))))))
-      (if opt
-         (setq varform
-               `(if (equal "" ,var)
-                    ""
-                  (format ,f (if (equal "" ,var) "" (concat ,var ,c)))))
-       (setq varform `(format ,f (if (equal ,var "") "" (concat ,var ,c (get-text-property 0 'extra-space ,var))))))
+      (if (eq var 'eval)
+         (setq varform `(format ,f (org-eval ,(read (match-string 4 s)))))
+       (if opt
+           (setq varform
+                 `(if (equal "" ,var)
+                      ""
+                    (format ,f (if (equal "" ,var) "" (concat ,var ,c)))))
+         (setq varform `(format ,f (if (equal ,var "") "" (concat ,var ,c (get-text-property 0 'extra-space ,var)))))))
       (setq s (replace-match "%s" t nil s))
       (push varform vars))
     (setq vars (nreverse vars))
@@ -5461,12 +5873,12 @@ could bind the variable in the options section of a custom command.")
 (defun org-agenda-highlight-todo (x)
   (let ((org-done-keywords org-done-keywords-for-agenda)
        (case-fold-search nil)
-        re pl)
+       re)
     (if (eq x 'line)
        (save-excursion
          (beginning-of-line 1)
          (setq re (org-get-at-bol 'org-todo-regexp))
-         (goto-char (+ (point) (or (org-get-at-bol 'prefix-length) 0)))
+         (goto-char (or (text-property-any (point-at-bol) (point-at-eol) 'org-heading t) (point)))
          (when (looking-at (concat "[ \t]*\\.*\\(" re "\\) +"))
            (add-text-properties (match-beginning 0) (match-end 1)
                                 (list 'face (org-get-todo-face 1)))
@@ -5474,21 +5886,31 @@ could bind the variable in the options section of a custom command.")
              (delete-region (match-beginning 1) (1- (match-end 0)))
              (goto-char (match-beginning 1))
              (insert (format org-agenda-todo-keyword-format s)))))
-      (setq re (concat (get-text-property 0 'org-todo-regexp x))
-           pl (get-text-property 0 'prefix-length x))
-      (when (and re
-                (equal (string-match (concat "\\(\\.*\\)" re "\\( +\\)")
-                                     x (or pl 0)) pl))
-       (add-text-properties
-        (or (match-end 1) (match-end 0)) (match-end 0)
-        (list 'face (org-get-todo-face (match-string 2 x)))
-        x)
-       (when (match-end 1)
-         (setq x (concat (substring x 0 (match-end 1))
-                         (format org-agenda-todo-keyword-format
-                                 (match-string 2 x))
-                         (org-add-props " " (text-properties-at 0 x))
-                         (substring x (match-end 3))))))
+      (let ((pl (text-property-any 0 (length x) 'org-heading t x)))
+       (setq re (get-text-property 0 'org-todo-regexp x))
+       (when (and re
+                  ;; Test `pl' because if there's no heading content,
+                  ;; there's no point matching to highlight.  Note
+                  ;; that if we didn't test `pl' first, and there
+                  ;; happened to be no keyword from `org-todo-regexp'
+                  ;; on this heading line, then the `equal' comparison
+                  ;; afterwards would spuriously succeed in the case
+                  ;; where `pl' is nil -- causing an args-out-of-range
+                  ;; error when we try to add text properties to text
+                  ;; that isn't there.
+                  pl
+                  (equal (string-match (concat "\\(\\.*\\)" re "\\( +\\)")
+                                       x pl) pl))
+         (add-text-properties
+          (or (match-end 1) (match-end 0)) (match-end 0)
+          (list 'face (org-get-todo-face (match-string 2 x)))
+          x)
+         (when (match-end 1)
+           (setq x (concat (substring x 0 (match-end 1))
+                           (format org-agenda-todo-keyword-format
+                                   (match-string 2 x))
+                           (org-add-props " " (text-properties-at 0 x))
+                           (substring x (match-end 3)))))))
       x)))
 
 (defsubst org-cmp-priority (a b)
@@ -5500,7 +5922,7 @@ could bind the variable in the options section of a custom command.")
          (t nil))))
 
 (defsubst org-cmp-effort (a b)
-  "Compare the priorities of string A and B."
+  "Compare the effort values of string A and B."
   (let* ((def (if org-sort-agenda-noeffort-is-high 32767 -1))
         (ea (or (get-text-property 1 'effort-minutes a) def))
         (eb (or (get-text-property 1 'effort-minutes b) def)))
@@ -5541,8 +5963,8 @@ could bind the variable in the options section of a custom command.")
 
 (defsubst org-cmp-alpha (a b)
   "Compare the headlines, alphabetically."
-  (let* ((pla (get-text-property 0 'prefix-length a))
-        (plb (get-text-property 0 'prefix-length b))
+  (let* ((pla (text-property-any 0 (length a) 'org-heading t a))
+        (plb (text-property-any 0 (length b) 'org-heading t b))
         (ta (and pla (substring a pla)))
         (tb (and plb (substring b plb))))
     (when pla
@@ -5763,29 +6185,46 @@ in the agenda."
 When this is the global TODO list, a prefix argument will be interpreted."
   (interactive)
   (let* ((org-agenda-keep-modes t)
-        (filter org-agenda-filter)
-        (preset (get 'org-agenda-filter :preset-filter))
-        (org-agenda-filter-while-redo (or filter preset))
+        (tag-filter org-agenda-tag-filter)
+        (tag-preset (get 'org-agenda-tag-filter :preset-filter))
+        (cat-filter org-agenda-category-filter)
+        (cat-preset (get 'org-agenda-category-filter :preset-filter))
+        (org-agenda-tag-filter-while-redo (or tag-filter tag-preset))
         (cols org-agenda-columns-active)
         (line (org-current-line))
         (window-line (- line (org-current-line (window-start))))
         (lprops (get 'org-agenda-redo-command 'org-lprops)))
-    (put 'org-agenda-filter :preset-filter nil)
+    (put 'org-agenda-tag-filter :preset-filter nil)
+    (put 'org-agenda-category-filter :preset-filter nil)
     (and cols (org-columns-quit))
     (message "Rebuilding agenda buffer...")
     (org-let lprops '(eval org-agenda-redo-command))
     (setq org-agenda-undo-list nil
          org-agenda-pending-undo-list nil)
     (message "Rebuilding agenda buffer...done")
-    (put 'org-agenda-filter :preset-filter preset)
-    (and (or filter preset) (org-agenda-filter-apply filter))
-    (and cols (interactive-p) (org-agenda-columns))
+    (put 'org-agenda-tag-filter :preset-filter tag-preset)
+    (put 'org-agenda-category-filter :preset-filter cat-preset)
+    (and (or tag-filter tag-preset) (org-agenda-filter-apply tag-filter 'tag))
+    (and (or cat-filter cat-preset) (org-agenda-filter-apply cat-filter 'category))
+    (and cols (org-called-interactively-p 'any) (org-agenda-columns))
     (org-goto-line line)
     (recenter window-line)))
 
-
 (defvar org-global-tags-completion-table nil)
 (defvar org-agenda-filter-form nil)
+(defvar org-agenda-filtered-by-category nil)
+
+(defun org-agenda-filter-by-category (strip)
+  "Keep only those lines in the agenda buffer that have a specific category.
+The category is that of the current line."
+  (interactive "P")
+  (if org-agenda-filtered-by-category
+      (org-agenda-filter-show-all-cat)
+    (let ((cat (org-no-properties (get-text-property (point) 'org-category))))
+      (if cat (org-agenda-filter-apply
+              (list (concat (if strip "-" "+") cat)) 'category)
+       (error "No category at point")))))
+
 (defun org-agenda-filter-by-tag (strip &optional char narrow)
   "Keep only those lines in the agenda buffer that have a specific tag.
 The tag is selected with its fast selection letter, as configured.
@@ -5804,25 +6243,26 @@ to switch to narrowing."
         (efforts (org-split-string
                   (or (cdr (assoc (concat org-effort-property "_ALL")
                                   org-global-properties))
-                      "0 0:10 0:30 1:00 2:00 3:00 4:00 5:00 6:00 7:00 8:00"                  "")))
+                      "0 0:10 0:30 1:00 2:00 3:00 4:00 5:00 6:00 7:00 8:00"
+                      "")))
         (effort-op org-agenda-filter-effort-default-operator)
         (effort-prompt "")
         (inhibit-read-only t)
-        (current org-agenda-filter)
-        a n tag)
+        (current org-agenda-tag-filter)
+        maybe-refresh a n tag)
     (unless char
       (message
        "%s by tag [%s ], [TAB], %s[/]:off, [+-]:narrow, [>=<?]:effort: "
        (if narrow "Narrow" "Filter") tag-chars
        (if org-agenda-auto-exclude-function "[RET], " ""))
-      (setq char (read-char)))
+      (setq char (read-char-exclusive)))
     (when (member char '(?+ ?-))
       ;; Narrowing down
       (cond ((equal char ?-) (setq strip t narrow t))
            ((equal char ?+) (setq strip nil narrow t)))
       (message
        "Narrow by tag [%s ], [TAB], [/]:off, [>=<]:effort: " tag-chars)
-      (setq char (read-char)))
+      (setq char (read-char-exclusive)))
     (when (member char '(?< ?> ?= ??))
       ;; An effort operator
       (setq effort-op (char-to-string char))
@@ -5835,7 +6275,7 @@ to switch to narrowing."
                     (if (= i 9) "0" (int-to-string (1+ i)))
                     "]" (nth i efforts))))
        (message "Effort%s: %s " effort-op effort-prompt)
-       (setq char (read-char))
+       (setq char (read-char-exclusive))
        (when (or (< char ?0) (> char ?9))
          (error "Need 1-9,0 to select effort" ))))
     (when (equal char ?\t)
@@ -5847,19 +6287,27 @@ to switch to narrowing."
                   "Tag: " org-global-tags-completion-table))))
     (cond
      ((equal char ?\r)
-      (org-agenda-filter-by-tag-show-all)
+      (org-agenda-filter-show-all-tag)
       (when org-agenda-auto-exclude-function
-       (setq org-agenda-filter '())
+       (setq org-agenda-tag-filter '())
        (dolist (tag (org-agenda-get-represented-tags))
          (let ((modifier (funcall org-agenda-auto-exclude-function tag)))
            (if modifier
-               (push modifier org-agenda-filter))))
-       (if (not (null org-agenda-filter))
-           (org-agenda-filter-apply org-agenda-filter))))
+               (push modifier org-agenda-tag-filter))))
+       (if (not (null org-agenda-tag-filter))
+           (org-agenda-filter-apply org-agenda-tag-filter 'tag)))
+      (setq maybe-refresh t))
      ((equal char ?/)
-      (org-agenda-filter-by-tag-show-all)
-      (when (get 'org-agenda-filter :preset-filter)
-       (org-agenda-filter-apply org-agenda-filter)))
+      (org-agenda-filter-show-all-tag)
+      (when (get 'org-agenda-tag-filter :preset-filter)
+       (org-agenda-filter-apply org-agenda-tag-filter 'tag))
+      (setq maybe-refresh t))
+     ((equal char ?. )
+      (setq org-agenda-tag-filter
+           (mapcar (lambda(tag) (concat "+" tag))
+                   (org-get-at-bol 'tags)))
+      (org-agenda-filter-apply org-agenda-tag-filter 'tag)
+      (setq maybe-refresh t))
      ((or (equal char ?\ )
          (setq a (rassoc char alist))
          (and (>= char ?0) (<= char ?9)
@@ -5870,13 +6318,17 @@ to switch to narrowing."
               (setq tag "?eff")
               a (cons tag nil))
          (and tag (setq a (cons tag nil))))
-      (org-agenda-filter-by-tag-show-all)
+      (org-agenda-filter-show-all-tag)
       (setq tag (car a))
-      (setq org-agenda-filter
+      (setq org-agenda-tag-filter
            (cons (concat (if strip "-" "+") tag)
                  (if narrow current nil)))
-      (org-agenda-filter-apply org-agenda-filter))
-     (t (error "Invalid tag selection character %c" char)))))
+      (org-agenda-filter-apply org-agenda-tag-filter 'tag)
+      (setq maybe-refresh t))
+     (t (error "Invalid tag selection character %c" char)))
+    (when (and maybe-refresh
+              (eq org-agenda-clockreport-mode 'with-filter))
+      (org-agenda-redo))))
 
 (defun org-agenda-get-represented-tags ()
   "Get a list of all tags currently represented in the agenda."
@@ -5890,15 +6342,17 @@ to switch to narrowing."
     tags))
 
 (defun org-agenda-filter-by-tag-refine (strip &optional char)
-  "Refine the current filter.  See `org-agenda-filter-by-tag."
+  "Refine the current filter.  See `org-agenda-filter-by-tag'."
   (interactive "P")
   (org-agenda-filter-by-tag strip char 'refine))
 
 (defun org-agenda-filter-make-matcher ()
-  "Create the form that tests a line for the agenda filter."
+  "Create the form that tests a line for agenda filter."
   (let (f f1)
-    (dolist (x (append (get 'org-agenda-filter :preset-filter)
-                      org-agenda-filter))
+    ;; first compute the tag-filter matcher
+    (dolist (x (delete-dups
+               (append (get 'org-agenda-tag-filter
+                            :preset-filter) org-agenda-tag-filter)))
       (if (member x '("-" "+"))
          (setq f1 (if (equal x "-") 'tags '(not tags)))
        (if (string-match "[<=>?]" x)
@@ -5907,6 +6361,14 @@ to switch to narrowing."
        (if (equal (string-to-char x) ?-)
            (setq f1 (list 'not f1))))
       (push f1 f))
+    ;; then compute the category-filter matcher
+    (dolist (x (delete-dups
+               (append (get 'org-agenda-category-filter
+                            :preset-filter) org-agenda-category-filter)))
+      (if (equal "-" (substring x 0 1))
+         (setq f1 (list 'not (list 'equal (substring x 1) 'cat)))
+       (setq f1 (list 'equal (substring x 1) 'cat)))
+      (push f1 f))
     (cons 'and (nreverse f))))
 
 (defun org-agenda-filter-effort-form (e)
@@ -5920,7 +6382,7 @@ E looks like \"+<2:25\"."
                   ((equal op ??) op)
                   (t '=)))
     (list 'org-agenda-compare-effort (list 'quote op)
-         (org-hh:mm-string-to-minutes e))))
+         (org-duration-string-to-minutes e))))
 
 (defun org-agenda-compare-effort (op value)
   "Compare the effort of the current line with VALUE, using OP.
@@ -5931,49 +6393,67 @@ If the line does not have an effort defined, return nil."
       (funcall op (or eff (if org-sort-agenda-noeffort-is-high 32767 0))
               value))))
 
-(defun org-agenda-filter-apply (filter)
+(defun org-agenda-filter-apply (filter type)
   "Set FILTER as the new agenda filter and apply it."
-  (let (tags)
-    (setq org-agenda-filter filter
-         org-agenda-filter-form (org-agenda-filter-make-matcher))
+  (let (tags cat)
+    (if (eq type 'tag)
+       (setq org-agenda-tag-filter filter)
+      (setq org-agenda-category-filter filter))
+    (setq org-agenda-filter-form (org-agenda-filter-make-matcher))
+    (if (and (eq type 'category)
+            (not (equal (substring (car filter) 0 1) "-")))
+       ;; Only set `org-agenda-filtered-by-category' to t
+       ;; when a unique category is used as the filter
+       (setq org-agenda-filtered-by-category t))
     (org-agenda-set-mode-name)
     (save-excursion
       (goto-char (point-min))
       (while (not (eobp))
        (if (org-get-at-bol 'org-marker)
            (progn
-             (setq tags (org-get-at-bol 'tags)) ; used in eval
+             (setq tags (org-get-at-bol 'tags) ; used in eval
+                   cat (get-text-property (point) 'org-category))
              (if (not (eval org-agenda-filter-form))
-                 (org-agenda-filter-by-tag-hide-line))
+                 (org-agenda-filter-hide-line type))
              (beginning-of-line 2))
          (beginning-of-line 2))))
     (if (get-char-property (point) 'invisible)
-       (org-agenda-previous-line))))
+       (ignore-errors (org-agenda-previous-line)))))
 
-(defun org-agenda-filter-by-tag-hide-line ()
+(defun org-agenda-filter-hide-line (type)
   (let (ov)
     (setq ov (make-overlay (max (point-min) (1- (point-at-bol)))
                               (point-at-eol)))
     (overlay-put ov 'invisible t)
-    (overlay-put ov 'type 'tags-filter)
-    (push ov org-agenda-filter-overlays)))
+    (overlay-put ov 'type type)
+    (if (eq type 'tag)
+       (push ov org-agenda-tag-filter-overlays)
+      (push ov org-agenda-cat-filter-overlays))))
 
 (defun org-agenda-fix-tags-filter-overlays-at (&optional pos)
   (setq pos (or pos (point)))
   (save-excursion
     (dolist (ov (overlays-at pos))
       (when (and (overlay-get ov 'invisible)
-                (eq (overlay-get ov 'type) 'tags-filter))
+                (eq (overlay-get ov 'type) 'tag))
        (goto-char pos)
        (if (< (overlay-start ov) (point-at-eol))
            (move-overlay ov (point-at-eol)
                              (overlay-end ov)))))))
 
-(defun org-agenda-filter-by-tag-show-all ()
-  (mapc 'delete-overlay org-agenda-filter-overlays)
-  (setq org-agenda-filter-overlays nil)
-  (setq org-agenda-filter nil)
-  (setq org-agenda-filter-form nil)
+(defun org-agenda-filter-show-all-tag nil
+  (mapc 'delete-overlay org-agenda-tag-filter-overlays)
+  (setq org-agenda-tag-filter-overlays nil
+       org-agenda-tag-filter nil
+       org-agenda-filter-form nil)
+  (org-agenda-set-mode-name))
+
+(defun org-agenda-filter-show-all-cat nil
+  (mapc 'delete-overlay org-agenda-cat-filter-overlays)
+  (setq org-agenda-cat-filter-overlays nil
+       org-agenda-filtered-by-category nil
+       org-agenda-category-filter nil
+       org-agenda-filter-form nil)
   (org-agenda-set-mode-name))
 
 (defun org-agenda-manipulate-query-add ()
@@ -6039,7 +6519,7 @@ Negative selection means regexp must not match for selection of an entry."
      (tdpos (goto-char tdpos))
      ((eq org-agenda-type 'agenda)
       (let* ((sd (org-agenda-compute-starting-span
-                 (org-today) (or org-agenda-ndays org-agenda-span)))
+                 (org-today) (or org-agenda-current-span org-agenda-ndays org-agenda-span)))
             (org-agenda-overriding-arguments org-agenda-last-arguments))
        (setf (nth 1 org-agenda-overriding-arguments) sd)
        (org-agenda-redo)
@@ -6092,17 +6572,20 @@ With prefix ARG, go backward that many times the current span."
 (defun org-agenda-view-mode-dispatch ()
   "Call one of the view mode commands."
   (interactive)
-  (message "View: [d]ay [w]eek [m]onth [y]ear                         [q]uit/abort
-      time[G]rid     [[]inactive [f]ollow [l]og [L]og-all   [E]ntryText
-      [a]rch-trees   [A]rch-files    clock[R]eport   include[D]iary")
+  (message "View: [d]ay [w]eek [m]onth [y]ear [SPC]reset    [q]uit/abort
+      time[G]rid     [[]inactive [f]ollow [l]og [L]og-all   [c]lockcheck
+      [a]rch-trees   [A]rch-files    clock[R]eport   include[D]iary
+      [E]ntryText")
   (let ((a (read-char-exclusive)))
     (case a
+      (?\  (call-interactively 'org-agenda-reset-view))
       (?d (call-interactively 'org-agenda-day-view))
       (?w (call-interactively 'org-agenda-week-view))
       (?m (call-interactively 'org-agenda-month-view))
       (?y (call-interactively 'org-agenda-year-view))
       (?l (call-interactively 'org-agenda-log-mode))
       (?L (org-agenda-log-mode '(4)))
+      (?c (org-agenda-log-mode 'clockcheck))
       ((?F ?f) (call-interactively 'org-agenda-follow-mode))
       (?a (call-interactively 'org-agenda-archives-mode))
       (?A (org-agenda-archives-mode 'files))
@@ -6118,6 +6601,10 @@ With prefix ARG, go backward that many times the current span."
       (?q (message "Abort"))
       (otherwise (error "Invalid key" )))))
 
+(defun org-agenda-reset-view ()
+  "Switch to default view for agenda."
+  (interactive)
+  (org-agenda-change-time-span (or org-agenda-ndays org-agenda-span)))
 (defun org-agenda-day-view (&optional day-of-year)
   "Switch to daily view for agenda.
 With argument DAY-OF-YEAR, switch to that day of the year."
@@ -6161,7 +6648,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)
@@ -6259,8 +6747,7 @@ so that the date SD will be in that range."
   (interactive)
   (setq org-agenda-follow-mode (not org-agenda-follow-mode))
   (org-agenda-set-mode-name)
-  (if (and org-agenda-follow-mode (org-get-at-bol 'org-marker))
-      (org-agenda-show))
+  (org-agenda-do-context-action)
   (message "Follow mode is %s"
           (if org-agenda-follow-mode "on" "off")))
 
@@ -6301,10 +6788,13 @@ With a double `C-u' prefix arg, show *only* log items, nothing else."
   (interactive "P")
   (org-agenda-check-type t 'agenda 'timeline)
   (setq org-agenda-show-log
-       (if (equal special '(16))
-           'only
-         (if special '(closed clock state)
-           (not org-agenda-show-log))))
+       (cond
+        ((equal special '(16)) 'only)
+        ((eq special 'clockcheck)
+         (if (eq org-agenda-show-log 'clockcheck)
+             nil 'clockcheck))
+        (special '(closed clock state))
+        (t (not org-agenda-show-log))))
   (org-agenda-set-mode-name)
   (org-agenda-redo)
   (message "Log mode is %s"
@@ -6373,15 +6863,38 @@ When called with a prefix argument, include all archive files as well."
              (if org-agenda-use-time-grid   " Grid"   "")
              (if (and (boundp 'org-habit-show-habits)
                       org-habit-show-habits) " Habit"   "")
-             (if (consp org-agenda-show-log) " LogAll"
-               (if org-agenda-show-log " Log" ""))
-             (if (or org-agenda-filter (get 'org-agenda-filter
+             (cond
+              ((consp org-agenda-show-log) " LogAll")
+              ((eq org-agenda-show-log 'clockcheck) " ClkCk")
+              (org-agenda-show-log " Log")
+              (t ""))
+             (if (or org-agenda-category-filter (get 'org-agenda-category-filter
+                                                     :preset-filter))
+                 '(:eval (org-propertize
+                          (concat " <"
+                                  (mapconcat
+                                   'identity
+                                   (append
+                                    (get 'org-agenda-category-filter :preset-filter)
+                                    org-agenda-category-filter)
+                                   "")
+                                  ">")
+                          'face 'org-agenda-filter-category
+                          'help-echo "Category used in filtering"))
+               "")
+             (if (or org-agenda-tag-filter (get 'org-agenda-tag-filter
                                             :preset-filter))
-                 (concat " {" (mapconcat
-                               'identity
-                               (append (get 'org-agenda-filter
-                                            :preset-filter)
-                                       org-agenda-filter) "") "}")
+                 '(:eval (org-propertize
+                          (concat " {"
+                                  (mapconcat
+                                   'identity
+                                   (append
+                                    (get 'org-agenda-tag-filter :preset-filter)
+                                    org-agenda-tag-filter)
+                                   "")
+                                  "}")
+                          'face 'org-agenda-filter-tags
+                          'help-echo "Tags used in filtering"))
                "")
              (if org-agenda-archives-mode
                  (if (eq org-agenda-archives-mode t)
@@ -6415,11 +6928,13 @@ When called with a prefix argument, include all archive files as well."
 (defun org-agenda-do-context-action ()
   "Show outline path and, maybe, follow mode window."
   (let ((m (org-get-at-bol 'org-marker)))
-    (if (and org-agenda-follow-mode m)
-       (org-agenda-show))
-    (if (and m org-agenda-show-outline-path)
-       (org-with-point-at m
-         (org-display-outline-path t)))))
+    (when (and (markerp m) (marker-buffer m))
+      (and org-agenda-follow-mode
+          (if org-agenda-follow-indirect
+              (org-agenda-tree-to-indirect-buffer)
+            (org-agenda-show)))
+      (and org-agenda-show-outline-path
+          (org-with-point-at m (org-display-outline-path t))))))
 
 (defun org-agenda-show-priority ()
   "Show the priority of the current item.
@@ -6449,11 +6964,13 @@ and by additional input from the age of a schedules or deadline entry."
     (widen)
     (push-mark)
     (goto-char pos)
-    (when (org-mode-p)
+    (when (eq major-mode 'org-mode)
       (org-show-context 'agenda)
       (save-excursion
        (and (outline-next-heading)
-            (org-flag-heading nil)))) ; show the next heading
+            (org-flag-heading nil))))  ; show the next heading
+    (when (outline-invisible-p)
+      (show-entry))                    ; display invisible text
     (recenter (/ (window-height) 2))
     (run-hooks 'org-agenda-after-show-hook)
     (and highlight (org-highlight (point-at-bol) (point-at-eol)))))
@@ -6476,7 +6993,7 @@ Point is in the buffer where the item originated.")
      (with-current-buffer buffer
        (save-excursion
         (goto-char pos)
-        (if (and (org-mode-p) (not (member type '("sexp"))))
+        (if (and (eq major-mode 'org-mode) (not (member type '("sexp"))))
             (setq dbeg (progn (org-back-to-heading t) (point))
                   dend (org-end-of-subtree t t))
           (setq dbeg (point-at-bol)
@@ -6528,7 +7045,7 @@ Point is in the buffer where the item originated.")
         (pos (marker-position marker)))
     (org-with-remote-undo buffer
       (with-current-buffer buffer
-       (if (org-mode-p)
+       (if (eq major-mode 'org-mode)
            (if (and confirm
                     (not (y-or-n-p "Archive this subtree or entry? ")))
                (error "Abort")
@@ -6575,7 +7092,7 @@ If this information is not given, the function uses the tree at point."
           (pos (marker-position marker))
           (rfloc (or rfloc
                      (org-refile-get-location
-                      (if goto "Goto: " "Refile to: ") buffer
+                      (if goto "Goto" "Refile to") buffer
                       org-refile-allow-creating-parent-nodes))))
       (with-current-buffer buffer
        (save-excursion
@@ -6595,9 +7112,7 @@ at the text of the entry itself."
                     (org-get-at-bol 'org-marker)))
         (buffer (and marker (marker-buffer marker)))
         (prefix (buffer-substring
-                 (point-at-bol)
-                 (+ (point-at-bol)
-                    (or (org-get-at-bol 'prefix-length) 0)))))
+                 (point-at-bol) (point-at-eol))))
     (cond
      (buffer
       (with-current-buffer buffer
@@ -6631,15 +7146,17 @@ at the text of the entry itself."
                       (org-agenda-error)))
           (buffer (marker-buffer marker))
           (pos (marker-position marker)))
-      (switch-to-buffer buffer)
+      (org-pop-to-buffer-same-window buffer)
       (and delete-other-windows (delete-other-windows))
       (widen)
       (goto-char pos)
-      (when (org-mode-p)
+      (when (eq major-mode 'org-mode)
        (org-show-context 'agenda)
        (save-excursion
          (and (outline-next-heading)
-              (org-flag-heading nil)))))))  ; show the next heading
+              (org-flag-heading nil))) ; show the next heading
+       (when (outline-invisible-p)
+         (show-entry))))))             ; display invisible text
 
 (defun org-agenda-goto-mouse (ev)
   "Go to the Org-mode file which contains the item at the mouse click."
@@ -6707,7 +7224,7 @@ if it was hidden in the outline."
        (org-back-to-heading)
        (run-hook-with-args 'org-cycle-hook 'folded))
       (message "Remote: FOLDED"))
-     ((and (interactive-p) (= more 1))
+     ((and (org-called-interactively-p 'any) (= more 1))
       (message "Remote: show with default settings"))
      ((= more 2)
       (show-entry)
@@ -6797,6 +7314,24 @@ With numerical prefix arg ARG, go up to this level and then take that tree.
 With a \\[universal-argument] prefix, make a separate frame for this tree (i.e. don't
 use the dedicated frame)."
   (interactive)
+  (if (and current-prefix-arg (listp current-prefix-arg))
+      (org-agenda-do-tree-to-indirect-buffer)
+    (let ((agenda-window (selected-window))
+          (indirect-window
+          (and org-last-indirect-buffer
+               (get-buffer-window org-last-indirect-buffer))))
+      (save-window-excursion (org-agenda-do-tree-to-indirect-buffer))
+      (unwind-protect
+          (progn
+            (unless (and indirect-window (window-live-p indirect-window))
+              (setq indirect-window (split-window agenda-window)))
+            (select-window indirect-window)
+            (switch-to-buffer org-last-indirect-buffer :norecord)
+            (fit-window-to-buffer indirect-window))
+        (select-window (get-buffer-window org-agenda-buffer-name))))))
+
+(defun org-agenda-do-tree-to-indirect-buffer ()
+  "Same as `org-agenda-tree-to-indirect-buffer' without saving window."
   (org-agenda-check-no-diary)
   (let* ((marker (or (org-get-at-bol 'org-marker)
                     (org-agenda-error)))
@@ -6886,7 +7421,7 @@ the same tree node, and the headline of the tree node in the Org-mode file."
                                            &optional fixface just-this)
   "Change all lines in the agenda buffer which match HDMARKER.
 The new content of the line will be NEWHEAD (as modified by
-`org-format-agenda-item').  HDMARKER is checked with
+`org-agenda-format-item').  HDMARKER is checked with
 `equal' against all `org-hd-marker' text properties in the file.
 If FIXFACE is non-nil, the face of each item is modified according to
 the new TODO state.
@@ -6911,15 +7446,22 @@ If FORCE-TAGS is non nil, the car of it returns the new tags."
                dotime (org-get-at-bol 'dotime)
                cat (org-get-at-bol 'org-category)
                tags thetags
-               new (org-format-agenda-item "x" newhead cat tags dotime 'noprefix)
-               pl (org-get-at-bol 'prefix-length)
+               new
+               (let ((org-prefix-format-compiled
+                      (or (get-text-property (point) 'format)
+                          org-prefix-format-compiled)))
+                 (with-current-buffer (marker-buffer hdmarker)
+                   (save-excursion
+                     (save-restriction
+                       (widen)
+                       (org-agenda-format-item (org-get-at-bol 'extra)
+                                               newhead cat tags dotime)))))
+               pl (text-property-any (point-at-bol) (point-at-eol) 'org-heading t)
                undone-face (org-get-at-bol 'undone-face)
                done-face (org-get-at-bol 'done-face))
-         (goto-char (+ (point) pl))
-         ;; (org-move-to-column pl)  FIXME: does the above line work correctly?
+         (beginning-of-line 1)
          (cond
           ((equal new "")
-           (beginning-of-line 1)
            (and (looking-at ".*\n?") (replace-match "")))
           ((looking-at ".*")
            (replace-match new t t)
@@ -7009,9 +7551,8 @@ the same tree node, and the headline of the tree node in the Org-mode file."
   "Set tags for the current headline."
   (interactive)
   (org-agenda-check-no-diary)
-  (if (and (org-region-active-p) (interactive-p))
+  (if (and (org-region-active-p) (org-called-interactively-p 'any))
       (call-interactively 'org-change-tag-in-region)
-    (org-agenda-show)   ;;; FIXME This is a stupid hack and should not be needed
     (let* ((hdmarker (or (org-get-at-bol 'org-hd-marker)
                         (org-agenda-error)))
           (buffer (marker-buffer hdmarker))
@@ -7040,7 +7581,6 @@ the same tree node, and the headline of the tree node in the Org-mode file."
   "Set a property for the current headline."
   (interactive)
   (org-agenda-check-no-diary)
-  (org-agenda-show)   ;;; FIXME This is a stupid hack and should not be needed
   (let* ((hdmarker (or (org-get-at-bol 'org-hd-marker)
                       (org-agenda-error)))
         (buffer (marker-buffer hdmarker))
@@ -7063,7 +7603,6 @@ the same tree node, and the headline of the tree node in the Org-mode file."
   "Set the effort property for the current headline."
   (interactive)
   (org-agenda-check-no-diary)
-  (org-agenda-show)   ;;; FIXME This is a stupid hack and should not be needed
   (let* ((hdmarker (or (org-get-at-bol 'org-hd-marker)
                       (org-agenda-error)))
         (buffer (marker-buffer hdmarker))
@@ -7078,16 +7617,17 @@ the same tree node, and the headline of the tree node in the Org-mode file."
          (org-show-context 'agenda))
        (save-excursion
          (and (outline-next-heading)
-              (org-flag-heading nil)))   ; show the next heading
+              (org-flag-heading nil))) ; show the next heading
        (goto-char pos)
        (call-interactively 'org-set-effort)
-       (end-of-line 1)))))
+       (end-of-line 1)
+       (setq newhead (org-get-heading)))
+      (org-agenda-change-all-lines newhead hdmarker))))
 
 (defun org-agenda-toggle-archive-tag ()
   "Toggle the archive tag for the current entry."
   (interactive)
   (org-agenda-check-no-diary)
-  (org-agenda-show)   ;;; FIXME This is a stupid hack and should not be needed
   (let* ((hdmarker (or (org-get-at-bol 'org-hd-marker)
                        (org-agenda-error)))
         (buffer (marker-buffer hdmarker))
@@ -7141,26 +7681,44 @@ the same tree node, and the headline of the tree node in the Org-mode file."
     (org-agenda-date-earlier (prefix-numeric-value arg)))))
 
 (defun org-agenda-date-later (arg &optional what)
-  "Change the date of this item to one day later."
+  "Change the date of this item to ARG day(s) later."
   (interactive "p")
   (org-agenda-check-type t 'agenda 'timeline)
   (org-agenda-check-no-diary)
   (let* ((marker (or (org-get-at-bol 'org-marker)
                     (org-agenda-error)))
         (buffer (marker-buffer marker))
-        (pos (marker-position marker)))
+        (pos (marker-position marker))
+        cdate today)
     (org-with-remote-undo buffer
-     (with-current-buffer buffer
-       (widen)
-       (goto-char pos)
-       (if (not (org-at-timestamp-p))
-          (error "Cannot find time stamp"))
-       (org-timestamp-change arg (or what 'day)))
-     (org-agenda-show-new-time marker org-last-changed-timestamp))
+      (with-current-buffer buffer
+       (widen)
+       (goto-char pos)
+       (if (not (org-at-timestamp-p))
+           (error "Cannot find time stamp"))
+       (when (and org-agenda-move-date-from-past-immediately-to-today
+                  (equal arg 1)
+                  (or (not what) (eq what 'day))
+                  (not (save-match-data (org-at-date-range-p))))
+         (setq cdate (org-parse-time-string (match-string 0) 'nodefault)
+               cdate (calendar-absolute-from-gregorian
+                      (list (nth 4 cdate) (nth 3 cdate) (nth 5 cdate)))
+               today (org-today))
+         (if (> today cdate)
+             ;; immediately shift to today
+             (setq arg (- today cdate))))
+       (org-timestamp-change arg (or what 'day))
+       (when (and (org-at-date-range-p)
+                  (re-search-backward org-tr-regexp-both (point-at-bol)))
+         (let ((end org-last-changed-timestamp))
+           (org-timestamp-change arg (or what 'day))
+           (setq org-last-changed-timestamp
+                 (concat org-last-changed-timestamp "--" end)))))
+      (org-agenda-show-new-time marker org-last-changed-timestamp))
     (message "Time stamp changed to %s" org-last-changed-timestamp)))
 
 (defun org-agenda-date-earlier (arg &optional what)
-  "Change the date of this item to one day earlier."
+  "Change the date of this item to ARG day(s) earlier."
   (interactive "p")
   (org-agenda-date-later (- arg) what))
 
@@ -7234,9 +7792,9 @@ be used to request time specification in the time stamp."
       (org-agenda-show-new-time marker org-last-changed-timestamp))
     (message "Time stamp changed to %s" org-last-changed-timestamp)))
 
-(defun org-agenda-schedule (arg)
+(defun org-agenda-schedule (arg &optional time)
   "Schedule the item at point.
-Arg is passed through to `org-schedule'."
+ARG is passed through to `org-schedule'."
   (interactive "P")
   (org-agenda-check-type t 'agenda 'timeline 'todo 'tags 'search)
   (org-agenda-check-no-diary)
@@ -7252,13 +7810,13 @@ Arg is passed through to `org-schedule'."
       (with-current-buffer buffer
        (widen)
        (goto-char pos)
-       (setq ts (org-schedule arg)))
+       (setq ts (org-schedule arg time)))
       (org-agenda-show-new-time marker ts "S"))
     (message "Item scheduled for %s" ts)))
 
-(defun org-agenda-deadline (arg)
+(defun org-agenda-deadline (arg &optional time)
   "Schedule the item at point.
-Arg is passed through to `org-deadline'."
+ARG is passed through to `org-deadline'."
   (interactive "P")
   (org-agenda-check-type t 'agenda 'timeline 'todo 'tags 'search)
   (org-agenda-check-no-diary)
@@ -7272,7 +7830,7 @@ Arg is passed through to `org-deadline'."
       (with-current-buffer buffer
        (widen)
        (goto-char pos)
-       (setq ts (org-deadline arg)))
+       (setq ts (org-deadline arg time)))
       (org-agenda-show-new-time marker ts "D"))
        (message "Deadline for this item set to %s" ts)))
 
@@ -7465,6 +8023,7 @@ top-level    as top-level entries at the end of the file."
 (defcustom org-agenda-insert-diary-extract-time nil
   "Non-nil means extract any time specification from the diary entry."
   :group 'org-agenda
+  :version "24.1"
   :type 'boolean)
 
 (defun org-agenda-add-entry-to-org-agenda-diary-file (type text &optional d1 d2)
@@ -7481,7 +8040,7 @@ the resulting entry will not be shown.  When TEXT is empty, switch to
      ((eq type 'anniversary)
       (or (re-search-forward "^*[ \t]+Anniversaries" nil t)
        (progn
-         (or (org-on-heading-p t)
+         (or (org-at-heading-p t)
              (progn
                (outline-next-heading)
                (insert "* Anniversaries\n\n")
@@ -7490,26 +8049,17 @@ the resulting entry will not be shown.  When TEXT is empty, switch to
       (org-back-over-empty-lines)
       (backward-char 1)
       (insert "\n")
-      (require 'diary-lib)
-      (let ((calendar-date-display-form
-            (if (if (boundp 'calendar-date-style)
-                    (eq calendar-date-style 'european)
-                  (with-no-warnings ;; european-calendar-style is obsolete as of version 23.1
-                    (org-bound-and-true-p european-calendar-style))) ; Emacs 22
-                '(day " " month " " year)
-              '(month " " day " " year))))
-
-       (insert (format "%%%%(diary-anniversary %s) %s"
-                       (calendar-date-string d1 nil t) text))))
+      (insert (format "%%%%(org-anniversary %d %2d %2d) %s"
+                     (nth 2 d1) (car d1) (nth 1 d1) text)))
      ((eq type 'day)
       (let ((org-prefix-has-time t)
            (org-agenda-time-leading-zero t)
            fmt time time2)
        (if org-agenda-insert-diary-extract-time
-           ;; Use org-format-agenda-item to parse text for a time-range and
+           ;; Use org-agenda-format-item to parse text for a time-range and
            ;; remove it.  FIXME: This is a hack, we should refactor
            ;; that function to make time extraction available separately
-           (setq fmt (org-format-agenda-item nil text nil nil t)
+           (setq fmt (org-agenda-format-item nil text nil nil t)
                  time (get-text-property 0 'time fmt)
                  time2 (if (> (length time) 0)
                            ;; split-string removes trailing ...... if
@@ -7744,7 +8294,7 @@ This is a command that has to be installed in `calendar-mode-map'."
 (defun org-agenda-bulk-mark (&optional arg)
   "Mark the entry at point for future bulk action."
   (interactive "p")
-  (dotimes (i (max arg 1))
+  (dotimes (i (or arg 1))
     (unless (org-get-at-bol 'org-agenda-diary-link)
       (let* ((m (org-get-at-bol 'org-hd-marker))
             ov)
@@ -7762,6 +8312,20 @@ This is a command that has to be installed in `calendar-mode-map'."
        (message "%d entries marked for bulk action"
                 (length org-agenda-bulk-marked-entries))))))
 
+(defun org-agenda-bulk-mark-regexp (regexp)
+  "Mark entries match REGEXP."
+  (interactive "sMark entries matching regexp: ")
+  (let (entries-marked)
+    (save-excursion
+      (goto-char (point-min))
+      (goto-char (next-single-property-change (point) 'txt))
+      (while (re-search-forward regexp nil t)
+       (when (string-match regexp (get-text-property (point) 'txt))
+         (setq entries-marked (+ entries-marked 1))
+         (call-interactively 'org-agenda-bulk-mark))))
+    (if (not entries-marked)
+       (message "No entry matching this regexp."))))
+
 (defun org-agenda-bulk-unmark ()
   "Unmark the entry at point for future bulk action."
   (interactive)
@@ -7808,9 +8372,25 @@ This will remove the markers, and the overlays."
   "Execute an remote-editing action on all marked entries.
 The prefix arg is passed through to the command if possible."
   (interactive "P")
-  (unless org-agenda-bulk-marked-entries
-    (error "No entries are marked"))
-  (message "Bulk: [r]efile [$]arch [A]rch->sib [t]odo [+/-]tag [s]chd [S]catter [d]eadline")
+  ;; Make sure we have markers, and only valid ones
+  (unless org-agenda-bulk-marked-entries (error "No entries are marked"))
+  (mapc
+   (lambda (m)
+     (unless (and (markerp m)
+                 (marker-buffer m)
+                 (buffer-live-p (marker-buffer m))
+                 (marker-position m))
+       (error "Marker %s for bulk command is invalid" m)))
+   org-agenda-bulk-marked-entries)
+
+  ;; Prompt for the bulk command
+  (message (concat "Bulk: [r]efile [$]arch [A]rch->sib [t]odo"
+                  " [+/-]tag [s]chd [S]catter [d]eadline [f]unction"
+                  (when org-agenda-bulk-custom-functions
+                    (concat " Custom: ["
+                            (mapconcat (lambda(f) (char-to-string (car f)))
+                                       org-agenda-bulk-custom-functions "")
+                            "]"))))
   (let* ((action (read-char-exclusive))
         (org-log-refile (if org-log-refile 'time nil))
         (entries (reverse org-agenda-bulk-marked-entries))
@@ -7825,7 +8405,7 @@ The prefix arg is passed through to the command if possible."
 
      ((member action '(?r ?w))
       (setq rfloc (org-refile-get-location
-                  "Refile to"
+                  "Refile to"
                   (marker-buffer (car org-agenda-bulk-marked-entries))
                   org-refile-allow-creating-parent-nodes))
       (if (nth 3 rfloc)
@@ -7873,27 +8453,45 @@ The prefix arg is passed through to the command if possible."
                           (fset 'read-string old)
                         (fmakunbound 'read-string)))))))
 
-     ((eq action '?S)
-      (let ((days (read-number
-                  (format "Scatter tasks across how many %sdays: "
-                          (if arg "week" "")) 7)))
-       (setq cmd
-             `(let ((distance (random ,(1+ days))))
-                (if arg
-                    (let ((dist distance)
-                          (day-of-week
-                           (calendar-day-of-week
-                            (calendar-gregorian-from-absolute (org-today)))))
-                      (dotimes (i (1+ dist))
-                        (while (member day-of-week org-agenda-weekend-days)
-                          (incf distance)
+     ((equal action ?S)
+      (if (not (org-agenda-check-type nil 'agenda 'timeline 'todo))
+         (error "Can't scatter tasks in \"%s\" agenda view" org-agenda-type)
+       (let ((days (read-number
+                    (format "Scatter tasks across how many %sdays: "
+                            (if arg "week" "")) 7)))
+         (setq cmd
+               `(let ((distance (1+ (random ,days))))
+                  (if arg
+                      (let ((dist distance)
+                            (day-of-week
+                             (calendar-day-of-week
+                              (calendar-gregorian-from-absolute (org-today)))))
+                        (dotimes (i (1+ dist))
+                          (while (member day-of-week org-agenda-weekend-days)
+                            (incf distance)
+                            (incf day-of-week)
+                            (if (= day-of-week 7)
+                                (setq day-of-week 0)))
                           (incf day-of-week)
                           (if (= day-of-week 7)
-                              (setq day-of-week 0)))
-                        (incf day-of-week)
-                        (if (= day-of-week 7)
-                            (setq day-of-week 0)))))
-                (org-agenda-date-later distance)))))
+                              (setq day-of-week 0)))))
+                  ;; silently fail when try to replan a sexp entry
+                  (condition-case nil
+                      (let* ((date (calendar-gregorian-from-absolute
+                                    (+ (org-today) distance)))
+                             (time (encode-time 0 0 0 (nth 1 date) (nth 0 date)
+                                                (nth 2 date))))
+                        (org-agenda-schedule nil time))
+                    (error nil)))))))
+
+     ((assoc action org-agenda-bulk-custom-functions)
+      (setq cmd (list (cadr (assoc action org-agenda-bulk-custom-functions)))
+           redo-at-end t))
+
+     ((equal action ?f)
+      (setq cmd (list (intern
+                      (org-icompleting-read "Function: "
+                                            obarray 'fboundp t nil nil)))))
 
      (t (error "Invalid bulk action")))
 
@@ -7914,7 +8512,8 @@ The prefix arg is passed through to the command if possible."
          (progn (message "Skipping removed entry at %s" e)
                 (setq cntskip (1+ cntskip)))
        (goto-char pos)
-       (eval cmd)
+       (let (org-loop-over-headlines-in-active-region)
+         (eval cmd))
        (setq org-agenda-bulk-marked-entries
              (delete e org-agenda-bulk-marked-entries))
        (setq cnt (1+ cnt))))
@@ -7946,7 +8545,7 @@ tag and (if present) the flagging note."
          (org-agenda-remove-flag hdmarker)
          (let ((win (get-buffer-window "*Flagging Note*")))
            (and win (delete-window win)))
-         (message "Entry unflaged"))
+         (message "Entry unflagged"))
       (setq note (org-entry-get hdmarker "THEFLAGGINGNOTE"))
       (unless note
        (error "No flagging note"))
@@ -7969,7 +8568,7 @@ tag and (if present) the flagging note."
       (org-entry-delete nil "THEFLAGGINGNOTE")
       (setq newhead (org-get-heading)))
     (org-agenda-change-all-lines newhead marker)
-    (message "Entry unflaged")))
+    (message "Entry unflagged")))
 
 (defun org-agenda-get-any-marker (&optional pos)
   (or (get-text-property (or pos (point-at-bol)) 'org-hd-marker)
@@ -7980,7 +8579,7 @@ tag and (if present) the flagging note."
 (defvar appt-time-msg-list)
 
 ;;;###autoload
-(defun org-agenda-to-appt (&optional refresh filter)
+(defun org-agenda-to-appt (&optional refresh filter &rest args)
   "Activate appointments found in `org-agenda-files'.
 With a \\[universal-argument] prefix, refresh the list of
 appointments.
@@ -7991,6 +8590,10 @@ expression, and filter out entries that don't match it.
 If FILTER is a string, use this string as a regular expression
 for filtering entries out.
 
+If FILTER is a function, filter out entries against which
+calling the function returns nil.  This function takes one
+argument: an entry from `org-agenda-get-day-entries'.
+
 FILTER can also be an alist with the car of each cell being
 either 'headline or 'category.  For example:
 
@@ -7998,12 +8601,18 @@ either 'headline or 'category.  For example:
     (category \"Work\"))
 
 will only add headlines containing IMPORTANT or headlines
-belonging to the \"Work\" category."
+belonging to the \"Work\" category.
+
+ARGS are symbols indicating what kind of entries to consider.
+By default `org-agenda-to-appt' will use :deadline, :scheduled
+and :timestamp entries.  See the docstring of `org-diary' for
+details and examples."
   (interactive "P")
   (if refresh (setq appt-time-msg-list nil))
   (if (eq filter t)
       (setq filter (read-from-minibuffer "Regexp filter: ")))
   (let* ((cnt 0) ; count added events
+        (scope (or args '(:deadline :scheduled :timestamp)))
         (org-agenda-new-buffers nil)
         (org-deadline-warning-days 0)
         ;; Do not use `org-today' here because appt only takes
@@ -8017,10 +8626,10 @@ belonging to the \"Work\" category."
     (org-prepare-agenda-buffers files)
     (while (setq file (pop files))
       (setq entries
-           (append entries
-                   (org-agenda-get-day-entries
-                    file today :timestamp :scheduled :deadline))))
-    (setq entries (delq nil entries))
+           (delq nil
+                 (append entries
+                         (apply 'org-agenda-get-day-entries
+                                file today scope)))))
     ;; Map thru entries and find if we should filter them out
     (mapc
      (lambda(x)
@@ -8029,11 +8638,14 @@ belonging to the \"Work\" category."
              (tod (get-text-property 1 'time-of-day x))
              (ok (or (null filter)
                      (and (stringp filter) (string-match filter evt))
+                     (and (functionp filter) (funcall filter x))
                      (and (listp filter)
-                          (or (string-match
-                               (cadr (assoc 'category filter)) cat)
-                              (string-match
-                               (cadr (assoc 'headline filter)) evt))))))
+                          (let ((cat-filter (cadr (assoc 'category filter)))
+                                (evt-filter (cadr (assoc 'headline filter))))
+                            (or (and (stringp cat-filter)
+                                     (string-match cat-filter cat))
+                                (and (stringp evt-filter)
+                                     (string-match evt-filter evt))))))))
         ;; FIXME: Shall we remove text-properties for the appt text?
         ;; (setq evt (set-text-properties 0 (length evt) nil evt))
         (when (and ok tod)
@@ -8056,7 +8668,14 @@ belonging to the \"Work\" category."
                date)))
     (eq date today)))
 
-(provide 'org-agenda)
+(defun org-agenda-todo-yesterday (&optional arg)
+  "Like `org-agenda-todo' but the time of change will be 23:59 of yesterday"
+  (interactive "P")
+  (let* ((hour (third (decode-time
+                       (org-current-time))))
+         (org-extend-today-until (1+ hour)))
+    (org-agenda-todo arg)))
 
+(provide 'org-agenda)
 
 ;;; org-agenda.el ends here