(query-replace-read-from): Use
[bpt/emacs.git] / lisp / calendar / calendar.el
CommitLineData
3afbc435 1;;; calendar.el --- calendar functions
fd7fa35a 2
f059e122 3;; Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1997,
1293540e 4;; 2000, 2001, 2003, 2004 Free Software Foundation, Inc.
3a801d0c 5
fd7fa35a 6;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
e9571d2a 7;; Keywords: calendar
3076647c 8;; Human-Keywords: calendar, Gregorian calendar, diary, holidays
fd7fa35a 9
ecaa0527
RS
10;; This file is part of GNU Emacs.
11
e555fdd8
RS
12;; GNU Emacs is free software; you can redistribute it and/or modify
13;; it under the terms of the GNU General Public License as published by
14;; the Free Software Foundation; either version 2, or (at your option)
15;; any later version.
16
ecaa0527 17;; GNU Emacs is distributed in the hope that it will be useful,
e555fdd8
RS
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
b578f267
EN
23;; along with GNU Emacs; see the file COPYING. If not, write to the
24;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25;; Boston, MA 02111-1307, USA.
ecaa0527 26
fd7fa35a
ER
27;;; Commentary:
28
811a8484
JW
29;; This collection of functions implements a calendar window. It
30;; generates a calendar for the current month, together with the
31;; previous and coming months, or for any other three-month period.
32;; The calendar can be scrolled forward and backward in the window to
33;; show months in the past or future; the cursor can move forward and
34;; backward by days, weeks, or months, making it possible, for
35;; instance, to jump to the date a specified number of days, weeks, or
36;; months from the date under the cursor. The user can display a list
37;; of holidays and other notable days for the period shown; the
38;; notable days can be marked on the calendar, if desired. The user
39;; can also specify that dates having corresponding diary entries (in
40;; a file that the user specifies) be marked; the diary entries for
41;; any date can be viewed in a separate window. The diary and the
42;; notable days can be viewed independently of the calendar. Dates
43;; can be translated from the (usual) Gregorian calendar to the day of
44;; the year/days remaining in year, to the ISO commercial calendar, to
45;; the Julian (old style) calendar, to the Hebrew calendar, to the
46;; Islamic calendar, to the Baha'i calendar, to the French
47;; Revolutionary calendar, to the Mayan calendar, to the Chinese
48;; calendar, to the Coptic calendar, to the Ethiopic calendar, and to
49;; the astronomical (Julian) day number. When floating point is
50;; available, times of sunrise/sunset can be displayed, as can the
51;; phases of the moon. Appointment notification for diary entries is
3076647c 52;; available. Calendar printing via LaTeX is available.
7e1dae73
JB
53
54;; The following files are part of the calendar/diary code:
55
3076647c 56;; appt.el Appointment notification
327b6868 57;; cal-china.el Chinese calendar
3076647c
ER
58;; cal-coptic.el Coptic/Ethiopic calendars
59;; cal-dst.el Daylight savings time rules
60;; cal-hebrew.el Hebrew calendar
327b6868 61;; cal-islam.el Islamic calendar
811a8484 62;; cal-bahai.el Baha'i calendar
3076647c
ER
63;; cal-iso.el ISO calendar
64;; cal-julian.el Julian/astronomical calendars
65;; cal-mayan.el Mayan calendars
6a2aa94c 66;; cal-menu.el Menu support
7086b78e 67;; cal-move.el Movement in the calendar
a45eee72 68;; cal-persia.el Persian calendar
3076647c 69;; cal-tex.el Calendars in LaTeX
bcbb4a0a 70;; cal-x.el X-windows dedicated frame functions
f5e13137 71;; diary-lib.el Diary functions
7e1dae73 72;; holidays.el Holiday functions
7e1dae73 73;; lunar.el Phases of the moon
3076647c 74;; solar.el Sunrise/sunset, equinoxes/solstices
ecaa0527 75
ecaa0527 76;; Technical details of all the calendrical calculations can be found in
a96a5fca
PE
77;; ``Calendrical Calculations'' by Nachum Dershowitz and Edward M. Reingold,
78;; Cambridge University Press (1997).
7e1dae73 79
a96a5fca 80;; An earlier version of the technical details appeared in
ecaa0527
RS
81;; ``Calendrical Calculations'' by Nachum Dershowitz and Edward M. Reingold,
82;; Software--Practice and Experience, Volume 20, Number 9 (September, 1990),
7e1dae73
JB
83;; pages 899-928. ``Calendrical Calculations, Part II: Three Historical
84;; Calendars'' by E. M. Reingold, N. Dershowitz, and S. M. Clamen,
e4c61e50
JB
85;; Software--Practice and Experience, Volume 23, Number 4 (April, 1993),
86;; pages 383-404.
7e1dae73
JB
87
88;; Hard copies of these two papers can be obtained by sending email to
89;; reingold@cs.uiuc.edu with the SUBJECT "send-paper-cal" (no quotes) and
90;; the message BODY containing your mailing address (snail).
ecaa0527 91
a96a5fca
PE
92;; Comments, corrections, and improvements should be sent to
93;; Edward M. Reingold Department of Computer Science
94;; (217) 333-6733 University of Illinois at Urbana-Champaign
95;; reingold@cs.uiuc.edu 1304 West Springfield Avenue
96;; Urbana, Illinois 61801
97
fd7fa35a 98;;; Code:
ecaa0527 99
f059e122 100(eval-when-compile
d4ff5db9
DL
101 (defvar displayed-month)
102 (defvar displayed-year)
103 (defvar calendar-month-name-array)
104 (defvar calendar-starred-day))
105
e555fdd8
RS
106(defun calendar-version ()
107 (interactive)
3076647c 108 (message "Version 6, October 12, 1995"))
e555fdd8 109
b032077a
RS
110(defgroup calendar nil
111 "Calendar and time management support."
112 :group 'applications)
113
114(defgroup diary nil
115 "Emacs diary."
116 :group 'calendar)
117
118(defgroup appt nil
119 "Appointment notification."
120 :group 'calendar)
121
122(defgroup holidays nil
123 "Holidays support in calendar."
124 :group 'calendar
125 :prefix "calendar-"
126 :group 'local)
127
128(defgroup chinese-calendar nil
129 "Chinese calendar support."
130 :group 'calendar)
131
132(defgroup calendar-tex nil
133 "Options for printing calendar with LaTeX."
134 :prefix "cal-tex-"
135 :group 'calendar)
136
137(defgroup calendar-hooks nil
138 "Calendar hooks."
139 :prefix "calendar-"
140 :group 'calendar)
141
142
d8a200a7 143;;;###autoload
b032077a 144(defcustom calendar-week-start-day 0
d8a200a7 145 "*The day of the week on which a week in the calendar begins.
b032077a
RS
1460 means Sunday (default), 1 means Monday, and so on."
147 :type 'integer
148 :group 'calendar)
d8a200a7 149
cba0c253 150;;;###autoload
b032077a 151(defcustom calendar-offset 0
cba0c253
ER
152 "*The offset of the principal month from the center of the calendar window.
1530 means the principal month is in the center (default), -1 means on the left,
154+1 means on the right. Larger (or smaller) values push the principal month off
b032077a
RS
155the screen."
156 :type 'integer
157 :group 'calendar)
cba0c253 158
7e1dae73 159;;;###autoload
b032077a 160(defcustom view-diary-entries-initially nil
1293540e 161 "*Non-nil means display current date's diary entries on entry to calendar.
ecaa0527
RS
162The diary is displayed in another window when the calendar is first displayed,
163if the current date is visible. The number of days of diary entries displayed
1293540e
GM
164is governed by the variable `number-of-diary-entries'. This variable can
165be overridden by the value of `calendar-setup'."
b032077a
RS
166 :type 'boolean
167 :group 'diary)
ecaa0527 168
7e1dae73 169;;;###autoload
b032077a 170(defcustom number-of-diary-entries 1
ecaa0527 171 "*Specifies how many days of diary entries are to be displayed initially.
3cbb4860 172This variable affects the diary display when the command \\[diary] is used,
ecaa0527
RS
173or if the value of the variable `view-diary-entries-initially' is t. For
174example, if the default value 1 is used, then only the current day's diary
175entries will be displayed. If the value 2 is used, then both the current
e555fdd8
RS
176day's and the next day's entries will be displayed.
177
178The value can also be a vector such as [0 2 2 2 2 4 1]; this value
179says to display no diary entries on Sunday, the display the entries
180for the current date and the day after on Monday through Thursday,
181display Friday through Monday's entries on Friday, and display only
182Saturday's entries on Saturday.
183
184This variable does not affect the diary display with the `d' command
185from the calendar; in that case, the prefix argument controls the
b032077a
RS
186number of days of diary entries displayed."
187 :type '(choice (integer :tag "Entries")
188 (vector :value [0 0 0 0 0 0 0]
189 (integer :tag "Sunday")
190 (integer :tag "Monday")
191 (integer :tag "Tuesday")
192 (integer :tag "Wednesday")
193 (integer :tag "Thursday")
194 (integer :tag "Friday")
195 (integer :tag "Saturday")))
196 :group 'diary)
ecaa0527 197
7e1dae73 198;;;###autoload
b032077a 199(defcustom mark-diary-entries-in-calendar nil
e555fdd8 200 "*Non-nil means mark dates with diary entries, in the calendar window.
b032077a
RS
201The marking symbol is specified by the variable `diary-entry-marker'."
202 :type 'boolean
203 :group 'diary)
ecaa0527 204
7e1e5cf1
SS
205;;;###autoload
206(defcustom calendar-remove-frame-by-deleting nil
207 "*Determine how the calendar mode removes a frame no longer needed.
208If nil, make an icon of the frame. If non-nil, delete the frame."
209 :type 'boolean
210 :group 'view)
211
5d22135b
MR
212(defvar diary-face 'diary-face
213 "Face name to use for diary entries.")
9c887ada
MB
214(defface diary-face
215 '((((class color) (background light))
42121c23 216 :foreground "red")
9c887ada 217 (((class color) (background dark))
42121c23 218 :foreground "yellow")
9c887ada 219 (t
1fd714a4 220 :weight bold))
9c887ada
MB
221 "Face for highlighting diary entries."
222 :group 'diary)
223
9c887ada
MB
224(defface calendar-today-face
225 '((t (:underline t)))
226 "Face for indicating today's date."
227 :group 'diary)
228
9c887ada
MB
229(defface holiday-face
230 '((((class color) (background light))
42121c23 231 :background "pink")
9c887ada 232 (((class color) (background dark))
42121c23 233 :background "chocolate4")
9c887ada 234 (t
42121c23 235 :inverse-video t))
9c887ada
MB
236 "Face for indicating dates that have holidays."
237 :group 'diary)
a69e7dae 238
f5f57411
SM
239(eval-after-load "facemenu"
240 '(progn
241 (add-to-list 'facemenu-unlisted-faces 'diary-face)
242 (add-to-list 'facemenu-unlisted-faces 'calendar-today-face)
243 (add-to-list 'facemenu-unlisted-faces 'holiday-face)))
244
b032077a 245(defcustom diary-entry-marker
13f0f988 246 (if (not (display-color-p))
6a2aa94c 247 "+"
6a2aa94c 248 'diary-face)
a69e7dae
RS
249 "*How to mark dates that have diary entries.
250The value can be either a single-character string or a face."
b032077a
RS
251 :type '(choice string face)
252 :group 'diary)
6a2aa94c 253
b032077a 254(defcustom calendar-today-marker
13f0f988 255 (if (not (display-color-p))
6a2aa94c 256 "="
6a2aa94c 257 'calendar-today-face)
a69e7dae
RS
258 "*How to mark today's date in the calendar.
259The value can be either a single-character string or a face.
260Marking today's date is done only if you set up `today-visible-calendar-hook'
261to request that."
b032077a
RS
262 :type '(choice string face)
263 :group 'calendar)
6a2aa94c 264
b032077a 265(defcustom calendar-holiday-marker
13f0f988 266 (if (not (display-color-p))
6a2aa94c 267 "*"
6a2aa94c 268 'holiday-face)
a69e7dae
RS
269 "*How to mark notable dates in the calendar.
270The value can be either a single-character string or a face."
b032077a
RS
271 :type '(choice string face)
272 :group 'calendar)
ecaa0527 273
7e1dae73 274;;;###autoload
b032077a 275(defcustom view-calendar-holidays-initially nil
e555fdd8 276 "*Non-nil means display holidays for current three month period on entry.
354d0644 277The holidays are displayed in another window when the calendar is first
b032077a
RS
278displayed."
279 :type 'boolean
280 :group 'holidays)
ecaa0527 281
e5d77022 282;;;###autoload
b032077a 283(defcustom mark-holidays-in-calendar nil
e555fdd8 284 "*Non-nil means mark dates of holidays in the calendar window.
b032077a
RS
285The marking symbol is specified by the variable `calendar-holiday-marker'."
286 :type 'boolean
287 :group 'holidays)
ecaa0527 288
e5d77022 289;;;###autoload
b032077a 290(defcustom all-hebrew-calendar-holidays nil
354d0644 291 "*If nil, show only major holidays from the Hebrew calendar.
e555fdd8 292This means only those Jewish holidays that appear on secular calendars.
354d0644 293
b032077a
RS
294If t, show all the holidays that would appear in a complete Hebrew calendar."
295 :type 'boolean
296 :group 'holidays)
ecaa0527 297
e5d77022 298;;;###autoload
b032077a 299(defcustom all-christian-calendar-holidays nil
354d0644 300 "*If nil, show only major holidays from the Christian calendar.
e555fdd8 301This means only those Christian holidays that appear on secular calendars.
354d0644 302
e555fdd8 303If t, show all the holidays that would appear in a complete Christian
b032077a
RS
304calendar."
305 :type 'boolean
306 :group 'holidays)
ecaa0527 307
e5d77022 308;;;###autoload
b032077a 309(defcustom all-islamic-calendar-holidays nil
354d0644 310 "*If nil, show only major holidays from the Islamic calendar.
e555fdd8 311This means only those Islamic holidays that appear on secular calendars.
354d0644 312
e555fdd8 313If t, show all the holidays that would appear in a complete Islamic
b032077a
RS
314calendar."
315 :type 'boolean
316 :group 'holidays)
ecaa0527 317
d13c1378
JB
318(defcustom diary-file-name-prefix-function (function (lambda (str) str))
319 "*The function that will take a diary file name and return the desired prefix."
808052d6 320 :type 'function
d13c1378
JB
321 :group 'diary)
322
811a8484
JW
323;;;###autoload
324(defcustom all-bahai-calendar-holidays nil
325 "*If nil, show only major holidays from the Baha'i calendar.
326These are the days on which work and school must be suspended.
327
328If t, show all the holidays that would appear in a complete Baha'i
329calendar."
330 :type 'boolean
331 :group 'holidays)
332
7e1dae73 333;;;###autoload
b032077a 334(defcustom calendar-load-hook nil
7e1dae73 335 "*List of functions to be called after the calendar is first loaded.
b032077a
RS
336This is the place to add key bindings to `calendar-mode-map'."
337 :type 'hook
338 :group 'calendar-hooks)
7e1dae73
JB
339
340;;;###autoload
b032077a 341(defcustom initial-calendar-window-hook nil
ecaa0527
RS
342 "*List of functions to be called when the calendar window is first opened.
343The functions invoked are called after the calendar window is opened, but
344once opened is never called again. Leaving the calendar with the `q' command
b032077a
RS
345and reentering it will cause these functions to be called again."
346 :type 'hook
347 :group 'calendar-hooks)
ecaa0527 348
7e1dae73 349;;;###autoload
b032077a 350(defcustom today-visible-calendar-hook nil
ecaa0527
RS
351 "*List of functions called whenever the current date is visible.
352This can be used, for example, to replace today's date with asterisks; a
353function `calendar-star-date' is included for this purpose:
354 (setq today-visible-calendar-hook 'calendar-star-date)
6b1abbd1 355It can also be used to mark the current date with `calendar-today-marker';
6a2aa94c 356a function is also provided for this:
ecaa0527
RS
357 (setq today-visible-calendar-hook 'calendar-mark-today)
358
359The corresponding variable `today-invisible-calendar-hook' is the list of
360functions called when the calendar function was called when the current
361date is not visible in the window.
362
363Other than the use of the provided functions, the changing of any
364characters in the calendar buffer by the hooks may cause the failure of the
b032077a
RS
365functions that move by days and weeks."
366 :type 'hook
367 :group 'calendar-hooks)
ecaa0527 368
7e1dae73 369;;;###autoload
b032077a 370(defcustom today-invisible-calendar-hook nil
ecaa0527
RS
371 "*List of functions called whenever the current date is not visible.
372
373The corresponding variable `today-visible-calendar-hook' is the list of
374functions called when the calendar function was called when the current
375date is visible in the window.
376
377Other than the use of the provided functions, the changing of any
378characters in the calendar buffer by the hooks may cause the failure of the
b032077a
RS
379functions that move by days and weeks."
380 :type 'hook
381 :group 'calendar-hooks)
ecaa0527 382
5c9705e5
RS
383;;;###autoload
384(defcustom calendar-move-hook nil
385 "*List of functions called whenever the cursor moves in the calendar.
386
7e1e5cf1 387For example,
5c9705e5
RS
388
389 (add-hook 'calendar-move-hook (lambda () (view-diary-entries 1)))
390
391redisplays the diary for whatever date the cursor is moved to."
392 :type 'hook
393 :group 'calendar-hooks)
394
7e1dae73 395;;;###autoload
b032077a 396(defcustom diary-file "~/diary"
ecaa0527
RS
397 "*Name of the file in which one's personal diary of dates is kept.
398
2c8811d4
GM
399The file's entries are lines beginning with any of the forms
400specified by the variable `american-date-diary-pattern', by default:
ecaa0527
RS
401
402 MONTH/DAY
403 MONTH/DAY/YEAR
404 MONTHNAME DAY
405 MONTHNAME DAY, YEAR
406 DAYNAME
407
2c8811d4
GM
408with the remainder of the line being the diary entry string for
409that date. MONTH and DAY are one or two digit numbers, YEAR is a
410number and may be written in full or abbreviated to the final two
411digits (if `abbreviated-calendar-year' is non-nil). MONTHNAME
412and DAYNAME can be spelled in full (as specified by the variables
413`calendar-month-name-array' and `calendar-day-name-array'),
414abbreviated (as specified by `calendar-month-abbrev-array' and
415`calendar-day-abbrev-array') with or without a period,
416capitalized or not. Any of DAY, MONTH, or MONTHNAME, YEAR can be
417`*' which matches any day, month, or year, respectively. If the
418date does not contain a year, it is generic and applies to any
419year. A DAYNAME entry applies to the appropriate day of the week
420in every week.
421
422The European style (in which the day precedes the month) can be
423used instead, if you execute `european-calendar' when in the
424calendar, or set `european-calendar-style' to t in your .emacs
425file. The European forms (see `european-date-diary-pattern') are
ecaa0527
RS
426
427 DAY/MONTH
428 DAY/MONTH/YEAR
429 DAY MONTHNAME
430 DAY MONTHNAME YEAR
431 DAYNAME
432
433To revert to the default American style from the European style, execute
434`american-calendar' in the calendar.
435
6b1abbd1
RS
436A diary entry can be preceded by the character
437`diary-nonmarking-symbol' (ordinarily `&') to make that entry
438nonmarking--that is, it will not be marked on dates in the calendar
439window but will appear in a diary window.
ecaa0527
RS
440
441Multiline diary entries are made by indenting lines after the first with
442either a TAB or one or more spaces.
443
444Lines not in one the above formats are ignored. Here are some sample diary
445entries (in the default American style):
446
447 12/22/1988 Twentieth wedding anniversary!!
448 &1/1. Happy New Year!
449 10/22 Ruth's birthday.
450 21: Payday
451 Tuesday--weekly meeting with grad students at 10am
452 Supowit, Shen, Bitner, and Kapoor to attend.
453 1/13/89 Friday the thirteenth!!
454 &thu 4pm squash game with Lloyd.
455 mar 16 Dad's birthday
456 April 15, 1989 Income tax due.
457 &* 15 time cards due.
458
459If the first line of a diary entry consists only of the date or day name with
e555fdd8
RS
460no trailing blanks or punctuation, then that line is not displayed in the
461diary window; only the continuation lines is shown. For example, the
ecaa0527
RS
462single diary entry
463
464 02/11/1989
465 Bill Blattner visits Princeton today
466 2pm Cognitive Studies Committee meeting
467 2:30-5:30 Lizzie at Lawrenceville for `Group Initiative'
468 4:00pm Jamie Tappenden
469 7:30pm Dinner at George and Ed's for Alan Ryan
470 7:30-10:00pm dance at Stewart Country Day School
471
472will appear in the diary window without the date line at the beginning. This
473facility allows the diary window to look neater, but can cause confusion if
474used with more than one day's entries displayed.
475
476Diary entries can be based on Lisp sexps. For example, the diary entry
477
478 %%(diary-block 11 1 1990 11 10 1990) Vacation
479
811a8484
JW
480causes the diary entry \"Vacation\" to appear from November 1 through
481November 10, 1990. Other functions available are `diary-float',
482`diary-anniversary', `diary-cyclic', `diary-day-of-year',
483`diary-iso-date', `diary-french-date', `diary-hebrew-date',
484`diary-islamic-date', `diary-bahai-date', `diary-mayan-date',
7086b78e 485`diary-chinese-date', `diary-coptic-date', `diary-ethiopic-date',
c21eb13d 486`diary-persian-date', `diary-yahrzeit', `diary-sunrise-sunset',
811a8484
JW
487`diary-phases-of-moon', `diary-parasha', `diary-omer',
488`diary-rosh-hodesh', and `diary-sabbath-candles'. See the
489documentation for the function `list-sexp-diary-entries' for more
490details.
ecaa0527 491
811a8484
JW
492Diary entries based on the Hebrew, the Islamic and/or the Baha'i
493calendar are also possible, but because these are somewhat slow, they
494are ignored unless you set the `nongregorian-diary-listing-hook' and
495the `nongregorian-diary-marking-hook' appropriately. See the
496documentation for these functions for details.
ecaa0527
RS
497
498Diary files can contain directives to include the contents of other files; for
b032077a
RS
499details, see the documentation for the variable `list-diary-entries-hook'."
500 :type 'file
501 :group 'diary)
ecaa0527 502
7e1dae73 503;;;###autoload
b032077a
RS
504(defcustom diary-nonmarking-symbol "&"
505 "*Symbol indicating that a diary entry is not to be marked in the calendar."
506 :type 'string
507 :group 'diary)
ecaa0527 508
7e1dae73 509;;;###autoload
b032077a
RS
510(defcustom hebrew-diary-entry-symbol "H"
511 "*Symbol indicating a diary entry according to the Hebrew calendar."
512 :type 'string
513 :group 'diary)
ecaa0527 514
7e1dae73 515;;;###autoload
b032077a
RS
516(defcustom islamic-diary-entry-symbol "I"
517 "*Symbol indicating a diary entry according to the Islamic calendar."
518 :type 'string
519 :group 'diary)
ecaa0527 520
811a8484
JW
521;;;###autoload
522(defcustom bahai-diary-entry-symbol "B"
523 "*Symbol indicating a diary entry according to the Baha'i calendar."
524 :type 'string
525 :group 'diary)
526
7e1dae73 527;;;###autoload
b032077a 528(defcustom diary-include-string "#include"
354d0644 529 "*The string indicating inclusion of another file of diary entries.
b032077a
RS
530See the documentation for the function `include-other-diary-files'."
531 :type 'string
532 :group 'diary)
ecaa0527 533
d13c1378
JB
534(defcustom diary-glob-file-regexp-prefix "^\\#"
535 "*The regular expression that gets pre-pended to each of the attribute-regexp's for file-wide specifiers."
536 :type 'regexp
537 :group 'diary)
538
2c8811d4
GM
539(defcustom diary-face-attrs
540 '((" *\\[foreground:\\([-a-z]+\\)\\]$" 1 :foreground string)
541 (" *\\[background:\\([-a-z]+\\)\\]$" 1 :background string)
542 (" *\\[width:\\([-a-z]+\\)\\]$" 1 :width symbol)
543 (" *\\[height:\\([-0-9a-z]+\\)\\]$" 1 :height int)
544 (" *\\[weight:\\([-a-z]+\\)\\]$" 1 :weight symbol)
545 (" *\\[slant:\\([-a-z]+\\)\\]$" 1 :slant symbol)
546 (" *\\[underline:\\([-a-z]+\\)\\]$" 1 :underline stringtnil)
547 (" *\\[overline:\\([-a-z]+\\)\\]$" 1 :overline stringtnil)
548 (" *\\[strike-through:\\([-a-z]+\\)\\]$" 1 :strike-through stringtnil)
549 (" *\\[inverse-video:\\([-a-z]+\\)\\]$" 1 :inverse-video tnil)
550 (" *\\[face:\\([-0-9a-z]+\\)\\]$" 1 :face string)
551 (" *\\[font:\\([-a-z0-9]+\\)\\]$" 1 :font string)
552 ;; Unsupported.
553;;; (" *\\[box:\\([-a-z]+\\)\\]$" 1 :box)
554;;; (" *\\[stipple:\\([-a-z]+\\)\\]$" 1 :stipple)
555 )
556 "*A list of (regexp regnum attr attrtype) lists where the
557regexp says how to find the tag, the regnum says which
558parenthetical sub-regexp this regexp looks for, and the attr says
559which attribute of the face (or that this _is_ a face) is being
560modified."
d13c1378
JB
561 :type 'sexp
562 :group 'diary)
563
564(defcustom diary-file-name-prefix nil
2c8811d4 565 "If non-nil each diary entry is prefixed with the name of the file where it is defined."
d13c1378
JB
566 :type 'boolean
567 :group 'diary)
568
7e1dae73 569;;;###autoload
b032077a 570(defcustom sexp-diary-entry-symbol "%%"
3cbb4860 571 "*The string used to indicate a sexp diary entry in `diary-file'.
b032077a
RS
572See the documentation for the function `list-sexp-diary-entries'."
573 :type 'string
574 :group 'diary)
ecaa0527 575
7e1dae73 576;;;###autoload
b032077a 577(defcustom abbreviated-calendar-year t
354d0644 578 "*Interpret a two-digit year DD in a diary entry as either 19DD or 20DD.
811a8484
JW
579For the Gregorian calendar; similarly for the Hebrew, Islamic and
580Baha'i calendars. If this variable is nil, years must be written in
581full."
b032077a
RS
582 :type 'boolean
583 :group 'diary)
ecaa0527 584
7e1dae73 585;;;###autoload
b032077a 586(defcustom european-calendar-style nil
354d0644
JB
587 "*Use the European style of dates in the diary and in any displays.
588If this variable is t, a date 1/2/1990 would be interpreted as February 1,
2c8811d4
GM
5891990. The default European date styles (see `european-date-diary-pattern')
590are
ecaa0527
RS
591
592 DAY/MONTH
593 DAY/MONTH/YEAR
594 DAY MONTHNAME
595 DAY MONTHNAME YEAR
596 DAYNAME
597
2c8811d4
GM
598Names can be capitalized or not, written in full (as specified by the
599variable `calendar-day-name-array'), or abbreviated (as specified by
1293540e
GM
600`calendar-day-abbrev-array') with or without a period. To take effect,
601this variable should be set before the calendar package and its associates
602are loaded. Otherwise, use one of the functions `european-calendar' or
603`american-calendar' to force the appropriate update."
b032077a
RS
604 :type 'boolean
605 :group 'diary)
ecaa0527 606
7e1dae73 607;;;###autoload
b032077a 608(defcustom american-date-diary-pattern
ecaa0527
RS
609 '((month "/" day "[^/0-9]")
610 (month "/" day "/" year "[^0-9]")
611 (monthname " *" day "[^,0-9]")
612 (monthname " *" day ", *" year "[^0-9]")
613 (dayname "\\W"))
614 "*List of pseudo-patterns describing the American patterns of date used.
b032077a
RS
615See the documentation of `diary-date-forms' for an explanation."
616 :type '(repeat (choice (cons :tag "Backup"
617 :value (backup . nil)
618 (const backup)
619 (repeat (list :inline t :format "%v"
620 (symbol :tag "Keyword")
621 (choice symbol regexp))))
622 (repeat (list :inline t :format "%v"
623 (symbol :tag "Keyword")
624 (choice symbol regexp)))))
625 :group 'diary)
ecaa0527 626
7e1dae73 627;;;###autoload
b032077a 628(defcustom european-date-diary-pattern
ecaa0527
RS
629 '((day "/" month "[^/0-9]")
630 (day "/" month "/" year "[^0-9]")
bb0541f8 631 (backup day " *" monthname "\\W+\\<\\([^*0-9]\\|\\([0-9]+[:aApP]\\)\\)")
ecaa0527
RS
632 (day " *" monthname " *" year "[^0-9]")
633 (dayname "\\W"))
634 "*List of pseudo-patterns describing the European patterns of date used.
b032077a
RS
635See the documentation of `diary-date-forms' for an explanation."
636 :type '(repeat (choice (cons :tag "Backup"
637 :value (backup . nil)
638 (const backup)
639 (repeat (list :inline t :format "%v"
640 (symbol :tag "Keyword")
641 (choice symbol regexp))))
642 (repeat (list :inline t :format "%v"
643 (symbol :tag "Keyword")
644 (choice symbol regexp)))))
645 :group 'diary)
646
647(defcustom diary-date-forms
ecaa0527
RS
648 (if european-calendar-style
649 european-date-diary-pattern
650 american-date-diary-pattern)
651 "*List of pseudo-patterns describing the forms of date used in the diary.
8c64a298 652The patterns on the list must be MUTUALLY EXCLUSIVE and should not match
ecaa0527
RS
653any portion of the diary entry itself, just the date component.
654
655A pseudo-pattern is a list of regular expressions and the keywords `month',
656`day', `year', `monthname', and `dayname'. The keyword `monthname' will
2c8811d4
GM
657match the name of the month (see `calendar-month-name-array'), capitalized
658or not, or its user-specified abbreviation (see `calendar-month-abbrev-array'),
659followed by a period or not; it will also match `*'. Similarly, `dayname'
660will match the name of the day (see `calendar-day-name-array'), capitalized or
661not, or its user-specified abbreviation (see `calendar-day-abbrev-array'),
662followed by a period or not. The keywords `month', `day', and `year' will
663match those numerical values, preceded by arbitrarily many zeros; they will
664also match `*'.
ecaa0527
RS
665
666The matching of the diary entries with the date forms is done with the
667standard syntax table from Fundamental mode, but with the `*' changed so
668that it is a word constituent.
669
670If, to be mutually exclusive, a pseudo-pattern must match a portion of the
671diary entry itself, the first element of the pattern MUST be `backup'. This
7e1dae73
JB
672directive causes the date recognizer to back up to the beginning of the
673current word of the diary entry, so in no case can the pattern match more than
b032077a
RS
674a portion of the first word of the diary entry."
675 :type '(repeat (choice (cons :tag "Backup"
676 :value (backup . nil)
677 (const backup)
678 (repeat (list :inline t :format "%v"
679 (symbol :tag "Keyword")
680 (choice symbol regexp))))
681 (repeat (list :inline t :format "%v"
682 (symbol :tag "Keyword")
683 (choice symbol regexp)))))
684 :group 'diary)
ecaa0527 685
7e1dae73 686;;;###autoload
b032077a 687(defcustom european-calendar-display-form
7e1dae73 688 '((if dayname (concat dayname ", ")) day " " monthname " " year)
354d0644 689 "*Pseudo-pattern governing the way a date appears in the European style.
5d22135b 690See the documentation of `calendar-date-display-form' for an explanation."
b032077a
RS
691 :type 'sexp
692 :group 'calendar)
ecaa0527 693
7e1dae73 694;;;###autoload
b032077a 695(defcustom american-calendar-display-form
7e1dae73 696 '((if dayname (concat dayname ", ")) monthname " " day ", " year)
354d0644 697 "*Pseudo-pattern governing the way a date appears in the American style.
b032077a
RS
698See the documentation of `calendar-date-display-form' for an explanation."
699 :type 'sexp
700 :group 'calendar)
ecaa0527 701
b032077a 702(defcustom calendar-date-display-form
ecaa0527
RS
703 (if european-calendar-style
704 european-calendar-display-form
705 american-calendar-display-form)
354d0644
JB
706 "*Pseudo-pattern governing the way a date appears.
707
708Used by the function `calendar-date-string', a pseudo-pattern is a list of
709expressions that can involve the keywords `month', `day', and `year', all
710numbers in string form, and `monthname' and `dayname', both alphabetic
711strings. For example, the ISO standard would use the pseudo- pattern
ecaa0527
RS
712
713 '(year \"-\" month \"-\" day)
714
715while a typical American form would be
716
717 '(month \"/\" day \"/\" (substring year -2))
718
719and
720
721 '((format \"%9s, %9s %2s, %4s\" dayname monthname day year))
722
723would give the usual American style in fixed-length fields.
724
b032077a
RS
725See the documentation of the function `calendar-date-string'."
726 :type 'sexp
727 :group 'calendar)
ecaa0527
RS
728
729(defun european-calendar ()
730 "Set the interpretation and display of dates to the European style."
731 (interactive)
732 (setq european-calendar-style t)
733 (setq calendar-date-display-form european-calendar-display-form)
734 (setq diary-date-forms european-date-diary-pattern)
735 (update-calendar-mode-line))
736
737(defun american-calendar ()
738 "Set the interpretation and display of dates to the American style."
739 (interactive)
740 (setq european-calendar-style nil)
741 (setq calendar-date-display-form american-calendar-display-form)
742 (setq diary-date-forms american-date-diary-pattern)
743 (update-calendar-mode-line))
744
7e1dae73 745;;;###autoload
b032077a 746(defcustom print-diary-entries-hook 'lpr-buffer
354d0644
JB
747 "*List of functions called after a temporary diary buffer is prepared.
748The buffer shows only the diary entries currently visible in the diary
749buffer. The default just does the printing. Other uses might include, for
750example, rearranging the lines into order by day and time, saving the buffer
b032077a
RS
751instead of deleting it, or changing the function used to do the printing."
752 :type 'hook
753 :group 'diary)
ecaa0527 754
e5d77022 755;;;###autoload
b032077a 756(defcustom list-diary-entries-hook nil
354d0644
JB
757 "*List of functions called after diary file is culled for relevant entries.
758It is to be used for diary entries that are not found in the diary file.
ecaa0527
RS
759
760A function `include-other-diary-files' is provided for use as the value of
761this hook. This function enables you to use shared diary files together
6b1abbd1 762with your own. The files included are specified in the diary file by lines
ecaa0527
RS
763of the form
764
765 #include \"filename\"
766
767This is recursive; that is, #include directives in files thus included are
768obeyed. You can change the \"#include\" to some other string by changing
769the variable `diary-include-string'. When you use `include-other-diary-files'
770as part of the list-diary-entries-hook, you will probably also want to use the
6b1abbd1 771function `mark-included-diary-files' as part of `mark-diary-entries-hook'.
ecaa0527
RS
772
773For example, you could use
774
775 (setq list-diary-entries-hook
7e1dae73 776 '(include-other-diary-files sort-diary-entries))
ecaa0527
RS
777 (setq diary-display-hook 'fancy-diary-display)
778
6b1abbd1 779in your `.emacs' file to cause the fancy diary buffer to be displayed with
ecaa0527 780diary entries from various included files, each day's entries sorted into
b032077a
RS
781lexicographic order."
782 :type 'hook
3d880a4b 783 :options '(include-other-diary-files sort-diary-entries)
b032077a 784 :group 'diary)
ecaa0527 785
e5d77022 786;;;###autoload
b032077a 787(defcustom diary-hook nil
34fa2dc2 788 "*List of functions called after the display of the diary.
b032077a
RS
789Can be used for appointment notification."
790 :type 'hook
791 :group 'diary)
34fa2dc2
RS
792
793;;;###autoload
b032077a 794(defcustom diary-display-hook nil
ecaa0527 795 "*List of functions that handle the display of the diary.
e555fdd8 796If nil (the default), `simple-diary-display' is used. Use `ignore' for no
34fa2dc2 797diary display.
ecaa0527
RS
798
799Ordinarily, this just displays the diary buffer (with holidays indicated in
800the mode line), if there are any relevant entries. At the time these
801functions are called, the variable `diary-entries-list' is a list, in order
802by date, of all relevant diary entries in the form of ((MONTH DAY YEAR)
803STRING), where string is the diary entry for the given date. This can be
34fa2dc2
RS
804used, for example, a different buffer for display (perhaps combined with
805holidays), or produce hard copy output.
ecaa0527
RS
806
807A function `fancy-diary-display' is provided as an alternative
808choice for this hook; this function prepares a special noneditable diary
809buffer with the relevant diary entries that has neat day-by-day arrangement
810with headings. The fancy diary buffer will show the holidays unless the
811variable `holidays-in-diary-buffer' is set to nil. Ordinarily, the fancy
812diary buffer will not show days for which there are no diary entries, even
813if that day is a holiday; if you want such days to be shown in the fancy
b032077a
RS
814diary buffer, set the variable `diary-list-include-blanks' to t."
815 :type 'hook
3d880a4b 816 :options '(fancy-diary-display)
b032077a 817 :group 'diary)
ecaa0527 818
e5d77022 819;;;###autoload
b032077a 820(defcustom nongregorian-diary-listing-hook nil
354d0644 821 "*List of functions called for listing diary file and included files.
811a8484
JW
822As the files are processed for diary entries, these functions are used
823to cull relevant entries. You can use either or both of
824`list-hebrew-diary-entries', `list-islamic-diary-entries' and
825`list-bahai-diary-entries'. The documentation for these functions
b032077a
RS
826describes the style of such diary entries."
827 :type 'hook
811a8484
JW
828 :options '(list-hebrew-diary-entries
829 list-islamic-diary-entries
830 list-bahai-diary-entries)
b032077a 831 :group 'diary)
ecaa0527 832
7e1dae73 833;;;###autoload
b032077a 834(defcustom mark-diary-entries-hook nil
ecaa0527
RS
835 "*List of functions called after marking diary entries in the calendar.
836
837A function `mark-included-diary-files' is also provided for use as the
3cbb4860 838`mark-diary-entries-hook'; it enables you to use shared diary files together
6b1abbd1 839with your own. The files included are specified in the diary file by lines
ecaa0527
RS
840of the form
841 #include \"filename\"
842This is recursive; that is, #include directives in files thus included are
843obeyed. You can change the \"#include\" to some other string by changing the
844variable `diary-include-string'. When you use `mark-included-diary-files' as
845part of the mark-diary-entries-hook, you will probably also want to use the
b032077a
RS
846function `include-other-diary-files' as part of `list-diary-entries-hook'."
847 :type 'hook
3d880a4b 848 :options '(mark-included-diary-files)
b032077a 849 :group 'diary)
ecaa0527 850
e5d77022 851;;;###autoload
b032077a 852(defcustom nongregorian-diary-marking-hook nil
354d0644 853 "*List of functions called for marking diary file and included files.
811a8484
JW
854As the files are processed for diary entries, these functions are used
855to cull relevant entries. You can use either or both of
856`mark-hebrew-diary-entries', `mark-islamic-diary-entries' and
857`mark-bahai-diary-entries'. The documentation for these functions
b032077a
RS
858describes the style of such diary entries."
859 :type 'hook
811a8484
JW
860 :options '(mark-hebrew-diary-entries
861 mark-islamic-diary-entries
862 mark-bahai-diary-entries)
b032077a 863 :group 'diary)
ecaa0527 864
e5d77022 865;;;###autoload
b032077a 866(defcustom diary-list-include-blanks nil
354d0644 867 "*If nil, do not include days with no diary entry in the list of diary entries.
ac96331d 868Such days will then not be shown in the fancy diary buffer, even if they
b032077a
RS
869are holidays."
870 :type 'boolean
871 :group 'diary)
ecaa0527 872
7e1dae73 873;;;###autoload
b032077a 874(defcustom holidays-in-diary-buffer t
e555fdd8
RS
875 "*Non-nil means include holidays in the diary display.
876The holidays appear in the mode line of the diary buffer, or in the
354d0644 877fancy diary buffer next to the date. This slows down the diary functions
b032077a
RS
878somewhat; setting it to nil makes the diary display faster."
879 :type 'boolean
880 :group 'holidays)
ecaa0527 881
2ec778d0
RS
882(defvar calendar-mark-ring nil)
883
e555fdd8
RS
884;;;###autoload
885(put 'general-holidays 'risky-local-variable t)
7e1dae73 886;;;###autoload
b032077a 887(defcustom general-holidays
354d0644
JB
888 '((holiday-fixed 1 1 "New Year's Day")
889 (holiday-float 1 1 3 "Martin Luther King Day")
11f23ea2 890 (holiday-fixed 2 2 "Groundhog Day")
354d0644
JB
891 (holiday-fixed 2 14 "Valentine's Day")
892 (holiday-float 2 1 3 "President's Day")
893 (holiday-fixed 3 17 "St. Patrick's Day")
9e32719f 894 (holiday-fixed 4 1 "April Fools' Day")
354d0644
JB
895 (holiday-float 5 0 2 "Mother's Day")
896 (holiday-float 5 1 -1 "Memorial Day")
897 (holiday-fixed 6 14 "Flag Day")
898 (holiday-float 6 0 3 "Father's Day")
899 (holiday-fixed 7 4 "Independence Day")
900 (holiday-float 9 1 1 "Labor Day")
901 (holiday-float 10 1 2 "Columbus Day")
902 (holiday-fixed 10 31 "Halloween")
903 (holiday-fixed 11 11 "Veteran's Day")
904 (holiday-float 11 4 4 "Thanksgiving"))
905 "*General holidays. Default value is for the United States.
b032077a
RS
906See the documentation for `calendar-holidays' for details."
907 :type 'sexp
908 :group 'holidays)
ecaa0527 909
7086b78e
ER
910;;;###autoload
911(put 'oriental-holidays 'risky-local-variable t)
912;;;###autoload
b032077a 913(defcustom oriental-holidays
7086b78e
ER
914 '((if (fboundp 'atan)
915 (holiday-chinese-new-year)))
916 "*Oriental holidays.
b032077a
RS
917See the documentation for `calendar-holidays' for details."
918 :type 'sexp
919 :group 'holidays)
7086b78e 920
e555fdd8
RS
921;;;###autoload
922(put 'local-holidays 'risky-local-variable t)
7e1dae73 923;;;###autoload
b032077a 924(defcustom local-holidays nil
7e1dae73 925 "*Local holidays.
b032077a
RS
926See the documentation for `calendar-holidays' for details."
927 :type 'sexp
928 :group 'holidays)
7e1dae73 929
e555fdd8
RS
930;;;###autoload
931(put 'other-holidays 'risky-local-variable t)
7e1dae73 932;;;###autoload
b032077a 933(defcustom other-holidays nil
7e1dae73 934 "*User defined holidays.
b032077a
RS
935See the documentation for `calendar-holidays' for details."
936 :type 'sexp
937 :group 'holidays)
ecaa0527 938
e555fdd8
RS
939;;;###autoload
940(put 'hebrew-holidays-1 'risky-local-variable t)
7e1dae73 941;;;###autoload
97344751 942(defvar hebrew-holidays-1
354d0644 943 '((holiday-rosh-hashanah-etc)
ecaa0527 944 (if all-hebrew-calendar-holidays
354d0644
JB
945 (holiday-julian
946 11
947 (let* ((m displayed-month)
948 (y displayed-year)
949 (year))
950 (increment-calendar-month m y -1)
951 (let ((year (extract-calendar-year
952 (calendar-julian-from-absolute
953 (calendar-absolute-from-gregorian
954 (list m 1 y))))))
955 (if (zerop (% (1+ year) 4))
956 22
97344751
RS
957 21))) "\"Tal Umatar\" (evening)"))))
958
e555fdd8
RS
959;;;###autoload
960(put 'hebrew-holidays-2 'risky-local-variable t)
97344751
RS
961;;;###autoload
962(defvar hebrew-holidays-2
963 '((if all-hebrew-calendar-holidays
354d0644
JB
964 (holiday-hanukkah)
965 (holiday-hebrew 9 25 "Hanukkah"))
ecaa0527 966 (if all-hebrew-calendar-holidays
354d0644
JB
967 (holiday-hebrew
968 10
969 (let ((h-year (extract-calendar-year
970 (calendar-hebrew-from-absolute
971 (calendar-absolute-from-gregorian
972 (list displayed-month 28 displayed-year))))))
973 (if (= (% (calendar-absolute-from-hebrew (list 10 10 h-year))
974 7)
975 6)
976 11 10))
977 "Tzom Teveth"))
ecaa0527 978 (if all-hebrew-calendar-holidays
97344751
RS
979 (holiday-hebrew 11 15 "Tu B'Shevat"))))
980
e555fdd8
RS
981;;;###autoload
982(put 'hebrew-holidays-3 'risky-local-variable t)
97344751 983;;;###autoload
d7fa63b2 984(defvar hebrew-holidays-3
97344751 985 '((if all-hebrew-calendar-holidays
354d0644 986 (holiday-hebrew
ecaa0527
RS
987 11
988 (let ((m displayed-month)
989 (y displayed-year))
990 (increment-calendar-month m y 1)
991 (let* ((h-year (extract-calendar-year
992 (calendar-hebrew-from-absolute
993 (calendar-absolute-from-gregorian
994 (list m
995 (calendar-last-day-of-month m y)
996 y)))))
997 (s-s
998 (calendar-hebrew-from-absolute
999 (if (=
1000 (% (calendar-absolute-from-hebrew
1001 (list 7 1 h-year))
1002 7)
1003 6)
1004 (calendar-dayname-on-or-before
1005 6 (calendar-absolute-from-hebrew
1006 (list 11 17 h-year)))
1007 (calendar-dayname-on-or-before
1008 6 (calendar-absolute-from-hebrew
1009 (list 11 16 h-year))))))
1010 (day (extract-calendar-day s-s)))
1011 day))
97344751
RS
1012 "Shabbat Shirah"))))
1013
e555fdd8
RS
1014;;;###autoload
1015(put 'hebrew-holidays-4 'risky-local-variable t)
97344751
RS
1016;;;###autoload
1017(defvar hebrew-holidays-4
1018 '((holiday-passover-etc)
ecaa0527
RS
1019 (if (and all-hebrew-calendar-holidays
1020 (let* ((m displayed-month)
1021 (y displayed-year)
1022 (year))
1023 (increment-calendar-month m y -1)
1024 (let ((year (extract-calendar-year
1025 (calendar-julian-from-absolute
1026 (calendar-absolute-from-gregorian
1027 (list m 1 y))))))
1028 (= 21 (% year 28)))))
354d0644 1029 (holiday-julian 3 26 "Kiddush HaHamah"))
ecaa0527 1030 (if all-hebrew-calendar-holidays
97344751
RS
1031 (holiday-tisha-b-av-etc))))
1032
e555fdd8
RS
1033;;;###autoload
1034(put 'hebrew-holidays 'risky-local-variable t)
97344751 1035;;;###autoload
b032077a 1036(defcustom hebrew-holidays (append hebrew-holidays-1 hebrew-holidays-2
97344751 1037 hebrew-holidays-3 hebrew-holidays-4)
7e1dae73 1038 "*Jewish holidays.
b032077a
RS
1039See the documentation for `calendar-holidays' for details."
1040 :type 'sexp
1041 :group 'holidays)
7e1dae73 1042
e555fdd8
RS
1043;;;###autoload
1044(put 'christian-holidays 'risky-local-variable t)
7e1dae73 1045;;;###autoload
b032077a 1046(defcustom christian-holidays
7e1dae73 1047 '((if all-christian-calendar-holidays
354d0644
JB
1048 (holiday-fixed 1 6 "Epiphany"))
1049 (holiday-easter-etc)
7e1dae73 1050 (if all-christian-calendar-holidays
354d0644 1051 (holiday-greek-orthodox-easter))
7e1dae73 1052 (if all-christian-calendar-holidays
354d0644 1053 (holiday-fixed 8 15 "Assumption"))
7e1dae73 1054 (if all-christian-calendar-holidays
354d0644
JB
1055 (holiday-advent))
1056 (holiday-fixed 12 25 "Christmas")
7e1dae73 1057 (if all-christian-calendar-holidays
354d0644 1058 (holiday-julian 12 25 "Eastern Orthodox Christmas")))
7e1dae73 1059 "*Christian holidays.
b032077a
RS
1060See the documentation for `calendar-holidays' for details."
1061 :type 'sexp
1062 :group 'holidays)
ecaa0527 1063
e555fdd8
RS
1064;;;###autoload
1065(put 'islamic-holidays 'risky-local-variable t)
7e1dae73 1066;;;###autoload
b032077a 1067(defcustom islamic-holidays
354d0644
JB
1068 '((holiday-islamic
1069 1 1
1070 (format "Islamic New Year %d"
1071 (let ((m displayed-month)
1072 (y displayed-year))
1073 (increment-calendar-month m y 1)
1074 (extract-calendar-year
1075 (calendar-islamic-from-absolute
1076 (calendar-absolute-from-gregorian
1077 (list
1078 m (calendar-last-day-of-month m y) y)))))))
ecaa0527 1079 (if all-islamic-calendar-holidays
354d0644 1080 (holiday-islamic 1 10 "Ashura"))
ecaa0527 1081 (if all-islamic-calendar-holidays
354d0644 1082 (holiday-islamic 3 12 "Mulad-al-Nabi"))
ecaa0527 1083 (if all-islamic-calendar-holidays
354d0644 1084 (holiday-islamic 7 26 "Shab-e-Mi'raj"))
ecaa0527 1085 (if all-islamic-calendar-holidays
354d0644
JB
1086 (holiday-islamic 8 15 "Shab-e-Bara't"))
1087 (holiday-islamic 9 1 "Ramadan Begins")
ecaa0527 1088 (if all-islamic-calendar-holidays
354d0644 1089 (holiday-islamic 9 27 "Shab-e Qadr"))
ecaa0527 1090 (if all-islamic-calendar-holidays
354d0644 1091 (holiday-islamic 10 1 "Id-al-Fitr"))
ecaa0527 1092 (if all-islamic-calendar-holidays
354d0644 1093 (holiday-islamic 12 10 "Id-al-Adha")))
7e1dae73 1094 "*Islamic holidays.
b032077a
RS
1095See the documentation for `calendar-holidays' for details."
1096 :type 'sexp
1097 :group 'holidays)
7e1dae73 1098
811a8484
JW
1099;;;###autoload
1100(put 'bahai-holidays 'risky-local-variable t)
1101;;;###autoload
1102(defcustom bahai-holidays
1103 '((holiday-fixed
1104 3 21
1105 (format "Baha'i New Year (Naw-Ruz) %d" (- displayed-year (1- 1844))))
1106 (holiday-fixed 4 21 "First Day of Ridvan")
1107 (if all-bahai-calendar-holidays
1108 (holiday-fixed 4 22 "Second Day of Ridvan"))
1109 (if all-bahai-calendar-holidays
1110 (holiday-fixed 4 23 "Third Day of Ridvan"))
1111 (if all-bahai-calendar-holidays
1112 (holiday-fixed 4 24 "Fourth Day of Ridvan"))
1113 (if all-bahai-calendar-holidays
1114 (holiday-fixed 4 25 "Fifth Day of Ridvan"))
1115 (if all-bahai-calendar-holidays
1116 (holiday-fixed 4 26 "Sixth Day of Ridvan"))
1117 (if all-bahai-calendar-holidays
1118 (holiday-fixed 4 27 "Seventh Day of Ridvan"))
1119 (if all-bahai-calendar-holidays
1120 (holiday-fixed 4 28 "Eighth Day of Ridvan"))
1121 (holiday-fixed 4 29 "Ninth Day of Ridvan")
1122 (if all-bahai-calendar-holidays
1123 (holiday-fixed 4 30 "Tenth Day of Ridvan"))
1124 (if all-bahai-calendar-holidays
1125 (holiday-fixed 5 1 "Eleventh Day of Ridvan"))
1126 (holiday-fixed 5 2 "Twelfth Day of Ridvan")
1127 (holiday-fixed 5 23 "Declaration of the Bab")
1128 (holiday-fixed 5 29 "Ascension of Baha'u'llah")
1129 (holiday-fixed 7 9 "Martyrdom of the Bab")
1130 (holiday-fixed 10 20 "Birth of the Bab")
1131 (holiday-fixed 11 12 "Birth of Baha'u'llah")
1132 (if all-bahai-calendar-holidays
1133 (holiday-fixed 11 26 "Day of the Covenant"))
1134 (if all-bahai-calendar-holidays
1135 (holiday-fixed 11 28 "Ascension of `Abdu'l-Baha")))
1136 "*Baha'i holidays.
1137See the documentation for `calendar-holidays' for details."
1138 :type 'sexp
1139 :group 'holidays)
1140
e555fdd8
RS
1141;;;###autoload
1142(put 'solar-holidays 'risky-local-variable t)
7e1dae73 1143;;;###autoload
b032077a 1144(defcustom solar-holidays
7e1dae73
JB
1145 '((if (fboundp 'atan)
1146 (solar-equinoxes-solstices))
3b92bdd2
RS
1147 (if (progn
1148 (require 'cal-dst)
1149 t)
354d0644 1150 (funcall
3b92bdd2 1151 'holiday-sexp
354d0644
JB
1152 calendar-daylight-savings-starts
1153 '(format "Daylight Savings Time Begins %s"
1154 (if (fboundp 'atan)
1155 (solar-time-string
8a7cdf3a
ER
1156 (/ calendar-daylight-savings-starts-time (float 60))
1157 calendar-standard-time-zone-name)
354d0644
JB
1158 ""))))
1159 (funcall
1160 'holiday-sexp
1161 calendar-daylight-savings-ends
1162 '(format "Daylight Savings Time Ends %s"
1163 (if (fboundp 'atan)
1164 (solar-time-string
8a7cdf3a
ER
1165 (/ calendar-daylight-savings-ends-time (float 60))
1166 calendar-daylight-time-zone-name)
354d0644 1167 ""))))
7e1dae73 1168 "*Sun-related holidays.
b032077a
RS
1169See the documentation for `calendar-holidays' for details."
1170 :type 'sexp
1171 :group 'holidays)
7e1dae73 1172
e555fdd8
RS
1173;;;###autoload
1174(put 'calendar-holidays 'risky-local-variable t)
b032077a 1175(defcustom calendar-holidays
354d0644
JB
1176 (append general-holidays local-holidays other-holidays
1177 christian-holidays hebrew-holidays islamic-holidays
811a8484 1178 bahai-holidays oriental-holidays solar-holidays)
3cbb4860 1179 "*List of notable days for the command \\[holidays].
7e1dae73 1180
811a8484
JW
1181Additional holidays are easy to add to the list, just put them in the
1182list `other-holidays' in your .emacs file. Similarly, by setting any
1183of `general-holidays', `local-holidays' `christian-holidays',
1184`hebrew-holidays', `islamic-holidays', `bahai-holidays',
1185`oriental-holidays', or `solar-holidays' to nil in your .emacs file,
1186you can eliminate unwanted categories of holidays. The intention is
1187that (in the US) `local-holidays' be set in site-init.el and
7086b78e 1188`other-holidays' be set by the user.
7e1dae73 1189
354d0644
JB
1190Entries on the list are expressions that return (possibly empty) lists of
1191items of the form ((month day year) string) of a holiday in the in the
1192three-month period centered around `displayed-month' of `displayed-year'.
1193Several basic functions are provided for this purpose:
1194
1195 (holiday-fixed MONTH DAY STRING) is a fixed date on the Gregorian calendar
1196 (holiday-float MONTH DAYNAME K STRING &optional day) is the Kth DAYNAME in
1197 MONTH on the Gregorian calendar (0 for Sunday,
1198 etc.); K<0 means count back from the end of the
3cbb4860 1199 month. An optional parameter DAY means the Kth
354d0644
JB
1200 DAYNAME after/before MONTH DAY.
1201 (holiday-hebrew MONTH DAY STRING) a fixed date on the Hebrew calendar
1202 (holiday-islamic MONTH DAY STRING) a fixed date on the Islamic calendar
811a8484 1203 (holiday-bahai MONTH DAY STRING) a fixed date on the Baha'i calendar
354d0644
JB
1204 (holiday-julian MONTH DAY STRING) a fixed date on the Julian calendar
1205 (holiday-sexp SEXP STRING) SEXP is a Gregorian-date-valued expression
7e1dae73
JB
1206 in the variable `year'; if it evaluates to
1207 a visible date, that's the holiday; if it
354d0644
JB
1208 evaluates to nil, there's no holiday. STRING
1209 is an expression in the variable `date'.
ecaa0527
RS
1210
1211For example, to add Bastille Day, celebrated in France on July 14, add
1212
354d0644 1213 (holiday-fixed 7 14 \"Bastille Day\")
ecaa0527
RS
1214
1215to the list. To add Hurricane Supplication Day, celebrated in the Virgin
1216Islands on the fourth Monday in August, add
1217
354d0644 1218 (holiday-float 8 1 4 \"Hurricane Supplication Day\")
ecaa0527
RS
1219
1220to the list (the last Monday would be specified with `-1' instead of `4').
7e1dae73 1221To add the last day of Hanukkah to the list, use
ecaa0527 1222
354d0644 1223 (holiday-hebrew 10 2 \"Last day of Hanukkah\")
ecaa0527
RS
1224
1225since the Hebrew months are numbered with 1 starting from Nisan, while to
1226add the Islamic feast celebrating Mohammed's birthday use
1227
354d0644 1228 (holiday-islamic 3 12 \"Mohammed's Birthday\")
ecaa0527
RS
1229
1230since the Islamic months are numbered from 1 starting with Muharram. To
811a8484
JW
1231add an entry for the Baha'i festival of Ridvan, use
1232
1233 (holiday-bahai 2 13 \"Festival of Ridvan\")
1234
1235since the Baha'i months are numbered from 1 starting with Baha. To
ecaa0527
RS
1236add Thomas Jefferson's birthday, April 2, 1743 (Julian), use
1237
354d0644 1238 (holiday-julian 4 2 \"Jefferson's Birthday\")
ecaa0527 1239
354d0644
JB
1240To include a holiday conditionally, use the sexp form or a conditional. For
1241example, to include American presidential elections, which occur on the first
1242Tuesday after the first Monday in November of years divisible by 4, add
ecaa0527 1243
354d0644 1244 (holiday-sexp
78e37e9c 1245 '(if (zerop (% year 4))
354d0644
JB
1246 (calendar-gregorian-from-absolute
1247 (1+ (calendar-dayname-on-or-before
1248 1 (+ 6 (calendar-absolute-from-gregorian
1249 (list 11 1 year)))))))
1250 \"US Presidential Election\")
7e1dae73
JB
1251
1252or
1253
ecaa0527 1254 (if (zerop (% displayed-year 4))
354d0644 1255 (holiday-fixed 11
ecaa0527
RS
1256 (extract-calendar-day
1257 (calendar-gregorian-from-absolute
1258 (1+ (calendar-dayname-on-or-before
1259 1 (+ 6 (calendar-absolute-from-gregorian
1260 (list 11 1 displayed-year)))))))
1261 \"US Presidential Election\"))
1262
1263to the list. To include the phases of the moon, add
1264
1265 (lunar-phases)
1266
354d0644
JB
1267to the holiday list, where `lunar-phases' is an Emacs-Lisp function that
1268you've written to return a (possibly empty) list of the relevant VISIBLE dates
1269with descriptive strings such as
ecaa0527 1270
b032077a
RS
1271 (((2 6 1989) \"New Moon\") ((2 12 1989) \"First Quarter Moon\") ... )."
1272 :type 'sexp
1273 :group 'holidays)
ecaa0527 1274
ecaa0527
RS
1275(defconst calendar-buffer "*Calendar*"
1276 "Name of the buffer used for the calendar.")
1277
1278(defconst holiday-buffer "*Holidays*"
1279 "Name of the buffer used for the displaying the holidays.")
1280
1281(defconst fancy-diary-buffer "*Fancy Diary Entries*"
1282 "Name of the buffer used for the optional fancy display of the diary.")
1283
726669d8
ER
1284(defconst other-calendars-buffer "*Other Calendars*"
1285 "Name of the buffer used for the display of date on other calendars.")
1286
cba0c253
ER
1287(defconst lunar-phases-buffer "*Phases of Moon*"
1288 "Name of the buffer used for the lunar phases.")
1289
ecaa0527 1290(defmacro increment-calendar-month (mon yr n)
18db8896
GM
1291 "Increment the variables MON and YR by N months.
1292Forward if N is positive or backward if N is negative.
1293A negative YR is interpreted as BC; -1 being 1 BC, and so on."
1294 `(let (macro-y)
1295 (if (< ,yr 0) (setq ,yr (1+ ,yr))) ; -1 BC -> 0 AD, etc
1296 (setq macro-y (+ (* ,yr 12) ,mon -1 ,n)
1297 ,mon (1+ (mod macro-y 12))
1298 ,yr (/ macro-y 12))
1299 (and (< macro-y 0) (> ,mon 1) (setq ,yr (1- ,yr)))
1300 (if (< ,yr 1) (setq ,yr (1- ,yr))))) ; 0 AD -> -1 BC, etc
ecaa0527
RS
1301
1302(defmacro calendar-for-loop (var from init to final do &rest body)
1303 "Execute a for loop."
7e1e5cf1
SS
1304 `(let ((,var (1- ,init)))
1305 (while (>= ,final (setq ,var (1+ ,var)))
1306 ,@body)))
ecaa0527
RS
1307
1308(defmacro calendar-sum (index initial condition expression)
354d0644 1309 "For INDEX = INITIAL et seq, as long as CONDITION holds, sum EXPRESSION."
7e1e5cf1
SS
1310 `(let ((,index ,initial)
1311 (sum 0))
1312 (while ,condition
1313 (setq sum (+ sum ,expression))
1314 (setq ,index (1+ ,index)))
1315 sum))
ecaa0527 1316
cba0c253
ER
1317;; The following are in-line for speed; they can be called thousands of times
1318;; when looking up holidays or processing the diary. Here, for example, are
1319;; the numbers of calls to calendar/diary/holiday functions in preparing the
e5d77022
JB
1320;; fancy diary display, for a moderately complex diary file, with functions
1321;; used instead of macros. There were a total of 10000 such calls:
1322;;
1323;; 1934 extract-calendar-month
1324;; 1852 extract-calendar-year
1325;; 1819 extract-calendar-day
1326;; 845 calendar-leap-year-p
1327;; 837 calendar-day-number
1328;; 775 calendar-absolute-from-gregorian
1329;; 346 calendar-last-day-of-month
1330;; 286 hebrew-calendar-last-day-of-month
1331;; 188 hebrew-calendar-leap-year-p
1332;; 180 hebrew-calendar-elapsed-days
1333;; 163 hebrew-calendar-last-month-of-year
1334;; 66 calendar-date-compare
1335;; 65 hebrew-calendar-days-in-year
1336;; 60 calendar-absolute-from-julian
1337;; 50 calendar-absolute-from-hebrew
1338;; 43 calendar-date-equal
1339;; 38 calendar-gregorian-from-absolute
1340;; .
1341;; .
1342;; .
1343;;
1344;; The use of these seven macros eliminates the overhead of 92% of the function
cba0c253 1345;; calls; it's faster this way.
e5d77022 1346
cba0c253 1347(defsubst extract-calendar-month (date)
ecaa0527 1348 "Extract the month part of DATE which has the form (month day year)."
cba0c253 1349 (car date))
ecaa0527 1350
cba0c253 1351(defsubst extract-calendar-day (date)
ecaa0527 1352 "Extract the day part of DATE which has the form (month day year)."
cba0c253 1353 (car (cdr date)))
ecaa0527 1354
cba0c253 1355(defsubst extract-calendar-year (date)
ecaa0527 1356 "Extract the year part of DATE which has the form (month day year)."
cba0c253 1357 (car (cdr (cdr date))))
ecaa0527 1358
cba0c253 1359(defsubst calendar-leap-year-p (year)
18db8896
GM
1360 "Return t if YEAR is a Gregorian leap year.
1361A negative year is interpreted as BC; -1 being 1 BC, and so on."
1362 ;; 1 BC = 0 AD, 2 BC acts like 1 AD, etc.
1363 (if (< year 0) (setq year (1- (abs year))))
cba0c253
ER
1364 (and (zerop (% year 4))
1365 (or (not (zerop (% year 100)))
1366 (zerop (% year 400)))))
1367
354d0644
JB
1368;; The foregoing is a bit faster, but not as clear as the following:
1369;;
cba0c253 1370;;(defsubst calendar-leap-year-p (year)
7e1dae73
JB
1371;; "Returns t if YEAR is a Gregorian leap year."
1372;; (or
1373;; (and (= (% year 4) 0)
1374;; (/= (% year 100) 0))
1375;; (= (% year 400) 0)))
e5d77022 1376
cba0c253 1377(defsubst calendar-last-day-of-month (month year)
e5d77022 1378 "The last day in MONTH during YEAR."
cba0c253
ER
1379 (if (and (= month 2) (calendar-leap-year-p year))
1380 29
1381 (aref [31 28 31 30 31 30 31 31 30 31 30 31] (1- month))))
1382
1383;; An explanation of the calculation can be found in PascAlgorithms by
1384;; Edward and Ruth Reingold, Scott-Foresman/Little, Brown, 1988.
1385
1386(defsubst calendar-day-number (date)
e5d77022
JB
1387 "Return the day number within the year of the date DATE.
1388For example, (calendar-day-number '(1 1 1987)) returns the value 1,
1389while (calendar-day-number '(12 31 1980)) returns 366."
cba0c253
ER
1390 (let* ((month (extract-calendar-month date))
1391 (day (extract-calendar-day date))
1392 (year (extract-calendar-year date))
1393 (day-of-year (+ day (* 31 (1- month)))))
1394 (if (> month 2)
1395 (progn
1396 (setq day-of-year (- day-of-year (/ (+ 23 (* 4 month)) 10)))
1397 (if (calendar-leap-year-p year)
e5d77022 1398 (setq day-of-year (1+ day-of-year)))))
cba0c253
ER
1399 day-of-year))
1400
1401(defsubst calendar-absolute-from-gregorian (date)
e5d77022 1402 "The number of days elapsed between the Gregorian date 12/31/1 BC and DATE.
18db8896
GM
1403The Gregorian date Sunday, December 31, 1 BC is imaginary.
1404DATE is a list of the form (month day year). A negative year is
1405interpreted as BC; -1 being 1 BC, and so on. Dates before 12/31/1 BC
1406return negative results."
1407 (let ((year (extract-calendar-year date))
1408 offset-years)
1409 (cond ((= year 0)
1410 (error "There was no year zero"))
1411 ((> year 0)
1412 (setq offset-years (1- year))
1413 (+ (calendar-day-number date) ; Days this year
1414 (* 365 offset-years) ; + Days in prior years
1415 (/ offset-years 4) ; + Julian leap years
1416 (- (/ offset-years 100)) ; - century years
1417 (/ offset-years 400))) ; + Gregorian leap years
1418 (t
1419 ;; Years between date and 1 BC, excluding 1 BC (1 for 2 BC, etc).
1420 (setq offset-years (abs (1+ year)))
1421 (- (calendar-day-number date)
1422 (* 365 offset-years)
1423 (/ offset-years 4)
1424 (- (/ offset-years 100))
1425 (/ offset-years 400)
1426 (calendar-day-number '(12 31 -1))))))) ; days in year 1 BC
e5d77022 1427
7086b78e
ER
1428(autoload 'calendar-goto-today "cal-move"
1429 "Reposition the calendar window so the current date is visible."
1430 t)
1431
1432(autoload 'calendar-forward-month "cal-move"
1433 "Move the cursor forward ARG months."
1434 t)
1435
1436(autoload 'calendar-forward-year "cal-move"
1437 "Move the cursor forward by ARG years."
1438 t)
1439
1440(autoload 'calendar-backward-month "cal-move"
1441 "Move the cursor backward by ARG months."
1442 t)
1443
1444(autoload 'calendar-backward-year "cal-move"
1445 "Move the cursor backward ARG years."
1446 t)
1447
1448(autoload 'scroll-calendar-left "cal-move"
1449 "Scroll the displayed calendar left by ARG months."
1450 t)
1451
1452(autoload 'scroll-calendar-right "cal-move"
1453 "Scroll the displayed calendar window right by ARG months."
1454 t)
1455
1456(autoload 'scroll-calendar-left-three-months "cal-move"
1457 "Scroll the displayed calendar window left by 3*ARG months."
1458 t)
1459
1460(autoload 'scroll-calendar-right-three-months "cal-move"
1461 "Scroll the displayed calendar window right by 3*ARG months."
1462 t)
1463
1464(autoload 'calendar-cursor-to-nearest-date "cal-move"
1465 "Move the cursor to the closest date."
1466 t)
1467
1468(autoload 'calendar-forward-day "cal-move"
1469 "Move the cursor forward ARG days."
1470 t)
1471
1472(autoload 'calendar-backward-day "cal-move"
1473 "Move the cursor back ARG days."
1474 t)
1475
1476(autoload 'calendar-forward-week "cal-move"
1477 "Move the cursor forward ARG weeks."
1478 t)
1479
1480(autoload 'calendar-backward-week "cal-move"
1481 "Move the cursor back ARG weeks."
1482 t)
1483
1484(autoload 'calendar-beginning-of-week "cal-move"
1485 "Move the cursor back ARG calendar-week-start-day's."
1486 t)
1487
1488(autoload 'calendar-end-of-week "cal-move"
1489 "Move the cursor forward ARG calendar-week-start-day+6's."
1490 t)
1491
1492(autoload 'calendar-beginning-of-month "cal-move"
1493 "Move the cursor backward ARG month beginnings."
1494 t)
1495
1496(autoload 'calendar-end-of-month "cal-move"
1497 "Move the cursor forward ARG month ends."
1498 t)
1499
1500(autoload 'calendar-beginning-of-year "cal-move"
1501 "Move the cursor backward ARG year beginnings."
1502 t)
1503
1504(autoload 'calendar-end-of-year "cal-move"
1505 "Move the cursor forward ARG year beginnings."
1506 t)
1507
1508(autoload 'calendar-cursor-to-visible-date "cal-move"
1509 "Move the cursor to DATE that is on the screen."
1510 t)
1511
1512(autoload 'calendar-goto-date "cal-move"
1513 "Move cursor to DATE."
1514 t)
1515
8923d271
GM
1516(autoload 'calendar-goto-day-of-year "cal-move"
1517 "Move cursor to day of year."
1518 t)
1519
945e6102
GM
1520(autoload 'calendar-only-one-frame-setup "cal-x"
1521 "Start calendar and display it in a dedicated frame.")
1522
7086b78e
ER
1523(autoload 'calendar-one-frame-setup "cal-x"
1524 "Start calendar and display it in a dedicated frame together with the diary.")
1525
1526(autoload 'calendar-two-frame-setup "cal-x"
1527 "Start calendar and diary in separate, dedicated frames.")
7e1e5cf1 1528
7086b78e 1529;;;###autoload
1293540e
GM
1530(defcustom calendar-setup nil
1531 "The frame setup of the calendar.
1532The choices are: `one-frame' (calendar and diary together in one separate,
1533dedicated frame); `two-frames' (calendar and diary in separate, dedicated
1534frames); `calendar-only' (calendar in a separate, dedicated frame); with
1535any other value the current frame is used. Using any of the first
1536three options overrides the value of `view-diary-entries-initially'."
1537 :type '(choice
1538 (const :tag "calendar and diary in separate frame" one-frame)
1539 (const :tag "calendar and diary each in own frame" two-frames)
1540 (const :tag "calendar in separate frame" calendar-only)
1541 (const :tag "use current frame" nil))
1542 :group 'calendar)
7086b78e 1543
94b304d7 1544;;;###autoload
ecaa0527 1545(defun calendar (&optional arg)
7086b78e 1546 "Choose between the one frame, two frame, or basic calendar displays.
bc461571
EZ
1547If called with an optional prefix argument, prompts for month and year.
1548
1549The original function `calendar' has been renamed `calendar-basic-setup'.
1550See the documentation of that function for more information."
7086b78e
ER
1551 (interactive "P")
1552 (cond ((equal calendar-setup 'one-frame) (calendar-one-frame-setup arg))
1553 ((equal calendar-setup 'two-frames) (calendar-two-frame-setup arg))
a4410177
KH
1554 ((equal calendar-setup 'calendar-only)
1555 (calendar-only-one-frame-setup arg))
7086b78e
ER
1556 (t (calendar-basic-setup arg))))
1557
1558(defun calendar-basic-setup (&optional arg)
ecaa0527
RS
1559 "Display a three-month calendar in another window.
1560The three months appear side by side, with the current month in the middle
1561surrounded by the previous and next months. The cursor is put on today's date.
1562
7e1dae73
JB
1563If called with an optional prefix argument, prompts for month and year.
1564
ecaa0527
RS
1565This function is suitable for execution in a .emacs file; appropriate setting
1566of the variable `view-diary-entries-initially' will cause the diary entries for
1567the current date to be displayed in another window. The value of the variable
1568`number-of-diary-entries' controls the number of days of diary entries
1569displayed upon initial display of the calendar.
1570
ecaa0527
RS
1571Once in the calendar window, future or past months can be moved into view.
1572Arbitrary months can be displayed, or the calendar can be scrolled forward
1573or backward.
1574
1575The cursor can be moved forward or backward by one day, one week, one month,
1576or one year. All of these commands take prefix arguments which, when negative,
1577cause movement in the opposite direction. For convenience, the digit keys
1578and the minus sign are automatically prefixes. The window is replotted as
1579necessary to display the desired date.
1580
1581Diary entries can be marked on the calendar or displayed in another window.
1582
3cbb4860 1583Use \\[describe-mode] for details of the key bindings in the calendar window.
ecaa0527
RS
1584
1585The Gregorian calendar is assumed.
1586
7e1dae73 1587After loading the calendar, the hooks given by the variable
2b803765 1588`calendar-load-hook' are run. This is the place to add key bindings to the
7e1dae73
JB
1589calendar-mode-map.
1590
ecaa0527
RS
1591After preparing the calendar window initially, the hooks given by the variable
1592`initial-calendar-window-hook' are run.
1593
1594The hooks given by the variable `today-visible-calendar-hook' are run
a69472b3 1595every time the calendar window gets scrolled, if the current date is visible
ecaa0527
RS
1596in the window. If it is not visible, the hooks given by the variable
1597`today-invisible-calendar-hook' are run. Thus, for example, setting
1598`today-visible-calendar-hook' to 'calendar-star-date will cause today's date
1599to be replaced by asterisks to highlight it whenever it is in the window."
1600 (interactive "P")
ecaa0527
RS
1601 (set-buffer (get-buffer-create calendar-buffer))
1602 (calendar-mode)
ecd42d42 1603 (let* ((pop-up-windows t)
7e1dae73 1604 (split-height-threshold 1000)
cba0c253
ER
1605 (date (if arg
1606 (calendar-read-date t)
1607 (calendar-current-date)))
1608 (month (extract-calendar-month date))
1609 (year (extract-calendar-year date)))
ecaa0527 1610 (pop-to-buffer calendar-buffer)
cba0c253 1611 (increment-calendar-month month year (- calendar-offset))
7e1dae73
JB
1612 (generate-calendar-window month year)
1613 (if (and view-diary-entries-initially (calendar-date-is-visible-p date))
1614 (view-diary-entries
1615 (if (vectorp number-of-diary-entries)
1616 (aref number-of-diary-entries (calendar-day-of-week date))
1617 number-of-diary-entries))))
1618 (let* ((diary-buffer (get-file-buffer diary-file))
1619 (diary-window (if diary-buffer (get-buffer-window diary-buffer)))
1620 (split-height-threshold (if diary-window 2 1000)))
1621 (if view-calendar-holidays-initially
1622 (list-calendar-holidays)))
ecaa0527
RS
1623 (run-hooks 'initial-calendar-window-hook))
1624
fb30f0ce 1625(autoload 'view-diary-entries "diary-lib"
ecaa0527 1626 "Prepare and display a buffer with diary entries.
6b1abbd1 1627Searches your diary file for entries that match ARG days starting with
ecaa0527
RS
1628the date indicated by the cursor position in the displayed three-month
1629calendar."
1630 t)
1631
7e1dae73
JB
1632(autoload 'calendar-sunrise-sunset "solar"
1633 "Local time of sunrise and sunset for date under cursor."
1634 t)
1635
1636(autoload 'calendar-phases-of-moon "lunar"
1637 "Create a buffer of the phases of the moon for the current calendar window."
1638 t)
1639
1640(autoload 'calendar-print-french-date "cal-french"
6a2aa94c 1641 "Show the French Revolutionary calendar equivalent of the date under the cursor."
7e1dae73
JB
1642 t)
1643
1644(autoload 'calendar-goto-french-date "cal-french"
1645 "Move cursor to French Revolutionary date."
1646 t)
1647
6a2aa94c 1648(autoload 'calendar-french-date-string "cal-french"
7086b78e 1649 "String of French Revolutionary date of Gregorian date."
6a2aa94c
RS
1650 t)
1651
1652(autoload 'calendar-mayan-date-string "cal-mayan"
7086b78e 1653 "String of Mayan date of Gregorian date."
6a2aa94c
RS
1654 t)
1655
7e1dae73 1656(autoload 'calendar-print-mayan-date "cal-mayan"
6a2aa94c 1657 "Show the Mayan long count, Tzolkin, and Haab equivalents of the date under the cursor."
7e1dae73
JB
1658 t)
1659
1660(autoload 'calendar-goto-mayan-long-count-date "cal-mayan"
1661 "Move cursor to Mayan long count date."
1662 t)
1663
1664(autoload 'calendar-next-haab-date "cal-mayan"
1665 "Move cursor to next instance of Mayan Haab date."
1666 t)
1667
1668(autoload 'calendar-previous-haab-date "cal-mayan"
1669 "Move cursor to previous instance of Mayan Haab date."
1670 t)
1671
1672(autoload 'calendar-next-tzolkin-date "cal-mayan"
1673 "Move cursor to next instance of Mayan Tzolkin date."
1674 t)
1675
1676(autoload 'calendar-previous-tzolkin-date "cal-mayan"
1677 "Move cursor to previous instance of Mayan Tzolkin date."
1678 t)
1679
1680(autoload 'calendar-next-calendar-round-date "cal-mayan"
a69472b3 1681 "Move cursor to next instance of Mayan Haab/Tzolkin combination."
7e1dae73
JB
1682 t)
1683
1684(autoload 'calendar-previous-calendar-round-date "cal-mayan"
a69472b3 1685 "Move cursor to previous instance of Mayan Haab/Tzolkin combination."
7e1dae73
JB
1686 t)
1687
327b6868 1688(autoload 'calendar-goto-chinese-date "cal-china"
6cf0fb79 1689 "Move cursor to Chinese date."
7086b78e
ER
1690 t)
1691
327b6868 1692(autoload 'calendar-print-chinese-date "cal-china"
7086b78e
ER
1693 "Show the Chinese date equivalents of date."
1694 t)
1695
327b6868 1696(autoload 'calendar-chinese-date-string "cal-china"
7086b78e
ER
1697 "String of Chinese date of Gregorian date."
1698 t)
1699
d1b8adf7 1700(autoload 'calendar-absolute-from-astro "cal-julian"
6cf0fb79 1701 "Absolute date of astronomical (Julian) day number D."
d1b8adf7 1702 t )
6cf0fb79 1703
14fcc701
KH
1704(autoload 'calendar-astro-from-absolute "cal-julian"
1705 "Astronomical (Julian) day number of absolute date D.")
1706
6cf0fb79
ER
1707(autoload 'calendar-astro-date-string "cal-julian"
1708 "String of astronomical (Julian) day number of Gregorian date."
1709 t)
1710
435d749c 1711(autoload 'calendar-goto-astro-day-number "cal-julian"
6cf0fb79
ER
1712 "Move cursor to astronomical (Julian) day number."
1713 t)
1714
d1b8adf7
GM
1715(autoload 'calendar-print-astro-day-number "cal-julian"
1716 "Show the astro date equivalents of date."
1717 t)
1718
6dcba8a3
RS
1719(autoload 'calendar-julian-from-absolute "cal-julian"
1720 "Compute the Julian (month day year) corresponding to the absolute DATE.
1721The absolute date is the number of days elapsed since the (imaginary)
1722Gregorian date Sunday, December 31, 1 BC.")
1723
7086b78e
ER
1724(autoload 'calendar-goto-julian-date "cal-julian"
1725 "Move cursor to Julian DATE; echo Julian date unless NOECHO is t."
1726 t)
1727
2b3f69c8
RS
1728(autoload 'calendar-print-julian-date "cal-julian"
1729 "Show the Julian calendar equivalent of the date under the cursor."
1730 t)
1731
07986bc4
RS
1732(autoload 'calendar-julian-date-string "cal-julian"
1733 "String of Julian date of Gregorian DATE.
1734Defaults to today's date if DATE is not given.
bfca0f6b 1735Driven by the variable `calendar-date-display-form'.")
07986bc4 1736
7086b78e
ER
1737(autoload 'calendar-goto-iso-date "cal-iso"
1738 "Move cursor to ISO date."
1739 t)
1740
1741(autoload 'calendar-print-iso-date "cal-iso"
1742 "Show the ISO date equivalents of date."
1743 t)
1744
1745(autoload 'calendar-iso-date-string "cal-iso"
1746 "String of ISO date of Gregorian date."
1747 t)
1748
93867648
GM
1749(autoload 'calendar-goto-islamic-date "cal-islam"
1750 "Move cursor to Islamic date."
1751 t)
1752
327b6868 1753(autoload 'calendar-print-islamic-date "cal-islam"
7086b78e
ER
1754 "Show the Islamic date equivalents of date."
1755 t)
1756
327b6868 1757(autoload 'calendar-islamic-date-string "cal-islam"
7086b78e
ER
1758 "String of Islamic date of Gregorian date."
1759 t)
1760
811a8484
JW
1761(autoload 'calendar-print-bahai-date "cal-bahai"
1762 "Show the Baha'i date equivalents of date."
1763 t)
1764
1765(autoload 'calendar-bahai-date-string "cal-bahai"
1766 "String of Baha'i date of Gregorian date."
1767 t)
1768
7086b78e
ER
1769(autoload 'calendar-goto-hebrew-date "cal-hebrew"
1770 "Move cursor to Hebrew date date."
1771 t)
1772
1773(autoload 'calendar-print-hebrew-date "cal-hebrew"
1774 "Show the Hebrew date equivalents of date."
1775 t)
1776
1777(autoload 'calendar-hebrew-date-string "cal-hebrew"
1778 "String of Hebrew date of Gregorian date."
1779 t)
1780
1781(autoload 'calendar-goto-coptic-date "cal-coptic"
1782 "Move cursor to Coptic date date."
1783 t)
1784
1785(autoload 'calendar-print-coptic-date "cal-coptic"
1786 "Show the Coptic date equivalents of date."
1787 t)
1788
1789(autoload 'calendar-coptic-date-string "cal-coptic"
1790 "String of Coptic date of Gregorian date."
1791 t)
1792
1793(autoload 'calendar-goto-ethiopic-date "cal-coptic"
1794 "Move cursor to Ethiopic date date."
1795 t)
1796
1797(autoload 'calendar-print-ethiopic-date "cal-coptic"
1798 "Show the Ethiopic date equivalents of date."
1799 t)
1800
1801(autoload 'calendar-ethiopic-date-string "cal-coptic"
1802 "String of Ethiopic date of Gregorian date."
1803 t)
1804
a45eee72 1805(autoload 'calendar-goto-persian-date "cal-persia"
c21eb13d
ER
1806 "Move cursor to Persian date date."
1807 t)
1808
a45eee72 1809(autoload 'calendar-print-persian-date "cal-persia"
c21eb13d
ER
1810 "Show the Persian date equivalents of date."
1811 t)
1812
a45eee72 1813(autoload 'calendar-persian-date-string "cal-persia"
c21eb13d
ER
1814 "String of Persian date of Gregorian date."
1815 t)
1816
fb30f0ce 1817(autoload 'show-all-diary-entries "diary-lib"
6b1abbd1
RS
1818 "Show all of the diary entries in the diary file.
1819This function gets rid of the selective display of the diary file so that
ecaa0527
RS
1820all entries, not just some, are visible. If there is no diary buffer, one
1821is created."
1822 t)
1823
fb30f0ce 1824(autoload 'mark-diary-entries "diary-lib"
ecaa0527 1825 "Mark days in the calendar window that have diary entries.
6b1abbd1 1826Each entry in diary file visible in the calendar window is marked."
ecaa0527
RS
1827 t)
1828
fb30f0ce 1829(autoload 'make-diary-entry "diary-lib"
7086b78e
ER
1830 "Insert a diary entry STRING which may be NONMARKING in FILE."
1831 t)
1832
fb30f0ce 1833(autoload 'insert-diary-entry "diary-lib"
ecaa0527
RS
1834 "Insert a diary entry for the date indicated by point."
1835 t)
1836
fb30f0ce 1837(autoload 'insert-weekly-diary-entry "diary-lib"
ecaa0527
RS
1838 "Insert a weekly diary entry for the day of the week indicated by point."
1839 t)
1840
354d0644 1841
fb30f0ce 1842(autoload 'insert-monthly-diary-entry "diary-lib"
ecaa0527
RS
1843 "Insert a monthly diary entry for the day of the month indicated by point."
1844 t)
1845
fb30f0ce 1846(autoload 'insert-yearly-diary-entry "diary-lib"
ecaa0527
RS
1847 "Insert an annual diary entry for the day of the year indicated by point."
1848 t)
1849
fb30f0ce 1850(autoload 'insert-anniversary-diary-entry "diary-lib"
ecaa0527
RS
1851 "Insert an anniversary diary entry for the date indicated by point."
1852 t)
1853
fb30f0ce 1854(autoload 'insert-block-diary-entry "diary-lib"
ecaa0527
RS
1855 "Insert a block diary entry for the dates indicated by point and mark."
1856 t)
1857
fb30f0ce 1858(autoload 'insert-cyclic-diary-entry "diary-lib"
ecaa0527
RS
1859 "Insert a cyclic diary entry starting at the date indicated by point."
1860 t)
1861
7086b78e 1862(autoload 'insert-hebrew-diary-entry "cal-hebrew"
ecaa0527
RS
1863 "Insert a diary entry for the Hebrew date corresponding to the date
1864indicated by point."
1865 t)
1866
7086b78e 1867(autoload 'insert-monthly-hebrew-diary-entry "cal-hebrew"
ecaa0527
RS
1868 "Insert a monthly diary entry for the day of the Hebrew month corresponding
1869to the date indicated by point."
1870 t)
1871
7086b78e 1872(autoload 'insert-yearly-hebrew-diary-entry "cal-hebrew"
ecaa0527
RS
1873 "Insert an annual diary entry for the day of the Hebrew year corresponding
1874to the date indicated by point."
1875 t)
1876
327b6868 1877(autoload 'insert-islamic-diary-entry "cal-islam"
ecaa0527
RS
1878 "Insert a diary entry for the Islamic date corresponding to the date
1879indicated by point."
1880 t)
1881
327b6868 1882(autoload 'insert-monthly-islamic-diary-entry "cal-islam"
ecaa0527
RS
1883 "Insert a monthly diary entry for the day of the Islamic month corresponding
1884to the date indicated by point."
1885 t)
1886
327b6868 1887(autoload 'insert-yearly-islamic-diary-entry "cal-islam"
ecaa0527
RS
1888 "Insert an annual diary entry for the day of the Islamic year corresponding
1889to the date indicated by point."
1890 t)
1891
811a8484
JW
1892(autoload 'insert-bahai-diary-entry "cal-bahai"
1893 "Insert a diary entry for the Baha'i date corresponding to the date
1894indicated by point."
1895 t)
1896
1897(autoload 'insert-monthly-bahai-diary-entry "cal-bahai"
1898 "Insert a monthly diary entry for the day of the Baha'i month corresponding
1899to the date indicated by point."
1900 t)
1901
1902(autoload 'insert-yearly-bahai-diary-entry "cal-bahai"
1903 "Insert an annual diary entry for the day of the Baha'i year corresponding
1904to the date indicated by point."
1905 t)
1906
ecaa0527
RS
1907(autoload 'list-calendar-holidays "holidays"
1908 "Create a buffer containing the holidays for the current calendar window.
1909The holidays are those in the list `calendar-notable-days'. Returns t if any
1910holidays are found, nil if not."
1911 t)
1912
3076647c
ER
1913(autoload 'cal-tex-cursor-month "cal-tex"
1914 "Make a buffer with LaTeX commands for the month cursor is on.
1915Optional prefix argument specifies number of months to be produced.
1916Calendar is condensed onto one page.")
1917
1918(autoload 'cal-tex-cursor-month-landscape "cal-tex"
1919 "Make a buffer with LaTeX commands for the month cursor is on.
1920Optional prefix argument specifies number of months to be produced.")
1921
1922(autoload 'cal-tex-cursor-day "cal-tex"
1923 "Make a buffer with LaTeX commands for the day cursor is on.")
1924
1925(autoload 'cal-tex-cursor-week "cal-tex"
5a2c140a
RS
1926 "Make a buffer with LaTeX commands for a two-page one-week calendar.
1927It applies to the week that point is in.
1928Optional prefix argument specifies number of weeks.
1929Holidays are included if `cal-tex-holidays' is t.")
1930
7e1e5cf1 1931(autoload 'cal-tex-cursor-week2 "cal-tex"
5a2c140a
RS
1932 "Make a buffer with LaTeX commands for a two-page one-week calendar.
1933It applies to the week that point is in.
1934Optional prefix argument specifies number of weeks.
1935Holidays are included if `cal-tex-holidays' is t.")
1936
1937(autoload 'cal-tex-cursor-week-iso "cal-tex"
1938 "Make a buffer with LaTeX commands for a one page ISO-style weekly calendar.
07e4feff 1939Optional prefix argument specifies number of weeks.
5a2c140a
RS
1940Diary entries are included if `cal-tex-diary' is t.
1941Holidays are included if `cal-tex-holidays' is t.")
1942
1943(autoload 'cal-tex-cursor-week-monday "cal-tex"
1944 "Make a buffer with LaTeX commands for a two-page one-week calendar.
1945It applies to the week that point is in, and starts on Monday.
1946Optional prefix argument specifies number of weeks.
1947Holidays are included if `cal-tex-holidays' is t.")
1948
1949(autoload 'cal-tex-cursor-filofax-2week "cal-tex"
1950 "Two-weeks-at-a-glance Filofax style calendar for week indicated by cursor.
1951Optional prefix argument specifies number of weeks.
1952Diary entries are included if cal-tex-diary is t.
1953Holidays are included if `cal-tex-holidays' is t.")
1954
1955(autoload 'cal-tex-cursor-filofax-week "cal-tex"
1956 "One-week-at-a-glance Filofax style calendar for week indicated by cursor.
1957Optional prefix argument specifies number of weeks.
7e1e5cf1 1958Weeks start on Monday.
5a2c140a
RS
1959Diary entries are included if cal-tex-diary is t.
1960Holidays are included if `cal-tex-holidays' is t.")
3076647c 1961
9018e77d
KH
1962(autoload 'cal-tex-cursor-filofax-daily "cal-tex"
1963 "Day-per-page Filofax style calendar for week indicated by cursor.
7e1e5cf1 1964Optional prefix argument specifies number of weeks. Weeks start on Monday.
9018e77d
KH
1965Diary entries are included if `cal-tex-diary' is t.
1966Holidays are included if `cal-tex-holidays' is t.")
1967
3076647c
ER
1968(autoload 'cal-tex-cursor-year "cal-tex"
1969 "Make a buffer with LaTeX commands for a year's calendar.
a69472b3 1970Optional prefix argument specifies number of years.")
3076647c
ER
1971
1972(autoload 'cal-tex-cursor-year-landscape "cal-tex"
1973 "Make a buffer with LaTeX commands for a year's calendar (landscape).
1974Optional prefix argument specifies number of years.")
1975
1976(autoload 'cal-tex-cursor-filofax-year "cal-tex"
1977 "Make a buffer with LaTeX commands for a year's calendar (Filofax).
1978Optional prefix argument specifies number of years.")
1979
ecaa0527
RS
1980(autoload 'mark-calendar-holidays "holidays"
1981 "Mark notable days in the calendar window."
1982 t)
1983
1984(autoload 'calendar-cursor-holidays "holidays"
1985 "Find holidays for the date specified by the cursor in the calendar window."
1986 t)
1987
7e1dae73
JB
1988(defun generate-calendar-window (&optional mon yr)
1989 "Generate the calendar window for the current date.
1990Or, for optional MON, YR."
ecaa0527 1991 (let* ((buffer-read-only nil)
ecaa0527
RS
1992 (today (calendar-current-date))
1993 (month (extract-calendar-month today))
1994 (day (extract-calendar-day today))
1995 (year (extract-calendar-year today))
7e1dae73
JB
1996 (today-visible
1997 (or (not mon)
1998 (let ((offset (calendar-interval mon yr month year)))
1999 (and (<= offset 1) (>= offset -1)))))
ecaa0527
RS
2000 (day-in-week (calendar-day-of-week today)))
2001 (update-calendar-mode-line)
7e1dae73
JB
2002 (if mon
2003 (generate-calendar mon yr)
2004 (generate-calendar month year))
ecaa0527
RS
2005 (calendar-cursor-to-visible-date
2006 (if today-visible today (list displayed-month 1 displayed-year)))
2007 (set-buffer-modified-p nil)
31754518
MB
2008 (if (or (one-window-p t) (/= (frame-width) (window-width)))
2009 ;; Don't mess with the window size, but ensure that the first
2010 ;; line is fully visible
2011 (set-window-vscroll nil 0)
2012 ;; Adjust the window to exactly fit the displayed calendar
b85fa13c 2013 (fit-window-to-buffer))
ecaa0527 2014 (sit-for 0)
d13c1378
JB
2015 (if (and (boundp 'font-lock-mode)
2016 font-lock-mode)
5d22135b 2017 (font-lock-fontify-buffer))
ecaa0527 2018 (and mark-holidays-in-calendar
d519ea8a 2019;;; (calendar-date-is-legal-p today) ; useful for BC dates
ecaa0527
RS
2020 (mark-calendar-holidays)
2021 (sit-for 0))
2022 (unwind-protect
2023 (if mark-diary-entries-in-calendar (mark-diary-entries))
2024 (if today-visible
2025 (run-hooks 'today-visible-calendar-hook)
2026 (run-hooks 'today-invisible-calendar-hook)))))
2027
2028(defun generate-calendar (month year)
4c635ea3
GM
2029 "Generate a three-month Gregorian calendar centered around MONTH, YEAR."
2030;;; A negative YEAR is interpreted as BC; -1 being 1 BC, and so on.
2031;;; Note that while calendars for years BC could be displayed as it
2032;;; stands, almost all other calendar functions (eg holidays) would
2033;;; at best have unpredictable results for such dates.
2034 (if (< (+ month (* 12 (1- year))) 2)
2035 (error "Months before February, 1 AD are not available"))
2036 (setq displayed-month month
2037 displayed-year year)
ecaa0527
RS
2038 (erase-buffer)
2039 (increment-calendar-month month year -1)
2040 (calendar-for-loop i from 0 to 2 do
2041 (generate-calendar-month month year (+ 5 (* 25 i)))
2042 (increment-calendar-month month year 1)))
2043
2044(defun generate-calendar-month (month year indent)
2045 "Produce a calendar for MONTH, YEAR on the Gregorian calendar.
f2172a68
EZ
2046The calendar is inserted at the top of the buffer in which point is currently
2047located, but indented INDENT spaces. The indentation is done from the first
2048character on the line and does not disturb the first INDENT characters on the
4c635ea3 2049line."
d8a200a7 2050 (let* ((blank-days;; at start of month
b6c0aabf 2051 (mod
d8a200a7
RS
2052 (- (calendar-day-of-week (list month 1 year))
2053 calendar-week-start-day)
2054 7))
2055 (last (calendar-last-day-of-month month year)))
2056 (goto-char (point-min))
2057 (calendar-insert-indented
2058 (calendar-string-spread
cbecb9f9 2059 (list (format "%s %d" (calendar-month-name month) year)) ? 20)
d8a200a7
RS
2060 indent t)
2061 (calendar-insert-indented "" indent);; Go to proper spot
2c8811d4 2062 ;; Use the first two characters of each day to head the columns.
d8a200a7 2063 (calendar-for-loop i from 0 to 6 do
2c8811d4
GM
2064 (insert
2065 (let ((string
2066 (calendar-day-name (mod (+ calendar-week-start-day i) 7) nil t)))
2067 (if enable-multibyte-characters
2068 (truncate-string-to-width string 2)
2069 (substring string 0 2)))
2070 " "))
d8a200a7
RS
2071 (calendar-insert-indented "" 0 t);; Force onto following line
2072 (calendar-insert-indented "" indent);; Go to proper spot
2073 ;; Add blank days before the first of the month
2074 (calendar-for-loop i from 1 to blank-days do (insert " "))
2075 ;; Put in the days of the month
2076 (calendar-for-loop i from 1 to last do
2077 (insert (format "%2d " i))
218abc51
EZ
2078 (add-text-properties
2079 (- (point) 3) (1- (point))
2080 '(mouse-face highlight
2081 help-echo "mouse-2: menu of operations for this date"))
b6c0aabf 2082 (and (zerop (mod (+ i blank-days) 7))
d8a200a7
RS
2083 (/= i last)
2084 (calendar-insert-indented "" 0 t) ;; Force onto following line
2085 (calendar-insert-indented "" indent)))));; Go to proper spot
ecaa0527
RS
2086
2087(defun calendar-insert-indented (string indent &optional newline)
2088 "Insert STRING at column INDENT.
2089If the optional parameter NEWLINE is t, leave point at start of next line,
2090inserting a newline if there was no next line; otherwise, leave point after
2091the inserted text. Value is always t."
2092 ;; Try to move to that column.
2093 (move-to-column indent)
2094 ;; If line is too short, indent out to that column.
2095 (if (< (current-column) indent)
2096 (indent-to indent))
2097 (insert string)
2098 ;; Advance to next line, if requested.
2099 (if newline
2100 (progn
2101 (end-of-line)
2102 (if (eobp)
2103 (newline)
2104 (forward-line 1))))
2105 t)
2106
2107(defun redraw-calendar ()
2108 "Redraw the calendar display."
2109 (interactive)
d172e3e4 2110 (let ((cursor-date (calendar-cursor-to-nearest-date)))
7e1dae73 2111 (generate-calendar-window displayed-month displayed-year)
ecaa0527
RS
2112 (calendar-cursor-to-visible-date cursor-date)))
2113
b032077a
RS
2114(defcustom calendar-debug-sexp nil
2115 "*Turn debugging on when evaluating a sexp in the diary or holiday list."
2116 :type 'boolean
2117 :group 'calendar)
354d0644 2118
ecaa0527
RS
2119(defvar calendar-mode-map nil)
2120(if calendar-mode-map
2121 nil
2122 (setq calendar-mode-map (make-sparse-keymap))
d24f1b15 2123 (require 'cal-menu)
ecaa0527
RS
2124 (calendar-for-loop i from 0 to 9 do
2125 (define-key calendar-mode-map (int-to-string i) 'digit-argument))
2126 (let ((l (list 'narrow-to-region 'mark-word 'mark-sexp 'mark-paragraph
6b39e127 2127 'mark-defun 'mark-whole-buffer 'mark-page
8f12817f
ER
2128 'downcase-region 'upcase-region 'kill-region
2129 'copy-region-as-kill 'capitalize-region 'write-region)))
6b39e127
RS
2130 (while l
2131 (substitute-key-definition (car l) 'calendar-not-implemented
2132 calendar-mode-map global-map)
2133 (setq l (cdr l))))
ecaa0527
RS
2134 (define-key calendar-mode-map "-" 'negative-argument)
2135 (define-key calendar-mode-map "\C-x>" 'scroll-calendar-right)
0d336f18 2136 (define-key calendar-mode-map [prior] 'scroll-calendar-right-three-months)
ff4373ed 2137 (define-key calendar-mode-map "\ev" 'scroll-calendar-right-three-months)
ecaa0527 2138 (define-key calendar-mode-map "\C-x<" 'scroll-calendar-left)
0d336f18 2139 (define-key calendar-mode-map [next] 'scroll-calendar-left-three-months)
ff4373ed 2140 (define-key calendar-mode-map "\C-v" 'scroll-calendar-left-three-months)
ecaa0527
RS
2141 (define-key calendar-mode-map "\C-b" 'calendar-backward-day)
2142 (define-key calendar-mode-map "\C-p" 'calendar-backward-week)
7e1dae73 2143 (define-key calendar-mode-map "\e{" 'calendar-backward-month)
ecaa0527
RS
2144 (define-key calendar-mode-map "\C-x[" 'calendar-backward-year)
2145 (define-key calendar-mode-map "\C-f" 'calendar-forward-day)
2146 (define-key calendar-mode-map "\C-n" 'calendar-forward-week)
e9c78f07
RS
2147 (define-key calendar-mode-map [left] 'calendar-backward-day)
2148 (define-key calendar-mode-map [up] 'calendar-backward-week)
2149 (define-key calendar-mode-map [right] 'calendar-forward-day)
2150 (define-key calendar-mode-map [down] 'calendar-forward-week)
7e1dae73 2151 (define-key calendar-mode-map "\e}" 'calendar-forward-month)
ecaa0527
RS
2152 (define-key calendar-mode-map "\C-x]" 'calendar-forward-year)
2153 (define-key calendar-mode-map "\C-a" 'calendar-beginning-of-week)
2154 (define-key calendar-mode-map "\C-e" 'calendar-end-of-week)
2155 (define-key calendar-mode-map "\ea" 'calendar-beginning-of-month)
2156 (define-key calendar-mode-map "\ee" 'calendar-end-of-month)
2157 (define-key calendar-mode-map "\e<" 'calendar-beginning-of-year)
2158 (define-key calendar-mode-map "\e>" 'calendar-end-of-year)
2159 (define-key calendar-mode-map "\C-@" 'calendar-set-mark)
5e2a0ae4 2160 ;; Many people are used to typing C-SPC and getting C-@.
e68e61b5 2161 (define-key calendar-mode-map [?\C- ] 'calendar-set-mark)
ecaa0527 2162 (define-key calendar-mode-map "\C-x\C-x" 'calendar-exchange-point-and-mark)
7e1dae73
JB
2163 (define-key calendar-mode-map "\e=" 'calendar-count-days-region)
2164 (define-key calendar-mode-map "gd" 'calendar-goto-date)
8923d271 2165 (define-key calendar-mode-map "gD" 'calendar-goto-day-of-year)
7e1dae73
JB
2166 (define-key calendar-mode-map "gj" 'calendar-goto-julian-date)
2167 (define-key calendar-mode-map "ga" 'calendar-goto-astro-day-number)
2168 (define-key calendar-mode-map "gh" 'calendar-goto-hebrew-date)
2169 (define-key calendar-mode-map "gi" 'calendar-goto-islamic-date)
811a8484 2170 (define-key calendar-mode-map "gb" 'calendar-goto-bahai-date)
7086b78e
ER
2171 (define-key calendar-mode-map "gC" 'calendar-goto-chinese-date)
2172 (define-key calendar-mode-map "gk" 'calendar-goto-coptic-date)
2173 (define-key calendar-mode-map "ge" 'calendar-goto-ethiopic-date)
c21eb13d 2174 (define-key calendar-mode-map "gp" 'calendar-goto-persian-date)
7e1dae73
JB
2175 (define-key calendar-mode-map "gc" 'calendar-goto-iso-date)
2176 (define-key calendar-mode-map "gf" 'calendar-goto-french-date)
2177 (define-key calendar-mode-map "gml" 'calendar-goto-mayan-long-count-date)
2178 (define-key calendar-mode-map "gmpc" 'calendar-previous-calendar-round-date)
2179 (define-key calendar-mode-map "gmnc" 'calendar-next-calendar-round-date)
2180 (define-key calendar-mode-map "gmph" 'calendar-previous-haab-date)
2181 (define-key calendar-mode-map "gmnh" 'calendar-next-haab-date)
2182 (define-key calendar-mode-map "gmpt" 'calendar-previous-tzolkin-date)
2183 (define-key calendar-mode-map "gmnt" 'calendar-next-tzolkin-date)
14f1a889
ER
2184 (define-key calendar-mode-map "Aa" 'appt-add)
2185 (define-key calendar-mode-map "Ad" 'appt-delete)
7e1dae73
JB
2186 (define-key calendar-mode-map "S" 'calendar-sunrise-sunset)
2187 (define-key calendar-mode-map "M" 'calendar-phases-of-moon)
2188 (define-key calendar-mode-map " " 'scroll-other-window)
ecaa0527 2189 (define-key calendar-mode-map "\C-c\C-l" 'redraw-calendar)
899b130e 2190 (define-key calendar-mode-map "." 'calendar-goto-today)
7e1dae73
JB
2191 (define-key calendar-mode-map "o" 'calendar-other-month)
2192 (define-key calendar-mode-map "q" 'exit-calendar)
2193 (define-key calendar-mode-map "a" 'list-calendar-holidays)
2194 (define-key calendar-mode-map "h" 'calendar-cursor-holidays)
2195 (define-key calendar-mode-map "x" 'mark-calendar-holidays)
2196 (define-key calendar-mode-map "u" 'calendar-unmark)
2197 (define-key calendar-mode-map "m" 'mark-diary-entries)
2198 (define-key calendar-mode-map "d" 'view-diary-entries)
46e07c15 2199 (define-key calendar-mode-map "D" 'view-other-diary-entries)
7e1dae73
JB
2200 (define-key calendar-mode-map "s" 'show-all-diary-entries)
2201 (define-key calendar-mode-map "pd" 'calendar-print-day-of-year)
7086b78e
ER
2202 (define-key calendar-mode-map "pC" 'calendar-print-chinese-date)
2203 (define-key calendar-mode-map "pk" 'calendar-print-coptic-date)
2204 (define-key calendar-mode-map "pe" 'calendar-print-ethiopic-date)
c21eb13d 2205 (define-key calendar-mode-map "pp" 'calendar-print-persian-date)
7e1dae73
JB
2206 (define-key calendar-mode-map "pc" 'calendar-print-iso-date)
2207 (define-key calendar-mode-map "pj" 'calendar-print-julian-date)
2208 (define-key calendar-mode-map "pa" 'calendar-print-astro-day-number)
2209 (define-key calendar-mode-map "ph" 'calendar-print-hebrew-date)
2210 (define-key calendar-mode-map "pi" 'calendar-print-islamic-date)
811a8484 2211 (define-key calendar-mode-map "pb" 'calendar-print-bahai-date)
7e1dae73
JB
2212 (define-key calendar-mode-map "pf" 'calendar-print-french-date)
2213 (define-key calendar-mode-map "pm" 'calendar-print-mayan-date)
726669d8 2214 (define-key calendar-mode-map "po" 'calendar-print-other-dates)
7e1dae73
JB
2215 (define-key calendar-mode-map "id" 'insert-diary-entry)
2216 (define-key calendar-mode-map "iw" 'insert-weekly-diary-entry)
2217 (define-key calendar-mode-map "im" 'insert-monthly-diary-entry)
2218 (define-key calendar-mode-map "iy" 'insert-yearly-diary-entry)
2219 (define-key calendar-mode-map "ia" 'insert-anniversary-diary-entry)
2220 (define-key calendar-mode-map "ib" 'insert-block-diary-entry)
2221 (define-key calendar-mode-map "ic" 'insert-cyclic-diary-entry)
2222 (define-key calendar-mode-map "ihd" 'insert-hebrew-diary-entry)
2223 (define-key calendar-mode-map "ihm" 'insert-monthly-hebrew-diary-entry)
2224 (define-key calendar-mode-map "ihy" 'insert-yearly-hebrew-diary-entry)
2225 (define-key calendar-mode-map "iid" 'insert-islamic-diary-entry)
2226 (define-key calendar-mode-map "iim" 'insert-monthly-islamic-diary-entry)
2227 (define-key calendar-mode-map "iiy" 'insert-yearly-islamic-diary-entry)
811a8484
JW
2228 (define-key calendar-mode-map "iBd" 'insert-bahai-diary-entry)
2229 (define-key calendar-mode-map "iBm" 'insert-monthly-bahai-diary-entry)
2230 (define-key calendar-mode-map "iBy" 'insert-yearly-bahai-diary-entry)
3076647c
ER
2231 (define-key calendar-mode-map "?" 'calendar-goto-info-node)
2232 (define-key calendar-mode-map "tm" 'cal-tex-cursor-month)
2233 (define-key calendar-mode-map "tM" 'cal-tex-cursor-month-landscape)
2234 (define-key calendar-mode-map "td" 'cal-tex-cursor-day)
2235 (define-key calendar-mode-map "tw1" 'cal-tex-cursor-week)
2236 (define-key calendar-mode-map "tw2" 'cal-tex-cursor-week2)
5a2c140a
RS
2237 (define-key calendar-mode-map "tw3" 'cal-tex-cursor-week-iso)
2238 (define-key calendar-mode-map "tw4" 'cal-tex-cursor-week-monday)
9018e77d 2239 (define-key calendar-mode-map "tfd" 'cal-tex-cursor-filofax-daily)
5a2c140a
RS
2240 (define-key calendar-mode-map "tfw" 'cal-tex-cursor-filofax-2week)
2241 (define-key calendar-mode-map "tfW" 'cal-tex-cursor-filofax-week)
3076647c
ER
2242 (define-key calendar-mode-map "tfy" 'cal-tex-cursor-filofax-year)
2243 (define-key calendar-mode-map "ty" 'cal-tex-cursor-year)
2244 (define-key calendar-mode-map "tY" 'cal-tex-cursor-year-landscape))
ecaa0527
RS
2245
2246(defun describe-calendar-mode ()
5d22135b 2247 "Create a help buffer with a brief description of the `calendar-mode'."
ecaa0527
RS
2248 (interactive)
2249 (with-output-to-temp-buffer "*Help*"
2250 (princ
2251 (format
2252 "Calendar Mode:\nFor a complete description, type %s\n%s\n"
2253 (substitute-command-keys
2254 "\\<calendar-mode-map>\\[describe-mode] from within the calendar")
2255 (substitute-command-keys "\\{calendar-mode-map}")))
ddbfcbde
KH
2256 (save-excursion
2257 (set-buffer standard-output)
2258 (help-mode))
ecaa0527
RS
2259 (print-help-return-message)))
2260
2261;; Calendar mode is suitable only for specially formatted data.
2262(put 'calendar-mode 'mode-class 'special)
2263
2264(defvar calendar-mode-line-format
7e1dae73 2265 (list
d4ff5db9
DL
2266 (propertize (substitute-command-keys
2267 "\\<calendar-mode-map>\\[scroll-calendar-left]")
2268 'help-echo "mouse-2: scroll left"
f059e122 2269 'keymap (make-mode-line-mouse-map 'mouse-2
989a6aa7 2270 'mouse-scroll-calendar-left))
7e1dae73 2271 "Calendar"
d4ff5db9
DL
2272 (concat
2273 (propertize
2274 (substitute-command-keys
2275 "\\<calendar-mode-map>\\[calendar-goto-info-node] info")
2276 'help-echo "mouse-2: read Info on Calendar"
f059e122 2277 'keymap (make-mode-line-mouse-map 'mouse-2 'calendar-goto-info-node))
d4ff5db9
DL
2278 "/"
2279 (propertize
2280 (substitute-command-keys
2281 "\\<calendar-mode-map>\\[calendar-other-month] other")
2282 'help-echo "mouse-2: choose another month"
f059e122 2283 'keymap (make-mode-line-mouse-map
989a6aa7 2284 'mouse-2 'mouse-calendar-other-month))
d4ff5db9
DL
2285 "/"
2286 (propertize
2287 (substitute-command-keys
2288 "\\<calendar-mode-map>\\[calendar-goto-today] today")
2289 'help-echo "mouse-2: go to today's date"
d0b56ec5 2290 'keymap (make-mode-line-mouse-map 'mouse-2 #'calendar-goto-today)))
7e1dae73 2291 '(calendar-date-string (calendar-current-date) t)
d4ff5db9
DL
2292 (propertize (substitute-command-keys
2293 "\\<calendar-mode-map>\\[scroll-calendar-right]")
2294 'help-echo "mouse-2: scroll right"
f059e122 2295 'keymap (make-mode-line-mouse-map
989a6aa7 2296 'mouse-2 'mouse-scroll-calendar-right)))
a39f5a80
RS
2297 "The mode line of the calendar buffer.
2298
2299This must be a list of items that evaluate to strings--those strings are
2300evaluated and concatenated together, evenly separated by blanks. The variable
2301`date' is available for use as the date under (or near) the cursor; `date'
2302defaults to the current date if it is otherwise undefined. Here is an example
8c64a298 2303value that has the Hebrew date, the day number/days remaining in the year,
a39f5a80
RS
2304and the ISO week/year numbers in the mode. When calendar-move-hook is set to
2305'update-calendar-mode-line, these mode line shows these values for the date
2306under the cursor:
2307
2308 (list
2309 \"\"
2310 '(calendar-hebrew-date-string date)
2311 '(let* ((year (extract-calendar-year date))
2312 (d (calendar-day-number date))
2313 (days-remaining
2314 (- (calendar-day-number (list 12 31 year)) d)))
2315 (format \"%d/%d\" d days-remaining))
2316 '(let* ((d (calendar-absolute-from-gregorian date))
2317 (iso-date (calendar-iso-from-absolute d)))
2318 (format \"ISO week %d of %d\"
2319 (extract-calendar-month iso-date)
2320 (extract-calendar-year iso-date)))
2321 \"\"))
2322")
ecaa0527 2323
989a6aa7
RS
2324(defun mouse-scroll-calendar-left (event)
2325 "Scroll the displayed calendar left by one month.
2326Maintains the relative position of the cursor
2327with respect to the calendar as well as possible."
2328 (interactive "e")
2329 (save-selected-window
2330 (select-window (posn-window (event-start event)))
2331 (scroll-calendar-left 1)))
2332
2333(defun mouse-scroll-calendar-right (event)
2334 "Scroll the displayed calendar right by one month.
2335Maintains the relative position of the cursor
2336with respect to the calendar as well as possible."
2337 (interactive "e")
2338 (save-selected-window
2339 (select-window (posn-window (event-start event)))
2340 (scroll-calendar-right 1)))
2341
2342(defun mouse-calendar-other-month (event)
2343 "Display a three-month calendar centered around a specified month and year."
2344 (interactive "e")
2345 (save-selected-window
2346 (select-window (posn-window (event-start event)))
2347 (call-interactively 'calendar-other-month)))
2348
cba0c253
ER
2349(defun calendar-goto-info-node ()
2350 "Go to the info node for the calendar."
2351 (interactive)
2352 (require 'info)
83ff5106
RS
2353 (let ((where (save-window-excursion
2354 (Info-find-emacs-command-nodes 'calendar))))
cba0c253 2355 (if (not where)
3afbc435 2356 (error "Couldn't find documentation for the calendar")
83ff5106
RS
2357 (let (same-window-buffer-names)
2358 (info))
cba0c253
ER
2359 (Info-find-node (car (car where)) (car (cdr (car where)))))))
2360
5d22135b
MR
2361
2362
ecaa0527 2363(defun calendar-mode ()
7e1dae73 2364 "A major mode for the calendar window.
ecaa0527 2365
cba0c253
ER
2366For a complete description, type \
2367\\<calendar-mode-map>\\[calendar-goto-info-node] from within the calendar.
ecaa0527 2368
cba0c253 2369\\<calendar-mode-map>\\{calendar-mode-map}"
ecaa0527
RS
2370
2371 (kill-all-local-variables)
2372 (setq major-mode 'calendar-mode)
2373 (setq mode-name "Calendar")
2374 (use-local-map calendar-mode-map)
2375 (setq buffer-read-only t)
2376 (setq indent-tabs-mode nil)
7e1dae73 2377 (update-calendar-mode-line)
d24f1b15 2378 (add-hook 'activate-menubar-hook 'cal-menu-update nil t)
ecaa0527 2379 (make-local-variable 'calendar-mark-ring)
ecaa0527 2380 (make-local-variable 'displayed-month);; Month in middle of window.
5d22135b
MR
2381 (make-local-variable 'displayed-year) ;; Year in middle of window.
2382 (set (make-local-variable 'font-lock-defaults)
2383 '(calendar-font-lock-keywords t)))
ecaa0527 2384
7e1dae73 2385(defun calendar-string-spread (strings char length)
cbecb9f9
ER
2386 "Concatenate list of STRINGS separated with copies of CHAR to fill LENGTH.
2387The effect is like mapconcat but the separating pieces are as balanced as
2388possible. Each item of STRINGS is evaluated before concatenation so it can
2389actually be an expression that evaluates to a string. If LENGTH is too short,
2390the STRINGS are just concatenated and the result truncated."
7e1dae73
JB
2391;; The algorithm is based on equation (3.25) on page 85 of Concrete
2392;; Mathematics by Ronald L. Graham, Donald E. Knuth, and Oren Patashnik,
2393;; Addison-Wesley, Reading, MA, 1989
cbecb9f9
ER
2394 (let* ((strings (mapcar 'eval
2395 (if (< (length strings) 2)
2396 (append (list "") strings (list ""))
2397 strings)))
7e1dae73
JB
2398 (n (- length (length (apply 'concat strings))))
2399 (m (1- (length strings)))
2400 (s (car strings))
2401 (strings (cdr strings))
2402 (i 0))
2403 (while strings
2404 (setq s (concat s
2405 (make-string (max 0 (/ (+ n i) m)) char)
2406 (car strings)))
2407 (setq i (1+ i))
2408 (setq strings (cdr strings)))
2409 (substring s 0 length)))
2410
ecaa0527
RS
2411(defun update-calendar-mode-line ()
2412 "Update the calendar mode line with the current date and date style."
2413 (if (bufferp (get-buffer calendar-buffer))
2414 (save-excursion
2415 (set-buffer calendar-buffer)
2416 (setq mode-line-format
7e1dae73 2417 (calendar-string-spread
a39f5a80
RS
2418 (let ((date (condition-case nil
2419 (calendar-cursor-to-nearest-date)
2420 (error (calendar-current-date)))))
2421 (mapcar 'eval calendar-mode-line-format))
2422 ? (frame-width)))
2423 (force-mode-line-update))))
ecaa0527 2424
cba0c253
ER
2425(defun calendar-window-list ()
2426 "List of all calendar-related windows."
2427 (let ((calendar-buffers (calendar-buffer-list))
2428 list)
d4ff5db9
DL
2429 (walk-windows (lambda (w)
2430 (if (memq (window-buffer w) calendar-buffers)
2431 (setq list (cons w list))))
cba0c253
ER
2432 nil t)
2433 list))
2434
2435(defun calendar-buffer-list ()
2436 "List of all calendar-related buffers."
2437 (let* ((diary-buffer (get-file-buffer diary-file))
2438 (buffers (list "*Yahrzeits*" lunar-phases-buffer holiday-buffer
9c73a356
ER
2439 fancy-diary-buffer diary-buffer calendar-buffer
2440 other-calendars-buffer))
cba0c253
ER
2441 (buffer-list nil)
2442 b)
2443 (while buffers
2444 (setq b (car buffers))
2445 (setq b (cond ((stringp b) (get-buffer b))
2446 ((bufferp b) b)
2447 (t nil)))
2448 (if b (setq buffer-list (cons b buffer-list)))
2449 (setq buffers (cdr buffers)))
2450 buffer-list))
2451
ecaa0527 2452(defun exit-calendar ()
cba0c253 2453 "Get out of the calendar window and hide it and related buffers."
ecaa0527 2454 (interactive)
cba0c253 2455 (let* ((diary-buffer (get-file-buffer diary-file)))
38023020
ER
2456 (if (or (not diary-buffer)
2457 (not (buffer-modified-p diary-buffer))
2458 (yes-or-no-p
2459 "Diary modified; do you really want to exit the calendar? "))
cba0c253
ER
2460 ;; Need to do this multiple times because one time can replace some
2461 ;; calendar-related buffers with other calendar-related buffers
2462 (mapcar (lambda (x)
2463 (mapcar 'calendar-hide-window (calendar-window-list)))
2464 (calendar-window-list)))))
2465
2466(defun calendar-hide-window (window)
2467 "Hide WINDOW if it is calendar-related."
2468 (let ((buffer (if (window-live-p window) (window-buffer window))))
2469 (if (memq buffer (calendar-buffer-list))
2470 (cond
13f0f988 2471 ((and (display-multi-frame-p)
cba0c253
ER
2472 (eq 'icon (cdr (assoc 'visibility
2473 (frame-parameters
2474 (window-frame window))))))
2475 nil)
13f0f988 2476 ((and (display-multi-frame-p) (window-dedicated-p window))
7e1e5cf1
SS
2477 (if calendar-remove-frame-by-deleting
2478 (delete-frame (window-frame window))
2479 (iconify-frame (window-frame window))))
cba0c253
ER
2480 ((not (and (select-window window) (one-window-p window)))
2481 (delete-window window))
2482 (t (set-buffer buffer)
2483 (bury-buffer))))))
ecaa0527 2484
ecaa0527 2485(defun calendar-current-date ()
3cbb4860 2486 "Return the current date in a list (month day year)."
d8396371
RS
2487 (let ((now (decode-time)))
2488 (list (nth 4 now) (nth 3 now) (nth 5 now))))
ecaa0527 2489
ffd82264 2490(defun calendar-cursor-to-date (&optional error)
3cbb4860 2491 "Return a list (month day year) of current cursor position.
ffd82264
RS
2492If cursor is not on a specific date, signals an error if optional parameter
2493ERROR is t, otherwise just returns nil."
c93b9aae
ER
2494 (let* ((segment (/ (current-column) 25))
2495 (month (% (+ displayed-month segment -1) 12))
2496 (month (if (= 0 month) 12 month))
2497 (year
2498 (cond
2499 ((and (= 12 month) (= segment 0)) (1- displayed-year))
2500 ((and (= 1 month) (= segment 2)) (1+ displayed-year))
2501 (t displayed-year))))
7086b78e 2502 (if (and (looking-at "[ 0-9]?[0-9][^0-9]")
c93b9aae
ER
2503 (< 2 (count-lines (point-min) (point))))
2504 (save-excursion
7086b78e
ER
2505 (if (not (looking-at " "))
2506 (re-search-backward "[^0-9]"))
c93b9aae
ER
2507 (list month
2508 (string-to-int (buffer-substring (1+ (point)) (+ 4 (point))))
2509 year))
21c8986e
ER
2510 (if (looking-at "\\*")
2511 (save-excursion
2512 (re-search-backward "[^*]")
2513 (if (looking-at ".\\*\\*")
3a7f8079 2514 (list month calendar-starred-day year)
21c8986e
ER
2515 (if error (error "Not on a date!"))))
2516 (if error (error "Not on a date!"))))))
ecaa0527 2517
354d0644
JB
2518;; The following version of calendar-gregorian-from-absolute is preferred for
2519;; reasons of clarity, BUT it's much slower than the version that follows it.
2520
2521;;(defun calendar-gregorian-from-absolute (date)
2522;; "Compute the list (month day year) corresponding to the absolute DATE.
2523;;The absolute date is the number of days elapsed since the (imaginary)
2524;;Gregorian date Sunday, December 31, 1 BC."
2525;; (let* ((approx (/ date 366));; Approximation from below.
2526;; (year ;; Search forward from the approximation.
2527;; (+ approx
2528;; (calendar-sum y approx
2529;; (>= date (calendar-absolute-from-gregorian (list 1 1 (1+ y))))
2530;; 1)))
2531;; (month ;; Search forward from January.
2532;; (1+ (calendar-sum m 1
2533;; (> date
2534;; (calendar-absolute-from-gregorian
2535;; (list m (calendar-last-day-of-month m year) year)))
2536;; 1)))
2537;; (day ;; Calculate the day by subtraction.
2538;; (- date
2539;; (1- (calendar-absolute-from-gregorian (list month 1 year))))))
2540;; (list month day year)))
2541
ecaa0527
RS
2542(defun calendar-gregorian-from-absolute (date)
2543 "Compute the list (month day year) corresponding to the absolute DATE.
2544The absolute date is the number of days elapsed since the (imaginary)
18db8896
GM
2545Gregorian date Sunday, December 31, 1 BC. This function does not
2546handle dates in years BC."
354d0644
JB
2547;; See the footnote on page 384 of ``Calendrical Calculations, Part II:
2548;; Three Historical Calendars'' by E. M. Reingold, N. Dershowitz, and S. M.
2549;; Clamen, Software--Practice and Experience, Volume 23, Number 4
2550;; (April, 1993), pages 383-404 for an explanation.
2551 (let* ((d0 (1- date))
2552 (n400 (/ d0 146097))
2553 (d1 (% d0 146097))
2554 (n100 (/ d1 36524))
2555 (d2 (% d1 36524))
2556 (n4 (/ d2 1461))
2557 (d3 (% d2 1461))
2558 (n1 (/ d3 365))
2559 (day (1+ (% d3 365)))
2560 (year (+ (* 400 n400) (* 100 n100) (* n4 4) n1)))
2561 (if (or (= n100 4) (= n1 4))
2562 (list 12 31 year)
2563 (let ((year (1+ year))
2564 (month 1))
2565 (while (let ((mdays (calendar-last-day-of-month month year)))
2566 (and (< mdays day)
2567 (setq day (- day mdays))))
2568 (setq month (1+ month)))
2569 (list month day year)))))
ecaa0527 2570
ecaa0527
RS
2571(defun calendar-other-month (month year)
2572 "Display a three-month calendar centered around MONTH and YEAR."
ecd42d42 2573 (interactive (calendar-read-date 'noday))
ecaa0527
RS
2574 (if (and (= month displayed-month)
2575 (= year displayed-year))
2576 nil
2577 (let ((old-date (calendar-cursor-to-date))
2578 (today (calendar-current-date)))
7e1dae73 2579 (generate-calendar-window month year)
ecaa0527
RS
2580 (calendar-cursor-to-visible-date
2581 (cond
2582 ((calendar-date-is-visible-p old-date) old-date)
2583 ((calendar-date-is-visible-p today) today)
2584 (t (list month 1 year)))))))
2585
2586(defun calendar-set-mark (arg)
2587 "Mark the date under the cursor, or jump to marked date.
2588With no prefix argument, push current date onto marked date ring.
2589With argument, jump to mark, pop it, and put point at end of ring."
2590 (interactive "P")
ffd82264 2591 (let ((date (calendar-cursor-to-date t)))
ecaa0527
RS
2592 (if (null arg)
2593 (progn
2594 (setq calendar-mark-ring (cons date calendar-mark-ring))
2595 ;; Since the top of the mark ring is the marked date in the
2596 ;; calendar, the mark ring in the calendar is one longer than
2597 ;; in other buffers to get the same effect.
2598 (if (> (length calendar-mark-ring) (1+ mark-ring-max))
2599 (setcdr (nthcdr mark-ring-max calendar-mark-ring) nil))
2600 (message "Mark set"))
2601 (if (null calendar-mark-ring)
2602 (error "No mark set in this buffer")
2603 (calendar-goto-date (car calendar-mark-ring))
2604 (setq calendar-mark-ring
2605 (cdr (nconc calendar-mark-ring (list date))))))))
2606
2607(defun calendar-exchange-point-and-mark ()
2608 "Exchange the current cursor position with the marked date."
2609 (interactive)
2610 (let ((mark (car calendar-mark-ring))
ffd82264 2611 (date (calendar-cursor-to-date t)))
ecaa0527
RS
2612 (if (null mark)
2613 (error "No mark set in this buffer")
2614 (setq calendar-mark-ring (cons date (cdr calendar-mark-ring)))
2615 (calendar-goto-date mark))))
2616
2617(defun calendar-count-days-region ()
2618 "Count the number of days (inclusive) between point and the mark."
2619 (interactive)
2620 (let* ((days (- (calendar-absolute-from-gregorian
ffd82264 2621 (calendar-cursor-to-date t))
ecaa0527
RS
2622 (calendar-absolute-from-gregorian
2623 (or (car calendar-mark-ring)
2624 (error "No mark set in this buffer")))))
2625 (days (1+ (if (> days 0) days (- days)))))
2626 (message "Region has %d day%s (inclusive)"
2627 days (if (> days 1) "s" ""))))
2628
2629(defun calendar-not-implemented ()
2630 "Not implemented."
2631 (interactive)
2632 (error "%s not available in the calendar"
2633 (global-key-binding (this-command-keys))))
2634
2635(defun calendar-read (prompt acceptable &optional initial-contents)
2636 "Return an object read from the minibuffer.
2637Prompt with the string PROMPT and use the function ACCEPTABLE to decide if
2638entered item is acceptable. If non-nil, optional third arg INITIAL-CONTENTS
2639is a string to insert in the minibuffer before reading."
2640 (let ((value (read-minibuffer prompt initial-contents)))
2641 (while (not (funcall acceptable value))
2642 (setq value (read-minibuffer prompt initial-contents)))
2643 value))
2644
cba0c253 2645(defun calendar-read-date (&optional noday)
3cbb4860 2646 "Prompt for Gregorian date. Return a list (month day year).
cba0c253 2647If optional NODAY is t, does not ask for day, but just returns
ae58b7ad 2648\(month nil year); if NODAY is any other non-nil value the value returned is
3cbb4860 2649\(month year)"
7e1dae73 2650 (let* ((year (calendar-read
4c635ea3
GM
2651 "Year (>0): "
2652 (lambda (x) (> x 0))
7e1dae73
JB
2653 (int-to-string (extract-calendar-year
2654 (calendar-current-date)))))
2655 (month-array calendar-month-name-array)
2656 (completion-ignore-case t)
78e37e9c 2657 (month (cdr (assoc-string
7e1dae73
JB
2658 (completing-read
2659 "Month name: "
2660 (mapcar 'list (append month-array nil))
bf51dce3 2661 nil t)
78e37e9c 2662 (calendar-make-alist month-array 1) t)))
cba0c253 2663 (last (calendar-last-day-of-month month year)))
ecd42d42
ER
2664 (if noday
2665 (if (eq noday t)
2666 (list month nil year)
2667 (list month year))
2668 (list month
2669 (calendar-read (format "Day (1-%d): " last)
d4ff5db9 2670 (lambda (x) (and (< 0 x) (<= x last))))
ecd42d42 2671 year))))
7e1dae73 2672
ecaa0527 2673(defun calendar-interval (mon1 yr1 mon2 yr2)
18db8896
GM
2674 "The number of months difference between MON1, YR1 and MON2, YR2.
2675The result is positive if the second date is later than the first.
2676Negative years are interpreted as years BC; -1 being 1 BC, and so on."
2677 (if (< yr1 0) (setq yr1 (1+ yr1))) ; -1 BC -> 0 AD, etc
2678 (if (< yr2 0) (setq yr2 (1+ yr2)))
ecaa0527
RS
2679 (+ (* 12 (- yr2 yr1))
2680 (- mon2 mon1)))
2681
2c8811d4
GM
2682(defvar calendar-abbrev-length 3
2683 "*Length of abbreviations to be used for day and month names.
2684See also `calendar-day-abbrev-array' and `calendar-month-abbrev-array'.")
2685
d8a200a7 2686(defvar calendar-day-name-array
b642d11e 2687 ["Sunday" "Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday"]
2c8811d4
GM
2688 "*Array of capitalized strings giving, in order, the day names.
2689The first two characters of each string will be used to head the
2690day columns in the calendar. See also the variable
2691`calendar-day-abbrev-array'.")
2692
2693(defvar calendar-day-abbrev-array
2694 [nil nil nil nil nil nil nil]
2695 "*Array of capitalized strings giving the abbreviated day names.
2696The order should be the same as that of the full names specified
2697in `calendar-day-name-array'. These abbreviations may be used
2698instead of the full names in the diary file. Do not include a
2699trailing `.' in the strings specified in this variable, though
2700you may use such in the diary file. If any element of this array
2701is nil, then the abbreviation will be constructed as the first
2702`calendar-abbrev-length' characters of the corresponding full name.")
ecaa0527 2703
d8a200a7 2704(defvar calendar-month-name-array
ecaa0527 2705 ["January" "February" "March" "April" "May" "June"
b642d11e 2706 "July" "August" "September" "October" "November" "December"]
2c8811d4
GM
2707 "*Array of capitalized strings giving, in order, the month names.
2708See also the variable `calendar-month-abbrev-array'.")
2709
2710(defvar calendar-month-abbrev-array
2711 [nil nil nil nil nil nil nil nil nil nil nil nil]
2712 "*Array of capitalized strings giving the abbreviated month names.
2713The order should be the same as that of the full names specified
2714in `calendar-month-name-array'. These abbreviations are used in
2715the calendar menu entries, and can also be used in the diary
2716file. Do not include a trailing `.' in the strings specified in
2717this variable, though you may use such in the diary file. If any
2718element of this array is nil, then the abbreviation will be
2719constructed as the first `calendar-abbrev-length' characters of the
2720corresponding full name.")
2721
2722(defun calendar-abbrev-construct (abbrev full &optional period)
2723 "Internal calendar function to return a complete abbreviation array.
2724ABBREV is an array of abbreviations, FULL the corresponding array
2725of full names. The return value is the ABBREV array, with any nil
2726elements replaced by the first three characters taken from the
2727corresponding element of FULL. If optional argument PERIOD is non-nil,
2728each element returned has a final `.' character."
3d880a4b 2729 (let (elem array name)
2c8811d4 2730 (dotimes (i (length full))
3d880a4b
GM
2731 (setq name (aref full i)
2732 elem (or (aref abbrev i)
2733 (substring name 0
2734 (min calendar-abbrev-length (length name))))
2c8811d4
GM
2735 elem (format "%s%s" elem (if period "." ""))
2736 array (append array (list elem))))
2737 (vconcat array)))
ecaa0527 2738
5d22135b 2739(defvar calendar-font-lock-keywords
f5f57411
SM
2740 `((,(concat (regexp-opt (mapcar 'identity calendar-month-name-array) t)
2741 " -?[0-9]+")
2742 . font-lock-function-name-face) ; month and year
2743 (,(regexp-opt
2744 (list (substring (aref calendar-day-name-array 6) 0 2)
2745 (substring (aref calendar-day-name-array 0) 0 2)))
2746 ;; Saturdays and Sundays are hilited differently.
2747 . font-lock-comment-face)
2c8811d4 2748 ;; First two chars of each day are used in the calendar.
f5f57411
SM
2749 (,(regexp-opt (mapcar (lambda (x) (substring x 0 2)) calendar-day-name-array))
2750 . font-lock-reference-face))
5d22135b
MR
2751 "Default keywords to highlight in Calendar mode.")
2752
2c8811d4 2753(defun calendar-day-name (date &optional abbrev absolute)
e0dfc625 2754 "Return a string with the name of the day of the week of DATE.
2c8811d4
GM
2755DATE should be a list in the format (MONTH DAY YEAR), unless the
2756optional argument ABSOLUTE is non-nil, in which case DATE should
2757be an integer in the range 0 to 6 corresponding to the day of the
2758week. Day names are taken from the variable `calendar-day-name-array',
2759unless the optional argument ABBREV is non-nil, in which case
2760the variable `calendar-day-abbrev-array' is used."
2761 (aref (if abbrev
2762 (calendar-abbrev-construct calendar-day-abbrev-array
2763 calendar-day-name-array)
2764 calendar-day-name-array)
2765 (if absolute date (calendar-day-of-week date))))
2766
2767(defun calendar-make-alist (sequence &optional start-index filter abbrevs)
ecaa0527 2768 "Make an assoc list corresponding to SEQUENCE.
2c8811d4
GM
2769Each element of sequence will be associated with an integer, starting
2770from 1, or from START-INDEX if that is non-nil. If a sequence ABBREVS
2771is supplied, the function `calendar-abbrev-construct' is used to
2772construct abbreviations corresponding to the elements in SEQUENCE.
2773Each abbreviation is entered into the alist with the same
2774association index as the full name it represents.
2775If FILTER is provided, apply it to each key in the alist."
2776 (let ((index 0)
2777 (offset (or start-index 1))
2778 (aseq (if abbrevs (calendar-abbrev-construct abbrevs sequence)))
2779 (aseqp (if abbrevs (calendar-abbrev-construct abbrevs sequence
2780 'period)))
2781 alist elem)
8923d271 2782 (dotimes (i (length sequence) (reverse alist))
2c8811d4
GM
2783 (setq index (+ i offset)
2784 elem (elt sequence i)
2785 alist
2786 (cons (cons (if filter (funcall filter elem) elem) index) alist))
2787 (if aseq
2788 (setq elem (elt aseq i)
2789 alist (cons (cons (if filter (funcall filter elem) elem)
2790 index) alist)))
2791 (if aseqp
2792 (setq elem (elt aseqp i)
2793 alist (cons (cons (if filter (funcall filter elem) elem)
2794 index) alist))))))
2795
2796(defun calendar-month-name (month &optional abbrev)
2797 "Return a string with the name of month number MONTH.
2798Months are numbered from one. Month names are taken from the
2799variable `calendar-month-name-array', unless the optional
2800argument ABBREV is non-nil, in which case
2801`calendar-month-abbrev-array' is used."
2802 (aref (if abbrev
2803 (calendar-abbrev-construct calendar-month-abbrev-array
2804 calendar-month-name-array)
2805 calendar-month-name-array)
2806 (1- month)))
ecaa0527
RS
2807
2808(defun calendar-day-of-week (date)
18db8896
GM
2809 "Return the day-of-the-week index of DATE, 0 for Sunday, 1 for Monday, etc.
2810DATE is a list of the form (month day year). A negative year is
2811interpreted as BC; -1 being 1 BC, and so on."
2812 (mod (calendar-absolute-from-gregorian date) 7))
ecaa0527 2813
ecaa0527 2814(defun calendar-unmark ()
6a2aa94c 2815 "Delete all diary/holiday marks/highlighting from the calendar."
ecaa0527 2816 (interactive)
ecaa0527 2817 (setq mark-holidays-in-calendar nil)
6a2aa94c
RS
2818 (setq mark-diary-entries-in-calendar nil)
2819 (redraw-calendar))
ecaa0527
RS
2820
2821(defun calendar-date-is-visible-p (date)
3cbb4860 2822 "Return t if DATE is legal and is visible in the calendar window."
ecaa0527
RS
2823 (let ((gap (calendar-interval
2824 displayed-month displayed-year
2825 (extract-calendar-month date) (extract-calendar-year date))))
2826 (and (calendar-date-is-legal-p date) (> 2 gap) (< -2 gap))))
2827
2828(defun calendar-date-is-legal-p (date)
3cbb4860 2829 "Return t if DATE is a legal date."
ecaa0527
RS
2830 (let ((month (extract-calendar-month date))
2831 (day (extract-calendar-day date))
2832 (year (extract-calendar-year date)))
2833 (and (<= 1 month) (<= month 12)
2834 (<= 1 day) (<= day (calendar-last-day-of-month month year))
18db8896
GM
2835 ;; BC dates left as non-legal, to suppress errors from
2836 ;; complex holiday algorithms not suitable for years BC.
2837 ;; Note there are side effects on calendar navigation.
ecaa0527
RS
2838 (<= 1 year))))
2839
2840(defun calendar-date-equal (date1 date2)
3cbb4860 2841 "Return t if the DATE1 and DATE2 are the same."
ecaa0527
RS
2842 (and
2843 (= (extract-calendar-month date1) (extract-calendar-month date2))
2844 (= (extract-calendar-day date1) (extract-calendar-day date2))
2845 (= (extract-calendar-year date1) (extract-calendar-year date2))))
2846
2847(defun mark-visible-calendar-date (date &optional mark)
6a2aa94c 2848 "Mark DATE in the calendar window with MARK.
d13c1378 2849MARK is a single-character string, a list of face attributes/values, or a face.
5d22135b 2850MARK defaults to `diary-entry-marker'."
ecaa0527
RS
2851 (if (calendar-date-is-legal-p date)
2852 (save-excursion
2853 (set-buffer calendar-buffer)
2854 (calendar-cursor-to-visible-date date)
d13c1378
JB
2855 (let ((mark (or (and (stringp mark) (= (length mark) 1) mark) ; single-char
2856 (and (listp mark) (> (length mark) 0) mark) ; attr list
2857 (and (facep mark) mark) ; face-name
2858 diary-entry-marker)))
2859 (if (facep mark)
2860 (progn ; face or an attr-list that contained a face
2861 (overlay-put
2862 (make-overlay (1- (point)) (1+ (point))) 'face mark))
2863 (if (and (stringp mark)
2864 (= (length mark) 1)) ; single-char
2865 (let ((buffer-read-only nil))
2866 (forward-char 1)
2867 (delete-char 1)
2868 (insert mark)
2869 (forward-char -2))
1293540e
GM
2870 (let ; attr list
2871 ((temp-face
2872 (make-symbol (apply 'concat "temp-face-"
2873 (mapcar '(lambda (sym)
2874 (cond ((symbolp sym) (symbol-name sym))
2875 ((numberp sym) (int-to-string sym))
2876 (t sym))) mark))))
2877 (faceinfo mark))
d13c1378
JB
2878 (make-face temp-face)
2879 ;; Remove :face info from the mark, copy the face info into temp-face
d13c1378
JB
2880 (while (setq faceinfo (memq :face faceinfo))
2881 (copy-face (read (nth 1 faceinfo)) temp-face)
2882 (setcar faceinfo nil)
2883 (setcar (cdr faceinfo) nil))
2884 (setq mark (delq nil mark))
2885 ;; Apply the font aspects
2886 (apply 'set-face-attribute temp-face nil mark)
2887 (overlay-put
2888 (make-overlay (1- (point)) (1+ (point))) 'face temp-face))))))))
ecaa0527
RS
2889
2890(defun calendar-star-date ()
2891 "Replace the date under the cursor in the calendar window with asterisks.
3cbb4860 2892This function can be used with the `today-visible-calendar-hook' run after the
ecaa0527 2893calendar window has been prepared."
3cbb4860
SM
2894 (let ((inhibit-read-only t))
2895 (make-local-variable 'calendar-starred-day)
ecaa0527 2896 (forward-char 1)
c00f638d 2897 (setq calendar-starred-day
7e1dae73
JB
2898 (string-to-int
2899 (buffer-substring (point) (- (point) 2))))
ecaa0527
RS
2900 (delete-char -2)
2901 (insert "**")
2902 (backward-char 1)
2903 (set-buffer-modified-p nil)))
2904
2905(defun calendar-mark-today ()
6a2aa94c 2906 "Mark the date under the cursor in the calendar window.
5d22135b 2907The date is marked with `calendar-today-marker'. This function can be used with
3cbb4860 2908the `today-visible-calendar-hook' run after the calendar window has been
6a2aa94c
RS
2909prepared."
2910 (mark-visible-calendar-date
2911 (calendar-cursor-to-date)
2912 calendar-today-marker))
ecaa0527
RS
2913
2914(defun calendar-date-compare (date1 date2)
3cbb4860 2915 "Return t if DATE1 is before DATE2, nil otherwise.
ecaa0527
RS
2916The actual dates are in the car of DATE1 and DATE2."
2917 (< (calendar-absolute-from-gregorian (car date1))
2918 (calendar-absolute-from-gregorian (car date2))))
2919
2920(defun calendar-date-string (date &optional abbreviate nodayname)
2921 "A string form of DATE, driven by the variable `calendar-date-display-form'.
2c8811d4
GM
2922An optional parameter ABBREVIATE, when non-nil, causes the month
2923and day names to be abbreviated as specified by
2924`calendar-month-abbrev-array' and `calendar-day-abbrev-array',
2925respectively. An optional parameter NODAYNAME, when t, omits the
2926name of the day of the week."
ecaa0527 2927 (let* ((dayname
2c8811d4
GM
2928 (unless nodayname
2929 (calendar-day-name date abbreviate)))
ecaa0527 2930 (month (extract-calendar-month date))
2c8811d4 2931 (monthname (calendar-month-name month abbreviate))
ecaa0527
RS
2932 (day (int-to-string (extract-calendar-day date)))
2933 (month (int-to-string month))
2934 (year (int-to-string (extract-calendar-year date))))
2935 (mapconcat 'eval calendar-date-display-form "")))
2936
2937(defun calendar-dayname-on-or-before (dayname date)
3cbb4860 2938 "Return the absolute date of the DAYNAME on or before absolute DATE.
ecaa0527
RS
2939DAYNAME=0 means Sunday, DAYNAME=1 means Monday, and so on.
2940
2941Note: Applying this function to d+6 gives us the DAYNAME on or after an
2942absolute day d. Similarly, applying it to d+3 gives the DAYNAME nearest to
2943absolute date d, applying it to d-1 gives the DAYNAME previous to absolute
2944date d, and applying it to d+7 gives the DAYNAME following absolute date d."
2945 (- date (% (- date dayname) 7)))
2946
04d5d338
PE
2947(defun calendar-nth-named-absday (n dayname month year &optional day)
2948 "The absolute date of Nth DAYNAME in MONTH, YEAR before/after optional DAY.
2949A DAYNAME of 0 means Sunday, 1 means Monday, and so on. If N<0,
2950return the Nth DAYNAME before MONTH DAY, YEAR (inclusive).
2951If N>0, return the Nth DAYNAME after MONTH DAY, YEAR (inclusive).
2952
2953If DAY is omitted, it defaults to 1 if N>0, and MONTH's last day otherwise."
2954 (if (> n 0)
2955 (+ (* 7 (1- n))
2956 (calendar-dayname-on-or-before
2957 dayname
2958 (+ 6 (calendar-absolute-from-gregorian
2959 (list month (or day 1) year)))))
2960 (+ (* 7 (1+ n))
2961 (calendar-dayname-on-or-before
2962 dayname
2963 (calendar-absolute-from-gregorian
2964 (list month
2965 (or day (calendar-last-day-of-month month year))
2966 year))))))
2967
354d0644
JB
2968(defun calendar-nth-named-day (n dayname month year &optional day)
2969 "The date of Nth DAYNAME in MONTH, YEAR before/after optional DAY.
2970A DAYNAME of 0 means Sunday, 1 means Monday, and so on. If N<0,
2971return the Nth DAYNAME before MONTH DAY, YEAR (inclusive).
2972If N>0, return the Nth DAYNAME after MONTH DAY, YEAR (inclusive).
2973
2974If DAY is omitted, it defaults to 1 if N>0, and MONTH's last day otherwise."
ecaa0527 2975 (calendar-gregorian-from-absolute
04d5d338 2976 (calendar-nth-named-absday n dayname month year day)))
ecaa0527 2977
6a2aa94c
RS
2978(defun calendar-day-of-year-string (&optional date)
2979 "String of day number of year of Gregorian DATE.
2980Defaults to today's date if DATE is not given."
2981 (let* ((d (or date (calendar-current-date)))
2982 (year (extract-calendar-year d))
2983 (day (calendar-day-number d))
2984 (days-remaining (- (calendar-day-number (list 12 31 year)) day)))
2985 (format "Day %d of %d; %d day%s remaining in the year"
2986 day year days-remaining (if (= days-remaining 1) "" "s"))))
2987
726669d8
ER
2988(defun calendar-print-other-dates ()
2989 "Show dates on other calendars for date under the cursor."
2990 (interactive)
2991 (let* ((date (calendar-cursor-to-date t)))
2992 (save-excursion
2993 (set-buffer (get-buffer-create other-calendars-buffer))
2994 (setq buffer-read-only nil)
2995 (calendar-set-mode-line
2996 (concat (calendar-date-string date) " (Gregorian)"))
2997 (erase-buffer)
2998 (insert
2999 (mapconcat 'identity
3000 (list (calendar-day-of-year-string date)
3001 (format "ISO date: %s" (calendar-iso-date-string date))
3002 (format "Julian date: %s"
3003 (calendar-julian-date-string date))
3004 (format
3005 "Astronomical (Julian) day number (at noon UTC): %s.0"
3006 (calendar-astro-date-string date))
3007 (format "Fixed (RD) date: %s"
3008 (calendar-absolute-from-gregorian date))
3009 (format "Hebrew date (before sunset): %s"
3010 (calendar-hebrew-date-string date))
3011 (format "Persian date: %s"
3012 (calendar-persian-date-string date))
3013 (let ((i (calendar-islamic-date-string date)))
3014 (if (not (string-equal i ""))
3015 (format "Islamic date (before sunset): %s" i)))
811a8484
JW
3016 (let ((b (calendar-bahai-date-string date)))
3017 (if (not (string-equal b ""))
3018 (format "Baha'i date (before sunset): %s" b)))
726669d8
ER
3019 (format "Chinese date: %s"
3020 (calendar-chinese-date-string date))
3021 (let ((c (calendar-coptic-date-string date)))
3022 (if (not (string-equal c ""))
3023 (format "Coptic date: %s" c)))
3024 (let ((e (calendar-ethiopic-date-string date)))
3025 (if (not (string-equal e ""))
3026 (format "Ethiopic date: %s" e)))
3027 (let ((f (calendar-french-date-string date)))
3028 (if (not (string-equal f ""))
3029 (format "French Revolutionary date: %s" f)))
3030 (format "Mayan date: %s"
3031 (calendar-mayan-date-string date)))
3032 "\n"))
3033 (goto-char (point-min))
3034 (set-buffer-modified-p nil)
3035 (setq buffer-read-only t)
3036 (display-buffer other-calendars-buffer))))
3037
7e1dae73 3038(defun calendar-print-day-of-year ()
6a2aa94c 3039 "Show day number in year/days remaining in year for date under the cursor."
ecaa0527 3040 (interactive)
ffd82264 3041 (message (calendar-day-of-year-string (calendar-cursor-to-date t))))
ecaa0527 3042
7e1dae73
JB
3043(defun calendar-set-mode-line (str)
3044 "Set mode line to STR, centered, surrounded by dashes."
3045 (setq mode-line-format
d519ea8a
GM
3046 (calendar-string-spread
3047 (list str) ?-
3048 ;; As per doc of window-width, total visible mode-line length.
3049 (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))))))
7e1dae73 3050
7086b78e
ER
3051(defun calendar-mod (m n)
3052 "Non-negative remainder of M/N with N instead of 0."
3053 (1+ (mod (1- m) n)))
7e1dae73
JB
3054
3055(run-hooks 'calendar-load-hook)
ecaa0527
RS
3056
3057(provide 'calendar)
3058
b578f267
EN
3059;;; Local variables:
3060;;; byte-compile-dynamic: t
3061;;; End:
3062
ab5796a9 3063;;; arch-tag: 19c61596-c8fb-4c69-bcf1-7dd739919cd8
94b304d7 3064;;; calendar.el ends here