Merge from emacs-24; up to 2012-04-22T13:58:00Z!cyd@gnu.org
[bpt/emacs.git] / lisp / org / org-agenda.el
index 4ad19b3..ddb56ca 100644 (file)
@@ -1,12 +1,10 @@
 ;;; org-agenda.el --- Dynamic task and appointment lists for Org
 
-;; Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 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: 6.33x
 ;;
 ;; 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:
 
 (require 'org)
 (eval-when-compile
-  (require 'cl)
-  (require 'calendar))
+  (require 'cl))
 
 (declare-function diary-add-to-list "diary-lib"
                   (date string specifier &optional marker globcolor literal))
@@ -52,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" ())
 (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
 (defvar org-habit-show-habits)
 (defvar org-habit-show-habits-only-for-today)
@@ -88,17 +108,21 @@ only needed when the text to be killed contains more than N non-white lines."
          (integer :tag "When more than N lines")))
 
 (defcustom org-agenda-compact-blocks nil
-  "Non-nil means, make the block agenda more compact.
-This is done by leaving out unnecessary lines."
+  "Non-nil means make the block agenda more compact.
+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)))
 
@@ -108,7 +132,7 @@ If it is a character, it will be repeated to fill the window width."
  :group 'org-agenda)
 
 (defcustom org-agenda-with-colors t
-  "Non-nil means, use colors in agenda views."
+  "Non-nil means use colors in agenda views."
   :group 'org-agenda-export
   :type 'boolean)
 
@@ -143,13 +167,13 @@ specifies the maximum number of lines that will be added for each entry
 that is listed in the agenda view.
 
 Note that this variable is not used during display, only when exporting
-the agenda.  For agenda display, see org-agenda-entry-text-mode and the
-variable `org-agenda-entry-text-maxlines'."
+the agenda.  For agenda display, see the variables `org-agenda-entry-text-mode'
+and `org-agenda-entry-text-maxlines'."
   :group 'org-agenda
   :type 'integer)
 
 (defcustom org-agenda-add-entry-text-descriptive-links t
-  "Non-nil means, export org-links as descriptive links in agenda added text.
+  "Non-nil means export org-links as descriptive links in agenda added text.
 This variable applies to the text added to the agenda when
 `org-agenda-add-entry-text-maxlines' is larger than 0.
 When this variable nil, the URL will (also) be shown."
@@ -198,6 +222,11 @@ you can \"misuse\" it to also add other text to the header.  However,
   :group 'org-export-html
   :type 'string)
 
+(defcustom org-agenda-persistent-filter nil
+  "When set, keep filters from one agenda view to the next."
+  :group 'org-agenda
+  :type 'boolean)
+
 (defgroup org-agenda-custom-commands nil
  "Options concerning agenda views in Org-mode."
  :tag "Org Agenda Custom Commands"
@@ -212,9 +241,14 @@ you can \"misuse\" it to also add other text to the header.  However,
     (const todo-state-up) (const todo-state-down)
     (const effort-up) (const effort-down)
     (const habit-up) (const habit-down)
+    (const alpha-up) (const alpha-down)
     (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"
@@ -236,8 +270,12 @@ you can \"misuse\" it to also add other text to the header.  However,
                  (const org-agenda-prefix-format :value "  %-12:c%?-12t% s")
                  (string))
            (list :tag "Number of days in agenda"
-                 (const org-agenda-ndays)
-                 (integer :value 1))
+                 (const org-agenda-span)
+                 (choice (const :tag "Day" 'day)
+                         (const :tag "Week" 'week)
+                         (const :tag "Month" 'month)
+                         (const :tag "Year" 'year)
+                         (integer :tag "Custom")))
            (list :tag "Fixed starting date"
                  (const org-agenda-start-day)
                  (string :value "2007-11-01"))
@@ -252,12 +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)
+                 (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)
@@ -273,6 +326,24 @@ you can \"misuse\" it to also add other text to the header.  However,
                             :tag "Condition type"
                             (list :tag "Regexp matches" :inline t (const :format "" 'regexp) (regexp))
                             (list :tag "Regexp does not match" :inline t (const :format "" 'notregexp) (regexp))
+                            (list :tag "TODO state is" :inline t
+                                  (const 'todo)
+                                  (choice
+                                   (const :tag "any not-done state" 'todo)
+                                   (const :tag "any done state" 'done)
+                                   (const :tag "any state" 'any)
+                                   (list :tag "Keyword list"
+                                         (const :format "" quote)
+                                         (repeat (string :tag "Keyword")))))
+                            (list :tag "TODO state is not" :inline t
+                                  (const 'nottodo)
+                                  (choice
+                                   (const :tag "any not-done state" 'todo)
+                                   (const :tag "any done state" 'done)
+                                   (const :tag "any state" 'any)
+                                   (list :tag "Keyword list"
+                                         (const :format "" quote)
+                                         (repeat (string :tag "Keyword")))))
                             (const :tag "scheduled" 'scheduled)
                             (const :tag "not scheduled" 'notscheduled)
                             (const :tag "deadline" 'deadline)
@@ -291,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:
@@ -336,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)
@@ -481,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"
@@ -499,20 +588,20 @@ this one will be used."
   :group 'org-agenda)
 
 (defvar org-agenda-archives-mode nil
-  "Non-nil means, the agenda will include archived items.
+  "Non-nil means the agenda will include archived items.
 If this is the symbol `trees', trees in the selected agenda scope
 that are marked with the ARCHIVE tag will be included anyway.  When this is
 t, also all archive files associated with the current selection of agenda
 files will be included.")
 
 (defcustom org-agenda-skip-comment-trees t
-  "Non-nil means, skip trees that start with the COMMENT keyword.
+  "Non-nil means skip trees that start with the COMMENT keyword.
 When nil, these trees are also scanned by agenda commands."
   :group 'org-agenda-skip
   :type 'boolean)
 
 (defcustom org-agenda-todo-list-sublevels t
-  "Non-nil means, check also the sublevels of a TODO entry for TODO entries.
+  "Non-nil means check also the sublevels of a TODO entry for TODO entries.
 When nil, the sublevels of a TODO entry are not checked, resulting in
 potentially much shorter TODO lists."
   :group 'org-agenda-skip
@@ -520,7 +609,7 @@ potentially much shorter TODO lists."
   :type 'boolean)
 
 (defcustom org-agenda-todo-ignore-with-date nil
-  "Non-nil means, don't show entries with a date in the global todo list.
+  "Non-nil means don't show entries with a date in the global todo list.
 You can use this if you prefer to mark mere appointments with a TODO keyword,
 but don't want them to show up in the TODO list.
 When this is set, it also covers deadlines and scheduled items, the settings
@@ -531,31 +620,123 @@ See also the variable `org-agenda-tags-todo-honor-ignore-options'."
   :group 'org-agenda-todo-list
   :type 'boolean)
 
+(defcustom org-agenda-todo-ignore-timestamp nil
+  "Non-nil means don't show entries with a timestamp.
+This applies when creating the global todo list.
+Valid values are:
+
+past     Don't show entries for today or in the past.
+
+future   Don't show entries with a timestamp in the future.
+         The idea behind this is that if it has a future
+         timestamp, you don't want to think about it until the
+         date.
+
+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)
+         (integer :tag "Ignore if N or more days in past(-) or future(+).")))
+
 (defcustom org-agenda-todo-ignore-scheduled nil
-  "Non-nil means, don't show scheduled entries in the global todo list.
-The idea behind this is that by scheduling it, you have already taken care
-of this item.
+  "Non-nil means, ignore some scheduled TODO items when making TODO list.
+This applies when creating the global todo list.
+Valid values are:
+
+past     Don't show entries scheduled today or in the past.
+
+future   Don't show entries scheduled in the future.
+         The idea behind this is that by scheduling it, you don't want to
+         think about it until the scheduled date.
+
+all      Don't show any scheduled entries in the global todo list.
+         The idea behind this is that by scheduling it, you have already
+         \"taken care\" of this item.
+
+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'."
+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
-  :type 'boolean)
+  :type '(choice
+         (const :tag "Ignore future-scheduled todos" future)
+         (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)
+         (integer :tag "Ignore if N or more days in past(-) or future(+).")))
 
 (defcustom org-agenda-todo-ignore-deadlines nil
-  "Non-nil means, don't show near deadline entries in the global todo list.
-Near means closer than `org-deadline-warning-days' days.
-The idea behind this is that such items will appear in the agenda anyway.
+  "Non-nil means ignore some deadlined TODO items when making TODO list.
+There are different motivations for using different values, please think
+carefully when configuring this variable.
+
+This applies when creating the global todo list.
+Valid values are:
+
+near    Don't show near deadline entries.  A deadline is near when it is
+        closer than `org-deadline-warning-days' days.  The idea behind this
+        is that such items will appear in the agenda anyway.
+
+far     Don't show TODO entries where a deadline has been defined, but
+        the deadline is not near.  This is useful if you don't want to
+        use the todo list to figure out what to do now.
+
+past    Don't show entries with a deadline timestamp for today or in the past.
+
+future  Don't show entries with a deadline timestamp in the future, not even
+        when they become `near' ones.  Use it with caution.
+
+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'."
+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
-  :type 'boolean)
+  :type '(choice
+         (const :tag "Ignore near deadlines" near)
+         (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)
+         (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.
+  "Non-nil means honor todo-list ...ignore options also in tags-todo search.
 The variables
    `org-agenda-todo-ignore-with-date',
-   `org-agenda-todo-ignore-scheduled'
+   `org-agenda-todo-ignore-timestamp',
+   `org-agenda-todo-ignore-scheduled',
    `org-agenda-todo-ignore-deadlines'
 make the global TODO list skip entries that have time stamps of certain
 kinds.  If this option is set, the same options will also apply for the
@@ -603,7 +784,26 @@ deadlines are always turned off when the item is DONE."
   :group 'org-agenda-daily/weekly
   :type 'boolean)
 
-(defcustom org-agenda-skip-additional-timestamps-same-entry t
+(defcustom org-agenda-skip-deadline-prewarning-if-scheduled nil
+  "Non-nil means skip deadline prewarning when entry is also scheduled.
+This will apply on all days where a prewarning for the deadline would
+be shown, but not at the day when the entry is actually due.  On that day,
+the deadline will be shown anyway.
+This variable may be set to nil, t, or a number which will then give
+the number of days before the actual deadline when the prewarnings
+should resume.
+This can be used in a workflow where the first showing of the deadline will
+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 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."
@@ -617,7 +817,7 @@ entry, the rest of the entry will not be searched."
   :type 'boolean)
 
 (defcustom org-agenda-dim-blocked-tasks t
-  "Non-nil means, dim blocked tasks in the agenda display.
+  "Non-nil means dim blocked tasks in the agenda display.
 This causes some overhead during agenda construction, but if you
 have turned on `org-enforce-todo-dependencies',
 `org-enforce-todo-checkbox-dependencies', or any other blocking
@@ -635,11 +835,11 @@ 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
-  "Non-nil means, `org-timeline' also shows dates without an entry.
+  "Non-nil means `org-timeline' also shows dates without an entry.
 When nil, only the days which actually have entries are shown.
 When t, all days between the first and the last date are shown.
 When an integer, show also empty dates, but if there is a gap of more than
@@ -655,25 +855,50 @@ N days, just insert a special line indicating the size of the gap."
   :tag "Org Agenda Startup"
   :group 'org-agenda)
 
+(defcustom org-agenda-menu-show-matcher t
+  "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 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
+  "Non-nil means, use two columns to show custom commands in the dispatcher.
+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
   "Hook run just before displaying an agenda buffer."
   :group 'org-agenda-startup
   :type 'hook)
 
 (defcustom org-agenda-mouse-1-follows-link nil
-  "Non-nil means, mouse-1 on a link will follow the link in the agenda.
+  "Non-nil means mouse-1 on a link will follow the link in the agenda.
 A longer mouse click will still set point.  Does not work on XEmacs.
 Needs to be set before org.el is loaded."
   :group 'org-agenda-startup
   :type 'boolean)
 
 (defcustom org-agenda-start-with-follow-mode nil
-  "The initial value of follow-mode in a newly created agenda window."
+  "The initial value of follow mode in a newly created agenda window."
   :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-il means, show outline path in echo area after line motion."
+  "Non-nil means show outline path in echo area after line motion."
   :group 'org-agenda-startup
   :type 'boolean)
 
@@ -707,7 +932,7 @@ have been removed when this is called, as will any matches for regular
 expressions listed in `org-agenda-entry-text-exclude-regexps'.")
 
 (defvar org-agenda-include-inactive-timestamps nil
-  "Non-nil means, include inactive time stamps in agenda and timeline.")
+  "Non-nil means include inactive time stamps in agenda and timeline.")
 
 (defgroup org-agenda-windows nil
   "Options concerning the windows used by the Agenda in Org Mode."
@@ -740,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
@@ -749,15 +974,28 @@ option will be ignored."
   :group 'org-agenda-windows
   :type 'boolean)
 
-(defcustom org-agenda-ndays 7
-  "Number of days to include in overview display.
+(defcustom org-agenda-ndays nil
+   "Number of days to include in overview display.
 Should be 1 or 7.
+Obsolete, see `org-agenda-span'."
+   :group 'org-agenda-daily/weekly
+   :type 'integer)
+
+(make-obsolete-variable 'org-agenda-ndays 'org-agenda-span "24.1")
+
+(defcustom org-agenda-span 'week
+  "Number of days to include in overview display.
+Can be day, week, month, year, or any number of days.
 Custom commands can set this variable in the options section."
   :group 'org-agenda-daily/weekly
-  :type 'integer)
+  :type '(choice (const :tag "Day" day)
+                (const :tag "Week" week)
+                (const :tag "Month" month)
+                (const :tag "Year" year)
+                (integer :tag "Custom")))
 
 (defcustom org-agenda-start-on-weekday 1
-  "Non-nil means, start the overview always on the specified weekday.
+  "Non-nil means start the overview always on the specified weekday.
 0 denotes Sunday, 1 denotes Monday etc.
 When nil, always start on the current day.
 Custom commands can set this variable in the options section."
@@ -766,7 +1004,7 @@ Custom commands can set this variable in the options section."
                 (integer :tag "Weekday No.")))
 
 (defcustom org-agenda-show-all-dates t
-  "Non-nil means, `org-agenda' shows every day in the selected range.
+  "Non-nil means `org-agenda' shows every day in the selected range.
 When nil, only the days which actually have entries are shown."
   :group 'org-agenda-daily/weekly
   :type 'boolean)
@@ -805,6 +1043,43 @@ This function makes sure that dates are aligned for easy reading."
     (format "%-10s %2d %s %4d%s"
            dayname day monthname year weekstring)))
 
+(defcustom org-agenda-time-leading-zero nil
+  "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)
+  "Convert TIME of a string like '13:45' to an AM/PM style time string."
+  (let* ((hour-number (string-to-number (substring time 0 -3)))
+         (minute (substring time -2))
+         (ampm "am"))
+    (cond
+     ((equal hour-number 12)
+      (setq ampm "pm"))
+     ((> hour-number 12)
+      (setq ampm "pm")
+      (setq hour-number (- hour-number 12))))
+    (concat
+     (if org-agenda-time-leading-zero
+        (format "%02d" hour-number)
+       (format "%02s" (number-to-string hour-number)))
+     ":" minute ampm)))
+
+(defun org-agenda-time-of-day-to-ampm-maybe (time)
+  "Conditionally convert TIME to AM/PM format
+based on `org-agenda-timegrid-use-ampm'"
+  (if org-agenda-timegrid-use-ampm
+      (org-agenda-time-of-day-to-ampm time)
+    time))
+
 (defcustom org-agenda-weekend-days '(6 0)
   "Which days are weekend?
 These days get the special face `org-agenda-date-weekend' in the agenda
@@ -819,26 +1094,40 @@ 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."
   :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."
+(defcustom org-agenda-include-deadlines t
+  "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
+  :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."
+  "Non-nil means show all occurrences of a repeating stamp in the agenda.
+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.
@@ -860,8 +1149,52 @@ 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.
+  "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
 notes, the first line of these notes will be added to the entry in the
 agenda display."
@@ -891,15 +1224,43 @@ current display in the agenda."
   :group 'org-agenda-daily/weekly
   :type 'plist)
 
-(defcustom org-agenda-search-view-search-words-only nil
-  "Non-nil means, the search string is interpreted as individual words
-The search then looks for each word separately in each entry and
-selects entries that have matches for all words.
-When nil, matching as loose words will only take place if the first
-word is preceded by + or -.  If that is not the case, the search
-string will just be matched as a substring in the entry, but with
-each space character allowing for any whitespace, including newlines."
+(defcustom org-agenda-search-view-always-boolean nil
+  "Non-nil means the search string is interpreted as individual parts.
+
+The search string for search view can either be interpreted as a phrase,
+or as a list of snippets that define a boolean search for a number of
+strings.
+
+When this is non-nil, the string will be split on whitespace, and each
+snippet will be searched individually, and all must match in order to
+select an entry.  A snippet is then a single string of non-white
+characters, or a string in double quotes, or a regexp in {} braces.
+If a snippet is preceded by \"-\", the snippet must *not* match.
+\"+\" is syntactic sugar for positive selection.  Each snippet may
+be found as a full word or a partial word, but see the variable
+`org-agenda-search-view-force-full-words'.
+
+When this is nil, search will look for the entire search phrase as one,
+with each space character matching any amount of whitespace, including
+line breaks.
+
+Even when this is nil, you can still switch to Boolean search dynamically
+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)
+    (defvaralias 'org-agenda-search-view-search-words-only
+      'org-agenda-search-view-always-boolean))
+
+(defcustom org-agenda-search-view-force-full-words nil
+  "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
@@ -908,7 +1269,7 @@ each space character allowing for any whitespace, including newlines."
   :group 'org-agenda)
 
 (defcustom org-agenda-search-headline-for-time t
-  "Non-nil means, search headline for a time-of-day.
+  "Non-nil means search headline for a time-of-day.
 If the headline contains a time-of-day in one format or another, it will
 be used to sort the entry into the time sequence of items for a day.
 Some people have time stamps in the headline that refer to the creation
@@ -919,7 +1280,7 @@ for a time."
   :type 'boolean)
 
 (defcustom org-agenda-use-time-grid t
-  "Non-nil means, show a time grid in the agenda schedule.
+  "Non-nil means show a time grid in the agenda schedule.
 A time grid is a set of lines for specific times (like every two hours between
 8:00 and 20:00).  The items scheduled for a day at specific times are
 sorted in between these lines.
@@ -960,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"
@@ -993,6 +1367,8 @@ user-defined-up    Sort according to `org-agenda-cmp-user-defined', high last.
 user-defined-down  Sort according to `org-agenda-cmp-user-defined', high first.
 habit-up           Put entries that are habits first
 habit-down         Put entries that are habits last
+alpha-up           Sort headlines alphabetically
+alpha-down         Sort headlines alphabetically, reversed
 
 The different possibilities will be tried in sequence, and testing stops
 if one comparison returns a \"not-equal\".  For example, the default
@@ -1036,7 +1412,7 @@ part of an agenda sorting strategy."
   :type 'symbol)
 
 (defcustom org-sort-agenda-notime-is-late t
-  "Non-nil means, items without time are considered late.
+  "Non-nil means items without time are considered late.
 This is only relevant for sorting.  When t, items which have no explicit
 time like 15:30 will be considered as 99:01, i.e. later than any items which
 do have a time.  When nil, the default time is before 0:00.  You can use this
@@ -1046,7 +1422,7 @@ agenda entries."
   :type 'boolean)
 
 (defcustom org-sort-agenda-noeffort-is-high t
-  "Non-nil means, items without effort estimate are sorted as high effort.
+  "Non-nil means items without effort estimate are sorted as high effort.
 This also applies when filtering an agenda view with respect to the
 < or > effort operator.  Then, tasks with no effort defined will be treated
 as tasks with high effort.
@@ -1060,36 +1436,38 @@ When nil, such items are sorted as 0 minutes effort."
   :group 'org-agenda)
 
 (defcustom org-agenda-prefix-format
-  '((agenda  . "  %-12:c%?-12t% s")
+  '((agenda  . " %i %-12:c%?-12t% s")
     (timeline  . "  % s")
-    (todo  . "  %-12:c")
-    (tags  . "  %-12:c")
-    (search . "  %-12:c"))
+    (todo  . " %i %-12:c")
+    (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.
-  %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
@@ -1097,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'.
@@ -1163,6 +1538,15 @@ that passed since this item was scheduled first."
          (string :tag "Scheduled today     ")
          (string :tag "Scheduled previously")))
 
+(defcustom org-agenda-inactive-leader "["
+  "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")))
+
 (defcustom org-agenda-deadline-leaders '("Deadline:  " "In %3d d.: ")
   "Text preceding deadline items in the agenda view.
 This is a list with two strings.  The first applies when the item has its
@@ -1177,7 +1561,7 @@ is (was)."
                  (function))))
 
 (defcustom org-agenda-remove-times-when-in-prefix t
-  "Non-nil means, remove duplicate time specifications in agenda items.
+  "Non-nil means remove duplicate time specifications in agenda items.
 When the format `org-agenda-prefix-format' contains a `%t' specifier, a
 time-of-day specification in a headline or diary entry is extracted and
 placed into the prefix.  If this option is non-nil, the original specification
@@ -1185,7 +1569,7 @@ placed into the prefix.  If this option is non-nil, the original specification
 11:30-4pm) will be removed for agenda display.  This makes the agenda less
 cluttered.
 The option can be t or nil.  It may also be the symbol `beg', indicating
-that the time should only be removed what it is located at the beginning of
+that the time should only be removed when it is located at the beginning of
 the headline/diary entry."
   :group 'org-agenda-line-format
   :type '(choice
@@ -1193,6 +1577,12 @@ the headline/diary entry."
          (const :tag "Never" nil)
          (const :tag "When at beginning of entry" beg)))
 
+(defcustom org-agenda-remove-timeranges-from-blocks nil
+  "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
   "Default duration for appointments that only have a starting time.
@@ -1204,14 +1594,14 @@ When non-nil, this must be the number of minutes, e.g. 60 for one hour."
          (const :tag "No default duration")))
 
 (defcustom org-agenda-show-inherited-tags t
-  "Non-nil means, show inherited tags in each agenda line."
+  "Non-nil means show inherited tags in each agenda line."
   :group 'org-agenda-line-format
   :type 'boolean)
 
 (defcustom org-agenda-hide-tags-regexp nil
   "Regular expression used to filter away specific tags in agenda views.
 This means that these tags will be present, but not be shown in the agenda
-line.  Secondayt filltering will still work on the hidden tags.
+line.  Secondary filtering will still work on the hidden tags.
 Nil means don't hide any tags."
   :group 'org-agenda-line-format
   :type '(choice
@@ -1219,7 +1609,7 @@ Nil means don't hide any tags."
          (string :tag "Regexp   ")))
 
 (defcustom org-agenda-remove-tags nil
-  "Non-nil means, remove the tags from the headline copy in the agenda.
+  "Non-nil means remove the tags from the headline copy in the agenda.
 When this is the symbol `prefix', only remove tags when
 `org-agenda-prefix-format' contains a `%T' specifier."
   :group 'org-agenda-line-format
@@ -1244,16 +1634,18 @@ it means that the tags should be flushright to that column.  For example,
     (defvaralias 'org-agenda-align-tags-to-column 'org-agenda-tags-column))
 
 (defcustom org-agenda-fontify-priorities 'cookies
-  "Non-nil means, highlight low and high priorities in agenda.
+  "Non-nil means highlight low and high priorities in agenda.
 When t, the highest priority entries are bold, lowest priority italic.
-However, settings in org-priority-faces will overrule these faces.
+However, settings in `org-priority-faces' will overrule these faces.
 When this variable is the symbol `cookies', only fontify the
 cookies, not the entire task.
 This may also be an association list of priority faces, whose
 keys are the character values of `org-highest-priority',
 `org-default-priority', and `org-lowest-priority' (the default values
-are ?A, ?B, and ?C, respectively).  The face may be a named face,
-or a list like `(:background \"Red\")'."
+are ?A, ?B, and ?C, respectively).  The face may be a named face, a
+color as a string, or a list like `(:background \"Red\")'.
+If it is a color, the variable `org-faces-easy-properties'
+determines if it is a foreground or a background color."
   :group 'org-agenda-line-format
   :type '(choice
          (const :tag "Never" nil)
@@ -1261,7 +1653,57 @@ or a list like `(:background \"Red\")'."
          (const :tag "Cookies only" cookies)
          (repeat :tag "Specify"
                  (list (character :tag "Priority" :value ?A)
-                       (sexp :tag "face")))))
+                       (choice    :tag "Face    "
+                                  (string :tag "Color")
+                                  (sexp :tag "Face"))))))
+
+(defcustom org-agenda-day-face-function nil
+  "Function called to determine what face should be used to display a day.
+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
+  "Alist of category icon to be displayed in agenda views.
+
+Each entry should have the following format:
+
+  (CATEGORY-REGEXP FILE-OR-DATA TYPE DATA-P PROPS)
+
+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 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.
+PROPS are additional image attributes to assign to the image,
+like, e.g. `:ascent center'.
+
+   (\"Org\" \"/path/to/icon.png\" nil nil :ascent center)
+
+If you want to set the display properties yourself, just put a
+list as second element:
+
+  (CATEGORY-REGEXP (MY PROPERTY LIST))
+
+For example, to display a 16px horizontal space for Emacs
+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")
+                                         (symbol :tag "Type")
+                                         (boolean :tag "Data?")
+                                         (repeat :tag "Extra image properties" :inline t symbol))
+                                   (list :tag "Display properties" sexp))))
 
 (defgroup org-agenda-column-view nil
   "Options concerning column view in the agenda."
@@ -1269,22 +1711,12 @@ or a list like `(:background \"Red\")'."
   :group 'org-agenda)
 
 (defcustom org-agenda-columns-show-summaries t
-  "Non-nil means, show summaries for columns displayed in the agenda view."
+  "Non-nil means show summaries for columns displayed in the agenda view."
   :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.
+  "Non-nil means recompute all summary properties before column view.
 When column view in the agenda is listing properties that have a summary
 operator, it can go to all relevant buffers and recompute the summaries
 there.  This can mean overhead for the agenda column view, but is necessary
@@ -1295,7 +1727,7 @@ computations are current."
   :type 'boolean)
 
 (defcustom org-agenda-columns-add-appointments-to-effort-sum nil
-  "Non-nil means, the duration of an appointment will add to day effort.
+  "Non-nil means the duration of an appointment will add to day effort.
 The property to which appointment durations will be added is the one given
 in the option `org-effort-property'.  If an appointment does not have
 an end time, `org-agenda-default-appointment-duration' will be used.  If that
@@ -1309,14 +1741,45 @@ estimate."
 The sole argument to the function, which is called once for each
 possible tag, is a string giving the name of the tag.  The
 function should return either nil if the tag should be included
-as normal, or \"-<TAG>\" to exclude the tag."
+as normal, or \"-<TAG>\" to exclude the tag.
+Note that for the purpose of tag filtering, only the lower-case version of
+all tags will be considered, so that this function will only ever see
+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)
 
+(defmacro org-agenda-with-point-at-orig-entry (string &rest body)
+  "Execute BODY with point at location given by `org-hd-marker' property.
+If STRING is non-nil, the text property will be fetched from position 0
+in that string.  If STRING is nil, it will be fetched from the beginning
+of the current line."
+  (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'.
 This is mostly for hacking and trying a new command - once the command
@@ -1342,7 +1805,7 @@ works you probably want to add it to `org-agenda-custom-commands' for good."
 (defvar org-agenda-redo-command nil)
 (defvar org-agenda-query-string nil)
 (defvar org-agenda-mode-hook nil
-  "Hook for org-agenda-mode, run after the mode is turned on.")
+  "Hook for `org-agenda-mode', run after the mode is turned on.")
 (defvar org-agenda-type nil)
 (defvar org-agenda-force-single-file nil)
 (defvar org-agenda-bulk-marked-entries) ;; Defined further down in this file
@@ -1405,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)
@@ -1456,6 +1921,7 @@ The following commands are available:
 (org-defkey org-agenda-mode-map "l" 'org-agenda-log-mode)
 (org-defkey org-agenda-mode-map "v" 'org-agenda-view-mode-dispatch)
 (org-defkey org-agenda-mode-map "D" 'org-agenda-toggle-diary)
+(org-defkey org-agenda-mode-map "!" 'org-agenda-toggle-deadlines)
 (org-defkey org-agenda-mode-map "G" 'org-agenda-toggle-time-grid)
 (org-defkey org-agenda-mode-map "r" 'org-agenda-redo)
 (org-defkey org-agenda-mode-map "g" 'org-agenda-redo)
@@ -1466,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)
@@ -1496,7 +1962,7 @@ The following commands are available:
 (org-defkey org-agenda-mode-map "\C-c\C-x\C-x" 'org-agenda-clock-cancel)
 (org-defkey org-agenda-mode-map "X" 'org-agenda-clock-cancel)
 (org-defkey org-agenda-mode-map "\C-c\C-x\C-j" 'org-clock-goto)
-(org-defkey org-agenda-mode-map "J" 'org-clock-goto)
+(org-defkey org-agenda-mode-map "J" 'org-agenda-clock-goto)
 (org-defkey org-agenda-mode-map "+" 'org-agenda-priority-up)
 (org-defkey org-agenda-mode-map "-" 'org-agenda-priority-down)
 (org-defkey org-agenda-mode-map [(shift up)] 'org-agenda-priority-up)
@@ -1514,15 +1980,14 @@ 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)
 (org-defkey org-agenda-mode-map "\C-c\C-x\C-mp"    'org-mobile-push)
 
-(org-defkey org-agenda-mode-map
-  (if (featurep 'xemacs) [(button2)] [(mouse-2)]) 'org-agenda-goto-mouse)
-(org-defkey org-agenda-mode-map
-  (if (featurep 'xemacs) [(button3)] [(mouse-3)]) 'org-agenda-show-mouse)
+(org-defkey org-agenda-mode-map [mouse-2] 'org-agenda-goto-mouse)
+(org-defkey org-agenda-mode-map [mouse-3] 'org-agenda-show-mouse)
 (when org-agenda-mouse-1-follows-link
   (org-defkey org-agenda-mode-map [follow-link] 'mouse-face))
 (easy-menu-define org-agenda-menu org-agenda-mode-map "Agenda menu"
@@ -1538,24 +2003,27 @@ The following commands are available:
     ("View"
      ["Day View" org-agenda-day-view
       :active (org-agenda-check-type nil 'agenda)
-      :style radio :selected (equal org-agenda-ndays 1)
+      :style radio :selected (eq org-agenda-current-span 'day)
       :keys "v d  (or just d)"]
      ["Week View" org-agenda-week-view
       :active (org-agenda-check-type nil 'agenda)
-      :style radio :selected (equal org-agenda-ndays 7)
+      :style radio :selected (eq org-agenda-current-span 'week)
       :keys "v w  (or just w)"]
      ["Month View" org-agenda-month-view
       :active (org-agenda-check-type nil 'agenda)
-      :style radio :selected (member org-agenda-ndays '(28 29 30 31))
+      :style radio :selected (eq org-agenda-current-span 'month)
       :keys "v m"]
      ["Year View" org-agenda-year-view
       :active (org-agenda-check-type nil 'agenda)
-      :style radio :selected (member org-agenda-ndays '(365 366))
+      :style radio :selected (eq org-agenda-current-span 'year)
       :keys "v y"]
      "--"
      ["Include Diary" org-agenda-toggle-diary
       :style toggle :selected org-agenda-include-diary
       :active (org-agenda-check-type nil 'agenda)]
+     ["Include Deadlines" org-agenda-toggle-deadlines
+      :style toggle :selected org-agenda-include-deadlines
+      :active (org-agenda-check-type nil 'agenda)]
      ["Use Time Grid" org-agenda-toggle-time-grid
       :style toggle :selected org-agenda-use-time-grid
       :active (org-agenda-check-type nil 'agenda)]
@@ -1579,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]
     "--"
@@ -1607,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]
@@ -1674,7 +2143,7 @@ The following commands are available:
 ;;; Agenda undo
 
 (defvar org-agenda-allow-remote-undo t
-  "Non-nil means, allow remote undo from the agenda buffer.")
+  "Non-nil means allow remote undo from the agenda buffer.")
 (defvar org-agenda-undo-list nil
   "List of undoable operations in the agenda since last refresh.")
 (defvar org-agenda-undo-has-started-in nil
@@ -1682,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
@@ -1798,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
@@ -1820,7 +2290,6 @@ Pressing `<' twice means to restrict to the current subtree or region
            (move-marker org-agenda-restrict-end
                         (progn (org-end-of-subtree t)))))))
 
-      (require 'calendar)  ; FIXME: can we avoid this for some commands?
       ;; For example the todo list should not need it (but does...)
       (cond
        ((setq entry (assoc keys org-agenda-custom-commands))
@@ -1851,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)
@@ -1861,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))
@@ -1889,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))
@@ -1899,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
@@ -1913,12 +2393,13 @@ 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 "")
           restriction second-time
-          c entry key type match prefixes rmheader header-end custom1 desc)
+          c entry key type match prefixes rmheader header-end custom1 desc
+          line lines left right n n1)
       (save-window-excursion
        (delete-other-windows)
        (org-switch-to-buffer-other-window " *Agenda Commands*")
@@ -1956,56 +2437,91 @@ s   Search for keywords                 C   Configure custom agenda commands
            (move-marker header-end (match-end 0)))
          (goto-char header-end)
          (delete-region (point) (point-max))
+
+         ;; Produce all the lines that describe custom commands and prefixes
+         (setq lines nil)
          (while (setq entry (pop custom1))
            (setq key (car entry) desc (nth 1 entry)
                  type (nth 2 entry)
                  match (nth 3 entry))
            (if (> (length key) 1)
                (add-to-list 'prefixes (string-to-char key))
-             (insert
-              (format
-               "\n%-4s%-14s: %s"
-               (org-add-props (copy-sequence key)
-                   '(face bold))
-               (cond
-                ((string-match "\\S-" desc) desc)
-                ((eq type 'agenda) "Agenda for current week or day")
-                ((eq type 'alltodo) "List of all TODO entries")
-                ((eq type 'search) "Word search")
-                ((eq type 'stuck) "List of stuck projects")
-                ((eq type 'todo) "TODO keyword")
-                ((eq type 'tags) "Tags query")
-                ((eq type 'tags-todo) "Tags (TODO)")
-                ((eq type 'tags-tree) "Tags tree")
-                ((eq type 'todo-tree) "TODO kwd tree")
-                ((eq type 'occur-tree) "Occur tree")
-                ((functionp type) (if (symbolp type)
-                                      (symbol-name type)
-                                    "Lambda expression"))
-                (t "???"))
-               (cond
-                ((stringp match)
-                 (setq match (copy-sequence match))
-                 (org-add-props match nil 'face 'org-warning))
-                (match
-                 (format "set of %d commands" (length match)))
-                (t ""))))))
+             (setq line
+                   (format
+                    "%-4s%-14s"
+                    (org-add-props (copy-sequence key)
+                        '(face bold))
+                    (cond
+                     ((string-match "\\S-" desc) desc)
+                     ((eq type 'agenda) "Agenda for current week or day")
+                     ((eq type 'alltodo) "List of all TODO entries")
+                     ((eq type 'search) "Word search")
+                     ((eq type 'stuck) "List of stuck projects")
+                     ((eq type 'todo) "TODO keyword")
+                     ((eq type 'tags) "Tags query")
+                     ((eq type 'tags-todo) "Tags (TODO)")
+                     ((eq type 'tags-tree) "Tags tree")
+                     ((eq type 'todo-tree) "TODO kwd tree")
+                     ((eq type 'occur-tree) "Occur tree")
+                     ((functionp type) (if (symbolp type)
+                                           (symbol-name type)
+                                         "Lambda expression"))
+                     (t "???"))))
+             (if org-agenda-menu-show-matcher
+                 (setq line
+                       (concat line ": "
+                               (cond
+                                ((stringp match)
+                                 (setq match (copy-sequence match))
+                                 (org-add-props match nil 'face 'org-warning))
+                                (match
+                                 (format "set of %d commands" (length match)))
+                                (t ""))))
+               (if (org-string-nw-p match)
+                   (add-text-properties
+                    0 (length line) (list 'help-echo
+                                          (concat "Matcher: "match)) line)))
+             (push line lines)))
+         (setq lines (nreverse lines))
          (when prefixes
            (mapc (lambda (x)
-                   (insert
-                    (format "\n%s   %s"
+                   (push
+                    (format "%s   %s"
                             (org-add-props (char-to-string x)
-                                           nil 'face 'bold)
-                            (or (cdr (assoc (concat selstring (char-to-string x))
+                                nil 'face 'bold)
+                            (or (cdr (assoc (concat selstring
+                                                    (char-to-string x))
                                             prefix-descriptions))
-                                "Prefix key"))))
+                                "Prefix key"))
+                    lines))
                  prefixes))
+
+         ;; Check if we should display in two columns
+         (if org-agenda-menu-two-column
+             (progn
+               (setq n (length lines)
+                     n1 (+ (/ n 2) (mod n 2))
+                     right (nthcdr n1 lines)
+                     left (copy-sequence lines))
+               (setcdr (nthcdr (1- n1) left) nil))
+           (setq left lines right nil))
+         (while left
+           (insert "\n" (pop left))
+           (when right
+             (if (< (current-column) 40)
+                 (move-to-column 40 t)
+               (insert "   "))
+             (insert (pop right))))
+
+         ;; Make the window the right size
          (goto-char (point-min))
          (if second-time
              (if (not (pos-visible-in-window-p (point-max)))
                  (org-fit-window-to-buffer))
            (setq second-time t)
            (org-fit-window-to-buffer))
+
+         ;; Ask for selection
          (message "Press key for agenda command%s:"
                   (if (or restrict-ok org-agenda-overriding-restriction)
                       (if org-agenda-overriding-restriction
@@ -2061,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!
@@ -2099,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)))
@@ -2109,25 +2633,15 @@ s   Search for keywords                 C   Configure custom agenda commands
 If CMD-KEY is a string of length 1, it is used as a key in
 `org-agenda-custom-commands' and triggers this command.  If it is a
 longer string it is used as a tags/todo match string.
-Paramters are alternating variable names and values that will be bound
+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)
 
@@ -2137,7 +2651,7 @@ before running the agenda command."
 If CMD-KEY is a string of length 1, it is used as a key in
 `org-agenda-custom-commands' and triggers this command.  If it is a
 longer string it is used as a tags/todo match string.
-Paramters are alternating variable names and values that will be bound
+Parameters are alternating variable names and values that will be bound
 before running the agenda command.
 
 The output gives a line for each selected agenda item.  Each
@@ -2166,34 +2680,30 @@ 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-of-day 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,
-so the export commands can easily use it."
+  "Make sure all properties on an agenda item have a canonical form.
+This ensures the export commands can easily use it."
   (let (tmp re)
     (when (setq tmp (plist-get props 'tags))
       (setq props (plist-put props 'tags (mapconcat 'identity tmp ":"))))
@@ -2239,17 +2749,14 @@ so 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)
@@ -2259,15 +2766,17 @@ so 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."
@@ -2280,7 +2789,8 @@ so 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.
@@ -2295,9 +2805,6 @@ higher priority settings."
   (interactive "FWrite agenda to file: \nP")
   (if (not (file-writable-p file))
       (error "Cannot write agenda to file %s" file))
-  (cond
-   ((string-match "\\.html?\\'" file) (require 'htmlize))
-   ((string-match "\\.ps\\'" file) (require 'ps-print)))
   (org-let (if nosettings nil org-agenda-exporter-settings)
     '(save-excursion
        (save-window-excursion
@@ -2305,6 +2812,8 @@ higher priority settings."
         (let ((bs (copy-sequence (buffer-string))) beg)
           (org-agenda-unmark-filtered-text)
           (with-temp-buffer
+            (rename-buffer org-agenda-write-buffer-name t)
+            (set-buffer-modified-p nil)
             (insert bs)
             (org-agenda-remove-marked-text 'org-filtered)
             (while (setq beg (text-property-any (point-min) (point-max)
@@ -2317,6 +2826,7 @@ higher priority settings."
              ((org-bound-and-true-p org-mobile-creating-agendas)
               (org-mobile-write-agenda-for-mobile file))
              ((string-match "\\.html?\\'" file)
+              (require 'htmlize)
               (set-buffer (htmlize-buffer (current-buffer)))
 
               (when (and org-agenda-export-html-style
@@ -2331,18 +2841,17 @@ higher priority settings."
               (message "HTML written to %s" file))
              ((string-match "\\.ps\\'" file)
               (require 'ps-print)
-              (flet ((ps-get-buffer-name () "Agenda View"))
-                (ps-print-buffer-with-faces file))
+              (ps-print-buffer-with-faces file)
               (message "Postscript written to %s" file))
              ((string-match "\\.pdf\\'" file)
               (require 'ps-print)
-              (flet ((ps-get-buffer-name () "Agenda View"))
-                (ps-print-buffer-with-faces
-                 (concat (file-name-sans-extension file) ".ps")))
+              (ps-print-buffer-with-faces
+               (concat (file-name-sans-extension file) ".ps"))
               (call-process "ps2pdf" nil nil nil
                             (expand-file-name
                              (concat (file-name-sans-extension file) ".ps"))
                             (expand-file-name file))
+              (delete-file (concat (file-name-sans-extension file) ".ps"))
               (message "PDF written to %s" file))
              ((string-match "\\.ics\\'" file)
               (require 'org-icalendar)
@@ -2364,18 +2873,20 @@ 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."
   (let ((inhibit-read-only t))
     (mapc
      (lambda (o)
-       (when (equal (org-overlay-buffer o) (current-buffer))
+       (when (equal (overlay-buffer o) (current-buffer))
         (put-text-property
-         (org-overlay-start o) (org-overlay-end o)
+         (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."
@@ -2408,7 +2919,9 @@ Drawers will be excluded, also the line with scheduling/deadline info."
          (setq txt (org-agenda-get-some-entry-text
                     m org-agenda-add-entry-text-maxlines "    > "))
          (end-of-line 1)
-         (if (string-match "\\S-" txt) (insert "\n" txt)))))))
+         (if (string-match "\\S-" txt)
+             (insert "\n" txt)
+           (or (eobp) (forward-char 1))))))))
 
 (defun org-agenda-get-some-entry-text (marker n-lines &optional indent
                                              &rest keep)
@@ -2420,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
@@ -2536,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)))
 
@@ -2556,31 +3069,50 @@ 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-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 \"-\".
 This variable should not be set directly, but agenda custom commands can
-bind it in the options section.")
+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.")
+
+(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)
-  (setq org-agenda-filter nil)
-  (put 'org-agenda-filter :preset-filter org-agenda-filter-preset)
+  (unless org-agenda-persistent-filter
+    (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)
@@ -2597,14 +3129,18 @@ bind it in the options section.")
        (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)
        (switch-to-buffer-other-frame abuf))
        ((equal org-agenda-window-setup 'reorganize-frame)
        (delete-other-windows)
-       (org-switch-to-buffer-other-window abuf))))
+       (org-switch-to-buffer-other-window abuf)))
+      ;; additional test in case agenda is invoked from within agenda
+      ;; buffer via elisp link
+      (unless (equal (current-buffer) abuf)
+       (org-pop-to-buffer-same-window abuf)))
     (setq buffer-read-only nil)
     (let ((inhibit-read-only t)) (erase-buffer))
     (org-agenda-mode)
@@ -2643,16 +3179,18 @@ bind it in the options section.")
          (org-habit-insert-consistency-graphs))
       (run-hooks 'org-finalize-agenda-hook)
       (setq org-agenda-type (org-get-at-bol 'org-agenda-type))
-      (when (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 ()
   "Mark the current clock entry in the agenda if it is present."
   (mapc (lambda (o)
-         (if (eq (org-overlay-get o 'type) 'org-agenda-clocking)
-             (org-delete-overlay o)))
-       (org-overlays-in (point-min) (point-max)))
+         (if (eq (overlay-get o 'type) 'org-agenda-clocking)
+             (delete-overlay o)))
+       (overlays-in (point-min) (point-max)))
   (when (marker-buffer org-clock-hd-marker)
     (save-excursion
       (goto-char (point-min))
@@ -2661,18 +3199,18 @@ bind it in the options section.")
          (goto-char s)
          (when (equal (org-get-at-bol 'org-hd-marker)
                       org-clock-hd-marker)
-           (setq ov (org-make-overlay (point-at-bol) (1+ (point-at-eol))))
-           (org-overlay-put ov 'type 'org-agenda-clocking)
-           (org-overlay-put ov 'face 'org-agenda-clocking)
-           (org-overlay-put ov 'help-echo
+           (setq ov (make-overlay (point-at-bol) (1+ (point-at-eol))))
+           (overlay-put ov 'type 'org-agenda-clocking)
+           (overlay-put ov 'face 'org-agenda-clocking)
+           (overlay-put ov 'help-echo
                             "The clock is running in this item")))))))
 
 (defun org-agenda-fontify-priorities ()
   "Make highest priority lines bold, and lowest italic."
   (interactive)
-  (mapc (lambda (o) (if (eq (org-overlay-get o 'org-type) 'org-priority)
-                       (org-delete-overlay o)))
-       (org-overlays-in (point-min) (point-max)))
+  (mapc (lambda (o) (if (eq (overlay-get o 'org-type) 'org-priority)
+                       (delete-overlay o)))
+       (overlays-in (point-min) (point-max)))
   (save-excursion
     (let ((inhibit-read-only t)
          b e p ov h l)
@@ -2687,21 +3225,25 @@ bind it in the options section.")
              e (if (eq org-agenda-fontify-priorities 'cookies)
                    (match-end 0)
                  (point-at-eol))
-             ov (org-make-overlay b e))
-       (org-overlay-put
+             ov (make-overlay b e))
+       (overlay-put
         ov 'face
-        (cond ((cdr (assoc p org-priority-faces)))
+        (cond ((org-face-from-face-or-color
+                'priority nil
+                (cdr (assoc p org-priority-faces))))
               ((and (listp org-agenda-fontify-priorities)
-                    (cdr (assoc p org-agenda-fontify-priorities))))
+                    (org-face-from-face-or-color
+                     'priority nil
+                     (cdr (assoc p org-agenda-fontify-priorities)))))
               ((equal p l) 'italic)
               ((equal p h) 'bold)))
-       (org-overlay-put ov 'org-type 'org-priority)))))
+       (overlay-put ov 'org-type 'org-priority)))))
 
 (defun org-agenda-dim-blocked-tasks ()
   "Dim currently blocked TODO's in the agenda display."
-  (mapc (lambda (o) (if (eq (org-overlay-get o 'org-type) 'org-blocked-todo)
-                       (org-delete-overlay o)))
-       (org-overlays-in (point-min) (point-max)))
+  (mapc (lambda (o) (if (eq (overlay-get o 'org-type) 'org-blocked-todo)
+                       (delete-overlay o)))
+       (overlays-in (point-min) (point-max)))
   (save-excursion
     (let ((inhibit-read-only t)
          (org-depend-tag-blocked nil)
@@ -2714,27 +3256,19 @@ bind it in the options section.")
        (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)))
                      (point-at-bol))
                  e (point-at-eol)
-                 ov (org-make-overlay b e))
+                 ov (make-overlay b e))
            (if invis1
-               (org-overlay-put ov 'invisible t)
-             (org-overlay-put ov 'face 'org-agenda-dimmed-todo-face))
-           (org-overlay-put ov 'org-type 'org-blocked-todo)))))))
+               (overlay-put ov 'invisible t)
+             (overlay-put ov 'face 'org-agenda-dimmed-todo-face))
+           (overlay-put ov 'org-type 'org-blocked-todo)))))))
 
 (defvar org-agenda-skip-function nil
   "Function to be called at each match during agenda construction.
@@ -2743,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)
@@ -2761,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)
@@ -2807,10 +3353,10 @@ no longer in use."
                            (org-agenda-get-some-entry-text
                             m org-agenda-entry-text-maxlines "    > "))))
     (when (string-match "\\S-" txt)
-      (setq o (org-make-overlay (point-at-bol) (point-at-eol)))
-      (org-overlay-put o 'evaporate t)
-      (org-overlay-put o 'org-overlay-type 'agenda-entry-content)
-      (org-overlay-put o 'after-string txt))))
+      (setq o (make-overlay (point-at-bol) (point-at-eol)))
+      (overlay-put o 'evaporate t)
+      (overlay-put o 'org-overlay-type 'agenda-entry-content)
+      (overlay-put o 'after-string txt))))
 
 (defun org-agenda-entry-text-show ()
   "Add entry context for all agenda lines."
@@ -2827,16 +3373,26 @@ no longer in use."
   "Remove any shown entry context."
   (delq nil
        (mapcar (lambda (o)
-                 (if (eq (org-overlay-get o 'org-overlay-type)
+                 (if (eq (overlay-get o 'org-overlay-type)
                          'agenda-entry-content)
-                     (progn (org-delete-overlay o) t)))
-               (org-overlays-in (point-min) (point-max)))))
+                     (progn (delete-overlay o) t)))
+               (overlays-in (point-min) (point-max)))))
+
+(defun org-agenda-get-day-face (date)
+  "Return the face DATE should be displayed with."
+  (or (and (functionp org-agenda-day-face-function)
+          (funcall org-agenda-day-face-function date))
+      (cond ((org-agenda-todayp date)
+            'org-agenda-date-today)
+           ((member (calendar-day-of-week date) org-agenda-weekend-days)
+            'org-agenda-date-weekend)
+           (t 'org-agenda-date))))
 
 ;;; Agenda timeline
 
 (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,
@@ -2844,13 +3400,12 @@ under the current date.
 If the buffer contains an active region, only check the region for
 dates."
   (interactive "P")
-  (require 'calendar)
   (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)
+        (entry (buffer-file-name (or (buffer-base-buffer (current-buffer))
+                                     (current-buffer))))
         (date (calendar-current-date))
         (beg (if (org-region-active-p) (region-beginning) (point-min)))
         (end (if (org-region-active-p) (region-end) (point-max)))
@@ -2859,21 +3414,20 @@ dates."
                                         org-timeline-show-empty-dates))
         (org-deadline-warning-days 0)
         (org-agenda-only-exact-dates t)
-        (today (time-to-days (current-time)))
+        (today (org-today))
         (past t)
         args
-        s e rtn d emptyp wd)
+        s e rtn d emptyp)
     (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)
                                              (if (>= x today) x nil))
                                            day-numbers))))
-    (org-prepare-agenda (concat "Timeline "
-                               (file-name-nondirectory buffer-file-name)))
+    (org-prepare-agenda (concat "Timeline " (file-name-nondirectory entry)))
     (if doclosed (push :closed args))
     (push :timestamp args)
     (push :deadline args)
@@ -2897,8 +3451,7 @@ dates."
            (progn
              (setq past nil)
              (insert (make-string 79 ?-) "\n")))
-       (setq date (calendar-gregorian-from-absolute d)
-             wd (calendar-day-of-week date))
+       (setq date (calendar-gregorian-from-absolute d))
        (setq s (point))
        (setq rtn (and (not emptyp)
                       (apply 'org-agenda-get-day-entries entry
@@ -2912,9 +3465,7 @@ dates."
                 (funcall org-agenda-format-date date))
               "\n")
              (put-text-property s (1- (point)) 'face
-                                (if (member wd org-agenda-weekend-days)
-                                    'org-agenda-date-weekend
-                                  'org-agenda-date))
+                                (org-agenda-get-day-face date))
              (put-text-property s (1- (point)) 'org-date-line t)
              (put-text-property s (1- (point)) 'org-agenda-date-header t)
              (if (equal d today)
@@ -2938,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 (time-to-days (current-time)))))
+       (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 '<))
@@ -2972,59 +3527,85 @@ 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-span nil) ; local variable in the agenda buffer
-(defvar org-include-all-loc nil) ; local variable
+(defvar org-agenda-current-span nil
+  "The current span used in the agenda view.") ; local variable in the agenda buffer
+(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.
+This variable is a list of symbols that controls the types of
+items that appear in the daily/weekly agenda.  Allowed symbols in this
+list are are
+
+   :timestamp    List items containing a date stamp or date range matching
+                 the selected date.  This includes sexp entries in
+                 angular brackets.
+
+   :sexp         List entries resulting from plain diary-like sexps.
+
+   :deadline     List deadline due on that date.  When the date is today,
+                 also list any deadlines past due, or due within
+                `org-deadline-warning-days'.  `:deadline' must appear before
+                 `:scheduled' if the setting of
+                 `org-agenda-skip-scheduled-if-deadline-is-shown' is to have
+                 any effect.
+
+   :scheduled    List all items which are scheduled for the given date.
+                The diary for *today* also contains items which were
+                scheduled earlier and are not yet marked DONE.
+
+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 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 ndays)
+(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 NDAYS to change
-the number of days.  NDAYS defaults to `org-agenda-ndays'.
+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 ndays include-all include-all nil))
-  (setq ndays (or ndays org-agenda-ndays)
-       start-day (or start-day org-agenda-start-day))
+  (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)
-           ndays (nth 2 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 ndays))
+  (setq org-agenda-last-arguments (list arg start-day span))
   (org-compile-prefix-format 'agenda)
   (org-set-sorting-strategy 'agenda)
-  (require 'calendar)
-  (let* ((org-agenda-start-on-weekday
-         (if (or (equal ndays 7) (and (null ndays) (equal 7 org-agenda-ndays)))
-             org-agenda-start-on-weekday nil))
+  (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))
+        (org-agenda-start-on-weekday
+         (if (eq ndays 7)
+             org-agenda-start-on-weekday))
         (thefiles (org-agenda-files nil 'ifmode))
         (files thefiles)
-        (today (time-to-days
-                (time-subtract (current-time)
-                               (list 0 (* 3600 org-extend-today-until) 0))))
-        (sd (or start-day today))
         (start (if (or (null org-agenda-start-on-weekday)
-                       (< org-agenda-ndays 7))
+                       (< ndays 7))
                    sd
                  (let* ((nt (calendar-day-of-week
                              (calendar-gregorian-from-absolute sd)))
@@ -3034,42 +3615,19 @@ given in `org-agenda-start-on-weekday'."
         (day-numbers (list start))
         (day-cnt 0)
         (inhibit-redisplay (not debug-on-error))
-        s e rtn rtnall file date d start-pos end-pos todayp nd wd
-        clocktable-start clocktable-end)
+        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 ndays))
-    ;; Make the list of days
-    (setq ndays (or ndays org-agenda-ndays)
-         nd ndays)
-    (while (> ndays 1)
-      (push (1+ (car day-numbers)) day-numbers)
-      (setq ndays (1- ndays)))
+         (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))
     (setq clocktable-start (car day-numbers)
          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-agenda-span
-                  (org-agenda-ndays-to-span nd))
-    (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")))
+    (org-set-local 'org-arg-loc arg)
+    (org-set-local 'org-agenda-current-span (org-agenda-ndays-to-span span))
     (unless org-agenda-compact-blocks
       (let* ((d1 (car day-numbers))
             (d2 (org-last day-numbers))
@@ -3079,7 +3637,7 @@ given in `org-agenda-start-on-weekday'."
        (if org-agenda-overriding-header
            (insert (org-add-props (copy-sequence org-agenda-overriding-header)
                        nil 'face 'org-agenda-structure) "\n")
-         (insert (capitalize (symbol-name (org-agenda-ndays-to-span nd)))
+         (insert (org-agenda-span-name span)
                  "-agenda"
                  (if (< (- d2 d1) 350)
                      (if (= w1 w2)
@@ -3092,7 +3650,6 @@ given in `org-agenda-start-on-weekday'."
       (org-agenda-mark-header-line s))
     (while (setq d (pop day-numbers))
       (setq date (calendar-gregorian-from-absolute d)
-           wd (calendar-day-of-week date)
            s (point))
       (if (or (setq todayp (= d today))
              (and (not start-pos) (= d sd)))
@@ -3104,19 +3661,23 @@ given in `org-agenda-start-on-weekday'."
       (while (setq file (pop files))
        (catch 'nextfile
          (org-check-agenda-file file)
-         (cond
-          ((eq org-agenda-show-log 'only)
-           (setq rtn (org-agenda-get-day-entries
-                      file date :closed)))
-          (org-agenda-show-log
-           (setq rtn (org-agenda-get-day-entries
-                      file date
-                      :deadline :scheduled :timestamp :sexp :closed)))
-          (t
-           (setq rtn (org-agenda-get-day-entries
-                      file date
-                      :deadline :scheduled :sexp :timestamp))))
-         (setq rtnall (append rtnall rtn))))
+         (let ((org-agenda-entry-types org-agenda-entry-types))
+           (unless org-agenda-include-deadlines
+             (setq org-agenda-entry-types
+                   (delq :deadline org-agenda-entry-types)))
+           (cond
+            ((memq org-agenda-show-log '(only clockcheck))
+             (setq rtn (org-agenda-get-day-entries
+                        file date :closed)))
+            (org-agenda-show-log
+             (setq rtn (apply 'org-agenda-get-day-entries
+                              file date
+                              (append '(:closed) org-agenda-entry-types))))
+            (t
+             (setq rtn (apply 'org-agenda-get-day-entries
+                              file date
+                              org-agenda-entry-types)))))
+         (setq rtnall (append rtnall rtn)))) ;; all entries
       (if org-agenda-include-diary
          (let ((org-agenda-search-headline-for-time t))
            (require 'diary-lib)
@@ -3132,31 +3693,36 @@ given in `org-agenda-start-on-weekday'."
               (funcall org-agenda-format-date date))
             "\n")
            (put-text-property s (1- (point)) 'face
-                              (if (member wd org-agenda-weekend-days)
-                                  'org-agenda-date-weekend
-                                'org-agenda-date))
+                              (org-agenda-get-day-face date))
            (put-text-property s (1- (point)) 'org-date-line t)
            (put-text-property s (1- (point)) 'org-agenda-date-header t)
            (put-text-property s (1- (point)) 'org-day-cnt day-cnt)
            (when todayp
-             (put-text-property s (1- (point)) 'org-today t)
-             (put-text-property s (1- (point)) 'face 'org-agenda-date-today))
-           (if rtnall (insert
+             (put-text-property s (1- (point)) 'org-today t))
+           (if rtnall (insert ;; all entries
                        (org-finalize-agenda-entries
                         (org-agenda-add-time-grid-maybe
-                         rtnall nd todayp))
+                         rtnall ndays todayp))
                        "\n"))
            (put-text-property s (1- (point)) 'day d)
            (put-text-property s (1- (point)) 'org-day-cnt day-cnt))))
     (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-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 ""))))
        (setq tbl (apply 'org-get-clocktable p))
        (insert tbl)))
     (goto-char (point-min))
@@ -3171,12 +3737,38 @@ 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 "")))
 
 (defun org-agenda-ndays-to-span (n)
-  (cond ((< n 7) 'day) ((= n 7) 'week) ((< n 32) 'month) (t 'year)))
+  "Return a span symbol for a span of N days, or N if none matches."
+  (cond ((symbolp n) n)
+       ((= n 1) 'day)
+       ((= n 7) 'week)
+       (t n)))
+
+(defun org-agenda-span-to-ndays (span start-day)
+  "Return ndays from SPAN starting at START-DAY."
+  (cond ((numberp span) span)
+       ((eq span 'day) 1)
+       ((eq span 'week) 7)
+       ((eq span 'month)
+        (let ((date (calendar-gregorian-from-absolute start-day)))
+          (calendar-last-day-of-month (car date) (caddr date))))
+       ((eq span 'year)
+        (let ((date (calendar-gregorian-from-absolute start-day)))
+          (if (calendar-leap-year-p (caddr date)) 366 365)))))
+
+(defun org-agenda-span-name (span)
+  "Return a SPAN name."
+  (if (null span)
+      ""
+    (if (symbolp span)
+       (capitalize (symbol-name span))
+      (format "%d days" span))))
 
 ;;; Agenda word search
 
@@ -3195,11 +3787,11 @@ that when \"+Ameli\" is searched as a work, it will also match \"Ameli's\"")
     (modify-syntax-entry ?` "." org-search-syntax-table))
   org-search-syntax-table)
 
+(defvar org-agenda-last-search-view-search-was-boolean nil)
+
 ;;;###autoload
 (defun org-search-view (&optional todo-only string edit-at)
-  "Show all entries that contain words or regular expressions.
-If the first character of the search string is an asterisks,
-search only the headlines.
+  "Show all entries that contain a phrase or words or regular expressions.
 
 With optional prefix argument TODO-ONLY, only consider entries that are
 TODO entries.  The argument STRING can be used to pass a default search
@@ -3207,28 +3799,37 @@ string into this function.  If EDIT-AT is non-nil, it means that the
 user should get a chance to edit this string, with cursor at position
 EDIT-AT.
 
-The search string is broken into \"words\" by splitting at whitespace.
-Depending on the variable `org-agenda-search-view-search-words-only'
-and on whether the first character in the search string is \"+\" or \"-\",
-The string is then interpreted either as a substring with variable amounts
-of whitespace, or as a list or individual words that should be matched.
-
-The default is a substring match, where each space in the search string
-can expand to an arbitrary amount of whitespace, including newlines.
-
-If matching individual words, these words are then interpreted as a
-boolean expression with logical AND.  Words prefixed with a minus must
-not occur in the entry. Words without a prefix or prefixed with a plus
-must occur in the entry.  Matching is case-insensitive and the words
-are enclosed by word delimiters.
-
-Words enclosed by curly braces are interpreted as regular expressions
-that must or must not match in the entry.
-
-If the search string starts with an asterisk, search only in headlines.
-If (possibly after the leading star) the search string starts with an
-exclamation mark, this also means to look at TODO entries only, an effect
-that can also be achieved with a prefix argument.
+The search string can be viewed either as a phrase that should be found as
+is, or it can be broken into a number of snippets, each of which must match
+in a Boolean way to select an entry.  The default depends on the variable
+`org-agenda-search-view-always-boolean'.
+Even if this is turned off (the default) you can always switch to
+Boolean search dynamically by preceding the first word with  \"+\" or \"-\".
+
+The default is a direct search of the whole phrase, where each space in
+the search string can expand to an arbitrary amount of whitespace,
+including newlines.
+
+If using a Boolean search, the search string is split on whitespace and
+each snippet is searched separately, with logical AND to select an entry.
+Words prefixed with a minus must *not* occur in the entry.  Words without
+a prefix or prefixed with a plus must occur in the entry.  Matching is
+case-insensitive.  Words are enclosed by word delimiters (i.e. they must
+match whole words, not parts of a word) if
+`org-agenda-search-view-force-full-words' is set (default is nil).
+
+Boolean search snippets enclosed by curly braces are interpreted as
+regular expressions that must or (when preceded with \"-\") must not
+match in the entry.  Snippets enclosed into double quotes will be taken
+as a whole, to include whitespace.
+
+- If the search string starts with an asterisk, search only in headlines.
+- If (possibly after the leading star) the search string starts with an
+  exclamation mark, this also means to look at TODO entries only, an effect
+  that can also be achieved with a prefix argument.
+- If (possibly after star and exclamation mark) the search string starts
+  with a colon, this will mean that the (non-regexp) snippets of the
+  Boolean search must match as full words.
 
 This command searches the agenda files, and in addition the files listed
 in `org-agenda-text-search-extra-files'."
@@ -3243,17 +3844,22 @@ in `org-agenda-text-search-extra-files'."
                      'org-complex-heading-regexp org-complex-heading-regexp
                      'mouse-face 'highlight
                      'help-echo (format "mouse-2 or RET jump to location")))
+        (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 as-words
+        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)
                 (string-match "\\S-" string))
-      (setq string (read-string "[+-]Word/{Regexp} ...: "
-                               (cond
-                                ((integerp edit-at) (cons string edit-at))
-                                (edit-at string))
-                               'org-agenda-search-history)))
+      (setq string (read-string
+                   (if org-agenda-search-view-always-boolean
+                       "[+-]Word/{Regexp} ...: "
+                     "Phrase, or [+-]Word/{Regexp} ...: ")
+                   (cond
+                    ((integerp edit-at) (cons string edit-at))
+                    (edit-at string))
+                   'org-agenda-search-history)))
     (org-set-local 'org-todo-only todo-only)
     (setq org-agenda-redo-command
          (list 'org-search-view (if todo-only t nil) string
@@ -3267,30 +3873,64 @@ in `org-agenda-text-search-extra-files'."
     (when (equal (string-to-char words) ?!)
       (setq todo-only t
            words (substring words 1)))
-    (if (or org-agenda-search-view-search-words-only
-           (member (string-to-char string) '(?- ?+)))
-       (setq as-words t))
+    (when (equal (string-to-char words) ?:)
+      (setq full-words t
+           words (substring words 1)))
+    (if (or org-agenda-search-view-always-boolean
+           (member (string-to-char words) '(?- ?+ ?\{)))
+       (setq boolean t))
     (setq words (org-split-string words))
-    (if as-words
+    (let (www w)
+      (while (setq w (pop words))
+       (while (and (string-match "\\\\\\'" w) words)
+         (setq w (concat (substring w 0 -1) " " (pop words))))
+       (push w www))
+      (setq words (nreverse www) www nil)
+      (while (setq w (pop words))
+       (when (and (string-match "\\`[-+]?{" w)
+                  (not (string-match "}\\'" w)))
+         (while (and words (not (string-match "}\\'" (car words))))
+           (setq w (concat w " " (pop words))))
+         (setq w (concat w " " (pop words))))
+       (push w www))
+      (setq words (nreverse www)))
+    (setq org-agenda-last-search-view-search-was-boolean boolean)
+    (when boolean
+      (let (wds w)
+       (while (setq w (pop words))
+         (if (or (equal (substring w 0 1) "\"")
+                 (and (> (length w) 1)
+                      (member (substring w 0 1) '("+" "-"))
+                      (equal (substring w 1 2) "\"")))
+             (while (and words (not (equal (substring w -1) "\"")))
+               (setq w (concat w " " (pop words)))))
+         (and (string-match "\\`\\([-+]?\\)\"" w)
+              (setq w (replace-match "\\1" nil nil w)))
+         (and (equal (substring w -1) "\"") (setq w (substring w 0 -1)))
+         (push w wds))
+       (setq words (nreverse wds))))
+    (if boolean
        (mapc (lambda (w)
                (setq c (string-to-char w))
                (if (equal c ?-)
                    (setq neg t w (substring w 1))
                  (if (equal c ?+)
                      (setq neg nil w (substring w 1))
-                 (setq neg nil)))
+                   (setq neg nil)))
                (if (string-match "\\`{.*}\\'" w)
                    (setq re (substring w 1 -1))
-                 (setq re (concat "\\<" (regexp-quote (downcase w)) "\\>")))
+                 (if full-words
+                     (setq re (concat "\\<" (regexp-quote (downcase w)) "\\>"))
+                   (setq re (regexp-quote (downcase w)))))
                (if neg (push re regexps-) (push re regexps+)))
              words)
       (push (mapconcat (lambda (w) (regexp-quote w)) words "\\s-+")
            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)
@@ -3311,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
@@ -3321,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))))
@@ -3351,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))
@@ -3362,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))))))))))
@@ -3397,17 +4039,17 @@ in `org-agenda-text-search-extra-files'."
 
 ;;;###autoload
 (defun org-todo-list (arg)
-  "Show all TODO entries from all agenda file in a single list.
+  "Show all (not done) TODO entries from all agenda file in a single list.
 The prefix arg can be used to select a specific TODO keyword and limit
 the list to these.  When using \\[universal-argument], you will be prompted
 for a keyword.  A numeric prefix directly selects the Nth keyword in
 `org-todo-keywords-1'."
   (interactive "P")
-  (require 'calendar)
   (org-compile-prefix-format 'todo)
   (org-set-sorting-strategy 'todo)
   (org-prepare-agenda "TODO")
-  (let* ((today (time-to-days (current-time)))
+  (if (and (stringp arg) (not (string-match "\\S-" arg))) (setq arg nil))
+  (let* ((today (org-today))
         (date (calendar-gregorian-from-absolute today))
         (kwds org-todo-keywords-for-agenda)
         (completion-ignore-case t)
@@ -3475,11 +4117,12 @@ The prefix arg TODO-ONLY limits the search to TODO entries."
   (org-compile-prefix-format 'tags)
   (org-set-sorting-strategy 'tags)
   (let* ((org-tags-match-list-sublevels
-;??????          (if todo-only t org-tags-match-list-sublevels))
          org-tags-match-list-sublevels)
         (completion-ignore-case t)
         rtn rtnall files file pos matcher
         buffer)
+    (when (and (stringp match) (not (string-match "\\S-" match)))
+      (setq match nil))
     (setq matcher (org-make-tags-matcher match)
          match (car matcher) matcher (cdr matcher))
     (org-prepare-agenda (concat "TAGS " match))
@@ -3501,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
@@ -3543,12 +4186,12 @@ 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.")
 
 (defun org-agenda-skip-entry-when-regexp-matches ()
-  "Checks if the current entry contains match for `org-agenda-skip-regexp'.
+  "Check if the current entry contains match for `org-agenda-skip-regexp'.
 If yes, it returns the end position of this entry, causing agenda commands
 to skip the entry but continuing the search in the subtree.  This is a
 function that can be put into `org-agenda-skip-function' for the duration
@@ -3560,7 +4203,7 @@ of a command."
     (and skip end)))
 
 (defun org-agenda-skip-subtree-when-regexp-matches ()
-  "Checks if the current subtree contains match for `org-agenda-skip-regexp'.
+  "Check if the current subtree contains match for `org-agenda-skip-regexp'.
 If yes, it returns the end position of this tree, causing agenda commands
 to skip this subtree.  This is a function that can be put into
 `org-agenda-skip-function' for the duration of a command."
@@ -3571,7 +4214,7 @@ to skip this subtree.  This is a function that can be put into
     (and skip end)))
 
 (defun org-agenda-skip-entry-when-regexp-matches-in-subtree ()
-  "Checks if the current subtree contains match for `org-agenda-skip-regexp'.
+  "Check if the current subtree contains match for `org-agenda-skip-regexp'.
 If yes, it returns the end position of the current entry (NOT the tree),
 causing agenda commands to skip the entry but continuing the search in
 the subtree.  This is a function that can be put into
@@ -3597,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:
@@ -3610,10 +4253,26 @@ timestamp     Check if there is a timestamp (also deadline or scheduled)
 nottimestamp  Check if there is no timestamp (also deadline or scheduled)
 regexp        Check if regexp matches
 notregexp     Check if regexp does not match.
+todo          Check if TODO keyword matches
+nottodo       Check if TODO keyword does not match
 
 The regexp is taken from the conditions list, it must come right after
 the `regexp' or `notregexp' element.
 
+`todo' and `nottodo' accept as an argument a list of todo
+keywords, which may include \"*\" to match any todo keyword.
+
+    (org-agenda-skip-entry-if 'todo '(\"TODO\" \"WAITING\"))
+
+would skip all entries with \"TODO\" or \"WAITING\" keywords.
+
+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'.
+
 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
 that can be put into `org-agenda-skip-function' for the duration of a command."
@@ -3643,16 +4302,51 @@ that can be put into `org-agenda-skip-function' for the duration of a command."
           (re-search-forward (nth 1 m) end t))
       (and (setq m (memq 'notregexp conditions))
           (stringp (nth 1 m))
-          (not (re-search-forward (nth 1 m) end t))))
+          (not (re-search-forward (nth 1 m) end t)))
+      (and (or
+           (setq m (memq 'nottodo conditions))
+           (setq m (memq 'todo conditions)))
+          (org-agenda-skip-if-todo m end)))
      end)))
 
+(defun org-agenda-skip-if-todo (args end)
+  "Helper function for `org-agenda-skip-if', do not use it directly.
+ARGS is a list with first element either `todo' or `nottodo'.
+The remainder is either a list of TODO keywords, or a state symbol
+`todo' or `done' or `any'."
+  (let ((kw (car args))
+       (arg (cadr args))
+       todo-wds todo-re)
+    (setq todo-wds
+         (org-uniquify
+          (cond
+           ((listp arg)   ;; list of keywords
+            (if (member "*" arg)
+                (mapcar 'substring-no-properties org-todo-keywords-1)
+              arg))
+           ((symbolp arg) ;; keyword class name
+            (cond
+             ((eq arg 'todo)
+              (org-delete-all org-done-keywords
+                              (mapcar 'substring-no-properties
+                                      org-todo-keywords-1)))
+             ((eq arg 'done) org-done-keywords)
+             ((eq arg 'any)
+              (mapcar 'substring-no-properties org-todo-keywords-1)))))))
+    (setq todo-re
+         (concat "^\\*+[ \t]+\\<\\("
+                 (mapconcat 'identity todo-wds  "\\|")
+                 "\\)\\>"))
+    (if (eq kw 'todo)
+       (re-search-forward todo-re end t)
+      (not (re-search-forward todo-re end t)))))
+
 ;;;###autoload
 (defun org-agenda-list-stuck-projects (&rest ignore)
   "Create agenda view for projects that are stuck.
 Stuck projects are project that have no next actions.  For the definitions
 of what a project is and how to check if it stuck, customize the variable
-`org-stuck-projects'.
-MATCH is being ignored."
+`org-stuck-projects'."
   (interactive)
   (let* ((org-agenda-skip-function
          'org-agenda-skip-entry-when-regexp-matches-in-subtree)
@@ -3674,11 +4368,13 @@ MATCH is being ignored."
                          "\\)\\>"))
         (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]*$")))))
+                               (org-re "\\):[[:alnum:]_@#%:]*[ \t]*$")))))
         (gen-re (nth 3 org-stuck-projects))
         (re-list
          (delq nil
@@ -3701,12 +4397,11 @@ MATCH is being ignored."
 
 (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)
   (let* ((diary-fancy-buffer "*temporary-fancy-diary-buffer*")
-        (fancy-diary-buffer diary-fancy-buffer)
         (diary-display-hook '(fancy-diary-display))
         (diary-display-function 'fancy-diary-display)
         (pop-up-frames nil)
@@ -3733,7 +4428,14 @@ MATCH is being ignored."
          ;; 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
@@ -3741,10 +4443,10 @@ MATCH is being ignored."
       (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))
+                'type "diary" 'date date 'face 'org-agenda-diary))
             entries)))))
 
 (defvar org-agenda-cleanup-fancy-diary-hook nil
@@ -3811,33 +4513,16 @@ Needed to avoid empty dates which mess up holiday display."
       (apply 'diary-add-to-list args)
     (apply 'add-to-diary-list args)))
 
+(defvar org-diary-last-run-time nil)
+
 ;;;###autoload
 (defun org-diary (&rest args)
   "Return diary information from org-files.
 This function can be used in a \"sexp\" diary entry in the Emacs calendar.
 It accesses org files and extracts information from those files to be
 listed in the diary.  The function accepts arguments specifying what
-items should be listed.  The following arguments are allowed:
-
-   :timestamp    List the headlines of items containing a date stamp or
-                date range matching the selected date.  Deadlines will
-                also be listed, on the expiration day.
-
-   :sexp         List entries resulting from diary-like sexps.
-
-   :deadline     List any deadlines past due, or due within
-                `org-deadline-warning-days'.  The listing occurs only
-                in the diary for *today*, not at any other date.  If
-                an entry is marked DONE, it is no longer listed.
-
-   :scheduled    List all items which are scheduled for the given date.
-                The diary for *today* also contains items which were
-                scheduled earlier and are not yet marked DONE.
-
-   :todo         List all TODO items from the org-file.  This may be a
-                long list - so this is not turned on by default.
-                Like deadlines, these entries only show up in the
-                diary for *today*, not at any other date.
+items should be listed.  For a list of arguments allowed here, see the
+variable `org-agenda-entry-types'.
 
 The call in the diary file should look like this:
 
@@ -3867,8 +4552,14 @@ function from a program - use `org-agenda-get-day-entries' instead."
   (let* ((files (if (and entry (stringp entry) (string-match "\\S-" entry))
                    (list entry)
                  (org-agenda-files t)))
+        (time (org-float-time))
         file rtn results)
-    (org-prepare-agenda-buffers files)
+    (when (or (not org-diary-last-run-time)
+             (> (- time
+                   org-diary-last-run-time)
+                3))
+      (org-prepare-agenda-buffers files))
+    (setq org-diary-last-run-time time)
     ;; If this is called during org-agenda, don't return any entries to
     ;; the calendar.  Org Agenda will list these entries itself.
     (if org-disable-agenda-to-diary (setq files nil))
@@ -3897,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
@@ -3910,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)
@@ -3933,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
@@ -3944,69 +4637,132 @@ 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)
-  "Do we have a reason to ignore this todo entry because it has a time stamp?"
+(defun org-agenda-check-for-timestamp-as-reason-to-ignore-todo-item
+  (&optional end)
+  "Do we have a reason to ignore this TODO entry because it has a time stamp?"
   (when (or org-agenda-todo-ignore-with-date
            org-agenda-todo-ignore-scheduled
-           org-agenda-todo-ignore-deadlines)
+           org-agenda-todo-ignore-deadlines
+           org-agenda-todo-ignore-timestamp)
     (setq end (or end (save-excursion (outline-next-heading) (point))))
     (save-excursion
       (or (and org-agenda-todo-ignore-with-date
               (re-search-forward org-ts-regexp end t))
          (and org-agenda-todo-ignore-scheduled
-              (re-search-forward org-scheduled-time-regexp end t))
+              (re-search-forward org-scheduled-time-regexp end t)
+              (cond
+               ((eq org-agenda-todo-ignore-scheduled 'future)
+                (> (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)
-              (org-deadline-close (match-string 1)))))))
+              (cond
+               ((memq org-agenda-todo-ignore-deadlines '(t all)) t)
+               ((eq org-agenda-todo-ignore-deadlines 'far)
+                (not (org-deadline-close (match-string 1))))
+               ((eq org-agenda-todo-ignore-deadlines 'future)
+                (> (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))
+                    (regexp
+                     (concat
+                      org-scheduled-time-regexp "\\|" org-deadline-time-regexp))
+                    (start (point)))
+                ;; Copy current buffer into a temporary one
+                (with-temp-buffer
+                  (insert-buffer-substring buffer start end)
+                  (goto-char (point-min))
+                  ;; Delete SCHEDULED and DEADLINE items
+                  (while (re-search-forward regexp end t)
+                    (delete-region (match-beginning 0) (match-end 0)))
+                  (goto-char (point-min))
+                  ;; No search for timestamp left
+                  (when (re-search-forward org-ts-regexp nil t)
+                    (cond
+                     ((eq org-agenda-todo-ignore-timestamp 'future)
+                      (> (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
   "No heading for this item in buffer or region.")
 
 (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
@@ -4035,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)))
@@ -4064,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 (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))
@@ -4073,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
-                      (if inactivep "[" nil)
-                      head category tags timestr nil
+           (setq head (or (match-string 1) ""))
+           (setq txt (org-agenda-format-item
+                      (if inactivep org-agenda-inactive-leader 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))
@@ -4102,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
@@ -4126,21 +4887,96 @@ 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))
 
-         (if (string-match "\\S-" result)
-             (setq txt result)
-           (setq txt "SEXP entry returned empty string"))
-
-         (setq txt (org-format-agenda-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
-           'type "sexp")
-         (push txt ee))))
+         (dolist (r (if (stringp result)
+                        (list result)
+                      result)) ;; we expect a list here
+           (if (string-match "\\S-" r)
+               (setq txt r)
+             (setq txt "SEXP entry returned empty string"))
+
+           (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)))
 
+;; 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.
+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)
+     (<= d date2)
+     (= (calendar-day-of-week date) dayname)
+     (or (not skip-weeks)
+        (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."
@@ -4153,7 +4989,9 @@ the documentation of `org-diary'."
                              (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
@@ -4173,8 +5011,8 @@ the documentation of `org-diary'."
                            (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
@@ -4185,29 +5023,30 @@ the documentation of `org-diary'."
              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
-         (cond
-          ((not org-agenda-log-mode-add-notes) (setq extra nil))
-          (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))))
-          (t (setq extra nil)))
-         (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)
@@ -4219,7 +5058,7 @@ the documentation of `org-diary'."
                  (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 ")"))
@@ -4229,12 +5068,132 @@ the documentation of `org-diary'."
          (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
@@ -4247,21 +5206,39 @@ the documentation of `org-diary'."
         (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
-        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)
       (catch :skip
        (org-agenda-skip)
+       (when (and org-agenda-skip-deadline-prewarning-if-scheduled
+                  (save-match-data
+                    (string-match org-scheduled-time-regexp
+                                  (buffer-substring (point-at-bol)
+                                                    (point-at-eol)))))
+         (setq suppress-prewarning
+               (if (integerp org-agenda-skip-deadline-prewarning-if-scheduled)
+                   org-agenda-skip-deadline-prewarning-if-scheduled
+                 0)))
        (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 (org-get-wdays s)
-             dfrac (/ (* 1.0 (- wdays diff)) (max wdays 1))
+             wdays (if suppress-prewarning
+                       (let ((org-deadline-warning-days suppress-prewarning))
+                         (org-get-wdays s))
+                     (org-get-wdays s))
+             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.
@@ -4270,13 +5247,14 @@ the documentation of `org-diary'."
                          (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))
@@ -4290,7 +5268,7 @@ the documentation of `org-diary'."
                      (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
@@ -4303,13 +5281,14 @@ the documentation of `org-diary'."
                             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)
@@ -4318,10 +5297,9 @@ the documentation of `org-diary'."
                (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))
@@ -4346,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
@@ -4355,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:
@@ -4367,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))
@@ -4399,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
@@ -4426,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))))))
@@ -4443,48 +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))
-               (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
-                          (if (= d0 d1) timestr))))
-             (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)))
@@ -4505,8 +5507,16 @@ The flag is set if the currently compiled format contains a `%e'.")
 (defvar org-prefix-category-max-length nil
   "Used by `org-compile-prefix-format' to remember the category field width.")
 
-(defun org-format-agenda-item (extra txt &optional category tags dotime
-                                    noprefix remove-re habitp)
+(defun org-agenda-get-category-icon (category)
+  "Return an image for CATEGORY according to `org-agenda-category-icon-alist'."
+  (dolist (entry org-agenda-category-icon-alist)
+    (when (org-string-match-p (car entry) category)
+      (if (listp (cadr entry))
+         (return (cadr entry))
+      (return (apply 'create-image (cdr entry)))))))
+
+(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.
@@ -4515,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
@@ -4529,11 +5537,17 @@ Any match of REMOVE-RE will be removed from TXT."
               org-agenda-show-inherited-tags
               org-agenda-hide-tags-regexp))
     (let* ((category (or category
-                        org-category
+                        (if (stringp org-category)
+                            org-category
+                          (and org-category (symbol-name org-category)))
                         (if buffer-file-name
                             (file-name-sans-extension
                              (file-name-nondirectory buffer-file-name))
                           "")))
+          (category-icon (org-agenda-get-category-icon category))
+          (category-icon (if category-icon
+                             (propertize " " 'display category-icon)
+                           ""))
           ;; time, tag, effort are needed for the eval of the prefix format
           (tag (if tags (nth (1- (length tags)) tags) ""))
           time effort neffort
@@ -4541,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
@@ -4568,28 +5582,19 @@ 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 (string-match (org-re "\\([ \t]+\\)\\(:[[:alnum:]_@:]+:\\)[ \t]*$")
+       (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)
        ;; Tags are in the string
        (if (or (eq org-agenda-remove-tags t)
@@ -4600,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
@@ -4608,38 +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 s1 "-" s2))
-                        (s1 (concat s1 "......"))
-                        (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)
@@ -4648,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
@@ -4656,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)
@@ -4663,18 +5678,18 @@ Any match of REMOVE-RE will be removed from TXT."
 The modified list may contain inherited tags, and tags matched by
 `org-agenda-hide-tags-regexp' will be removed."
   (when (or add-inherited hide-re)
-    (if (string-match (org-re "\\([ \t]+\\)\\(:[[:alnum:]_@:]+:\\)[ \t]*$") txt)
+    (if (string-match (org-re "\\([ \t]+\\)\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$") txt)
        (setq txt (substring txt 0 (match-beginning 0))))
+    (setq tags
+         (delq nil
+               (mapcar (lambda (tg)
+                         (if (or (and hide-re (string-match hide-re tg))
+                                 (and (not add-inherited)
+                                      (get-text-property 0 'inherited tg)))
+                             nil
+                           tg))
+                       tags)))
     (when tags
-      (setq tags
-           (delq nil
-                 (mapcar (lambda (tg)
-                           (if (or (and hide-re (string-match hide-re tg))
-                                   (and (not add-inherited)
-                                        (get-text-property 0 'inherited tg)))
-                               nil
-                             tg))
-                         tags)))
       (let ((have-i (get-text-property 0 'inherited (car tags)))
            i)
        (setq txt (concat txt " :"
@@ -4719,13 +5734,23 @@ The modified list may contain inherited tags, and tags matched by
          (throw 'exit list))
       (while (setq time (pop gridtimes))
        (unless (and remove (member time have))
-         (setq time (int-to-string time))
-         (push (org-format-agenda-item
+         (setq time (replace-regexp-in-string " " "0" (format "%04s" time)))
+         (push (org-agenda-format-item
                 nil string "" nil
                 (concat (substring time 0 -2) ":" (substring time -2)))
                new)
          (put-text-property
-          1 (length (car new)) 'face 'org-time-grid (car new))))
+          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)))))
@@ -4735,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)
@@ -4744,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.]*\\)\\([ .;,:!?=|/<>]?\\)\\([ctse]\\)"
+    (while (string-match "%\\(\\?\\)?\\([-+]?[0-9.]*\\)\\([ .;,:!?=|/<>]?\\)\\([ctsei]\\|(.+)\\)"
                         s start)
-      (setq var (cdr (assoc (match-string 4 s)
-                           '(("c" . category) ("t" . time) ("s" . extra)
-                             ("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)))
@@ -4764,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))
@@ -4805,26 +5834,51 @@ HH:MM."
                    (mod h1 24) h1))
            (t0 (+ (* 100 h2) m))
            (t1 (concat (if (>= h1 24) "+" " ")
+                       (if (and org-agenda-time-leading-zero
+                                (< t0 1000)) "0" "")
                        (if (< t0 100) "0" "")
                        (if (< t0 10)  "0" "")
                        (int-to-string t0))))
        (if string (concat (substring t1 -4 -2) ":" (substring t1 -2)) t0)))))
 
+(defvar org-agenda-before-sorting-filter-function nil
+  "Function to be applied to agenda items prior to sorting.
+Prior to sorting also means just before they are inserted into the agenda.
+
+To aid sorting, you may revisit the original entries and add more text
+properties which will later be used by the sorting functions.
+
+The function should take a string argument, an agenda line.
+It has access to the text properties in that line, which contain among
+other things, the property `org-hd-marker' that points to the entry
+where the line comes from.  Note that not all lines going into the agenda
+have this property, only most.
+
+The function should return the modified string.  It is probably best
+to ONLY change text properties.
+
+You can also use this function as a filter, by returning nil for lines
+you don't want to have in the agenda at all.  For this application, you
+could bind the variable in the options section of a custom command.")
+
 (defun org-finalize-agenda-entries (list &optional nosort)
   "Sort and concatenate the agenda items."
   (setq list (mapcar 'org-agenda-highlight-todo list))
   (if nosort
       list
+    (when org-agenda-before-sorting-filter-function
+      (setq list (delq nil (mapcar org-agenda-before-sorting-filter-function list))))
     (mapconcat 'identity (sort list 'org-entries-lessp) "\n")))
 
 (defun org-agenda-highlight-todo (x)
   (let ((org-done-keywords org-done-keywords-for-agenda)
-        re pl)
+       (case-fold-search nil)
+       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)))
@@ -4832,20 +5886,31 @@ HH:MM."
              (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)
-       (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)
@@ -4857,7 +5922,7 @@ HH:MM."
          (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)))
@@ -4896,6 +5961,28 @@ HH:MM."
          ((< lb la) +1)
          (t nil))))
 
+(defsubst org-cmp-alpha (a b)
+  "Compare the headlines, alphabetically."
+  (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
+      (if (string-match (concat "\\`[ \t]*" (or (get-text-property 0 'org-todo-regexp a) "")
+                               "\\([ \t]*\\[[a-zA-Z0-9]\\]\\)? *") ta)
+         (setq ta (substring ta (match-end 0))))
+      (setq ta (downcase ta)))
+    (when plb
+      (if (string-match (concat "\\`[ \t]*" (or (get-text-property 0 'org-todo-regexp b) "")
+                               "\\([ \t]*\\[[a-zA-Z0-9]\\]\\)? *") tb)
+         (setq tb (substring tb (match-end 0))))
+      (setq tb (downcase tb)))
+    (cond ((not ta) +1)
+         ((not tb) -1)
+         ((string-lessp ta tb) -1)
+         ((string-lessp tb ta) +1)
+         (t nil))))
+
 (defsubst org-cmp-tag (a b)
   "Compare the string values of the first tags of A and B."
   (let ((ta (car (last (get-text-property 1 'tags a))))
@@ -4923,27 +6010,42 @@ HH:MM."
          ((and (not ha) hb) +1)
          (t nil))))
 
+(defsubst org-em (x y list) (or (memq x list) (memq y list)))
+
 (defun org-entries-lessp (a b)
   "Predicate for sorting agenda entries."
   ;; The following variables will be used when the form is evaluated.
   ;; So even though the compiler complains, keep them.
-  (let* ((time-up (org-cmp-time a b))
-        (time-down (if time-up (- time-up) nil))
-        (priority-up (org-cmp-priority a b))
-        (priority-down (if priority-up (- priority-up) nil))
-        (effort-up (org-cmp-effort a b))
-        (effort-down (if effort-up (- effort-up) nil))
-        (category-up (org-cmp-category a b))
-        (category-down (if category-up (- category-up) nil))
-        (category-keep (if category-up +1 nil))
-        (tag-up (org-cmp-tag a b))
-        (tag-down (if tag-up (- tag-up) nil))
-        (todo-state-up (org-cmp-todo-state a b))
+  (let* ((ss org-agenda-sorting-strategy-selected)
+        (time-up         (and (org-em 'time-up 'time-down ss)
+                              (org-cmp-time a b)))
+        (time-down       (if time-up (- time-up) nil))
+        (priority-up     (and (org-em 'priority-up 'priority-down ss)
+                              (org-cmp-priority a b)))
+        (priority-down   (if priority-up (- priority-up) nil))
+        (effort-up       (and (org-em 'effort-up 'effort-down ss)
+                              (org-cmp-effort a b)))
+        (effort-down     (if effort-up (- effort-up) nil))
+        (category-up     (and (or (org-em 'category-up 'category-down ss)
+                                  (memq 'category-keep ss))
+                              (org-cmp-category a b)))
+        (category-down   (if category-up (- category-up) nil))
+        (category-keep   (if category-up +1 nil))
+        (tag-up          (and (org-em 'tag-up 'tag-down ss)
+                              (org-cmp-tag a b)))
+        (tag-down        (if tag-up (- tag-up) nil))
+        (todo-state-up   (and (org-em 'todo-state-up 'todo-state-down ss)
+                              (org-cmp-todo-state a b)))
         (todo-state-down (if todo-state-up (- todo-state-up) nil))
-        (habit-up (org-cmp-habit-p a b))
-        (habit-down (if habit-up (- habit-up) nil))
+        (habit-up        (and (org-em 'habit-up 'habit-down ss)
+                              (org-cmp-habit-p a b)))
+        (habit-down      (if habit-up (- habit-up) nil))
+        (alpha-up        (and (org-em 'alpha-up 'alpha-down ss)
+                              (org-cmp-alpha a b)))
+        (alpha-down      (if alpha-up (- alpha-up) nil))
+        (need-user-cmp   (org-em 'user-defined-up 'user-defined-down ss))
         user-defined-up user-defined-down)
-    (if (and org-agenda-cmp-user-defined
+    (if (and need-user-cmp org-agenda-cmp-user-defined
             (functionp org-agenda-cmp-user-defined))
        (setq user-defined-up
              (funcall org-agenda-cmp-user-defined a b)
@@ -4954,12 +6056,12 @@ HH:MM."
 
 ;;; Agenda restriction lock
 
-(defvar org-agenda-restriction-lock-overlay (org-make-overlay 1 1)
+(defvar org-agenda-restriction-lock-overlay (make-overlay 1 1)
   "Overlay to mark the headline to which agenda commands are restricted.")
-(org-overlay-put org-agenda-restriction-lock-overlay
-                'face 'org-agenda-restriction-lock)
-(org-overlay-put org-agenda-restriction-lock-overlay
-                'help-echo "Agendas are currently limited to this subtree.")
+(overlay-put org-agenda-restriction-lock-overlay
+            'face 'org-agenda-restriction-lock)
+(overlay-put org-agenda-restriction-lock-overlay
+            'help-echo "Agendas are currently limited to this subtree.")
 (org-detach-overlay org-agenda-restriction-lock-overlay)
 
 (defun org-agenda-set-restriction-lock (&optional type)
@@ -4982,7 +6084,7 @@ in the file.  Otherwise, restriction will be to the current subtree."
        (put 'org-agenda-files 'org-restrict
             (list (buffer-file-name (buffer-base-buffer))))
        (org-back-to-heading t)
-       (org-move-overlay org-agenda-restriction-lock-overlay (point) (point-at-eol))
+       (move-overlay org-agenda-restriction-lock-overlay (point) (point-at-eol))
        (move-marker org-agenda-restrict-begin (point))
        (move-marker org-agenda-restrict-end
                     (save-excursion (org-end-of-subtree t)))
@@ -5071,8 +6173,9 @@ Org-mode buffers visited directly by the user will not be touched."
   (org-agenda-quit))
 
 (defun org-agenda-execute (arg)
-  "Execute another agenda command, keeping same window.\\<global-map>
-So this is just a shortcut for `\\[org-agenda]', available in the agenda."
+  "Execute another agenda command, keeping same window.
+So this is just a shortcut for \\<global-map>`\\[org-agenda]', available
+in the agenda."
   (interactive "P")
   (let ((org-agenda-window-setup 'current-window))
     (org-agenda arg)))
@@ -5082,28 +6185,46 @@ So this is just a shortcut for `\\[org-agenda]', available 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))
+        (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.
@@ -5122,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)
-        char 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))
@@ -5153,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)
@@ -5165,20 +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 '())
-       (dolist (tag org-tag-alist-for-agenda)
-         (let ((modifier (funcall org-agenda-auto-exclude-function
-                                  (car tag))))
+       (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)
@@ -5189,24 +6318,41 @@ 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."
+  (let (p tags)
+    (save-excursion
+      (goto-char (point-min))
+      (while (setq p (next-single-property-change (point) 'tags))
+       (goto-char p)
+       (mapc (lambda (x) (add-to-list 'tags x))
+             (get-text-property (point) 'tags))))
+    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)
@@ -5215,11 +6361,19 @@ 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)
   "Return the form to compare the effort of the current line with what E says.
-E looks line \"+<2:25\"."
+E looks like \"+<2:25\"."
   (let (op)
     (setq e (substring e 1))
     (setq op (string-to-char e) e (substring e 1))
@@ -5228,7 +6382,7 @@ E looks line \"+<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.
@@ -5239,67 +6393,87 @@ 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))))))
+         (beginning-of-line 2))))
+    (if (get-char-property (point) 'invisible)
+       (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 (org-make-overlay (max (point-min) (1- (point-at-bol)))
+    (setq ov (make-overlay (max (point-min) (1- (point-at-bol)))
                               (point-at-eol)))
-    (org-overlay-put ov 'invisible t)
-    (org-overlay-put ov 'type 'tags-filter)
-    (push ov org-agenda-filter-overlays)))
+    (overlay-put ov 'invisible t)
+    (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 (org-overlays-at pos))
-      (when (and (org-overlay-get ov 'invisible)
-                (eq (org-overlay-get ov 'type) 'tags-filter))
+    (dolist (ov (overlays-at pos))
+      (when (and (overlay-get ov 'invisible)
+                (eq (overlay-get ov 'type) 'tag))
        (goto-char pos)
-       (if (< (org-overlay-start ov) (point-at-eol))
-           (org-move-overlay ov (point-at-eol)
-                             (org-overlay-end ov)))))))
-
-(defun org-agenda-filter-by-tag-show-all ()
-  (mapc 'org-delete-overlay org-agenda-filter-overlays)
-  (setq org-agenda-filter-overlays nil)
-  (setq org-agenda-filter nil)
-  (setq org-agenda-filter-form nil)
+       (if (< (overlay-start ov) (point-at-eol))
+           (move-overlay ov (point-at-eol)
+                             (overlay-end ov)))))))
+
+(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 ()
   "Manipulate the query by adding a search term with positive selection.
-Positive selection means, the term must be matched for selection of an entry."
+Positive selection means the term must be matched for selection of an entry."
   (interactive)
   (org-agenda-manipulate-query ?\[))
 (defun org-agenda-manipulate-query-subtract ()
   "Manipulate the query by adding a search term with negative selection.
-Negative selection means, term must not be matched for selection of an entry."
+Negative selection means term must not be matched for selection of an entry."
   (interactive)
   (org-agenda-manipulate-query ?\]))
 (defun org-agenda-manipulate-query-add-re ()
   "Manipulate the query by adding a search regexp with positive selection.
-Positive selection means, the regexp must match for selection of an entry."
+Positive selection means the regexp must match for selection of an entry."
   (interactive)
   (org-agenda-manipulate-query ?\{))
 (defun org-agenda-manipulate-query-subtract-re ()
   "Manipulate the query by adding a search regexp with negative selection.
-Negative selection means, regexp must not match for selection of an entry."
+Negative selection means regexp must not match for selection of an entry."
   (interactive)
   (org-agenda-manipulate-query ?\}))
 (defun org-agenda-manipulate-query (char)
@@ -5311,8 +6485,10 @@ Negative selection means, regexp must not match for selection of an entry."
    ((eq org-agenda-type 'search)
     (org-add-to-string
      'org-agenda-query-string
-     (cdr (assoc char '((?\[ . " +") (?\] . " -")
-                       (?\{ . " +{}") (?\} . " -{}")))))
+     (if org-agenda-last-search-view-search-was-boolean
+        (cdr (assoc char '((?\[ . " +") (?\] . " -")
+                           (?\{ . " +{}") (?\} . " -{}"))))
+       " "))
     (setq org-agenda-redo-command
          (list 'org-search-view
                org-todo-only
@@ -5329,7 +6505,9 @@ Negative selection means, regexp must not match for selection of an entry."
 
 (defun org-agenda-goto-date (date)
   "Jump to DATE in agenda."
-  (interactive (list (org-read-date)))
+  (interactive (list (let ((org-read-date-prefer-future
+                           (eval org-agenda-jump-prefer-future)))
+                      (org-read-date))))
   (org-agenda-list nil date))
 
 (defun org-agenda-goto-today ()
@@ -5340,13 +6518,10 @@ Negative selection means, regexp must not match for selection of an entry."
     (cond
      (tdpos (goto-char tdpos))
      ((eq org-agenda-type 'agenda)
-      (let* ((sd (time-to-days
-                 (time-subtract (current-time)
-                                (list 0 (* 3600 org-extend-today-until) 0))))
-            (comp (org-agenda-compute-time-span sd org-agenda-span))
+      (let* ((sd (org-agenda-compute-starting-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) (car comp))
-       (setf (nth 2 org-agenda-overriding-arguments) (cdr comp))
+       (setf (nth 1 org-agenda-overriding-arguments) sd)
        (org-agenda-redo)
        (org-agenda-find-same-or-today-or-agenda)))
      (t (error "Cannot find today")))))
@@ -5363,28 +6538,28 @@ Negative selection means, regexp must not match for selection of an entry."
 With prefix ARG, go forward that many times the current span."
   (interactive "p")
   (org-agenda-check-type t 'agenda)
-  (let* ((span org-agenda-span)
+  (let* ((span org-agenda-current-span)
         (sd org-starting-day)
         (greg (calendar-gregorian-from-absolute sd))
         (cnt (org-get-at-bol 'org-day-cnt))
-        greg2 nd)
+        greg2)
     (cond
      ((eq span 'day)
-      (setq sd (+ arg sd) nd 1))
+      (setq sd (+ arg sd)))
      ((eq span 'week)
-      (setq sd (+ (* 7 arg) sd) nd 7))
+      (setq sd (+ (* 7 arg) sd)))
      ((eq span 'month)
       (setq greg2 (list (+ (car greg) arg) (nth 1 greg) (nth 2 greg))
            sd (calendar-absolute-from-gregorian greg2))
-      (setcar greg2 (1+ (car greg2)))
-      (setq nd (- (calendar-absolute-from-gregorian greg2) sd)))
+      (setcar greg2 (1+ (car greg2))))
      ((eq span 'year)
       (setq greg2 (list (car greg) (nth 1 greg) (+ arg (nth 2 greg)))
            sd (calendar-absolute-from-gregorian greg2))
-      (setcar (nthcdr 2 greg2) (1+ (nth 2 greg2)))
-      (setq nd (- (calendar-absolute-from-gregorian greg2) sd))))
+      (setcar (nthcdr 2 greg2) (1+ (nth 2 greg2))))
+     (t
+      (setq sd (+ (* span arg) sd))))
     (let ((org-agenda-overriding-arguments
-          (list (car org-agenda-last-arguments) sd nd t)))
+          (list (car org-agenda-last-arguments) sd span t)))
       (org-agenda-redo)
       (org-agenda-find-same-or-today-or-agenda cnt))))
 
@@ -5397,15 +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 [l]og [L]og-all [a]rch-trees [A]rch-files
-       clock[R]eport   time[G]rid   [[]inactive  [E]ntryText   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))
@@ -5413,6 +6593,7 @@ With prefix ARG, go backward that many times the current span."
       ((?E ?e) (call-interactively 'org-agenda-entry-text-mode))
       (?G (call-interactively 'org-agenda-toggle-time-grid))
       (?D (call-interactively 'org-agenda-toggle-diary))
+      (?\! (call-interactively 'org-agenda-toggle-deadlines))
       (?\[ (let ((org-agenda-include-inactive-timestamps t))
             (org-agenda-check-type t 'timeline 'agenda)
             (org-agenda-redo))
@@ -5420,11 +6601,14 @@ 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."
   (interactive "P")
-  (setq org-agenda-ndays 1)
   (org-agenda-change-time-span 'day day-of-year))
 (defun org-agenda-week-view (&optional iso-week)
   "Switch to daily view for agenda.
@@ -5434,7 +6618,6 @@ week.  Any digits before this encode a year.  So 200712 means
 week 12 of year 2007.  Years in the range 1938-2037 can also be
 written as 2-digit years."
   (interactive "P")
-  (setq org-agenda-ndays 7)
   (org-agenda-change-time-span 'week iso-week))
 (defun org-agenda-month-view (&optional month)
   "Switch to monthly view for agenda.
@@ -5459,70 +6642,62 @@ written as 2-digit years."
   "Change the agenda view to SPAN.
 SPAN may be `day', `week', `month', `year'."
   (org-agenda-check-type t 'agenda)
-  (if (and (not n) (equal org-agenda-span span))
+  (if (and (not n) (equal org-agenda-current-span span))
       (error "Viewing span is already \"%s\"" span))
   (let* ((sd (or (org-get-at-bol 'day)
                org-starting-day))
-        (computed (org-agenda-compute-time-span sd span n))
+        (sd (org-agenda-compute-starting-span sd span n))
         (org-agenda-overriding-arguments
-         (list (car org-agenda-last-arguments)
-               (car computed) (cdr computed) 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)
   (message "Switched to %s view" span))
 
-(defun org-agenda-compute-time-span (sd span &optional n)
-  "Compute starting date and number of days for agenda.
+(defun org-agenda-compute-starting-span (sd span &optional n)
+  "Compute starting date for agenda.
 SPAN may be `day', `week', `month', `year'.  The return value
 is a cons cell with the starting date and the number of days,
 so that the date SD will be in that range."
   (let* ((greg (calendar-gregorian-from-absolute sd))
         (dg (nth 1 greg))
         (mg (car greg))
-        (yg (nth 2 greg))
-        nd w1 y1 m1 thisweek)
+        (yg (nth 2 greg)))
     (cond
      ((eq span 'day)
       (when n
        (setq sd (+ (calendar-absolute-from-gregorian
                     (list mg 1 yg))
-                   n -1)))
-      (setq nd 1))
+                   n -1))))
      ((eq span 'week)
       (let* ((nt (calendar-day-of-week
                  (calendar-gregorian-from-absolute sd)))
             (d (if org-agenda-start-on-weekday
                    (- nt org-agenda-start-on-weekday)
-                 0)))
+                 0))
+            y1)
        (setq sd (- sd (+ (if (< d 0) 7 0) d)))
        (when n
          (require 'cal-iso)
-         (setq thisweek (car (calendar-iso-from-absolute sd)))
          (when (> n 99)
            (setq y1 (org-small-year-to-year (/ n 100))
                  n (mod n 100)))
          (setq sd
                (calendar-absolute-from-iso
                 (list n 1
-                      (or y1 (nth 2 (calendar-iso-from-absolute sd)))))))
-       (setq nd 7)))
+                      (or y1 (nth 2 (calendar-iso-from-absolute sd)))))))))
      ((eq span 'month)
-      (when (and n (> n 99))
-       (setq y1 (org-small-year-to-year (/ n 100))
-             n (mod n 100)))
-      (setq sd (calendar-absolute-from-gregorian
-               (list (or n mg) 1 (or y1 yg)))
-           nd (- (calendar-absolute-from-gregorian
-                  (list (1+ (or n mg)) 1 (or y1 yg)))
-                 sd)))
+      (let (y1)
+       (when (and n (> n 99))
+         (setq y1 (org-small-year-to-year (/ n 100))
+               n (mod n 100)))
+       (setq sd (calendar-absolute-from-gregorian
+                 (list (or n mg) 1 (or y1 yg))))))
      ((eq span 'year)
       (setq sd (calendar-absolute-from-gregorian
-               (list 1 1 (or n yg)))
-           nd (- (calendar-absolute-from-gregorian
-                  (list 1 1 (1+ (or n yg))))
-                 sd))))
-    (cons sd nd)))
+               (list 1 1 (or n yg))))))
+    sd))
 
 (defun org-agenda-next-date-line (&optional arg)
   "Jump to the next line indicating a date in agenda buffer."
@@ -5546,17 +6721,16 @@ so that the date SD will be in that range."
       (error "No previous date before this line in this buffer")))
 
 ;; Initialize the highlight
-(defvar org-hl (org-make-overlay 1 1))
-(org-overlay-put org-hl 'face 'highlight)
+(defvar org-hl (make-overlay 1 1))
+(overlay-put org-hl 'face 'highlight)
 
 (defun org-highlight (begin end &optional buffer)
   "Highlight a region with overlay."
-  (funcall (if (featurep 'xemacs) 'set-extent-endpoints 'move-overlay)
-          org-hl begin end (or buffer (current-buffer))))
+  (move-overlay org-hl begin end (or buffer (current-buffer))))
 
 (defun org-unhighlight ()
   "Detach overlay INDEX."
-  (funcall (if (featurep 'xemacs) 'detach-extent 'delete-overlay) org-hl))
+  (org-detach-overlay org-hl))
 
 ;; FIXME this is currently not used.
 (defun org-highlight-until-next-command (beg end &optional buffer)
@@ -5573,17 +6747,15 @@ 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")))
 
 (defun org-agenda-entry-text-mode (&optional arg)
   "Toggle entry text mode in an agenda buffer."
   (interactive "P")
-  (if (integerp arg)
-      (setq org-agenda-entry-text-mode t)
-    (setq org-agenda-entry-text-mode (not org-agenda-entry-text-mode)))
+  (setq org-agenda-entry-text-mode (or (integerp arg)
+                                       (not org-agenda-entry-text-mode)))
   (org-agenda-entry-text-hide)
   (and org-agenda-entry-text-mode
        (let ((org-agenda-entry-text-maxlines
@@ -5594,11 +6766,15 @@ so that the date SD will be in that range."
           (if org-agenda-entry-text-mode "on" "off")
           (if (integerp arg) arg org-agenda-entry-text-maxlines)))
 
-(defun org-agenda-clockreport-mode ()
-  "Toggle clocktable mode in an agenda buffer."
-  (interactive)
+(defun org-agenda-clockreport-mode (&optional with-filter)
+  "Toggle clocktable mode in an agenda buffer.
+With prefix arg WITH-FILTER, make the clocktable respect the current
+agenda filter."
+  (interactive "P")
   (org-agenda-check-type t 'agenda)
-  (setq org-agenda-clockreport-mode (not org-agenda-clockreport-mode))
+  (if with-filter
+      (setq org-agenda-clockreport-mode 'with-filter)
+    (setq org-agenda-clockreport-mode (not org-agenda-clockreport-mode)))
   (org-agenda-set-mode-name)
   (org-agenda-redo)
   (message "Clocktable mode is %s"
@@ -5612,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"
@@ -5650,6 +6829,16 @@ When called with a prefix argument, include all archive files as well."
   (message "Diary inclusion turned %s"
           (if org-agenda-include-diary "on" "off")))
 
+(defun org-agenda-toggle-deadlines ()
+  "Toggle inclusion of entries with a deadline in an agenda buffer."
+  (interactive)
+  (org-agenda-check-type t 'agenda)
+  (setq org-agenda-include-deadlines (not org-agenda-include-deadlines))
+  (org-agenda-redo)
+  (org-agenda-set-mode-name)
+  (message "Deadlines inclusion turned %s"
+          (if org-agenda-include-deadlines "on" "off")))
+
 (defun org-agenda-toggle-time-grid ()
   "Toggle time grid in an agenda buffer."
   (interactive)
@@ -5663,31 +6852,59 @@ When called with a prefix argument, include all archive files as well."
 (defun org-agenda-set-mode-name ()
   "Set the mode name to indicate all the small mode settings."
   (setq mode-name
-       (concat "Org-Agenda"
-               (if (equal org-agenda-ndays 1) " Day"    "")
-               (if (equal org-agenda-ndays 7) " Week"   "")
-               (if org-agenda-follow-mode     " Follow" "")
-               (if org-agenda-entry-text-mode " ETxt"   "")
-               (if org-agenda-include-diary   " Diary"  "")
-               (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
-                                              :preset-filter))
-                   (concat " {" (mapconcat
-                                 'identity
-                                 (append (get 'org-agenda-filter
-                                              :preset-filter)
-                                         org-agenda-filter) "") "}")
-                 "")
-               (if org-agenda-archives-mode
-                   (if (eq org-agenda-archives-mode t)
-                       " Archives"
-                     (format " :%s:" org-archive-tag))
-                 "")
-               (if org-agenda-clockreport-mode " Clock"   "")))
+       (list "Org-Agenda"
+             (if (get 'org-agenda-files 'org-restrict) " []" "")
+             " "
+             '(:eval (org-agenda-span-name org-agenda-current-span))
+             (if org-agenda-follow-mode     " Follow" "")
+             (if org-agenda-entry-text-mode " ETxt"   "")
+             (if org-agenda-include-diary   " Diary"  "")
+             (if org-agenda-include-deadlines " Ddl"  "")
+             (if org-agenda-use-time-grid   " Grid"   "")
+             (if (and (boundp 'org-habit-show-habits)
+                      org-habit-show-habits) " Habit"   "")
+             (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))
+                 '(: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)
+                     " Archives"
+                   (format " :%s:" org-archive-tag))
+               "")
+             (if org-agenda-clockreport-mode
+                 (if (eq org-agenda-clockreport-mode 'with-filter)
+                     " Clock{}" " Clock")
+               "")))
   (force-mode-line-update))
 
 (defun org-agenda-post-command-hook ()
@@ -5697,26 +6914,27 @@ When called with a prefix argument, include all archive files as well."
                               'org-agenda-type))))
 
 (defun org-agenda-next-line ()
-  "Move cursor to the next line, and show if follow-mode is active."
+  "Move cursor to the next line, and show if follow mode is active."
   (interactive)
   (call-interactively 'next-line)
   (org-agenda-do-context-action))
 
 (defun org-agenda-previous-line ()
   "Move cursor to the previous line, and show if follow-mode is active."
-
   (interactive)
   (call-interactively 'previous-line)
   (org-agenda-do-context-action))
 
 (defun org-agenda-do-context-action ()
-  "Show outline path and, maybe, follow-mode window."
+  "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.
@@ -5744,12 +6962,15 @@ and by additional input from the age of a schedules or deadline entry."
         (pos (marker-position marker)))
     (switch-to-buffer-other-window buffer)
     (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)))))
@@ -5772,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)
@@ -5824,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")
@@ -5860,7 +7081,7 @@ If this information is not given, the function uses the tree at point."
              (delete-region (point-at-bol) (1+ (point-at-eol)))))
          (beginning-of-line 0))))))
 
-(defun org-agenda-refile (&optional goto rfloc)
+(defun org-agenda-refile (&optional goto rfloc no-update)
   "Refile the item at point."
   (interactive "P")
   (if (equal goto '(16))
@@ -5871,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
@@ -5879,7 +7100,8 @@ If this information is not given, the function uses the tree at point."
            (widen)
            (goto-char marker)
            (org-remove-subtree-entries-from-agenda)
-           (org-refile goto buffer rfloc)))))))
+           (org-refile goto buffer rfloc)))))
+    (unless no-update (org-agenda-redo))))
 
 (defun org-agenda-open-link (&optional arg)
   "Follow the link in the current line, if any.
@@ -5890,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
@@ -5926,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."
@@ -6002,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)
@@ -6089,9 +7311,27 @@ docstring of `org-agenda-show-1'."
 This calls the command `org-tree-to-indirect-buffer' from the original
 Org-mode buffer.
 With numerical prefix arg ARG, go up to this level and then take that tree.
-With a C-u prefix, make a separate frame for this tree (i.e. don't use the
-dedicated frame)."
+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)))
@@ -6128,8 +7368,7 @@ the same tree node, and the headline of the tree node in the Org-mode file."
         (buffer (marker-buffer marker))
         (pos (marker-position marker))
         (hdmarker (org-get-at-bol 'org-hd-marker))
-        (todayp (equal (org-get-at-bol 'day)
-                       (time-to-days (current-time))))
+        (todayp (org-agenda-todayp (org-get-at-bol 'day)))
         (inhibit-read-only t)
         org-agenda-headline-snapshot-before-repeat newhead just-one)
     (org-with-remote-undo buffer
@@ -6182,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.
@@ -6207,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)
@@ -6238,7 +7484,7 @@ If FORCE-TAGS is non nil, the car of it returns the new tags."
   (let ((inhibit-read-only t) l c)
     (save-excursion
       (goto-char (if line (point-at-bol) (point-min)))
-      (while (re-search-forward (org-re "\\([ \t]+\\)\\(:[[:alnum:]_@:]+:\\)[ \t]*$")
+      (while (re-search-forward (org-re "\\([ \t]+\\)\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$")
                                (if line (point-at-eol) nil) t)
        (add-text-properties
         (match-beginning 2) (match-end 2)
@@ -6256,7 +7502,8 @@ If FORCE-TAGS is non nil, the car of it returns the new tags."
        (goto-char (match-beginning 1))
        (insert (org-add-props
                    (make-string (max 1 (- c (current-column))) ?\ )
-                   (text-properties-at (point)))))
+                   (plist-put (copy-sequence (text-properties-at (point)))
+                              'face nil))))
       (goto-char (point-min))
       (org-font-lock-add-tag-faces (point-max)))))
 
@@ -6304,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))
@@ -6335,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))
@@ -6358,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))
@@ -6373,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))
@@ -6436,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))
 
@@ -6523,14 +7786,15 @@ be used to request time specification in the time stamp."
       (with-current-buffer buffer
        (widen)
        (goto-char pos)
-       (if (not (org-at-timestamp-p))
+       (if (not (org-at-timestamp-p t))
            (error "Cannot find time stamp"))
-       (org-time-stamp arg))
+       (org-time-stamp arg (equal (char-after (match-beginning 0)) ?\[)))
       (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)
-  "Schedule the item at point."
+(defun org-agenda-schedule (arg &optional time)
+  "Schedule the item at point.
+ARG is passed through to `org-schedule'."
   (interactive "P")
   (org-agenda-check-type t 'agenda 'timeline 'todo 'tags 'search)
   (org-agenda-check-no-diary)
@@ -6546,12 +7810,13 @@ be used to request time specification in the time stamp."
       (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)
-  "Schedule the item at point."
+(defun org-agenda-deadline (arg &optional time)
+  "Schedule the item at point.
+ARG is passed through to `org-deadline'."
   (interactive "P")
   (org-agenda-check-type t 'agenda 'timeline 'todo 'tags 'search)
   (org-agenda-check-no-diary)
@@ -6565,7 +7830,7 @@ be used to request time specification in the time stamp."
       (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)))
 
@@ -6577,13 +7842,14 @@ m     Mark the entry at point for an agenda action
 s     Schedule the marked entry to the date at the cursor
 d     Set the deadline of the marked entry to the date at the cursor
 r     Call `org-remember' with cursor date as the default date
+c     Call `org-capture' with cursor date as the default date
 SPC   Show marked entry in other window
 TAB   Visit marked entry in other window
 
 The cursor may be at a date in the calendar, or in the Org agenda."
   (interactive)
   (let (ans)
-    (message "Select action: [m]ark | [s]chedule [d]eadline [r]emember [ ]show")
+    (message "Select action: [m]ark | [s]chedule [d]eadline [r]emember [c]apture [ ]show")
     (setq ans (read-char-exclusive))
     (cond
      ((equal ans ?m)
@@ -6604,6 +7870,8 @@ The cursor may be at a date in the calendar, or in the Org agenda."
       (org-agenda-do-action '(org-deadline nil org-overriding-default-time)))
      ((equal ans ?r)
       (org-agenda-do-action '(org-remember) t))
+     ((equal ans ?c)
+      (org-agenda-do-action '(org-capture) t))
      ((equal ans ?\ )
       (let ((cw (selected-window)))
        (org-switch-to-buffer-other-window
@@ -6655,9 +7923,9 @@ The cursor may be at a date in the calendar, or in the Org agenda."
          (setq newhead (org-get-heading)))
        (org-agenda-change-all-lines newhead hdmarker)))))
 
-(defun org-agenda-clock-out (&optional arg)
+(defun org-agenda-clock-out ()
   "Stop the currently running clock."
-  (interactive "P")
+  (interactive)
   (unless (marker-buffer org-clock-marker)
     (error "No running clock"))
   (let ((marker (make-marker)) newhead)
@@ -6682,6 +7950,23 @@ The cursor may be at a date in the calendar, or in the Org agenda."
   (org-with-remote-undo (marker-buffer org-clock-marker)
     (org-clock-cancel)))
 
+(defun org-agenda-clock-goto ()
+  "Jump to the currently clocked in task within the agenda.
+If the currently clocked in task is not listed in the agenda
+buffer, display it in another window."
+  (interactive)
+  (let (pos)
+    (mapc (lambda (o)
+           (if (eq (overlay-get o 'type) 'org-agenda-clocking)
+               (setq pos (overlay-start o))))
+         (overlays-in (point-min) (point-max)))
+    (cond (pos (goto-char pos))
+         ;; If the currently clocked entry is not in the agenda
+         ;; buffer, we visit it in another window:
+         (org-clock-current-task
+          (org-switch-to-buffer-other-window (org-clock-goto)))
+         (t (message "No running clock, use `C-c C-x C-j' to jump to the most recent one")))))
+
 (defun org-agenda-diary-entry-in-org-file ()
   "Make a diary entry in the file `org-agenda-diary-file'."
   (let (d1 d2 char (text "") dp1 dp2)
@@ -6719,6 +8004,7 @@ The cursor may be at a date in the calendar, or in the Org agenda."
      ((equal char ?j)
       (org-switch-to-buffer-other-window
        (find-file-noselect org-agenda-diary-file))
+      (require 'org-datetree)
       (org-datetree-find-date-create d1)
       (org-reveal t))
      (t (error "Invalid selection character `%c'" char)))))
@@ -6734,6 +8020,12 @@ top-level    as top-level entries at the end of the file."
          (const :tag "in a date tree" date-tree)
          (const :tag "as top level at end of file" top-level)))
 
+(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)
   "Add a diary entry with TYPE to `org-agenda-diary-file'.
 If TEXT is not empty, it will become the headline of the new entry, and
@@ -6748,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")
@@ -6757,24 +8049,33 @@ 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)
-                  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)
-      (if (eq org-agenda-insert-diary-strategy 'top-level)
-         (org-agenda-insert-diary-as-top-level text)
-       (require 'org-datetree)
-       (org-datetree-find-date-create d1)
-       (org-agenda-insert-diary-make-new-entry text))
-      (org-insert-time-stamp (org-time-from-absolute
-                             (calendar-absolute-from-gregorian d1)))
+      (let ((org-prefix-has-time t)
+           (org-agenda-time-leading-zero t)
+           fmt time time2)
+       (if org-agenda-insert-diary-extract-time
+           ;; 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-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
+                           ;; no end time given.  First space
+                           ;; separates time from date.
+                           (concat " " (car (split-string time "\\.")))
+                         nil)
+                 text (get-text-property 0 'txt fmt)))
+       (if (eq org-agenda-insert-diary-strategy 'top-level)
+           (org-agenda-insert-diary-as-top-level text)
+         (require 'org-datetree)
+         (org-datetree-find-date-create d1)
+         (org-agenda-insert-diary-make-new-entry text))
+       (org-insert-time-stamp (org-time-from-absolute
+                               (calendar-absolute-from-gregorian d1))
+                              nil nil nil nil time2))
       (end-of-line 0))
      ((eq type 'block)
       (if (> (calendar-absolute-from-gregorian d1)
@@ -6823,7 +8124,7 @@ a timestamp can be added there."
     (org-back-over-empty-lines)
     (or (looking-at "[ \t]*$")
        (progn (insert "\n") (backward-char 1)))
-    (org-insert-heading)
+    (org-insert-heading nil t)
     (org-do-demote)
     (setq col (current-column))
     (insert text "\n")
@@ -6940,9 +8241,7 @@ argument, latitude and longitude will be prompted for."
         (date (calendar-gregorian-from-absolute day))
         (calendar-move-hook nil)
         (calendar-view-holidays-initially-flag nil)
-        (calendar-view-diary-initially-flag nil)
-        (view-calendar-holidays-initially nil)
-        (view-diary-entries-initially nil))
+        (calendar-view-diary-initially-flag nil))
     (calendar)
     (calendar-goto-date date)))
 
@@ -6992,23 +8291,40 @@ This is a command that has to be installed in `calendar-mode-map'."
   (eq (get-char-property (point-at-bol) 'type)
       'org-marked-entry-overlay))
 
-(defun org-agenda-bulk-mark ()
+(defun org-agenda-bulk-mark (&optional arg)
   "Mark the entry at point for future bulk action."
-  (interactive)
-  (org-agenda-check-no-diary)
-  (let* ((m (org-get-at-bol 'org-hd-marker))
-        ov)
-    (unless (org-agenda-bulk-marked-p)
-      (unless m (error "Nothing to mark at point"))
-      (push m org-agenda-bulk-marked-entries)
-      (setq ov (org-make-overlay (point-at-bol) (+ 2 (point-at-bol))))
-      (org-overlay-display ov "> "
-                          (org-get-todo-face "TODO")
-                          'evaporate)
-      (org-overlay-put ov 'type 'org-marked-entry-overlay))
-    (beginning-of-line 2)
-    (message "%d entries marked for bulk action"
-            (length org-agenda-bulk-marked-entries))))
+  (interactive "p")
+  (dotimes (i (or arg 1))
+    (unless (org-get-at-bol 'org-agenda-diary-link)
+      (let* ((m (org-get-at-bol 'org-hd-marker))
+            ov)
+       (unless (org-agenda-bulk-marked-p)
+         (unless m (error "Nothing to mark at point"))
+         (push m org-agenda-bulk-marked-entries)
+         (setq ov (make-overlay (point-at-bol) (+ 2 (point-at-bol))))
+         (org-overlay-display ov "> "
+                              (org-get-todo-face "TODO")
+                              'evaporate)
+         (overlay-put ov 'type 'org-marked-entry-overlay))
+       (beginning-of-line 2)
+       (while (and (get-char-property (point) 'invisible) (not (eobp)))
+         (beginning-of-line 2))
+       (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."
@@ -7020,6 +8336,8 @@ This is a command that has to be installed in `calendar-mode-map'."
          (delete (org-get-at-bol 'org-hd-marker)
                  org-agenda-bulk-marked-entries)))
   (beginning-of-line 2)
+  (while (and (get-char-property (point) 'invisible) (not (eobp)))
+    (beginning-of-line 2))
   (message "%d entries marked for bulk action"
           (length org-agenda-bulk-marked-entries)))
 
@@ -7038,9 +8356,9 @@ This only removes the overlays, it does not remove the markers
 from the list in `org-agenda-bulk-marked-entries'."
   (interactive)
   (mapc (lambda (ov)
-         (and (eq (org-overlay-get ov 'type) 'org-marked-entry-overlay)
-              (org-delete-overlay ov)))
-       (org-overlays-in (or beg (point-min)) (or end (point-max)))))
+         (and (eq (overlay-get ov 'type) 'org-marked-entry-overlay)
+              (delete-overlay ov)))
+       (overlays-in (or beg (point-min)) (or end (point-max)))))
 
 (defun org-agenda-bulk-remove-all-marks ()
   "Remove all marks in the agenda buffer.
@@ -7050,14 +8368,33 @@ This will remove the markers, and the overlays."
   (setq org-agenda-bulk-marked-entries nil)
   (org-agenda-bulk-remove-overlays (point-min) (point-max)))
 
-(defun org-agenda-bulk-action ()
-  "Execute an remote-editing action on all marked entries."
-  (interactive)
-  (unless org-agenda-bulk-marked-entries
-    (error "No entries are marked"))
-  (message "Bulk: [r]efile [$]archive [A]rch->sib [t]odo [+/-]tag [s]chedule [d]eadline")
+(defun org-agenda-bulk-action (&optional arg)
+  "Execute an remote-editing action on all marked entries.
+The prefix arg is passed through to the command if possible."
+  (interactive "P")
+  ;; 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))
+        redo-at-end
         cmd rfloc state e tag pos (cnt 0) (cntskip 0))
     (cond
      ((equal action ?$)
@@ -7068,16 +8405,18 @@ This will remove the markers, and the overlays."
 
      ((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))
-      (setcar (nthcdr 3 rfloc)
-             (move-marker (make-marker) (nth 3 rfloc)
-                          (or (get-file-buffer (nth 1 rfloc))
-                              (find-buffer-visiting (nth 1 rfloc))
-                              (error "This should not happen"))))
+      (if (nth 3 rfloc)
+         (setcar (nthcdr 3 rfloc)
+                 (move-marker (make-marker) (nth 3 rfloc)
+                              (or (get-file-buffer (nth 1 rfloc))
+                                  (find-buffer-visiting (nth 1 rfloc))
+                                  (error "This should not happen")))))
 
-      (setq cmd (list 'org-agenda-refile nil (list 'quote rfloc))))
+      (setq cmd (list 'org-agenda-refile nil (list 'quote rfloc) t)
+           redo-at-end t))
 
      ((equal action ?t)
       (setq state (org-icompleting-read
@@ -7098,20 +8437,62 @@ This will remove the markers, and the overlays."
       (setq cmd `(org-agenda-set-tags ,tag ,(if (eq action ?+) ''on ''off))))
 
      ((memq action '(?s ?d))
-      (let* ((date (org-read-date
-                   nil nil nil
-                   (if (eq action ?s) "(Re)Schedule to" "Set Deadline to")))
-            (ans org-read-date-final-answer)
+      (let* ((date (unless arg
+                    (org-read-date
+                     nil nil nil
+                     (if (eq action ?s) "(Re)Schedule to" "Set Deadline to"))))
+            (ans (if arg nil org-read-date-final-answer))
             (c1 (if (eq action ?s) 'org-agenda-schedule 'org-agenda-deadline)))
        (setq cmd `(let* ((bound (fboundp 'read-string))
                          (old (and bound (symbol-function 'read-string))))
                     (unwind-protect
                         (progn
                           (fset 'read-string (lambda (&rest ignore) ,ans))
-                          (call-interactively ',c1))
+                          (eval '(,c1 arg)))
                       (if bound
                           (fset 'read-string old)
                         (fmakunbound 'read-string)))))))
+
+     ((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)))))
+                  ;; 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")))
 
     ;; Sort the markers, to make sure that parents are handled before children
@@ -7131,12 +8512,14 @@ This will remove the markers, and the overlays."
          (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))))
     (setq org-agenda-bulk-marked-entries nil)
     (org-agenda-bulk-remove-all-marks)
+    (when redo-at-end (org-agenda-redo))
     (message "Acted on %d entries%s"
             cnt
             (if (= cntskip 0)
@@ -7162,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"))
@@ -7185,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)
@@ -7196,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.
@@ -7207,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:
 
@@ -7214,15 +8601,23 @@ 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")
-  (require 'calendar)
   (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
+        ;; time and without date as argument, so it may pass wrong
+        ;; information otherwise
         (today (org-date-to-gregorian
                 (time-to-days (current-time))))
         (org-agenda-restrict nil)
@@ -7231,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)
@@ -7243,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)
@@ -7265,17 +8663,19 @@ belonging to the \"Work\" category."
 
 (defun org-agenda-todayp (date)
   "Does DATE mean today, when considering `org-extend-today-until'?"
-  (let (today h)
-    (if (listp date) (setq date (calendar-absolute-from-gregorian date)))
-    (setq today (calendar-absolute-from-gregorian (calendar-current-date)))
-    (setq h (nth 2 (decode-time (current-time))))
-    (or (and (>= h org-extend-today-until)
-            (= date today))
-       (and (< h org-extend-today-until)
-            (= date (1- today))))))
+  (let ((today (org-today))
+       (date (if (and date (listp date)) (calendar-absolute-from-gregorian date)
+               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)))
 
-;; arch-tag: 77f7565d-7c4b-44af-a2df-9f6f7070cff1
+(provide 'org-agenda)
 
 ;;; org-agenda.el ends here