async.el 33.2 KB
Newer Older
Linus Tolke's avatar
Linus Tolke committed
1
2
;;;;;
;;;;; $Id$
3
;;;;; Copyright (C) 1991-2002  Lysator Academic Computer Association.
Linus Tolke's avatar
Linus Tolke committed
4
;;;;;
5
;;;;; This file is part of the LysKOM Emacs LISP client.
Linus Tolke's avatar
Linus Tolke committed
6
7
8
;;;;; 
;;;;; LysKOM is free software; you can redistribute it and/or modify it
;;;;; under the terms of the GNU General Public License as published by 
9
;;;;; the Free Software Foundation; either version 2, or (at your option) 
Linus Tolke's avatar
Linus Tolke committed
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
;;;;; any later version.
;;;;; 
;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT
;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
;;;;; FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
;;;;; for more details.
;;;;; 
;;;;; You should have received a copy of the GNU General Public License
;;;;; along with LysKOM; see the file COPYING.  If not, write to
;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN,
;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, 
;;;;; MA 02139, USA.
;;;;;
;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. 
;;;;;
Per Cederqvist's avatar
.    
Per Cederqvist committed
25
26
27
28
29
30
31
32
33
34
35
36
37
;;;; ================================================================
;;;; ================================================================
;;;;
;;;; File: async.el
;;;;
;;;; These functions implement a nice service that give the user
;;;; continuous messages about what other users are doing and what
;;;; is happening inside the lyskom server.
;;;;
;;;; Author: Linus Tolke
;;;; Entry:  Inge Wallin
;;;;

38
39
40
41
(setq lyskom-clientversion-long 
      (concat lyskom-clientversion-long
	      "$Id$\n"))

Per Cederqvist's avatar
.    
Per Cederqvist committed
42

David Byers's avatar
David Byers committed
43
44
45
46
47
(defun lyskom-is-ignoring-async (buffer message &rest args)
  (save-excursion 
    (set-buffer buffer)
    (let ((tmp (assq message lyskom-ignoring-async-list)))
      (and tmp (equal args (cdr tmp))))))
David Byers's avatar
David Byers committed
48

