comparison lisp/gnus/gnus-util.el @ 31716:9968f55ad26e

Update to emacs-21-branch of the Gnus CVS repository.
author Gerd Moellmann <gerd@gnu.org>
date Tue, 19 Sep 2000 13:37:09 +0000
parents 15fc6acbae7a
children 51cea22fd2aa
comparison
equal deleted inserted replaced
31715:7c896543d225 31716:9968f55ad26e
1 ;;; gnus-util.el --- utility functions for Gnus 1 ;;; gnus-util.el --- utility functions for Gnus
2 ;; Copyright (C) 1996,97,98 Free Software Foundation, Inc. 2 ;; Copyright (C) 1996, 1997, 1998, 1999, 2000
3 ;; Free Software Foundation, Inc.
3 4
4 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org> 5 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
5 ;; Keywords: news 6 ;; Keywords: news
6 7
7 ;; This file is part of GNU Emacs. 8 ;; This file is part of GNU Emacs.
31 ;;; Code: 32 ;;; Code:
32 33
33 (require 'custom) 34 (require 'custom)
34 (eval-when-compile (require 'cl)) 35 (eval-when-compile (require 'cl))
35 (require 'nnheader) 36 (require 'nnheader)
36 (require 'timezone)
37 (require 'message) 37 (require 'message)
38 (eval-when-compile (require 'rmail)) 38 (require 'time-date)
39 39
40 (eval-and-compile 40 (eval-and-compile
41 (autoload 'nnmail-date-to-time "nnmail")
42 (autoload 'rmail-insert-rmail-file-header "rmail") 41 (autoload 'rmail-insert-rmail-file-header "rmail")
43 (autoload 'rmail-count-new-messages "rmail") 42 (autoload 'rmail-count-new-messages "rmail")
44 (autoload 'rmail-show-message "rmail")) 43 (autoload 'rmail-show-message "rmail"))
45 44
46 (defun gnus-boundp (variable) 45 (defun gnus-boundp (variable)
74 `(let ((symbol (intern ,string ,hashtable))) 73 `(let ((symbol (intern ,string ,hashtable)))
75 (or (boundp symbol) 74 (or (boundp symbol)
76 (set symbol nil)) 75 (set symbol nil))
77 symbol)) 76 symbol))
78 77
79 (defun gnus-truncate-string (str width)
80 (substring str 0 width))
81
82 ;; Added by Geoffrey T. Dairiki <dairiki@u.washington.edu>. A safe way 78 ;; Added by Geoffrey T. Dairiki <dairiki@u.washington.edu>. A safe way
83 ;; to limit the length of a string. This function is necessary since 79 ;; to limit the length of a string. This function is necessary since
84 ;; `(substr "abc" 0 30)' pukes with "Args out of range". 80 ;; `(substr "abc" 0 30)' pukes with "Args out of range".
85 (defsubst gnus-limit-string (str width) 81 (defsubst gnus-limit-string (str width)
86 (if (> (length str) width) 82 (if (> (length str) width)
105 (defmacro gnus-kill-buffer (buffer) 101 (defmacro gnus-kill-buffer (buffer)
106 `(let ((buf ,buffer)) 102 `(let ((buf ,buffer))
107 (when (gnus-buffer-exists-p buf) 103 (when (gnus-buffer-exists-p buf)
108 (kill-buffer buf)))) 104 (kill-buffer buf))))
109 105
110 (if (fboundp 'point-at-bol) 106 (defalias 'gnus-point-at-bol
111 (fset 'gnus-point-at-bol 'point-at-bol) 107 (if (fboundp 'point-at-bol)
112 (defun gnus-point-at-bol () 108 'point-at-bol
113 "Return point at the beginning of the line." 109 'line-beginning-position))
114 (let ((p (point))) 110
115 (beginning-of-line) 111 (defalias 'gnus-point-at-eol
116 (prog1 112 (if (fboundp 'point-at-eol)
117 (point) 113 'point-at-eol
118 (goto-char p))))) 114 'line-end-position))
119
120 (if (fboundp 'point-at-eol)
121 (fset 'gnus-point-at-eol 'point-at-eol)
122 (defun gnus-point-at-eol ()
123 "Return point at the end of the line."
124 (let ((p (point)))
125 (end-of-line)
126 (prog1
127 (point)
128 (goto-char p)))))
129 115
130 (defun gnus-delete-first (elt list) 116 (defun gnus-delete-first (elt list)
131 "Delete by side effect the first occurrence of ELT as a member of LIST." 117 "Delete by side effect the first occurrence of ELT as a member of LIST."
132 (if (equal (car list) elt) 118 (if (equal (car list) elt)
133 (cdr list) 119 (cdr list)
177 (setq name address)) 163 (setq name address))
178 ;; XOVER might not support folded From headers. 164 ;; XOVER might not support folded From headers.
179 (and (string-match "(.*" from) 165 (and (string-match "(.*" from)
180 (setq name (substring from (1+ (match-beginning 0)) 166 (setq name (substring from (1+ (match-beginning 0))
181 (match-end 0))))) 167 (match-end 0)))))
182 ;; Fix by Hallvard B Furuseth <h.b.furuseth@usit.uio.no>. 168 (list (if (string= name "") nil name) (or address from))))
183 (list (or name from) (or address from)))) 169
184 170
185 (defun gnus-fetch-field (field) 171 (defun gnus-fetch-field (field)
186 "Return the value of the header FIELD of current article." 172 "Return the value of the header FIELD of current article."
187 (save-excursion 173 (save-excursion
188 (save-restriction 174 (save-restriction
229 (defun gnus-string> (s1 s2) 215 (defun gnus-string> (s1 s2)
230 (not (or (string< s1 s2) 216 (not (or (string< s1 s2)
231 (string= s1 s2)))) 217 (string= s1 s2))))
232 218
233 ;;; Time functions. 219 ;;; Time functions.
234
235 (defun gnus-days-between (date1 date2)
236 ;; Return the number of days between date1 and date2.
237 (- (gnus-day-number date1) (gnus-day-number date2)))
238
239 (defun gnus-day-number (date)
240 (let ((dat (mapcar (lambda (s) (and s (string-to-int s)) )
241 (timezone-parse-date date))))
242 (timezone-absolute-from-gregorian
243 (nth 1 dat) (nth 2 dat) (car dat))))
244
245 (defun gnus-time-to-day (time)
246 "Convert TIME to day number."
247 (let ((tim (decode-time time)))
248 (timezone-absolute-from-gregorian
249 (nth 4 tim) (nth 3 tim) (nth 5 tim))))
250
251 (defun gnus-encode-date (date)
252 "Convert DATE to internal time."
253 (let* ((parse (timezone-parse-date date))
254 (date (mapcar (lambda (d) (and d (string-to-int d))) parse))
255 (time (mapcar 'string-to-int (timezone-parse-time (aref parse 3)))))
256 (encode-time (caddr time) (cadr time) (car time)
257 (caddr date) (cadr date) (car date)
258 (* 60 (timezone-zone-to-minute (nth 4 date))))))
259
260 (defun gnus-time-minus (t1 t2)
261 "Subtract two internal times."
262 (let ((borrow (< (cadr t1) (cadr t2))))
263 (list (- (car t1) (car t2) (if borrow 1 0))
264 (- (+ (if borrow 65536 0) (cadr t1)) (cadr t2)))))
265
266 (defun gnus-time-less (t1 t2)
267 "Say whether time T1 is less than time T2."
268 (or (< (car t1) (car t2))
269 (and (= (car t1) (car t2))
270 (< (nth 1 t1) (nth 1 t2)))))
271 220
272 (defun gnus-file-newer-than (file date) 221 (defun gnus-file-newer-than (file date)
273 (let ((fdate (nth 5 (file-attributes file)))) 222 (let ((fdate (nth 5 (file-attributes file))))
274 (or (> (car fdate) (car date)) 223 (or (> (car fdate) (car date))
275 (and (= (car fdate) (car date)) 224 (and (= (car fdate) (car date))
341 (yes-or-no-p prompt) 290 (yes-or-no-p prompt)
342 (message ""))) 291 (message "")))
343 292
344 (defun gnus-dd-mmm (messy-date) 293 (defun gnus-dd-mmm (messy-date)
345 "Return a string like DD-MMM from a big messy string." 294 "Return a string like DD-MMM from a big messy string."
346 (let ((datevec (ignore-errors (timezone-parse-date messy-date)))) 295 (condition-case ()
347 (if (or (not datevec) 296 (format-time-string "%d-%b" (safe-date-to-time messy-date))
348 (string-equal "0" (aref datevec 1))) 297 (error " - ")))
349 "??-???"
350 (format "%2s-%s"
351 (condition-case ()
352 ;; Make sure leading zeroes are stripped.
353 (number-to-string (string-to-number (aref datevec 2)))
354 (error "??"))
355 (capitalize
356 (or (car
357 (nth (1- (string-to-number (aref datevec 1)))
358 timezone-months-assoc))
359 "???"))))))
360 298
361 (defmacro gnus-date-get-time (date) 299 (defmacro gnus-date-get-time (date)
362 "Convert DATE string to Emacs time. 300 "Convert DATE string to Emacs time.
363 Cache the result as a text property stored in DATE." 301 Cache the result as a text property stored in DATE."
364 ;; Either return the cached value... 302 ;; Either return the cached value...
365 `(let ((d ,date)) 303 `(let ((d ,date))
366 (if (equal "" d) 304 (if (equal "" d)
367 '(0 0) 305 '(0 0)
368 (or (get-text-property 0 'gnus-time d) 306 (or (get-text-property 0 'gnus-time d)
369 ;; or compute the value... 307 ;; or compute the value...
370 (let ((time (nnmail-date-to-time d))) 308 (let ((time (safe-date-to-time d)))
371 ;; and store it back in the string. 309 ;; and store it back in the string.
372 (put-text-property 0 1 'gnus-time time d) 310 (put-text-property 0 1 'gnus-time time d)
373 time))))) 311 time)))))
374 312
375 (defsubst gnus-time-iso8601 (time) 313 (defsubst gnus-time-iso8601 (time)
449 (while (string-match "<[^>]+>" references beg) 387 (while (string-match "<[^>]+>" references beg)
450 (push (substring references (match-beginning 0) (setq beg (match-end 0))) 388 (push (substring references (match-beginning 0) (setq beg (match-end 0)))
451 ids)) 389 ids))
452 (nreverse ids))) 390 (nreverse ids)))
453 391
454 (defun gnus-parent-id (references &optional n) 392 (defsubst gnus-parent-id (references &optional n)
455 "Return the last Message-ID in REFERENCES. 393 "Return the last Message-ID in REFERENCES.
456 If N, return the Nth ancestor instead." 394 If N, return the Nth ancestor instead."
457 (when references 395 (when references
458 (let ((ids (inline (gnus-split-references references)))) 396 (let ((ids (inline (gnus-split-references references))))
459 (car (last ids (or n 1)))))) 397 (while (nthcdr (or n 1) ids)
398 (setq ids (cdr ids)))
399 (car ids))))
460 400
461 (defsubst gnus-buffer-live-p (buffer) 401 (defsubst gnus-buffer-live-p (buffer)
462 "Say whether BUFFER is alive or not." 402 "Say whether BUFFER is alive or not."
463 (and buffer 403 (and buffer
464 (get-buffer buffer) 404 (get-buffer buffer)
494 (let ((event (read-event))) 434 (let ((event (read-event)))
495 ;; should be gnus-characterp, but this can't be called in XEmacs anyway 435 ;; should be gnus-characterp, but this can't be called in XEmacs anyway
496 (cons (and (numberp event) event) event))) 436 (cons (and (numberp event) event) event)))
497 437
498 (defun gnus-sortable-date (date) 438 (defun gnus-sortable-date (date)
499 "Make sortable string by string-lessp from DATE. 439 "Make string suitable for sorting from DATE."
500 Timezone package is used." 440 (gnus-time-iso8601 (date-to-time date)))
501 (condition-case ()
502 (progn
503 (setq date (inline (timezone-fix-time
504 date nil
505 (aref (inline (timezone-parse-date date)) 4))))
506 (inline
507 (timezone-make-sortable-date
508 (aref date 0) (aref date 1) (aref date 2)
509 (inline
510 (timezone-make-time-string
511 (aref date 3) (aref date 4) (aref date 5))))))
512 (error "")))
513 441
514 (defun gnus-copy-file (file &optional to) 442 (defun gnus-copy-file (file &optional to)
515 "Copy FILE to TO." 443 "Copy FILE to TO."
516 (interactive 444 (interactive
517 (list (read-file-name "Copy file: " default-directory) 445 (list (read-file-name "Copy file: " default-directory)
539 (progn 467 (progn
540 (set-buffer gnus-work-buffer) 468 (set-buffer gnus-work-buffer)
541 (erase-buffer)) 469 (erase-buffer))
542 (set-buffer (gnus-get-buffer-create gnus-work-buffer)) 470 (set-buffer (gnus-get-buffer-create gnus-work-buffer))
543 (kill-all-local-variables) 471 (kill-all-local-variables)
544 (buffer-disable-undo (current-buffer)))) 472 (mm-enable-multibyte)))
545 473
546 (defmacro gnus-group-real-name (group) 474 (defmacro gnus-group-real-name (group)
547 "Find the real name of a foreign newsgroup." 475 "Find the real name of a foreign newsgroup."
548 `(let ((gname ,group)) 476 `(let ((gname ,group))
549 (if (string-match "^[^:]+:" gname) 477 (if (string-match "^[^:]+:" gname)
551 gname))) 479 gname)))
552 480
553 (defun gnus-make-sort-function (funs) 481 (defun gnus-make-sort-function (funs)
554 "Return a composite sort condition based on the functions in FUNC." 482 "Return a composite sort condition based on the functions in FUNC."
555 (cond 483 (cond
556 ((not (listp funs)) funs) 484 ;; Just a simple function.
485 ((gnus-functionp funs) funs)
486 ;; No functions at all.
557 ((null funs) funs) 487 ((null funs) funs)
558 ((cdr funs) 488 ;; A list of functions.
489 ((or (cdr funs)
490 (listp (car funs)))
559 `(lambda (t1 t2) 491 `(lambda (t1 t2)
560 ,(gnus-make-sort-function-1 (reverse funs)))) 492 ,(gnus-make-sort-function-1 (reverse funs))))
493 ;; A list containing just one function.
561 (t 494 (t
562 (car funs)))) 495 (car funs))))
563 496
564 (defun gnus-make-sort-function-1 (funs) 497 (defun gnus-make-sort-function-1 (funs)
565 "Return a composite sort condition based on the functions in FUNC." 498 "Return a composite sort condition based on the functions in FUNC."
566 (if (cdr funs) 499 (let ((function (car funs))
567 `(or (,(car funs) t1 t2) 500 (first 't1)
568 (and (not (,(car funs) t2 t1)) 501 (last 't2))
569 ,(gnus-make-sort-function-1 (cdr funs)))) 502 (when (consp function)
570 `(,(car funs) t1 t2))) 503 (cond
504 ;; Reversed spec.
505 ((eq (car function) 'not)
506 (setq function (cadr function)
507 first 't2
508 last 't1))
509 ((gnus-functionp function)
510 ;; Do nothing.
511 )
512 (t
513 (error "Invalid sort spec: %s" function))))
514 (if (cdr funs)
515 `(or (,function ,first ,last)
516 (and (not (,function ,last ,first))
517 ,(gnus-make-sort-function-1 (cdr funs))))
518 `(,function ,first ,last))))
571 519
572 (defun gnus-turn-off-edit-menu (type) 520 (defun gnus-turn-off-edit-menu (type)
573 "Turn off edit menu in `gnus-TYPE-mode-map'." 521 "Turn off edit menu in `gnus-TYPE-mode-map'."
574 (define-key (symbol-value (intern (format "gnus-%s-mode-map" type))) 522 (define-key (symbol-value (intern (format "gnus-%s-mode-map" type)))
575 [menu-bar edit] 'undefined)) 523 [menu-bar edit] 'undefined))
589 (print-readably t)) 537 (print-readably t))
590 (prin1-to-string form))) 538 (prin1-to-string form)))
591 539
592 (defun gnus-make-directory (directory) 540 (defun gnus-make-directory (directory)
593 "Make DIRECTORY (and all its parents) if it doesn't exist." 541 "Make DIRECTORY (and all its parents) if it doesn't exist."
594 (when (and directory 542 (let ((file-name-coding-system nnmail-pathname-coding-system))
595 (not (file-exists-p directory))) 543 (when (and directory
596 (make-directory directory t)) 544 (not (file-exists-p directory)))
545 (make-directory directory t)))
597 t) 546 t)
598 547
599 (defun gnus-write-buffer (file) 548 (defun gnus-write-buffer (file)
600 "Write the current buffer's contents to FILE." 549 "Write the current buffer's contents to FILE."
601 ;; Make sure the directory exists. 550 ;; Make sure the directory exists.
602 (gnus-make-directory (file-name-directory file)) 551 (gnus-make-directory (file-name-directory file))
603 ;; Write the buffer. 552 (let ((file-name-coding-system nnmail-pathname-coding-system))
604 (write-region (point-min) (point-max) file nil 'quietly)) 553 ;; Write the buffer.
554 (write-region (point-min) (point-max) file nil 'quietly)))
605 555
606 (defun gnus-delete-file (file) 556 (defun gnus-delete-file (file)
607 "Delete FILE if it exists." 557 "Delete FILE if it exists."
608 (when (file-exists-p file) 558 (when (file-exists-p file)
609 (delete-file file))) 559 (delete-file file)))
612 "Return STRING stripped of all whitespace." 562 "Return STRING stripped of all whitespace."
613 (while (string-match "[\r\n\t ]+" string) 563 (while (string-match "[\r\n\t ]+" string)
614 (setq string (replace-match "" t t string))) 564 (setq string (replace-match "" t t string)))
615 string) 565 string)
616 566
617 (defun gnus-put-text-property-excluding-newlines (beg end prop val) 567 (defsubst gnus-put-text-property-excluding-newlines (beg end prop val)
618 "The same as `put-text-property', but don't put this prop on any newlines in the region." 568 "The same as `put-text-property', but don't put this prop on any newlines in the region."
619 (save-match-data 569 (save-match-data
620 (save-excursion 570 (save-excursion
621 (save-restriction 571 (save-restriction
622 (goto-char beg) 572 (goto-char beg)
623 (while (re-search-forward "[ \t]*\n" end 'move) 573 (while (re-search-forward gnus-emphasize-whitespace-regexp end 'move)
624 (gnus-put-text-property beg (match-beginning 0) prop val) 574 (gnus-put-text-property beg (match-beginning 0) prop val)
625 (setq beg (point))) 575 (setq beg (point)))
626 (gnus-put-text-property beg (point) prop val))))) 576 (gnus-put-text-property beg (point) prop val)))))
627 577
628 (defun gnus-put-text-property-excluding-characters-with-faces (beg end 578 (defun gnus-put-text-property-excluding-characters-with-faces (beg end
731 (concat "\"" filename "\" does not exist, create it? "))) 681 (concat "\"" filename "\" does not exist, create it? ")))
732 (let ((file-buffer (create-file-buffer filename))) 682 (let ((file-buffer (create-file-buffer filename)))
733 (save-excursion 683 (save-excursion
734 (set-buffer file-buffer) 684 (set-buffer file-buffer)
735 (rmail-insert-rmail-file-header) 685 (rmail-insert-rmail-file-header)
736 (let ((require-final-newline nil)) 686 (let ((require-final-newline nil)
687 (coding-system-for-write mm-text-coding-system))
737 (gnus-write-buffer filename))) 688 (gnus-write-buffer filename)))
738 (kill-buffer file-buffer)) 689 (kill-buffer file-buffer))
739 (error "Output file does not exist"))) 690 (error "Output file does not exist")))
740 (set-buffer tmpbuf) 691 (set-buffer tmpbuf)
741 (erase-buffer) 692 (erase-buffer)
742 (insert-buffer-substring artbuf) 693 (insert-buffer-substring artbuf)
743 (gnus-convert-article-to-rmail) 694 (gnus-convert-article-to-rmail)
744 ;; Decide whether to append to a file or to an Emacs buffer. 695 ;; Decide whether to append to a file or to an Emacs buffer.
745 (let ((outbuf (get-file-buffer filename))) 696 (let ((outbuf (get-file-buffer filename)))
746 (if (not outbuf) 697 (if (not outbuf)
747 (append-to-file (point-min) (point-max) filename) 698 (mm-append-to-file (point-min) (point-max) filename)
748 ;; File has been visited, in buffer OUTBUF. 699 ;; File has been visited, in buffer OUTBUF.
749 (set-buffer outbuf) 700 (set-buffer outbuf)
750 (let ((buffer-read-only nil) 701 (let ((buffer-read-only nil)
751 (msg (and (boundp 'rmail-current-message) 702 (msg (and (boundp 'rmail-current-message)
752 (symbol-value 'rmail-current-message)))) 703 (symbol-value 'rmail-current-message))))
782 (gnus-y-or-n-p 733 (gnus-y-or-n-p
783 (concat "\"" filename "\" does not exist, create it? "))) 734 (concat "\"" filename "\" does not exist, create it? ")))
784 (let ((file-buffer (create-file-buffer filename))) 735 (let ((file-buffer (create-file-buffer filename)))
785 (save-excursion 736 (save-excursion
786 (set-buffer file-buffer) 737 (set-buffer file-buffer)
787 (let ((require-final-newline nil)) 738 (let ((require-final-newline nil)
739 (coding-system-for-write mm-text-coding-system))
788 (gnus-write-buffer filename))) 740 (gnus-write-buffer filename)))
789 (kill-buffer file-buffer)) 741 (kill-buffer file-buffer))
790 (error "Output file does not exist"))) 742 (error "Output file does not exist")))
791 (set-buffer tmpbuf) 743 (set-buffer tmpbuf)
792 (erase-buffer) 744 (erase-buffer)
810 (goto-char (point-max)) 762 (goto-char (point-max))
811 (unless (bolp) 763 (unless (bolp)
812 (insert "\n")) 764 (insert "\n"))
813 (insert "\n")) 765 (insert "\n"))
814 (goto-char (point-max)) 766 (goto-char (point-max))
815 (append-to-file (point-min) (point-max) filename))) 767 (mm-append-to-file (point-min) (point-max) filename)))
816 ;; File has been visited, in buffer OUTBUF. 768 ;; File has been visited, in buffer OUTBUF.
817 (set-buffer outbuf) 769 (set-buffer outbuf)
818 (let ((buffer-read-only nil)) 770 (let ((buffer-read-only nil))
819 (goto-char (point-max)) 771 (goto-char (point-max))
820 (unless (eobp) 772 (unless (eobp)
851 803
852 ;;; 804 ;;;
853 ;;; .netrc and .authinforc parsing 805 ;;; .netrc and .authinforc parsing
854 ;;; 806 ;;;
855 807
856 (defvar gnus-netrc-syntax-table
857 (let ((table (copy-syntax-table text-mode-syntax-table)))
858 (modify-syntax-entry ?@ "w" table)
859 (modify-syntax-entry ?- "w" table)
860 (modify-syntax-entry ?_ "w" table)
861 (modify-syntax-entry ?! "w" table)
862 (modify-syntax-entry ?. "w" table)
863 (modify-syntax-entry ?, "w" table)
864 (modify-syntax-entry ?: "w" table)
865 (modify-syntax-entry ?\; "w" table)
866 (modify-syntax-entry ?% "w" table)
867 (modify-syntax-entry ?) "w" table)
868 (modify-syntax-entry ?( "w" table)
869 table)
870 "Syntax table when parsing .netrc files.")
871
872 (defun gnus-parse-netrc (file) 808 (defun gnus-parse-netrc (file)
873 "Parse FILE and return an list of all entries in the file." 809 "Parse FILE and return an list of all entries in the file."
874 (if (not (file-exists-p file)) 810 (when (file-exists-p file)
875 () 811 (with-temp-buffer
876 (save-excursion
877 (let ((tokens '("machine" "default" "login" 812 (let ((tokens '("machine" "default" "login"
878 "password" "account" "macdef" "force")) 813 "password" "account" "macdef" "force"
814 "port"))
879 alist elem result pair) 815 alist elem result pair)
880 (nnheader-set-temp-buffer " *netrc*") 816 (insert-file-contents file)
881 (unwind-protect 817 (goto-char (point-min))
882 (progn 818 ;; Go through the file, line by line.
883 (set-syntax-table gnus-netrc-syntax-table) 819 (while (not (eobp))
884 (insert-file-contents file) 820 (narrow-to-region (point) (gnus-point-at-eol))
885 (goto-char (point-min)) 821 ;; For each line, get the tokens and values.
886 ;; Go through the file, line by line. 822 (while (not (eobp))
887 (while (not (eobp)) 823 (skip-chars-forward "\t ")
888 (narrow-to-region (point) (gnus-point-at-eol)) 824 ;; Skip lines that begin with a "#".
889 ;; For each line, get the tokens and values. 825 (if (eq (char-after) ?#)
890 (while (not (eobp)) 826 (goto-char (point-max))
891 (skip-chars-forward "\t ") 827 (unless (eobp)
892 (unless (eobp) 828 (setq elem
893 (setq elem (buffer-substring 829 (if (= (following-char) ?\")
894 (point) (progn (forward-sexp 1) (point)))) 830 (read (current-buffer))
895 (cond 831 (buffer-substring
896 ((equal elem "macdef") 832 (point) (progn (skip-chars-forward "^\t ")
897 ;; We skip past the macro definition. 833 (point)))))
898 (widen) 834 (cond
899 (while (and (zerop (forward-line 1)) 835 ((equal elem "macdef")
900 (looking-at "$"))) 836 ;; We skip past the macro definition.
901 (narrow-to-region (point) (point))) 837 (widen)
902 ((member elem tokens) 838 (while (and (zerop (forward-line 1))
903 ;; Tokens that don't have a following value are ignored, 839 (looking-at "$")))
904 ;; except "default". 840 (narrow-to-region (point) (point)))
905 (when (and pair (or (cdr pair) 841 ((member elem tokens)
906 (equal (car pair) "default"))) 842 ;; Tokens that don't have a following value are ignored,
907 (push pair alist)) 843 ;; except "default".
908 (setq pair (list elem))) 844 (when (and pair (or (cdr pair)
909 (t 845 (equal (car pair) "default")))
910 ;; Values that haven't got a preceding token are ignored. 846 (push pair alist))
911 (when pair 847 (setq pair (list elem)))
912 (setcdr pair elem) 848 (t
913 (push pair alist) 849 ;; Values that haven't got a preceding token are ignored.
914 (setq pair nil)))))) 850 (when pair
915 (if alist 851 (setcdr pair elem)
916 (push (nreverse alist) result)) 852 (push pair alist)
917 (setq alist nil 853 (setq pair nil)))))))
918 pair nil) 854 (when alist
919 (widen) 855 (push (nreverse alist) result))
920 (forward-line 1)) 856 (setq alist nil
921 (nreverse result)) 857 pair nil)
922 (kill-buffer " *netrc*")))))) 858 (widen)
923 859 (forward-line 1))
924 (defun gnus-netrc-machine (list machine) 860 (nreverse result)))))
925 "Return the netrc values from LIST for MACHINE or for the default entry." 861
926 (let ((rest list)) 862 (defun gnus-netrc-machine (list machine &optional port defaultport)
927 (while (and list 863 "Return the netrc values from LIST for MACHINE or for the default entry.
928 (not (equal (cdr (assoc "machine" (car list))) machine))) 864 If PORT specified, only return entries with matching port tokens.
865 Entries without port tokens default to DEFAULTPORT."
866 (let ((rest list)
867 result)
868 (while list
869 (when (equal (cdr (assoc "machine" (car list))) machine)
870 (push (car list) result))
929 (pop list)) 871 (pop list))
930 (car (or list 872 (unless result
931 (progn (while (and rest (not (assoc "default" (car rest)))) 873 ;; No machine name matches, so we look for default entries.
932 (pop rest)) 874 (while rest
933 rest))))) 875 (when (assoc "default" (car rest))
876 (push (car rest) result))
877 (pop rest)))
878 (when result
879 (setq result (nreverse result))
880 (while (and result
881 (not (equal (or port defaultport "nntp")
882 (or (gnus-netrc-get (car result) "port")
883 defaultport "nntp"))))
884 (pop result))
885 (car result))))
934 886
935 (defun gnus-netrc-get (alist type) 887 (defun gnus-netrc-get (alist type)
936 "Return the value of token TYPE from ALIST." 888 "Return the value of token TYPE from ALIST."
937 (cdr (assoc type alist))) 889 (cdr (assoc type alist)))
938 890
939 ;;; Various 891 ;;; Various
940 892
941 (defvar gnus-group-buffer) ; Compiler directive 893 (defvar gnus-group-buffer) ; Compiler directive
942 (defun gnus-alive-p () 894 (defun gnus-alive-p ()
943 "Say whether Gnus is running or not." 895 "Say whether Gnus is running or not."
944 (and (boundp 'gnus-group-buffer) 896 (and (boundp 'gnus-group-buffer)
945 (get-buffer gnus-group-buffer) 897 (get-buffer gnus-group-buffer)
946 (save-excursion 898 (save-excursion
969 (let (entry) 921 (let (entry)
970 (while (setq entry (assq key alist)) 922 (while (setq entry (assq key alist))
971 (setq alist (delq entry alist))) 923 (setq alist (delq entry alist)))
972 alist)) 924 alist))
973 925
974 (defmacro gnus-pull (key alist) 926 (defmacro gnus-pull (key alist &optional assoc-p)
975 "Modify ALIST to be without KEY." 927 "Modify ALIST to be without KEY."
976 (unless (symbolp alist) 928 (unless (symbolp alist)
977 (error "Not a symbol: %s" alist)) 929 (error "Not a symbol: %s" alist))
978 `(setq ,alist (delq (assq ,key ,alist) ,alist))) 930 (let ((fun (if assoc-p 'assoc 'assq)))
931 `(setq ,alist (delq (,fun ,key ,alist) ,alist))))
979 932
980 (defun gnus-globalify-regexp (re) 933 (defun gnus-globalify-regexp (re)
981 "Returns a regexp that matches a whole line, iff RE matches a part of it." 934 "Returns a regexp that matches a whole line, iff RE matches a part of it."
982 (concat (unless (string-match "^\\^" re) "^.*") 935 (concat (unless (string-match "^\\^" re) "^.*")
983 re 936 re
984 (unless (string-match "\\$$" re) ".*$"))) 937 (unless (string-match "\\$$" re) ".*$")))
985 938
939 (defun gnus-set-window-start (&optional point)
940 "Set the window start to POINT, or (point) if nil."
941 (let ((win (get-buffer-window (current-buffer) t)))
942 (when win
943 (set-window-start win (or point (point))))))
944
945 (defun gnus-annotation-in-region-p (b e)
946 (if (= b e)
947 (eq (cadr (memq 'gnus-undeletable (text-properties-at b))) t)
948 (text-property-any b e 'gnus-undeletable t)))
949
950 (defun gnus-or (&rest elems)
951 "Return non-nil if any of the elements are non-nil."
952 (catch 'found
953 (while elems
954 (when (pop elems)
955 (throw 'found t)))))
956
957 (defun gnus-and (&rest elems)
958 "Return non-nil if all of the elements are non-nil."
959 (catch 'found
960 (while elems
961 (unless (pop elems)
962 (throw 'found nil)))
963 t))
964
965 (defun gnus-write-active-file (file hashtb &optional full-names)
966 (let ((coding-system-for-write nnmail-active-file-coding-system))
967 (with-temp-file file
968 (mapatoms
969 (lambda (sym)
970 (when (and sym
971 (boundp sym)
972 (symbol-value sym))
973 (insert (format "%S %d %d y\n"
974 (if full-names
975 sym
976 (intern (gnus-group-real-name (symbol-name sym))))
977 (or (cdr (symbol-value sym))
978 (car (symbol-value sym)))
979 (car (symbol-value sym))))))
980 hashtb)
981 (goto-char (point-max))
982 (while (search-backward "\\." nil t)
983 (delete-char 1)))))
984
986 (provide 'gnus-util) 985 (provide 'gnus-util)
987 986
988 ;;; gnus-util.el ends here 987 ;;; gnus-util.el ends here