[23665] in Source-Commits
/svn/athena r23280 - in trunk/athena/bin/discuss: debian edsc
daemon@ATHENA.MIT.EDU (broder@MIT.EDU)
Fri Jan 9 21:34:16 2009
Date: Fri, 9 Jan 2009 21:33:46 -0500 (EST)
From: broder@MIT.EDU
Message-Id: <200901100233.VAA07970@drugstore.mit.edu>
To: source-commits@MIT.EDU
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Author: broder
Date: 2009-01-09 21:33:45 -0500 (Fri, 09 Jan 2009)
New Revision: 23280
Added:
trunk/athena/bin/discuss/edsc/discuss.el.in
Removed:
trunk/athena/bin/discuss/edsc/discuss.el
Modified:
trunk/athena/bin/discuss/debian/changelog
trunk/athena/bin/discuss/edsc/Makefile.in
Log:
Remove hard-coded paths from Emacs discuss-mode, in favor if
retrieving them from autoconf.
Modified: trunk/athena/bin/discuss/debian/changelog
===================================================================
--- trunk/athena/bin/discuss/debian/changelog 2009-01-10 00:59:14 UTC (rev 23279)
+++ trunk/athena/bin/discuss/debian/changelog 2009-01-10 02:33:45 UTC (rev 23280)
@@ -2,8 +2,10 @@
* Revert a small part of the OS X com_err patch from 10.0.6 in favor of
changes to aclocal.m4
+ * Remove hard-coded paths from discuss-mode, in favor of getting them
+ from autoconf.
- -- Evan Broder <broder@mit.edu> Fri, 09 Jan 2009 19:23:15 -0500
+ -- Evan Broder <broder@mit.edu> Fri, 09 Jan 2009 21:32:25 -0500
debathena-discuss (10.0.6-0debathena1) unstable; urgency=low
Modified: trunk/athena/bin/discuss/edsc/Makefile.in
===================================================================
--- trunk/athena/bin/discuss/edsc/Makefile.in 2009-01-10 00:59:14 UTC (rev 23279)
+++ trunk/athena/bin/discuss/edsc/Makefile.in 2009-01-10 02:33:45 UTC (rev 23280)
@@ -37,7 +37,7 @@
all: edsc
clean:
- rm -f edsc *.o version.h
+ rm -f edsc *.o version.h discuss.el
depend:
@@ -54,6 +54,9 @@
version.h: ${SRCS} newvers.sh
sh newvers.sh
+discuss.el: discuss.el.in Makefile
+ sed -e 's|#libexecdir#|${libexecdir}|' $< > $@
+
edsc: $(OBJS)
${CC} ${LDFLAGS} -o edsc ${OBJS} ${LIBS}
Deleted: trunk/athena/bin/discuss/edsc/discuss.el
Copied: trunk/athena/bin/discuss/edsc/discuss.el.in (from rev 23276, trunk/athena/bin/discuss/edsc/discuss.el)
===================================================================
--- trunk/athena/bin/discuss/edsc/discuss.el 2009-01-09 21:11:46 UTC (rev 23276)
+++ trunk/athena/bin/discuss/edsc/discuss.el.in 2009-01-10 02:33:45 UTC (rev 23280)
@@ -0,0 +1,1224 @@
+;;; Emacs lisp code to remote control a "discuss" shell process to
+;;; provide an emacs-based interface to the discuss conferencing system.
+;;;
+;;; Copyright (C) 1989, 1993 by the Massachusetts Institute of Technology
+;;; Developed by the MIT Student Information Processing Board (SIPB).
+;;; Written by Stan Zanarotti, Bill Sommerfeld and Theodore Ts'o.
+;;; For copying information, see the file mit-copyright.h in this release.
+;;;
+;;; $Id: discuss.el,v 1.41 1999-06-04 14:11:13 danw Exp $
+;;;
+
+;;
+;; WARNING --- change discuss-source-dir when installing this file!
+;;
+
+(provide 'discuss)
+
+(defvar discuss-source-dir nil
+ "Source directory from which this version of discuss is loaded, including
+the trailing `/'. It must end with `/', since it will be directly
+concatenated to other file names. Setting this to nil or an empty string
+will cause load-path to be used.")
+
+(defvar discuss-pathname "#libexecdir#/edsc"
+ "*Name of program to run as slave process for discuss.")
+
+(defvar discuss-DWIM nil
+ "If true, enable Do_What_I_Mean mode. Allows the user to read discuss by
+repeatedly hitting the space bar. For the truly lazy user.")
+
+(defvar discuss-safe-delete nil
+ "If true, discuss asks for confirmation before deleting a transaction with
+discuss-delete-trn.")
+
+(defvar discuss-reply-by-mail-with-message-id nil
+ "If true, use the Message-Id field in a message for generating the
+In-Reply-To field, rather than using the discuss convention of
+In-Reply-To: [###] in Meeting.")
+
+(defvar discuss-auto-reply-to-alist nil
+ "Association list of discuss meeting names (long forms) and default
+Reply-To addresses that should be inserted into replies by mail (to help
+ensure that people don't drop the CC to the discuss meeting.)")
+
+(defvar discuss-font-lock-keywords '(("^\\(From: .*\\)" 1 'bold t)
+ ("^\\(Subject: .*\\)" 1 'bold t))
+ "Keywords to highlight in transactions if using font-lock mode.
+(Add (add-hook 'discuss-show-trn-hooks 'font-lock-mode) to your
+.emacs to enable discuss font-lock mode.)")
+
+(defvar discuss-visible-headers nil
+ "If non-nil, a regexp matching the mail headers to display in discuss
+meetings fed by mailing lists. If nil, the value of discuss-invisible-headers
+is used instead.")
+
+(defvar discuss-invisible-headers "^From \\|^Received:"
+ "If discuss-visible-headers is nil, discuss-invisible-headers is a regexp
+matching the mail headers to be not shown by default in discuss meetings
+fed by mailing lists.")
+
+(defvar discuss-keep-discuss-ls nil
+ "If nil, windows containing *discuss-ls* buffers will be deleted when
+leaving transaction mode.")
+
+(defvar discuss-use-short-meeting-name nil
+ "If nil, transaction mode buffers will use the full name of the discuss
+meeting. If non-nil, they will use the short name.")
+
+(defvar discuss-mtgs-mode-map nil
+ "Keymap used by the meetings-list mode of the discuss subsystem.")
+
+(defvar discuss-list-mode-map nil
+ "Keymap used by the transaction-list mode of the discuss subsystem.")
+
+(defvar discuss-trn-mode-map nil
+ "Keymap used by the transaction mode of the discuss subsystem.")
+
+(defvar discuss-main-buffer "*meetings*"
+ "Name of main buffer for discuss, which holds a list of the current
+meetings.")
+
+(defvar discuss-version nil "Version of discuss code loaded.")
+(defun discuss-version nil (interactive) (message discuss-version))
+
+(defvar discuss-process nil
+ "Structure discribing the slave discuss subprocess.")
+
+(defvar discuss-cont nil
+ "Internal hook to call when discuss subprocess is done.")
+
+(defvar discuss-unwind nil
+ "Internal hook to call when discuss subprocess returns an error.")
+
+(defvar discuss-in-progress nil
+ "t if a request to the slave subprocess is outstanding.")
+
+(defvar discuss-form nil
+ "Lisp form returned by the subprocess.")
+
+(defvar discuss-meeting-list nil
+ "Meeting list.")
+
+(defvar discuss-meeting-completion-list nil
+ "Meeting list changed into the right format for completion-read.")
+
+(defvar discuss-show-num 0
+ "Current discuss transaction number.")
+
+(defvar discuss-show-headers nil
+ "Whether or not all headers are being displayed on the current transaction.")
+
+(defvar discuss-meeting nil
+ "Buffer-local variable containing the name of the meeting of a discuss
+transaction buffer. Nil means this buffer is not a discuss-transaction
+buffer.")
+
+(defvar discuss-meeting-info nil
+ "Buffer-local variable containing the info struction for the discuss
+transaction buffer.")
+
+(defvar discuss-cur-mtg-buf nil
+ "Name of buffer for current Discuss meeting.")
+
+(defvar discuss-cur-direction 0
+ "Current discuss direction.")
+
+(defvar discuss-async t
+ "*Run discuss commands asynchronously.
+
+Currently ignored (always async).")
+
+(defvar discuss-in-show-trn nil)
+
+(defvar discuss-error nil
+ "Contains error message returned by edsc process. If nil, means last
+request completed successfully.")
+
+
+;;; Major modes defined by this package.
+
+;;; List of all meetings.
+
+(defun discuss-mtgs-mode ()
+ "Major mode for providing an emacs discuss subsystem.
+This looks a lot like RMAIL. This works by using ``edsc'' as a subjob.
+
+The following commands are available:
+\\[describe-mode] List available commands.
+\\[discuss-forward-meeting] Go to next meeting that has unread transactions.
+\\[discuss-prev-meeting] Go to previous meeting has unread transactions.
+\\[discuss-lsm] List meetings.
+\\[discuss-goto] Go to meeting listed on line.
+\\[discuss-add-mtg] Add meeting.
+\\[discuss-del-mtg] Delete meeting listed on line.
+\\[discuss-catchup] Mark a meeting as read (catch up).
+\\[discuss-quit] Quit Discuss."
+ (interactive)
+ (kill-all-local-variables)
+ (setq major-mode 'discuss-mtgs-mode)
+ (setq mode-name "Discuss (meetings)")
+ (use-local-map discuss-mtgs-mode-map)
+ (setq buffer-read-only t)
+ (run-hooks 'discuss-mode-hooks))
+
+;;; Meeting list mode.
+
+(defun discuss-list-mode ()
+ "Major mode for looking at listings of a meeting under the
+discuss subsystem."
+ (interactive)
+ (kill-all-local-variables)
+ (setq major-mode 'discuss-list-mode)
+ (setq mode-name "Discuss (list)")
+ (use-local-map discuss-list-mode-map)
+ (setq buffer-read-only t)
+ (make-local-variable 'trans-buffer)
+ (setq trans-buffer nil)
+ (make-local-variable 'meeting-name)
+ (setq meeting-name nil)
+ (run-hooks 'discuss-list-hooks))
+
+;;; Transaction mode.
+
+(defun discuss-trn-mode ()
+"Major mode for looking at transactions of a meeting under the
+discuss subsystem.
+All normal editing commands are turned off.
+Instead, these commands are available:
+
+\\[describe-mode] List available commands.
+\\[discuss-scroll-up] Scroll to next screen of this transaction.
+\\[scroll-down] Scroll to previous screen of this transaction.
+\\[discuss-ls] List headers of remaining transactions.
+\\[discuss-next-trn] Move to Next transaction.
+\\[discuss-prev-trn] Move to Previous transaction.
+\\[discuss-last-trn] Move to Last transaction in meeting.
+\\[discuss-first-trn] Move to First transaction in meeting.
+\\[discuss-nref] Move to Next transaction in chain.
+\\[discuss-pref] Move to Previous transaction in chain.
+\\[discuss-fref] Move to First transaction in chain.
+\\[discuss-lref] Move to Last transaction in chain.
+\\[discuss-show-trn] Goto a specific transaction.
+\\[discuss-delete-trn] Delete transaction (and move forwards).
+\\[discuss-delete-trn-backwards] Delete transaction (and move backwards).
+\\[discuss-retrieve-trn] Retrieve (undelete) a deleted transaction.
+\\[discuss-update] Redisplay this transaction from the top.
+\\[discuss-show-trn-with-headers] Redisplay this transaction with full mail headers.
+\\[discuss-reply] Reply to this transaction (via discuss.)
+\\[discuss-reply-by-mail] Reply to this transaction (via mail.)
+\\[discuss-forward] Forward this transaction via mail.
+\\[discuss-trn-output] Append this transaction to a UNIX file.
+\\[discuss-talk] Talk. Enter a new transaction.
+\\[discuss-toggle-trn-flag] Toggle the flag on this transaction.
+\\[discuss-set-seen-and-leave-mtg] Mark transaction as highest-seen and leave meeting.
+\\[discuss-catchup] Catch up. Mark all of the transactions in this meeting as read.
+\\[discuss-add-mtg] Add meeting (if this transaction is a meeting annoucement).
+\\[discuss-leave-mtg] Quit (leave) meeting."
+ (interactive)
+ (kill-all-local-variables)
+ (setq major-mode 'discuss-trn-mode)
+ (setq mode-name "Discuss (transaction)")
+ (use-local-map discuss-trn-mode-map)
+ (setq buffer-read-only t)
+ (make-local-variable 'discuss-current-transaction)
+ (setq discuss-current-transaction 0)
+ (make-local-variable 'discuss-highest-seen)
+ (setq discuss-highest-seen 0)
+ (make-local-variable 'discuss-output-last-file)
+ (make-local-variable 'discuss-meeting)
+ (make-local-variable 'discuss-meeting-info)
+ (setq discuss-output-last-file nil)
+ (run-hooks 'discuss-trn-hooks))
+
+
+;;; Main entry point: Start up a slave process and listen for requests.
+
+(defun discuss (&optional arg)
+ "Enter discuss mode for emacs and list meetings."
+ (interactive "P")
+ (message "Starting discuss....")
+ (if (not (and (get-buffer discuss-main-buffer)
+ (buffer-name (get-buffer discuss-main-buffer))
+ (> (length discuss-meeting-list) 0)))
+ (progn
+ (switch-to-buffer (get-buffer-create discuss-main-buffer))
+ (discuss-mtgs-mode)
+ (setq discuss-meeting-list nil)
+ (if arg
+ (message "Hit `g' and enter a meeting name.")
+ (discuss-lsm)))
+ (switch-to-buffer discuss-main-buffer)))
+
+;;; Entry points typically entered through key sequences.
+
+(defun discuss-list-meetings ()
+ "List discuss meetings."
+ (interactive)
+ (message "Listing meetings..."
+ (switch-to-buffer (get-buffer discuss-main-buffer))
+ (let ((buffer-read-only nil))
+ (erase-buffer))
+ (discuss-send-cmd "(gml)\n" 'discuss-end-of-lsm 'discuss-read-form)))
+
+(fset 'discuss-lsm (symbol-function 'discuss-list-meetings))
+
+;;(defmacro cadr (x)
+;; (list 'car (list 'cdr x)))
+(defun cadr (x) (car (cdr x)))
+
+;;(defmacro caddr (x)
+;; (` (car (cdr (cdr (, x))))))
+(defun caddr (x) (car (cdr (cdr x))))
+
+;;(defmacro cddr (x)
+;; (` (cdr (cdr (, x)))))
+(defun cddr (x) (cdr (cdr x)))
+
+(defun discuss-lsm-1 (entry)
+ (insert (cond ((eq (car entry) 1)
+ " c ")
+ ((stringp (car entry))
+ " X ")
+ (t
+ " "))
+ (cadr entry))
+ (cond ((stringp (car entry))
+ (insert " (" (car entry) ")"))
+ ((cddr entry)
+ (mapcar 'discuss-lsm-2 (cddr entry))))
+ (insert "\n"))
+
+(defun discuss-lsm-2 (name)
+ (insert ", " name))
+
+;; Compliments of jik
+(defun flatten (list)
+ (if (eq nil list) '())
+ (let* ((newlist (copy-list (car list)))
+ (restoflist (cdr list))
+ (pointer newlist))
+ (while (not (eq nil restoflist))
+ (while (not (eq nil (cdr pointer)))
+ (setq pointer (cdr pointer)))
+ (setcdr pointer (copy-list (car restoflist)))
+ (setq restoflist (cdr restoflist)))
+ newlist))
+
+(defun copy-list (list)
+ (if (eq nil list)
+ '()
+ (cons (car list) (copy-list (cdr list)))))
+
+(defun discuss-end-of-lsm ()
+ (message "Listing meetings...")
+ (let ((orig-buffer (current-buffer)))
+ (set-buffer discuss-main-buffer)
+ (setq discuss-meeting-list (apply 'vector discuss-form))
+ (setq discuss-meeting-completion-list
+ (mapcar (function (lambda (x) (cons x 0)))
+ (flatten (mapcar 'cdr discuss-form))))
+ (let ((buffer-read-only nil))
+ (erase-buffer)
+ (goto-char (point-min))
+ (insert " Flags Meeting name\n"
+ " ----- ------------\n")
+ (mapcar 'discuss-lsm-1 discuss-form)
+ (goto-char (point-max))
+ (backward-delete-char 1))
+ (goto-char (point-min))
+ (forward-line 2)
+ (set-buffer orig-buffer))
+ (message "Listing meetings...done."))
+
+(defun discuss-find-meeting (meeting)
+ (let ((i 0)
+ (eol (length discuss-meeting-list)))
+ (while (and (< i eol)
+ (not (member meeting (aref discuss-meeting-list i))))
+ (setq i (1+ i)))
+ (if (< i eol)
+ (aref discuss-meeting-list i)
+ nil)))
+
+
+(defun discuss-quit ()
+ "Exits Discuss mode."
+ (interactive)
+ (if discuss-cur-mtg-buf
+ (discuss-leave-mtg))
+ (discuss-restart)
+ (switch-to-buffer (other-buffer))
+ (bury-buffer discuss-main-buffer))
+
+(defun discuss-goto (&optional meeting)
+ "Go to a meeting."
+ (interactive (list (if (or current-prefix-arg
+ (not (equal (buffer-name) discuss-main-buffer))
+ (= (point) 1))
+ (completing-read "Meeting name: "
+ discuss-meeting-completion-list
+ nil t ""))))
+ (if (not meeting)
+ (let ((curline (- (count-lines 1 (min (1+ (point)) (point-max))) 3)))
+ (if (< curline 0)
+ (error "Not looking at a meeting."))
+ (setq meeting (cadr (aref discuss-meeting-list
+ curline)))))
+ (if (not (and discuss-cur-mtg-buf
+ (buffer-name discuss-cur-mtg-buf)
+ (equal discuss-current-meeting meeting)))
+ (progn
+ (if discuss-cur-mtg-buf
+ (discuss-leave-mtg))
+ (setq discuss-cur-mtg-buf
+ (get-buffer-create (if discuss-use-short-meeting-name
+ (caddr (discuss-find-meeting meeting))
+ (concat "*" meeting " meeting*"))))
+ (switch-to-buffer discuss-cur-mtg-buf)
+ (discuss-trn-mode))
+ (progn
+ (set-buffer discuss-cur-mtg-buf)
+ (discuss-send-cmd (format "(ss %d %s)\n"
+ discuss-highest-seen
+ discuss-meeting)
+ nil
+ (if discuss-old-ss nil 'discuss-read-form))))
+ (switch-to-buffer discuss-cur-mtg-buf)
+ (setq discuss-meeting meeting)
+ (setq discuss-current-meeting meeting) ;;; denigrated
+ (setq discuss-output-last-file (concat discuss-meeting ".trans"))
+ (discuss-send-cmd (format "(gmi %s)\n" meeting)
+ 'discuss-end-of-goto 'discuss-read-form
+ 'discuss-goto-error))
+
+(defun discuss-goto-error ()
+ "Called to back out when there's an error in going to a meeting."
+ (kill-buffer (buffer-name discuss-cur-mtg-buf))
+ (setq discuss-cur-mtg-buf nil)
+ (setq discuss-current-meeting nil)
+ (switch-to-buffer discuss-main-buffer))
+
+(defun discuss-end-of-goto ()
+ (let ((last (nth 4 discuss-form)))
+ ;
+ ; To have gotten this far, we must have had status access....
+ ;
+ (if (not (string-match "r" (nth 10 discuss-form)))
+ (progn
+ (discuss-goto-error)
+ (error "Insufficient access to read transactions in %s"
+ (nth 1 discuss-current-meeting-info))))
+ (setq discuss-highest-seen (nth 11 discuss-form))
+ (if (> discuss-highest-seen last)
+ (progn
+ (beep)
+ (message "Warning! Last seen transaction higher than last transaction")
+ (sit-for 1)
+ (setq discuss-highest-seen last)))
+ (message "%s meeting: %d new, %d last."
+ (cadr discuss-form)
+ (- last discuss-highest-seen)
+ last)
+ (set-buffer discuss-cur-mtg-buf)
+ (setq discuss-current-meeting-info discuss-form)
+ (cond ((not (zerop discuss-current-transaction)) nil)
+ ((zerop (nth 3 discuss-form)) (error "Empty meeting."))
+ ((or (zerop discuss-highest-seen) (>= discuss-highest-seen last))
+ (discuss-show-trn last))
+ (t (discuss-send-cmd (format "(nut %d %s)\n"
+ discuss-highest-seen
+ discuss-meeting)
+; 'discuss-next-goto
+ '(lambda () (progn (discuss-show-trn
+ (car discuss-form))))
+ 'discuss-read-form)))))
+
+;(defun discuss-next-goto ()
+; (discuss-show-trn (car discuss-form)))
+
+;;;
+;;; This is broken --- only works in transaction buffer. Of course, this is
+;;; is the only place that you'd really want to use it. Actually, it
+;;; sort of works in meetings-mode too, but only barely so.
+;;; This should be cleaned up. -- TYT
+;;;
+(defun discuss-stat (&optional meeting)
+ "Go to a meeting."
+ (interactive (list (if (eq (current-buffer) discuss-cur-mtg-buf)
+ discuss-meeting
+ (if (or current-prefix-arg
+ (not (equal (buffer-name) discuss-main-buffer))
+ (= (point) 1))
+ (completing-read "Meeting name: "
+ discuss-meeting-completion-list
+ nil t "")))))
+ (if (not meeting)
+ (let ((curline (- (count-lines 1 (min (1+ (point)) (point-max))) 3)))
+ (if (< curline 0)
+ (error "Not looking at a meeting."))
+ (setq meeting (cadr (aref discuss-meeting-list
+ curline)))))
+ (discuss-send-cmd (format "(gmi %s)\n" meeting)
+ 'discuss-end-of-stat 'discuss-read-form))
+
+(defun discuss-end-of-stat ()
+ (setq discuss-current-meeting-info discuss-form)
+ (setq discuss-meeting-info discuss-form)
+ (let ((last (nth 4 discuss-form))
+ (highest-seen (nth 11 discuss-form)))
+ (if (and (equal (cadr discuss-form) discuss-current-meeting)
+ (not (= discuss-highest-seen 0)))
+ (setq highest-seen discuss-highest-seen)) ;; This is wrong...
+ (message "%s meeting: %d new, %d last."
+ (cadr discuss-form)
+ (- last highest-seen)
+ last)))
+
+(defun discuss-show-trn-with-headers ()
+ "Show transaction with full headers."
+ (interactive)
+ (discuss-show-trn discuss-current-transaction t))
+
+(defun discuss-show-trn (trn-num &optional show-headers)
+ "Show transaction number N (prefix argument)."
+ (interactive
+ (list (if (not (numberp current-prefix-arg))
+ (string-to-int (read-string "Transaction number: "))
+ current-prefix-arg)))
+ (if (and trn-num (numberp trn-num))
+ (progn
+ (setq discuss-show-num trn-num)
+ (setq discuss-show-headers show-headers)
+ (discuss-send-cmd (format "(gtfc %d %d %s)\n"
+ discuss-cur-direction
+ trn-num
+ discuss-current-meeting)
+ 'discuss-end-show-trn
+ 'discuss-read-form))))
+
+(defun discuss-end-show-trn ()
+ (let ((transaction-file (car discuss-form)))
+ (set-buffer discuss-cur-mtg-buf)
+ (setq discuss-current-transaction-info (cdr discuss-form))
+ (setq discuss-current-transaction discuss-show-num)
+ (setq discuss-highest-seen (max discuss-highest-seen
+ discuss-current-transaction))
+ (if (>= discuss-current-transaction
+ (nth 4 discuss-current-meeting-info))
+ (let ((discuss-in-show-trn t))
+ (discuss-update)
+ (discuss-block-til-ready nil)))
+
+ (setq mode-line-process (format " %d/%d"
+ discuss-current-transaction
+ (nth 4 discuss-current-meeting-info)))
+ (let ((buffer-read-only nil))
+ (erase-buffer)
+ (insert-file-contents transaction-file)
+ (if (not discuss-show-headers)
+ (discuss-clean-msg-header))
+ (goto-char (point-min)))
+ (if (= (caddr discuss-current-transaction-info) 0)
+ (progn
+ (message "Last transaction in %s" discuss-meeting)
+ (discuss-mark-read-meeting discuss-meeting)
+ (discuss-next-meeting t)))
+ (make-local-variable 'font-lock-defaults)
+ (setq font-lock-defaults '(discuss-font-lock-keywords t))
+ (run-hooks 'discuss-show-trn-hooks)))
+
+(defun discuss-clean-msg-header ()
+ (save-excursion
+ (goto-char (point-min))
+ (next-line 2) ; skip title and subject
+ (if (looking-at "From \\|[^ ]+:")
+ (let ((start (point)))
+ (save-restriction
+ (if (search-forward "\n\n" nil 'move)
+ (backward-char 1))
+ (narrow-to-region start (point))
+ (goto-char (point-min))
+ (condition-case nil
+ (if discuss-visible-headers
+ (while (< (point) (point-max))
+ (cond ((looking-at discuss-visible-headers)
+ (re-search-forward "\n[^ \t]"))
+ (t
+ (delete-region (point)
+ (progn (re-search-forward "\n[^ \t]")
+ (- (point) 1))))))
+ (while (re-search-forward discuss-invisible-headers nil t)
+ (beginning-of-line)
+ (delete-region (point) (progn (re-search-forward "\n[^ \t]")
+ (- (point) 1)))
+ (beginning-of-line)))
+ (error nil)))))))
+
+(defun discuss-update ()
+ "Update Discuss display to show new transactions."
+ (interactive)
+ (discuss-send-cmd (format "(gmi %s)\n" discuss-meeting)
+ 'discuss-end-of-update 'discuss-read-form))
+
+(defun discuss-end-of-update ()
+ (setq discuss-current-meeting-info discuss-form)
+ (save-excursion
+ (set-buffer discuss-cur-mtg-buf)
+ (if (not discuss-in-show-trn)
+ (discuss-show-trn discuss-current-transaction))))
+
+(defun discuss-next-trn ()
+ "Show next transaction."
+ (interactive)
+ (if (or (not discuss-current-transaction)
+ (= discuss-current-transaction 0))
+ (error "Not looking at transactions")
+ (let ((next (caddr discuss-current-transaction-info)))
+ (if (= next 0)
+ (progn
+ (discuss-send-cmd (format "(gti %d %s)\n"
+ discuss-current-transaction
+ discuss-current-meeting)
+ nil 'discuss-read-form)
+ (discuss-block-til-ready nil)
+ (setq discuss-current-transaction-info discuss-form)
+ (if (= 0 (caddr discuss-current-transaction-info))
+ (if discuss-DWIM
+ (discuss-leave-mtg)
+ (error "No next transaction."))
+ (progn
+ (setq discuss-cur-direction 1)
+ (discuss-send-cmd (format "(im %s)\n" discuss-current-meeting)
+ nil 'discuss-read-form)
+ (discuss-next-trn))))
+ (progn
+ (setq discuss-cur-direction 1)
+ (discuss-show-trn next))))))
+
+(defun discuss-prev-trn ()
+ "Show previous transaction."
+ (interactive)
+ (if (or (not discuss-current-transaction)
+ (= discuss-current-transaction 0))
+ (error "Not looking at transactions")
+ (let ((prev (cadr discuss-current-transaction-info)))
+ (if (= prev 0)
+ (error "No previous transaction.")
+ (progn
+ (setq discuss-cur-direction 2)
+ (discuss-show-trn prev))))))
+
+
+(defun discuss-nref ()
+ "Show next transaction in chain."
+ (interactive)
+ (if (or (not discuss-current-transaction)
+ (= discuss-current-transaction 0))
+ (error "Not looking at transactions")
+ (let ((nref (nth 4 discuss-current-transaction-info)))
+ (if (= nref 0)
+ (error "No next reference.")
+ (progn
+ (setq discuss-cur-direction 3)
+ (discuss-show-trn nref))))))
+
+(defun discuss-pref ()
+ "Show previous transaction in chain."
+ (interactive)
+ (if (or (not discuss-current-transaction)
+ (= discuss-current-transaction 0))
+ (error "Not looking at transactions")
+ (let ((pref (nth 3 discuss-current-transaction-info)))
+ (if (= pref 0)
+ (error "No previous reference.")
+ (progn
+ (setq discuss-cur-direction 4)
+ (discuss-show-trn pref))))))
+
+(defun discuss-lref ()
+ "Show last transaction in chain."
+ (interactive)
+ (if (or (not discuss-current-transaction)
+ (= discuss-current-transaction 0))
+ (error "Not looking at transactions")
+ (let ((lref (nth 6 discuss-current-transaction-info)))
+ (if (= lref 0)
+ (error "No last reference.")
+ (progn
+ (setq discuss-cur-direction 4)
+ (discuss-show-trn lref))))))
+
+(defun discuss-fref ()
+ "Show first transaction in chain."
+ (interactive)
+ (if (or (not discuss-current-transaction)
+ (= discuss-current-transaction 0))
+ (error "Not looking at transactions")
+ (let ((fref (nth 5 discuss-current-transaction-info)))
+ (if (= fref 0)
+ (error "No first reference.")
+ (progn
+ (setq discuss-cur-direction 3)
+ (discuss-show-trn fref))))))
+
+(defun discuss-first-trn ()
+ "Show first transaction of meeting."
+ (interactive)
+ (let ((first (nth 3 discuss-current-meeting-info)))
+ (setq discuss-cur-direction 1)
+ (discuss-show-trn first)))
+
+(defun discuss-last-trn ()
+ "Show last transaction of meeting."
+ (interactive)
+ (let ((last (nth 4 discuss-current-meeting-info)))
+ (setq discuss-cur-direction 2)
+ (discuss-show-trn last)))
+
+(defun discuss-toggle-trn-flag ()
+ "Toggle the per-transaction flag."
+ (interactive)
+ (let ((old-flag (nth 13 discuss-current-transaction-info)))
+ (if old-flag
+ (progn
+ (discuss-send-cmd (format "(it %d %s)\n"
+ discuss-current-transaction
+ discuss-meeting)
+ 'nil 'discuss-read-form)
+ (message "Toggling the transaction flag....")
+ (discuss-send-cmd (format "(sfl %d %d %s)\n"
+ (logxor old-flag 2)
+ discuss-current-transaction
+ discuss-meeting)
+ 'discuss-end-of-toggle 'discuss-read-form)))))
+
+(defun discuss-end-of-toggle ()
+ (discuss-show-trn discuss-current-transaction)
+ (message ""))
+
+(defun discuss-set-seen-and-leave-mtg (arg)
+ "Sets the highest transaction number seen in the current meeting to
+the argument or the current transaction and leaves the meeting."
+ (interactive "p")
+ (if (not discuss-cur-mtg-buf)
+ (error "Not looking at a meeting.")
+ (if current-prefix-arg
+ (setq discuss-highest-seen arg)
+ (setq discuss-highest-seen discuss-current-transaction))
+ (discuss-next-meeting t t)
+ (discuss-mark-unread-meeting discuss-current-meeting)
+ (discuss-leave-mtg)))
+
+(defun discuss-leave-mtg ()
+ "Leave the current discuss meeting."
+ (interactive)
+ (if (buffer-name discuss-cur-mtg-buf)
+ (progn
+ (set-buffer discuss-cur-mtg-buf)
+ (if (not (= discuss-highest-seen 0))
+ (discuss-send-cmd (format "(ss %d %s)\n"
+ discuss-highest-seen
+ discuss-meeting)
+ nil
+ (if discuss-old-ss nil 'discuss-read-form)))
+ (kill-buffer (buffer-name discuss-cur-mtg-buf))
+ (setq discuss-cur-mtg-buf nil)
+ (setq discuss-current-meeting nil)
+ (if (and (not discuss-keep-discuss-ls) (get-buffer "*discuss-ls*"))
+ (progn
+ (delete-windows-on (get-buffer "*discuss-ls*"))
+ (bury-buffer (get-buffer "*discuss-ls*"))))
+ (switch-to-buffer discuss-main-buffer))))
+
+(defun discuss-catchup (&optional meeting)
+ "Mark all messages in the current meeting as read."
+ (interactive
+ (list (or discuss-cur-mtg-buf
+ (if (or current-prefix-arg (= (point) 1))
+ (completing-read "Meeting name: "
+ discuss-meeting-completion-list
+ nil t "")))))
+
+ ;; If meeting is nil or a string, we are in the *meetings* buffer. Use the
+ ;; meeting on the current line.
+ (if (or (not meeting) (stringp meeting))
+ (let ((curline (- (count-lines 1 (min (1+ (point)) (point-max))) 3)))
+ (if meeting
+ nil
+ (if (< curline 0)
+ (error "Not looking at a meeting."))
+ (setq meeting (cadr (aref discuss-meeting-list curline))))
+ (message "Catching up in %s" meeting)
+ (discuss-send-cmd (format "(gmi %s)\n" meeting)
+ 'discuss-end-of-catchup 'discuss-read-form))
+ ;; Otherwise just set discuss-highest-seen.
+ (setq discuss-highest-seen (nth 6 discuss-current-meeting-info))
+ (discuss-mark-read-meeting (nth 1 discuss-current-meeting-info))
+ (discuss-next-meeting t)
+ (discuss-leave-mtg)
+ ))
+
+(defun discuss-end-of-catchup ()
+ (let ((meeting (nth 1 discuss-form))
+ (highest (nth 6 discuss-form)))
+ (discuss-send-cmd (format "(ss %d %s)\n" highest meeting)
+ nil
+ (if discuss-old-ss nil 'discuss-read-form))
+ (discuss-mark-read-meeting meeting)
+ (discuss-next-meeting t)
+ (message "Done.")
+ ))
+
+(defun discuss-delete-trn-backwards (trn-num)
+ (interactive
+ (cond (current-prefix-arg
+ (if discuss-cur-mtg-buf
+ (list (string-to-int (read-input "Transaction to delete: ")))
+ (error "Not currently visiting a meeting.")))
+ ((eq (current-buffer) discuss-cur-mtg-buf)
+ (list discuss-current-transaction))
+ (t
+ (if discuss-cur-mtg-buf
+ (list (string-to-int (read-input "Transaction to delete: ")))
+ (error "Not currently visiting a meeting.")))
+ ))
+ (discuss-delete-trn trn-num t))
+
+(defun discuss-delete-trn (trn-num &optional backwards)
+ (interactive
+ (cond (current-prefix-arg
+ (if discuss-cur-mtg-buf
+ (list (string-to-int (read-input "Transaction to delete: ")))
+ (error "Not currently visiting a meeting.")))
+ ((eq (current-buffer) discuss-cur-mtg-buf)
+ (list discuss-current-transaction))
+ (t
+ (if discuss-cur-mtg-buf
+ (list (string-to-int (read-input "Transaction to delete: ")))
+ (error "Not currently visiting a meeting.")))
+ ))
+ ;; Probably we should make sure the transaction can be deleted before
+ ;; asking this question, but the cache code is too confusing...
+ (if (and discuss-safe-delete
+ (not (yes-or-no-p (format "Delete transaction %d? " trn-num))))
+ nil
+ (let ((info discuss-current-transaction-info)
+ other)
+ (if (and info
+ (= discuss-current-transaction trn-num))
+ (progn
+ (if backwards
+ (setq discuss-current-transaction (cadr info)
+ other (caddr info))
+ (setq discuss-current-transaction (caddr info)
+ other (cadr info)))
+ (if (= discuss-current-transaction 0)
+ (setq discuss-current-transaction other))
+ (if (= discuss-current-transaction 0)
+ (progn
+ (message "No more transactions in meeting!")
+ (beep)))
+ ))
+ (discuss-send-cmd (format "(itn %d %s)\n"
+ trn-num
+ discuss-meeting)
+ 'nil 'discuss-read-form)
+ (message "Deleting %d...." trn-num)
+ (discuss-send-cmd (format "(dt %d %s)\n" trn-num discuss-meeting)
+ 'discuss-end-del-trn 'discuss-read-form))))
+
+(defun discuss-end-del-trn ()
+ (message "Done.")
+ (discuss-show-trn discuss-current-transaction))
+
+(defun discuss-retrieve-trn (trn-num)
+ "Retrieve a deleted transaction."
+ (interactive "nTransaction to retrieve: ")
+ (setq discuss-current-transaction trn-num)
+ (message "Retrieving %d...." trn-num)
+ (discuss-send-cmd (format "(rt %d %s)\n" trn-num discuss-meeting)
+ 'discuss-end-rt-trn 'discuss-read-form))
+
+(defun discuss-end-rt-trn ()
+ (message "Done.")
+ (discuss-send-cmd (format "(itn %d %s)\n"
+ discuss-current-transaction
+ discuss-meeting)
+ 'nil 'discuss-read-form)
+ (discuss-show-trn discuss-current-transaction))
+
+(defun discuss-la-invalidate-relatives (trn-num)
+ (discuss-send-cmd (format "(itn %d %s)\n"
+ trn-num
+ discuss-meeting)
+ 'nil 'discuss-read-form)
+ )
+
+(defun discuss-format-trn-num (num)
+ (format "[%s%d]"
+ (cond ((<= num 9) "000")
+ ((<= num 99) "00")
+ ((<= num 999) "0")
+ (t ""))
+ num))
+
+;;; Discuss DWIM
+(defun discuss-scroll-up ()
+ (interactive)
+ (condition-case err
+ (scroll-up nil)
+ (error
+ (if (and discuss-DWIM
+ (equal err '(end-of-buffer)))
+ (if (equal discuss-current-transaction
+ (nth 4 discuss-current-meeting-info))
+ (discuss-leave-mtg)
+ (discuss-next-trn))
+ (signal (car err) (cdr err))))))
+
+
+;;; Routines for communicating with slave process. Since things are
+;;; asynchronous when communicating with the process, we may have to
+;;; spin on a flag if something else is in progress.
+;;;
+;;; The optional arguments to discuss-send-cmd are a function to be
+;;; called by the filter-func when the end-of-operation is seen and a
+;;; function to be used as a filter (it gets called with the process and
+;;; a string when the process outputs something.
+;;;
+;;; It is possible that if discuss-in-progress gets set to true
+;;; accidentally that things could get deadlocked; I think that can be
+;;; avoided in the purely, but I'm not sure.. (knowing how easily elisp
+;;; breaks unexpectedly, I should put in a lock timeout and a function to
+;;; unlock things).
+
+(defun discuss-restart ()
+ "Used to save the world when edsc gets hung or dies...
+
+Flushes the discuss cache and destroys the edsc process."
+ (interactive)
+ (if (and discuss-process
+ (equal (process-status discuss-process) 'run))
+ (send-string discuss-process "(quit)\n"))
+ (setq discuss-process nil
+ discuss-in-progress nil))
+
+(defun discuss-send-cmd (cmd &optional end-func filter-func unwind-func)
+ "Send an command to the edsc process."
+ (if (not discuss-process)
+ (let ((process-connection-type nil))
+ (if (not (file-exists-p discuss-pathname))
+ (error "%s does not exist!" discuss-pathname))
+ (setq discuss-process (start-process "discuss-shell"
+ nil
+ discuss-pathname))
+ (set-process-sentinel discuss-process 'discuss-edsc-sentinel)
+ (discuss-send-cmd "(gpv)\n" nil 'discuss-read-form)
+ (discuss-block-til-ready t)
+ (let* ((discuss-vers (cond (discuss-form
+ (car discuss-form))
+ ((equal discuss-error
+ "Unimplemented operation")
+ 10)
+ (t
+ (error "Edsc returned error: %s"
+ discuss-error))))
+ (ver-string
+ (format "%d.%d"
+ (/ discuss-vers 10)
+ (- discuss-vers (* (/ discuss-vers 10) 10)))))
+ (if (> 23 discuss-vers)
+ (setq discuss-version-string "")
+ (setq discuss-version-string (cadr discuss-form)))
+ (setq discuss-old-ss (= 23 discuss-vers))
+ (if (> 25 discuss-vers)
+ (progn
+ (discuss-restart)
+ (error
+ "Bad version of edsc (%s) --- you need at least version 2.5."
+ ver-string))
+ (progn
+ (message "Started edsc process.... version %s %s)"
+ ver-string discuss-version-string)
+ (sit-for 1))))))
+
+ ;; block until we have control over things..
+ (discuss-block-til-ready t)
+ (if filter-func
+ (setq discuss-in-progress t))
+ (save-excursion
+ (setq discuss-debug-cmd cmd)
+ (setq discuss-reading-string "")
+ (setq discuss-cont end-func)
+ (setq discuss-unwind unwind-func)
+ (if filter-func (set-process-filter discuss-process filter-func))
+ (send-string discuss-process cmd)))
+
+(defun discuss-block-til-ready (verbose)
+ "Block, waiting until the previous operation for discuss finished.
+If VERBOSE is non-nil, then print a message that we're waiting for the
+discuss server while we spin-block."
+ (if discuss-in-progress
+ (progn
+ (while discuss-in-progress
+ (if verbose
+ (message "waiting for discuss..."))
+ (sit-for 1)
+ (accept-process-output))
+ (message ""))))
+
+;;;
+;;; This gets called when something nasty has happened to our edsc.
+;;;
+(defun discuss-edsc-sentinel (process signal)
+ (let ((buffer (process-buffer process))
+ (status (process-status process)))
+ (cond
+ ((eq status 'exit)
+ (discuss-restart))
+ ((eq status 'signal)
+ (ding)
+ (message "discuss-shell: %s."
+ (substring signal 0 -1))
+ (discuss-restart))
+ )))
+
+;;; Routines to filter the output from discuss.
+;;; These are pretty simplistic
+
+(defun discuss-read-form (process string)
+ (setq discuss-reading-string (concat discuss-reading-string string))
+ (let* ((end-of-line (string-match "\n" discuss-reading-string)))
+ (if end-of-line
+ (let ((flag-char (substring discuss-reading-string 0 1))
+ (first-line (substring discuss-reading-string 1
+ end-of-line)))
+ (setq discuss-error nil)
+ (cond ((equal flag-char "-") ; warning
+ (message first-line)
+ (setq discuss-reading-string
+ (substring discuss-reading-string (1+ end-of-line)))
+ (discuss-read-form process ""))
+ ((equal flag-char "l") ; Sun os ld.so warning crock
+ (message "l" first-line)
+ (setq discuss-reading-string
+ (substring discuss-reading-string (1+ end-of-line)))
+ (discuss-read-form process ""))
+ ((equal flag-char ";") ; error
+ (setq discuss-error first-line)
+ (message discuss-error)
+ (ding)
+ (setq discuss-reading-string
+ (substring discuss-reading-string (1+ end-of-line)))
+ (setq discuss-in-progress nil)
+ (setq discuss-form nil)
+ (if discuss-unwind
+ (apply discuss-unwind nil)))
+ (t
+ (setq discuss-form
+ (car (read-from-string (concat "(" first-line))))
+ (setq discuss-in-progress nil)
+ (if discuss-cont
+ (apply discuss-cont nil))))))))
+
+
+; run this at each load
+(defun discuss-initialize nil
+ (setq discuss-version
+ "$Id: discuss.el,v 1.41 1999-06-04 14:11:13 danw Exp $")
+
+;;;
+;;; Lots of autoload stuff....
+;;;
+
+(autoload 'discuss-talk (concat discuss-source-dir "discuss-enter")
+ "Enter a new discuss transaction." t)
+
+(autoload 'discuss-reply (concat discuss-source-dir "discuss-enter")
+ "Reply to an existing discuss transaction." t)
+
+(autoload 'discuss-randrp (concat discuss-source-dir "discuss-enter")
+ "Random reply in a meeting." t)
+
+(autoload 'discuss-ls (concat discuss-source-dir "discuss-ls")
+ "List the headings of the transactions in a meeting." t)
+
+(autoload 'discuss-list-acl (concat discuss-source-dir "discuss-acl")
+ "List the ACL of a meeting." t)
+
+(autoload 'discuss-forward (concat discuss-source-dir "discuss-misc")
+ "Forward a transaction via mail." t)
+
+(autoload 'discuss-forward-to-meeting
+ (concat discuss-source-dir "discuss-misc")
+ "Forward a transaction to another discuss meeting." t)
+
+(autoload 'discuss-reply-by-mail (concat discuss-source-dir "discuss-misc")
+ "Forward a transaction via mail." t)
+
+(autoload 'discuss-add-mtg (concat discuss-source-dir "discuss-misc")
+ "Add a discuss meeting" t)
+
+(autoload 'discuss-del-mtg (concat discuss-source-dir "discuss-misc")
+ "Delete a discuss meeting" t)
+
+;;; Keymaps, here at the end, where the trash belongs..
+
+(if discuss-mtgs-mode-map
+ nil
+ (setq discuss-mtgs-mode-map (make-keymap))
+ (suppress-keymap discuss-mtgs-mode-map)
+ (define-key discuss-mtgs-mode-map "a" 'discuss-add-mtg)
+ (define-key discuss-mtgs-mode-map "d" 'discuss-del-mtg)
+ (define-key discuss-mtgs-mode-map "n" 'discuss-forward-meeting)
+ (define-key discuss-mtgs-mode-map "p" 'discuss-prev-meeting)
+ (define-key discuss-mtgs-mode-map " " 'discuss-next-meeting)
+ (define-key discuss-mtgs-mode-map "\177" 'discuss-prev-meeting)
+ (define-key discuss-mtgs-mode-map "l" 'discuss-lsm)
+ (define-key discuss-mtgs-mode-map "g" 'discuss-goto)
+ (define-key discuss-mtgs-mode-map "q" 'discuss-quit)
+ (define-key discuss-mtgs-mode-map "s" 'discuss-stat)
+ (define-key discuss-mtgs-mode-map "c" 'discuss-catchup)
+ (define-key discuss-mtgs-mode-map "?" 'describe-mode))
+
+(if discuss-trn-mode-map
+ nil
+ (setq discuss-trn-mode-map (make-keymap))
+ (suppress-keymap discuss-trn-mode-map)
+ (define-key discuss-trn-mode-map "." 'discuss-update)
+ (define-key discuss-trn-mode-map "," 'discuss-show-trn-with-headers)
+ (define-key discuss-trn-mode-map " " 'discuss-scroll-up)
+ (define-key discuss-trn-mode-map "\177" 'scroll-down)
+ (define-key discuss-trn-mode-map "n" 'discuss-next-trn)
+ (define-key discuss-trn-mode-map "p" 'discuss-prev-trn)
+ (define-key discuss-trn-mode-map "d" 'discuss-delete-trn)
+ (define-key discuss-trn-mode-map "R" 'discuss-retrieve-trn)
+ (define-key discuss-trn-mode-map "\M-n" 'discuss-nref)
+ (define-key discuss-trn-mode-map "\M-p" 'discuss-pref)
+ (define-key discuss-trn-mode-map "g" 'discuss-show-trn)
+ (define-key discuss-trn-mode-map "<" 'discuss-first-trn)
+ (define-key discuss-trn-mode-map ">" 'discuss-last-trn)
+ (define-key discuss-trn-mode-map "f" 'discuss-forward)
+ (define-key discuss-trn-mode-map "F" 'discuss-toggle-trn-flag)
+ (define-key discuss-trn-mode-map "h" 'discuss-trn-summary)
+ (define-key discuss-trn-mode-map "\e\C-h" 'discuss-trn-summary)
+ (define-key discuss-trn-mode-map "t" 'discuss-talk)
+ (define-key discuss-trn-mode-map "r" 'discuss-reply)
+ (define-key discuss-trn-mode-map "\C-c\C-r" 'discuss-randrp)
+ (define-key discuss-trn-mode-map "\M-r" 'discuss-reply-by-mail)
+ (define-key discuss-trn-mode-map "\C-o" 'discuss-trn-output)
+ (define-key discuss-trn-mode-map "i" 'discuss-trn-input)
+ (define-key discuss-trn-mode-map "q" 'discuss-leave-mtg)
+ (define-key discuss-trn-mode-map "?" 'describe-mode)
+ (define-key discuss-trn-mode-map "s" 'discuss-stat)
+ (define-key discuss-trn-mode-map "a" 'discuss-add-mtg)
+ (define-key discuss-trn-mode-map "\C-d" 'discuss-delete-trn-backwards)
+ (define-key discuss-trn-mode-map "\M-f" 'discuss-fref)
+ (define-key discuss-trn-mode-map "\M-l" 'discuss-lref)
+ (define-key discuss-trn-mode-map "=" 'discuss-ls)
+ (define-key discuss-trn-mode-map "c" 'discuss-catchup)
+ (define-key discuss-trn-mode-map "l" 'discuss-set-seen-and-leave-mtg)
+)
+
+
+ (fmakunbound 'discuss-initialize)
+ ) ;end of discuss-initialize
+(discuss-initialize)
+
+;;; discuss-trn-output mostly stolen from rmail-output...
+;;; converted by [eichin:19881026.1505EST]
+;(defvar discuss-output-last-file nil
+; "*Default file for discuss saves")
+
+(defun discuss-trn-output (file-name)
+ "Append this message to file named FILE-NAME."
+ (interactive
+ (list
+ (read-file-name
+ (concat "Append to: (default "
+ (file-name-nondirectory discuss-output-last-file)
+ ") ")
+ (file-name-directory discuss-output-last-file)
+ discuss-output-last-file)))
+ (setq file-name (expand-file-name file-name))
+ (setq discuss-output-last-file file-name)
+ (let ((discuss-trn-buf (current-buffer))
+ (tembuf (get-buffer-create " discuss-trn-output"))
+ (case-fold-search t))
+ (save-excursion
+ (set-buffer tembuf)
+ (erase-buffer)
+ (insert-buffer-substring discuss-trn-buf)
+ (goto-char (point-max))
+ (insert "\n") ;other modifying here as well
+ (append-to-file (point-min) (point-max) file-name))
+ (kill-buffer tembuf)))
+
+;;;
+;;; this is just a quick hack, but I don't see an `better' way to do it...
+;;;
+(defun discuss-next-meeting (&optional quiet dontgo)
+ "Find the next changed meeting in the discuss *meetings* buffer, or wrap."
+ (interactive)
+ (let ((buffer (current-buffer)))
+ (set-buffer discuss-main-buffer)
+ ;; If we're in DWIM mode, and we're currently looking at a changed
+ ;; meeting, go to it.
+ (if (and discuss-DWIM
+ (not dontgo)
+ (re-search-backward "^ c" (save-excursion (beginning-of-line)
+ (point))
+ t))
+ (discuss-goto)
+ (if (not (re-search-forward "^ c " nil t))
+ (progn
+ (goto-char (point-min))
+ (if (not (re-search-forward "^ c " nil t))
+ (if (not quiet)
+ (message "No new meetings, try discuss-lsm instead."))
+ ))))
+ (set-buffer buffer)))
+
+(defun discuss-forward-meeting (&optional quiet)
+ "Find the next changed meeting in the discuss *meetings* buffer, or wrap."
+ (interactive)
+ (let ((discuss-DWIM nil))
+ (discuss-next-meeting quiet)))
+
+(defun discuss-prev-meeting ()
+ "Find the previous changed meeting in the discuss *meetings* buffer, or wrap."
+ (interactive)
+ (beginning-of-line)
+ (if (not (re-search-backward "^ c " nil t))
+ (progn
+ (goto-char (point-max))
+ (if (not (re-search-backward "^ c " nil t))
+ (message "No new meetings, try discuss-lsm instead.")
+ )))
+ (forward-char 3))
+
+(defun discuss-mark-read-meeting (meeting &optional inschar)
+ "Mark a meeting as read on the discuss-mode listing. An optional
+argument means insert that character instead of a space before the
+meeting (usually a c)."
+ (setq inschar (or inschar ?\ ))
+ (save-excursion
+ (set-buffer discuss-main-buffer)
+ (goto-char (point-min))
+ (if (not (re-search-forward (concat " " (regexp-quote meeting)
+ "\\(,\\|$\\)")
+ nil t))
+ (progn
+ (ding)
+ (message "Couldn't update changed flag for meeting %s." meeting))
+ (beginning-of-line)
+ (forward-char 1)
+ (let ((buffer-read-only nil))
+ (insert-char inschar 1)
+ (delete-char 1)
+ ))))
+
+(defun discuss-mark-unread-meeting (meeting)
+ "Mark a meeting as unread on the discuss-mode listing."
+ (discuss-mark-read-meeting meeting ?c))
Property changes on: trunk/athena/bin/discuss/edsc/discuss.el.in
___________________________________________________________________
Name: svn:mergeinfo
+