home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / elisp / misc / reportmail.el < prev    next >
Encoding:
Text File  |  1991-03-20  |  21.6 KB  |  596 lines

  1. ; Path: utkcs2!emory!samsung!cs.utexas.edu!tut.cis.ohio-state.edu!pt.cs.cmu.edu!PROOF.ERGO.CS.CMU.EDU!bcp
  2. ; >From: bcp@CS.CMU.EDU (Benjamin Pierce)
  3. ; Newsgroups: gnu.emacs
  4. ; Subject: Reportmail (was: Mail alert in mode line?)
  5. ; Date: 21 Jul 90 03:25:07 GMT
  6. ; Organization: Carnegie Mellon University
  7. ; Dave Plaut, Mark Leone, and I wrote a bit of code to report incoming
  8. ; mail in the mode line.  Installation instructions are included below.
  9. ;     Benli
  10. ;; REPORTMAIL: Display time and load in mode line of Emacs.
  11. ;; Originally time.el in the emacs distribution.
  12. ;; Mods by BCP and DCP to display incoming mail.
  13. ;;
  14. ;; Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc.
  15.  
  16. ;; This file is part of GNU Emacs.
  17.  
  18. ;; GNU Emacs is distributed in the hope that it will be useful,
  19. ;; but WITHOUT ANY WARRANTY.  No author or distributor
  20. ;; accepts responsibility to anyone for the consequences of using it
  21. ;; or for whether it serves any particular purpose or works at all,
  22. ;; unless he says so in writing.  Refer to the GNU Emacs General Public
  23. ;; License for full details.
  24.  
  25. ;; Everyone is granted permission to copy, modify and redistribute
  26. ;; GNU Emacs, but only under the conditions described in the
  27. ;; GNU Emacs General Public License.   A copy of this license is
  28. ;; supposed to have been given to you along with GNU Emacs so you
  29. ;; can know your rights and responsibilities.  It should be in a
  30. ;; file named COPYING.  Among other things, the copyright notice
  31. ;; and this notice must be preserved on all copies.
  32.  
  33. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  34. ;
  35. ; To use reportmail, add the following to your .emacs file:
  36. ;
  37. ;    (load-library "reportmail")
  38. ;
  39. ;    ;; Edit this list as appropriate
  40. ;    (setq display-time-my-addresses
  41. ;     '("Benjamin.Pierce" "bcp" "Benjamin Pierce" "\"Benjamin C. Pierce"))
  42. ;    ;; By default, mail arrival is reported with a message but no beep  
  43. ;    (setq display-time-mail-ring-bell t)
  44. ;    (display-time)
  45. ;
  46. ; In the CMU SCS environment, messages waiting to be read are kept in a 
  47. ; file called /usr/spool/mail/<userid>, separated by control-Cs.
  48. ; If your environment differs, you will want to modify the values of
  49. ; the variables 
  50. ;             display-time-incoming-mail-file 
  51. ; and/or      display-time-message-separator.
  52. ;
  53. ;
  54. ; The reportmail package has a notion of "junk mail," which can be used to
  55. ; reduce the frequency of irritating interruptions by reporting only the
  56. ; arrival of messages that seem to be interesting.  If you're on a lot
  57. ; of high-volume mailing lists, this can be quite convenient.  To use
  58. ; this facility, add something like the following to your .emacs file:
  59. ;   ;; The value of this variable is a list of lists, where the first
  60. ;   ;; element in each list is the name of a header field and the
  61. ;   ;; remaining elements are various prefixes of the value of this
  62. ;   ;; header field that signal the junkiness of a message.  
  63. ;   (setq display-time-junk-mail-checklist
  64. ;     '(("From" "bcp" "Benjamin Pierce" "Benjamin.Pierce"
  65. ;               "Mail Delivery Subsystem" "network" "daemon@bartok")
  66. ;       ("To" "sml-request" "sml-redistribution-request" 
  67. ;        "scheme" "TeXhax-Distribution-list")
  68. ;       ("Resent-From" "Benjamin.Pierce")
  69. ;       ("Sender" "WRITERS" "Haskell" "Electronic Music Digest" "NEW-LIST")))
  70. ;   
  71. ;
  72. ; If you normally keep your emacs window iconified, reportmail can 
  73. ; maintain an xbiff display as well.  The xbiff window will only be 
  74. ; highlighted when non-junk mail is waiting to be read.  For example:
  75. ;
  76. ;    (if window-system-version
  77. ;        (setq display-time-use-xbiff t))
  78. ;    (setq display-time-xbiff-arg-list '("-update" "30" "-geometry" "+0+0"))
  79. ;
  80. ;
  81. ; There are several other user-customization variables that you may wish
  82. ; to modify.  These are documented below.
  83.  
  84.  
  85. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  86. ;
  87. ; HISTORY
  88. ;
  89. ; 19 Jul 90     Benjamin Pierce (bcp@cs.cmu.edu)
  90. ;       Improved user documentation and eliminated known CMU dependencies.
  91. ;
  92. ; 13 Jul 90    Mark Leone (mleone@cs.cmu.edu)
  93. ;    Added display-time-use-xbiff option.  Various layout changes.
  94. ;
  95. ; 20 May 90     Benjamin Pierce (bcp@cs.cmu.edu)
  96. ;       Fixed a bug that occasionally caused fields to be extracted
  97. ;       from the wrong buffer.
  98. ;
  99. ; 14 May 90     Benjamin Pierce (bcp@cs.cmu.edu)
  100. ;       Added concept of junk mail and ability to display message
  101. ;       recipient in addition to sender and subject.  (Major internal
  102. ;       reorganization was needed to implement this cleanly.)
  103. ;
  104. ; 18 Nov 89     Benjamin Pierce (bcp@cs.cmu.edu)
  105. ;       Fixed to work when display-time is called with 
  106. ;       global-mode-string not a list
  107. ;
  108. ; 15 Jan 89    David Plaut (dcp@cs.cmu.edu)
  109. ;    Added ability to discard load from displayed string
  110. ;
  111. ;    To use:    (setq display-time-load nil)
  112. ;
  113. ;    Added facility for reporting incoming mail (modeled after gosmacs
  114. ;    reportmail.ml package written by Benjamin Pierce).
  115.  
  116.  
  117. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  118. ;;;                       User Variables                          ;;;
  119. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  120.  
  121. (defvar display-time-announce-mail t
  122.   "*Toggles whether name of mail sender is displayed in mode line.")
  123.  
  124. (defvar display-time-announce-junk-mail-too nil
  125.   "*When non-NIL, announce incoming junk mail as well as interesting mail")
  126.  
  127. (defvar display-time-time t
  128.   "*Toggles whether the time is displayed.")
  129.  
  130. (defvar display-time-load nil
  131.   "*Toggles whether machine load is displayed.")
  132.  
  133. (defvar display-time-day-and-date nil
  134.   "*Toggles whether day and date are displayed.")
  135.  
  136. (defvar display-time-mail-ring-bell nil
  137.   "*Toggles whether bell is rung on mail arrival.")
  138.  
  139. (defvar display-time-my-addresses 
  140.   (list (user-full-name) (user-login-name))
  141.   "*Report the addressee of incoming mail, unless it appears in this list")
  142. ;; For example:
  143. ;; (setq display-time-my-addresses
  144. ;;  '("Benjamin.Pierce" "bcp" "Benjamin Pierce" "\"Benjamin C. Pierce"))
  145.  
  146. (defvar display-time-junk-mail-checklist nil
  147.   "*A list of lists of strings.  In each sublist, the first component is the
  148. name of a message field and the rest are values that flag a piece of
  149. junk mail.")
  150. ;; For example:
  151. ;; (setq display-time-junk-mail-checklist
  152. ;;  '(("From" "bcp" "Benjamin Pierce" "Benjamin.Pierce"
  153. ;;            "Mail Delivery Subsystem" "network" "daemon@bartok")
  154. ;;    ("To" "sml-request" "sml-redistribution-request" "computermusic" 
  155. ;;     "scheme" "TeXhax-Distribution-list")
  156. ;;    ("Resent-From" "Benjamin.Pierce")
  157. ;;    ("Sender" "WRITERS" "Haskell" "Electronic Music Digest" "NEW-LIST")))
  158.  
  159. (defvar display-time-max-from-length 35
  160.   "*Truncate sender name to this length in mail announcements")
  161.  
  162. (defvar display-time-max-to-length 11
  163.   "*Truncate addressee name to this length in mail announcements")
  164.  
  165. (defvar display-time-interval 30
  166.   "*Seconds between updates of time in the mode line.  Also used
  167. as interval for checking incoming mail.")
  168.  
  169. (defvar display-time-incoming-mail-file
  170.   (let ((spool-name (getenv "MAIL")))
  171.     (if (or (null spool-name) (not (file-exists-p spool-name)))
  172.     (let ((user-name (getenv "USER")))
  173.       (setq spool-name (concat "/usr/spool/mail/" user-name))
  174.       (if (or (null user-name) (not (file-exists-p spool-name)))
  175.           (setq spool-name ""))))
  176.     spool-name)
  177.   "User's incoming mail file.  Default is value of environment variable MAIL,
  178. if set;  otherwise /usr/spool/mail/$USER is used.")
  179.  
  180. (defvar display-time-message-separator "\C-c")
  181.  
  182. (defvar display-time-use-xbiff nil
  183.   "If set, display-time uses xbiff to announce new mail.")
  184.  
  185. (defvar display-time-xbiff-arg-list nil
  186.   "List of arguments passed to xbiff.  Useful for setting geometry, etc.")
  187. ;;; For example: 
  188. ;;; (setq display-time-xbiff-arg-list '("-update" "30" "-geometry" "+0+0"))
  189.  
  190. (defvar display-time-mail-arrived-file
  191.   (concat "/usr/" (getenv "USER") "/.mail-arrived")
  192.   "New mail announcements saved in this file if xbiff used.  Deleted when 
  193. mail is read.  Xbiff used to monitor existence of this file.")
  194.  
  195. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  196. ;;;                       Internal Variables                      ;;;
  197. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  198.  
  199. (defvar display-time-loadst-process nil
  200.   "The process providing time, load, and mail info.")
  201.  
  202. (defvar display-time-xbiff-process nil
  203.   "The xbiff process used to announce incoming mail.")
  204.  
  205. (defvar display-time-string nil
  206.   "Time displayed in mode line")
  207.  
  208. (defvar display-time-mail-buffer-name "*Mail*"
  209.   "Name of buffer used for announcing mail.")
  210.  
  211. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  212. ;;;                       Macros                                  ;;;
  213. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  214.  
  215. (defmacro when (condition &rest body)
  216.   (append (list 'if (list 'not condition) '()) body))
  217.  
  218. (defmacro unless (condition &rest body)
  219.   (append (list 'if condition '()) body))
  220.  
  221. (defmacro del-file (filename)
  222.   (list 'if (list 'file-exists-p filename) (list 'delete-file filename)))
  223.  
  224. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  225. ;;;                       Time Display                            ;;;
  226. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  227.  
  228. (defun display-time-kill ()
  229.   "Kill all display-time processes.  Done automatically if display-time
  230. is re-invoked."
  231.   (interactive)
  232.   (if display-time-loadst-process (delete-process display-time-loadst-process))
  233.   (if display-time-xbiff-process (delete-process display-time-xbiff-process))
  234. )
  235.  
  236.  
  237. (defun display-time ()
  238.   "Displays current time, date, load level, and incoming mail status in 
  239. mode line of each buffer (if corresponding user variables are set)."
  240.   (interactive)
  241.   (let ((process-connection-type nil))  ; UIUCDCS mod
  242.     (save-excursion
  243.       (display-time-kill)
  244.       (if (or (string-equal "" display-time-incoming-mail-file)
  245.           (not (file-exists-p display-time-incoming-mail-file)))
  246.       (error "Display-time-incoming-mail-file not found!"))
  247.       
  248.       (if (not global-mode-string) (setq global-mode-string '("")))
  249.       (if (not (listp global-mode-string))
  250.       (setq global-mode-string (list global-mode-string "  ")))
  251.       (if (not (memq 'display-time-string global-mode-string))
  252.       (setq global-mode-string
  253.         (append global-mode-string '(display-time-string))))
  254.       (setq display-time-string "time and load")
  255.       
  256.       (setq display-time-loadst-process
  257.         (start-process "display-time-loadst" nil
  258.                "loadst" 
  259.                "-n" (int-to-string display-time-interval)))
  260.       (process-kill-without-query display-time-loadst-process)
  261.       (set-process-sentinel display-time-loadst-process 
  262.                 'display-time-sentinel)
  263.       (set-process-filter display-time-loadst-process 'display-time-filter)
  264.       
  265.       (if display-time-use-xbiff
  266.       (progn
  267.         (del-file display-time-mail-arrived-file)
  268.         (setq display-time-xbiff-process
  269.           (apply 'start-process "display-time-xbiff" nil
  270.              "xbiff" "-file" display-time-mail-arrived-file
  271.              display-time-xbiff-arg-list))
  272.         (process-kill-without-query display-time-xbiff-process)
  273.         (sit-for 1)            ; Need time to see if xbiff fails.
  274.         (if (/= 0 (process-exit-status display-time-xbiff-process))
  275.         (error "Display time: xbiff failed.  Check xbiff-arg-list"))))))
  276.   (display-time-reset-mail-processing))
  277.  
  278.  
  279. (defun display-time-sentinel (proc reason)
  280.   (or (eq (process-status proc) 'run)
  281.       (setq display-time-string ""))
  282.   ;; Force mode-line updates
  283.   (save-excursion (set-buffer (other-buffer)))
  284.   (set-buffer-modified-p (buffer-modified-p))
  285.   (sit-for 0))
  286.  
  287.  
  288. (defun display-time-filter (proc string)
  289.   ;; Desired data can't need more than the last 30 chars,
  290.   ;; so save time by flushing the rest.
  291.   ;; This way, if we have many different times all collected at once,
  292.   ;; we can discard all but the last few very fast.
  293.   (if (> (length string) 30) (setq string (substring string -30)))
  294.   ;; Now discard all but the very last one.
  295.   (while (and (> (length string) 4)
  296.           (string-match "[0-9]+:[0-9][0-9].." string 4))
  297.     (setq string (substring string (match-beginning 0))))
  298.   (if (string-match "[^0-9][0-9]+:" string)
  299.       (setq string (substring string 0 (1+ (match-beginning 0)))))
  300.   ;; If we're announcing mail and mail has come, process any new messages
  301.   (when display-time-announce-mail
  302.     (if (string-match "Mail" string)
  303.         (display-time-process-new-mail)
  304.         (display-time-reset-mail-processing)))
  305.   ;; Format the mode line time display
  306.   (let ((time-string (if (string-match "Mail" string)
  307.              (if display-time-announce-mail 
  308.                  display-time-mail-modeline
  309.                  "Mail "))))
  310.     (if (and display-time-time (string-match "[0-9]+:[0-9][0-9].." string))
  311.     (setq time-string 
  312.           (concat time-string
  313.               (substring string (match-beginning 0) (match-end 0))
  314.               " ")))
  315.     (if display-time-day-and-date
  316.     (setq time-string
  317.           (concat time-string
  318.               (substring (current-time-string) 0 11))))
  319.     (if (and display-time-load (string-match "[0-9]+\\.[0-9][0-9]" string))
  320.     (setq time-string
  321.           (concat time-string
  322.               (substring string (match-beginning 0) (match-end 0))
  323.               " ")))
  324.     ;; Install the new time for display.
  325.     (setq display-time-string time-string)
  326.     ;; Force redisplay of all buffers' mode lines to be considered.
  327.     (save-excursion (set-buffer (other-buffer)))
  328.     (set-buffer-modified-p (buffer-modified-p))
  329.     ;; Do redisplay right now, if no input pending.
  330.     (sit-for 0)))
  331.  
  332.  
  333. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  334. ;;;                       Mail processing                         ;;;
  335. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  336.  
  337. (defvar display-time-mail-who-from ""
  338.   "Short-form name of sender of last piece of interesting unread mail")
  339.  
  340. (defvar display-time-mail-modeline ""
  341.   "Terse mail announcement (displayed in modeline)")
  342.  
  343. (defvar display-time-previous-mail-buffer-max 1
  344.   "The length of the mail buffer the last time we looked at it")
  345.  
  346. (defvar display-time-msg-count 0
  347.   "How many interesting messages have arrived")
  348.  
  349. (defvar display-time-junk-msg-count 0
  350.   "How many junk messages have arrived")
  351.  
  352.  
  353. ;; A test procedure for trying out new display-time features
  354. (defun display-time-test ()
  355.   (interactive)
  356.   (display-time-reset-mail-processing)
  357.   (display-time-process-new-mail))
  358.  
  359. (defun display-time-reset-mail-processing ()
  360.   (let ((mail-buffer (get-buffer display-time-mail-buffer-name)))
  361.     (if mail-buffer (kill-buffer mail-buffer)))
  362.   (if display-time-use-xbiff
  363.       ;; This function is only called when no mail is in the spool.
  364.       ;; Hence we should delete the mail-arrived file.
  365.       (del-file display-time-mail-arrived-file))
  366.   (display-time-reset-mail-processing-vars))
  367.  
  368. (defun display-time-reset-mail-processing-vars ()
  369.   (setq display-time-msg-count 0)
  370.   (setq display-time-junk-msg-count 0)
  371.   (setq display-time-mail-who-from "Junk mail")
  372.   (setq display-time-previous-mail-buffer-max 1))
  373.  
  374. (defun display-time-process-new-mail ()
  375.   (let ((mail-buffer (get-buffer display-time-mail-buffer-name))
  376.     start)
  377.     (unless (and mail-buffer (verify-visited-file-modtime mail-buffer))
  378.       (save-window-excursion
  379.     (if mail-buffer (kill-buffer mail-buffer))
  380.     ;; Change to pop-to-buffer when we're debugging:
  381.     (set-buffer (find-file-noselect display-time-incoming-mail-file))
  382.     (rename-buffer display-time-mail-buffer-name)
  383.     (if (< display-time-previous-mail-buffer-max (point-max))
  384.         (progn
  385.           (goto-char display-time-previous-mail-buffer-max)
  386.           (if (not (looking-at display-time-message-separator))
  387.           (display-time-reset-mail-processing-vars)))
  388.         (display-time-reset-mail-processing-vars))
  389.     (goto-char display-time-previous-mail-buffer-max)
  390.     (if (not (eobp))
  391.         (forward-char 1))
  392.     (while (not (eobp))
  393.       (setq start (point))
  394.       (if (not (search-forward display-time-message-separator nil t))
  395.           (goto-char (point-max)))
  396.       (narrow-to-region start (point))
  397.       (display-time-process-this-message)
  398.       (goto-char (point-max))
  399.       (widen))
  400.     (setq display-time-previous-mail-buffer-max (point-max))))))
  401.  
  402. (defun display-time-process-this-message ()
  403.   ;; Here's where we should check to see whether it's junk mail
  404.   (if (display-time-junk-message)
  405.       (display-time-process-junk-message)  
  406.       (display-time-process-good-message))
  407.   
  408.   ;; Update mode line contents
  409.   (setq display-time-mail-modeline 
  410.     (concat "[" (display-time-format-msg-count) 
  411.         display-time-mail-who-from
  412.         "] "))
  413.   ;; (stop-here (concat "New mode line: " display-time-mail-modeline))
  414.   )
  415.  
  416. (defun display-time-junk-message ()
  417.   "Check to see whether this message is interesting"
  418.   (let ((checklist display-time-junk-mail-checklist)
  419.     (junk nil))
  420.     (while (and checklist (not junk))
  421.       (if (display-time-member 
  422.        (display-time-get-field (car (car checklist)))
  423.        (cdr (car checklist)))
  424.       (setq junk t)
  425.       (setq checklist (cdr checklist))))
  426.     junk))
  427.  
  428. (defun display-time-process-good-message ()
  429.   ;; Update the message counter
  430.   (setq display-time-msg-count (+ display-time-msg-count 1))
  431.  
  432.   ;; Format components of announcement
  433.   (let* ((subject (display-time-get-field "Subject" ""))
  434.      (from (display-time-get-field "From" ""))
  435.      (to (display-time-get-field "To" ""))
  436.          (print-subject (if (string= subject "")
  437.                 ""
  438.                 (concat " (" subject ")")))
  439.      (print-from (display-time-truncate from display-time-max-from-length))
  440.      (short-from (display-time-truncate 
  441.               (display-time-extract-short-addr from) 25))
  442.      (print-to (if (display-time-member to display-time-my-addresses)
  443.                ""
  444.                (display-time-truncate 
  445.             (display-time-extract-short-addr to)
  446.             display-time-max-to-length))))
  447.  
  448.     ;; Announce message
  449.     (let ((msg (concat 
  450.            (display-time-format-msg-count)
  451.            "Mail " 
  452.            (if (string= print-to "") "" 
  453.                (concat "to " print-to " "))
  454.            "from " print-from 
  455.            print-subject)))
  456.       (if display-time-use-xbiff
  457.       (save-excursion
  458.         (let ((tmp-buf (generate-new-buffer "*Tmp*")))
  459.           (set-buffer tmp-buf)
  460.           (insert msg)
  461.           (newline)
  462.           (append-to-file (point-min) (point-max) 
  463.                   display-time-mail-arrived-file)
  464.           (kill-buffer tmp-buf))))
  465.       (message "%s" msg))
  466.  
  467.     (if display-time-mail-ring-bell (ding))
  468.     (sit-for 2)
  469.     
  470.     ;; Update mode line information
  471.     (setq display-time-mail-who-from short-from)))
  472.  
  473. (defun display-time-process-junk-message ()
  474.   ;; Update the message counter
  475.   (setq display-time-junk-msg-count (+ display-time-junk-msg-count 1))
  476.  
  477.   ;; Format components of announcement
  478.   (let* ((subject (display-time-get-field "Subject" ""))
  479.      (from (display-time-get-field "From" ""))
  480.      (to (display-time-get-field "To" ""))
  481.          (print-subject (if (string= subject "")
  482.                 ""
  483.                 (concat " (" subject ")")))
  484.      (print-from (display-time-truncate from display-time-max-from-length))
  485.      (short-from (display-time-truncate 
  486.               (display-time-extract-short-addr from) 25))
  487.      (print-to (if (display-time-member to display-time-my-addresses)
  488.                ""
  489.                (display-time-truncate 
  490.             (display-time-extract-short-addr to)
  491.             display-time-max-to-length))))
  492.  
  493.     ;; Announce message
  494.     (when display-time-announce-junk-mail-too
  495.       (let ((msg (concat 
  496.               (display-time-format-msg-count)
  497.               "Junk Mail " 
  498.               (if (string= print-to "") "" 
  499.             (concat "to " print-to " "))
  500.               "from " print-from 
  501.               print-subject)))
  502.         (if display-time-use-xbiff
  503.         (save-excursion
  504.           (let ((tmp-buf (generate-new-buffer "*Tmp*")))
  505.             (set-buffer tmp-buf)
  506.             (insert msg)
  507.             (newline)
  508.             (append-to-file (point-min) (point-max) 
  509.                     display-time-mail-arrived-file)
  510.             (kill-buffer tmp-buf))))
  511.         (message "%s" msg)
  512.         (if display-time-mail-ring-bell (ding))
  513.         (sit-for 2)))))
  514.  
  515. (defun display-time-format-msg-count ()
  516.    (if (> (+ display-time-msg-count display-time-junk-msg-count) 1) 
  517.        (concat 
  518.     (int-to-string display-time-msg-count) 
  519.     (if (> display-time-junk-msg-count 0)
  520.         (concat "(" (int-to-string display-time-junk-msg-count) ")"))
  521.     ": ")
  522.        ""))
  523.  
  524. (defun display-time-get-field (field &optional default)
  525.   (when (not (equal (buffer-name) display-time-mail-buffer-name))
  526.     (beep)
  527.     (message "bcp-time bug: processing buffer %s, not %s"
  528.          (buffer-name)
  529.          display-time-mail-buffer-name)
  530.     (sit-for 2))
  531.   (goto-char (point-min))
  532.   (if (re-search-forward (concat "^" field ":[ |\C-i]*") nil t)
  533.     (let ((start (point)))
  534.       (end-of-line)
  535.       (buffer-substring start (point)))
  536.     (or default "<unknown>")))
  537.  
  538. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  539. ;;;                       Auxilliary Functions                    ;;;
  540. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  541.  
  542. (defun display-time-member (e l)
  543.   "Is string E and element of list L?"
  544.   (let ((done nil)
  545.     (result nil))
  546.     (while (not done)
  547.       (cond 
  548.        ((null l) (setq done t))
  549.        ((display-time-is-prefix (car l) e) (setq result l) (setq done t))
  550.        (t (setq l (cdr l)))))
  551.     result))
  552.  
  553. (defun display-time-truncate (s max)
  554.   (if (and s (>= (length s) max))
  555.       (concat (substring s 0 max) "...")
  556.       s))
  557.  
  558. (defun display-time-is-prefix (pstr1 str2) 
  559.   "Is PSTR1 a prefix of STR2?"
  560.   (and (<= (length pstr1) (length str2))
  561.       (equal pstr1 (substring str2 0 (length pstr1)))))
  562.  
  563. (defun display-time-extract-short-addr (long-addr)
  564.   (let ((name "\\([A-Za-z0-9-_+\\. ]+\\)"))
  565.     (if (or 
  566.      ;; David Plaut <dcp@CS.CMU.EDU>     -> David Plaut
  567.      (string-match (concat name "[ |    ]+<.+>") long-addr)
  568.     
  569.      ;; anything (David Plaut) anything     -> David Plaut
  570.      (string-match ".+(\\(.+\\)).*" long-addr)
  571.      
  572.      ;; plaut%address.bitnet@vma.cc.cmu.edu -> plaut
  573.      (string-match (concat name "%.+@.+") long-addr)
  574.  
  575.      ;; random!uucp!addresses!dcp@uu.relay.net -> dcp
  576.      (string-match (concat ".*!" name "@.+") long-addr)
  577.  
  578.      ;; David.Plaut@CS.CMU.EDU         -> David.Plaut
  579.      (string-match (concat name "@.+") long-addr)
  580.      )
  581.     (substring long-addr (match-beginning 1) (match-end 1))
  582.     long-addr)))
  583.  
  584.  
  585.