- (buffer-read-only))
- (cond ((eq what 'today)
- (progn
- (setq ndate (calendar-date-string
- (calendar-current-date) t t))
- (replace-match ndate nil nil nil 1)))
- ((eq what 'calendar)
- (setq ndate (save-match-data (todos-set-date-from-calendar)))
- (replace-match ndate nil nil nil 1))
- (t
- (unless (eq what 'timeonly)
- (when first
- (setq ndate (if (save-match-data
- (string-match "[0-9]+" odate))
- (if (y-or-n-p "Change date? ")
- (todos-read-date)
- (todos-read-dayname))
- (if (y-or-n-p "Change day? ")
- (todos-read-dayname)
- (todos-read-date)))))
- (replace-match ndate nil nil nil 1))
- (unless (eq what 'dateonly)
- (when first
- (setq ntime (save-match-data (todos-read-time)))
- (when (< 0 (length ntime))
- (setq ntime (concat " " ntime))))
- (if otime
- (replace-match ntime nil nil nil 2)
- (goto-char (match-end 1))
- (insert ntime)))))
+ (omonthname (match-string-no-properties 6))
+ (omonth (match-string-no-properties 7))
+ (oday (match-string-no-properties 8))
+ (oyear (match-string-no-properties 9))
+ (tmn-array todos-month-name-array)
+ (mlist (append tmn-array nil))
+ (tma-array todos-month-abbrev-array)
+ (mablist (append tma-array nil))
+ (yy (and oyear (unless (string= oyear "*")
+ (string-to-number oyear))))
+ (mm (or (and omonth (unless (string= omonth "*")
+ (string-to-number omonth)))
+ (1+ (- (length mlist)
+ (length (or (member omonthname mlist)
+ (member omonthname mablist)))))))
+ (dd (and oday (unless (string= oday "*")
+ (string-to-number oday)))))
+ ;; If there are marked items, use only the first to set
+ ;; header changes, and apply these to all marked items.
+ (when first
+ (cond
+ ((eq what 'date)
+ (setq ndate (todos-read-date)))
+ ((eq what 'calendar)
+ (setq ndate (save-match-data (todos-set-date-from-calendar))))
+ ((eq what 'today)
+ (setq ndate (calendar-date-string (calendar-current-date) t t)))
+ ((eq what 'dayname)
+ (setq ndate (todos-read-dayname)))
+ ((eq what 'time)
+ (setq ntime (save-match-data (todos-read-time)))
+ (when (> (length ntime) 0)
+ (setq ntime (concat " " ntime))))
+ ;; When date string consists only of a day name,
+ ;; passing other date components is a NOP.
+ ((and (memq what '(year month day))
+ (not (or oyear omonth oday))))
+ ((eq what 'year)
+ (setq day oday
+ monthname omonthname
+ month omonth
+ year (cond ((not current-prefix-arg)
+ (todos-read-date 'year))
+ ((string= oyear "*")
+ (error "Cannot increment *"))
+ (t ; FIXME: handle negative years
+ (number-to-string (+ yy inc))))))
+ ((eq what 'month)
+ (setf day oday
+ year oyear
+ (if (memq 'month calendar-date-display-form)
+ month
+ monthname)
+ (cond ((not current-prefix-arg)
+ (todos-read-date 'month))
+ ((or (string= omonth "*") (= mm 13))
+ (error "Cannot increment *"))
+ (t
+ (let ((mminc (+ mm inc)))
+ ;; Increment or decrement month by INC
+ ;; modulo 12.
+ (setq mm (% mminc 12))
+ ;; If result is 0, make month December.
+ (setq mm (if (= mm 0) 12 (abs mm)))
+ ;; Adjust year if necessary.
+ (setq year (or (and (cond ((> mminc 12)
+ (+ yy (/ mminc 12)))
+ ((< mminc 1)
+ (- yy (/ mminc 12) 1))
+ (t yy))
+ (number-to-string yy))
+ oyear)))
+ ;; Return the changed numerical month as
+ ;; a string or the corresponding month name.
+ (if omonth
+ (number-to-string mm)
+ (aref tma-array (1- mm))))))
+ (let ((yy (string-to-number year)) ; 0 if year is "*".
+ ;; When mm is 13 (corresponding to "*" as value
+ ;; of month), this raises an args-out-of-range
+ ;; error in calendar-last-day-of-month, so use 1
+ ;; (corresponding to January) to get 31 days.
+ (mm (if (= mm 13) 1 mm)))
+ (if (> (string-to-number day)
+ (calendar-last-day-of-month mm yy))
+ (error "%s %s does not have %s days"
+ (aref tmn-array (1- mm))
+ (if (= mm 2) yy "") day))))
+ ((eq what 'day)
+ (setq year oyear
+ month omonth
+ monthname omonthname
+ day (cond
+ ((not current-prefix-arg)
+ (todos-read-date 'day mm oyear))
+ ((string= oday "*")
+ (error "Cannot increment *"))
+ ((or (string= omonth "*") (string= omonthname "*"))
+ (setq dd (+ dd inc))
+ (if (> dd 31)
+ (error "A month cannot have more than 31 days")
+ (number-to-string dd)))
+ ;; Increment or decrement day by INC,
+ ;; adjusting month and year if necessary
+ ;; (if year is "*" assume current year to
+ ;; calculate adjustment).
+ (t
+ (let* ((yy (or yy (calendar-extract-year
+ (calendar-current-date))))
+ (date (calendar-gregorian-from-absolute
+ (+ (calendar-absolute-from-gregorian
+ (list mm dd yy)) inc)))
+ (adjmm (nth 0 date)))
+ ;; Set year and month(name) to adjusted values.
+ (unless (string= year "*")
+ (setq year (number-to-string (nth 2 date))))
+ (if month
+ (setq month (number-to-string adjmm))
+ (setq monthname (aref tma-array (1- adjmm))))
+ ;; Return changed numerical day as a string.
+ (number-to-string (nth 1 date)))))))))
+ ;; If new year, month or day date string components were
+ ;; calculated, rebuild the whole date string from them.
+ (when (memq what '(year month day))
+ (if (or oyear omonth omonthname oday)
+ (setq ndate (mapconcat 'eval calendar-date-display-form ""))
+ (message "Cannot edit date component of empty date string")))
+ (when ndate (replace-match ndate nil nil nil 1))
+ ;; Add new time string to the header, if it was supplied.
+ (when ntime
+ (if otime
+ (replace-match ntime nil nil nil 2)
+ (goto-char (match-end 1))
+ (insert ntime)))