]> code.delx.au - gnu-emacs/blob - lisp/calendar/cal-move.el
(gud-def): Add %c case.
[gnu-emacs] / lisp / calendar / cal-move.el
1 ;;; cal-move.el --- calendar functions for movement in the calendar
2
3 ;; Copyright (C) 1995, 2001, 2002, 2003, 2004, 2005, 2006
4 ;; Free Software Foundation, Inc.
5
6 ;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
7 ;; Maintainer: Glenn Morris <rgm@gnu.org>
8 ;; Keywords: calendar
9 ;; Human-Keywords: calendar
10
11 ;; This file is part of GNU Emacs.
12
13 ;; GNU Emacs is free software; you can redistribute it and/or modify
14 ;; it under the terms of the GNU General Public License as published by
15 ;; the Free Software Foundation; either version 2, or (at your option)
16 ;; any later version.
17
18 ;; GNU Emacs is distributed in the hope that it will be useful,
19 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 ;; GNU General Public License for more details.
22
23 ;; You should have received a copy of the GNU General Public License
24 ;; along with GNU Emacs; see the file COPYING. If not, write to the
25 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
26 ;; Boston, MA 02110-1301, USA.
27
28 ;;; Commentary:
29
30 ;; This collection of functions implements movement in the calendar for
31 ;; calendar.el.
32
33 ;; Comments, corrections, and improvements should be sent to
34 ;; Edward M. Reingold Department of Computer Science
35 ;; (217) 333-6733 University of Illinois at Urbana-Champaign
36 ;; reingold@cs.uiuc.edu 1304 West Springfield Avenue
37 ;; Urbana, Illinois 61801
38
39 ;;; Code:
40
41 (defvar displayed-month)
42 (defvar displayed-year)
43
44 (require 'calendar)
45
46 (defun calendar-goto-today ()
47 "Reposition the calendar window so the current date is visible."
48 (interactive)
49 (let ((today (calendar-current-date)));; The date might have changed.
50 (if (not (calendar-date-is-visible-p today))
51 (generate-calendar-window)
52 (update-calendar-mode-line)
53 (calendar-cursor-to-visible-date today)))
54 (run-hooks 'calendar-move-hook))
55
56 (defun calendar-forward-month (arg)
57 "Move the cursor forward ARG months.
58 Movement is backward if ARG is negative."
59 (interactive "p")
60 (calendar-cursor-to-nearest-date)
61 (let* ((cursor-date (calendar-cursor-to-date t))
62 (month (extract-calendar-month cursor-date))
63 (day (extract-calendar-day cursor-date))
64 (year (extract-calendar-year cursor-date)))
65 (increment-calendar-month month year arg)
66 (let ((last (calendar-last-day-of-month month year)))
67 (if (< last day)
68 (setq day last)))
69 ;; Put the new month on the screen, if needed, and go to the new date.
70 (let ((new-cursor-date (list month day year)))
71 (if (not (calendar-date-is-visible-p new-cursor-date))
72 (calendar-other-month month year))
73 (calendar-cursor-to-visible-date new-cursor-date)))
74 (run-hooks 'calendar-move-hook))
75
76 (defun calendar-forward-year (arg)
77 "Move the cursor forward by ARG years.
78 Movement is backward if ARG is negative."
79 (interactive "p")
80 (calendar-forward-month (* 12 arg)))
81
82 (defun calendar-backward-month (arg)
83 "Move the cursor backward by ARG months.
84 Movement is forward if ARG is negative."
85 (interactive "p")
86 (calendar-forward-month (- arg)))
87
88 (defun calendar-backward-year (arg)
89 "Move the cursor backward ARG years.
90 Movement is forward is ARG is negative."
91 (interactive "p")
92 (calendar-forward-month (* -12 arg)))
93
94 (defun scroll-calendar-left (&optional arg)
95 "Scroll the displayed calendar left by ARG months.
96 If ARG is negative the calendar is scrolled right. Maintains the relative
97 position of the cursor with respect to the calendar as well as possible."
98 (interactive "p")
99 (unless arg (setq arg 1))
100 (calendar-cursor-to-nearest-date)
101 (let ((old-date (calendar-cursor-to-date))
102 (today (calendar-current-date)))
103 (if (/= arg 0)
104 (let ((month displayed-month)
105 (year displayed-year))
106 (increment-calendar-month month year arg)
107 (generate-calendar-window month year)
108 (calendar-cursor-to-visible-date
109 (cond
110 ((calendar-date-is-visible-p old-date) old-date)
111 ((calendar-date-is-visible-p today) today)
112 (t (list month 1 year)))))))
113 (run-hooks 'calendar-move-hook))
114
115 (defun scroll-calendar-right (&optional arg)
116 "Scroll the displayed calendar window right by ARG months.
117 If ARG is negative the calendar is scrolled left. Maintains the relative
118 position of the cursor with respect to the calendar as well as possible."
119 (interactive "p")
120 (scroll-calendar-left (- (or arg 1))))
121
122 (defun scroll-calendar-left-three-months (arg)
123 "Scroll the displayed calendar window left by 3*ARG months.
124 If ARG is negative the calendar is scrolled right. Maintains the relative
125 position of the cursor with respect to the calendar as well as possible."
126 (interactive "p")
127 (scroll-calendar-left (* 3 arg)))
128
129 (defun scroll-calendar-right-three-months (arg)
130 "Scroll the displayed calendar window right by 3*ARG months.
131 If ARG is negative the calendar is scrolled left. Maintains the relative
132 position of the cursor with respect to the calendar as well as possible."
133 (interactive "p")
134 (scroll-calendar-left (* -3 arg)))
135
136 (defun calendar-cursor-to-nearest-date ()
137 "Move the cursor to the closest date.
138 The position of the cursor is unchanged if it is already on a date.
139 Returns the list (month day year) giving the cursor position."
140 (let ((date (calendar-cursor-to-date))
141 (column (current-column)))
142 (if date
143 date
144 (if (> 3 (count-lines (point-min) (point)))
145 (progn
146 (goto-line 3)
147 (move-to-column column)))
148 (if (not (looking-at "[0-9]"))
149 (if (and (not (looking-at " *$"))
150 (or (< column 25)
151 (and (> column 27)
152 (< column 50))
153 (and (> column 52)
154 (< column 75))))
155 (progn
156 (re-search-forward "[0-9]" nil t)
157 (backward-char 1))
158 (re-search-backward "[0-9]" nil t)))
159 (calendar-cursor-to-date))))
160
161 (defun calendar-forward-day (arg)
162 "Move the cursor forward ARG days.
163 Moves backward if ARG is negative."
164 (interactive "p")
165 (if (/= 0 arg)
166 (let*
167 ((cursor-date (calendar-cursor-to-date))
168 (cursor-date (if cursor-date
169 cursor-date
170 (if (> arg 0) (setq arg (1- arg)))
171 (calendar-cursor-to-nearest-date)))
172 (new-cursor-date
173 (calendar-gregorian-from-absolute
174 (+ (calendar-absolute-from-gregorian cursor-date) arg)))
175 (new-display-month (extract-calendar-month new-cursor-date))
176 (new-display-year (extract-calendar-year new-cursor-date)))
177 ;; Put the new month on the screen, if needed, and go to the new date.
178 (if (not (calendar-date-is-visible-p new-cursor-date))
179 (calendar-other-month new-display-month new-display-year))
180 (calendar-cursor-to-visible-date new-cursor-date)))
181 (run-hooks 'calendar-move-hook))
182
183 (defun calendar-backward-day (arg)
184 "Move the cursor back ARG days.
185 Moves forward if ARG is negative."
186 (interactive "p")
187 (calendar-forward-day (- arg)))
188
189 (defun calendar-forward-week (arg)
190 "Move the cursor forward ARG weeks.
191 Moves backward if ARG is negative."
192 (interactive "p")
193 (calendar-forward-day (* arg 7)))
194
195 (defun calendar-backward-week (arg)
196 "Move the cursor back ARG weeks.
197 Moves forward if ARG is negative."
198 (interactive "p")
199 (calendar-forward-day (* arg -7)))
200
201 (defun calendar-beginning-of-week (arg)
202 "Move the cursor back ARG calendar-week-start-day's."
203 (interactive "p")
204 (calendar-cursor-to-nearest-date)
205 (let ((day (calendar-day-of-week (calendar-cursor-to-date))))
206 (calendar-backward-day
207 (if (= day calendar-week-start-day)
208 (* 7 arg)
209 (+ (mod (- day calendar-week-start-day) 7)
210 (* 7 (1- arg)))))))
211
212 (defun calendar-end-of-week (arg)
213 "Move the cursor forward ARG calendar-week-start-day+6's."
214 (interactive "p")
215 (calendar-cursor-to-nearest-date)
216 (let ((day (calendar-day-of-week (calendar-cursor-to-date))))
217 (calendar-forward-day
218 (if (= day (mod (1- calendar-week-start-day) 7))
219 (* 7 arg)
220 (+ (- 6 (mod (- day calendar-week-start-day) 7))
221 (* 7 (1- arg)))))))
222
223 (defun calendar-beginning-of-month (arg)
224 "Move the cursor backward ARG month beginnings."
225 (interactive "p")
226 (calendar-cursor-to-nearest-date)
227 (let* ((date (calendar-cursor-to-date))
228 (month (extract-calendar-month date))
229 (day (extract-calendar-day date))
230 (year (extract-calendar-year date)))
231 (if (= day 1)
232 (calendar-backward-month arg)
233 (calendar-cursor-to-visible-date (list month 1 year))
234 (calendar-backward-month (1- arg)))))
235
236 (defun calendar-end-of-month (arg)
237 "Move the cursor forward ARG month ends."
238 (interactive "p")
239 (calendar-cursor-to-nearest-date)
240 (let* ((date (calendar-cursor-to-date))
241 (month (extract-calendar-month date))
242 (day (extract-calendar-day date))
243 (year (extract-calendar-year date))
244 (last-day (calendar-last-day-of-month month year)))
245 (if (/= day last-day)
246 (progn
247 (calendar-cursor-to-visible-date (list month last-day year))
248 (setq arg (1- arg))))
249 (increment-calendar-month month year arg)
250 (let ((last-day (list
251 month
252 (calendar-last-day-of-month month year)
253 year)))
254 (if (not (calendar-date-is-visible-p last-day))
255 (calendar-other-month month year)
256 (calendar-cursor-to-visible-date last-day))))
257 (run-hooks 'calendar-move-hook))
258
259 (defun calendar-beginning-of-year (arg)
260 "Move the cursor backward ARG year beginnings."
261 (interactive "p")
262 (calendar-cursor-to-nearest-date)
263 (let* ((date (calendar-cursor-to-date))
264 (month (extract-calendar-month date))
265 (day (extract-calendar-day date))
266 (year (extract-calendar-year date))
267 (jan-first (list 1 1 year))
268 (calendar-move-hook nil))
269 (if (and (= day 1) (= 1 month))
270 (calendar-backward-month (* 12 arg))
271 (if (and (= arg 1)
272 (calendar-date-is-visible-p jan-first))
273 (calendar-cursor-to-visible-date jan-first)
274 (calendar-other-month 1 (- year (1- arg)))
275 (calendar-cursor-to-visible-date (list 1 1 displayed-year)))))
276 (run-hooks 'calendar-move-hook))
277
278 (defun calendar-end-of-year (arg)
279 "Move the cursor forward ARG year beginnings."
280 (interactive "p")
281 (calendar-cursor-to-nearest-date)
282 (let* ((date (calendar-cursor-to-date))
283 (month (extract-calendar-month date))
284 (day (extract-calendar-day date))
285 (year (extract-calendar-year date))
286 (dec-31 (list 12 31 year))
287 (calendar-move-hook nil))
288 (if (and (= day 31) (= 12 month))
289 (calendar-forward-month (* 12 arg))
290 (if (and (= arg 1)
291 (calendar-date-is-visible-p dec-31))
292 (calendar-cursor-to-visible-date dec-31)
293 (calendar-other-month 12 (+ year (1- arg)))
294 (calendar-cursor-to-visible-date (list 12 31 displayed-year)))))
295 (run-hooks 'calendar-move-hook))
296
297 (defun calendar-cursor-to-visible-date (date)
298 "Move the cursor to DATE that is on the screen."
299 (let* ((month (extract-calendar-month date))
300 (day (extract-calendar-day date))
301 (year (extract-calendar-year date))
302 (first-of-month-weekday (calendar-day-of-week (list month 1 year))))
303 (goto-line (+ 3
304 (/ (+ day -1
305 (mod
306 (- (calendar-day-of-week (list month 1 year))
307 calendar-week-start-day)
308 7))
309 7)))
310 (move-to-column (+ 6
311 (* 25
312 (1+ (calendar-interval
313 displayed-month displayed-year month year)))
314 (* 3 (mod
315 (- (calendar-day-of-week date)
316 calendar-week-start-day)
317 7))))))
318
319 (defun calendar-goto-date (date)
320 "Move cursor to DATE."
321 (interactive (list (calendar-read-date)))
322 (let ((month (extract-calendar-month date))
323 (year (extract-calendar-year date)))
324 (if (not (calendar-date-is-visible-p date))
325 (calendar-other-month
326 (if (and (= month 1) (= year 1))
327 2
328 month)
329 year)))
330 (calendar-cursor-to-visible-date date)
331 (run-hooks 'calendar-move-hook))
332
333 (defun calendar-goto-day-of-year (year day &optional noecho)
334 "Move cursor to YEAR, DAY number; echo DAY/YEAR unless NOECHO is t.
335 Negative DAY counts backward from end of year."
336 (interactive
337 (let* ((year (calendar-read
338 "Year (>0): "
339 (lambda (x) (> x 0))
340 (int-to-string (extract-calendar-year
341 (calendar-current-date)))))
342 (last (if (calendar-leap-year-p year) 366 365))
343 (day (calendar-read
344 (format "Day number (+/- 1-%d): " last)
345 '(lambda (x) (and (<= 1 (abs x)) (<= (abs x) last))))))
346 (list year day)))
347 (calendar-goto-date
348 (calendar-gregorian-from-absolute
349 (if (< 0 day)
350 (+ -1 day (calendar-absolute-from-gregorian (list 1 1 year)))
351 (+ 1 day (calendar-absolute-from-gregorian (list 12 31 year))))))
352 (or noecho (calendar-print-day-of-year)))
353
354 (provide 'cal-move)
355
356 ;;; arch-tag: d0883c46-7e16-4914-8ff8-8f67e699b781
357 ;;; cal-move.el ends here