(Commentary): No longer maintained by original author, bug reports as
[bpt/emacs.git] / lisp / calendar / calendar.el
index cdae40a..03f9a95 100644 (file)
@@ -1,9 +1,10 @@
 ;;; calendar.el --- calendar functions
 
 ;; Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1997,
-;;     2000, 2001 Free Software Foundation, Inc.
+;;   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007  Free Software Foundation, Inc.
 
 ;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
+;; Maintainer: Glenn Morris <rgm@gnu.org>
 ;; Keywords: calendar
 ;; Human-Keywords: calendar, Gregorian calendar, diary, holidays
 
 
 ;; 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., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Commentary:
 
-;; This collection of functions implements a calendar window.  It generates a
-;; calendar for the current month, together with the previous and coming
-;; months, or for any other three-month period.  The calendar can be scrolled
-;; forward and backward in the window to show months in the past or future;
-;; the cursor can move forward and backward by days, weeks, or months, making
-;; it possible, for instance, to jump to the date a specified number of days,
-;; weeks, or months from the date under the cursor.  The user can display a
-;; list of holidays and other notable days for the period shown; the notable
-;; days can be marked on the calendar, if desired.  The user can also specify
-;; that dates having corresponding diary entries (in a file that the user
-;; specifies) be marked; the diary entries for any date can be viewed in a
-;; separate window.  The diary and the notable days can be viewed
-;; independently of the calendar.  Dates can be translated from the (usual)
-;; Gregorian calendar to the day of the year/days remaining in year, to the
-;; ISO commercial calendar, to the Julian (old style) calendar, to the Hebrew
-;; calendar, to the Islamic calendar, to the French Revolutionary calendar, to
-;; the Mayan calendar, to the Chinese calendar, to the Coptic calendar, to the
-;; Ethiopic calendar, and to the astronomical (Julian) day number.  When
-;; floating point is available, times of sunrise/sunset can be displayed, as
-;; can the phases of the moon.  Appointment notification for diary entries is
+;; This collection of functions implements a calendar window.  It
+;; generates a calendar for the current month, together with the
+;; previous and coming months, or for any other three-month period.
+;; The calendar can be scrolled forward and backward in the window to
+;; show months in the past or future; the cursor can move forward and
+;; backward by days, weeks, or months, making it possible, for
+;; instance, to jump to the date a specified number of days, weeks, or
+;; months from the date under the cursor.  The user can display a list
+;; of holidays and other notable days for the period shown; the
+;; notable days can be marked on the calendar, if desired.  The user
+;; can also specify that dates having corresponding diary entries (in
+;; a file that the user specifies) be marked; the diary entries for
+;; any date can be viewed in a separate window.  The diary and the
+;; notable days can be viewed independently of the calendar.  Dates
+;; can be translated from the (usual) Gregorian calendar to the day of
+;; the year/days remaining in year, to the ISO commercial calendar, to
+;; the Julian (old style) calendar, to the Hebrew calendar, to the
+;; Islamic calendar, to the Baha'i calendar, to the French
+;; Revolutionary calendar, to the Mayan calendar, to the Chinese
+;; calendar, to the Coptic calendar, to the Ethiopic calendar, and to
+;; the astronomical (Julian) day number.  When floating point is
+;; available, times of sunrise/sunset can be displayed, as can the
+;; phases of the moon.  Appointment notification for diary entries is
 ;; available.  Calendar printing via LaTeX is available.
 
 ;; The following files are part of the calendar/diary code:
 ;;       appt.el                       Appointment notification
 ;;       cal-china.el                  Chinese calendar
 ;;       cal-coptic.el                 Coptic/Ethiopic calendars
-;;       cal-dst.el                    Daylight savings time rules
+;;       cal-dst.el                    Daylight saving time rules
 ;;       cal-hebrew.el                 Hebrew calendar
 ;;       cal-islam.el                  Islamic calendar
+;;       cal-bahai.el                  Baha'i calendar
 ;;       cal-iso.el                    ISO calendar
 ;;       cal-julian.el                 Julian/astronomical calendars
 ;;       cal-mayan.el                  Mayan calendars
 ;;       solar.el                      Sunrise/sunset, equinoxes/solstices
 
 ;; Technical details of all the calendrical calculations can be found in
-;; ``Calendrical Calculations'' by Nachum Dershowitz and Edward M. Reingold,
-;; Cambridge University Press (1997).
+;; ``Calendrical Calculations: The Millennium Edition'' by Edward M. Reingold
+;; and Nachum Dershowitz, Cambridge University Press (2001).
 
 ;; An earlier version of the technical details appeared in
 ;; ``Calendrical Calculations'' by Nachum Dershowitz and Edward M. Reingold,
 ;; Software--Practice and Experience, Volume 20, Number 9 (September, 1990),
-;; pages 899-928 ``Calendrical Calculations, Part II: Three Historical
+;; pages 899-928, and in ``Calendrical Calculations, Part II: Three Historical
 ;; Calendars'' by E. M. Reingold,  N. Dershowitz, and S. M. Clamen,
 ;; Software--Practice and Experience, Volume 23, Number 4 (April, 1993),
 ;; pages 383-404.
 ;; reingold@cs.uiuc.edu with the SUBJECT "send-paper-cal" (no quotes) and
 ;; the message BODY containing your mailing address (snail).
 
-;; Comments, corrections, and improvements should be sent to
-;;  Edward M. Reingold               Department of Computer Science
-;;  (217) 333-6733                   University of Illinois at Urbana-Champaign
-;;  reingold@cs.uiuc.edu             1304 West Springfield Avenue
-;;                                   Urbana, Illinois 61801
-
 ;;; Code:
 
