;;; timer.el --- run a function with args at some time in future.

;; Copyright (C) 1996 Free Software Foundation, Inc.

;; Maintainer: FSF

;; This file is part of GNU Emacs.

;; GNU Emacs is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.

;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING.  If not, write to the
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.

;;; Commentary:

;; This package gives you the capability to run Emacs Lisp commands at
;; specified times in the future, either as one-shots or periodically.

;;; Code:

(unless (fboundp #'run-at-time)
  (warn "While loading fsf-compat, run-at-time was not fboundp.  This
typically means your fsf-compat package is newer than xemacs-base.  You
should update your xemacs-base package."))

(require 'itimer)

(defalias 'timer-create 'make-itimer)

(defalias 'timerp 'itimerp)

;(defvar timer-idle-list nil
;  "List of active idle-time timers in order of increasing time")
(defvaralias 'timer-idle-list 'itimer-list)
(defvaralias 'timer-list 'itimer-list)

(defun timer-set-time (timer time &optional delta)
  "Set the trigger time of TIMER to TIME.
TIME must be in the internal format returned by, e.g., `current-time'.
If optional third argument DELTA is a positive integer, make the timer
fire repeatedly that many seconds apart."
  (let ((timer-when (itimer-time-difference time (current-time))))
    (or (> timer-when 0)
        (setq timer-when itimer-short-interval))
    (set-itimer-value timer timer-when))
  (and (numberp delta)
       (> delta 0)
       (set-itimer-restart timer delta))
  timer)

(defun timer-set-idle-time (timer secs &optional repeat)
  "Set the trigger idle time of TIMER to SECS.
If optional third argument REPEAT is non-nil, make the timer
fire each time Emacs is idle for that many seconds."
  (set-itimer-is-idle timer t)
  (set-itimer-value timer secs)
  (when repeat
    (set-itimer-restart timer repeat))
  timer)

;; timer-next-integral-multiple-of-time and timer-relative-time have moved
;; to xemacs-base/timer-funcs.el

(defun timer-inc-time (timer secs &optional usecs)
  "Increment the time set in TIMER by SECS seconds and USECS microseconds.
SECS may be a fraction.  If USECS is omitted, that means it is zero."
  (set-itimer-value
   timer
   (+ (itimer-value timer) secs (if usecs (/ usecs 1000000.0) 0))))

(defun timer-set-time-with-usecs (timer time usecs &optional delta)
  "Set the trigger time of TIMER to TIME plus USECS.
TIME must be in the internal format returned by, e.g., `current-time'.
The microsecond count from TIME is ignored, and USECS is used instead.
If optional fourth argument DELTA is a positive number, make the timer
fire repeatedly that many seconds apart."
  (let ((list (list nil nil nil)))
    (setcar list (car time))
    (setcar (nthcdr 1 list) (if (consp (cdr time))
				(car (cdr time))
			      (cdr time)))
    (setcar (nthcdr 2 list) usecs)
    (set-itimer-value timer (itimer-time-difference list (current-time)))
    (and (numberp delta)
	 (> delta 0)
	 (set-itimer-restart timer delta))
    timer))
(make-obsolete 'timer-set-time-with-usecs
               "use `timer-set-time' and `timer-inc-time' instead.")

(defun timer-set-function (timer function &optional args)
  "Make TIMER call FUNCTION with optional ARGS when triggering."
  (set-itimer-function timer function)
  (set-itimer-function-arguments timer args)
  (set-itimer-uses-arguments timer t)
  timer)

(defun timer-activate (timer &optional triggered-p)
  "Put TIMER on the list of active timers.
TRIGGERED-P is for Emacs compatibility and is currently ignored."
  (activate-itimer timer))

(defun timer-activate-when-idle (timer &optional dont-wait)
  "Arrange to activate TIMER whenever Emacs is next idle.
DONT-WAIT is for Emacs compatibility and is currently ignored."
  (set-itimer-is-idle timer t)
  (activate-itimer timer))

;; can't do this, different kind of timer
;;(defalias 'disable-timeout 'cancel-timer)

(defun cancel-timer (timer)
  "Remove TIMER from the list of active timers."
  (or (timerp timer)
      (error "Invalid timer"))
  (delete-itimer timer)
  nil)

;; cancel-function-timers has moved to xemacs-base/timer-funcs.el

(defun timer-until (timer time)
  "Calculate number of seconds from when TIMER will run, until TIME.
TIMER is a timer, and stands for the time when its next repeat is scheduled.
TIME is a time-list."
  (- (itimer-time-difference time (current-time)) (itimer-value timer)))

;; timer-event-handler and timeout-event-p are internal functions (not
;; called by users).  We do it differently; see itimer.el.

;; Except for add-timeout, the remaining functions in this file
;; (run-at-time, run-with-timer, run-with-idle-timer, with-timeout-handler,
;; with-timeout, and y-or-n-p-with-timeout) have moved to
;; xemacs-base/timer-funcs.el.  The add-timeout function is an XEmacs builtin.


(provide 'timer)

;;; timer.el ends here
