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