aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGlenn Morris2008-06-26 03:41:20 +0000
committerGlenn Morris2008-06-26 03:41:20 +0000
commitb1c172fe60585561d49d11dc59beb2eef0e9fa03 (patch)
treeca84bac14d9ef14533ae7d653593038e35602fb8
parent86011bf229c999b8932b338ec7b28e063b504a52 (diff)
downloademacs-b1c172fe60585561d49d11dc59beb2eef0e9fa03.tar.gz
emacs-b1c172fe60585561d49d11dc59beb2eef0e9fa03.zip
(calendar-date-echo-text): Doc fix. Add default :value for sexp type.
(calendar-month-edges): New variable. (calendar-month-edges): New function. (calendar-recompute-layout-variables): Set calendar-month-edges. (calendar-intermonth-header, calendar-intermonth-text): New options. (calendar-insert-at-column): New function. (calendar-generate-month): Use calendar-insert-at-column. Handle intermonth text. Add 'date property. (calendar-column-to-month): Remove function. (calendar-column-to-segment): New function. (calendar-cursor-to-date): Use calendar-column-to-segment. Check 'date property. (calendar-print-other-dates): Handle mouse events.
-rw-r--r--lisp/calendar/calendar.el233
1 files changed, 163 insertions, 70 deletions
diff --git a/lisp/calendar/calendar.el b/lisp/calendar/calendar.el
index 6de0f01d553..f081d1cd437 100644
--- a/lisp/calendar/calendar.el
+++ b/lisp/calendar/calendar.el
@@ -353,16 +353,14 @@ redisplays the diary for whatever date the cursor is moved to."
353(defcustom calendar-date-echo-text 353(defcustom calendar-date-echo-text
354 "mouse-2: general menu\nmouse-3: menu for this date" 354 "mouse-2: general menu\nmouse-3: menu for this date"
355 "String displayed when the cursor is over a date in the calendar. 355 "String displayed when the cursor is over a date in the calendar.
356When this variable is evaluated, DAY, MONTH, and YEAR are 356Can be either a fixed string, or a lisp expression that returns one.
357When this expression is evaluated, DAY, MONTH, and YEAR are
357integers appropriate to the relevant date. For example, to 358integers appropriate to the relevant date. For example, to
358display the ISO week: 359display the ISO date:
359 360
360 (require 'cal-iso) 361 (setq calendar-date-echo-text '(format \"ISO date: %s\"
361 (setq calendar-date-echo-text '(format \"ISO week: %2d \" 362 (calendar-iso-date-string
362 (car 363 (list month day year))))
363 (calendar-iso-from-absolute
364 (calendar-absolute-from-gregorian
365 (list month day year))))))
366Changing this variable without using customize has no effect on 364Changing this variable without using customize has no effect on
367pre-existing calendar windows." 365pre-existing calendar windows."
368 :group 'calendar 366 :group 'calendar
@@ -371,8 +369,11 @@ pre-existing calendar windows."
371 :set (lambda (sym val) 369 :set (lambda (sym val)
372 (set sym val) 370 (set sym val)
373 (calendar-redraw)) 371 (calendar-redraw))
374 :type '(choice (string :tag "Literal string") 372 :type '(choice (string :tag "Fixed string")
375 (sexp :tag "Lisp expression")) 373 (sexp :value
374 (format "ISO date: %s"
375 (calendar-iso-date-string
376 (list month day year)))))
376 :version "23.1") 377 :version "23.1")
377 378
378 379
@@ -385,6 +386,36 @@ pre-existing calendar windows."
385(defvar calendar-right-margin nil 386(defvar calendar-right-margin nil
386 "Right margin of the calendar.") 387 "Right margin of the calendar.")
387 388
389(defvar calendar-month-edges nil
390 "Alist of month edge columns.
391Each element has the form (N LEFT FIRST LAST RIGHT), where
392LEFT is the leftmost column associated with month segment N,
393FIRST and LAST are the first and last columns with day digits in,
394and LAST is the rightmost column.")
395
396(defun calendar-month-edges (segment)
397 "Compute the month edge columns for month SEGMENT.
398Returns a list (LEFT FIRST LAST RIGHT), where LEFT is the
399leftmost column associated with a month, FIRST and LAST are the
400first and last columns with day digits in, and LAST is the
401rightmost column."
402 ;; The leftmost column with a digit in it in this month segment.
403 (let* ((first (+ calendar-left-margin
404 (* segment calendar-month-width)))
405 ;; The rightmost column with a digit in it in this month segment.
406 (last (+ first (1- calendar-month-digit-width)))
407 (left (if (eq segment 0)
408 0
409 (+ calendar-left-margin
410 (* segment calendar-month-width)
411 (- (/ calendar-intermonth-spacing 2)))))
412 ;; The rightmost edge of this month segment, dividing the
413 ;; space between months in two.
414 (right (+ calendar-left-margin
415 (* (1+ segment) calendar-month-width)
416 (- (/ calendar-intermonth-spacing 2)))))
417 (list left first last right)))
418
388(defun calendar-recompute-layout-variables () 419(defun calendar-recompute-layout-variables ()
389 "Recompute some layout-related calendar \"constants\"." 420 "Recompute some layout-related calendar \"constants\"."
390 (setq calendar-month-digit-width (+ (* 6 calendar-column-width) 421 (setq calendar-month-digit-width (+ (* 6 calendar-column-width)
@@ -393,7 +424,11 @@ pre-existing calendar windows."
393 calendar-intermonth-spacing) 424 calendar-intermonth-spacing)
394 calendar-right-margin (+ calendar-left-margin 425 calendar-right-margin (+ calendar-left-margin
395 (* 3 (* 7 calendar-column-width)) 426 (* 3 (* 7 calendar-column-width))
396 (* 2 calendar-intermonth-spacing)))) 427 (* 2 calendar-intermonth-spacing))
428 calendar-month-edges nil)
429 (dotimes (i 3)
430 (push (cons i (calendar-month-edges i)) calendar-month-edges))
431 (setq calendar-month-edges (reverse calendar-month-edges)))
397 432
398;; FIXME add font-lock-keywords. 433;; FIXME add font-lock-keywords.
399(defun calendar-set-layout-variable (symbol value &optional minmax) 434(defun calendar-set-layout-variable (symbol value &optional minmax)
@@ -430,6 +465,7 @@ Then redraw the calendar, if necessary."
430 :type 'integer 465 :type 'integer
431 :version "23.1") 466 :version "23.1")
432 467
468;; FIXME calendar-month-column-width?
433(defcustom calendar-column-width 3 469(defcustom calendar-column-width 3
434 "Width of each day column in the calendar. Minimum value is 3." 470 "Width of each day column in the calendar. Minimum value is 3."
435 :initialize 'custom-initialize-default 471 :initialize 'custom-initialize-default
@@ -1267,6 +1303,75 @@ Optional integers MON and YR are used instead of today's date."
1267 (or (zerop (forward-line 1)) 1303 (or (zerop (forward-line 1))
1268 (insert "\n"))) 1304 (insert "\n")))
1269 1305
1306(defcustom calendar-intermonth-header nil
1307 "Header text display in the space to the left of each calendar month.
1308See `calendar-intermonth-text'."
1309 :group 'calendar
1310 :initialize 'custom-initialize-default
1311 :risky t
1312 :set (lambda (sym val)
1313 (set sym val)
1314 (calendar-redraw))
1315 :type '(choice (const nil :tag "Nothing")
1316 (string :tag "Fixed string")
1317 (sexp :value
1318 (propertize "WK" 'font-lock-face
1319 'font-lock-function-name-face)))
1320 :version "23.1")
1321
1322(defcustom calendar-intermonth-text nil
1323 "Text to display in the space to the left of each calendar month.
1324Can be nil, a fixed string, or a lisp expression that returns a string.
1325When the expression is evaluated, the variables DAY, MONTH and YEAR
1326are integers appropriate for the first day in each week.
1327Will be truncated to the smaller of `calendar-left-margin' and
1328`calendar-intermonth-spacing'. The last character is forced to be a space.
1329For example, to display the ISO week numbers:
1330
1331 (setq calendar-week-start-day 1
1332 calendar-intermonth-text
1333 '(propertize
1334 (format \"%2d\"
1335 (car
1336 (calendar-iso-from-absolute
1337 (calendar-absolute-from-gregorian (list month day year)))))
1338 'font-lock-face 'font-lock-function-name-face))
1339
1340See also `calendar-intermonth-header'."
1341 :group 'calendar
1342 :initialize 'custom-initialize-default
1343 :risky t
1344 :set (lambda (sym val)
1345 (set sym val)
1346 (calendar-redraw))
1347 :type '(choice (const nil :tag "Nothing")
1348 (string :tag "Fixed string")
1349 (sexp :value
1350 (propertize
1351 (format "%2d"
1352 (car
1353 (calendar-iso-from-absolute
1354 (calendar-absolute-from-gregorian
1355 (list month day year)))))
1356 'font-lock-face 'font-lock-function-name-face)))
1357 :version "23.1")
1358
1359(defun calendar-insert-at-column (indent string truncate)
1360 "Move to column INDENT, adding spaces as needed.
1361Inserts STRING so that it ends at INDENT. STRING is either a
1362literal string, or a sexp to evaluate to return such. Truncates
1363STRING to length TRUNCATE, ensure a trailing space."
1364 (if (not (ignore-errors (stringp (setq string (eval string)))))
1365 (calendar-move-to-column indent)
1366 (if (> (length string) truncate)
1367 (setq string (substring string 0 truncate)))
1368 (or (string-match " $" string)
1369 (if (= (length string) truncate)
1370 (aset string (1- truncate) ?\s)
1371 (setq string (concat string " "))))
1372 (calendar-move-to-column (- indent (length string)))
1373 (insert string)))
1374
1270(defun calendar-generate-month (month year indent) 1375(defun calendar-generate-month (month year indent)
1271 "Produce a calendar for MONTH, YEAR on the Gregorian calendar. 1376 "Produce a calendar for MONTH, YEAR on the Gregorian calendar.
1272The calendar is inserted at the top of the buffer in which point is currently 1377The calendar is inserted at the top of the buffer in which point is currently
@@ -1279,7 +1384,10 @@ line."
1279 calendar-week-start-day) 1384 calendar-week-start-day)
1280 7)) 1385 7))
1281 (last (calendar-last-day-of-month month year)) 1386 (last (calendar-last-day-of-month month year))
1282 string day) 1387 (trunc (min calendar-intermonth-spacing
1388 (1- calendar-left-margin)))
1389 (day 1)
1390 string)
1283 (goto-char (point-min)) 1391 (goto-char (point-min))
1284 (calendar-move-to-column indent) 1392 (calendar-move-to-column indent)
1285 (insert 1393 (insert
@@ -1287,7 +1395,7 @@ line."
1287 (list (format "%s %d" (calendar-month-name month) year)) 1395 (list (format "%s %d" (calendar-month-name month) year))
1288 ?\s calendar-month-digit-width)) 1396 ?\s calendar-month-digit-width))
1289 (calendar-ensure-newline) 1397 (calendar-ensure-newline)
1290 (calendar-move-to-column indent) ; go to proper spot 1398 (calendar-insert-at-column indent calendar-intermonth-header trunc)
1291 ;; Use the first two characters of each day to head the columns. 1399 ;; Use the first two characters of each day to head the columns.
1292 (dotimes (i 7) 1400 (dotimes (i 7)
1293 (insert 1401 (insert
@@ -1299,7 +1407,7 @@ line."
1299 (substring string 0 calendar-day-header-width))) 1407 (substring string 0 calendar-day-header-width)))
1300 (make-string (- calendar-column-width calendar-day-header-width) ?\s))) 1408 (make-string (- calendar-column-width calendar-day-header-width) ?\s)))
1301 (calendar-ensure-newline) 1409 (calendar-ensure-newline)
1302 (calendar-move-to-column indent) 1410 (calendar-insert-at-column indent calendar-intermonth-text trunc)
1303 ;; Add blank days before the first of the month. 1411 ;; Add blank days before the first of the month.
1304 (insert (make-string (* blank-days calendar-column-width) ?\s)) 1412 (insert (make-string (* blank-days calendar-column-width) ?\s))
1305 ;; Put in the days of the month. 1413 ;; Put in the days of the month.
@@ -1309,15 +1417,17 @@ line."
1309 (insert (format (format "%%%dd%%s" calendar-day-digit-width) day 1417 (insert (format (format "%%%dd%%s" calendar-day-digit-width) day
1310 (make-string 1418 (make-string
1311 (- calendar-column-width calendar-day-digit-width) ?\s))) 1419 (- calendar-column-width calendar-day-digit-width) ?\s)))
1312 ;; FIXME set-text-properties? 1420 ;; 'date property prevents intermonth text confusing re-searches.
1313 (add-text-properties 1421 ;; (Tried intangible, it did not really work.)
1422 (set-text-properties
1314 (- (point) (1+ calendar-day-digit-width)) (1- (point)) 1423 (- (point) (1+ calendar-day-digit-width)) (1- (point))
1315 `(mouse-face highlight help-echo ,(eval calendar-date-echo-text))) 1424 `(mouse-face highlight help-echo ,(eval calendar-date-echo-text)
1316 (and (zerop (mod (+ day blank-days) 7)) 1425 date t))
1317 (/= day last) 1426 (when (and (zerop (mod (+ day blank-days) 7))
1318 (progn 1427 (/= day last))
1319 (calendar-ensure-newline) 1428 (calendar-ensure-newline)
1320 (calendar-move-to-column indent)))))) 1429 (setq day (1+ day)) ; first day of next week
1430 (calendar-insert-at-column indent calendar-intermonth-text trunc)))))
1321 1431
1322(defun calendar-redraw () 1432(defun calendar-redraw ()
1323 "Redraw the calendar display, if `calendar-buffer' is live." 1433 "Redraw the calendar display, if `calendar-buffer' is live."
@@ -1660,39 +1770,13 @@ the STRINGS are just concatenated and the result truncated."
1660 (let ((now (decode-time))) 1770 (let ((now (decode-time)))
1661 (list (nth 4 now) (nth 3 now) (nth 5 now)))) 1771 (list (nth 4 now) (nth 3 now) (nth 5 now))))
1662 1772
1663(defun calendar-column-to-month (&optional real) 1773(defun calendar-column-to-segment ()
1664 "Convert current column to calendar month offset number (leftmost is 0). 1774 "Convert current column to calendar month \"segment\".
1665If the cursor is in the right margin (i.e. beyond the last digit) of 1775The left-most month returns 0, the next right 1, and so on."
1666month N, returns -(N+1). If optional REAL is non-nil, return a 1776 (let ((col (max 0 (+ (current-column)
1667cons (month year), where month is the real month number (1-12)." 1777 (/ calendar-intermonth-spacing 2)
1668 (let* ((ccol (current-column)) 1778 (- calendar-left-margin)))))
1669 (col (max 0 (+ ccol (/ calendar-intermonth-spacing 2) 1779 (/ col (+ (* 7 calendar-column-width) calendar-intermonth-spacing))))
1670 (- calendar-left-margin))))
1671 (segment (/ col (+ (* 7 calendar-column-width)
1672 calendar-intermonth-spacing)))
1673 month year lastdigit edge)
1674 (if real
1675 (progn
1676 ;; NB assumes 3 month display.
1677 (if (zerop (setq month (% (+ displayed-month segment -1) 12)))
1678 (setq month 12))
1679 (setq year (cond
1680 ((and (= 12 month) (zerop segment)) (1- displayed-year))
1681 ((and (= 1 month) (= segment 2)) (1+ displayed-year))
1682 (t displayed-year)))
1683 (cons month year))
1684 ;; The rightmost column with a digit in it in this month segment.
1685 (setq lastdigit (+ calendar-left-margin
1686 calendar-month-digit-width -1
1687 (* segment calendar-month-width))
1688 ;; The rightmost edge of this month segment, dividing the
1689 ;; space between months in two.
1690 edge (+ calendar-left-margin
1691 (* (1+ segment) calendar-month-width)
1692 (- (/ calendar-intermonth-spacing 2))))
1693 (if (and (> ccol lastdigit) (< ccol edge))
1694 (- (1+ segment))
1695 segment))))
1696 1780
1697(defun calendar-cursor-to-date (&optional error event) 1781(defun calendar-cursor-to-date (&optional error event)
1698 "Return a list (month day year) of current cursor position. 1782 "Return a list (month day year) of current cursor position.
@@ -1705,15 +1789,15 @@ use instead of point."
1705 (current-buffer)) 1789 (current-buffer))
1706 (save-excursion 1790 (save-excursion
1707 (if event (goto-char (posn-point (event-start event)))) 1791 (if event (goto-char (posn-point (event-start event))))
1708 (let* ((month (calendar-column-to-month t)) 1792 (let* ((segment (calendar-column-to-segment))
1709 (year (cdr month)) 1793 (month (% (+ displayed-month (1- segment)) 12)))
1710 (month (car month)))
1711 ;; Call with point on either of the two digits in a 2-digit date, 1794 ;; Call with point on either of the two digits in a 2-digit date,
1712 ;; or on or before the digit of a 1-digit date. 1795 ;; or on or before the digit of a 1-digit date.
1713 (if (not (and (looking-at "[ 0-9]?[0-9][^0-9]") 1796 (if (not (and (looking-at "[ 0-9]?[0-9][^0-9]")
1714 (>= (count-lines (point-min) (point)) 1797 (get-text-property (point) 'date)))
1715 calendar-first-date-row)))
1716 (if error (error "Not on a date!")) 1798 (if error (error "Not on a date!"))
1799 ;; Convert segment to real month and year.
1800 (if (zerop month) (setq month 12))
1717 ;; Go back to before the first date digit. 1801 ;; Go back to before the first date digit.
1718 (or (looking-at " ") 1802 (or (looking-at " ")
1719 (re-search-backward "[^0-9]")) 1803 (re-search-backward "[^0-9]"))
@@ -1721,7 +1805,10 @@ use instead of point."
1721 (string-to-number 1805 (string-to-number
1722 (buffer-substring (1+ (point)) 1806 (buffer-substring (1+ (point))
1723 (+ 1 calendar-day-digit-width (point)))) 1807 (+ 1 calendar-day-digit-width (point))))
1724 year)))))) 1808 (cond
1809 ((and (= 12 month) (zerop segment)) (1- displayed-year))
1810 ((and (= 1 month) (= segment 2)) (1+ displayed-year))
1811 (t displayed-year))))))))
1725 1812
1726(add-to-list 'debug-ignored-errors "Not on a date!") 1813(add-to-list 'debug-ignored-errors "Not on a date!")
1727 1814
@@ -2332,14 +2419,20 @@ DATE is (month day year). Calendars that do not apply are omitted."
2332 (format "Mayan date: %s" 2419 (format "Mayan date: %s"
2333 (calendar-mayan-date-string date)))))) 2420 (calendar-mayan-date-string date))))))
2334 2421
2335(defun calendar-print-other-dates () 2422(defun calendar-print-other-dates (&optional event)
2336 "Show dates on other calendars for date under the cursor." 2423 "Show dates on other calendars for date under the cursor.
2337 (interactive) 2424If called by a mouse-event, pops up a menu with the result."
2338 (let ((date (calendar-cursor-to-date t))) 2425 (interactive (list last-nonmenu-event))
2339 (calendar-in-read-only-buffer calendar-other-calendars-buffer 2426 (let* ((date (calendar-cursor-to-date t event))
2340 (calendar-set-mode-line (format "%s (Gregorian)" 2427 (title (format "%s (Gregorian)" (calendar-date-string date)))
2341 (calendar-date-string date))) 2428 selection)
2342 (insert (mapconcat 'identity (calendar-other-dates date) "\n"))))) 2429 (if (mouse-event-p event)
2430 (and (setq selection (cal-menu-x-popup-menu event title
2431 (mapcar 'list (calendar-other-dates date))))
2432 (call-interactively selection))
2433 (calendar-in-read-only-buffer calendar-other-calendars-buffer
2434 (calendar-set-mode-line title)
2435 (insert (mapconcat 'identity (calendar-other-dates date) "\n"))))))
2343 2436
2344(defun calendar-print-day-of-year () 2437(defun calendar-print-day-of-year ()
2345 "Show day number in year/days remaining in year for date under the cursor." 2438 "Show day number in year/days remaining in year for date under the cursor."