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