-(eval-when-compile
-  (defvar displayed-month)
-  (defvar displayed-year)
-  (defvar calendar-month-name-array)
-  (defvar calendar-starred-day))
+(defvar displayed-month)
+(defvar displayed-year)
+(defvar calendar-month-name-array)
+(defvar calendar-starred-day)
 
 (defun calendar-version ()
   (interactive)
   :group 'calendar)
 
 
-;;;###autoload
-(defcustom calendar-week-start-day 0
-  "*The day of the week on which a week in the calendar begins.
-0 means Sunday (default), 1 means Monday, and so on."
-  :type 'integer
-  :group 'calendar)
+(defconst calendar-buffer "*Calendar*"
+  "Name of the buffer used for the calendar.")
 
 ;;;###autoload
 (defcustom calendar-offset 0
-  "*The offset of the principal month from the center of the calendar window.
+  "The offset of the principal month from the center of the calendar window.
 0 means the principal month is in the center (default), -1 means on the left,
 +1 means on the right.  Larger (or smaller) values push the principal month off
 the screen."
@@ -154,75 +148,54 @@ the screen."
 
 ;;;###autoload
 (defcustom view-diary-entries-initially nil
-  "*Non-nil means display current date's diary entries on entry.
+  "Non-nil means display current date's diary entries on entry to calendar.
 The diary is displayed in another window when the calendar is first displayed,
 if the current date is visible.  The number of days of diary entries displayed
-is governed by the variable `number-of-diary-entries'."
+is governed by the variable `number-of-diary-entries'.  This variable can
+be overridden by the value of `calendar-setup'."
   :type 'boolean
   :group 'diary)
 
-;;;###autoload
-(defcustom number-of-diary-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,
-or if the value of the variable `view-diary-entries-initially' is t.  For
-example, if the default value 1 is used, then only the current day's diary
-entries will be displayed.  If the value 2 is used, then both the current
-day's and the next day's entries will be displayed.
-
-The value can also be a vector such as [0 2 2 2 2 4 1]; this value
-says to display no diary entries on Sunday, the display the entries
-for the current date and the day after on Monday through Thursday,
-display Friday through Monday's entries on Friday, and display only
-Saturday's entries on Saturday.
-
-This variable does not affect the diary display with the `d' command
-from the calendar; in that case, the prefix argument controls the
-number of days of diary entries displayed."
-  :type '(choice (integer :tag "Entries")
-                (vector :value [0 0 0 0 0 0 0]
-                        (integer :tag "Sunday")
-                        (integer :tag "Monday")
-                        (integer :tag "Tuesday")
-                        (integer :tag "Wednesday")
-                        (integer :tag "Thursday")
-                        (integer :tag "Friday")
-                        (integer :tag "Saturday")))
-  :group 'diary)
-
 ;;;###autoload
 (defcustom mark-diary-entries-in-calendar nil
-  "*Non-nil means mark dates with diary entries, in the calendar window.
+  "Non-nil means mark dates with diary entries, in the calendar window.
 The marking symbol is specified by the variable `diary-entry-marker'."
   :type 'boolean
   :group 'diary)
 
 ;;;###autoload
 (defcustom calendar-remove-frame-by-deleting nil
-  "*Determine how the calendar mode removes a frame no longer needed.
+  "Determine how the calendar mode removes a frame no longer needed.
 If nil, make an icon of the frame.  If non-nil, delete the frame."
   :type 'boolean
   :group 'view)
 
-(add-to-list 'facemenu-unlisted-faces 'diary-face)
-(defface diary-face
-  '((((class color) (background light))
+(defvar diary-face 'diary
+  "Face name to use for diary entries.")
+(defface diary
+  '((((min-colors 88) (class color) (background light))
+     :foreground "red1")
+    (((class color) (background light))
      :foreground "red")
+    (((min-colors 88) (class color) (background dark))
+     :foreground "yellow1")
     (((class color) (background dark))
      :foreground "yellow")
     (t
      :weight bold))
   "Face for highlighting diary entries."
   :group 'diary)
+;; backward-compatibility alias
+(put 'diary-face 'face-alias 'diary)
 
-(add-to-list 'facemenu-unlisted-faces 'calendar-today-face)
-(defface calendar-today-face
+(defface calendar-today
   '((t (:underline t)))
   "Face for indicating today's date."
   :group 'diary)
+;; backward-compatibility alias
+(put 'calendar-today-face 'face-alias 'calendar-today)
 
-(add-to-list 'facemenu-unlisted-faces 'holiday-face)
-(defface holiday-face
+(defface holiday
   '((((class color) (background light))
      :background "pink")
     (((class color) (background dark))
@@ -231,12 +204,14 @@ If nil, make an icon of the frame.  If non-nil, delete the frame."
      :inverse-video t))
   "Face for indicating dates that have holidays."
   :group 'diary)
+;; backward-compatibility alias
+(put 'holiday-face 'face-alias 'holiday)
 
 (defcustom diary-entry-marker
   (if (not (display-color-p))
       "+"
-    'diary-face)
-  "*How to mark dates that have diary entries.
+    'diary)
+  "How to mark dates that have diary entries.
 The value can be either a single-character string or a face."
   :type '(choice string face)
   :group 'diary)
@@ -244,8 +219,8 @@ The value can be either a single-character string or a face."
 (defcustom calendar-today-marker
   (if (not (display-color-p))
       "="
-    'calendar-today-face)
-  "*How to mark today's date in the calendar.
+    'calendar-today)
+  "How to mark today's date in the calendar.
 The value can be either a single-character string or a face.
 Marking today's date is done only if you set up `today-visible-calendar-hook'
 to request that."
@@ -255,15 +230,15 @@ to request that."
 (defcustom calendar-holiday-marker
   (if (not (display-color-p))
       "*"
-    'holiday-face)
-  "*How to mark notable dates in the calendar.
+    'holiday)
+  "How to mark notable dates in the calendar.
 The value can be either a single-character string or a face."
   :type '(choice string face)
   :group 'calendar)
 
 ;;;###autoload
 (defcustom view-calendar-holidays-initially nil
-  "*Non-nil means display holidays for current three month period on entry.
+  "Non-nil means display holidays for current three month period on entry.
 The holidays are displayed in another window when the calendar is first
 displayed."
   :type 'boolean
@@ -271,14 +246,14 @@ displayed."
 
 ;;;###autoload
 (defcustom mark-holidays-in-calendar nil
-  "*Non-nil means mark dates of holidays in the calendar window.
+  "Non-nil means mark dates of holidays in the calendar window.
 The marking symbol is specified by the variable `calendar-holiday-marker'."
   :type 'boolean
   :group 'holidays)
 
 ;;;###autoload
 (defcustom all-hebrew-calendar-holidays nil
-  "*If nil, show only major holidays from the Hebrew calendar.
+  "If nil, show only major holidays from the Hebrew calendar.
 This means only those Jewish holidays that appear on secular calendars.
 
 If t, show all the holidays that would appear in a complete Hebrew calendar."
@@ -287,7 +262,7 @@ If t, show all the holidays that would appear in a complete Hebrew calendar."
 
 ;;;###autoload
 (defcustom all-christian-calendar-holidays nil
-  "*If nil, show only major holidays from the Christian calendar.
+  "If nil, show only major holidays from the Christian calendar.
 This means only those Christian holidays that appear on secular calendars.
 
 If t, show all the holidays that would appear in a complete Christian
@@ -297,7 +272,7 @@ calendar."
 
 ;;;###autoload
 (defcustom all-islamic-calendar-holidays nil
-  "*If nil, show only major holidays from the Islamic calendar.
+  "If nil, show only major holidays from the Islamic calendar.
 This means only those Islamic holidays that appear on secular calendars.
 
 If t, show all the holidays that would appear in a complete Islamic
@@ -305,16 +280,36 @@ calendar."
   :type 'boolean
   :group 'holidays)
 
+(defcustom diary-file-name-prefix-function (function (lambda (str) str))
+  "The function that will take a diary file name and return the desired prefix."
+  :type 'function
+  :group 'diary)
+
+;;;###autoload
+(defcustom all-bahai-calendar-holidays nil
+  "If nil, show only major holidays from the Baha'i calendar.
+These are the days on which work and school must be suspended.
+
+If t, show all the holidays that would appear in a complete Baha'i
+calendar."
+  :type 'boolean
+  :group 'holidays)
+
+(defcustom calendar-mode-hook nil
+  "Hook run when entering `calendar-mode'."
+  :type 'hook
+  :group 'calendar-hooks)
+
 ;;;###autoload
 (defcustom calendar-load-hook nil
-  "*List of functions to be called after the calendar is first loaded.
+  "List of functions to be called after the calendar is first loaded.
 This is the place to add key bindings to `calendar-mode-map'."
   :type 'hook
   :group 'calendar-hooks)
 
 ;;;###autoload
 (defcustom initial-calendar-window-hook nil
-  "*List of functions to be called when the calendar window is first opened.
+  "List of functions to be called when the calendar window is first opened.
 The functions invoked are called after the calendar window is opened, but
 once opened is never called again.  Leaving the calendar with the `q' command
 and reentering it will cause these functions to be called again."
@@ -323,7 +318,7 @@ and reentering it will cause these functions to be called again."
 
 ;;;###autoload
 (defcustom today-visible-calendar-hook nil
-  "*List of functions called whenever the current date is visible.
+  "List of functions called whenever the current date is visible.
 This can be used, for example, to replace today's date with asterisks; a
 function `calendar-star-date' is included for this purpose:
     (setq today-visible-calendar-hook 'calendar-star-date)
@@ -343,7 +338,7 @@ functions that move by days and weeks."
 
 ;;;###autoload
 (defcustom today-invisible-calendar-hook nil
-  "*List of functions called whenever the current date is not visible.
+  "List of functions called whenever the current date is not visible.
 
 The corresponding variable `today-visible-calendar-hook' is the list of
 functions called when the calendar function was called when the current
@@ -357,11 +352,11 @@ functions that move by days and weeks."
 
 ;;;###autoload
 (defcustom calendar-move-hook nil
-  "*List of functions called whenever the cursor moves in the calendar.
+  "List of functions called whenever the cursor moves in the calendar.
 
 For example,
 
-  (add-hook 'calendar-move-hook (lambda () (view-diary-entries 1)))
+  (add-hook 'calendar-move-hook (lambda () (diary-view-entries 1)))
 
 redisplays the diary for whatever date the cursor is moved to."
   :type 'hook
@@ -369,9 +364,10 @@ redisplays the diary for whatever date the cursor is moved to."
 
 ;;;###autoload
 (defcustom diary-file "~/diary"
-  "*Name of the file in which one's personal diary of dates is kept.
+  "Name of the file in which one's personal diary of dates is kept.
 
-The file's entries are lines in any of the forms
+The file's entries are lines beginning with any of the forms
+specified by the variable `american-date-diary-pattern', by default:
 
             MONTH/DAY
             MONTH/DAY/YEAR
@@ -379,19 +375,24 @@ The file's entries are lines in any of the forms
             MONTHNAME DAY, YEAR
             DAYNAME
 
-at the beginning of the line; the remainder of the line is the diary entry
-string for that date.  MONTH and DAY are one or two digit numbers, YEAR is
-a number and may be written in full or abbreviated to the final two digits.
-If the date does not contain a year, it is generic and applies to any year.
-DAYNAME entries apply to any date on which is on that day of the week.
-MONTHNAME and DAYNAME can be spelled in full, abbreviated to three
-characters (with or without a period), capitalized or not.  Any of DAY,
-MONTH, or MONTHNAME, YEAR can be `*' which matches any day, month, or year,
-respectively.
-
-The European style (in which the day precedes the month) can be used
-instead, if you execute `european-calendar' when in the calendar, or set
-`european-calendar-style' to t in your .emacs file.  The European forms are
+with the remainder of the line being the diary entry string for
+that date.  MONTH and DAY are one or two digit numbers, YEAR is a
+number and may be written in full or abbreviated to the final two
+digits (if `abbreviated-calendar-year' is non-nil).  MONTHNAME
+and DAYNAME can be spelled in full (as specified by the variables
+`calendar-month-name-array' and `calendar-day-name-array'),
+abbreviated (as specified by `calendar-month-abbrev-array' and
+`calendar-day-abbrev-array') with or without a period,
+capitalized or not.  Any of DAY, MONTH, or MONTHNAME, YEAR can be
+`*' which matches any day, month, or year, respectively. If the
+date does not contain a year, it is generic and applies to any
+year.  A DAYNAME entry applies to the appropriate day of the week
+in every week.
+
+The European style (in which the day precedes the month) can be
+used instead, if you execute `european-calendar' when in the
+calendar, or set `european-calendar-style' to t in your .emacs
+file.  The European forms (see `european-date-diary-pattern') are
 
             DAY/MONTH
             DAY/MONTH/YEAR
@@ -446,21 +447,23 @@ Diary entries can be based on Lisp sexps.  For example, the diary entry
 
       %%(diary-block 11 1 1990 11 10 1990) Vacation
 
-causes the diary entry \"Vacation\" to appear from November 1 through November
-10, 1990.  Other functions available are `diary-float', `diary-anniversary',
-`diary-cyclic', `diary-day-of-year', `diary-iso-date', `diary-french-date',
-`diary-hebrew-date', `diary-islamic-date', `diary-mayan-date',
+causes the diary entry \"Vacation\" to appear from November 1 through
+November 10, 1990.  Other functions available are `diary-float',
+`diary-anniversary', `diary-cyclic', `diary-day-of-year',
+`diary-iso-date', `diary-french-date', `diary-hebrew-date',
+`diary-islamic-date', `diary-bahai-date', `diary-mayan-date',
 `diary-chinese-date', `diary-coptic-date', `diary-ethiopic-date',
 `diary-persian-date', `diary-yahrzeit', `diary-sunrise-sunset',
-`diary-phases-of-moon', `diary-parasha', `diary-omer', `diary-rosh-hodesh',
-and `diary-sabbath-candles'.  See the documentation for the function
-`list-sexp-diary-entries' for more details.
+`diary-phases-of-moon', `diary-parasha', `diary-omer',
+`diary-rosh-hodesh', and `diary-sabbath-candles'.  See the
+documentation for the function `list-sexp-diary-entries' for more
+details.
 
-Diary entries based on the Hebrew and/or the Islamic calendar are also
-possible, but because these are somewhat slow, they are ignored
-unless you set the `nongregorian-diary-listing-hook' and the
-`nongregorian-diary-marking-hook' appropriately.  See the documentation
-for these functions for details.
+Diary entries based on the Hebrew, the Islamic and/or the Baha'i
+calendar are also possible, but because these are somewhat slow, they
+are ignored unless you set the `nongregorian-diary-listing-hook' and
+the `nongregorian-diary-marking-hook' appropriately.  See the
+documentation for these functions for details.
 
 Diary files can contain directives to include the contents of other files; for
 details, see the documentation for the variable `list-diary-entries-hook'."
@@ -469,49 +472,92 @@ details, see the documentation for the variable `list-diary-entries-hook'."
 
 ;;;###autoload
 (defcustom diary-nonmarking-symbol "&"
-  "*Symbol indicating that a diary entry is not to be marked in the calendar."
+  "Symbol indicating that a diary entry is not to be marked in the calendar."
   :type 'string
   :group 'diary)
 
 ;;;###autoload
 (defcustom hebrew-diary-entry-symbol "H"
-  "*Symbol indicating a diary entry according to the Hebrew calendar."
+  "Symbol indicating a diary entry according to the Hebrew calendar."
   :type 'string
   :group 'diary)
 
 ;;;###autoload
 (defcustom islamic-diary-entry-symbol "I"
-  "*Symbol indicating a diary entry according to the Islamic calendar."
+  "Symbol indicating a diary entry according to the Islamic calendar."
+  :type 'string
+  :group 'diary)
+
+;;;###autoload
+(defcustom bahai-diary-entry-symbol "B"
+  "Symbol indicating a diary entry according to the Baha'i calendar."
   :type 'string
   :group 'diary)
 
 ;;;###autoload
 (defcustom diary-include-string "#include"
-  "*The string indicating inclusion of another file of diary entries.
+  "The string indicating inclusion of another file of diary entries.
 See the documentation for the function `include-other-diary-files'."
   :type 'string
   :group 'diary)
 
+(defcustom diary-glob-file-regexp-prefix "^\\#"
+  "The regular expression that gets pre-pended to each of the attribute-regexp's for file-wide specifiers."
+  :type 'regexp
+  :group 'diary)
+
+(defcustom diary-face-attrs
+  '((" *\\[foreground:\\([-a-z]+\\)\\]$" 1 :foreground string)
+    (" *\\[background:\\([-a-z]+\\)\\]$" 1 :background string)
+    (" *\\[width:\\([-a-z]+\\)\\]$" 1 :width symbol)
+    (" *\\[height:\\([-0-9a-z]+\\)\\]$" 1 :height int)
+    (" *\\[weight:\\([-a-z]+\\)\\]$" 1 :weight symbol)
+    (" *\\[slant:\\([-a-z]+\\)\\]$" 1 :slant symbol)
+    (" *\\[underline:\\([-a-z]+\\)\\]$" 1 :underline stringtnil)
+    (" *\\[overline:\\([-a-z]+\\)\\]$" 1 :overline stringtnil)
+    (" *\\[strike-through:\\([-a-z]+\\)\\]$" 1 :strike-through stringtnil)
+    (" *\\[inverse-video:\\([-a-z]+\\)\\]$" 1 :inverse-video tnil)
+    (" *\\[face:\\([-0-9a-z]+\\)\\]$" 1 :face string)
+    (" *\\[font:\\([-a-z0-9]+\\)\\]$" 1 :font string)
+    ;; Unsupported.
+;;;    (" *\\[box:\\([-a-z]+\\)\\]$" 1 :box)
+;;;    (" *\\[stipple:\\([-a-z]+\\)\\]$" 1 :stipple)
+    )
+  "A list of (regexp regnum attr attrtype) lists where the
+regexp says how to find the tag, the regnum says which
+parenthetical sub-regexp this regexp looks for, and the attr says
+which attribute of the face (or that this _is_ a face) is being
+modified."
+  :type 'sexp
+  :group 'diary)
+
+(defcustom diary-file-name-prefix nil
+  "If non-nil each diary entry is prefixed with the name of the file where it is defined."
+  :type 'boolean
+  :group 'diary)
+
 ;;;###autoload
 (defcustom sexp-diary-entry-symbol "%%"
-  "*The string used to indicate a sexp diary entry in `diary-file'.
+  "The string used to indicate a sexp diary entry in `diary-file'.
 See the documentation for the function `list-sexp-diary-entries'."
   :type 'string
   :group 'diary)
 
 ;;;###autoload
 (defcustom abbreviated-calendar-year t
-  "*Interpret a two-digit year DD in a diary entry as either 19DD or 20DD.
-For the Gregorian calendar; similarly for the Hebrew and Islamic calendars.
-If this variable is nil, years must be written in full."
+  "Interpret a two-digit year DD in a diary entry as either 19DD or 20DD.
+For the Gregorian calendar; similarly for the Hebrew, Islamic and
+Baha'i calendars.  If this variable is nil, years must be written in
+full."
   :type 'boolean
   :group 'diary)
 
 ;;;###autoload
 (defcustom european-calendar-style nil
-  "*Use the European style of dates in the diary and in any displays.
+  "Use the European style of dates in the diary and in any displays.
 If this variable is t, a date 1/2/1990 would be interpreted as February 1,
-1990.  The accepted European date styles are
+1990.  The default European date styles (see `european-date-diary-pattern')
+are
 
             DAY/MONTH
             DAY/MONTH/YEAR
@@ -519,9 +565,22 @@ If this variable is t, a date 1/2/1990 would be interpreted as February 1,
             DAY MONTHNAME YEAR
             DAYNAME
 
-Names can be capitalized or not, written in full, or abbreviated to three
-characters with or without a period."
+Names can be capitalized or not, written in full (as specified by the
+variable `calendar-day-name-array'), or abbreviated (as specified by
+`calendar-day-abbrev-array') with or without a period.
+
+Setting this variable directly does not take effect (if the
+calendar package is already loaded).  Rather, use either
+\\[customize] or the functions `european-calendar' and
+`american-calendar'."
   :type 'boolean
+  ;; Without :initialize (require 'calendar) throws an error because
+  ;; american-calendar is undefined at this point.
+  :initialize 'custom-initialize-default
+  :set (lambda (symbol value)
+         (if value
+             (european-calendar)
+           (american-calendar)))
   :group 'diary)
 
 ;;;###autoload
@@ -531,7 +590,7 @@ characters with or without a period."
     (monthname " *" day "[^,0-9]")
     (monthname " *" day ", *" year "[^0-9]")
     (dayname "\\W"))
-  "*List of pseudo-patterns describing the American patterns of date used.
+  "List of pseudo-patterns describing the American patterns of date used.
 See the documentation of `diary-date-forms' for an explanation."
   :type '(repeat (choice (cons :tag "Backup"
                               :value (backup . nil)
@@ -551,7 +610,7 @@ See the documentation of `diary-date-forms' for an explanation."
     (backup day " *" monthname "\\W+\\<\\([^*0-9]\\|\\([0-9]+[:aApP]\\)\\)")
     (day " *" monthname " *" year "[^0-9]")
     (dayname "\\W"))
-  "*List of pseudo-patterns describing the European patterns of date used.
+  "List of pseudo-patterns describing the European patterns of date used.
 See the documentation of `diary-date-forms' for an explanation."
   :type '(repeat (choice (cons :tag "Backup"
                               :value (backup . nil)
@@ -564,22 +623,28 @@ See the documentation of `diary-date-forms' for an explanation."
                                       (choice symbol regexp)))))
   :group 'diary)
 
+(autoload 'diary-font-lock-keywords "diary-lib")
+(autoload 'diary-live-p "diary-lib")
+(defvar diary-font-lock-keywords)
+
 (defcustom diary-date-forms
   (if european-calendar-style
       european-date-diary-pattern
     american-date-diary-pattern)
-  "*List of pseudo-patterns describing the forms of date used in the diary.
-The patterns on the list must be MUTUALLY EXCLUSIVE and must should not match
+  "List of pseudo-patterns describing the forms of date used in the diary.
+The patterns on the list must be MUTUALLY EXCLUSIVE and should not match
 any portion of the diary entry itself, just the date component.
 
 A pseudo-pattern is a list of regular expressions and the keywords `month',
 `day', `year', `monthname', and `dayname'.  The keyword `monthname' will
-match the name of the month, capitalized or not, or its three-letter
-abbreviation, followed by a period or not; it will also match `*'.
-Similarly, `dayname' will match the name of the day, capitalized or not, or
-its three-letter abbreviation, followed by a period or not.  The keywords
-`month', `day', and `year' will match those numerical values, preceded by
-arbitrarily many zeros; they will also match `*'.
+match the name of the month (see `calendar-month-name-array'), capitalized
+or not, or its user-specified abbreviation (see `calendar-month-abbrev-array'),
+followed by a period or not; it will also match `*'.  Similarly, `dayname'
+will match the name of the day (see `calendar-day-name-array'), capitalized or
+not, or its user-specified abbreviation (see `calendar-day-abbrev-array'),
+followed by a period or not.  The keywords `month', `day', and `year' will
+match those numerical values, preceded by arbitrarily many zeros; they will
+also match `*'.
 
 The matching of the diary entries with the date forms is done with the
 standard syntax table from Fundamental mode, but with the `*' changed so
@@ -599,20 +664,29 @@ a portion of the first word of the diary entry."
                         (repeat (list :inline t :format "%v"
                                       (symbol :tag "Keyword")
                                       (choice symbol regexp)))))
+  :initialize 'custom-initialize-default
+  :set (lambda (symbol value)
+         (unless (equal value (eval symbol))
+           (custom-set-default symbol value)
+           (setq diary-font-lock-keywords (diary-font-lock-keywords))
+           ;; Need to redraw not just to get new font-locking, but also
+           ;; to pick up any newly recognized entries.
+           (and (diary-live-p)
+                (diary))))
   :group 'diary)
 
 ;;;###autoload
 (defcustom european-calendar-display-form
   '((if dayname (concat dayname ", ")) day " " monthname " " year)
-  "*Pseudo-pattern governing the way a date appears in the European style.
-See the documentation of calendar-date-display-form for an explanation."
+  "Pseudo-pattern governing the way a date appears in the European style.
+See the documentation of `calendar-date-display-form' for an explanation."
   :type 'sexp
   :group 'calendar)
 
 ;;;###autoload
 (defcustom american-calendar-display-form
   '((if dayname (concat dayname ", ")) monthname " " day ", " year)
-  "*Pseudo-pattern governing the way a date appears in the American style.
+  "Pseudo-pattern governing the way a date appears in the American style.
 See the documentation of `calendar-date-display-form' for an explanation."
   :type 'sexp
   :group 'calendar)
@@ -621,7 +695,7 @@ See the documentation of `calendar-date-display-form' for an explanation."
   (if european-calendar-style
       european-calendar-display-form
     american-calendar-display-form)
-  "*Pseudo-pattern governing the way a date appears.
+  "Pseudo-pattern governing the way a date appears.
 
 Used by the function `calendar-date-string', a pseudo-pattern is a list of
 expressions that can involve the keywords `month', `day', and `year', all
@@ -662,7 +736,7 @@ See the documentation of the function `calendar-date-string'."
 
 ;;;###autoload
 (defcustom print-diary-entries-hook 'lpr-buffer
-  "*List of functions called after a temporary diary buffer is prepared.
+  "List of functions called after a temporary diary buffer is prepared.
 The buffer shows only the diary entries currently visible in the diary
 buffer.  The default just does the printing.  Other uses might include, for
 example, rearranging the lines into order by day and time, saving the buffer
@@ -672,7 +746,7 @@ instead of deleting it, or changing the function used to do the printing."
 
 ;;;###autoload
 (defcustom list-diary-entries-hook nil
-  "*List of functions called after diary file is culled for relevant entries.
+  "List of functions called after diary file is culled for relevant entries.
 It is to be used for diary entries that are not found in the diary file.
 
 A function `include-other-diary-files' is provided for use as the value of
@@ -698,18 +772,21 @@ in your `.emacs' file to cause the fancy diary buffer to be displayed with
 diary entries from various included files, each day's entries sorted into
 lexicographic order."
   :type 'hook
+  :options '(include-other-diary-files sort-diary-entries)
   :group 'diary)
 
 ;;;###autoload
 (defcustom diary-hook nil
-  "*List of functions called after the display of the diary.
+  "List of functions called after the display of the diary.
 Can be used for appointment notification."
   :type 'hook
   :group 'diary)
 
+(autoload 'diary-set-maybe-redraw "diary-lib")
+
 ;;;###autoload
 (defcustom diary-display-hook nil
-  "*List of functions that handle the display of the diary.
+  "List of functions that handle the display of the diary.
 If nil (the default), `simple-diary-display' is used.  Use `ignore' for no
 diary display.
 
@@ -730,21 +807,28 @@ diary buffer will not show days for which there are no diary entries, even
 if that day is a holiday; if you want such days to be shown in the fancy
 diary buffer, set the variable `diary-list-include-blanks' to t."
   :type 'hook
+  :options '(fancy-diary-display)
+  :initialize 'custom-initialize-default
+  :set 'diary-set-maybe-redraw
   :group 'diary)
 
 ;;;###autoload
 (defcustom nongregorian-diary-listing-hook nil
-  "*List of functions called for listing diary file and included files.
-As the files are processed for diary entries, these functions are used to cull
-relevant entries.  You can use either or both of `list-hebrew-diary-entries'
-and `list-islamic-diary-entries'.  The documentation for these functions
+  "List of functions called for listing diary file and included files.
+As the files are processed for diary entries, these functions are used
+to cull relevant entries.  You can use either or both of
+`list-hebrew-diary-entries', `list-islamic-diary-entries' and
+`list-bahai-diary-entries'.  The documentation for these functions
 describes the style of such diary entries."
   :type 'hook
+  :options '(list-hebrew-diary-entries
+            list-islamic-diary-entries
+            list-bahai-diary-entries)
   :group 'diary)
 
 ;;;###autoload
 (defcustom mark-diary-entries-hook nil
-  "*List of functions called after marking diary entries in the calendar.
+  "List of functions called after marking diary entries in the calendar.
 
 A function `mark-included-diary-files' is also provided for use as the
 `mark-diary-entries-hook'; it enables you to use shared diary files together
@@ -757,21 +841,26 @@ variable `diary-include-string'.  When you use `mark-included-diary-files' as
 part of the mark-diary-entries-hook, you will probably also want to use the
 function `include-other-diary-files' as part of `list-diary-entries-hook'."
   :type 'hook
+  :options '(mark-included-diary-files)
   :group 'diary)
 
 ;;;###autoload
 (defcustom nongregorian-diary-marking-hook nil
-  "*List of functions called for marking diary file and included files.
-As the files are processed for diary entries, these functions are used to cull
-relevant entries.  You can use either or both of `mark-hebrew-diary-entries'
-and `mark-islamic-diary-entries'.  The documentation for these functions
+  "List of functions called for marking diary file and included files.
+As the files are processed for diary entries, these functions are used
+to cull relevant entries.  You can use either or both of
+`mark-hebrew-diary-entries', `mark-islamic-diary-entries' and
+`mark-bahai-diary-entries'.  The documentation for these functions
 describes the style of such diary entries."
   :type 'hook
+  :options '(mark-hebrew-diary-entries
+            mark-islamic-diary-entries
+            mark-bahai-diary-entries)
   :group 'diary)
 
 ;;;###autoload
 (defcustom diary-list-include-blanks nil
-  "*If nil, do not include days with no diary entry in the list of diary entries.
+  "If nil, do not include days with no diary entry in the list of diary entries.
 Such days will then not be shown in the fancy diary buffer, even if they
 are holidays."
   :type 'boolean
@@ -779,7 +868,7 @@ are holidays."
 
 ;;;###autoload
 (defcustom holidays-in-diary-buffer t
-  "*Non-nil means include holidays in the diary display.
+  "Non-nil means include holidays in the diary display.
 The holidays appear in the mode line of the diary buffer, or in the
 fancy diary buffer next to the date.  This slows down the diary functions
 somewhat; setting it to nil makes the diary display faster."
@@ -809,7 +898,7 @@ somewhat; setting it to nil makes the diary display faster."
     (holiday-fixed 10 31 "Halloween")
     (holiday-fixed 11 11 "Veteran's Day")
     (holiday-float 11 4 4 "Thanksgiving"))
-  "*General holidays.  Default value is for the United States.
+  "General holidays.  Default value is for the United States.
 See the documentation for `calendar-holidays' for details."
   :type 'sexp
   :group 'holidays)
@@ -820,7 +909,7 @@ See the documentation for `calendar-holidays' for details."
 (defcustom oriental-holidays
   '((if (fboundp 'atan)
        (holiday-chinese-new-year)))
-  "*Oriental holidays.
+  "Oriental holidays.
 See the documentation for `calendar-holidays' for details."
   :type 'sexp
   :group 'holidays)
@@ -829,7 +918,7 @@ See the documentation for `calendar-holidays' for details."
 (put 'local-holidays 'risky-local-variable t)
 ;;;###autoload
 (defcustom local-holidays nil
-  "*Local holidays.
+  "Local holidays.
 See the documentation for `calendar-holidays' for details."
   :type 'sexp
   :group 'holidays)
@@ -838,7 +927,7 @@ See the documentation for `calendar-holidays' for details."
 (put 'other-holidays 'risky-local-variable t)
 ;;;###autoload
 (defcustom other-holidays nil
-  "*User defined holidays.
+  "User defined holidays.
 See the documentation for `calendar-holidays' for details."
   :type 'sexp
   :group 'holidays)
@@ -942,7 +1031,7 @@ See the documentation for `calendar-holidays' for details."
 ;;;###autoload
 (defcustom hebrew-holidays (append hebrew-holidays-1 hebrew-holidays-2
                                hebrew-holidays-3 hebrew-holidays-4)
-  "*Jewish holidays.
+  "Jewish holidays.
 See the documentation for `calendar-holidays' for details."
   :type 'sexp
   :group 'holidays)
@@ -953,17 +1042,47 @@ See the documentation for `calendar-holidays' for details."
 (defcustom christian-holidays
   '((if all-christian-calendar-holidays
         (holiday-fixed 1 6 "Epiphany"))
-    (holiday-easter-etc)
+    (holiday-easter-etc 0 "Easter Sunday")
+    (holiday-easter-etc -2 "Good Friday")
+    (holiday-easter-etc -46 "Ash Wednesday")
+    (if all-christian-calendar-holidays
+        (holiday-easter-etc -63 "Septuagesima Sunday"))
+    (if all-christian-calendar-holidays
+        (holiday-easter-etc -56 "Sexagesima Sunday"))
+    (if all-christian-calendar-holidays
+        (holiday-easter-etc -49 "Shrove Sunday"))
+    (if all-christian-calendar-holidays
+        (holiday-easter-etc -48 "Shrove Monday"))
+    (if all-christian-calendar-holidays
+        (holiday-easter-etc -47 "Shrove Tuesday"))
+    (if all-christian-calendar-holidays
+        (holiday-easter-etc -14 "Passion Sunday"))
+    (if all-christian-calendar-holidays
+        (holiday-easter-etc -7 "Palm Sunday"))
+    (if all-christian-calendar-holidays
+        (holiday-easter-etc -3 "Maundy Thursday"))
+    (if all-christian-calendar-holidays
+        (holiday-easter-etc 35 "Rogation Sunday"))
+    (if all-christian-calendar-holidays
+        (holiday-easter-etc 39 "Ascension Day"))
+    (if all-christian-calendar-holidays
+        (holiday-easter-etc 49 "Pentecost (Whitsunday)"))
+    (if all-christian-calendar-holidays
+        (holiday-easter-etc 50 "Whitmonday"))
+    (if all-christian-calendar-holidays
+        (holiday-easter-etc 56 "Trinity Sunday"))
+    (if all-christian-calendar-holidays
+        (holiday-easter-etc 60 "Corpus Christi"))
     (if all-christian-calendar-holidays
         (holiday-greek-orthodox-easter))
     (if all-christian-calendar-holidays
         (holiday-fixed 8 15 "Assumption"))
     (if all-christian-calendar-holidays
-        (holiday-advent))
+        (holiday-advent 0 "Advent"))
     (holiday-fixed 12 25 "Christmas")
     (if all-christian-calendar-holidays
         (holiday-julian 12 25 "Eastern Orthodox Christmas")))
-  "*Christian holidays.
+  "Christian holidays.
 See the documentation for `calendar-holidays' for details."
   :type 'sexp
   :group 'holidays)
@@ -998,7 +1117,49 @@ See the documentation for `calendar-holidays' for details."
         (holiday-islamic 10 1 "Id-al-Fitr"))
     (if all-islamic-calendar-holidays
         (holiday-islamic 12 10 "Id-al-Adha")))
-  "*Islamic holidays.
+  "Islamic holidays.
+See the documentation for `calendar-holidays' for details."
+  :type 'sexp
+  :group 'holidays)
+
+;;;###autoload
+(put 'bahai-holidays 'risky-local-variable t)
+;;;###autoload
+(defcustom bahai-holidays
+  '((holiday-fixed
+     3 21
+     (format "Baha'i New Year (Naw-Ruz) %d" (- displayed-year (1- 1844))))
+    (holiday-fixed  4 21 "First Day of Ridvan")
+    (if all-bahai-calendar-holidays
+       (holiday-fixed  4 22 "Second Day of Ridvan"))
+    (if all-bahai-calendar-holidays
+       (holiday-fixed  4 23 "Third Day of Ridvan"))
+    (if all-bahai-calendar-holidays
+       (holiday-fixed  4 24 "Fourth Day of Ridvan"))
+    (if all-bahai-calendar-holidays
+       (holiday-fixed  4 25 "Fifth Day of Ridvan"))
+    (if all-bahai-calendar-holidays
+       (holiday-fixed  4 26 "Sixth Day of Ridvan"))
+    (if all-bahai-calendar-holidays
+       (holiday-fixed  4 27 "Seventh Day of Ridvan"))
+    (if all-bahai-calendar-holidays
+       (holiday-fixed  4 28 "Eighth Day of Ridvan"))
+    (holiday-fixed  4 29 "Ninth Day of Ridvan")
+    (if all-bahai-calendar-holidays
+       (holiday-fixed  4 30 "Tenth Day of Ridvan"))
+    (if all-bahai-calendar-holidays
+       (holiday-fixed  5  1 "Eleventh Day of Ridvan"))
+    (holiday-fixed  5  2 "Twelfth Day of Ridvan")
+    (holiday-fixed  5 23 "Declaration of the Bab")
+    (holiday-fixed  5 29 "Ascension of Baha'u'llah")
+    (holiday-fixed  7  9 "Martyrdom of the Bab")
+    (holiday-fixed 10 20 "Birth of the Bab")
+    (holiday-fixed 11 12 "Birth of Baha'u'llah")
+    (if all-bahai-calendar-holidays
+       (holiday-fixed 11 26 "Day of the Covenant"))
+    (if all-bahai-calendar-holidays
+       (holiday-fixed 11 28 "Ascension of `Abdu'l-Baha")))
+  "Baha'i holidays.
 See the documentation for `calendar-holidays' for details."
   :type 'sexp
   :group 'holidays)
@@ -1015,7 +1176,7 @@ See the documentation for `calendar-holidays' for details."
       (funcall
        'holiday-sexp
         calendar-daylight-savings-starts
-        '(format "Daylight Savings Time Begins %s"
+        '(format "Daylight Saving Time Begins %s"
                   (if (fboundp 'atan)
                       (solar-time-string
                        (/ calendar-daylight-savings-starts-time (float 60))
@@ -1024,13 +1185,13 @@ See the documentation for `calendar-holidays' for details."
     (funcall
      'holiday-sexp
      calendar-daylight-savings-ends
-     '(format "Daylight Savings Time Ends %s"
+     '(format "Daylight Saving Time Ends %s"
               (if (fboundp 'atan)
                   (solar-time-string
                    (/ calendar-daylight-savings-ends-time (float 60))
                    calendar-daylight-time-zone-name)
                 ""))))
-  "*Sun-related holidays.
+  "Sun-related holidays.
 See the documentation for `calendar-holidays' for details."
   :type 'sexp
   :group 'holidays)
@@ -1040,16 +1201,28 @@ See the documentation for `calendar-holidays' for details."
 (defcustom calendar-holidays
   (append general-holidays local-holidays other-holidays
           christian-holidays hebrew-holidays islamic-holidays
-          oriental-holidays solar-holidays)
-  "*List of notable days for the command \\[holidays].
+          bahai-holidays oriental-holidays solar-holidays)
+  "List of notable days for the command \\[holidays].
+
+Additional holidays are easy to add to the list, just put them in the
+list `other-holidays' in your .emacs file.  Similarly, by setting any
+of `general-holidays', `local-holidays' `christian-holidays',
+`hebrew-holidays', `islamic-holidays', `bahai-holidays',
+`oriental-holidays', or `solar-holidays' to nil in your .emacs file,
+you can eliminate unwanted categories of holidays.
+
+The aforementioned variables control the holiday choices offered
+by the function `list-holidays' when it is called interactively.
+
+They also initialize the default value of `calendar-holidays',
+which is the default list of holidays used by the function
+`list-holidays' in the non-interactive case.  Note that these
+variables have no effect on `calendar-holidays' after it has been
+set (e.g. after the calendar is loaded).  In that case, customize
+`calendar-holidays' directly.
 
-Additional holidays are easy to add to the list, just put them in the list
-`other-holidays' in your .emacs file.  Similarly, by setting any of
-`general-holidays', `local-holidays' `christian-holidays', `hebrew-holidays',
-`islamic-holidays', `oriental-holidays', or `solar-holidays' to nil in your
-.emacs file, you can eliminate unwanted categories of holidays.  The intention
-is that (in the US) `local-holidays' be set in site-init.el and
-`other-holidays' be set by the user.
+The intention is that (in the US) `local-holidays' be set in
+site-init.el and `other-holidays' be set by the user.
 
 Entries on the list are expressions that return (possibly empty) lists of
 items of the form ((month day year) string) of a holiday in the in the
@@ -1064,6 +1237,7 @@ Several basic functions are provided for this purpose:
                                DAYNAME after/before MONTH DAY.
     (holiday-hebrew MONTH DAY STRING)  a fixed date on the Hebrew calendar
     (holiday-islamic MONTH DAY STRING) a fixed date on the Islamic calendar
+    (holiday-bahai MONTH DAY STRING)   a fixed date on the Baha'i calendar
     (holiday-julian MONTH DAY STRING)  a fixed date on the Julian calendar
     (holiday-sexp SEXP STRING) SEXP is a Gregorian-date-valued expression
                                in the variable `year'; if it evaluates to
@@ -1091,6 +1265,11 @@ add the Islamic feast celebrating Mohammed's birthday use
      (holiday-islamic 3 12 \"Mohammed's Birthday\")
 
 since the Islamic months are numbered from 1 starting with Muharram.  To
+add an entry for the Baha'i festival of Ridvan, use
+
+     (holiday-bahai 2 13 \"Festival of Ridvan\")
+
+since the Baha'i months are numbered from 1 starting with Baha.  To
 add Thomas Jefferson's birthday, April 2, 1743 (Julian), use
 
      (holiday-julian 4 2 \"Jefferson's Birthday\")
@@ -1100,7 +1279,7 @@ example, to include American presidential elections, which occur on the first
 Tuesday after the first Monday in November of years divisible by 4, add
 
      (holiday-sexp
-       (if (zerop (% year 4))
+       '(if (zerop (% year 4))
            (calendar-gregorian-from-absolute
              (1+ (calendar-dayname-on-or-before
                    1 (+ 6 (calendar-absolute-from-gregorian
@@ -1130,9 +1309,6 @@ with descriptive strings such as
   :type 'sexp
   :group 'holidays)
 
-(defconst calendar-buffer "*Calendar*"
-  "Name of the buffer used for the calendar.")
-
 (defconst holiday-buffer "*Holidays*"
   "Name of the buffer used for the displaying the holidays.")
 
@@ -1146,20 +1322,36 @@ with descriptive strings such as
   "Name of the buffer used for the lunar phases.")
 
 (defmacro increment-calendar-month (mon yr n)
-  "Move the variables MON and YR to the month and year by N months.
-Forward if N is positive or backward if N is negative."
-  `(let ((macro-y (+ (* ,yr 12) ,mon -1 ,n)))
-    (setq ,mon (1+ (% macro-y 12)))
-    (setq ,yr (/ macro-y 12))))
+  "Increment the variables MON and YR by N months.
+Forward if N is positive or backward if N is negative.
+A negative YR is interpreted as BC; -1 being 1 BC, and so on."
+  `(let (macro-y)
+     (if (< ,yr 0) (setq ,yr (1+ ,yr))) ; -1 BC -> 0 AD, etc
+     (setq macro-y (+ (* ,yr 12) ,mon -1 ,n)
+           ,mon (1+ (mod macro-y 12))
+           ,yr (/ macro-y 12))
+     (and (< macro-y 0) (> ,mon 1) (setq ,yr (1- ,yr)))
+     (if (< ,yr 1) (setq ,yr (1- ,yr))))) ; 0 AD -> -1 BC, etc
+
+(defun calendar-increment-month (n &optional mon yr)
+  "Return the Nth month after MON/YR.
+The return value is a pair (MONTH . YEAR).
+MON defaults to `displayed-month'.  YR defaults to `displayed-year'."
+  (unless mon (setq mon displayed-month))
+  (unless yr (setq yr displayed-year))
+  (increment-calendar-month mon yr n)
+  (cons mon yr))
 
 (defmacro calendar-for-loop (var from init to final do &rest body)
   "Execute a for loop."
+  (declare (debug (symbolp "from" form "to" form "do" body)))
   `(let ((,var (1- ,init)))
     (while (>= ,final (setq ,var (1+ ,var)))
       ,@body)))
 
 (defmacro calendar-sum (index initial condition expression)
   "For INDEX = INITIAL et seq, as long as CONDITION holds, sum EXPRESSION."
+  (declare (debug (symbolp form form form)))
   `(let ((,index ,initial)
          (sum 0))
     (while ,condition
@@ -1201,6 +1393,7 @@ Forward if N is positive or backward if N is negative."
   "Extract the month part of DATE which has the form (month day year)."
   (car date))
 
+;; Note gives wrong answer for result of (calendar-read-date 'noday).
 (defsubst extract-calendar-day (date)
   "Extract the day part of DATE which has the form (month day year)."
   (car (cdr date)))
@@ -1210,7 +1403,10 @@ Forward if N is positive or backward if N is negative."
   (car (cdr (cdr date))))
 
 (defsubst calendar-leap-year-p (year)
-  "Return t if YEAR is a Gregorian leap year."
+  "Return t if YEAR is a Gregorian leap year.
+A negative year is interpreted as BC; -1 being 1 BC, and so on."
+  ;; 1 BC = 0 AD, 2 BC acts like 1 AD, etc.
+  (if (< year 0) (setq year (1- (abs year))))
   (and (zerop (% year 4))
        (or (not (zerop (% year 100)))
            (zerop (% year 400)))))
@@ -1250,13 +1446,30 @@ while (calendar-day-number '(12 31 1980)) returns 366."
 
 (defsubst calendar-absolute-from-gregorian (date)
   "The number of days elapsed between the Gregorian date 12/31/1 BC and DATE.
-The Gregorian date Sunday, December 31, 1 BC is imaginary."
-  (let ((prior-years (1- (extract-calendar-year date))))
-    (+ (calendar-day-number date);; Days this year
-       (* 365 prior-years);;        + Days in prior years
-       (/ prior-years 4);;          + Julian leap years
-       (- (/ prior-years 100));;    - century years
-       (/ prior-years 400))));;     + Gregorian leap years
+The Gregorian date Sunday, December 31, 1 BC is imaginary.
+DATE is a list of the form (month day year).  A negative year is
+interpreted as BC; -1 being 1 BC, and so on.  Dates before 12/31/1 BC
+return negative results."
+  (let ((year (extract-calendar-year date))
+        offset-years)
+    (cond ((= year 0)
+           (error "There was no year zero"))
+          ((> year 0)
+           (setq offset-years (1- year))
+           (+ (calendar-day-number date) ; Days this year
+              (* 365 offset-years)       ; + Days in prior years
+              (/ offset-years 4)         ; + Julian leap years
+              (- (/ offset-years 100))   ; - century years
+              (/ offset-years 400)))     ; + Gregorian leap years
+          (t
+           ;; Years between date and 1 BC, excluding 1 BC (1 for 2 BC, etc).
+           (setq offset-years (abs (1+ year)))
+           (- (calendar-day-number date)
+              (* 365 offset-years)
+              (/ offset-years 4)
+              (- (/ offset-years 100))
+              (/ offset-years 400)
+              (calendar-day-number '(12 31 -1))))))) ; days in year 1 BC
 
 (autoload 'calendar-goto-today "cal-move"
   "Reposition the calendar window so the current date is visible."
@@ -1346,6 +1559,13 @@ The Gregorian date Sunday, December 31, 1 BC is imaginary."
   "Move cursor to DATE."
   t)
 
+(autoload 'calendar-goto-day-of-year "cal-move"
+  "Move cursor to day of year."
+  t)
+
+(autoload 'calendar-only-one-frame-setup "cal-x"
+ "Start calendar and display it in a dedicated frame.")
+
 (autoload 'calendar-one-frame-setup "cal-x"
   "Start calendar and display it in a dedicated frame together with the diary.")
 
@@ -1353,17 +1573,33 @@ The Gregorian date Sunday, December 31, 1 BC is imaginary."
   "Start calendar and diary in separate, dedicated frames.")
 
 ;;;###autoload
-(defvar calendar-setup nil
-  "The frame set up of the calendar.
-The choices are `one-frame' (calendar and diary together in one separate,
-dedicated frame), `two-frames' (calendar and diary in separate, dedicated
-frames), `calendar-only' (calendar in a separate, dedicated frame); with
-any other value the current frame is used.")
+(defcustom calendar-setup nil
+  "The frame setup of the calendar.
+The choices are: `one-frame' (calendar and diary together in one separate,
+dedicated frame); `two-frames' (calendar and diary in separate, dedicated
+frames); `calendar-only' (calendar in a separate, dedicated frame); with
+any other value the current frame is used.  Using any of the first
+three options overrides the value of `view-diary-entries-initially'."
+  :type '(choice
+          (const :tag "calendar and diary in separate frame" one-frame)
+          (const :tag "calendar and diary each in own frame" two-frames)
+          (const :tag "calendar in separate frame" calendar-only)
+          (const :tag "use current frame" nil))
+  :group 'calendar)
+
+(defcustom calendar-minimum-window-height 8
+  "Minimum height `generate-calendar-window' should use for calendar window."
+  :type 'integer
+  :version "22.1"
+  :group 'calendar)
 
 ;;;###autoload
 (defun calendar (&optional arg)
   "Choose between the one frame, two frame, or basic calendar displays.
-The original function `calendar' has been renamed `calendar-basic-setup'."
+If called with an optional prefix argument, prompts for month and year.
+
+The original function `calendar' has been renamed `calendar-basic-setup'.
+See the documentation of that function for more information."
   (interactive "P")
   (cond ((equal calendar-setup 'one-frame) (calendar-one-frame-setup arg))
         ((equal calendar-setup 'two-frames) (calendar-two-frame-setup arg))
@@ -1371,6 +1607,19 @@ The original function `calendar' has been renamed `calendar-basic-setup'."
          (calendar-only-one-frame-setup arg))
         (t (calendar-basic-setup arg))))
 
+(autoload 'diary-view-entries "diary-lib"
+  "Prepare and display a buffer with diary entries.
+Searches your diary file for entries that match ARG days starting with
+the date indicated by the cursor position in the displayed three-month
+calendar."
+  t)
+
+(autoload 'list-calendar-holidays "holidays"
+  "Create a buffer containing the holidays for the current calendar window.
+The holidays are those in the list `calendar-notable-days'.  Returns t if any
+holidays are found, nil if not."
+  t)
+
 (defun calendar-basic-setup (&optional arg)
   "Display a three-month calendar in another window.
 The three months appear side by side, with the current month in the middle
@@ -1423,14 +1672,14 @@ to be replaced by asterisks to highlight it whenever it is in the window."
                  (calendar-current-date)))
          (month (extract-calendar-month date))
          (year (extract-calendar-year date)))
+    ;; (calendar-read-date t) returns a date with day = nil, which is
+    ;; not a legal date for the visible test in the diary section.
+    (if arg (setcar (cdr date) 1))
     (pop-to-buffer calendar-buffer)
     (increment-calendar-month month year (- calendar-offset))
     (generate-calendar-window month year)
     (if (and view-diary-entries-initially (calendar-date-is-visible-p date))
-        (view-diary-entries
-         (if (vectorp number-of-diary-entries)
-             (aref number-of-diary-entries (calendar-day-of-week date))
-           number-of-diary-entries))))
+        (diary-view-entries)))
   (let* ((diary-buffer (get-file-buffer diary-file))
          (diary-window (if diary-buffer (get-buffer-window diary-buffer)))
          (split-height-threshold (if diary-window 2 1000)))
@@ -1438,11 +1687,11 @@ to be replaced by asterisks to highlight it whenever it is in the window."
         (list-calendar-holidays)))
   (run-hooks 'initial-calendar-window-hook))
 
-(autoload 'view-diary-entries "diary-lib"
-  "Prepare and display a buffer with diary entries.
-Searches your diary file for entries that match ARG days starting with
-the date indicated by the cursor position in the displayed three-month
-calendar."
+(autoload 'view-other-diary-entries "diary-lib"
+  "Prepare and display buffer of diary entries from an alternative diary file.
+Searches for entries that match ARG days, starting with the date indicated
+by the cursor position in the displayed three-month calendar.
+D-FILE specifies the file to use as the diary file."
   t)
 
 (autoload 'calendar-sunrise-sunset "solar"
@@ -1462,12 +1711,10 @@ calendar."
   t)
 
 (autoload 'calendar-french-date-string "cal-french"
-  "String of French Revolutionary date of Gregorian date."
-  t)
+  "String of French Revolutionary date of Gregorian date.")
 
 (autoload 'calendar-mayan-date-string "cal-mayan"
-  "String of Mayan date of Gregorian date."
-  t)
+  "String of Mayan date of Gregorian date.")
 
 (autoload 'calendar-print-mayan-date "cal-mayan"
   "Show the Mayan long count, Tzolkin, and Haab equivalents of the date under the cursor."
@@ -1510,8 +1757,7 @@ calendar."
  t)
 
 (autoload 'calendar-chinese-date-string "cal-china"
-  "String of Chinese date of Gregorian date."
-  t)
+  "String of Chinese date of Gregorian date.")
 
 (autoload 'calendar-absolute-from-astro  "cal-julian"
   "Absolute date of astronomical (Julian) day number D."
@@ -1521,8 +1767,7 @@ calendar."
   "Astronomical (Julian) day number of absolute date D.")
 
 (autoload 'calendar-astro-date-string "cal-julian"
-  "String of astronomical (Julian) day number of Gregorian date."
-  t)
+  "String of astronomical (Julian) day number of Gregorian date.")
 
 (autoload 'calendar-goto-astro-day-number "cal-julian"
    "Move cursor to astronomical (Julian) day number."
@@ -1554,13 +1799,16 @@ Driven by the variable `calendar-date-display-form'.")
   "Move cursor to ISO date."
   t)
 
+(autoload 'calendar-goto-iso-week "cal-iso"
+  "Move cursor to start of ISO week."
+  t)
+
 (autoload 'calendar-print-iso-date "cal-iso"
   "Show the ISO date equivalents of date."
   t)
 
 (autoload 'calendar-iso-date-string "cal-iso"
-  "String of ISO date of Gregorian date."
-  t)
+  "String of ISO date of Gregorian date.")
 
 (autoload 'calendar-goto-islamic-date "cal-islam"
   "Move cursor to Islamic date."
@@ -1571,11 +1819,17 @@ Driven by the variable `calendar-date-display-form'.")
   t)
 
 (autoload 'calendar-islamic-date-string "cal-islam"
-  "String of Islamic date of Gregorian date."
+  "String of Islamic date of Gregorian date.")
+
+(autoload 'calendar-print-bahai-date "cal-bahai"
+  "Show the Baha'i date equivalents of date."
   t)
 
+(autoload 'calendar-bahai-date-string "cal-bahai"
+  "String of Baha'i date of Gregorian date.")
+
 (autoload 'calendar-goto-hebrew-date "cal-hebrew"
-  "Move cursor to Hebrew date date."
+  "Move cursor to Hebrew date."
   t)
 
 (autoload 'calendar-print-hebrew-date "cal-hebrew"
@@ -1583,11 +1837,10 @@ Driven by the variable `calendar-date-display-form'.")
   t)
 
 (autoload 'calendar-hebrew-date-string "cal-hebrew"
-  "String of Hebrew date of Gregorian date."
-  t)
+  "String of Hebrew date of Gregorian date.")
 
 (autoload 'calendar-goto-coptic-date "cal-coptic"
-   "Move cursor to Coptic date date."
+   "Move cursor to Coptic date."
    t)
 
 (autoload 'calendar-print-coptic-date "cal-coptic"
@@ -1595,11 +1848,10 @@ Driven by the variable `calendar-date-display-form'.")
  t)
 
 (autoload 'calendar-coptic-date-string "cal-coptic"
-  "String of Coptic date of Gregorian date."
-  t)
+  "String of Coptic date of Gregorian date.")
 
 (autoload 'calendar-goto-ethiopic-date "cal-coptic"
-   "Move cursor to Ethiopic date date."
+   "Move cursor to Ethiopic date."
    t)
 
 (autoload 'calendar-print-ethiopic-date "cal-coptic"
@@ -1607,11 +1859,10 @@ Driven by the variable `calendar-date-display-form'.")
  t)
 
 (autoload 'calendar-ethiopic-date-string "cal-coptic"
-  "String of Ethiopic date of Gregorian date."
-  t)
+  "String of Ethiopic date of Gregorian date.")
 
 (autoload 'calendar-goto-persian-date "cal-persia"
-   "Move cursor to Persian date date."
+   "Move cursor to Persian date."
    t)
 
 (autoload 'calendar-print-persian-date "cal-persia"
@@ -1619,10 +1870,9 @@ Driven by the variable `calendar-date-display-form'.")
  t)
 
 (autoload 'calendar-persian-date-string "cal-persia"
-  "String of Persian date of Gregorian date."
-  t)
+  "String of Persian date of Gregorian date.")
 
-(autoload 'show-all-diary-entries "diary-lib"
+(autoload 'diary-show-all-entries "diary-lib"
   "Show all of the diary entries in the diary file.
 This function gets rid of the selective display of the diary file so that
 all entries, not just some, are visible.  If there is no diary buffer, one
@@ -1635,8 +1885,7 @@ Each entry in diary file visible in the calendar window is marked."
   t)
 
 (autoload 'make-diary-entry "diary-lib"
-  "Insert a diary entry STRING which may be NONMARKING in FILE."
-  t)
+  "Insert a diary entry STRING which may be NONMARKING in FILE.")
 
 (autoload 'insert-diary-entry "diary-lib"
   "Insert a diary entry for the date indicated by point."
@@ -1697,78 +1946,99 @@ to the date indicated by point."
 to the date indicated by point."
   t)
 
-(autoload 'list-calendar-holidays "holidays"
-  "Create a buffer containing the holidays for the current calendar window.
-The holidays are those in the list `calendar-notable-days'.  Returns t if any
-holidays are found, nil if not."
+(autoload 'insert-bahai-diary-entry "cal-bahai"
+  "Insert a diary entry for the Baha'i date corresponding to the date
+indicated by point."
+  t)
+
+(autoload 'insert-monthly-bahai-diary-entry "cal-bahai"
+  "Insert a monthly diary entry for the day of the Baha'i month corresponding
+to the date indicated by point."
+  t)
+
+(autoload 'insert-yearly-bahai-diary-entry "cal-bahai"
+  "Insert an annual diary entry for the day of the Baha'i year corresponding
+to the date indicated by point."
   t)
 
 (autoload 'cal-tex-cursor-month "cal-tex"
   "Make a buffer with LaTeX commands for the month cursor is on.
 Optional prefix argument specifies number of months to be produced.
-Calendar is condensed onto one page.")
+Calendar is condensed onto one page." t)
 
 (autoload 'cal-tex-cursor-month-landscape "cal-tex"
   "Make a buffer with LaTeX commands for the month cursor is on.
-Optional prefix argument specifies number of months to be produced.")
+Optional prefix argument specifies number of months to be produced." t)
 
 (autoload 'cal-tex-cursor-day "cal-tex"
-  "Make a buffer with LaTeX commands for the day cursor is on.")
+  "Make a buffer with LaTeX commands for the day cursor is on." t)
 
 (autoload 'cal-tex-cursor-week "cal-tex"
   "Make a buffer with LaTeX commands for a two-page one-week calendar.
 It applies to the week that point is in.
 Optional prefix argument specifies number of weeks.
-Holidays are included if `cal-tex-holidays' is t.")
+Holidays are included if `cal-tex-holidays' is t." t)
 
 (autoload 'cal-tex-cursor-week2 "cal-tex"
   "Make a buffer with LaTeX commands for a two-page one-week calendar.
 It applies to the week that point is in.
 Optional prefix argument specifies number of weeks.
-Holidays are included if `cal-tex-holidays' is t.")
+Holidays are included if `cal-tex-holidays' is t." t)
 
 (autoload 'cal-tex-cursor-week-iso "cal-tex"
   "Make a buffer with LaTeX commands for a one page ISO-style weekly calendar.
 Optional prefix argument specifies number of weeks.
 Diary entries are included if `cal-tex-diary' is t.
-Holidays are included if `cal-tex-holidays' is t.")
+Holidays are included if `cal-tex-holidays' is t." t)
 
 (autoload 'cal-tex-cursor-week-monday "cal-tex"
   "Make a buffer with LaTeX commands for a two-page one-week calendar.
 It applies to the week that point is in, and starts on Monday.
 Optional prefix argument specifies number of weeks.
-Holidays are included if `cal-tex-holidays' is t.")
+Holidays are included if `cal-tex-holidays' is t." t)
 
 (autoload 'cal-tex-cursor-filofax-2week "cal-tex"
   "Two-weeks-at-a-glance Filofax style calendar for week indicated by cursor.
 Optional prefix argument specifies number of weeks.
 Diary entries are included if cal-tex-diary is t.
-Holidays are included if `cal-tex-holidays' is t.")
+Holidays are included if `cal-tex-holidays' is t." t)
 
 (autoload 'cal-tex-cursor-filofax-week "cal-tex"
   "One-week-at-a-glance Filofax style calendar for week indicated by cursor.
 Optional prefix argument specifies number of weeks.
 Weeks start on Monday.
 Diary entries are included if cal-tex-diary is t.
-Holidays are included if `cal-tex-holidays' is t.")
+Holidays are included if `cal-tex-holidays' is t." t)
 
 (autoload 'cal-tex-cursor-filofax-daily "cal-tex"
   "Day-per-page Filofax style calendar for week indicated by cursor.
 Optional prefix argument specifies number of weeks.  Weeks start on Monday.
 Diary entries are included if `cal-tex-diary' is t.
-Holidays are included if `cal-tex-holidays' is t.")
+Holidays are included if `cal-tex-holidays' is t." t)
 
 (autoload 'cal-tex-cursor-year "cal-tex"
   "Make a buffer with LaTeX commands for a year's calendar.
-Optional prefix argument specifies number of years.")
+Optional prefix argument specifies number of years." t)
 
 (autoload 'cal-tex-cursor-year-landscape "cal-tex"
   "Make a buffer with LaTeX commands for a year's calendar (landscape).
-Optional prefix argument specifies number of years.")
+Optional prefix argument specifies number of years." t)
 
 (autoload 'cal-tex-cursor-filofax-year "cal-tex"
   "Make a buffer with LaTeX commands for a year's calendar (Filofax).
-Optional prefix argument specifies number of years.")
+Optional prefix argument specifies number of years." t)
+
+(autoload 'cal-html-cursor-month "cal-html"
+  "Write an HTML calendar file for numeric MONTH of four-digit YEAR.
+The output directory DIR is created if necessary.  Interactively,
+MONTH and YEAR are taken from the calendar cursor position.  Note
+that any existing output files are overwritten." t)
+
+(autoload 'cal-html-cursor-year "cal-html"
+  "Write HTML calendar files (index and monthly pages) for four-digit YEAR.
+The output directory DIR is created if necessary.  Interactively,
+YEAR is taken from the calendar cursor position.  Note that any
+existing output files are overwritten." t)
 
 (autoload 'mark-calendar-holidays "holidays"
   "Mark notable days in the calendar window."
@@ -1790,24 +2060,33 @@ Or, for optional MON, YR."
           (or (not mon)
               (let ((offset (calendar-interval mon yr month year)))
                 (and (<= offset 1) (>= offset -1)))))
-         (day-in-week (calendar-day-of-week today)))
+         (day-in-week (calendar-day-of-week today))
+         (in-calendar-window (eq (window-buffer (selected-window))
+                                 (get-buffer calendar-buffer))))
     (update-calendar-mode-line)
     (if mon
         (generate-calendar mon yr)
-        (generate-calendar month year))
+      (generate-calendar month year))
     (calendar-cursor-to-visible-date
      (if today-visible today (list displayed-month 1 displayed-year)))
     (set-buffer-modified-p nil)
-    (if (or (one-window-p t) (/= (frame-width) (window-width)))
-       ;; Don't mess with the window size, but ensure that the first
-       ;; line is fully visible
-       (set-window-vscroll nil 0)
-      ;; Adjust the window to exactly fit the displayed calendar
-      (fit-window-to-buffer))
-    (sit-for 0)
+    ;; Don't do any window-related stuff if we weren't called from a
+    ;; window displaying the calendar
+    (when in-calendar-window
+      (if (or (one-window-p t) (/= (frame-width) (window-width)))
+          ;; Don't mess with the window size, but ensure that the first
+          ;; line is fully visible
+          (set-window-vscroll nil 0)
+        ;; Adjust the window to exactly fit the displayed calendar
+        (fit-window-to-buffer nil nil calendar-minimum-window-height))
+      (sit-for 0))
+    (if (and (boundp 'font-lock-mode)
+            font-lock-mode)
+       (font-lock-fontify-buffer))
     (and mark-holidays-in-calendar
+;;;         (calendar-date-is-legal-p today) ; useful for BC dates
          (mark-calendar-holidays)
-         (sit-for 0))
+         (and in-calendar-window (sit-for 0)))
     (unwind-protect
         (if mark-diary-entries-in-calendar (mark-diary-entries))
       (if today-visible
@@ -1816,10 +2095,14 @@ Or, for optional MON, YR."
 
 (defun generate-calendar (month year)
   "Generate a three-month Gregorian calendar centered around MONTH, YEAR."
+;;; A negative YEAR is interpreted as BC; -1 being 1 BC, and so on.
+;;; Note that while calendars for years BC could be displayed as it
+;;; stands, almost all other calendar functions (eg holidays) would
+;;; at best have unpredictable results for such dates.
   (if (< (+ month (* 12 (1- year))) 2)
-      (error "Months before February, 1 AD are not available"))
-  (setq displayed-month month)
-  (setq displayed-year year)
+      (error "Months before January, 1 AD cannot be displayed"))
+  (setq displayed-month month
+        displayed-year year)
   (erase-buffer)
   (increment-calendar-month month year -1)
   (calendar-for-loop i from 0 to 2 do
@@ -1828,10 +2111,10 @@ Or, for optional MON, YR."
 
 (defun generate-calendar-month (month year indent)
   "Produce a calendar for MONTH, YEAR on the Gregorian calendar.
-The calendar is inserted in the buffer starting at the line on which point
-is currently located, but indented INDENT spaces.  The indentation is done
-from the first character on the line and does not disturb the first INDENT
-characters on the line."
+The calendar is inserted at the top of the buffer in which point is currently
+located, but indented INDENT spaces.  The indentation is done from the first
+character on the line and does not disturb the first INDENT characters on the
+line."
   (let* ((blank-days;; at start of month
           (mod
            (- (calendar-day-of-week (list month 1 year))
@@ -1844,10 +2127,15 @@ characters on the line."
      (list (format "%s %d" (calendar-month-name month) year)) ?  20)
     indent t)
    (calendar-insert-indented "" indent);; Go to proper spot
+   ;; Use the first two characters of each day to head the columns.
    (calendar-for-loop i from 0 to 6 do
-      (insert (calendar-day-name (mod (+ calendar-week-start-day i) 7)
-                                2 t))
-      (insert " "))
+      (insert
+       (let ((string
+              (calendar-day-name (mod (+ calendar-week-start-day i) 7) nil t)))
+         (if enable-multibyte-characters
+             (truncate-string-to-width string 2)
+           (substring string 0 2)))
+       " "))
    (calendar-insert-indented "" 0 t);; Force onto following line
    (calendar-insert-indented "" indent);; Go to proper spot
    ;; Add blank days before the first of the month
@@ -1885,151 +2173,179 @@ the inserted text.  Value is always t."
   t)
 
 (defun redraw-calendar ()
-  "Redraw the calendar display."
+  "Redraw the calendar display, if `calendar-buffer' is live."
   (interactive)
-  (let ((cursor-date (calendar-cursor-to-nearest-date)))
-    (generate-calendar-window displayed-month displayed-year)
-    (calendar-cursor-to-visible-date cursor-date)))
+  (if (get-buffer calendar-buffer)
+      (with-current-buffer calendar-buffer
+        (let ((cursor-date (calendar-cursor-to-nearest-date)))
+          (generate-calendar-window displayed-month displayed-year)
+          (calendar-cursor-to-visible-date cursor-date)))))
+
+;;;###autoload
+(defcustom calendar-week-start-day 0
+  "The day of the week on which a week in the calendar begins.
+0 means Sunday (default), 1 means Monday, and so on.
+
+If you change this variable directly (without using customize)
+after starting `calendar', you should call `redraw-calendar' to
+update the calendar display to reflect the change, otherwise
+movement commands will not work correctly."
+  :type 'integer
+  ;; Change the initialize so that if you reload calendar.el, it will not
+  ;; cause a redraw (which may fail, e.g. with "invalid byte-code in
+  ;; calendar.elc" because of the "byte-compile-dynamic").
+  :initialize 'custom-initialize-default
+  :set (lambda (sym val)
+         (set sym val)
+         (redraw-calendar))
+  :group 'calendar)
 
 (defcustom calendar-debug-sexp nil
-  "*Turn debugging on when evaluating a sexp in the diary or holiday list."
+  "Turn debugging on when evaluating a sexp in the diary or holiday list."
   :type 'boolean
   :group 'calendar)
 
 (defvar calendar-mode-map nil)
 (if calendar-mode-map
     nil
-  (setq calendar-mode-map (make-sparse-keymap))
-  (require 'cal-menu)
-  (calendar-for-loop i from 0 to 9 do
-       (define-key calendar-mode-map (int-to-string i) 'digit-argument))
-  (let ((l (list 'narrow-to-region 'mark-word 'mark-sexp 'mark-paragraph
-                 'mark-defun 'mark-whole-buffer 'mark-page
-                 'downcase-region 'upcase-region 'kill-region
-                 'copy-region-as-kill 'capitalize-region 'write-region)))
-    (while l
-      (substitute-key-definition (car l) 'calendar-not-implemented
-                                calendar-mode-map global-map)
-      (setq l (cdr l))))
-  (define-key calendar-mode-map "-"     'negative-argument)
-  (define-key calendar-mode-map "\C-x>" 'scroll-calendar-right)
-  (define-key calendar-mode-map [prior] 'scroll-calendar-right-three-months)
-  (define-key calendar-mode-map "\ev"   'scroll-calendar-right-three-months)
-  (define-key calendar-mode-map "\C-x<" 'scroll-calendar-left)
-  (define-key calendar-mode-map [next]  'scroll-calendar-left-three-months)
-  (define-key calendar-mode-map "\C-v"  'scroll-calendar-left-three-months)
-  (define-key calendar-mode-map "\C-b"  'calendar-backward-day)
-  (define-key calendar-mode-map "\C-p"  'calendar-backward-week)
-  (define-key calendar-mode-map "\e{"   'calendar-backward-month)
-  (define-key calendar-mode-map "\C-x[" 'calendar-backward-year)
-  (define-key calendar-mode-map "\C-f"  'calendar-forward-day)
-  (define-key calendar-mode-map "\C-n"  'calendar-forward-week)
-  (define-key calendar-mode-map [left]  'calendar-backward-day)
-  (define-key calendar-mode-map [up]    'calendar-backward-week)
-  (define-key calendar-mode-map [right] 'calendar-forward-day)
-  (define-key calendar-mode-map [down]  'calendar-forward-week)
-  (define-key calendar-mode-map "\e}"   'calendar-forward-month)
-  (define-key calendar-mode-map "\C-x]" 'calendar-forward-year)
-  (define-key calendar-mode-map "\C-a"  'calendar-beginning-of-week)
-  (define-key calendar-mode-map "\C-e"  'calendar-end-of-week)
-  (define-key calendar-mode-map "\ea"   'calendar-beginning-of-month)
-  (define-key calendar-mode-map "\ee"   'calendar-end-of-month)
-  (define-key calendar-mode-map "\e<"   'calendar-beginning-of-year)
-  (define-key calendar-mode-map "\e>"   'calendar-end-of-year)
-  (define-key calendar-mode-map "\C-@"  'calendar-set-mark)
-  ;; Many people are used to typing C-SPC and getting C-@.
-  (define-key calendar-mode-map [?\C- ] 'calendar-set-mark)
-  (define-key calendar-mode-map "\C-x\C-x" 'calendar-exchange-point-and-mark)
-  (define-key calendar-mode-map "\e=" 'calendar-count-days-region)
-  (define-key calendar-mode-map "gd"  'calendar-goto-date)
-  (define-key calendar-mode-map "gj"  'calendar-goto-julian-date)
-  (define-key calendar-mode-map "ga"  'calendar-goto-astro-day-number)
-  (define-key calendar-mode-map "gh"  'calendar-goto-hebrew-date)
-  (define-key calendar-mode-map "gi"  'calendar-goto-islamic-date)
-  (define-key calendar-mode-map "gC"  'calendar-goto-chinese-date)
-  (define-key calendar-mode-map "gk"  'calendar-goto-coptic-date)
-  (define-key calendar-mode-map "ge"  'calendar-goto-ethiopic-date)
-  (define-key calendar-mode-map "gp"  'calendar-goto-persian-date)
-  (define-key calendar-mode-map "gc"  'calendar-goto-iso-date)
-  (define-key calendar-mode-map "gf"  'calendar-goto-french-date)
-  (define-key calendar-mode-map "gml"  'calendar-goto-mayan-long-count-date)
-  (define-key calendar-mode-map "gmpc" 'calendar-previous-calendar-round-date)
-  (define-key calendar-mode-map "gmnc" 'calendar-next-calendar-round-date)
-  (define-key calendar-mode-map "gmph" 'calendar-previous-haab-date)
-  (define-key calendar-mode-map "gmnh" 'calendar-next-haab-date)
-  (define-key calendar-mode-map "gmpt" 'calendar-previous-tzolkin-date)
-  (define-key calendar-mode-map "gmnt" 'calendar-next-tzolkin-date)
-  (define-key calendar-mode-map "Aa"   'appt-add)
-  (define-key calendar-mode-map "Ad"   'appt-delete)
-  (define-key calendar-mode-map "S"   'calendar-sunrise-sunset)
-  (define-key calendar-mode-map "M"   'calendar-phases-of-moon)
-  (define-key calendar-mode-map " "   'scroll-other-window)
-  (define-key calendar-mode-map "\C-c\C-l" 'redraw-calendar)
-  (define-key calendar-mode-map "."   'calendar-goto-today)
-  (define-key calendar-mode-map "o"   'calendar-other-month)
-  (define-key calendar-mode-map "q"   'exit-calendar)
-  (define-key calendar-mode-map "a"   'list-calendar-holidays)
-  (define-key calendar-mode-map "h"   'calendar-cursor-holidays)
-  (define-key calendar-mode-map "x"   'mark-calendar-holidays)
-  (define-key calendar-mode-map "u"   'calendar-unmark)
-  (define-key calendar-mode-map "m"   'mark-diary-entries)
-  (define-key calendar-mode-map "d"   'view-diary-entries)
-  (define-key calendar-mode-map "D"   'view-other-diary-entries)
-  (define-key calendar-mode-map "s"   'show-all-diary-entries)
-  (define-key calendar-mode-map "pd"  'calendar-print-day-of-year)
-  (define-key calendar-mode-map "pC"  'calendar-print-chinese-date)
-  (define-key calendar-mode-map "pk"  'calendar-print-coptic-date)
-  (define-key calendar-mode-map "pe"  'calendar-print-ethiopic-date)
-  (define-key calendar-mode-map "pp"  'calendar-print-persian-date)
-  (define-key calendar-mode-map "pc"  'calendar-print-iso-date)
-  (define-key calendar-mode-map "pj"  'calendar-print-julian-date)
-  (define-key calendar-mode-map "pa"  'calendar-print-astro-day-number)
-  (define-key calendar-mode-map "ph"  'calendar-print-hebrew-date)
-  (define-key calendar-mode-map "pi"  'calendar-print-islamic-date)
-  (define-key calendar-mode-map "pf"  'calendar-print-french-date)
-  (define-key calendar-mode-map "pm"  'calendar-print-mayan-date)
-  (define-key calendar-mode-map "po"  'calendar-print-other-dates)
-  (define-key calendar-mode-map "id"  'insert-diary-entry)
-  (define-key calendar-mode-map "iw"  'insert-weekly-diary-entry)
-  (define-key calendar-mode-map "im"  'insert-monthly-diary-entry)
-  (define-key calendar-mode-map "iy"  'insert-yearly-diary-entry)
-  (define-key calendar-mode-map "ia"  'insert-anniversary-diary-entry)
-  (define-key calendar-mode-map "ib"  'insert-block-diary-entry)
-  (define-key calendar-mode-map "ic"  'insert-cyclic-diary-entry)
-  (define-key calendar-mode-map "ihd" 'insert-hebrew-diary-entry)
-  (define-key calendar-mode-map "ihm" 'insert-monthly-hebrew-diary-entry)
-  (define-key calendar-mode-map "ihy" 'insert-yearly-hebrew-diary-entry)
-  (define-key calendar-mode-map "iid" 'insert-islamic-diary-entry)
-  (define-key calendar-mode-map "iim" 'insert-monthly-islamic-diary-entry)
-  (define-key calendar-mode-map "iiy" 'insert-yearly-islamic-diary-entry)
-  (define-key calendar-mode-map "?"   'calendar-goto-info-node)
-  (define-key calendar-mode-map "tm" 'cal-tex-cursor-month)
-  (define-key calendar-mode-map "tM" 'cal-tex-cursor-month-landscape)
-  (define-key calendar-mode-map "td" 'cal-tex-cursor-day)
-  (define-key calendar-mode-map "tw1" 'cal-tex-cursor-week)
-  (define-key calendar-mode-map "tw2" 'cal-tex-cursor-week2)
-  (define-key calendar-mode-map "tw3" 'cal-tex-cursor-week-iso)
-  (define-key calendar-mode-map "tw4" 'cal-tex-cursor-week-monday)
-  (define-key calendar-mode-map "tfd" 'cal-tex-cursor-filofax-daily)
-  (define-key calendar-mode-map "tfw" 'cal-tex-cursor-filofax-2week)
-  (define-key calendar-mode-map "tfW" 'cal-tex-cursor-filofax-week)
-  (define-key calendar-mode-map "tfy" 'cal-tex-cursor-filofax-year)
-  (define-key calendar-mode-map "ty" 'cal-tex-cursor-year)
-  (define-key calendar-mode-map "tY" 'cal-tex-cursor-year-landscape))
+  (let ((map (make-keymap)))
+    (suppress-keymap map)
+    (dolist (c '(narrow-to-region mark-word mark-sexp mark-paragraph
+                 mark-defun mark-whole-buffer mark-page
+                 downcase-region upcase-region kill-region
+                 copy-region-as-kill capitalize-region write-region))
+      (define-key map (vector 'remap c) 'calendar-not-implemented))
+    (define-key map "<"     'scroll-calendar-right)
+    (define-key map "\C-x<" 'scroll-calendar-right)
+    (define-key map [prior] 'scroll-calendar-right-three-months)
+    (define-key map "\ev"   'scroll-calendar-right-three-months)
+    (define-key map ">"     'scroll-calendar-left)
+    (define-key map "\C-x>" 'scroll-calendar-left)
+    (define-key map [next]  'scroll-calendar-left-three-months)
+    (define-key map "\C-v"  'scroll-calendar-left-three-months)
+    (define-key map "\C-b"  'calendar-backward-day)
+    (define-key map "\C-p"  'calendar-backward-week)
+    (define-key map "\e{"   'calendar-backward-month)
+    (define-key map "\C-x[" 'calendar-backward-year)
+    (define-key map "\C-f"  'calendar-forward-day)
+    (define-key map "\C-n"  'calendar-forward-week)
+    (define-key map [left]  'calendar-backward-day)
+    (define-key map [up]    'calendar-backward-week)
+    (define-key map [right] 'calendar-forward-day)
+    (define-key map [down]  'calendar-forward-week)
+    (define-key map "\e}"   'calendar-forward-month)
+    (define-key map "\C-x]" 'calendar-forward-year)
+    (define-key map "\C-a"  'calendar-beginning-of-week)
+    (define-key map "\C-e"  'calendar-end-of-week)
+    (define-key map "\ea"   'calendar-beginning-of-month)
+    (define-key map "\ee"   'calendar-end-of-month)
+    (define-key map "\e<"   'calendar-beginning-of-year)
+    (define-key map "\e>"   'calendar-end-of-year)
+    (define-key map "\C-@"  'calendar-set-mark)
+    ;; Many people are used to typing C-SPC and getting C-@.
+    (define-key map [?\C- ] 'calendar-set-mark)
+    (define-key map "\C-x\C-x" 'calendar-exchange-point-and-mark)
+    (define-key map "\e=" 'calendar-count-days-region)
+    (define-key map "gd"  'calendar-goto-date)
+    (define-key map "gD"  'calendar-goto-day-of-year)
+    (define-key map "gj"  'calendar-goto-julian-date)
+    (define-key map "ga"  'calendar-goto-astro-day-number)
+    (define-key map "gh"  'calendar-goto-hebrew-date)
+    (define-key map "gi"  'calendar-goto-islamic-date)
+    (define-key map "gb"  'calendar-goto-bahai-date)
+    (define-key map "gC"  'calendar-goto-chinese-date)
+    (define-key map "gk"  'calendar-goto-coptic-date)
+    (define-key map "ge"  'calendar-goto-ethiopic-date)
+    (define-key map "gp"  'calendar-goto-persian-date)
+    (define-key map "gc"  'calendar-goto-iso-date)
+    (define-key map "gw"  'calendar-goto-iso-week)
+    (define-key map "gf"  'calendar-goto-french-date)
+    (define-key map "gml"  'calendar-goto-mayan-long-count-date)
+    (define-key map "gmpc" 'calendar-previous-calendar-round-date)
+    (define-key map "gmnc" 'calendar-next-calendar-round-date)
+    (define-key map "gmph" 'calendar-previous-haab-date)
+    (define-key map "gmnh" 'calendar-next-haab-date)
+    (define-key map "gmpt" 'calendar-previous-tzolkin-date)
+    (define-key map "gmnt" 'calendar-next-tzolkin-date)
+    (define-key map "Aa"   'appt-add)
+    (define-key map "Ad"   'appt-delete)
+    (define-key map "S"   'calendar-sunrise-sunset)
+    (define-key map "M"   'calendar-phases-of-moon)
+    (define-key map " "   'scroll-other-window)
+    (define-key map (kbd "DEL") 'scroll-other-window-down)
+    (define-key map "\C-c\C-l" 'redraw-calendar)
+    (define-key map "."   'calendar-goto-today)
+    (define-key map "o"   'calendar-other-month)
+    (define-key map "q"   'exit-calendar)
+    (define-key map "a"   'list-calendar-holidays)
+    (define-key map "h"   'calendar-cursor-holidays)
+    (define-key map "x"   'mark-calendar-holidays)
+    (define-key map "u"   'calendar-unmark)
+    (define-key map "m"   'mark-diary-entries)
+    (define-key map "d"   'diary-view-entries)
+    (define-key map "D"   'view-other-diary-entries)
+    (define-key map "s"   'diary-show-all-entries)
+    (define-key map "pd"  'calendar-print-day-of-year)
+    (define-key map "pC"  'calendar-print-chinese-date)
+    (define-key map "pk"  'calendar-print-coptic-date)
+    (define-key map "pe"  'calendar-print-ethiopic-date)
+    (define-key map "pp"  'calendar-print-persian-date)
+    (define-key map "pc"  'calendar-print-iso-date)
+    (define-key map "pj"  'calendar-print-julian-date)
+    (define-key map "pa"  'calendar-print-astro-day-number)
+    (define-key map "ph"  'calendar-print-hebrew-date)
+    (define-key map "pi"  'calendar-print-islamic-date)
+    (define-key map "pb"  'calendar-print-bahai-date)
+    (define-key map "pf"  'calendar-print-french-date)
+    (define-key map "pm"  'calendar-print-mayan-date)
+    (define-key map "po"  'calendar-print-other-dates)
+    (define-key map "id"  'insert-diary-entry)
+    (define-key map "iw"  'insert-weekly-diary-entry)
+    (define-key map "im"  'insert-monthly-diary-entry)
+    (define-key map "iy"  'insert-yearly-diary-entry)
+    (define-key map "ia"  'insert-anniversary-diary-entry)
+    (define-key map "ib"  'insert-block-diary-entry)
+    (define-key map "ic"  'insert-cyclic-diary-entry)
+    (define-key map "ihd" 'insert-hebrew-diary-entry)
+    (define-key map "ihm" 'insert-monthly-hebrew-diary-entry)
+    (define-key map "ihy" 'insert-yearly-hebrew-diary-entry)
+    (define-key map "iid" 'insert-islamic-diary-entry)
+    (define-key map "iim" 'insert-monthly-islamic-diary-entry)
+    (define-key map "iiy" 'insert-yearly-islamic-diary-entry)
+    (define-key map "iBd" 'insert-bahai-diary-entry)
+    (define-key map "iBm" 'insert-monthly-bahai-diary-entry)
+    (define-key map "iBy" 'insert-yearly-bahai-diary-entry)
+    (define-key map "?"   'calendar-goto-info-node)
+    (define-key map "Hm" 'cal-html-cursor-month)
+    (define-key map "Hy" 'cal-html-cursor-year)
+    (define-key map "tm" 'cal-tex-cursor-month)
+    (define-key map "tM" 'cal-tex-cursor-month-landscape)
+    (define-key map "td" 'cal-tex-cursor-day)
+    (define-key map "tw1" 'cal-tex-cursor-week)
+    (define-key map "tw2" 'cal-tex-cursor-week2)
+    (define-key map "tw3" 'cal-tex-cursor-week-iso)
+    (define-key map "tw4" 'cal-tex-cursor-week-monday)
+    (define-key map "tfd" 'cal-tex-cursor-filofax-daily)
+    (define-key map "tfw" 'cal-tex-cursor-filofax-2week)
+    (define-key map "tfW" 'cal-tex-cursor-filofax-week)
+    (define-key map "tfy" 'cal-tex-cursor-filofax-year)
+    (define-key map "ty" 'cal-tex-cursor-year)
+    (define-key map "tY" 'cal-tex-cursor-year-landscape)
+    (setq calendar-mode-map map)
+    ;; Require cal-menu after initializing calendar-mode-map because it uses it.
+    (require 'cal-menu)))
 
 (defun describe-calendar-mode ()
-  "Create a help buffer with a brief description of the calendar-mode."
+  "Create a help buffer with a brief description of the `calendar-mode'."
   (interactive)
-  (with-output-to-temp-buffer "*Help*"
+  (help-setup-xref (list #'describe-calendar-mode) (interactive-p))
+  (with-output-to-temp-buffer (help-buffer)
     (princ
      (format
       "Calendar Mode:\nFor a complete description, type %s\n%s\n"
       (substitute-command-keys
        "\\<calendar-mode-map>\\[describe-mode] from within the calendar")
       (substitute-command-keys "\\{calendar-mode-map}")))
-    (save-excursion
-      (set-buffer standard-output)
-      (help-mode))
     (print-help-return-message)))
 
 ;; Calendar mode is suitable only for specially formatted data.
@@ -2037,42 +2353,91 @@ the inserted text.  Value is always t."
 
 (defvar calendar-mode-line-format
   (list
-   (propertize (substitute-command-keys
-               "\\<calendar-mode-map>\\[scroll-calendar-left]")
-              'help-echo "mouse-2: scroll left"
-              'keymap (make-mode-line-mouse-map 'mouse-2
-                                                #'scroll-calendar-left))
+   (propertize "<"
+              'help-echo "mouse-1: previous month"
+              'mouse-face 'mode-line-highlight
+              'keymap (make-mode-line-mouse-map 'mouse-1
+                                                'mouse-scroll-calendar-right))
    "Calendar"
    (concat
     (propertize
      (substitute-command-keys
       "\\<calendar-mode-map>\\[calendar-goto-info-node] info")
-     'help-echo "mouse-2: read Info on Calendar"
-     'keymap (make-mode-line-mouse-map 'mouse-2 'calendar-goto-info-node))
-    "/"
+     'help-echo "mouse-1: read Info on Calendar"
+     'mouse-face 'mode-line-highlight
+     'keymap (make-mode-line-mouse-map 'mouse-1 'calendar-goto-info-node))
+    " / "
     (propertize
      (substitute-command-keys
-     "\\<calendar-mode-map>\\[calendar-other-month] other")
-     'help-echo "mouse-2: choose another month"
+     " \\<calendar-mode-map>\\[calendar-other-month] other")
+     'help-echo "mouse-1: choose another month"
+     'mouse-face 'mode-line-highlight
      'keymap (make-mode-line-mouse-map
-             'mouse-2
-             (lambda ()
-               (interactive)
-               (call-interactively
-                'calendar-other-month))))
-    "/"
+             'mouse-1 'mouse-calendar-other-month))
+    " / "
     (propertize
      (substitute-command-keys
      "\\<calendar-mode-map>\\[calendar-goto-today] today")
-     'help-echo "mouse-2: go to today's date"
-     'keymap (make-mode-line-mouse-map 'mouse-2 #'calendar-goto-today)))
+     'help-echo "mouse-1: go to today's date"
+     'mouse-face 'mode-line-highlight
+     'keymap (make-mode-line-mouse-map 'mouse-1 #'calendar-goto-today)))
    '(calendar-date-string (calendar-current-date) t)
-   (propertize (substitute-command-keys
-               "\\<calendar-mode-map>\\[scroll-calendar-right]")
-              'help-echo "mouse-2: scroll right"
+   (propertize ">"
+              'help-echo "mouse-1: next month"
+              'mouse-face 'mode-line-highlight
               'keymap (make-mode-line-mouse-map
-                       'mouse-2 #'scroll-calendar-right)))
-  "The mode line of the calendar buffer.")
+                       'mouse-1 'mouse-scroll-calendar-left)))
+  "The mode line of the calendar buffer.
+
+This must be a list of items that evaluate to strings--those strings are
+evaluated and concatenated together, evenly separated by blanks.  The variable
+`date' is available for use as the date under (or near) the cursor; `date'
+defaults to the current date if it is otherwise undefined.  Here is an example
+value that has the Hebrew date, the day number/days remaining in the year,
+and the ISO week/year numbers in the mode.  When calendar-move-hook is set to
+'update-calendar-mode-line, these mode line shows these values for the date
+under the cursor:
+
+      (list
+       \"\"
+       '(calendar-hebrew-date-string date)
+       '(let* ((year (extract-calendar-year date))
+               (d (calendar-day-number date))
+               (days-remaining
+                (- (calendar-day-number (list 12 31 year)) d)))
+          (format \"%d/%d\" d days-remaining))
+       '(let* ((d (calendar-absolute-from-gregorian date))
+               (iso-date (calendar-iso-from-absolute d)))
+          (format \"ISO week %d of %d\"
+            (extract-calendar-month iso-date)
+            (extract-calendar-year iso-date)))
+       \"\"))
+")
+
+(defun mouse-scroll-calendar-left (event)
+  "Scroll the displayed calendar left by one month.
+Maintains the relative position of the cursor
+with respect to the calendar as well as possible."
+  (interactive "e")
+  (save-selected-window
+    (select-window (posn-window (event-start event)))
+    (scroll-calendar-left 1)))
+
+(defun mouse-scroll-calendar-right (event)
+  "Scroll the displayed calendar right by one month.
+Maintains the relative position of the cursor
+with respect to the calendar as well as possible."
+  (interactive "e")
+  (save-selected-window
+    (select-window (posn-window (event-start event)))
+    (scroll-calendar-right 1)))
+
+(defun mouse-calendar-other-month (event)
+  "Display a three-month calendar centered around a specified month and year."
+  (interactive "e")
+  (save-selected-window
+    (select-window (posn-window (event-start event)))
+    (call-interactively 'calendar-other-month)))
 
 (defun calendar-goto-info-node ()
   "Go to the info node for the calendar."
@@ -2086,6 +2451,8 @@ the inserted text.  Value is always t."
        (info))
       (Info-find-node (car (car where)) (car (cdr (car where)))))))
 
+
+
 (defun calendar-mode ()
   "A major mode for the calendar window.
 
@@ -2093,7 +2460,6 @@ For a complete description, type \
 \\<calendar-mode-map>\\[calendar-goto-info-node] from within the calendar.
 
 \\<calendar-mode-map>\\{calendar-mode-map}"
-
   (kill-all-local-variables)
   (setq major-mode 'calendar-mode)
   (setq mode-name "Calendar")
@@ -2104,7 +2470,10 @@ For a complete description, type \
   (add-hook 'activate-menubar-hook 'cal-menu-update nil t)
   (make-local-variable 'calendar-mark-ring)
   (make-local-variable 'displayed-month);;  Month in middle of window.
-  (make-local-variable 'displayed-year));;  Year in middle of window.
+  (make-local-variable 'displayed-year)        ;;  Year in middle of window.
+  (set (make-local-variable 'font-lock-defaults)
+       '(calendar-font-lock-keywords t))
+  (run-mode-hooks 'calendar-mode-hook))
 
 (defun calendar-string-spread (strings char length)
   "Concatenate list of STRINGS separated with copies of CHAR to fill LENGTH.
@@ -2124,22 +2493,25 @@ the STRINGS are just concatenated and the result truncated."
          (s (car strings))
          (strings (cdr strings))
          (i 0))
-    (while strings
+    (dolist (string strings)
       (setq s (concat s
                       (make-string (max 0 (/ (+ n i) m)) char)
-                      (car strings)))
-      (setq i (1+ i))
-      (setq strings (cdr strings)))
+                      string))
+      (setq i (1+ i)))
     (substring s 0 length)))
 
 (defun update-calendar-mode-line ()
   "Update the calendar mode line with the current date and date style."
   (if (bufferp (get-buffer calendar-buffer))
-      (save-excursion
-        (set-buffer calendar-buffer)
+      (with-current-buffer calendar-buffer
         (setq mode-line-format
               (calendar-string-spread
-               calendar-mode-line-format ?  (frame-width))))))
+               (let ((date (condition-case nil
+                               (calendar-cursor-to-nearest-date)
+                             (error (calendar-current-date)))))
+                 (mapcar 'eval  calendar-mode-line-format))
+               ?  (frame-width)))
+        (force-mode-line-update))))
 
 (defun calendar-window-list ()
   "List of all calendar-related windows."
@@ -2147,7 +2519,7 @@ the STRINGS are just concatenated and the result truncated."
         list)
     (walk-windows (lambda (w)
                    (if (memq (window-buffer w) calendar-buffers)
-                       (setq list (cons w list))))
+                       (push w list)))
                   nil t)
     list))
 
@@ -2157,15 +2529,12 @@ the STRINGS are just concatenated and the result truncated."
          (buffers (list "*Yahrzeits*" lunar-phases-buffer holiday-buffer
                         fancy-diary-buffer diary-buffer calendar-buffer
                         other-calendars-buffer))
-         (buffer-list nil)
-         b)
-    (while buffers
-      (setq b (car buffers))
+         (buffer-list nil))
+    (dolist (b buffers)
       (setq b (cond ((stringp b) (get-buffer b))
                     ((bufferp b) b)
                     (t nil)))
-      (if b (setq buffer-list (cons b buffer-list)))
-      (setq buffers (cdr buffers)))
+      (if b (push b buffer-list)))
     buffer-list))
 
 (defun exit-calendar ()
@@ -2224,16 +2593,17 @@ ERROR is t, otherwise just returns nil."
           (if (not (looking-at " "))
                    (re-search-backward "[^0-9]"))
           (list month
-                (string-to-int (buffer-substring (1+ (point)) (+ 4 (point))))
+                (string-to-number (buffer-substring (1+ (point)) (+ 4 (point))))
                 year))
-      (if (looking-at "\\*")
-          (save-excursion
-            (re-search-backward "[^*]")
-            (if (looking-at ".\\*\\*")
-                (list month calendar-starred-day year)
-              (if error (error "Not on a date!"))))
+      (if (and (looking-at "\\*")
+               (save-excursion
+                 (re-search-backward "[^*]")
+                 (looking-at ".\\*\\*")))
+          (list month calendar-starred-day year)
         (if error (error "Not on a date!"))))))
 
+(add-to-list 'debug-ignored-errors "Not on a date!")
+
 ;; The following version of calendar-gregorian-from-absolute is preferred for
 ;; reasons of clarity, BUT it's much slower than the version that follows it.
 
@@ -2261,7 +2631,8 @@ ERROR is t, otherwise just returns nil."
 (defun calendar-gregorian-from-absolute (date)
   "Compute the list (month day year) corresponding to the absolute DATE.
 The absolute date is the number of days elapsed since the (imaginary)
-Gregorian date Sunday, December 31, 1 BC."
+Gregorian date Sunday, December 31, 1 BC.  This function does not
+handle dates in years BC."
 ;; See the footnote on page 384 of ``Calendrical Calculations, Part II:
 ;; Three Historical Calendars'' by E. M. Reingold,  N. Dershowitz, and S. M.
 ;; Clamen, Software--Practice and Experience, Volume 23, Number 4
@@ -2309,7 +2680,7 @@ With argument, jump to mark, pop it, and put point at end of ring."
   (let ((date (calendar-cursor-to-date t)))
     (if (null arg)
         (progn
-          (setq calendar-mark-ring (cons date calendar-mark-ring))
+          (push date calendar-mark-ring)
           ;; Since the top of the mark ring is the marked date in the
           ;; calendar, the mark ring in the calendar is one longer than
           ;; in other buffers to get the same effect.
@@ -2372,12 +2743,12 @@ If optional NODAY is t, does not ask for day, but just returns
                                 (calendar-current-date)))))
          (month-array calendar-month-name-array)
          (completion-ignore-case t)
-         (month (cdr (assoc-ignore-case
+         (month (cdr (assoc-string
                        (completing-read
                         "Month name: "
                         (mapcar 'list (append month-array nil))
                         nil t)
-                      (calendar-make-alist month-array 1))))
+                      (calendar-make-alist month-array 1) t)))
          (last (calendar-last-day-of-month month year)))
     (if noday
         (if (eq noday t)
@@ -2389,59 +2760,145 @@ If optional NODAY is t, does not ask for day, but just returns
             year))))
 
 (defun calendar-interval (mon1 yr1 mon2 yr2)
-  "The number of months difference between MON1, YR1 and MON2, YR2."
+  "The number of months difference between MON1, YR1 and MON2, YR2.
+The result is positive if the second date is later than the first.
+Negative years are interpreted as years BC; -1 being 1 BC, and so on."
+  (if (< yr1 0) (setq yr1 (1+ yr1)))      ; -1 BC -> 0 AD, etc
+  (if (< yr2 0) (setq yr2 (1+ yr2)))
   (+ (* 12 (- yr2 yr1))
      (- mon2 mon1)))
 
-(defun calendar-day-name (date &optional width absolute)
-  "Return a string with the name of the day of the week of DATE.
-If WIDTH is non-nil, return just the first WIDTH characters of the name.
-If ABSOLUTE is non-nil, then DATE is actually the day-of-the-week
-rather than a date."
-  (let ((string (aref calendar-day-name-array
-                     (if absolute date (calendar-day-of-week date)))))
-    (cond ((null width) string)
-         (enable-multibyte-characters (truncate-string-to-width string width))
-         (t (substring string 0 width)))))
+(defvar calendar-abbrev-length 3
+  "*Length of abbreviations to be used for day and month names.
+See also `calendar-day-abbrev-array' and `calendar-month-abbrev-array'.")
 
 (defvar calendar-day-name-array
   ["Sunday" "Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday"]
-  "Array of capitalized strings giving, in order, the day names.")
+  "*Array of capitalized strings giving, in order, the day names.
+The first two characters of each string will be used to head the
+day columns in the calendar.  See also the variable
+`calendar-day-abbrev-array'.")
+
+(defvar calendar-day-abbrev-array
+  [nil nil nil nil nil nil nil]
+  "*Array of capitalized strings giving the abbreviated day names.
+The order should be the same as that of the full names specified
+in `calendar-day-name-array'.  These abbreviations may be used
+instead of the full names in the diary file.  Do not include a
+trailing `.' in the strings specified in this variable, though
+you may use such in the diary file.  If any element of this array
+is nil, then the abbreviation will be constructed as the first
+`calendar-abbrev-length' characters of the corresponding full name.")
 
 (defvar calendar-month-name-array
   ["January" "February" "March"     "April"   "May"      "June"
    "July"    "August"   "September" "October" "November" "December"]
-  "Array of capitalized strings giving, in order, the month names.")
-
-(defun calendar-make-alist (sequence &optional start-index filter)
+  "*Array of capitalized strings giving, in order, the month names.
+See also the variable `calendar-month-abbrev-array'.")
+
+(defvar calendar-month-abbrev-array
+  [nil nil nil nil nil nil nil nil nil nil nil nil]
+ "*Array of capitalized strings giving the abbreviated month names.
+The order should be the same as that of the full names specified
+in `calendar-month-name-array'.  These abbreviations are used in
+the calendar menu entries, and can also be used in the diary
+file.  Do not include a trailing `.' in the strings specified in
+this variable, though you may use such in the diary file.  If any
+element of this array is nil, then the abbreviation will be
+constructed as the first `calendar-abbrev-length' characters of the
+corresponding full name.")
+
+(defun calendar-abbrev-construct (abbrev full &optional period)
+  "Internal calendar function to return a complete abbreviation array.
+ABBREV is an array of abbreviations, FULL the corresponding array
+of full names.  The return value is the ABBREV array, with any nil
+elements replaced by the first three characters taken from the
+corresponding element of FULL.  If optional argument PERIOD is non-nil,
+each element returned has a final `.' character."
+  (let (elem array name)
+    (dotimes (i (length full))
+      (setq name (aref full i)
+            elem (or (aref abbrev i)
+                     (substring name 0
+                                (min calendar-abbrev-length (length name))))
+            elem (format "%s%s" elem (if period "." ""))
+            array (append array (list elem))))
+    (vconcat array)))
+
+(defvar calendar-font-lock-keywords
+  `((,(concat (regexp-opt (mapcar 'identity calendar-month-name-array) t)
+             " -?[0-9]+")
+     . font-lock-function-name-face) ; month and year
+    (,(regexp-opt
+       (list (substring (aref calendar-day-name-array 6) 0 2)
+            (substring (aref calendar-day-name-array 0) 0 2)))
+     ;; Saturdays and Sundays are hilited differently.
+     . font-lock-comment-face)
+    ;; First two chars of each day are used in the calendar.
+    (,(regexp-opt (mapcar (lambda (x) (substring x 0 2)) calendar-day-name-array))
+     . font-lock-reference-face))
+  "Default keywords to highlight in Calendar mode.")
+
+(defun calendar-day-name (date &optional abbrev absolute)
+  "Return a string with the name of the day of the week of DATE.
+DATE should be a list in the format (MONTH DAY YEAR), unless the
+optional argument ABSOLUTE is non-nil, in which case DATE should
+be an integer in the range 0 to 6 corresponding to the day of the
+week.  Day names are taken from the variable `calendar-day-name-array',
+unless the optional argument ABBREV is non-nil, in which case
+the variable `calendar-day-abbrev-array' is used."
+  (aref (if abbrev
+            (calendar-abbrev-construct calendar-day-abbrev-array
+                                       calendar-day-name-array)
+          calendar-day-name-array)
+        (if absolute date (calendar-day-of-week date))))
+
+(defun calendar-make-alist (sequence &optional start-index filter abbrevs)
   "Make an assoc list corresponding to SEQUENCE.
-Start at index 1, unless optional START-INDEX is provided.
-If FILTER is provided, apply it to each item in the list."
-  (let ((index (if start-index (1- start-index) 0)))
-    (mapcar
-     (lambda (x)
-        (setq index (1+ index))
-        (cons (if filter (funcall filter x) x)
-              index))
-     (append sequence nil))))
-
-(defun calendar-month-name (month &optional width)
-  "The name of MONTH.
-If WIDTH is non-nil, return just the first WIDTH characters of the name."
-  (let ((string (aref calendar-month-name-array (1- month))))
-    (if width
-       (let ((i 0) (result "") (pos 0))
-         (while (< i width)
-           (let ((chartext (char-to-string (aref string pos))))
-             (setq pos (+ pos (length chartext)))
-             (setq result (concat result chartext)))
-           (setq i (1+ i)))
-         result)
-      string)))
+Each element of sequence will be associated with an integer, starting
+from 1, or from START-INDEX if that is non-nil.  If a sequence ABBREVS
+is supplied, the function `calendar-abbrev-construct' is used to
+construct abbreviations corresponding to the elements in SEQUENCE.
+Each abbreviation is entered into the alist with the same
+association index as the full name it represents.
+If FILTER is provided, apply it to each key in the alist."
+  (let ((index 0)
+        (offset (or start-index 1))
+        (aseq (if abbrevs (calendar-abbrev-construct abbrevs sequence)))
+        (aseqp (if abbrevs (calendar-abbrev-construct abbrevs sequence
+                                                      'period)))
+        alist elem)
+    (dotimes (i (length sequence) (reverse alist))
+      (setq index (+ i offset)
+            elem (elt sequence i)
+            alist
+            (cons (cons (if filter (funcall filter elem) elem) index) alist))
+      (if aseq
+          (setq elem (elt aseq i)
+                alist (cons (cons (if filter (funcall filter elem) elem)
+                                  index) alist)))
+      (if aseqp
+          (setq elem (elt aseqp i)
+                alist (cons (cons (if filter (funcall filter elem) elem)
+                                  index) alist))))))
+
+(defun calendar-month-name (month &optional abbrev)
+  "Return a string with the name of month number MONTH.
+Months are numbered from one.  Month names are taken from the
+variable `calendar-month-name-array', unless the optional
+argument ABBREV is non-nil, in which case
+`calendar-month-abbrev-array' is used."
+  (aref (if abbrev
+            (calendar-abbrev-construct calendar-month-abbrev-array
+                                       calendar-month-name-array)
+          calendar-month-name-array)
+        (1- month)))
 
 (defun calendar-day-of-week (date)
-  "Return the day-of-the-week index of DATE, 0 for Sunday, 1 for Monday, etc."
-  (% (calendar-absolute-from-gregorian date) 7))
+  "Return the day-of-the-week index of DATE, 0 for Sunday, 1 for Monday, etc.
+DATE is a list of the form (month day year).  A negative year is
+interpreted as BC; -1 being 1 BC, and so on."
+  (mod (calendar-absolute-from-gregorian date) 7))
 
 (defun calendar-unmark ()
   "Delete all diary/holiday marks/highlighting from the calendar."
@@ -2451,19 +2908,26 @@ If WIDTH is non-nil, return just the first WIDTH characters of the name."
   (redraw-calendar))
 
 (defun calendar-date-is-visible-p (date)
-  "Return t if DATE is legal and is visible in the calendar window."
+  "Return t if DATE is valid and is visible in the calendar window."
   (let ((gap (calendar-interval
               displayed-month displayed-year
               (extract-calendar-month date) (extract-calendar-year date))))
     (and (calendar-date-is-legal-p date) (> 2 gap) (< -2 gap))))
 
 (defun calendar-date-is-legal-p (date)
-  "Return t if DATE is a legal date."
+  "Return t if DATE is a valid date."
   (let ((month (extract-calendar-month date))
         (day (extract-calendar-day date))
         (year (extract-calendar-year date)))
     (and (<= 1 month) (<= month 12)
-         (<= 1 day) (<= day (calendar-last-day-of-month month year))
+         ;; (calendar-read-date t) returns a date with day = nil.
+         ;; Should not be valid (?), since many funcs prob assume integer.
+         ;; (calendar-read-date 'noday) returns (month year), which
+         ;; currently results in extract-calendar-year returning nil.
+         day year (<= 1 day) (<= day (calendar-last-day-of-month month year))
+         ;; BC dates left as non-valid, to suppress errors from
+         ;; complex holiday algorithms not suitable for years BC.
+         ;; Note there are side effects on calendar navigation.
          (<= 1 year))))
 
 (defun calendar-date-equal (date1 date2)
@@ -2475,40 +2939,74 @@ If WIDTH is non-nil, return just the first WIDTH characters of the name."
 
 (defun mark-visible-calendar-date (date &optional mark)
   "Mark DATE in the calendar window with MARK.
-MARK is either a single-character string or a face.
-MARK defaults to diary-entry-marker."
+MARK is a single-character string, a list of face attributes/values, or a face.
+MARK defaults to `diary-entry-marker'."
   (if (calendar-date-is-legal-p date)
-      (save-excursion
-        (set-buffer calendar-buffer)
-        (calendar-cursor-to-visible-date date)
-        (let ((mark (or mark diary-entry-marker)))
-          (if (stringp mark)
-              (let ((buffer-read-only nil))
-                (forward-char 1)
-                (delete-char 1)
-                (insert mark)
-                (forward-char -2))
-           (overlay-put
-             (make-overlay (1- (point)) (1+ (point))) 'face mark))))))
+      (with-current-buffer calendar-buffer
+        (save-excursion
+          (calendar-cursor-to-visible-date date)
+          (setq mark
+                (or (and (stringp mark) (= (length mark) 1) mark) ; single-char
+                    (and (listp mark) (> (length mark) 0) mark)   ; attr list
+                    (and (facep mark) mark)                       ; face-name
+                    diary-entry-marker))
+          (cond
+           ;; face or an attr-list that contained a face
+           ((facep mark)
+            (overlay-put
+             (make-overlay (1- (point)) (1+ (point))) 'face mark))
+           ;; single-char
+           ((and (stringp mark) (= (length mark) 1))
+            (let ((inhibit-read-only t))
+              (forward-char 1)
+              ;; Insert before delete so as to better preserve markers.
+              (insert mark)
+              (delete-char 1)
+              (forward-char -2)))
+           (t ;; attr list
+            (let ((temp-face
+                   (make-symbol
+                    (apply 'concat "temp-"
+                           (mapcar (lambda (sym)
+                                     (cond
+                                      ((symbolp sym) (symbol-name sym))
+                                      ((numberp sym) (number-to-string sym))
+                                      (t sym)))
+                                   mark))))
+                  (faceinfo mark))
+              (make-face temp-face)
+              ;; Remove :face info from the mark, copy the face info into
+              ;; temp-face
+              (while (setq faceinfo (memq :face faceinfo))
+                (copy-face (read (nth 1 faceinfo)) temp-face)
+                (setcar faceinfo nil)
+                (setcar (cdr faceinfo) nil))
+              (setq mark (delq nil mark))
+              ;; Apply the font aspects
+              (apply 'set-face-attribute temp-face nil mark)
+              (overlay-put
+               (make-overlay (1- (point)) (1+ (point))) 'face temp-face))))))))
 
 (defun calendar-star-date ()
   "Replace the date under the cursor in the calendar window with asterisks.
 This function can be used with the `today-visible-calendar-hook' run after the
 calendar window has been prepared."
-  (let ((inhibit-read-only t))
-    (make-local-variable 'calendar-starred-day)
+  (let ((inhibit-read-only t)
+        (modified (buffer-modified-p)))
     (forward-char 1)
-    (setq calendar-starred-day
-          (string-to-int
-           (buffer-substring (point) (- (point) 2))))
-    (delete-char -2)
+    (set (make-local-variable 'calendar-starred-day)
+         (string-to-number
+          (buffer-substring (point) (- (point) 2))))
+    ;; Insert before deleting, to better preserve markers.
     (insert "**")
-    (backward-char 1)
-    (set-buffer-modified-p nil)))
+    (forward-char -2)
+    (delete-char -2)
+    (forward-char 1)
+    (restore-buffer-modified-p modified)))
 
 (defun calendar-mark-today ()
   "Mark the date under the cursor in the calendar window.
-The date is marked with calendar-today-marker.  This function can be used with
+The date is marked with `calendar-today-marker'.  This function can be used with
 the `today-visible-calendar-hook' run after the calendar window has been
 prepared."
   (mark-visible-calendar-date
@@ -2523,20 +3021,16 @@ The actual dates are in the car of DATE1 and DATE2."
 
 (defun calendar-date-string (date &optional abbreviate nodayname)
   "A string form of DATE, driven by the variable `calendar-date-display-form'.
-An optional parameter ABBREVIATE, when t, causes the month and day names to be
-abbreviated to three characters.  An optional parameter NODAYNAME, when t,
-omits the name of the day of the week."
+An optional parameter ABBREVIATE, when non-nil, causes the month
+and day names to be abbreviated as specified by
+`calendar-month-abbrev-array' and `calendar-day-abbrev-array',
+respectively.  An optional parameter NODAYNAME, when t, omits the
+name of the day of the week."
   (let* ((dayname
-          (if nodayname
-              nil
-            (if abbreviate
-                (calendar-day-name date 3)
-              (calendar-day-name date))))
+          (unless nodayname
+            (calendar-day-name date abbreviate)))
          (month (extract-calendar-month date))
-         (monthname
-          (if abbreviate
-              (calendar-month-name month 3)
-            (calendar-month-name month)))
+         (monthname (calendar-month-name month abbreviate))
          (day (int-to-string (extract-calendar-day date)))
          (month (int-to-string month))
          (year (int-to-string (extract-calendar-year date))))
@@ -2597,47 +3091,49 @@ Defaults to today's date if DATE is not given."
   "Show dates on other calendars for date under the cursor."
   (interactive)
   (let* ((date (calendar-cursor-to-date t)))
-    (save-excursion
-      (set-buffer (get-buffer-create other-calendars-buffer))
-      (setq buffer-read-only nil)
-      (calendar-set-mode-line
-       (concat (calendar-date-string date) " (Gregorian)"))
-      (erase-buffer)
-      (insert
-       (mapconcat 'identity
-                  (list (calendar-day-of-year-string date)
-                        (format "ISO date: %s" (calendar-iso-date-string date))
-                        (format "Julian date: %s"
-                                (calendar-julian-date-string date))
-                        (format
-                         "Astronomical (Julian) day number (at noon UTC): %s.0"
-                         (calendar-astro-date-string date))
-                        (format "Fixed (RD) date: %s"
-                                (calendar-absolute-from-gregorian date))
-                        (format "Hebrew date (before sunset): %s"
-                                (calendar-hebrew-date-string date))
-                        (format "Persian date: %s"
-                                (calendar-persian-date-string date))
-                        (let ((i (calendar-islamic-date-string date)))
-                          (if (not (string-equal i ""))
-                              (format "Islamic date (before sunset): %s" i)))
-                        (format "Chinese date: %s"
-                                (calendar-chinese-date-string date))
-                        (let ((c (calendar-coptic-date-string date)))
-                          (if (not (string-equal c ""))
-                              (format "Coptic date: %s" c)))
-                        (let ((e (calendar-ethiopic-date-string date)))
-                          (if (not (string-equal e ""))
-                              (format "Ethiopic date: %s" e)))
-                        (let ((f (calendar-french-date-string date)))
-                          (if (not (string-equal f ""))
-                              (format "French Revolutionary date: %s" f)))
-                        (format "Mayan date: %s"
-                                (calendar-mayan-date-string date)))
-                  "\n"))
-      (goto-char (point-min))
-      (set-buffer-modified-p nil)
-      (setq buffer-read-only t)
+    (with-current-buffer (get-buffer-create other-calendars-buffer)
+      (let ((inhibit-read-only t)
+            (modified (buffer-modified-p)))
+        (calendar-set-mode-line
+         (concat (calendar-date-string date) " (Gregorian)"))
+        (erase-buffer)
+        (apply
+         'insert
+         (delq nil
+               (list
+                (calendar-day-of-year-string date) "\n"
+                (format "ISO date: %s\n" (calendar-iso-date-string date))
+                (format "Julian date: %s\n"
+                        (calendar-julian-date-string date))
+                (format "Astronomical (Julian) day number (at noon UTC): %s.0\n"
+                        (calendar-astro-date-string date))
+                (format "Fixed (RD) date: %s\n"
+                        (calendar-absolute-from-gregorian date))
+                (format "Hebrew date (before sunset): %s\n"
+                        (calendar-hebrew-date-string date))
+                (format "Persian date: %s\n"
+                        (calendar-persian-date-string date))
+                (let ((i (calendar-islamic-date-string date)))
+                  (if (not (string-equal i ""))
+                      (format "Islamic date (before sunset): %s\n" i)))
+                (let ((b (calendar-bahai-date-string date)))
+                  (if (not (string-equal b ""))
+                      (format "Baha'i date (before sunset): %s\n" b)))
+                (format "Chinese date: %s\n"
+                        (calendar-chinese-date-string date))
+                (let ((c (calendar-coptic-date-string date)))
+                  (if (not (string-equal c ""))
+                      (format "Coptic date: %s\n" c)))
+                (let ((e (calendar-ethiopic-date-string date)))
+                  (if (not (string-equal e ""))
+                      (format "Ethiopic date: %s\n" e)))
+                (let ((f (calendar-french-date-string date)))
+                  (if (not (string-equal f ""))
+                      (format "French Revolutionary date: %s\n" f)))
+                (format "Mayan date: %s\n"
+                        (calendar-mayan-date-string date)))))
+        (goto-char (point-min))
+        (restore-buffer-modified-p modified))
       (display-buffer other-calendars-buffer))))
 
 (defun calendar-print-day-of-year ()
@@ -2647,8 +3143,15 @@ Defaults to today's date if DATE is not given."
 
 (defun calendar-set-mode-line (str)
   "Set mode line to STR, centered, surrounded by dashes."
-  (setq mode-line-format
-        (calendar-string-spread (list str) ?- (frame-width))))
+  (let* ((edges (window-edges))
+         ;; As per doc of window-width, total visible mode-line length.
+         (width (- (nth 2 edges) (nth 0 edges))))
+    (setq mode-line-format
+          (if buffer-file-name
+              `("-" mode-line-modified
+                ,(calendar-string-spread (list str) ?- (- width 6))
+                "---")
+            (calendar-string-spread (list str) ?- width)))))
 
 (defun calendar-mod (m n)
   "Non-negative remainder of M/N with N instead of 0."
@@ -2658,8 +3161,9 @@ Defaults to today's date if DATE is not given."
 
 (provide 'calendar)
 
-;;; Local variables:
-;;; byte-compile-dynamic: t
-;;; End:
+;; Local variables:
+;; byte-compile-dynamic: t
+;; End:
 
+;; arch-tag: 19c61596-c8fb-4c69-bcf1-7dd739919cd8
 ;;; calendar.el ends here