5a8c3a9eea84eeb690167ff88c15f3069f7dd736
[elisp/wanderlust.git] / utils / wl-addrbook.el
1 ;; wl-addrbook.el --- Aliases and personal information
2
3 ;; Author:  Masahiro MURATA <muse@ba2.so-net.ne.jp>
4 ;;      Kazu Yamamoto <Kazu@Mew.org>
5 ;; Keywords: mail, net news
6
7 ;;; Commentary:
8
9 ;;  Insert the following lines in your ~/.wl
10 ;;
11 ;; (require 'wl-addrbook)
12 ;; (wl-addrbook-setup)
13
14 ;; Original code: Kazu Yamamoto <Kazu@Mew.org>
15 ;;      mew-addrbook.el (Mew developing team)
16
17 ;;; Code:
18
19 (require 'wl-util)
20
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.")
33
34 ;;(defvar wl-anonymous-recipients ":;")
35
36 (defvar wl-addrbook-hashtb nil)
37
38 (defvar wl-addrbook-strip-domainpart t
39   "*If *non-nil*, a shortname is created by stripping its domain part.")
40
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")
46
47 (defvar wl-summary-use-addrbook-from-func t)
48
49 ;;; utils
50
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)
56
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)))
70
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))))))))
85
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)))))
97
98 (defun wl-address-parse-address-list (addrs)
99   (mapcar 'wl-address-header-extract-address (wl-parse-addresses addrs)))
100
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))))
105
106 (defsubst wl-addrbook-get-record-by-addr (addr &optional alist)
107   (elmo-get-hash-val (downcase addr) (wl-addrbook-hashtb)))
108
109 (defsubst wl-addrbook-get-record-by-alias (alias &optional alist)
110   (elmo-get-hash-val (format "#%s" (downcase alias)) (wl-addrbook-hashtb)))
111
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))))))
128
129 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
130 ;;;
131 ;;; Address book
132 ;;;
133
134 (defun wl-addrbook-setup ()
135   (require 'wl-complete)
136   ;; replace wl-address-init function.
137   (setq wl-address-init-function 'wl-addrbook-init)
138   ;;
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))
146
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"))
168
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)))
179
180 ;;
181
182 (defmacro wl-alias-get (key)
183   `(wl-addrbook-alias-get ,key wl-addrbook-alist))
184
185 (defmacro wl-alias-next (key)
186   `(wl-addrbook-alias-next ,key wl-addrbook-alist))
187
188 (defalias 'wl-addrbook-alias-hit 'wl-addrbook-get-record-by-alias)
189
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))))
197
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))
211      (t
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))))
219
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))))
224
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))))
245            (t 
246             ;; the old entry remains
247             )))
248          (match-adbk
249           ;; do nothing
250           )
251          (t
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)))))))
255
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)))))))
264
265 ;;
266
267 (defun wl-addrbook-shortname-get (addr)
268   (nth 0 (wl-addrbook-get-record-by-addr addr)))
269
270 (defun wl-addrbook-nickname-get (addr)
271   (nth 2 (wl-addrbook-get-record-by-addr addr)))
272
273 (defun wl-addrbook-name-get (addr)
274   (nth 3 (wl-addrbook-get-record-by-addr addr)))
275 ;;
276
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))
288           ()
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 " "))))
337
338 (defun wl-addrbook-strsafe (var)
339   (if (or (string-equal "" var) (string-equal "*" var))
340       nil
341     (save-match-data
342       (elmo-replace-in-string var (char-to-string 0) " "))))
343
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))))
365
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))))
375
376 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
377 ;;;
378 ;;; Addrbook mode
379 ;;;
380
381 (defvar wl-addrbook-mode-map nil)
382
383 (if wl-addrbook-mode-map
384     ()
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))
390
391 (defvar wl-addrbook-mode-alias "Alias")
392 (defvar wl-addrbook-mode-personalinfo "Personal Info")
393 (defconst wl-addrbook-buffer-name "*WL Addrbook*")
394
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)))))
419
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))
437    (t
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))
442
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)
451                        t)
452     (and val (insert val))
453     (insert "\n")))
454
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:
459
460 \\[wl-addrbook-register]        Register information in Addrbook mode to Addrbook.
461 \\[wl-addrbook-kill]    Kill Addrbook mode.
462 "
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))
471
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."))))
491       (t
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))
519             (t
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.")))))
544
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.")))
550
551 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
552 ;;;
553 ;;; Show nick name of Addrbook in summary.
554 ;;;
555
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)))
560
561 (provide 'wl-addrbook)
562
563 ;;; Copyright Notice:
564
565 ;; Copyright (C) 1999-2001 Mew developing team.
566 ;; Copyright (C) 2001 Masahiro Murata <muse@ba2.so-net.ne.jp>
567 ;; All rights reserved.
568
569 ;; Redistribution and use in source and binary forms, with or without
570 ;; modification, are permitted provided that the following conditions
571 ;; are met:
572 ;; 
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.
581 ;; 
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.
593
594 ;;; wl-addrbook.el ends here