Switch to recommended form of GPLv3 permissions notice.
[bpt/emacs.git] / lisp / calendar / diary-lib.el
index 61b46a2..618c06d 100644 (file)
@@ -9,10 +9,10 @@
 
 ;; This file is part of GNU Emacs.
 
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; GNU Emacs is free software: you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 3, or (at your option)
-;; any later version.
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -20,9 +20,7 @@
 ;; GNU General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 
 (require 'calendar)
 (require 'diary-loaddefs)
 
+(defgroup diary nil
+  "Emacs diary."
+  :prefix "diary-"
+  :group 'calendar)
+
 (defcustom diary-include-string "#include"
   "The string indicating inclusion of another file of diary entries.
 See the documentation for the function `diary-include-other-diary-files'."
@@ -49,25 +52,25 @@ are holidays."
 (defcustom diary-face 'diary
   "Face name to use for diary entries."
   :type 'face
-  :group 'diary)
+  :group 'calendar-faces)
 (make-obsolete-variable 'diary-face "customize the face `diary' instead."
                         "23.1")
 
 (defface diary-anniversary '((t :inherit font-lock-keyword-face))
   "Face used for anniversaries in the fancy diary display."
   :version "22.1"
-  :group 'diary)
+  :group 'calendar-faces)
 
 (defface diary-time '((t :inherit font-lock-variable-name-face))
-  "Face used for times of day in the diary."
+  "Face used for times of day in the fancy diary display."
   :version "22.1"
-  :group 'diary)
+  :group 'calendar-faces)
 
 (defface diary-button '((((type pc) (class color))
                          (:foreground "lightblue")))
-  "Default face used for buttons."
+  "Face used for buttons in the fancy diary display."
   :version "22.1"
-  :group 'diary)
+  :group 'calendar-faces)
 ;; Backward-compatibility alias. FIXME make obsolete.
 (put 'diary-button-face 'face-alias 'diary-button)
 
@@ -130,15 +133,15 @@ are: `string', `symbol', `int', `tnil',`stringtnil.'"
   :type 'function
   :group 'diary)
 
+(define-obsolete-variable-alias 'sexp-diary-entry-symbol
+  'diary-sexp-entry-symbol "23.1")
+
 (defcustom diary-sexp-entry-symbol "%%"
   "The string used to indicate a sexp diary entry in `diary-file'.
 See the documentation for the function `diary-list-sexp-entries'."
   :type 'string
   :group 'diary)
 
-(define-obsolete-variable-alias 'sexp-diary-entry-symbol
-  'diary-sexp-entry-symbol "23.1")
-
 (defcustom diary-hook nil
   "List of functions called after the display of the diary.
 Used for example by the appointment package - see `appt-activate'."
@@ -174,6 +177,9 @@ the variable `diary-list-include-blanks' non-nil."
   :set 'diary-set-maybe-redraw
   :group 'diary)
 
+(define-obsolete-variable-alias 'list-diary-entries-hook
+  'diary-list-entries-hook "23.1")
+
 (defcustom diary-list-entries-hook nil
   "List of functions called after diary file is culled for relevant entries.
 You might wish to add `diary-include-other-diary-files', in which case
@@ -191,8 +197,8 @@ lexicographic order."
   :options '(diary-include-other-diary-files diary-sort-entries)
   :group 'diary)
 
-(define-obsolete-variable-alias 'list-diary-entries-hook
-  'diary-list-entries-hook "23.1")
+(define-obsolete-variable-alias 'mark-diary-entries-hook
+  'diary-mark-entries-hook "23.1")
 
 (defcustom diary-mark-entries-hook nil
   "List of functions called after marking diary entries in the calendar.
@@ -203,8 +209,8 @@ you will probably also want to add `diary-include-other-diary-files' to
   :options '(diary-mark-included-diary-files)
   :group 'diary)
 
-(define-obsolete-variable-alias 'mark-diary-entries-hook
-  'diary-mark-entries-hook "23.1")
+(define-obsolete-variable-alias 'nongregorian-diary-listing-hook
+  'diary-nongregorian-listing-hook "23.1")
 
 (defcustom diary-nongregorian-listing-hook nil
   "List of functions called for listing diary file and included files.
@@ -219,8 +225,8 @@ describes the style of such diary entries."
              diary-islamic-list-entries)
   :group 'diary)
 
-(define-obsolete-variable-alias 'nongregorian-diary-listing-hook
-  'diary-nongregorian-listing-hook "23.1")
+(define-obsolete-variable-alias 'nongregorian-diary-marking-hook
+  'diary-nongregorian-marking-hook "23.1")
 
 (defcustom diary-nongregorian-marking-hook nil
   "List of functions called for marking diary file and included files.
@@ -235,8 +241,8 @@ describes the style of such diary entries."
              diary-islamic-mark-entries)
   :group 'diary)
 
-(define-obsolete-variable-alias 'nongregorian-diary-marking-hook
-  'diary-nongregorian-marking-hook "23.1")
+(define-obsolete-variable-alias 'print-diary-entries-hook
+  'diary-print-entries-hook "23.1")
 
 (defcustom diary-print-entries-hook 'lpr-buffer
   "Run by `diary-print-entries' after preparing a temporary diary buffer.
@@ -248,9 +254,6 @@ changing the function used to do the printing."
   :type 'hook
   :group 'diary)
 
-(define-obsolete-variable-alias 'print-diary-entries-hook
-  'diary-print-entries-hook "23.1")
-
 (defcustom diary-unknown-time -9999
   "Value returned by `diary-entry-time' when no time is found.
 The default value -9999 causes entries with no recognizable time
@@ -288,6 +291,9 @@ month, day, year), and `diary-entry' (a string)."
   :type 'sexp
   :group 'diary)
 
+(define-obsolete-variable-alias 'abbreviated-calendar-year
+  'diary-abbreviated-year-flag "23.1")
+
 (defcustom diary-abbreviated-year-flag t
   "Interpret a two-digit year DD in a diary entry as either 19DD or 20DD.
 This applies to the Gregorian, Hebrew, Islamic, and Baha'i calendars.
@@ -298,9 +304,6 @@ If this variable is nil, years must be written in full."
   :type 'boolean
   :group 'diary)
 
-(define-obsolete-variable-alias 'abbreviated-calendar-year
-  'diary-abbreviated-year-flag "23.1")
-
 (defcustom diary-outlook-formats
   '(
     ;; When: 11 October 2001 12:00-14:00 (GMT) Greenwich Mean Time : Dublin, ...
@@ -422,6 +425,9 @@ just visiting the `diary-file'), and SYMBOL's value is to be changed."
          ;; Note this assumes diary was called without prefix arg.
          (diary))))
 
+(define-obsolete-variable-alias 'number-of-diary-entries
+  'diary-number-of-entries "23.1")
+
 (defcustom diary-number-of-entries 1
   "Specifies how many days of diary entries are to be displayed initially.
 This variable affects the diary display when the command \\[diary] is used,
@@ -452,10 +458,7 @@ number of days of diary entries displayed."
   :set 'diary-set-maybe-redraw
   :group 'diary)
 
-(define-obsolete-variable-alias 'number-of-diary-entries
-  'diary-number-of-entries "23.1")
-
-;;; More user options in calendar.el.
+;;; More user options in calendar.el, holidays.el.
 
 
 (defun diary-check-diary-file ()
@@ -1325,8 +1328,7 @@ is marked.  See the documentation for the function `diary-list-sexp-entries'."
       (setq m displayed-month
             y displayed-year))
     (calendar-increment-month m y -1)
-    (setq first-date (calendar-absolute-from-gregorian (list m 1 y))
-          date (1- first-date))
+    (setq first-date (calendar-absolute-from-gregorian (list m 1 y)))
     (calendar-increment-month m y 2)
     (setq last-date
           (calendar-absolute-from-gregorian
@@ -1351,6 +1353,9 @@ is marked.  See the documentation for the function `diary-list-sexp-entries'."
           (forward-line 1))
         (if (bolp) (backward-char 1))
         (setq entry (buffer-substring-no-properties entry-start (point))))
+      (setq date (1- first-date))
+      ;; FIXME this loops over all visible dates.
+      ;; Could be optimized in many cases. Depends on whether t or * present.
       (while (<= (setq date (1+ date)) last-date)
         (when (setq mark (diary-sexp-entry
                           sexp entry
@@ -1599,12 +1604,13 @@ DAY MONTH YEAR in the European style).
     be a list of integers, `t' (meaning all values), or an integer.
 
   %%(diary-float MONTH DAYNAME N &optional DAY MARK) text
-    Entry will appear on the Nth DAYNAME of MONTH (0 being Sunday,
-    1 Monday, etc; if N is negative it counts backward from the end
-    of the month.  MONTH can be a list of months, a single month, or `t'
-    to specify all months.  Optional DAY means the Nth DAYNAME of MONTH
-    on or after/before DAY.  DAY defaults to 1 if N>0 and the last day of
-    the month if N<0.
+    Entry will appear on the Nth DAYNAME after/before MONTH DAY.
+    DAYNAME=0 means Sunday, DAYNAME=1 means Monday, and so on.
+    If N>0, use the Nth DAYNAME after MONTH DAY.
+    If N<0, use the Nth DAYNAME before MONTH DAY.
+    DAY defaults to 1 if N>0, and MONTH's last day otherwise.
+    MONTH can be a list of months, a single month, or `t' to
+    specify all months.
 
   %%(diary-block M1 D1 Y1 M2 D2 Y2 &optional MARK) text
     Entry will appear on dates between M1/D1/Y1 and M2/D2/Y2,
@@ -1628,8 +1634,9 @@ DAY MONTH YEAR in the European style).
   %%(diary-remind SEXP DAYS &optional MARKING) text
     Entry is a reminder for diary sexp SEXP.  DAYS is either a
     single number or a list of numbers indicating the number(s)
-    of days before the event that the warning(s) should occur.  If
-    the current date is (one of) DAYS before the event indicated
+    of days before the event that the warning(s) should occur.
+    A negative number -DAYS has the same meaning as a list (1 2 ... DAYS).
+    If the current date is (one of) DAYS before the event indicated
     by EXPR, then a suitable message (as specified by
     `diary-remind-message') appears.  In addition to the
     reminders beforehand, the diary entry also appears on the
@@ -1785,12 +1792,12 @@ use when highlighting the day in the calendar."
 
 ;; To be called from diary-sexp-entry, where DATE, ENTRY are bound.
 (defun diary-float (month dayname n &optional day mark)
-  "Floating diary entry--entry applies if date is the nth dayname of month.
-Parameters are MONTH, DAYNAME, N.  MONTH can be a list of months, an integer,
-or `t' (meaning all months).  If N is negative, count backward from the end
-of the month.
-
-An optional parameter DAY means the Nth DAYNAME on or after/before MONTH DAY.
+  "Diary entry for the Nth DAYNAME after/before MONTH DAY.
+DAYNAME=0 means Sunday, DAYNAME=1 means Monday, and so on.
+If N>0, use the Nth DAYNAME after MONTH DAY.
+If N<0, use the Nth DAYNAME before MONTH DAY.
+DAY defaults to 1 if N>0, and MONTH's last day otherwise.
+MONTH can be a list of months, an integer, or `t' (meaning all months).
 Optional MARK specifies a face or single-character string to use when
 highlighting the day in the calendar."
   ;; This is messy because the diary entry may apply, but the date on which it
@@ -1908,22 +1915,28 @@ string to use when highlighting the day in the calendar."
 
 (defun diary-remind (sexp days &optional marking)
   "Provide a reminder of a diary entry.
-SEXP is a diary-sexp.  DAYS is either a single number or a list of numbers
-indicating the number(s) of days before the event that the warning(s) should
-occur on.  If the current date is (one of) DAYS before the event indicated by
-SEXP, then a suitable message (as specified by `diary-remind-message' is
-returned.
-
-In addition to the reminders beforehand, the diary entry also appears on the
-date itself.
-
-A `diary-nonmarking-symbol' at the beginning of the line of the `diary-remind'
-entry specifies that the diary entry (not the reminder) is non-marking.
-Marking of reminders is independent of whether the entry itself is a marking
-or nonmarking; if optional parameter MARKING is non-nil then the reminders are
-marked on the calendar."
-  (let ((diary-entry (eval sexp))
-        date)
+SEXP is a diary-sexp.  DAYS is either a single number or a list
+of numbers indicating the number(s) of days before the event that
+the warning(s) should occur on.  A negative number -DAYS has the
+same meaning as a list (1 2 ... DAYS).  If the current date
+is (one of) DAYS before the event indicated by SEXP, then this function
+returns a suitable message (as specified by `diary-remind-message').
+
+In addition to the reminders beforehand, the diary entry also
+appears on the date itself.
+
+A `diary-nonmarking-symbol' at the beginning of the line of the
+`diary-remind' entry specifies that the diary entry (not the
+reminder) is non-marking.  Marking of reminders is independent of
+whether the entry itself is a marking or nonmarking; if optional
+parameter MARKING is non-nil then the reminders are marked on the
+calendar."
+  ;; `date' has a value at this point, from diary-sexp-entry.
+  ;; Convert a negative number to a list of days.
+  (and (integerp days)
+       (< days 0)
+       (setq days (number-sequence 1 (- days))))
+  (let ((diary-entry (eval sexp)))
     (cond
      ;; Diary entry applies on date.
      ((and diary-entry
@@ -1933,12 +1946,13 @@ marked on the calendar."
      ((and (integerp days)
            (not diary-entry)      ; diary entry does not apply to date
            (or (not diary-marking-entries-flag) marking))
-      (setq date (calendar-gregorian-from-absolute
-                  (+ (calendar-absolute-from-gregorian date) days)))
-      (when (setq diary-entry (eval sexp)) ; re-evaluate with adjusted date
-        ;; Discard any mark portion from diary-anniversary, etc.
-        (if (consp diary-entry) (setq diary-entry (cdr diary-entry)))
-        (mapconcat 'eval diary-remind-message "")))
+      ;; Adjust date, and re-evaluate.
+      (let ((date (calendar-gregorian-from-absolute
+                   (+ (calendar-absolute-from-gregorian date) days))))
+        (when (setq diary-entry (eval sexp))
+          ;; Discard any mark portion from diary-anniversary, etc.
+          (if (consp diary-entry) (setq diary-entry (cdr diary-entry)))
+          (mapconcat 'eval diary-remind-message ""))))
      ;; Diary entry may apply to one of a list of days before date.
      ((and (listp days) days)
       (or (diary-remind sexp (car days) marking)
@@ -2287,6 +2301,9 @@ and return a font-lock pattern matching array of MONTHS and marking SYMBOL."
    "\\(: .*\\)?")
   "Regular expression matching a date header in Fancy Diary.")
 
+(define-obsolete-variable-alias 'fancy-diary-font-lock-keywords
+  'diary-fancy-font-lock-keywords "23.1")
+
 (defvar diary-fancy-font-lock-keywords
   (list
    (list
@@ -2304,9 +2321,6 @@ and return a font-lock pattern matching array of MONTHS and marking SYMBOL."
               diary-time-regexp) . 'diary-time))
   "Keywords to highlight in fancy diary display.")
 
-(define-obsolete-variable-alias 'fancy-diary-font-lock-keywords
-  'diary-fancy-font-lock-keywords "23.1")
-
 ;; If region looks like it might start or end in the middle of a
 ;; multiline pattern, extend the region to encompass the whole pattern.
 (defun diary-fancy-font-lock-fontify-region-function (beg end &optional verbose)