Use modb-standard-entity-filename instead of hardcoded name
[more-wl.git] / utils / wl-addrbook.el
blob5a8c3a9eea84eeb690167ff88c15f3069f7dd736
1 ;; wl-addrbook.el --- Aliases and personal information
3 ;; Author: Masahiro MURATA <muse@ba2.so-net.ne.jp>
4 ;; Kazu Yamamoto <Kazu@Mew.org>
5 ;; Keywords: mail, net news
7 ;;; Commentary:
9 ;; Insert the following lines in your ~/.wl
11 ;; (require 'wl-addrbook)
12 ;; (wl-addrbook-setup)
14 ;; Original code: Kazu Yamamoto <Kazu@Mew.org>
15 ;; mew-addrbook.el (Mew developing team)
17 ;;; Code:
19 (require 'wl-util)
21 (defvar wl-addrbook-file "~/.im/Addrbook"
22 "*Addrbook file for completion")
23 (defvar wl-addrbook-expand-max-depth 5
24 "*A value to limit alias(addrbook) expansion loop.")
25 (defvar wl-addrbook-comment-regexp "^;.*$\\|#.*$"
26 "*Regular expression for \".im/Addrbook\".")
27 (defvar wl-addrbook-override-by-newone t
28 "If non-nil, the 'user' entry in 'wl-alias-auto-alist'
29 is override by a new entry of (user different-address).
30 This means that addresses in To: and Cc: in Draft mode are
31 always learned with an exception 'user' is defined in Addrbook.
32 If nil, the old 'user' entry remains.")
34 ;;(defvar wl-anonymous-recipients ":;")
36 (defvar wl-addrbook-hashtb nil)
38 (defvar wl-addrbook-strip-domainpart t
39 "*If *non-nil*, a shortname is created by stripping its domain part.")
41 (defvar wl-addrbook-alist nil
42 "(key addr) or (key (addr1, addr2) nickname name)")
43 (defvar wl-alias-auto-alist nil
44 "(key addr)")
45 (defvar wl-alias-auto-file-name "auto-alias")
47 (defvar wl-summary-use-addrbook-from-func t)
49 ;;; utils
51 (defun wl-uniq-alist (alst)
52 "Distractively uniqfy elements of ALST."
53 (let ((tmp alst))
54 (while tmp (setq tmp (setcdr tmp (wl-delete-alist2 (car (car tmp)) (cdr tmp))))))
55 alst)
57 (defun wl-delete-alist2 (key alist)
58 "Destructively delete elements whose first member is equal to key"
59 (if (null key)
60 alist
61 (let (ret)
62 (while (equal (car (nth 0 alist)) key)
63 (setq alist (cdr alist)))
64 (setq ret alist)
65 (while alist
66 (if (equal (car (nth 1 alist)) key)
67 (setcdr alist (cdr (cdr alist)))
68 (setq alist (cdr alist))))
69 ret)))
71 (defun wl-get-next (LIST MEM)
72 (let (frst next crnt)
73 (setq frst (car LIST))
74 (setq LIST (cdr LIST))
75 (setq next (car LIST))
76 (if (equal frst MEM)
77 (if next next frst)
78 (catch 'loop
79 (while LIST
80 (setq crnt next)
81 (setq LIST (cdr LIST))
82 (setq next (car LIST))
83 (if (equal crnt MEM)
84 (throw 'loop (if next next frst))))))))
86 (defun wl-address-extract-user (addr)
87 "Extracts username from ADDR"
88 (if (string-match "@.*:" addr) ;; xxx what's this?
89 (setq addr (substring addr (match-end 0) nil))
90 (setq addr (elmo-replace-in-string addr " " "_"))
91 (setq addr (substring addr 0 (string-match "%" addr)))
92 (setq addr (substring addr 0 (string-match "@" addr)))
93 ;; just for refile: "To: recipients:;" -> recipients
94 ;;(setq addr (substring addr 0 (string-match wl-anonymous-recipients addr)))
95 ;; removing Notes domain
96 (setq addr (substring addr 0 (string-match "/" addr)))))
98 (defun wl-address-parse-address-list (addrs)
99 (mapcar 'wl-address-header-extract-address (wl-parse-addresses addrs)))
101 ;; hash table for wl-addrbook-alist
102 (defmacro wl-addrbook-hashtb ()
103 '(or wl-addrbook-hashtb
104 (setq wl-addrbook-hashtb (elmo-make-hash 1021))))
106 (defsubst wl-addrbook-get-record-by-addr (addr &optional alist)
107 (elmo-get-hash-val (downcase addr) (wl-addrbook-hashtb)))
109 (defsubst wl-addrbook-get-record-by-alias (alias &optional alist)
110 (elmo-get-hash-val (format "#%s" (downcase alias)) (wl-addrbook-hashtb)))
112 (defun wl-addrbook-make-hashtb ()
113 (let ((ht (wl-addrbook-hashtb))
114 (alist wl-addrbook-alist)
115 list addrs addr)
116 (while alist
117 (setq list (car alist)
118 alist (cdr alist))
119 ;; key is alias
120 (if (car list)
121 (elmo-set-hash-val (format "#%s" (downcase (car list))) list ht))
122 (when (listp (setq addrs (nth 1 list)))
123 (while addrs
124 (setq addr (car addrs)
125 addrs (cdr addrs))
126 ;; key is address
127 (elmo-set-hash-val (downcase addr) list ht))))))
129 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
131 ;;; Address book
134 (defun wl-addrbook-setup ()
135 (require 'wl-complete)
136 ;; replace wl-address-init function.
137 (setq wl-address-init-function 'wl-addrbook-init)
139 (when wl-summary-use-addrbook-from-func
140 (setq wl-summary-get-petname-function 'wl-addrbook-get-nickname))
141 (define-key wl-summary-mode-map "\C-c\C-a" 'wl-summary-addrbook-add)
142 (define-key wl-draft-mode-map "\C-i" 'wl-draft-addrbook-header-comp-or-tab)
143 (define-key wl-draft-mode-map "\e\t" 'wl-draft-addrbook-expand)
144 (define-key wl-draft-mode-map "\C-c\t" 'wl-draft-circular-comp)
145 (add-hook 'mail-send-hook 'wl-draft-learn-alias))
147 (defun wl-addrbook-init ()
148 (message "Updating addrbook...")
149 (or wl-alias-auto-alist
150 (if wl-alias-auto-file-name
151 (setq wl-alias-auto-alist
152 (elmo-object-load (expand-file-name
153 wl-alias-auto-file-name
154 elmo-msgdb-directory)))))
155 (setq wl-addrbook-alist (wl-addrbook-make-alist))
156 ;; wl-alias-auto-alist is used independently so must use copy-alist
157 (if wl-addrbook-alist
158 (nconc wl-addrbook-alist (copy-alist wl-alias-auto-alist))
159 (setq wl-addrbook-alist (copy-alist wl-alias-auto-alist)))
160 ;; (if wl-addrbook-alist
161 ;; (nconc wl-addrbook-alist (wl-petname-make-alist))
162 ;; (setq wl-addrbook-version (wl-petname-make-alist)))
163 (setq wl-addrbook-alist (wl-uniq-alist wl-addrbook-alist))
164 (wl-addrbook-make-hashtb)
165 (add-hook 'kill-emacs-hook (function wl-addrbook-clean-up))
166 (add-hook 'wl-exit-hook (function wl-addrbook-clean-up))
167 (message "Updating addrbook...done"))
169 (defun wl-addrbook-clean-up ()
170 (remove-hook 'kill-emacs-hook (function wl-addrbook-clean-up))
171 (remove-hook 'wl-exit-hook (function wl-addrbook-clean-up))
172 (when wl-alias-auto-file-name
173 (elmo-object-save (expand-file-name
174 wl-alias-auto-file-name
175 elmo-msgdb-directory)
176 wl-alias-auto-alist)
177 (setq wl-alias-auto-alist nil)
178 (setq wl-addrbook-hashtb nil)))
182 (defmacro wl-alias-get (key)
183 `(wl-addrbook-alias-get ,key wl-addrbook-alist))
185 (defmacro wl-alias-next (key)
186 `(wl-addrbook-alias-next ,key wl-addrbook-alist))
188 (defalias 'wl-addrbook-alias-hit 'wl-addrbook-get-record-by-alias)
190 (defun wl-addrbook-alias-get (key alist)
191 (let ((addrs (wl-addrbook-alias-get1 key alist 0)))
192 (cond
193 ((stringp addrs) addrs)
194 ((listp addrs)
195 (mapconcat (lambda (x) x) (nreverse addrs) ", "))
196 (t key))))
198 (defun wl-addrbook-alias-get1 (key alist n)
199 "Expand KEY to addresses according ALIST.
200 If addresses is a list, that follows one-of convention and
201 return the first member of the list.
202 If addresses is a string, expands it recursively."
203 (let* ((crnt (nth 1 (wl-addrbook-alias-hit key alist)))
204 (keys (and (stringp crnt)
205 (elmo-parse crnt "\\([^, \t]+\\)")))
206 ret tmp)
207 (cond
208 ((> n wl-addrbook-expand-max-depth) key)
209 ((null crnt) key)
210 ((listp crnt) (car crnt))
212 (while keys
213 (setq tmp (wl-addrbook-alias-get1 (car keys) alist (1+ n)))
214 (if (listp tmp)
215 (setq ret (nconc tmp ret))
216 (setq ret (cons tmp ret)))
217 (setq keys (cdr keys)))
218 ret))))
220 (defun wl-addrbook-alias-next (key alist)
221 (let* ((addrs (nth 1 (wl-addrbook-get-record-by-addr key alist))))
222 (if (and addrs (listp addrs))
223 (wl-get-next addrs key))))
225 (defun wl-addrbook-alias-add (addr)
226 (if (and (stringp addr) (string-match "@" addr))
227 (let* ((user (wl-address-extract-user addr))
228 (match-auto (assoc user wl-alias-auto-alist))
229 (match-adbk (assoc user wl-addrbook-alist)))
230 (cond
231 (match-auto
232 (cond
233 ((equal addr (nth 1 match-auto))
234 ;; move the entry to the top for the recent-used-first.
235 (setq wl-alias-auto-alist
236 (cons match-auto (delete match-auto wl-alias-auto-alist))))
237 (wl-addrbook-override-by-newone
238 ;; override match-auto by (user addr)
239 (setq wl-addrbook-alist
240 (cons (list user addr)
241 (delete match-auto wl-addrbook-alist)))
242 (setq wl-alias-auto-alist
243 (cons (list user addr)
244 (delete match-auto wl-alias-auto-alist))))
246 ;; the old entry remains
248 (match-adbk
249 ;; do nothing
252 (setq wl-addrbook-alist (cons (list user addr) wl-addrbook-alist))
253 (setq wl-alias-auto-alist
254 (cons (list user addr) wl-alias-auto-alist)))))))
256 (defun wl-addrbook-alias-delete (addr)
257 (if (and (stringp addr) (string-match "@" addr))
258 (let* ((user (wl-address-extract-user addr))
259 (ent (assoc user wl-addrbook-alist)))
260 (if (and ent (equal (cdr ent) addr))
261 (progn
262 (setq wl-addrbook-alist (delete ent wl-addrbook-alist))
263 (setq wl-alias-auto-alist (delete ent wl-alias-auto-alist)))))))
267 (defun wl-addrbook-shortname-get (addr)
268 (nth 0 (wl-addrbook-get-record-by-addr addr)))
270 (defun wl-addrbook-nickname-get (addr)
271 (nth 2 (wl-addrbook-get-record-by-addr addr)))
273 (defun wl-addrbook-name-get (addr)
274 (nth 3 (wl-addrbook-get-record-by-addr addr)))
277 (defun wl-addrbook-insert-file (file cregexp &optional unquote)
278 (let* ((case-fold-search t)
279 (coding-system-for-read wl-cs-autoconv)
280 (pars (elmo-parse file "\\([^, ]+\\)")) ;; parents
281 (files pars) ;; included
282 par chr path beg qchar)
283 ;; include parents files
284 (while pars
285 (setq par (car pars))
286 (setq pars (cdr pars))
287 (if (not (file-readable-p par))
289 (insert-file-contents par)
290 (setq path (file-name-directory par))
291 ;; include children files
292 (while (re-search-forward "^\<[ \t]*\\([^ \t\n]+\\).*$" nil t)
293 (setq chr (expand-file-name (wl-match-buffer 1) path))
294 (delete-region (match-beginning 0) (match-end 0))
295 (if (and (file-readable-p chr) (not (member chr files)))
296 (progn
297 (insert-file-contents chr)
298 (setq files (cons chr files)))))
299 (goto-char (point-max))))
300 ;; remove commets
301 (goto-char (point-min))
302 (while (re-search-forward cregexp nil t)
303 (delete-region (match-beginning 0) (match-end 0)))
304 ;; concat continuation lines
305 (goto-char (point-min))
306 (while (re-search-forward "\\\\\n" nil t)
307 (delete-region (match-beginning 0) (match-end 0)))
308 ;; concat separated lines by comma
309 (goto-char (point-min))
310 (while (re-search-forward ",[ \t]*$" nil t)
311 (end-of-line)
312 (forward-char 1)
313 (delete-backward-char 1)
314 (delete-horizontal-space))
315 ;; unquote, replace white spaces to "\0".
316 (if unquote
317 (catch 'quote
318 (goto-char (point-min))
319 (while (re-search-forward "[\"']" nil t)
320 (setq qchar (char-before (point)))
321 ;; (point) is for backward compatibility
322 (backward-delete-char 1) ;; delete quote
323 (setq beg (point))
324 (if (not (re-search-forward (char-to-string qchar) nil t))
325 (throw 'quote nil) ;; error
326 (backward-delete-char 1) ;; delete quote
327 (save-restriction
328 (narrow-to-region beg (point))
329 (goto-char (point-min))
330 (while (re-search-forward "[ \t]+" nil t)
331 (replace-match "\0"))
332 (goto-char (point-max))))))) ;; just in case
333 ;; remove optional white spaces
334 (goto-char (point-min))
335 (while (re-search-forward "[ \t]+" nil t)
336 (replace-match " "))))
338 (defun wl-addrbook-strsafe (var)
339 (if (or (string-equal "" var) (string-equal "*" var))
341 (save-match-data
342 (elmo-replace-in-string var (char-to-string 0) " "))))
344 (defun wl-addrbook-make-alist ()
345 (let (alias colon addrs nick name alist)
346 (wl-set-work-buf
347 (wl-addrbook-insert-file
348 wl-addrbook-file wl-addrbook-comment-regexp 'unquote)
349 (goto-char (point-min))
350 (while (re-search-forward "^ ?\\([^ \n:]+\\) ?\\(:?\\) ?\\([^ \n]+\\)" nil t)
351 (setq alias (wl-addrbook-strsafe (wl-match-buffer 1)))
352 (setq colon (wl-match-buffer 2))
353 (setq addrs (wl-addrbook-strsafe (wl-match-buffer 3)))
354 (if (equal colon ":")
355 (setq alist (cons (list alias addrs) alist))
356 (and addrs (setq addrs (elmo-parse addrs "\\([^, \t\r\n]+\\)")))
357 (if (looking-at " ?\\([^ \n]*\\) ?\\([^ \n]*\\)")
358 (progn
359 (setq nick (wl-addrbook-strsafe (wl-match-buffer 1)))
360 (setq name (wl-addrbook-strsafe (wl-match-buffer 2))))
361 (setq nick nil)
362 (setq name nil))
363 (setq alist (cons (list alias addrs nick name) alist))))
364 (nreverse alist))))
366 (defun wl-draft-learn-alias ()
367 (interactive)
368 (let ((recipients (mapconcat 'identity
369 (delq nil (std11-field-bodies '("To" "Cc")))
370 ",")))
371 (mapcar '(lambda (addr)
372 (wl-addrbook-alias-add
373 (wl-address-header-extract-address addr)))
374 (wl-parse-addresses recipients))))
376 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
378 ;;; Addrbook mode
381 (defvar wl-addrbook-mode-map nil)
383 (if wl-addrbook-mode-map
385 ;;(setq wl-addrbook-mode-map (make-sparse-keymap))
386 ;;(set-keymap-parent wl-addrbook-mode-map text-mode-map)
387 (setq wl-addrbook-mode-map (copy-keymap text-mode-map))
388 (define-key wl-addrbook-mode-map "\C-c\C-c" 'wl-addrbook-register)
389 (define-key wl-addrbook-mode-map "\C-c\C-q" 'wl-addrbook-kill))
391 (defvar wl-addrbook-mode-alias "Alias")
392 (defvar wl-addrbook-mode-personalinfo "Personal Info")
393 (defconst wl-addrbook-buffer-name "*WL Addrbook*")
395 (defun wl-summary-addrbook-add (&optional personalinfo)
396 "Adding the value of From: or To: in Message mode to Addrbook. When
397 executed with '\\[universal-argument]', it will add personal information. Otherwise,
398 it will add an alias."
399 (interactive "P")
400 (wl-summary-redisplay)
401 (let ((buf wl-message-buffer)
402 from shortname address addrs name)
403 (save-excursion
404 (set-buffer buf)
405 (setq address (std11-field-body "From"))
406 (if (wl-address-user-mail-address-p address)
407 (setq address (std11-field-body "To")))
408 (if (null address)
409 (message "No address to be registered")
410 (setq addrs (wl-address-header-extract-address address))
411 (if wl-addrbook-strip-domainpart
412 (setq shortname (wl-address-extract-user addrs))
413 (setq shortname addrs))
414 (if (string-match "\\(.*\\)<.*>" address)
415 (progn
416 (setq name (wl-match-string 1 address))
417 (setq name (elmo-replace-in-string name "[ \t]$" ""))))
418 (wl-addrbook-prepare-template personalinfo shortname addrs nil name)))))
420 (defun wl-addrbook-prepare-template (personalinfop shortname addrs &optional nickname name)
421 (delete-other-windows)
422 (switch-to-buffer (get-buffer-create wl-addrbook-buffer-name))
423 (erase-buffer)
424 (insert "#If you want to register this entry, type "
425 (substitute-command-keys
426 "'\\<wl-addrbook-mode-map>\\[wl-addrbook-register]'.\n")
427 "#If you want to NOT register this entry, type "
428 (substitute-command-keys
429 "'\\<wl-addrbook-mode-map>\\[wl-addrbook-kill]'.\n"))
430 (wl-addrbook-insert-template "Shortname" shortname)
431 (wl-addrbook-insert-template "Addresses" addrs)
432 (cond
433 (personalinfop
434 (wl-addrbook-insert-template "Nickname" nickname)
435 (wl-addrbook-insert-template "Name" name)
436 (wl-addrbook-mode wl-addrbook-mode-personalinfo))
438 (wl-addrbook-mode wl-addrbook-mode-alias)))
439 (wl-addrbook-insert-template "Comments" nil)
440 (goto-char (point-min))
441 (search-forward ": " nil t))
443 (defun wl-addrbook-insert-template (key val)
444 (let ((buffer-read-only nil)
445 (inhibit-read-only t)
446 (beg (point)))
447 (insert key ": ")
448 (put-text-property beg (point) 'read-only t)
449 (put-text-property (1- (point)) (point)
450 (if wl-on-xemacs 'end-open 'rear-nonsticky)
452 (and val (insert val))
453 (insert "\n")))
455 (defun wl-addrbook-mode (mname)
456 "\\<wl-addrbook-mode-map>
457 Mew Addrbook mode:: major mode to resistor Addrbook.
458 The keys that are defined for this mode are:
460 \\[wl-addrbook-register] Register information in Addrbook mode to Addrbook.
461 \\[wl-addrbook-kill] Kill Addrbook mode.
463 (interactive)
464 (setq major-mode 'wl-addrbook-mode)
465 (setq mode-name mname)
466 (setq mode-line-buffer-identification
467 (format "Wanderlust: %s" mname))
468 (use-local-map wl-addrbook-mode-map)
469 (run-hooks 'wl-addrbook-mode-hook)
470 (setq buffer-undo-list nil))
472 (defun wl-addrbook-register ()
473 "Register information in Addrbook mode to Addrbook."
474 (interactive)
475 (let ((shortname (std11-field-body "Shortname"))
476 (addrs (std11-field-body "Addresses"))
477 (nickname (std11-field-body "Nickname"))
478 (name (std11-field-body "Name"))
479 (comments (std11-field-body "Comments"))
480 (mode mode-name)
481 buf addrsl errmsg not-uniq)
482 (cond
483 ((equal mode wl-addrbook-mode-alias)
484 (cond
485 ((and (null shortname) (null addrs))
486 (setq errmsg "Must fill both Shortname and Addresses."))
487 ((null shortname)
488 (setq errmsg "Must fill Shortname."))
489 ((null addrs)
490 (setq errmsg "Must fill Addresses."))))
492 (cond
493 ((null addrs)
494 (setq errmsg "Must fill Addresses."))
495 ((and (null shortname) (null nickname) (null name))
496 (setq errmsg "Must fill Shortname or Nickname or Name."))
497 ((and name (string-match "^\"[^\"]*[^\000-\177]" name))
498 (setq errmsg "Remove quote around non-ASCII Name.")))))
499 (if errmsg
500 (message errmsg)
501 (save-excursion
502 (setq buf (find-file-noselect wl-addrbook-file))
503 (set-buffer buf)
504 (goto-char (point-min))
505 (if (and shortname
506 (re-search-forward
507 (concat "^" (regexp-quote shortname) "[ \t]*:?[ \t]+") nil t))
508 (setq not-uniq t))
509 (if not-uniq
510 () ;; see later
511 ;; All errors are checked.
512 (goto-char (point-max))
513 (if (not (bolp)) (insert "\n"))
514 (cond
515 ((equal mode wl-addrbook-mode-alias)
516 (setq wl-addrbook-alist
517 (cons (list shortname addrs) wl-addrbook-alist))
518 (insert shortname ":\t" addrs))
520 (setq addrsl (wl-address-parse-address-list addrs))
521 (setq wl-addrbook-alist
522 (cons (list shortname addrsl nickname name) wl-addrbook-alist))
523 (if (null shortname) (setq shortname "*"))
524 (if (and nickname (string-match "^[^\" \t]+[ \t]+.*$" nickname))
525 (setq nickname (concat "\"" nickname "\"")))
526 (if (and name (string-match "^[^\" \t]+[ \t]+.*$" name))
527 (setq name (concat "\"" name "\"")))
528 (if name
529 (insert shortname "\t" addrs "\t" (or nickname "*") "\t" name)
530 (if nickname
531 (insert shortname "\t" addrs "\t" nickname)
532 (insert shortname "\t" addrs)))))
533 (if comments
534 (insert "\t#" comments "\n")
535 (insert "\n"))
536 (save-buffer)))
537 (wl-addrbook-make-hashtb)
538 ;; Addrbook buffer
539 (kill-buffer buf)
540 (if not-uniq
541 (message "Shortname is already used. Change Shortname.")
542 (wl-addrbook-kill 'no-msg)
543 (message "Registered to Addrbook.")))))
545 (defun wl-addrbook-kill (&optional no-msg)
546 "Kill Addrbook mode."
547 (interactive "P")
548 (kill-buffer (current-buffer))
549 (or no-msg (message "Not registered.")))
551 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
553 ;;; Show nick name of Addrbook in summary.
556 (defun wl-addrbook-get-nickname (mailbox)
557 "For `wl-summary-get-petname-function'."
558 (wl-addrbook-nickname-get
559 (wl-address-header-extract-address mailbox)))
561 (provide 'wl-addrbook)
563 ;;; Copyright Notice:
565 ;; Copyright (C) 1999-2001 Mew developing team.
566 ;; Copyright (C) 2001 Masahiro Murata <muse@ba2.so-net.ne.jp>
567 ;; All rights reserved.
569 ;; Redistribution and use in source and binary forms, with or without
570 ;; modification, are permitted provided that the following conditions
571 ;; are met:
573 ;; 1. Redistributions of source code must retain the above copyright
574 ;; notice, this list of conditions and the following disclaimer.
575 ;; 2. Redistributions in binary form must reproduce the above copyright
576 ;; notice, this list of conditions and the following disclaimer in the
577 ;; documentation and/or other materials provided with the distribution.
578 ;; 3. Neither the name of the team nor the names of its contributors
579 ;; may be used to endorse or promote products derived from this software
580 ;; without specific prior written permission.
582 ;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND
583 ;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
584 ;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
585 ;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE
586 ;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
587 ;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
588 ;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
589 ;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
590 ;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
591 ;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
592 ;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
594 ;;; wl-addrbook.el ends here