async.el 34 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
     ((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)
279
280
          (when (and (eq pers-no lyskom-pers-no)
                     (not (eq lyskom-current-user-area new-user-area)))
281
282
283
284
285
            (initiate-get-pers-stat 'follow 
                                    'lyskom-async-new-user-area
                                    pers-no
                                    old-user-area
                                    new-user-area)))))
286
287
288
289
290
291

     ((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)
292
293
294
295
296
297
        (lyskom-save-excursion
          (set-buffer buffer)
          (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)))))
298
299
300
301
302

     ((eq msg-no 21)                    ; async-new-motd
      (let* ((conf-no (lyskom-parse-num))
             (old-motd (lyskom-parse-num))
             (new-motd (lyskom-parse-num)))
303
304
305
306
307
308
        (lyskom-save-excursion
          (set-buffer buffer)
          (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)))))
309

310
311
312
313
314
315
316
317
318
319
320
321
322
323
     ((eq msg-no 22)                    ; async-text-aux-changes
      (let* ((text-no (lyskom-parse-num))
             (deleted-aux (lyskom-parse-aux-item-list))
             (added-aux (lyskom-parse-aux-item-list))
             (text-stat nil))
        (lyskom-save-excursion
          (set-buffer buffer)
          (setq text-stat (cache-get-text-stat text-no))
          (when text-stat
            (set-text-stat->aux-items text-stat
                                      (lyskom-aux-item-modify-list
                                       (text-stat->aux-items text-stat)
                                       deleted-aux
                                       added-aux))))))
Per Cederqvist's avatar
.  
Per Cederqvist committed
324
325
326
     (t
      (lyskom-skip-tokens tokens)))))

327
328
329
330
331
332
333
334
335
336
337
338
(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
339

David Byers's avatar
David Byers committed
340
341
342
343
(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
344
  (lyskom-remove-membership conf-no)
David Byers's avatar
David Byers committed
345
  (when (eq conf-no lyskom-current-conf)
346
    (lyskom-leave-current-conf))
David Byers's avatar
David Byers committed
347
348
349
350
351
352
353
  (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
354
355
356
  ;; Are we already members?

  (when membership
David Byers's avatar
David Byers committed
357
358
    (let ((cur-mship (lyskom-try-get-membership conf-no t))
          (mship-type (membership->type membership)))
David Byers's avatar
David Byers committed
359
360
      (unless cur-mship
        (lyskom-format-insert-before-prompt 
David Byers's avatar
David Byers committed
361
362
363
364
365
         (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
366
367
368
         conf-conf-stat))

    (cond ((membership-type->passive (membership->type membership))
David Byers's avatar
David Byers committed
369
           (lyskom-replace-membership membership)
David Byers's avatar
David Byers committed
370
           (when (eq conf-no lyskom-current-conf)
371
             (lyskom-leave-current-conf))
David Byers's avatar
David Byers committed
372
373
374
375
376
377
378
379
380
           (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
381
           (lyskom-replace-membership membership))
David Byers's avatar
David Byers committed
382
383
384

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

David Byers's avatar
David Byers committed
387
(defun lyskom-show-presence (num flag)
388
389
390
  "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
391
        ((eq flag 'friends) (memq num kom-friends))
392
393
394
        ((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
395
396
        ((listp flag) (memq num flag))
        (t t)))
397
398


Per Cederqvist's avatar
.  
Per Cederqvist committed
399
400
(defun lyskom-show-logged-in-person (conf-stat)
  "Visa p} kommandoraden vem som loggat in."
401
402
403
404
  (let ((server (or (cdr (lyskom-string-assoc
                          lyskom-server-name
                          (append kom-server-aliases
                                  kom-builtin-server-aliases)))
405
                    lyskom-server-name)))
406
407
408
    (cond
     ((lyskom-is-in-minibuffer))
     ((lyskom-show-presence (conf-stat->conf-no conf-stat)
David Byers's avatar
David Byers committed
409
                            kom-presence-messages-in-echo-area)
410
411
412
413
      (lyskom-message
       "%s"
       (lyskom-format 'has-entered
                      (or conf-stat
414
                          (lyskom-get-string 'unknown-person))
415
416
                      server
                      ))))
417

418
419
420
421
422
423
    (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
424
                                                   `(face ,kom-presence-face))
425
426
                                              server)
        (lyskom-format-insert-before-prompt 'has-entered-r
427
                                            (lyskom-get-string 'unknown-person)
428
                                            (and kom-text-properties
429
                                                 `(face ,kom-presence-face))
430
                                            server))))))
Per Cederqvist's avatar
.  
Per Cederqvist committed
431
432
433
434


(defun lyskom-show-logged-out-person (conf-stat session-no)
  "Visa p} kommandoraden vem som loggat ut."
435
436
437
438
  (let ((server (or (cdr (lyskom-string-assoc
                          lyskom-server-name
                          (append kom-server-aliases
                                  kom-builtin-server-aliases)))
439
                    lyskom-server-name)))
Per Cederqvist's avatar
.  
Per Cederqvist committed
440
441
  (cond
   ((lyskom-is-in-minibuffer))
442
   ((lyskom-show-presence (conf-stat->conf-no conf-stat) 
David Byers's avatar
David Byers committed
443
                          kom-presence-messages-in-echo-area)
David Kågedal's avatar
David Kågedal committed
444
445
446
    (lyskom-message
     "%s"
     (lyskom-format 'has-left (or conf-stat
447
				  (lyskom-get-string 'unknown-person))
448
                    server))))
Per Cederqvist's avatar
.  
Per Cederqvist committed
449
  (cond
450
451
   ((lyskom-show-presence (conf-stat->conf-no conf-stat)
                          kom-presence-messages-in-buffer)
David Kågedal's avatar
David Kågedal committed
452
453
454
    (if conf-stat
	(lyskom-format-insert-before-prompt 'has-left-r conf-stat
					    (and kom-text-properties
455
						 `(face ,kom-presence-face))
456
                                            server)
David Kågedal's avatar
David Kågedal committed
457
      (lyskom-format-insert-before-prompt 'has-left-r
458
					  (lyskom-get-string 'unknown-person)
David Kågedal's avatar
David Kågedal committed
459
					  (and kom-text-properties
460
					       `(face ,kom-presence-face))
461
                                          server))))))
Per Cederqvist's avatar
.  
Per Cederqvist committed
462
463


464

Per Cederqvist's avatar
.  
Per Cederqvist committed
465
466
(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
467
  (or lyskom-inhibit-minibuffer-messages
468
      cursor-in-echo-area
David Kågedal's avatar
David Kågedal committed
469
      (not (zerop (minibuffer-depth)))))
Per Cederqvist's avatar
.  
Per Cederqvist committed
470
471


472
 (defun lyskom-show-personal-message (sender recipient message 
473
                                            &optional when nobeep)
Per Cederqvist's avatar
.  
Per Cederqvist committed
474
  "Insert a personal message into the lyskom buffer.
Joel Rosdahl's avatar
Joel Rosdahl committed
475
Args: SENDER: conf-stat for the person sending the message.
476
477
      RECIPIENT: 0 if this message is for everybody, otherwise the conf-stat
                 of the recipient.
478
      MESSAGE: A string containing the message.
479
      WHEN: Optional time of arrival. A lyskom time structure.
480
481
482
      NOBEEP: True means don't beep. No matter what."
  (lyskom-insert-personal-message sender recipient message when nobeep)
  (setq lyskom-last-personal-message-sender 
483
        (if (stringp sender) sender (conf-stat->conf-no sender)))
484
485
486
  (setq lyskom-last-group-message-recipient 
        (if (and recipient
                 (not (eq 0 recipient))
487
488
                 (not (eq (conf-stat->conf-no recipient) lyskom-pers-no)))
            (conf-stat->conf-no recipient)
489
          nil))
David Byers's avatar
David Byers committed
490
491
  (run-hooks 'lyskom-personal-message-hook)
  (run-hooks 'kom-personal-message-hook))
492

493

494
495
(defun lyskom-insert-personal-message (sender recipient message
                                              &optional when nobeep)
496
  "Insert a personal message in the current buffer.
497
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
  (lyskom-handle-as-personal-message
506
507
508
509
510
511
512
513
514
515
   (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
516
517
518
SENDER is a conf-stat (possibly nil).
RECIPIENT is 0 if the message is public, otherwise the conf-stat of the
recipient.
519
MESSAGE is a string containing the message.
520
521
WHEN, if given, is the time when the message arrived. It must be a lyskom
time structure.
522
Non-nil NOBEEP means don't beep."
523
  (let ((lyskom-last-text-format-flags nil)
524
525
        (now (lyskom-current-client-time)))
    (when (null when) (setq when (lyskom-current-client-time)))
526
    (if (or kom-show-personal-message-date
527
528
529
            (not (eq (time->mday when) (time->mday now)))
            (not (eq (time->mon when) (time->mon now)))
            (not (eq (time->year when) (time->year now))))
530
531
532
        (setq when (let ((kom-print-relative-dates nil))
                     (lyskom-format-time 'date-and-time when)))
      (setq when (lyskom-format-time 'time when)))
533

534
535
536
    (setq nobeep (or nobeep (and kom-ansaphone-on
                                 kom-silent-ansaphone)))

David Kågedal's avatar
David Kågedal committed
537
538
539
540
541
    (cond ((or (null recipient)		; Have been seen to be nil when
                                        ; listing recorded
                                        ; messages. Should it be?
                                        ; /davidk
	       (eq recipient 0))	; Public message
542
           (if (not nobeep) (lyskom-beep kom-ding-on-common-messages sender))
543
           (lyskom-format (lyskom-get-string-sol 'message-broadcast)
544
545
546
547
548
                          (cond
                           ((stringp sender) sender)
                           (sender sender)
                           (t (lyskom-get-string 'unknown)))
                          message
David Byers's avatar
David Byers committed
549
                          when
550
                          (when kom-async-highlight-dashed-lines
551
552
                            `(face ,(or kom-async-dashed-lines-face
                                        lyskom-default-async-dashed-lines-face)))
553
                          (when kom-async-highlight-text-body
554
555
                            `(face ,(or kom-async-text-body-face
                                        lyskom-default-async-text-body-face)))))
556
          ((= (conf-stat->conf-no recipient) lyskom-pers-no) ; Private
557
           (if (not nobeep) (lyskom-beep kom-ding-on-personal-messages sender))
558
           (lyskom-format (lyskom-get-string-sol 'message-from)
559
560
561
562
563
                          (cond
                           ((stringp sender) sender)
                           (sender sender)
                           (t (lyskom-get-string 'unknown)))
                          message
David Byers's avatar
David Byers committed
564
                          when
565
                          (when kom-async-highlight-dashed-lines
566
567
                            `(face ,(or kom-async-dashed-lines-face
                                        lyskom-default-async-dashed-lines-face)))
568
                          (when kom-async-highlight-text-body
569
570
                            `(face ,(or kom-async-text-body-face
                                        lyskom-default-async-text-body-face)))))
571
          (t                            ; Group message
572
           (if (not nobeep) (lyskom-beep kom-ding-on-group-messages recipient))
573
           (lyskom-format (lyskom-get-string-sol 'message-from-to)
574
575
576
                          message
                          (cond
                           ((stringp sender) sender)
David Byers's avatar
David Byers committed
577
                           (sender  sender)
578
579
580
                           (t (lyskom-get-string 'unknown)))
                          (cond
                           ((stringp recipient) recipient)
David Byers's avatar
David Byers committed
581
                           (recipient recipient)
582
                           (t (lyskom-get-string 'unknown)))
David Byers's avatar
David Byers committed
583
                          when
584
                          (when kom-async-highlight-dashed-lines
585
586
                            `(face ,(or kom-async-dashed-lines-face
                                        lyskom-default-async-dashed-lines-face)))
587
                          (when kom-async-highlight-text-body
588
589
                            `(face ,(or kom-async-text-body-face
                                        lyskom-default-async-text-body-face))))))))
590

591
592

  
593
594
595
596
(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
597
converted, before insertion."
598
599
600
601
602
  (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
603
604
605
606
607
608
609
610
    (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
611
612
613
614
615
616
617
618
619
620
621
622
623
624
         (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
625
626
                 (select-window (lyskom-display-buffer (current-buffer)
                                                       (not (eq pop t))))
627
628
                 (goto-char (point-max))
                 (recenter -1))))))))))
629
  
Per Cederqvist's avatar
.  
Per Cederqvist committed
630

631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648

;;; ================================================================
;;; 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
649
650
  (if (and kom-mark-read-texts-as-read-in-new-recipient
           (lyskom-text-read-at-least-once-p text-stat t)
651
652
653
654
655
656
657
658
659
660
661
662
           (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
663
664
665
666
667
668
669
670
      (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)))))
671
672
673
674
675

(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
676
677
  (run-hooks 'lyskom-new-recipient-hook)
  (run-hooks 'kom-new-recipient-hook))
678
679
680



Per Cederqvist's avatar
.  
Per Cederqvist committed
681
;;; ================================================================
David Byers's avatar
David Byers committed
682
;;;            Functions for dealing with a new or deleted text
Per Cederqvist's avatar
.  
Per Cederqvist committed
683
684
685
686


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

Per Cederqvist's avatar
.  
Per Cederqvist committed
691
692
  (let ((no-message nil))
    (run-hooks 'lyskom-new-text-hook)
David Byers's avatar
David Byers committed
693
    (run-hooks 'kom-new-text-hook)
Per Cederqvist's avatar
.  
Per Cederqvist committed
694
695
696
697
  
    (if (and (not no-message)
	     lyskom-is-waiting
	     (not (lyskom-is-in-minibuffer)))
698
699
	(lyskom-message "%s" (lyskom-format 'text-is-created
					    (text-stat->text-no text-stat))))))
Per Cederqvist's avatar
.  
Per Cederqvist committed
700

David Byers's avatar
David Byers committed
701
702
703
704
705
(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
706
707
  (run-hooks 'lyskom-deleted-text-hook)
  (run-hooks 'kom-deleted-text-hook))
David Byers's avatar
David Byers committed
708

Per Cederqvist's avatar
.  
Per Cederqvist committed
709
710
711
712
713
(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
714
715
716
      misc-info (text-stat->misc-info-list text-stat)
    (let ((type (misc-info->type misc-info)))
      (cond
717
       ((memq type lyskom-recpt-types-list)
718
719
	;; add on lyskom-reading-list and lyskom-to-do-list if
	;; this recipient is a recipient that has been checked.
720
721
722
723
724
725
	(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
726
727
728
729
730
731
732
733
734
735
736
737
				(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
738

739
  (lyskom-prefetch-text-stat-all text-stat)
740

741
  ;; Give a message if the user is waiting. Update the prompt.
742
743
744
  (lyskom-run 'async 'lyskom-default-new-text-hook text-stat)

  (lyskom-run 'async 'lyskom-prefetch-and-print-prompt))
745
746


David Byers's avatar
David Byers committed
747
748
749
750
751
752
(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)))
753
          (cond ((memq type lyskom-recpt-types-list)
David Byers's avatar
David Byers committed
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
                 (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))
786
        (read-list-delete-text (text-stat->text-no text-stat) 
David Byers's avatar
David Byers committed
787
788
789
                               lyskom-to-do-list)
        (read-list-delete-text (text-stat->text-no text-stat) 
                               lyskom-reading-list)))
David Byers's avatar
David Byers committed
790
791
792
793
794

    (lyskom-set-mode-line)))
                 

    
Per Cederqvist's avatar
.  
Per Cederqvist committed
795
796
797
798
799
800
801
802
803

(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
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
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.

821
822
823
824
    ;; Prefetch thoughts:
    ;; We need a way to check if a conferences is fetched.
    ;; davidk /960924
    
825
826
827
    (let ((membership (lyskom-try-get-membership
		       (conf-stat->conf-no recipient))))
      (if (and membership
828
	       ;; (lyskom-conf-fetched-p (conf-stat->conf-no recipient))
829
	       (lyskom-visible-membership membership)
830
831
832
833
834
835
836
	       (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
837
		       (membership->priority membership)
838
839
840
		       (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))
841
		(read-list-enter-read-info info lyskom-reading-list)))
David Byers's avatar
David Byers committed
842
843
844
845
846
847
848
849

        ;; 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))))
850
851

    (lyskom-set-mode-line))))
852
853
854
855
856


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