+(defcustom add-log-mailing-address nil
+ "*Electronic mail address of user, for inclusion in ChangeLog daily headers.
+This defaults to the value of `user-mail-address'."
+ :type '(choice (const :tag "Default" nil)
+ string)
+ :group 'change-log)
+
+(defcustom add-log-time-format 'add-log-iso8601-time-string
+ "*Function that defines the time format.
+For example, `add-log-iso8601-time-string', which gives the
+date in international ISO 8601 format,
+and `current-time-string' are two valid values."
+ :type '(radio (const :tag "International ISO 8601 format"
+ add-log-iso8601-time-string)
+ (const :tag "Old format, as returned by `current-time-string'"
+ current-time-string)
+ (function :tag "Other"))
+ :group 'change-log)
+
+(defcustom add-log-keep-changes-together nil
+ "*If non-nil, normally keep day's log entries for one file together.
+
+Log entries for a given file made with \\[add-change-log-entry] or
+\\[add-change-log-entry-other-window] will only be added to others \
+for that file made
+today if this variable is non-nil or that file comes first in today's
+entries. Otherwise another entry for that file will be started. An
+original log:
+
+ * foo (...): ...
+ * bar (...): change 1
+
+in the latter case, \\[add-change-log-entry-other-window] in a \
+buffer visiting `bar', yields:
+
+ * bar (...): -!-
+ * foo (...): ...
+ * bar (...): change 1
+
+and in the former:
+
+ * foo (...): ...
+ * bar (...): change 1
+ (...): -!-
+
+The NEW-ENTRY arg to `add-change-log-entry' can override the effect of
+this variable."
+ :version "20.3"
+ :type 'boolean
+ :group 'change-log)
+
+(defcustom add-log-file-name-function nil
+ "*If non-nil, function to call to identify the filename for a ChangeLog entry.
+This function is called with one argument, the value of variable
+`buffer-file-name' in that buffer. If this is nil, the default is to
+use the file's name relative to the directory of the change log file."
+ :type 'function
+ :group 'change-log)
+
+
+(defcustom change-log-version-info-enabled nil
+ "*If non-nil, enable recording version numbers with the changes."
+ :version "21.1"
+ :type 'boolean
+ :group 'change-log)
+
+(defcustom change-log-version-number-regexp-list
+ (let ((re "\\([0-9]+\.[0-9.]+\\)"))
+ (list
+ ;; (defconst ad-version "2.15"
+ (concat "^(def[^ \t\n]+[ \t]+[^ \t\n][ \t]\"" re)
+ ;; Revision: pcl-cvs.el,v 1.72 1999/09/05 20:21:54 monnier Exp
+ (concat "^;+ *Revision: +[^ \t\n]+[ \t]+" re)))
+ "*List of regexps to search for version number.
+The version number must be in group 1.
+Note: The search is conducted only within 10%, at the beginning of the file."
+ :version "21.1"
+ :type '(repeat regexp)
+ :group 'change-log)
+
+
+(defvar change-log-font-lock-keywords
+ '(;;
+ ;; Date lines, new and old styles.
+ ("^\\sw.........[0-9:+ ]*"
+ (0 font-lock-string-face)
+ ;; Name and e-mail; some people put e-mail in parens, not angles.
+ ("\\([^<(]+\\)[(<]\\([A-Za-z0-9_.-]+@[A-Za-z0-9_.-]+\\)[>)]" nil nil
+ (1 font-lock-constant-face)
+ (2 font-lock-variable-name-face)))
+ ;;
+ ;; File names.
+ ("^\t\\* \\([^ ,:([\n]+\\)"
+ (1 font-lock-function-name-face)
+ ;; Possibly further names in a list:
+ ("\\=, \\([^ ,:([\n]+\\)" nil nil (1 font-lock-function-name-face))
+ ;; Possibly a parenthesized list of names:
+ ("\\= (\\([^) ,:\n]+\\)" nil nil (1 font-lock-keyword-face))
+ ("\\=, *\\([^) ,:\n]+\\)" nil nil (1 font-lock-keyword-face)))
+ ;;
+ ;; Function or variable names.
+ ("^\t(\\([^) ,:\n]+\\)"
+ (1 font-lock-keyword-face)
+ ("\\=, *\\([^) ,:\n]+\\)" nil nil (1 font-lock-keyword-face)))
+ ;;
+ ;; Conditionals.
+ ("\\[!?\\([^]\n]+\\)\\]\\(:\\| (\\)" (1 font-lock-variable-name-face))
+ ;;
+ ;; Acknowledgements.
+ ("^\t\\(From\\|Patch\\(es\\)? by\\|Report\\(ed by\\| from\\)\\|Suggest\\(ed by\\|ion from\\)\\)"
+ 1 font-lock-comment-face)
+ (" \\(From\\|Patch\\(es\\)? by\\|Report\\(ed by\\| from\\)\\|Suggest\\(ed by\\|ion from\\)\\)"
+ 1 font-lock-comment-face))
+ "Additional expressions to highlight in Change Log mode.")
+
+(defvar change-log-mode-map (make-sparse-keymap)
+ "Keymap for Change Log major mode.")
+
+(defvar change-log-time-zone-rule nil
+ "Time zone used for calculating change log time stamps.
+It takes the same format as the TZ argument of `set-time-zone-rule'.
+If nil, use local time.")
+
+(defun add-log-iso8601-time-zone (time)
+ (let* ((utc-offset (or (car (current-time-zone time)) 0))
+ (sign (if (< utc-offset 0) ?- ?+))
+ (sec (abs utc-offset))
+ (ss (% sec 60))
+ (min (/ sec 60))
+ (mm (% min 60))
+ (hh (/ min 60)))
+ (format (cond ((not (zerop ss)) "%c%02d:%02d:%02d")
+ ((not (zerop mm)) "%c%02d:%02d")
+ (t "%c%02d"))
+ sign hh mm ss)))
+
+(defun add-log-iso8601-time-string ()
+ (if change-log-time-zone-rule
+ (let ((tz (getenv "TZ"))
+ (now (current-time)))
+ (unwind-protect
+ (progn
+ (set-time-zone-rule
+ change-log-time-zone-rule)
+ (concat
+ (format-time-string "%Y-%m-%d " now)
+ (add-log-iso8601-time-zone now)))
+ (set-time-zone-rule tz)))
+ (format-time-string "%Y-%m-%d")))