Per Cederqvist's avatar
.    
Per Cederqvist committed
49
50
51
52
53
(defun lyskom-parse-async (tokens buffer)
  "Parse an asynchronous message from the server.
The message consists of TOKENS tokens. Unknown messages are skipped.
Actions are taken to perform the various tasks that is required on reciept of
an asynchronous message.
David Byers's avatar
David Byers committed
54
55
56
57
58
59

If variable `kom-presence-messages-in-echo-area' is non-nil or some
minibuffer editing is going on then nothing is printed on the message
area. This function is called with the lyskom-unparsed-buffer as
current-buffer. All calls using the lyskom-variables have to be made
using the buffer BUFFER.
Per Cederqvist's avatar
.    
Per Cederqvist committed
60
61
62
63
64
65

Be careful when editing this. All parsing is done with the buffer this
function is called with as the current-buffer, while all calls from
this function shall be with current-buffer the BUFFER."
  (let ((msg-no (lyskom-parse-num)))
    (cond
David Byers's avatar
David Byers committed
66
67
     ((or (eq msg-no 0)
          (eq msg-no 15)) ; New text
Per Cederqvist's avatar
.    
Per Cederqvist committed
68
      (let* ((text-no (lyskom-parse-num))
David Byers's avatar
David Byers committed
69
70
71
	     (text-stat (if (eq msg-no 0)
                            (lyskom-parse-text-stat-old text-no)
                          (lyskom-parse-text-stat text-no))))
Per Cederqvist's avatar
.    
Per Cederqvist committed
72
	(lyskom-save-excursion
73
74
	 (set-buffer buffer)
	 (lyskom-async-new-text text-stat)))) ;
Per Cederqvist's avatar
.    
Per Cederqvist committed
75
76

     ((eq msg-no 1)			; Logout (obsolete)
77
      (lyskom-skip-tokens tokens))
Per Cederqvist's avatar
.    
Per Cederqvist committed
78
79
80
81
82
83
84
85
86
87

     ((eq msg-no 2)			; Login, obsolete.
      (lyskom-skip-tokens tokens))

     ((eq msg-no 3)			; Conference deleted
      (lyskom-skip-tokens tokens))

     ((eq msg-no 4)			; Conference created
      (lyskom-skip-tokens tokens))

88
89
     ((eq msg-no 5)			; A person or conference has
					; changed name.
Per Cederqvist's avatar
.    
Per Cederqvist committed
90
91
92
93
      (let ((conf-no (lyskom-parse-num))
	    (old-name (lyskom-parse-string))
	    (new-name (lyskom-parse-string)))
	(lyskom-save-excursion
94
95
96
97
	 (set-buffer buffer)
	 (if (and lyskom-pers-no (= conf-no lyskom-pers-no))
	     (lyskom-format-insert-before-prompt 
	      'you-changed-name-to
98
	      new-name
99
	      (lyskom-default-button 'conf conf-no)))
100
101
102
103
104
105
	 (let ((cached-stat (cache-get-conf-stat conf-no))
               (cached-ustat (cache-get-uconf-stat conf-no)))
	   (when cached-stat
             (set-conf-stat->name cached-stat new-name))
	   (when cached-ustat
             (set-uconf-stat->name cached-ustat new-name)))
106
107
	 (cond
	  ((lyskom-is-in-minibuffer))
David Byers's avatar
David Byers committed
108
          ((lyskom-show-presence conf-no kom-presence-messages-in-echo-area)
109
110
111
	   (lyskom-message "%s" (lyskom-format 'name-has-changed-to-name
					       old-name new-name))))
	 (cond
David Byers's avatar
David Byers committed
112
	  ((lyskom-show-presence conf-no kom-presence-messages-in-buffer)
113
114
115
116
	   (lyskom-format-insert-before-prompt
	    'name-has-changed-to-name-r 
	    old-name 
	    new-name
117
118
119
120
121
	    (lyskom-default-button 'conf conf-no))))

         ;; Update in the mship-edit buffer

         (lp--maybe-update-entry-for-conf conf-no))))
David Byers's avatar
David Byers committed
122

Per Cederqvist's avatar
.    
Per Cederqvist committed
123
     ((eq msg-no 6)			;i_am_on - something is moving
David Byers's avatar
David Byers committed
124
125
      (lyskom-parse-who-info))

Per Cederqvist's avatar
.    
Per Cederqvist committed
126
127
     ((eq msg-no 7)			; Database is syncing.
      (lyskom-save-excursion
128
129
       (set-buffer buffer)
       ;; I removed the test for kom-presence-messages /david
130
131
       (if (and (not (lyskom-is-in-minibuffer))
                kom-show-sync-messages)
132
133
134
135
136
137
138
139
140
141
	   (lyskom-message "%s" (lyskom-get-string 'database-sync)))
       (setq mode-line-process (lyskom-get-string 'mode-line-saving))
       (setq lyskom-is-saving t)
       ;; I guess the following two lines could be replaced by
       ;; force-mode-line-update in a modern emacs.
       (set-buffer-modified-p (buffer-modified-p))
       (sit-for 0)
       (if (not lyskom-pending-calls)
	   (initiate-get-time 'async nil))))
     
Per Cederqvist's avatar
.    
Per Cederqvist committed
142
     ((eq msg-no 8)			; Forced leave conference
David Byers's avatar
David Byers committed
143
      (let ((conf-no (lyskom-parse-num)))
David Byers's avatar
David Byers committed
144
        (unless (lyskom-is-ignoring-async buffer 8 conf-no)
David Byers's avatar
David Byers committed
145
146
147
148
149
150
          (lyskom-save-excursion
              (set-buffer buffer)
              (initiate-get-conf-stat 'follow
                                      'lyskom-async-forced-leave-conf
                                      conf-no
                                      conf-no)))))
151
     
Per Cederqvist's avatar
.    
Per Cederqvist committed
152
153
     ((eq msg-no 9)			; A person has logged in
      (let ((pers-no (lyskom-parse-num))
David Byers's avatar
David Byers committed
154
155
156
	    ;;;(session-no (lyskom-parse-num))
            )
        (lyskom-parse-num)
Per Cederqvist's avatar
.    
Per Cederqvist committed
157
	(lyskom-save-excursion
158
159
160
	 (set-buffer buffer)
	 (if (and lyskom-pers-no
		  (not (zerop lyskom-pers-no))
161
		  (/= pers-no lyskom-pers-no)) ; Don't show myself.
162
163
164
165
166
167
168
	     (initiate-get-conf-stat 'follow
				     'lyskom-show-logged-in-person
				     pers-no))
	 )))

     ;; msg-no 10 is the old broadcast message. No longer used.
     
Per Cederqvist's avatar
.    
Per Cederqvist committed
169
170
171
     ((eq msg-no 11)
      (lyskom-save-excursion
       (set-buffer buffer)
172
       (lyskom-insert-before-prompt (lyskom-get-string-sol 'lyskom-is-full))
173
174
175
       ))
     
     
Per Cederqvist's avatar
.    
Per Cederqvist committed
176
177
178
179
180
181
     ((eq msg-no 12)			; Message to the user (or everybody)
      (let ((recipient (lyskom-parse-num))
	    (sender (lyskom-parse-num))
	    (message (lyskom-parse-string)))
	(lyskom-save-excursion
	 (set-buffer buffer)
182
183
184
185
186
187
188
189
190
191
192
	 (if (zerop recipient)
	     (initiate-get-conf-stat 'async
				     'lyskom-handle-personal-message
				     sender
				     0
				     message)
	   (lyskom-collect 'async)
	   (initiate-get-conf-stat 'async nil sender)
	   (initiate-get-conf-stat 'async nil recipient)
	   (lyskom-use 'async 'lyskom-handle-personal-message message)))))
     
Per Cederqvist's avatar
.    
Per Cederqvist committed
193
194
195
196
     ((eq msg-no 13)			; New logout
      (let ((pers-no (lyskom-parse-num))
	    (session-no (lyskom-parse-num)))
	(lyskom-save-excursion
197
198
199
200
	 (set-buffer buffer)
	 (if (and lyskom-pers-no
		  (not (zerop lyskom-pers-no))
		  (/= lyskom-pers-no pers-no)
David Byers's avatar
David Byers committed
201
		  (or (lyskom-show-presence pers-no kom-presence-messages-in-echo-area)
David Byers's avatar
David Byers committed
202
		      (lyskom-show-presence pers-no kom-presence-messages-in-buffer)))
203
204
	     (initiate-get-conf-stat 'follow
				     'lyskom-show-logged-out-person
David Byers's avatar
David Byers committed
205
				     pers-no session-no)))))
Per Cederqvist's avatar
.    
Per Cederqvist committed
206

David Byers's avatar
David Byers committed
207
     ((eq msg-no 14)                    ; Deleted text
208
      (let* ((text-no (lyskom-parse-num))
David Byers's avatar
David Byers committed
209
210
211
212
213
214
215
216
217
            (text-stat (lyskom-parse-text-stat text-no)))
        (lyskom-save-excursion
         (set-buffer buffer)
         (lyskom-async-deleted-text text-stat))))

     ((eq msg-no 16)                    ; New recipient
      (let ((text-no (lyskom-parse-num))
            (conf-no (lyskom-parse-num))
            (misc-type (lyskom-parse-num)))
218
219
220
221
222
223
224
225
226
227
228
229
230
        (cond ((eq misc-type 0) (setq misc-type 'RECPT))
              ((eq misc-type 1) (setq misc-type 'CC-RECPT))
              ((eq misc-type 15) (setq misc-type 'BCC-RECPT)))
        (when (symbolp misc-type)
          (lyskom-save-excursion
            (set-buffer buffer)
            (cache-del-text-stat text-no)
            (cache-del-conf-stat conf-no)
            (initiate-get-text-stat 'follow
                                    'lyskom-async-new-recipient
                                    text-no
                                    text-no conf-no misc-type)
            ))))
David Byers's avatar
David Byers committed
231
232
233
234
235
236
237
238
239

     ((eq msg-no 17)                    ; Deleted recipient
      (let ((text-no (lyskom-parse-num))
            (conf-no (lyskom-parse-num))
            (misc-type (lyskom-parse-num)))
        (lyskom-save-excursion
         (set-buffer buffer)
          (cache-del-conf-stat conf-no)
          (cache-del-text-stat text-no)
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
          ;; FIXME: Code here.
          ;; FIXME: This implementation sucks. There is no need to
          ;; FIXME:   remove the text from the cache. Just modify it.
          ;; FIXME: If we cache maps somewhere, we'll want to remove
          ;; FIXME:   the text from the appropriate map.
          ;; FIXME: If we want to get *really* picky, and the user is
          ;; FIXME:   doing a review texts to conference, and this text
          ;; FIXME:   has been found, remove this text from those
          ;; FIXME:   lists too (probably not worth the effort).
          ;; FIXME: The text should be removed from the reading lists
          ;; FIXME:   if it is there because we are reading the conf
          ;; FIXME:   that is being removed. Take care not to lose
          ;; FIXME:   any comments to it though...
          ;; FIXME: The unread counter for the conference should be
          ;; FIXME:   decreased like it is in async-deleted-text (i hope).
255
          (lyskom-ignore misc-type)
David Byers's avatar
David Byers committed
256
257
258
259
260
         )))

     ((eq msg-no 18)                    ; New membership
      (let ((pers-no (lyskom-parse-num))
            (conf-no (lyskom-parse-num)))
David Byers's avatar
David Byers committed
261
        (unless (lyskom-is-ignoring-async buffer 18 pers-no conf-no)
David Byers's avatar
David Byers committed
262
263
264
265
          (lyskom-save-excursion
              (set-buffer buffer)
              (cache-del-pers-stat pers-no)
              (cache-del-conf-stat conf-no)
David Byers's avatar
David Byers committed
266
              (when (eq pers-no lyskom-pers-no)
David Byers's avatar
David Byers committed
267
268
                (lyskom-collect 'follow)
                (initiate-get-conf-stat 'follow nil conf-no)
269
                (initiate-query-read-texts 'follow nil pers-no conf-no t 0)
David Byers's avatar
David Byers committed
270
271
272
                (lyskom-use 'follow 'lyskom-async-new-membership pers-no conf-no))
            ))))

273
274
275
276
277
278
279
280
281
282
283
284
     ((eq msg-no 19)                    ; async-new-user-area
      (let* ((pers-no (lyskom-parse-num))
             (old-user-area (lyskom-parse-num))
             (new-user-area (lyskom-parse-num)))
        (lyskom-save-excursion
          (set-buffer buffer)
          (when (eq pers-no lyskom-pers-no)
            (initiate-get-pers-stat 'follow 
                                    'lyskom-async-new-user-area
                                    pers-no
                                    old-user-area
                                    new-user-area)))))
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304

     ((eq msg-no 20)                    ; async-new-presentation
      (let* ((conf-no (lyskom-parse-num))
             (old-pres (lyskom-parse-num))
             (new-pres (lyskom-parse-num)))
        (lyskom-ignore old-pres)
        (when (cache-get-conf-stat conf-no)
          (set-conf-stat->presentation (cache-get-conf-stat conf-no)
                                       new-pres)
         (lp--maybe-update-entry-for-conf conf-no))))

     ((eq msg-no 21)                    ; async-new-motd
      (let* ((conf-no (lyskom-parse-num))
             (old-motd (lyskom-parse-num))
             (new-motd (lyskom-parse-num)))
        (lyskom-ignore old-motd)
        (when (cache-get-conf-stat conf-no)
          (set-conf-stat->msg-of-day (cache-get-conf-stat conf-no)
                                     new-motd))))

Per Cederqvist's avatar
.    
Per Cederqvist committed
305
306
307
     (t
      (lyskom-skip-tokens tokens)))))

308
309
310
311
312
313
314
315
316
317
318
319
(defun lyskom-async-new-user-area (pers-stat old-user-area new-user-area)
  (when pers-stat
    (let ((need-reread (and (eq lyskom-pers-no (pers-stat->pers-no pers-stat))
                            (not (eq lyskom-current-user-area new-user-area)))))
  ;; Update the cache
  (set-pers-stat->user-area pers-stat new-user-area)
  ;; Re-read
  (when (and need-reread
             new-user-area
             (not (zerop new-user-area)))
    (initiate-get-text 'follow 'lyskom-read-options-eval new-user-area)))))

Per Cederqvist's avatar
.    
Per Cederqvist committed
320

David Byers's avatar
David Byers committed
321
322
323
324
(defun lyskom-async-forced-leave-conf (conf-stat conf-no)
  (if conf-stat
      (lyskom-format-insert-before-prompt 'no-longer-member conf-stat)
    (lyskom-format-insert-before-prompt 'no-longer-member-n conf-no))
David Byers's avatar
David Byers committed
325
  (lyskom-remove-membership conf-no)
David Byers's avatar
David Byers committed
326
  (when (eq conf-no lyskom-current-conf)
327
    (lyskom-leave-current-conf))
David Byers's avatar
David Byers committed
328
329
330
331
332
333
334
  (read-list-delete-read-info conf-no lyskom-to-do-list)
  (lyskom-update-prompt))

(defun lyskom-async-new-membership (conf-conf-stat
                                    membership
                                    pers-no 
                                    conf-no)
David Byers's avatar
David Byers committed
335
336
337
  ;; Are we already members?

  (when membership
David Byers's avatar
David Byers committed
338
339
    (let ((cur-mship (lyskom-try-get-membership conf-no t))
          (mship-type (membership->type membership)))
David Byers's avatar
David Byers committed
340
341
      (unless cur-mship
        (lyskom-format-insert-before-prompt 
David Byers's avatar
David Byers committed
342
343
344
345
346
         (cond ((membership-type->invitation mship-type)
                'have-become-invited-member)
               ((membership-type->passive mship-type)
                'have-become-passive-member)
               (t 'have-become-member))
David Byers's avatar
David Byers committed
347
348
349
         conf-conf-stat))

    (cond ((membership-type->passive (membership->type membership))
David Byers's avatar
David Byers committed
350
           (lyskom-replace-membership membership)
David Byers's avatar
David Byers committed
351
           (when (eq conf-no lyskom-current-conf)
352
             (lyskom-leave-current-conf))
David Byers's avatar
David Byers committed
353
354
355
356
357
358
359
360
361
           (read-list-delete-read-info conf-no lyskom-to-do-list)
           (lyskom-update-prompt))

          ;; Already a member. Perhaps the priority changed.
          ;; Update the cache. The reading list is probably also
          ;; not quite correct since the priority might have changed
          ;; FIXME: Maybe fix this.

          (cur-mship
David Byers's avatar
David Byers committed
362
           (lyskom-replace-membership membership))
David Byers's avatar
David Byers committed
363
364
365

          ;; Not a member. Completely new. Deal with it.
          (t (lyskom-add-membership membership conf-no))))))
David Byers's avatar
David Byers committed
366
367
    

David Byers's avatar
David Byers committed
368
(defun lyskom-show-presence (num flag)
369
370
371
  "Returns non-nil if presence messages for NUM should be displayed
according to the value of FLAG."
  (cond ((null flag) nil)
David Byers's avatar
David Byers committed
372
        ((eq flag 'friends) (memq num kom-friends))
373
374
375
        ((eq flag 'morons) (memq num kom-morons))
        ((eq flag 'friends-and-morons) (or (memq num kom-friends)
                                           (memq num kom-morons)))
David Byers's avatar
David Byers committed
376
377
        ((listp flag) (memq num flag))
        (t t)))
378
379


Per Cederqvist's avatar
.    
Per Cederqvist committed
380
381
(defun lyskom-show-logged-in-person (conf-stat)
  "Visa p} kommandoraden vem som loggat in."
382
383
384
385
  (let ((server (or (cdr (lyskom-string-assoc
                          lyskom-server-name
                          (append kom-server-aliases
                                  kom-builtin-server-aliases)))
386
                    lyskom-server-name)))
387
388
389
    (cond
     ((lyskom-is-in-minibuffer))
     ((lyskom-show-presence (conf-stat->conf-no conf-stat)
David Byers's avatar
David Byers committed
390
                            kom-presence-messages-in-echo-area)
391
392
393
394
      (lyskom-message
       "%s"
       (lyskom-format 'has-entered
                      (or conf-stat
395
                          (lyskom-get-string 'unknown-person))
396
397
                      server
                      ))))
398

399
400
401
402
403
404
    (cond
     ((lyskom-show-presence (conf-stat->conf-no conf-stat)
                            kom-presence-messages-in-buffer)
      (if conf-stat
          (lyskom-format-insert-before-prompt 'has-entered-r conf-stat
                                              (and kom-text-properties
405
                                                   `(face ,kom-presence-face))
