Annotation of 43BSDReno/contrib/emacs-18.55/lisp/cal.el, revision 1.1

1.1     ! root        1: ;; Record version number of Emacs.
        !             2: ;; Copyright (C) 1988 Free Software Foundation, Inc.
        !             3: 
        !             4: ;; This file is part of GNU Emacs.
        !             5: 
        !             6: ;; GNU Emacs is distributed in the hope that it will be useful,
        !             7: ;; but WITHOUT ANY WARRANTY.  No author or distributor
        !             8: ;; accepts responsibility to anyone for the consequences of using it
        !             9: ;; or for whether it serves any particular purpose or works at all,
        !            10: ;; unless he says so in writing.  Refer to the GNU Emacs General Public
        !            11: ;; License for full details.
        !            12: 
        !            13: ;; Everyone is granted permission to copy, modify and redistribute
        !            14: ;; GNU Emacs, but only under the conditions described in the
        !            15: ;; GNU Emacs General Public License.   A copy of this license is
        !            16: ;; supposed to have been given to you along with GNU Emacs so you
        !            17: ;; can know your rights and responsibilities.  It should be in a
        !            18: ;; file named COPYING.  Among other things, the copyright notice
        !            19: ;; and this notice must be preserved on all copies.
        !            20: ;;
        !            21: ;; Comments, corrections, and improvements should be sent to
        !            22: ;;  Edward M. Reingold               Department of Computer Science
        !            23: ;;  (217) 333-6733                   University of Illinois at Urbana-Champaign
        !            24: ;;  [email protected]           1304 West Springfield Avenue
        !            25: ;;                                   Urbana, Illinois 61801
        !            26: ;;
        !            27: ;; The author gratefully acknowledges the patient help of Richard Stallman
        !            28: ;; in making this function into a reasonable piece of code!
        !            29: ;;
        !            30: ;; Modification for month-offset arguments suggested and implemented by
        !            31: ;;  Constantine Rasmussen            Sun Microsystems, East Coast Division
        !            32: ;;  (617) 671-0404                   2 Federal Street;  Billerica, Ma.  01824
        !            33: ;;  ARPA: [email protected]   USENET: {cbosgd,decvax,hplabs,seismo}!sun!suneast!cdr
        !            34: ;;
        !            35: ;; Modification to mark current day with stars suggested by
        !            36: ;;  Franklin Davis                  Thinking Machines Corp
        !            37: ;;  (617) 876-1111                   245 First Street, Cambridge, MA  02142
        !            38: ;;  [email protected]
        !            39: 
        !            40: (defvar calendar-hook nil
        !            41:   "List of functions called after the calendar buffer has been prepared with
        !            42: the calendar of the current month.  This can be used, for example, to highlight
        !            43: today's date with asterisks--a function star-date is included for this purpose.
        !            44: The variable offset-calendar-hook is the list of functions called when the
        !            45: calendar function was called for a past or future month.")
        !            46: 
        !            47: (defvar offset-calendar-hook nil
        !            48:   "List of functions called after the calendar buffer has been prepared with
        !            49: the calendar of a past or future month.  The variable calendar-hook is the
        !            50: list of functions called when the calendar function was called for the
        !            51: current month.")
        !            52: 
        !            53: (defun calendar (&optional month-offset)
        !            54:   "Display three-month calendar in another window.
        !            55: The three months appear side by side, with the current month in the middle
        !            56: surrounded by the previous and next months.  The cursor is put on today's date.
        !            57: 
        !            58: An optional prefix argument ARG causes the calendar displayed to be
        !            59: ARG months in the future if ARG is positive or in the past if ARG is
        !            60: negative; in this case the cursor goes on the first day of the month.
        !            61: 
        !            62: The Gregorian calendar is assumed.
        !            63: 
        !            64: After preparing the calendar window, the hooks calendar-hook are run
        !            65: when the calendar is for the current month--that is, the was no prefix
        !            66: argument.  If the calendar is for a future or past month--that is, there
        !            67: was a prefix argument--the hooks offset-calendar-hook are run.  Thus, for
        !            68: example, setting calendar-hooks to 'star-date will cause today's date to be
        !            69: replaced by asterisks to highlight it in the window."
        !            70:   (interactive "P")
        !            71:   (if month-offset (setq month-offset (prefix-numeric-value month-offset)))
        !            72:   (let ((today (make-marker)))
        !            73:     (save-excursion
        !            74:       (set-buffer (get-buffer-create "*Calendar*"))
        !            75:       (setq buffer-read-only t)
        !            76:       (let*
        !            77:          ((buffer-read-only nil)
        !            78:           ;; Get today's date and extract the day, month and year.
        !            79:           (date (current-time-string))
        !            80:           (garbage (string-match
        !            81:                      " \\([A-Z][a-z][a-z]\\) *\\([0-9]*\\) .* \\([0-9]*\\)$"
        !            82:                      date))
        !            83:           (day (or (and month-offset 1) 
        !            84:                    (string-to-int
        !            85:                      (substring date (match-beginning 2) (match-end 2)))))
        !            86:           (month
        !            87:             (cdr (assoc
        !            88:                     (substring date (match-beginning 1) (match-end 1))
        !            89:                     '(("Jan" . 1) ("Feb" . 2)  ("Mar" . 3)  ("Apr" . 4)
        !            90:                       ("May" . 5) ("Jun" . 6)  ("Jul" . 7)  ("Aug" . 8)
        !            91:                       ("Sep" . 9) ("Oct" . 10) ("Nov" . 11) ("Dec" . 12)))))
        !            92:           (year (string-to-int
        !            93:                   (substring date (match-beginning 3) (match-end 3)))))
        !            94:        (erase-buffer)
        !            95:        ;; If user requested a month in the future or the past,
        !            96:        ;; advance the variables MONTH and YEAR to describe that one.
        !            97:        (cond
        !            98:           (month-offset
        !            99:             (let ((year-month (+ (+ (* year 12) (- month 1)) month-offset)))
        !           100:               (setq month (+ (% year-month 12) 1))
        !           101:               (setq year (/ year-month 12)))))
        !           102:        ;; Generate previous month, starting at left margin.
        !           103:        (generate-month;; previous month
        !           104:          (if (= month 1) 12 (1- month))
        !           105:          (if (= month 1) (1- year) year)
        !           106:          0)
        !           107:        ;; Generate this month, starting at column 24,
        !           108:        ;; and record where today's date appears, in the marker TODAY.
        !           109:        (goto-char (point-min))
        !           110:        (set-marker today (generate-month month year 24 day))
        !           111:        ;; Generate the following month, starting at column 48.
        !           112:        (goto-char (point-min))
        !           113:        (generate-month
        !           114:          (if (= month 12) 1 (1+ month))
        !           115:          (if (= month 12) (1+ year) year)
        !           116:          48)))
        !           117:     ;; Display the buffer and put cursor on today's date.
        !           118:     ;; Do it in another window, but if this buffer is already visible,
        !           119:     ;; just select its window.
        !           120:     (pop-to-buffer "*Calendar*")
        !           121:     (goto-char (marker-position today))
        !           122:     ;; Make TODAY point nowhere so it won't slow down buffer editing until GC.
        !           123:     (set-marker today nil))
        !           124:   ;; Make the window just tall enough for its contents.
        !           125:   (let ((h (1- (window-height)))
        !           126:         (l (count-lines (point-min) (point-max))))
        !           127:     (or (one-window-p t)
        !           128:         (<= h l)
        !           129:         (shrink-window (- h l))))
        !           130:   (if month-offset
        !           131:       (run-hooks 'offset-calendar-hook)
        !           132:       (run-hooks 'calendar-hook)))
        !           133: 
        !           134: (defun leap-year-p (year)
        !           135:   "Returns true if YEAR is a Gregorian leap year, and false if not."
        !           136:   (or
        !           137:     (and (=  (% year   4) 0)
        !           138:          (/= (% year 100) 0))
        !           139:     (= (% year 400) 0)))
        !           140: 
        !           141: (defun day-number (month day year)
        !           142:   "Return day-number within year (origin-1) of the date MONTH DAY YEAR.
        !           143: For example, (day-number 1 1 1987) returns the value 1,
        !           144: while (day-number 12 31 1980) returns 366."
        !           145: ;;
        !           146: ;; an explanation of the calculation can be found in PascAlgorithms by
        !           147: ;; Edward and Ruth Reingold, Scott-foresman/Little, Brown, 1988.
        !           148: ;;
        !           149:   (let ((day-of-year (+ day (* 31 (1- month)))))
        !           150:     (if (> month 2)
        !           151:         (progn
        !           152:           (setq day-of-year (- day-of-year (/ (+ 23 (* 4 month)) 10)))
        !           153:           (if (leap-year-p year)
        !           154:               (setq day-of-year (1+ day-of-year)))))
        !           155:     day-of-year))
        !           156: 
        !           157: (defun day-of-week (month day year)
        !           158:   "Returns the day-of-the-week index of MONTH DAY, YEAR.
        !           159: Value is 0 for Sunday, 1 for Monday, etc."
        !           160: ;;
        !           161: ;; Done by calculating the number of days elapsed since the (imaginary)
        !           162: ;; Gregorian date Sunday, December 31, 1 BC and taking that number mod 7.
        !           163: ;;
        !           164:   (%
        !           165:     (-
        !           166:       (+ (day-number month day year)
        !           167:          (* 365 (1- year))
        !           168:          (/ (1- year) 4))
        !           169:       (let ((correction (* (/ (1- year) 100) 3)))
        !           170:         (if (= (% correction 4) 0)
        !           171:             (/ correction 4)
        !           172:             (1+ (/ correction 4)))))
        !           173:     7))
        !           174: 
        !           175: (defun generate-month (month year indent &optional day)
        !           176:   "Produce a calendar for MONTH, YEAR on the Gregorian calendar, inserted
        !           177: in the buffer starting at the line on which point is currently located, but
        !           178: indented INDENT spaces.  The position in the buffer of the optional
        !           179: parameter DAY is returned.  The indentation is done from the first
        !           180: character on the line and does not disturb the first INDENT characters on
        !           181: the line."
        !           182:   (let* ((first-day-of-month (day-of-week month 1 year) 7)
        !           183:          (first-saturday (- 7 first-day-of-month))
        !           184:          (last-of-month
        !           185:            (if (and (leap-year-p year) (= month 2))
        !           186:                29
        !           187:                (aref [31 28 31 30 31 30 31 31 30 31 30 31] (1- month))))
        !           188:          (month-name
        !           189:            (aref ["January" "February" "March" "April" "May" "June"
        !           190:                   "July" "August" "September" "October" "November" "December"]
        !           191:                   (1- month))))
        !           192:     (insert-indented (format "   %s %d" month-name year) indent t)
        !           193:     (insert-indented " S  M Tu  W Th  F  S" indent t)
        !           194:     (insert-indented "" indent);; move point to appropriate spot on line
        !           195:     (let ((i 0))               ;; add blank days before the first of the month
        !           196:       (while (<= (setq i (1+ i)) first-day-of-month)
        !           197:         (insert "   ")))
        !           198:     (let ((i 0)
        !           199:           (day-marker))        ;; put in the days of the month
        !           200:       (while (<= (setq i (1+ i)) last-of-month)
        !           201:         (insert (format "%2d " i))
        !           202:         (and
        !           203:           day
        !           204:           (= i day)            ;; save the location of the specified day
        !           205:           (setq day-marker (- (point) 2)))
        !           206:         (and (= (% i 7) (% first-saturday 7))
        !           207:              (/= i last-of-month)
        !           208:              (insert-indented "" 0 t)        ;; force onto following line
        !           209:              (insert-indented "" indent)))   ;; go to proper spot on line
        !           210:       day-marker)))
        !           211: 
        !           212: (defun insert-indented (string indent &optional newline)
        !           213:   "Insert STRING at column INDENT.
        !           214: If the optional parameter NEWLINE is true, leave point at start of next
        !           215: line, inserting a newline if there was no next line; otherwise, leave point
        !           216: after the inserted text.  Value is always `t'."
        !           217:   ;; Try to move to that column.
        !           218:   (move-to-column indent)
        !           219:   ;; If line is too short, indent out to that column.
        !           220:   (if (< (current-column) indent)
        !           221:       (indent-to indent))
        !           222:   (insert string)
        !           223:   ;; Advance to next line, if requested.
        !           224:   (if newline
        !           225:       (progn
        !           226:        (end-of-line)
        !           227:        (if (eobp)
        !           228:             (newline)
        !           229:          (forward-line 1))))
        !           230:   t)
        !           231: 
        !           232: (defun star-date ()
        !           233:   "Replace today's date with asterisks in the calendar window.
        !           234: This function can be used with the calendar-hook run after the
        !           235: calendar window has been prepared."
        !           236:   (let ((buffer-read-only nil))
        !           237:     (forward-char 1)
        !           238:     (delete-backward-char 2)
        !           239:     (insert "**")
        !           240:     (backward-char 1)))
        !           241: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.