+(defsubst recentf-string-equal (s1 s2)
+ "Return non-nil if strings S1 and S2 have identical contents.
+Ignore case if `recentf-case-fold-search' is non-nil."
+ (if recentf-case-fold-search
+ (string-equal (downcase s1) (downcase s2))
+ (string-equal s1 s2)))
+
+(defsubst recentf-string-lessp (s1 s2)
+ "Return non-nil if string S1 is less than S2 in lexicographic order.
+Ignore case if `recentf-case-fold-search' is non-nil."
+ (if recentf-case-fold-search
+ (string-lessp (downcase s1) (downcase s2))
+ (string-lessp s1 s2)))
+
+(defun recentf-string-member (elt list)
+ "Return non-nil if ELT is an element of LIST.
+The value is actually the tail of LIST whose car is ELT.
+ELT must be a string and LIST a list of strings.
+Ignore case if `recentf-case-fold-search' is non-nil."
+ (while (and list (not (recentf-string-equal elt (car list))))
+ (setq list (cdr list)))
+ list)
+
+(defsubst recentf-trunc-list (l n)
+ "Return from L the list of its first N elements."
+ (let (nl)
+ (while (and l (> n 0))
+ (setq nl (cons (car l) nl)
+ n (1- n)
+ l (cdr l)))
+ (nreverse nl)))
+
+(defun recentf-dump-variable (variable &optional limit)
+ "Insert a \"(setq VARIABLE value)\" in the current buffer.
+When the value of VARIABLE is a list, optional argument LIMIT
+specifies a maximum number of elements to insert. By default insert
+the full list."
+ (let ((value (symbol-value variable)))
+ (if (atom value)
+ (insert (format "\n(setq %S '%S)\n" variable value))
+ (when (and (integerp limit) (> limit 0))
+ (setq value (recentf-trunc-list value limit)))
+ (insert (format "\n(setq %S\n '(" variable))
+ (dolist (e value)
+ (insert (format "\n %S" e)))
+ (insert "\n ))\n"))))
+
+(defvar recentf-auto-cleanup-timer nil
+ "Timer used to automatically cleanup the recent list.
+See also the option `recentf-auto-cleanup'.")
+
+(defun recentf-auto-cleanup ()
+ "Automatic cleanup of the recent list."
+ (when (timerp recentf-auto-cleanup-timer)
+ (cancel-timer recentf-auto-cleanup-timer))
+ (when recentf-mode
+ (setq recentf-auto-cleanup-timer
+ (cond
+ ((eq 'mode recentf-auto-cleanup)
+ (recentf-cleanup)
+ nil)
+ ((numberp recentf-auto-cleanup)
+ (run-with-idle-timer
+ recentf-auto-cleanup t 'recentf-cleanup))
+ ((stringp recentf-auto-cleanup)
+ (run-at-time
+ recentf-auto-cleanup nil 'recentf-cleanup))))))
+\f
+;;; File functions
+;;
+(defsubst recentf-push (filename)
+ "Push FILENAME into the recent list, if it isn't there yet.
+If it is there yet, move it at the beginning of the list.
+If `recentf-case-fold-search' is non-nil, ignore case when comparing
+filenames."
+ (let ((m (recentf-string-member filename recentf-list)))
+ (and m (setq recentf-list (delq (car m) recentf-list)))
+ (push filename recentf-list)))
+
+(defun recentf-apply-filename-handlers (name)
+ "Apply `recentf-filename-handlers' to file NAME.
+Return the transformed file name, or NAME if any handler failed, or
+returned nil."
+ (or (condition-case nil
+ (let ((handlers recentf-filename-handlers)
+ (filename name))
+ (while (and filename handlers)
+ (setq filename (funcall (car handlers) filename)
+ handlers (cdr handlers)))
+ filename)
+ (error nil))
+ name))
+
+(defsubst recentf-expand-file-name (name)
+ "Convert file NAME to absolute, and canonicalize it.
+NAME is first passed to the function `expand-file-name', then to
+`recentf-filename-handlers' to post process it."
+ (recentf-apply-filename-handlers (expand-file-name name)))
+