406
407
                                              server)
        (lyskom-format-insert-before-prompt 'has-entered-r
408
                                            (lyskom-get-string 'unknown-person)
409
                                            (and kom-text-properties
410
                                                 `(face ,kom-presence-face))
411
                                            server))))))
Per Cederqvist's avatar
.    
Per Cederqvist committed
412
413
414
415


(defun lyskom-show-logged-out-person (conf-stat session-no)
  "Visa p} kommandoraden vem som loggat ut."
416
417
418
419
  (let ((server (or (cdr (lyskom-string-assoc
                          lyskom-server-name
                          (append kom-server-aliases
                                  kom-builtin-server-aliases)))
420
                    lyskom-server-name)))
Per Cederqvist's avatar
.    
Per Cederqvist committed
421
422
  (cond
   ((lyskom-is-in-minibuffer))
423
   ((lyskom-show-presence (conf-stat->conf-no conf-stat) 
David Byers's avatar
David Byers committed
424
                          kom-presence-messages-in-echo-area)
David Kågedal's avatar
David Kågedal committed
425
426
427
    (lyskom-message
     "%s"
     (lyskom-format 'has-left (or conf-stat
428
				  (lyskom-get-string 'unknown-person))
429
                    server))))
Per Cederqvist's avatar
.    
Per Cederqvist committed
430
  (cond
431
432
   ((lyskom-show-presence (conf-stat->conf-no conf-stat)
                          kom-presence-messages-in-buffer)
David Kågedal's avatar
David Kågedal committed
433
434
435
    (if conf-stat
	(lyskom-format-insert-before-prompt 'has-left-r conf-stat
					    (and kom-text-properties
436
						 `(face ,kom-presence-face))
437
                                            server)
David Kågedal's avatar
David Kågedal committed
438
      (lyskom-format-insert-before-prompt 'has-left-r
439
					  (lyskom-get-string 'unknown-person)
David Kågedal's avatar
David Kågedal committed
440
					  (and kom-text-properties
441
					       `(face ,kom-presence-face))
442
                                          server))))))
Per Cederqvist's avatar
.    
Per Cederqvist committed
443
444


445

Per Cederqvist's avatar
.    
Per Cederqvist committed
446
447
(defun lyskom-is-in-minibuffer ()
  "Returns non-nil if I am using the minibuffer for some reading."
David Kågedal's avatar
David Kågedal committed
448
  (or lyskom-inhibit-minibuffer-messages
449
      cursor-in-echo-area
David Kågedal's avatar
David Kågedal committed
450
      (not (zerop (minibuffer-depth)))))
Per Cederqvist's avatar
.    
Per Cederqvist committed
451
452


453
454
(defun lyskom-show-personal-message (sender recipient message 
                                            &optional when nobeep)
Per Cederqvist's avatar
.    
Per Cederqvist committed
455
  "Insert a personal message into the lyskom buffer.
Joel Rosdahl's avatar
Joel Rosdahl committed
456
Args: SENDER: conf-stat for the person sending the message.
457
458
      RECIPIENT: 0 if this message is for everybody, otherwise the conf-stat
                 of the recipient.
459
      MESSAGE: A string containing the message.
460
      WHEN: Optional time of arrival. A lyskom time structure.
461
462
463
464
465
466
467
468
469
470
471
      NOBEEP: True means don't beep. No matter what."
  (lyskom-insert-personal-message sender recipient message when nobeep)
  (setq lyskom-last-personal-message-sender 
        (if (stringp sender) sender (conf-stat->name sender)))
  (setq lyskom-last-group-message-recipient 
        (if (and recipient
                 (not (eq 0 recipient))
                 (not (eq (conf-stat->conf-no recipient)
                          lyskom-pers-no)))
            (conf-stat->name recipient)
          nil))
David Byers's avatar
David Byers committed
472
473
  (run-hooks 'lyskom-personal-message-hook)
  (run-hooks 'kom-personal-message-hook))
474

475

476
477
(defun lyskom-insert-personal-message (sender recipient message
                                              &optional when nobeep)
478
  "Insert a personal message in the current buffer.
479
Arguments: SENDER RECIPIENT MESSAGE.
Joel Rosdahl's avatar
Joel Rosdahl committed
480
481
482
SENDER is a conf-stat (possibly nil).
RECIPIENT is 0 if the message is public, otherwise the conf-stat of the
recipient.
483
MESSAGE is a string containing the message.
484
485
WHEN, if given, is the time when the message arrived. It must be a lyskom
time structure.
486
Non-nil NOBEEP means don't beep."
487
  (lyskom-handle-as-personal-message
488
489
490
491
492
493
494
495
496
497
   (lyskom-format-as-personal-message sender recipient message when nobeep)
   (conf-stat->conf-no sender) 
   nil))

(defun lyskom-format-as-personal-message (sender 
                                          recipient
                                          message
                                          &optional when nobeep)
  "Formats a personal message, returning it as a string.
Arguments: SENDER RECIPIENT MESSAGE.
Joel Rosdahl's avatar
Joel Rosdahl committed
498
499
500
SENDER is a conf-stat (possibly nil).
RECIPIENT is 0 if the message is public, otherwise the conf-stat of the
recipient.
501
MESSAGE is a string containing the message.
502
503
WHEN, if given, is the time when the message arrived. It must be a lyskom
time structure.
504
Non-nil NOBEEP means don't beep."
505
  (let ((lyskom-last-text-format-flags nil)
506
507
        (now (lyskom-current-client-time)))
    (when (null when) (setq when (lyskom-current-client-time)))
508
    (if (or kom-show-personal-message-date
509
510
511
            (not (eq (time->mday when) (time->mday now)))
            (not (eq (time->mon when) (time->mon now)))
            (not (eq (time->year when) (time->year now))))
512
513
514
        (setq when (let ((kom-print-relative-dates nil))
                     (lyskom-format-time 'date-and-time when)))
      (setq when (lyskom-format-time 'time when)))
515

516
517
518
    (setq nobeep (or nobeep (and kom-ansaphone-on
                                 kom-silent-ansaphone)))

David Kågedal's avatar
David Kågedal committed
519
520
521
522
523
    (cond ((or (null recipient)		; Have been seen to be nil when
                                        ; listing recorded
                                        ; messages. Should it be?
                                        ; /davidk
	       (eq recipient 0))	; Public message
524
           (if (not nobeep) (lyskom-beep kom-ding-on-common-messages sender))
525
           (lyskom-format (lyskom-get-string-sol 'message-broadcast)
526
527
528
529
530
                          (cond
                           ((stringp sender) sender)
                           (sender sender)
                           (t (lyskom-get-string 'unknown)))
                          message
David Byers's avatar
David Byers committed
531
                          when
532
                          (when kom-async-highlight-dashed-lines
533
534
                            `(face ,(or kom-async-dashed-lines-face
                                        lyskom-default-async-dashed-lines-face)))
535
                          (when kom-async-highlight-text-body
536
537
                            `(face ,(or kom-async-text-body-face
                                        lyskom-default-async-text-body-face)))))
538
          ((= (conf-stat->conf-no recipient) lyskom-pers-no) ; Private
539
           (if (not nobeep) (lyskom-beep kom-ding-on-personal-messages sender))
540
           (lyskom-format (lyskom-get-string-sol 'message-from)
541
542
543
544
545
                          (cond
                           ((stringp sender) sender)
                           (sender sender)
                           (t (lyskom-get-string 'unknown)))
                          message
David Byers's avatar
David Byers committed
546
                          when
547
                          (when kom-async-highlight-dashed-lines
548
549
                            `(face ,(or kom-async-dashed-lines-face
                                        lyskom-default-async-dashed-lines-face)))
550
                          (when kom-async-highlight-text-body
551
552
                            `(face ,(or kom-async-text-body-face
                                        lyskom-default-async-text-body-face)))))
553
          (t                            ; Group message
554
           (if (not nobeep) (lyskom-beep kom-ding-on-group-messages recipient))
555
           (lyskom-format (lyskom-get-string-sol 'message-from-to)
556
557
558
                          message
                          (cond
                           ((stringp sender) sender)
David Byers's avatar
David Byers committed
559
                           (sender  sender)
560
561
562
                           (t (lyskom-get-string 'unknown)))
                          (cond
                           ((stringp recipient) recipient)
David Byers's avatar
David Byers committed
563
                           (recipient recipient)
564
                           (t (lyskom-get-string 'unknown)))
David Byers's avatar
David Byers committed
565
                          when
566
                          (when kom-async-highlight-dashed-lines
567
568
                            `(face ,(or kom-async-dashed-lines-face
                                        lyskom-default-async-dashed-lines-face)))
569
                          (when kom-async-highlight-text-body
570
571
                            `(face ,(or kom-async-text-body-face
                                        lyskom-default-async-text-body-face))))))))
572

573
574

  
575
576
577
578
(defun lyskom-handle-as-personal-message (string from &optional filter)
  "Insert STRING as a personal message and beep if not from me and
supposed to. The buffer, is chosen according to the
kom-show-personal-messages-in-buffer variable value. The text is
579
converted, before insertion."
580
581
582
583
584
  (if (and filter
           (or
            (eq 0 (string-match "^Remote-command: [0-9]+ [0-9]+\n" string))
            (eq 0 (string-match "^Auto-reply:\n" string))))
      nil
585
586
587
588
589
590
591
592
    (let ((pop kom-pop-personal-messages))
      (lyskom-save-excursion
       (cond
	((eq kom-show-personal-messages-in-buffer t)
	 (lyskom-insert-before-prompt string)
	 (if pop (display-buffer (current-buffer))))
	((null kom-show-personal-messages-in-buffer))
	(t
593
594
595
596
597
598
599
600
601
602
603
604
605
606
         (let ((inhibit-read-only t))
           (let ((message-buffer
                  (car (lyskom-buffers-of-category 'personal-messages))))
             (if message-buffer
                 (set-buffer message-buffer)
               (set-buffer (lyskom-get-buffer-create 
                            'personal-messages 
                            kom-show-personal-messages-in-buffer t))
               (lyskom-view-mode)
               (setq buffer-read-only t)))
           (goto-char (point-max))
           (lyskom-insert string )
           (if pop
               (save-selected-window
David Byers's avatar
David Byers committed
607
608
                 (select-window (lyskom-display-buffer (current-buffer)
                                                       (not (eq pop t))))
609
610
                 (goto-char (point-max))
                 (recenter -1))))))))))
611
  
Per Cederqvist's avatar
.    
Per Cederqvist committed
612

613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630

;;; ================================================================
;;; New recipient

;;; The text stat and might have been cached and thus invalid. Check
;;; for this. The conf-stat for the conf-no is almost certainly 
;;; invalid.

(defun lyskom-async-new-recipient (text-stat text-no conf-no misc-type)
  "Handle a new recipient message"

  ;; Check if we are added. A new letter!
  (when (and (eq  conf-no lyskom-pers-no)
             (not (eq (text-stat->author text-stat) lyskom-pers-no)))
    (lyskom-beep kom-ding-on-new-letter))

  ;; If the text is read in another conference, mark it as read here too
  ;; unless the new recipient is the mailbox
631
632
  (if (and kom-mark-read-texts-as-read-in-new-recipient
           (lyskom-text-read-at-least-once-p text-stat t)
633
634
635
636
637
638
639
640
641
642
643
644
           (not (eq conf-no lyskom-pers-no)))
      (initiate-mark-as-read 'follow
                             nil
                             conf-no 
                             (list text-no))

    ;; Text is previously unread or in the mailbox
    (let ((local-no nil))
      (lyskom-traverse misc-info (text-stat->misc-info-list text-stat)
        (when (and (eq (misc-info->type misc-info) misc-type)
                   (eq (misc-info->recipient-no misc-info) conf-no))
          (setq local-no (misc-info->local-no misc-info))))
David Byers's avatar
David Byers committed
645
646
647
648
649
650
651
652
      (when local-no
        (initiate-get-conf-stat 'async 'lyskom-add-new-text
                                conf-no
                                text-no
                                local-no)
        (lyskom-prefetch-text-all text-no)
        (lyskom-run 'async 'lyskom-default-new-recipient-hook text-stat)
        (lyskom-run 'async 'lyskom-prefetch-and-print-prompt)))))
653
654
655
656
657

(defun lyskom-default-new-recipient-hook (text-stat)
  (when (and (not lyskom-dont-change-prompt) ;We shall change it
             (not lyskom-executing-command)) ;We have time to do it.
    (lyskom-update-prompt))
David Byers's avatar
David Byers committed
658
659
  (run-hooks 'lyskom-new-recipient-hook)
  (run-hooks 'kom-new-recipient-hook))
660
661
662



Per Cederqvist's avatar
.    
Per Cederqvist committed
663
;;; ================================================================
David Byers's avatar
David Byers committed
664
;;;            Functions for dealing with a new or deleted text
Per Cederqvist's avatar
.    
Per Cederqvist committed
665
666
667
668


(defun lyskom-default-new-text-hook (text-stat)
  "Print a message if the user was waiting. Change the prompt. run hooks."
669
670
  (if (and (not lyskom-dont-change-prompt) ;We shall change it
	   (not lyskom-executing-command)) ;We have time to do it.
671
      (lyskom-update-prompt))
672

Per Cederqvist's avatar
.    
Per Cederqvist committed
673
674
  (let ((no-message nil))
    (run-hooks 'lyskom-new-text-hook)
David Byers's avatar
David Byers committed
675
    (run-hooks 'kom-new-text-hook)
Per Cederqvist's avatar
.    
Per Cederqvist committed
676
677
678
679
  
    (if (and (not no-message)
	     lyskom-is-waiting
	     (not (lyskom-is-in-minibuffer)))
680
681
	(lyskom-message "%s" (lyskom-format 'text-is-created
					    (text-stat->text-no text-stat))))))
Per Cederqvist's avatar
.    
Per Cederqvist committed
682

David Byers's avatar
David Byers committed
683
684
685
686
687
(defun lyskom-default-deleted-text-hook (text-stat)
  "Update the prompt. Run hooks"
  (if (and (not lyskom-dont-change-prompt) ;We shall change it
	   (not lyskom-executing-command)) ;We have time to do it.
      (lyskom-update-prompt))
David Byers's avatar
David Byers committed
688
689
  (run-hooks 'lyskom-deleted-text-hook)
  (run-hooks 'kom-deleted-text-hook))
David Byers's avatar
David Byers committed
690

Per Cederqvist's avatar
.    
Per Cederqvist committed
691
692
693
694
695
(defun lyskom-async-new-text (text-stat)
  "Take care of a message that a new text has been created."
  (cache-del-pers-stat (text-stat->author text-stat)) ;+++Borde {ndra i cachen i st{llet.
  
  (lyskom-traverse
696
697
698
      misc-info (text-stat->misc-info-list text-stat)
    (let ((type (misc-info->type misc-info)))
      (cond
699
       ((memq type lyskom-recpt-types-list)
700
701
	;; add on lyskom-reading-list and lyskom-to-do-list if
	;; this recipient is a recipient that has been checked.
702
703
704
705
706
707
	(if (and (eq  (misc-info->recipient-no misc-info)
                      lyskom-pers-no)
                 (not (eq (text-stat->author text-stat)
                          lyskom-pers-no)))
            (lyskom-beep kom-ding-on-new-letter))
        (initiate-get-conf-stat 'async 'lyskom-add-new-text
708
709
710
711
712
713
714
715
716
717
718
719
				(misc-info->recipient-no misc-info)
				(text-stat->text-no text-stat)
				(misc-info->local-no misc-info)))
       ((eq type 'COMM-TO)
	(cache-del-text-stat (misc-info->comm-to misc-info)))
       ((eq type 'FOOTN-TO)
	(cache-del-text-stat (misc-info->footn-to misc-info)))
       (t
	(signal 'lyskom-internal-error
		(list 'lyskom-async-new-text
		      "Unexpected misc-info in new text "
		      type))))))
Per Cederqvist's avatar
.    
Per Cederqvist committed
720

721
  (lyskom-prefetch-text-stat-all text-stat)
722

723
  ;; Give a message if the user is waiting. Update the prompt.
724
725
726
  (lyskom-run 'async 'lyskom-default-new-text-hook text-stat)

  (lyskom-run 'async 'lyskom-prefetch-and-print-prompt))
727
728


David Byers's avatar
David Byers committed
729
730
731
732
733
734
(defun lyskom-async-deleted-text (text-stat)
  "Take care of a message that a text has been deleted."
      (cache-del-pers-stat (text-stat->author text-stat))
      (lyskom-traverse
          misc-info (text-stat->misc-info-list text-stat)
        (let ((type (misc-info->type misc-info)))
735
          (cond ((memq type lyskom-recpt-types-list)
David Byers's avatar
David Byers committed
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
                 (initiate-get-conf-stat 'async 'lyskom-delete-old-text
                                         (misc-info->recipient-no misc-info)
                                         text-stat
                                         (misc-info->local-no misc-info)))
                ((eq type 'COMM-TO)
                 (cache-del-text-stat (misc-info->comm-to misc-info)))
                ((eq type 'FOOTN-TO)
                 (cache-del-text-stat (misc-info->footn-to misc-info))))))
      (lyskom-run 'async 'lyskom-default-deleted-text-hook text-stat)
      (lyskom-run 'async 'lyskom-prefetch-and-print-prompt))

(defun lyskom-delete-old-text (recipient text-stat local-no)
  "RECIPIENT is a conf-stat and previous recipient of TEXT-STAT.
This call is used in response to a deleted text message"
  (when recipient

    ;; Update the cache

    (cache-del-text-stat (text-stat->text-no text-stat))
    (cache-del-text (text-stat->text-no text-stat))
    (set-conf-stat->no-of-texts 
     recipient
     (min (conf-stat->no-of-texts recipient)
          (min (conf-stat->no-of-texts recipient)
               (1- (conf-stat->no-of-texts recipient)))))

    ;; Update the read lists

    (let ((membership (lyskom-try-get-membership
                       (conf-stat->conf-no recipient))))
      (when (and membership
                 (lyskom-visible-membership membership))
768
        (read-list-delete-text (text-stat->text-no text-stat) 
David Byers's avatar
David Byers committed
769
770
771
                               lyskom-to-do-list)
        (read-list-delete-text (text-stat->text-no text-stat) 
                               lyskom-reading-list)))
David Byers's avatar
David Byers committed
772
773
774
775
776

    (lyskom-set-mode-line)))
                 

    
Per Cederqvist's avatar
.    
Per Cederqvist committed
777
778
779
780
781
782
783
784
785

(defun lyskom-add-new-text (recipient text-no local-no)
  "RECIPIENT is a conf-stat and recipient of TEXT-NO.
Args: RECIPIENT TEXT-NO LOCAL-NO.
LOCAL-NO is the texts local number in RECIPIENT. This info is used
to update the no-of-texts field in the cache.

Also add this info in lyskom-to-do-list if info about RECIPIENT as been
fetched. Does not try to print prompt or do any prefetch. That will be
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
done after all the confs has been handled.

If recipient is nil this means we are crossposting to a protected conference.
In that case, just discard this call."

  (cond
   (recipient				;+++ Annan felhantering.
    ;; Update the cache.

    (set-conf-stat->no-of-texts
     recipient
     (max (conf-stat->no-of-texts recipient)
	  (+ local-no -1
	     (- (conf-stat->first-local-no recipient)))))

    ;; Update the read-lists.

803
804
805
806
    ;; Prefetch thoughts:
    ;; We need a way to check if a conferences is fetched.
    ;; davidk /960924
    
807
808
809
    (let ((membership (lyskom-try-get-membership
		       (conf-stat->conf-no recipient))))
      (if (and membership
810
	       ;; (lyskom-conf-fetched-p (conf-stat->conf-no recipient))
811
	       (lyskom-visible-membership membership)
812
813
814
815
816
817
818
	       (not (read-list-enter-text text-no recipient
					  lyskom-to-do-list)))
	  ;; If we have already read all texts in the conference or the
	  ;; text has not been prefetched
	  (let ((info (lyskom-create-read-info
		       'CONF
		       recipient
819
		       (membership->priority membership)
820
821
822
		       (lyskom-create-text-list (list text-no)))))
	    (read-list-enter-read-info info lyskom-to-do-list)
	    (if (= lyskom-current-conf (conf-stat->conf-no recipient))
823
		(read-list-enter-read-info info lyskom-reading-list)))
David Byers's avatar
David Byers committed
824
825
826
827
828
829
830
831

        ;; We don't have the membership yet. Treat it as an unread conf
        ;; and prefetch it. This might result in two prefetches of the
        ;; same conference, but the prefetch should be able to deal with
        ;; that.
        (unless membership
          (lyskom-prefetch-one-membership (conf-stat->conf-no recipient)
                                          lyskom-pers-no))))
832
833

    (lyskom-set-mode-line))))
834
835
836
837
838


;;; Local Variables: 
;;; eval: (put 'lyskom-traverse 'lisp-indent-hook 2)
;;; end: