1 ;;; wl-util.el -- Utility modules for Wanderlust.
3 ;; Copyright 1998,1999,2000 Yuuichi Teranishi <teranisi@gohome.org>
5 ;; Author: Yuuichi Teranishi <teranisi@gohome.org>
6 ;; Keywords: mail, net news
7 ;; Time-stamp: <2000-03-22 15:56:12 teranisi>
9 ;; This file is part of Wanderlust (Yet Another Message Interface on Emacsen).
11 ;; This program is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 2, or (at your option)
16 ;; This program is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ;; GNU General Public License for more details.
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs; see the file COPYING. If not, write to the
23 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 ;; Boston, MA 02111-1307, USA.
47 (unless (boundp symbol)
48 (set (make-local-variable symbol) nil))))
53 mime-edit-insert-user-agent-field
54 mime-edit-user-agent-value
56 mime-editor/codename))
58 (defun-maybe read-event ())
59 (defun-maybe next-command-event ())
60 (defun-maybe event-to-character (a))
61 (defun-maybe key-press-event-p (a))
62 (defun-maybe button-press-event-p (a))
63 (defun-maybe set-process-kanji-code (a b))
64 (defun-maybe set-process-coding-system (a b c))
65 (defun-maybe dispatch-event (a)))
67 (defalias 'wl-set-work-buf 'elmo-set-work-buf)
68 (make-obsolete 'wl-set-work-buf 'elmo-set-work-buf)
70 (defmacro wl-append (val func)
72 (list 'nconc val func)
73 (list 'setq val func)))
75 (defun wl-parse (string regexp &optional matchn)
76 (or matchn (setq matchn 1))
78 (store-match-data nil)
79 (while (string-match regexp string (match-end 0))
80 (setq list (cons (substring string (match-beginning matchn)
81 (match-end matchn)) list)))
84 (defun wl-delete-duplicates (list &optional all hack-addresses)
85 "Delete duplicate equivalent strings from the list.
86 If ALL is t, then if there is more than one occurrence of a string in the list,
87 then all occurrences of it are removed instead of just the subsequent ones.
88 If HACK-ADDRESSES is t, then the strings are considered to be mail addresses,
89 and only the address part is compared (so that \"Name <foo>\" and \"foo\"
90 would be considered to be equivalent.)"
91 (let ((hashtable (make-vector 29 0))
94 (fillarray hashtable 0)
98 (wl-address-header-extract-address (car list))
100 sym-string (or sym-string "-unparseable-garbage-")
101 sym (intern sym-string hashtable))
103 (and all (setcar (symbol-value sym) nil))
104 (setq new-list (cons (car list) new-list))
106 (setq list (cdr list)))
107 (delq nil (nreverse new-list))))
110 (defalias 'wl-string-member 'elmo-string-member)
111 (defalias 'wl-string-match-member 'elmo-string-match-member)
112 (defalias 'wl-string-delete-match 'elmo-string-delete-match)
113 (defalias 'wl-string-match-assoc 'elmo-string-match-assoc)
114 (defalias 'wl-string-assoc 'elmo-string-assoc)
115 (defalias 'wl-string-rassoc 'elmo-string-rassoc)
117 (defun wl-parse-addresses (string)
122 (let (list start s char)
124 (goto-char (point-min))
125 (skip-chars-forward "\t\f\n\r ")
128 (skip-chars-forward "^\"\\,(")
129 (setq char (following-char))
135 (setq s (buffer-substring start (point)))
136 (if (or (null (string-match "^[\t\f\n\r ]+$" s))
137 (not (string= s "")))
138 (setq list (cons s list)))
139 (skip-chars-forward ",\t\f\n\r ")
140 (setq start (point)))
142 (re-search-forward "[^\\]\"" nil 0))
146 (while (and (not (eobp)) (not (zerop parens)))
147 (re-search-forward "[()]" nil 0)
149 (= (char-after (- (point) 2)) ?\\)))
150 ((= (preceding-char) ?\()
151 (setq parens (1+ parens)))
153 (setq parens (1- parens)))))))))
154 (setq s (buffer-substring start (point)))
155 (if (and (null (string-match "^[\t\f\n\r ]+$" s))
156 (not (string= s "")))
157 (setq list (cons s list)))
158 (nreverse list)) ; jwz: fixed order
161 (defun wl-version (&optional with-codename)
162 (format "%s %s%s" wl-appname wl-version
164 (format " - \"%s\"" wl-codename) "")))
166 (defun wl-version-show ()
168 (message "%s" (wl-version t)))
171 (defun wl-extended-emacs-version (&optional with-codename)
172 "Stringified Emacs version"
175 ((string-match "^\\([0-9]+\\.[0-9]+\\)\\.[.0-9]+$" emacs-version)
176 (concat "Emacs " (wl-match-string 1 emacs-version)
177 (and (boundp 'mule-version)(concat "/Mule " mule-version))))
178 ((string-match "\\([A-Z]*[Mm][Aa][Cc][Ss]\\)[^(]*\\(\\((beta.*)\\|'\\)\\)?"
180 (concat (wl-match-string 1 emacs-version)
181 (format " %d.%d" emacs-major-version emacs-minor-version)
182 (if (and (boundp 'emacs-beta-version)
184 (format "b%d" emacs-beta-version))
186 (if (boundp 'xemacs-codename)
187 (concat " - \"" xemacs-codename "\"")))))
190 (defun wl-extended-emacs-version2 (&optional delimiter with-codename)
191 "Stringified Emacs version"
194 ((and (boundp 'mule-version)
196 (string-match "\\([0-9]+\.[0-9]+\\)\\(.*$\\)" mule-version))
197 (format "Mule%s%s@%d.%d%s"
199 (wl-match-string 1 mule-version)
203 (wl-match-string 2 mule-version)
205 ((string-match "^\\([0-9]+\\.[0-9]+\\)\\.[.0-9]+$" emacs-version)
206 (if (boundp 'nemacs-version)
207 (concat "Nemacs" (or delimiter " ")
210 (substring emacs-version
213 (concat "Emacs" (or delimiter " ")
214 (wl-match-string 1 emacs-version))))
215 ((string-match "\\([A-Z]*[Mm][Aa][Cc][Ss]\\)[^(]*\\(\\((beta.*)\\|'\\)\\)?"
217 (concat (wl-match-string 1 emacs-version)
219 (format "%d.%d" emacs-major-version emacs-minor-version)
220 (if (and (boundp 'emacs-beta-version)
222 (format "b%d" emacs-beta-version))
223 (if (and with-codename
224 (boundp 'xemacs-codename)
226 (format " (%s)" xemacs-codename))))
229 (defun wl-extended-emacs-version3 (&optional delimiter with-codename)
230 "Stringified Emacs version"
233 ((and (boundp 'mule-version)
235 (string-match "\\([0-9]+\.[0-9]+\\)\\(.*$\\)" mule-version))
236 (format "Emacs%s%d.%d Mule%s%s%s"
241 (wl-match-string 1 mule-version)
243 (wl-match-string 2 mule-version)
245 ((string-match "^\\([0-9]+\\.[0-9]+\\)\\.[.0-9]+$" emacs-version)
246 (if (boundp 'nemacs-version)
247 (let ((nemacs-codename-assoc '(("3.3.2" . " (FUJIMUSUME)")
248 ("3.3.1" . " (HINAMATSURI)")
249 ("3.2.3" . " (YUMENO-AWAYUKI)"))))
250 (format "Emacs%s%s Nemacs%s%s%s"
252 (wl-match-string 1 emacs-version)
255 (or (and with-codename
256 (cdr (assoc nemacs-version
257 nemacs-codename-assoc)))
259 (concat "Emacs" (or delimiter " ")
260 (wl-match-string 1 emacs-version))))
261 ((string-match "\\([A-Z]*[Mm][Aa][Cc][Ss]\\)[^(]*\\(\\((beta.*)\\|'\\)\\)?"
263 (concat (wl-match-string 1 emacs-version)
265 (format "%d.%d" emacs-major-version emacs-minor-version)
266 (if (and (boundp 'emacs-beta-version)
268 (format "b%d" emacs-beta-version))
269 (if (and with-codename
270 (boundp 'xemacs-codename)
272 (format " (%s)" xemacs-codename))))
275 (defun wl-append-element (list element)
277 (append list (list element))
280 (defun wl-read-event-char ()
281 "Get the next event."
282 (let ((event (read-event)))
283 ;; should be gnus-characterp, but this can't be called in XEmacs anyway
284 (cons (and (numberp event) event) event)))
286 (defun wl-xmas-read-event-char ()
287 "Get the next event."
288 (let ((event (next-command-event)))
290 ;; We junk all non-key events. Is this naughty?
291 (while (not (or (key-press-event-p event)
292 (button-press-event-p event)))
293 (dispatch-event event)
294 (setq event (next-command-event)))
295 (cons (and (key-press-event-p event)
296 (event-to-character event))
300 (fset 'wl-read-event-char 'wl-xmas-read-event-char))
302 (defmacro wl-push (v l)
303 (list 'setq l (list 'cons v l)))
306 (list 'car (list 'prog1 l (list 'setq l (list 'cdr l)))))
308 (defun wl-ask-folder (func mes-string)
310 (cmd (if (featurep 'xemacs)
311 (event-to-character last-command-event)
312 (string-to-char (format "%s" (this-command-keys))))))
314 (setq key (car (setq keve (wl-read-event-char))))
315 (if (or (equal key ?\ )
321 (wl-push (cdr keve) unread-command-events))))
323 ;(defalias 'wl-make-hash 'elmo-make-hash)
324 ;(make-obsolete 'wl-make-hash 'elmo-make-hash)
326 ;(defalias 'wl-get-hash-val 'elmo-get-hash-val)
327 ;(make-obsolete 'wl-get-hash-val 'elmo-get-hash-val)
329 ;(defalias 'wl-set-hash-val 'elmo-set-hash-val)
330 ;(make-obsolete 'wl-set-hash-val 'elmo-set-hash-val)
332 (defsubst wl-set-string-width (width string)
334 (elmo-set-buffer-multibyte default-enable-multibyte-characters)
336 (if (> (current-column) width)
337 (if (> (move-to-column width) width)
339 (condition-case nil ; ignore error
342 (concat (buffer-substring (point-min) (point)) " "))
343 (buffer-substring (point-min) (point)))
344 (if (= (current-column) width)
347 (format (format "%%%ds"
348 (- width (current-column)))
351 (defun wl-display-bytes (num)
354 ((> (setq result (/ num 1000000)) 0)
355 (setq remain (% num 1000000))
356 (if (> remain 400000)
357 (setq result (+ 1 result)))
358 (format "%dM" result))
359 ((> (setq result (/ num 1000)) 0)
360 (setq remain (% num 1000))
362 (setq result (+ 1 result)))
363 (format "%dK" result))
364 (t (format "%dB" result)))))
366 (defun wl-generate-user-agent-string ()
367 "A candidate of wl-generate-mailer-string-func.
368 Insert User-Agent field instead of X-Mailer field."
369 (let ((mime-user-agent (and (boundp 'mime-edit-insert-user-agent-field)
370 mime-edit-insert-user-agent-field
371 mime-edit-user-agent-value)))
373 (concat "User-Agent: "
374 wl-appname "/" wl-version
375 " (" wl-codename ") "
377 (if (and (boundp 'mime-editor/version)
379 (concat "User-Agent: "
380 wl-appname "/" wl-version
381 " (" wl-codename ") "
382 "tm/" mime-editor/version
383 (if (and (boundp 'mime-editor/codename)
384 mime-editor/codename)
385 (concat " (" mime-editor/codename ")"))
386 (if (and (boundp 'mime-library-product)
387 mime-library-product)
388 (concat " " (aref mime-library-product 0)
390 (mapconcat 'int-to-string
391 (aref mime-library-product 1)
393 " (" (aref mime-library-product 2) ")"))
397 (concat " " (apel-version)))
399 " " (wl-extended-emacs-version3 "/" t))
400 (concat "User-Agent: " wl-appname "/" wl-version " (" wl-codename ") "
401 (wl-extended-emacs-version3 "/" t))))))
403 (defun wl-make-modeline-subr ()
404 (let* ((duplicated (copy-sequence mode-line-format))
405 (cur-entry duplicated)
407 (if (memq 'wl-plug-state-indicator mode-line-format)
411 (if (or (and (symbolp (car cur-entry))
412 (eq 'mode-line-buffer-identification
414 (and (consp (car cur-entry))
416 (eq 'modeline-buffer-identification
417 (car (car cur-entry)))
418 (eq 'modeline-buffer-identification
419 (cdr (car cur-entry))))))
421 (setq return-modeline (append return-modeline
422 (list 'wl-plug-state-indicator)
424 (throw 'done return-modeline))
425 (setq return-modeline (append return-modeline
426 (list (car cur-entry)))))
427 (setq cur-entry (cdr cur-entry)))))))
429 (defalias 'wl-display-error 'elmo-display-error)
430 (make-obsolete 'wl-display-error 'elmo-display-error)
432 (defun wl-get-assoc-list-value (assoc-list folder &optional match)
434 (let ((alist assoc-list)
437 (setq pair (car alist))
438 (if (string-match (car pair) folder)
439 (cond ((eq match 'all)
440 (setq value (append value (list (cdr pair)))))
441 ((eq match 'all-list)
442 (setq value (append value (cdr pair))))
444 (throw 'found (cdr pair)))))
445 (setq alist (cdr alist)))
448 (defmacro wl-match-string (pos string)
449 "Substring POSth matched string."
450 (` (substring (, string) (match-beginning (, pos)) (match-end (, pos)))))
452 (defmacro wl-match-buffer (pos)
453 "Substring POSth matched from the current buffer."
454 (` (buffer-substring-no-properties
455 (match-beginning (, pos)) (match-end (, pos)))))
457 (put 'wl-as-coding-system 'lisp-indent-function 1)
458 (put 'wl-as-mime-charset 'lisp-indent-function 1)
462 (defmacro wl-as-coding-system (coding-system &rest body)
463 (` (let ((coding-system-for-read (, coding-system))
464 (coding-system-for-write (, coding-system)))
467 (defmacro wl-as-coding-system (coding-system &rest body)
468 (` (let ((file-coding-system-for-read (, coding-system))
469 (file-coding-system (, coding-system)))
472 (defmacro wl-as-coding-system (coding-system &rest body)
473 (` (let ((default-kanji-fileio-code (, coding-system))
474 (kanji-fileio-code (, coding-system))
478 (defmacro wl-as-mime-charset (mime-charset &rest body)
479 (` (wl-as-coding-system (mime-charset-to-coding-system (, mime-charset))
482 (defalias 'wl-string 'elmo-string)
483 (make-obsolete 'wl-string 'elmo-string)
485 (defun wl-parse-newsgroups (string &optional subscribe-only)
486 (let* ((nglist (wl-parse string "[ \t\f\r\n,]*\\([^ \t\f\r\n,]+\\)"))
488 (if (not subscribe-only)
491 (if (intern-soft (car nglist) wl-folder-newsgroups-hashtb)
492 (wl-append ret-val (list (car nglist))))
493 (setq nglist (cdr nglist)))
496 ;; Check if active region exists or not.
497 (if (boundp 'mark-active)
498 (defmacro wl-region-exists-p ()
500 (if (fboundp 'region-exists-p)
501 (defmacro wl-region-exists-p ()
502 (list 'region-exists-p))))
504 (if (not (fboundp 'overlays-in))
505 (defun overlays-in (beg end)
506 "Return a list of the overlays that overlap the region BEG ... END.
507 Overlap means that at least one character is contained within the overlay
508 and also contained within the specified region.
509 Empty overlays are included in the result if they are located at BEG
510 or between BEG and END."
511 (let ((ovls (overlay-lists))
517 (setq ovls (nconc (car ovls) (cdr ovls)))
521 (if (or (and (<= (overlay-start tmp) end)
522 (>= (overlay-start tmp) beg))
523 (and (<= (overlay-end tmp) end)
524 (>= (overlay-end tmp) beg)))
525 (setq retval (cons tmp retval))))
528 (defsubst wl-repeat-string (str times)
532 (setq ret-val (concat ret-val str))
533 (setq loop (- loop 1)))
536 (defun wl-list-diff (list1 list2)
537 "Return a list of elements of LIST1 that do not appear in LIST2."
538 (let ((list1 (copy-sequence list1)))
540 (setq list1 (delq (car list2) list1))
541 (setq list2 (cdr list2)))
544 (defun wl-append-assoc-list (item value alist)
545 "make assoc list '((item1 value1-1 value1-2 ...)) (item2 value2-1 ...)))"
546 (let ((entry (assoc item alist)))
549 (when (not (member value (cdr entry)))
550 (nconc entry (list value)))
553 (list (list item value))))))
555 (defun wl-delete-alist (key alist)
556 "Delete all entries in ALIST that have a key eq to KEY."
558 (while (setq entry (assq key alist))
559 (setq alist (delq entry alist)))
564 (static-unless (fboundp 'pp)
565 (defvar pp-escape-newlines t)
566 (defun pp (object &optional stream)
567 "Output the pretty-printed representation of OBJECT, any Lisp object.
568 Quoting characters are printed when needed to make output that `read'
569 can handle, whenever this is possible.
570 Output stream is STREAM, or value of `standard-output' (which see)."
571 (princ (pp-to-string object) (or stream standard-output)))
573 (defun pp-to-string (object)
574 "Return a string containing the pretty-printed representation of OBJECT,
575 any Lisp object. Quoting characters are used when needed to make output
576 that `read' can handle, whenever this is possible."
578 (set-buffer (generate-new-buffer " pp-to-string"))
581 (lisp-mode-variables t)
582 (let ((print-escape-newlines pp-escape-newlines))
583 (prin1 object (current-buffer)))
584 (goto-char (point-min))
587 ((looking-at "\\s(\\|#\\s(")
588 (while (looking-at "\\s(\\|#\\s(")
590 ((and (looking-at "\\(quote[ \t]+\\)\\([^.)]\\)")
591 (> (match-beginning 1) 1)
592 (= ?\( (char-after (1- (match-beginning 1))))
593 ;; Make sure this is a two-element list.
595 (goto-char (match-beginning 2))
597 ;; Avoid mucking with match-data; does this test work?
598 (char-equal ?\) (char-after (point)))))
599 ;; -1 gets the paren preceding the quote as well.
600 (delete-region (1- (match-beginning 1)) (match-end 1))
603 (if (looking-at "[ \t]*\)")
604 (delete-region (match-beginning 0) (match-end 0))
605 (error "Malformed quote"))
607 ((condition-case err-var
608 (prog1 t (down-list 1))
611 (skip-chars-backward " \t")
614 (progn (skip-chars-forward " \t") (point)))
615 (if (not (char-equal ?' (char-after (1- (point)))))
617 ((condition-case err-var
618 (prog1 t (up-list 1))
620 (while (looking-at "\\s)")
622 (skip-chars-backward " \t")
625 (progn (skip-chars-forward " \t") (point)))
626 (if (not (char-equal ?' (char-after (1- (point)))))
628 (t (goto-char (point-max)))))
629 (goto-char (point-min))
632 (kill-buffer (current-buffer))))))
634 (defsubst wl-get-date-iso8601 (date)
635 (or (get-text-property 0 'wl-date date)
636 (let* ((d1 (timezone-fix-time date nil nil))
637 (time (format "%04d%02d%02dT%02d%02d%02d"
638 (aref d1 0) (aref d1 1) (aref d1 2)
639 (aref d1 3) (aref d1 4) (aref d1 5))))
640 (put-text-property 0 1 'wl-date time date)
643 (defun wl-make-date-string ()
644 (let ((s (current-time-string)))
645 (string-match "\\`\\([A-Z][a-z][a-z]\\) +[A-Z][a-z][a-z] +[0-9][0-9]? *[0-9][0-9]?:[0-9][0-9]:[0-9][0-9] *[0-9]?[0-9]?[0-9][0-9]"
647 (concat (wl-match-string 1 s) ", "
648 (timezone-make-date-arpa-standard s (current-time-zone)))))
650 (defun wl-date-iso8601 (date)
651 "Convert the DATE to YYMMDDTHHMMSS."
653 (wl-get-date-iso8601 date)
656 (defun wl-day-number (date)
657 (let ((dat (mapcar '(lambda (s) (and s (string-to-int s)) )
658 (timezone-parse-date date))))
659 (timezone-absolute-from-gregorian
660 (nth 1 dat) (nth 2 dat) (car dat))))
662 (defun wl-url-news (url &rest args)
663 (interactive "sURL: ")
664 (if (string-match "^news:\\(.*\\)$" url)
665 (wl-summary-goto-folder-subr
666 (concat "-" (elmo-match-string 1 url)) nil nil nil t)
667 (message "Not a news: url.")))
669 (defun wl-url-nntp (url &rest args)
670 (interactive "sURL: ")
671 (let (folder fld-name server port msg)
673 "^nntp://\\([^:/]*\\):?\\([0-9]*\\)/\\([^/]*\\)/\\([0-9]*\\).*$" url)
675 (if (eq (length (setq fld-name
676 (elmo-match-string 3 url))) 0)
678 (if (eq (length (setq port
679 (elmo-match-string 2 url))) 0)
680 (setq port (int-to-string elmo-default-nntp-port)))
681 (if (eq (length (setq server
682 (elmo-match-string 1 url))) 0)
683 (setq server elmo-default-nntp-server))
684 (setq folder (concat "-" fld-name "@" server ":" port))
685 (if (eq (length (setq msg
686 (elmo-match-string 4 url))) 0)
687 (wl-summary-goto-folder-subr
688 folder nil nil nil t)
689 (wl-summary-goto-folder-subr
690 folder 'update nil nil t)
691 (goto-char (point-min))
692 (re-search-forward (concat "^ *" msg) nil t)
693 (wl-summary-redisplay)))
694 (message "Not a nntp: url."))))
696 (defmacro wl-concat-list (list separator)
697 (` (mapconcat 'identity (delete "" (delq nil (, list))) (, separator))))
699 (defmacro wl-current-message-buffer ()
701 (if (buffer-live-p wl-current-summary-buffer)
702 (set-buffer wl-current-summary-buffer))
703 wl-message-buf-name)))
705 (defmacro wl-kill-buffers (regexp)
708 (if (and (buffer-name x)
709 (string-match (, regexp) (buffer-name x)))
714 (defun wl-sendlog-time ()
715 (static-if (fboundp 'format-time-string)
716 (format-time-string "%Y/%m/%d %T")
717 (let ((date (current-time-string)))
718 (format "%s/%02d/%02d %s"
720 (cdr (assoc (upcase (substring date 4 7))
721 timezone-months-assoc))
722 (string-to-int (substring date 8 10))
723 (substring date 11 19)))))
725 (defun wl-collect-summary ()
728 (function (lambda (x)
729 (if (and (string-match "^Summary"
733 (equal major-mode 'wl-summary-mode)))
734 (setq result (nconc result (list x))))))
738 (static-if (fboundp 'read-directory-name)
739 (defalias 'wl-read-directory-name 'read-directory-name)
740 (defun wl-read-directory-name (prompt dir)
741 (let ((dir (read-file-name prompt dir)))
742 (unless (file-directory-p dir)
743 (error "%s is not directory" dir))
746 ;; local variable check.
747 (static-if (fboundp 'local-variable-p)
748 (defalias 'wl-local-variable-p 'local-variable-p)
749 (defmacro wl-local-variable-p (symbol &optional buffer)
750 (` (if (assq (, symbol) (buffer-local-variables (, buffer)))
753 (defun wl-number-base36 (num len)
758 (concat (wl-number-base36 (/ num 36) (1- len))
759 (char-to-string (aref "zyxwvutsrqponmlkjihgfedcba9876543210"
762 (defvar wl-unique-id-char nil)
764 (defun wl-unique-id ()
765 ;; Don't use microseconds from (current-time), they may be unsupported.
766 ;; Instead we use this randomly inited counter.
767 (setq wl-unique-id-char
768 (% (1+ (or wl-unique-id-char (logand (random t) (1- (lsh 1 20)))))
769 ;; (current-time) returns 16-bit ints,
770 ;; and 2^16*25 just fits into 4 digits i base 36.
772 (let ((tm (static-if (fboundp 'current-time)
774 (let* ((cts (split-string (current-time-string) "[ :]"))
775 (m (cdr (assoc (nth 1 cts)
776 '(("Jan" . "01") ("Feb" . "02")
777 ("Mar" . "03") ("Apr" . "04")
778 ("May" . "05") ("Jun" . "06")
779 ("Jul" . "07") ("Aug" . "08")
780 ("Sep" . "09") ("Oct" . "10")
781 ("Nov" . "11") ("Dec" . "12"))))))
782 (list (string-to-int (concat (nth 6 cts) m
783 (substring (nth 2 cts) 0 1)))
784 (string-to-int (concat (substring (nth 2 cts) 1)
785 (nth 4 cts) (nth 5 cts)
788 (if (memq system-type '(ms-dos emx vax-vms))
789 (let ((user (downcase (user-login-name))))
790 (while (string-match "[^a-z0-9_]" user)
791 (aset user (match-beginning 0) ?_))
793 (wl-number-base36 (user-uid) -1))
794 (wl-number-base36 (+ (car tm)
795 (lsh (% wl-unique-id-char 25) 16)) 4)
796 (wl-number-base36 (+ (nth 1 tm)
797 (lsh (/ wl-unique-id-char 25) 16)) 4)
798 ;; Append the name of the message interface, because while the
799 ;; generated ID is unique to this newsreader, other newsreaders
800 ;; might otherwise generate the same ID via another algorithm.
803 (defun wl-draft-make-message-id-string ()
804 (concat "<" (wl-unique-id) "@"
805 (or wl-message-id-domain
807 (concat (system-name) "." wl-local-domain)
812 (defvar wl-load-profile-func 'wl-local-load-profile)
813 (defun wl-local-load-profile ()
814 (message "Initializing ...")
815 (load wl-init-file 'noerror 'nomessage))
817 (defun wl-load-profile ()
818 (funcall wl-load-profile-func))
820 ;;; wl-util.el ends here