edit-text.el 78.2 KB
Newer Older
David Byers's avatar
David Byers committed
1
;;;;; -*-coding: iso-8859-1;-*-
Linus Tolke's avatar
Linus Tolke committed
2
3
;;;;;
;;;;; $Id$
4
;;;;; Copyright (C) 1991-2002  Lysator Academic Computer Association.
Linus Tolke's avatar
Linus Tolke committed
5
;;;;;
6
;;;;; This file is part of the LysKOM Emacs LISP client.
Linus Tolke's avatar
Linus Tolke committed
7
8
9
;;;;; 
;;;;; LysKOM is free software; you can redistribute it and/or modify it
;;;;; under the terms of the GNU General Public License as published by 
10
;;;;; the Free Software Foundation; either version 2, or (at your option) 
Linus Tolke's avatar
Linus Tolke committed
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
;;;;; 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
26
27
28
29
30
31
32
33
34
;;;; ================================================================
;;;; ================================================================
;;;;
;;;; File: edit-text.el
;;;;
;;;; This file contains functions which lets the LysKOM user edit
;;;; a text in a window. It also defines a new mode - lyskom-edit-mode.
;;;;

35
36
37
38
39
(setq lyskom-clientversion-long 
      (concat lyskom-clientversion-long
	      "$Id$\n"))


Per Cederqvist's avatar
.    
Per Cederqvist committed
40
41
;;;; ================================================================

42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
;;; Set variables to make lyskom-edit-mode a minor mode. This
;;; simplifies some stuff a lot

(defvar lyskom-edit-mode nil
  "Mode variable for lyskom-edit-mode")
(make-variable-buffer-local 'lyskom-edit-mode)

(defvar lyskom-edit-sending-mode nil
  "Mode variable for lyskom-edit-sending-mode")
(make-variable-buffer-local 'lyskom-edit-sending-mode)

(defvar lyskom-edit-sent-mode nil
  "Mode variable for lyskom-edit-sent-mode")
(make-variable-buffer-local 'lyskom-edit-sent-mode)

(put 'lyskom-edit-mode 'permanent-local t)

(or (assq 'lyskom-edit-mode minor-mode-alist)
    (setq minor-mode-alist (cons '(lyskom-edit-mode " LysKOM Edit")
                                 minor-mode-alist)))

(or (assq 'lyskom-edit-sending-mode minor-mode-alist)
    (setq minor-mode-alist (cons '(lyskom-edit-sending-mode " LysKOM Sending")
                                 minor-mode-alist)))

(or (assq 'lyskom-edit-sent-mode minor-mode-alist)
    (setq minor-mode-alist (cons '(lyskom-edit-sent-mode " LysKOM Sent")
                                 minor-mode-alist)))

(or (assq 'lyskom-edit-mode minor-mode-map-alist)
    (setq minor-mode-map-alist
	  (cons (cons 'lyskom-edit-mode lyskom-edit-mode-map)
		minor-mode-map-alist)))

(or (assq 'lyskom-edit-sending-mode minor-mode-map-alist)
    (setq minor-mode-map-alist
	  (cons (cons 'lyskom-edit-sending-mode lyskom-edit-mode-map)
		minor-mode-map-alist)))

(or (assq 'lyskom-edit-sent-mode minor-mode-map-alist)
    (setq minor-mode-map-alist
	  (cons (cons 'lyskom-edit-sending-mode lyskom-edit-mode-map)
		minor-mode-map-alist)))


Per Cederqvist's avatar
.    
Per Cederqvist committed
87
88
89
90

(defvar lyskom-edit-mode-name "LysKOM edit"
  "Name of the mode.")

91
92
93
(defvar lyskom-edit-text-sent nil
  "Non-nil when a text has been sent")

Linus Tolke's avatar
Linus Tolke committed
94
95
96
97
98
99
100
101
102
103
104
105
106
107
(defvar lyskom-is-dedicated-edit-window nil
  "Status variable for an edit-window.")

(defvar lyskom-edit-handler nil
  "Status variable for an edit-buffer.
See lyskom-edit-handler-data.")

(defvar lyskom-edit-handler-data nil
  "Status variable for an edit-buffer.
See lyskom-edit-handler.")

(defvar lyskom-edit-return-to-configuration nil
  "Status variable for an edit-buffer.")

108
109
110
111
112
113
(def-komtype lyskom-text-headers
  ((subject :read-only t)
   (misc-info :read-only t)
   (aux-items :read-only t)))
   

114
;;; Error signaled by lyskom-edit-parse-headers
115
(put 'lyskom-edit-text-abort 'error-conditions
116
     '(error lyskom-error lyskom-edit-error lyskom-edit-text-abort))
117

118
(put 'lyskom-unknown-header 'error-conditions
119
     '(error lyskom-error lyskom-edit-error lyskom-unknown-header))
120
121

(put 'lyskom-no-subject 'error-conditions
122
     '(error lyskom-error lyskom-edit-error lyskom-no-subject))
David Byers's avatar
David Byers committed
123

124
125
126
(put 'lyskom-edit-error 'error-conditions
     '(error lyskom-error lyskom-edit-error))

Per Cederqvist's avatar
.    
Per Cederqvist committed
127
128
129
130
131
132
133
134
135
136
137
138
139
(defun lyskom-edit-text (proc misc-list subject body
			      &optional handler &rest data)
  "Edit a text in a new buffer.
PROC is the associated process.
MISC-LIST is the default misc-list.
SUBJECT is subject (a string).
BODY is the default text-body (a string, normally empty.)
HANDLER is a function to call when the text has been created.
DATA is extra data to send to the function. HANDLER is called with
	(apply HANDLER text-no DATA)
where text-no is the number of the text.
Does lyskom-end-of-command."
  (setq lyskom-is-writing t)
140
  (lyskom-dispatch-edit-text proc misc-list subject body
141
                             handler data))
142
143
144
145


(defun lyskom-dispatch-edit-text (proc misc-list subject body
				       &optional handler &rest data)
146
  "Same as lyskom-edit-text except that it doesn't set lyskom-is-writing."
David Byers's avatar
X    
David Byers committed
147
148
149
150
  (let ((buffer (lyskom-get-buffer-create 'write-texts
                                          (concat 
                                           (buffer-name (process-buffer proc))
                                           "-edit")))
Per Cederqvist's avatar
.    
Per Cederqvist committed
151
	(config (current-window-configuration)))
David Byers's avatar
X    
David Byers committed
152
153

    (lyskom-display-buffer buffer)
154
155
156
    (text-mode)
    (lyskom-ignore-errors
      (run-hooks 'lyskom-edit-mode-mode-hook))
David Byers's avatar
X    
David Byers committed
157
    (lyskom-edit-mode)
Per Cederqvist's avatar
.    
Per Cederqvist committed
158
159
160
161
162
163
    (make-local-variable 'lyskom-edit-handler)
    (make-local-variable 'lyskom-edit-handler-data)
    (make-local-variable 'lyskom-edit-return-to-configuration)
    (setq lyskom-edit-handler handler)
    (setq lyskom-edit-handler-data data)
    (setq lyskom-edit-return-to-configuration config)
David Byers's avatar
David Byers committed
164
    (buffer-disable-undo)
Per Cederqvist's avatar
.    
Per Cederqvist committed
165
    (lyskom-edit-insert-miscs misc-list subject body)
David Byers's avatar
David Byers committed
166
    (buffer-enable-undo)
167
    (goto-char (point-min))
168
169
    (re-search-forward (regexp-quote (lyskom-get-string
				      'header-subject))
170
171
		       (point-max)
		       'end)
172
173
    (if (not (looking-at "\\s-*$"))
        (goto-char (point-max)))
174
    (lyskom-message "%s" (lyskom-get-string 'press-C-c-C-c)))
David Byers's avatar
David Byers committed
175
  (set-buffer lyskom-buffer)
Linus Tolke's avatar
Linus Tolke committed
176
  )
Per Cederqvist's avatar
.    
Per Cederqvist committed
177
178


179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
(defun lyskom-edit-find-separator (&optional move-point)
  "Return the end position of the separator line.
If MOVE-POINT is non-nil, move point to the start of the separator."
  (prog1
      (save-excursion
        (goto-char (point-min))
        (and (re-search-forward
              (concat "^"
                      (regexp-quote
                       (substitute-command-keys
                        (lyskom-get-string 'header-separator)))
                      "$")
              nil t)))
    (when (and move-point (match-beginning 0))
      (goto-char (match-beginning 0)))))

David Byers's avatar
David Byers committed
195

196
(defun lyskom-edit-insert-miscs (misc-list subject body &optional aux-list)
Per Cederqvist's avatar
.    
Per Cederqvist committed
197
  "Insert MISC-LIST into header of text.
David Byers's avatar
David Byers committed
198
199
200
201
202
RECPT		-> Mottagare: <%d> %s.
CC-RECPT	-> Extra kopia: <%d> %s.
BCC-RECPT       -> Blind kopia: <%d> %s.
COMM-TO		-> Kommentar till text %d.
FOOTN-TO	-> Fotnot till text %d.
203
nil             -> Ingenting."
Per Cederqvist's avatar
.    
Per Cederqvist committed
204
205
  (let ((edit-buffer (current-buffer))
	(where-put-misc (point-min-marker))
David Byers's avatar
David Byers committed
206
	(main-buffer lyskom-buffer))
Per Cederqvist's avatar
.    
Per Cederqvist committed
207
208
209
210
211
212
    (set-buffer main-buffer)
    (setq misc-list (cdr misc-list))
    (while (not (null misc-list))
      (let ((key (car (car misc-list)))
	    (data (cdr (car misc-list))))
	(cond
David Byers's avatar
David Byers committed
213
	 ((eq key 'RECPT)
214
215
216
	  (lyskom-edit-insert-misc-conf (blocking-do 'get-conf-stat data)
					(lyskom-get-string 'recipient)
					where-put-misc data))
David Byers's avatar
David Byers committed
217
	 ((eq key 'CC-RECPT)
218
219
220
	  (lyskom-edit-insert-misc-conf (blocking-do 'get-conf-stat data)
					(lyskom-get-string 'carbon-copy)
					where-put-misc data))
David Byers's avatar
David Byers committed
221
	 ((eq key 'BCC-RECPT)
David Byers's avatar
David Byers committed
222
223
224
	  (lyskom-edit-insert-misc-conf (blocking-do 'get-conf-stat data)
					(lyskom-get-string 'blank-carbon-copy)
					where-put-misc data))
David Byers's avatar
David Byers committed
225
	 ((eq key 'COMM-TO)
226
227
228
	  (lyskom-edit-get-commented-author (blocking-do 'get-text-stat data)
					    (lyskom-get-string 'comment)
					    where-put-misc data))
David Byers's avatar
David Byers committed
229
	 ((eq key 'FOOTN-TO)
230
231
232
233
	  (lyskom-edit-get-commented-author (blocking-do 'get-text-stat data)
					    (lyskom-get-string 'footnote)
					    where-put-misc data)))
	(setq misc-list (cdr misc-list))))
David Byers's avatar
David Byers committed
234
235
236
237
238
239
240
241
242
243
244
245
246
    (mapcar (lambda (item)
	      (let ((data (lyskom-aux-item-call
			   item '(edit-insert print)
			   item lyskom-pers-no)))
		(when data
		  (lyskom-princ
		   (lyskom-format "%#1@%[%#3s%] %#2s\n" 
				  (lyskom-default-button 'aux-edit-menu 
							 (cons edit-buffer
							       (copy-marker where-put-misc)))
				  data
				  (lyskom-get-string 'aux-item-prefix))
		   where-put-misc))))
247
            aux-list)
248
249
250
251
252
253
    (unless kom-edit-hide-add-button
      (lyskom-princ (lyskom-format "%[%#1@%#2s%]\n"
                                   (lyskom-default-button 'add-recipient-or-xref
                                                          edit-buffer)
                                   (lyskom-get-string 'add-recpt-button-text))
                    where-put-misc))
254
255
256
257
    (lyskom-princ (lyskom-format 'text-mass subject 
				 (substitute-command-keys
				  (lyskom-get-string 'header-separator))
				 body 
David Byers's avatar
David Byers committed
258
				 (lyskom-get-string 'header-subject)
David Byers's avatar
David Byers committed
259
260
261
262
                                 '(read-only t)
                                 '(read-only t front-sticky nil start-open t rear-nonsticky nil end-open nil)
                                 '(read-only t rear-nonsticky t end-open t front-sticky t start-open nil)
                                 )
263
		  where-put-misc)
264
265
    (set-buffer edit-buffer)
    (goto-char where-put-misc)
266
    (set-marker where-put-misc nil)))
Per Cederqvist's avatar
.    
Per Cederqvist committed
267
268
269


(defun lyskom-edit-insert-misc-conf (conf-stat string stream number)
270
271
  "Insert Recipient:, Carbon copy: or Blind Carbon copy: in
edit-buffer.
Per Cederqvist's avatar
.    
Per Cederqvist committed
272
273
CONF-STAT is the conf-stat of the conference that is about to be put in,
STRING is the string that is inserted.
274
STREAM is the buffer or a marker telling the position.
Per Cederqvist's avatar
.    
Per Cederqvist committed
275
NUMBER is the number of the person. Used if the conf-stat is nil."
276
277
278
279
280
281
282
283
284
285
286
287
  (lyskom-princ
   (lyskom-format "%[%#1@%#2s%]: <%#3m> %#4M\n" 
                  (lyskom-default-button
                   'recpt-type
                   (list (or (conf-stat->conf-no conf-stat) number)
                         (marker-buffer stream))
                   (list (lyskom-get-string 'recpt-type-popup-title)
                         string))
                  string
                  (or conf-stat number)
                  (or conf-stat ""))
   stream))
Per Cederqvist's avatar
.    
Per Cederqvist committed
288
289
290

(defun lyskom-edit-get-commented-author (text-stat string stream number)
  (if text-stat
David Byers's avatar
David Byers committed
291
292
293
294
295
296
      (let ((mx-from (car (lyskom-get-aux-item (text-stat->aux-items text-stat) 17)))
            (mx-author (car (lyskom-get-aux-item (text-stat->aux-items text-stat) 16))))
        
       

        (lyskom-edit-insert-commented-author 
297
         (if (or mx-from mx-author)
David Byers's avatar
David Byers committed
298
299
300
             (lyskom-format-mx-author mx-from mx-author)
           (blocking-do 'get-conf-stat (text-stat->author text-stat)))
         string stream number))
Per Cederqvist's avatar
.    
Per Cederqvist committed
301
302
303
304
    (lyskom-edit-insert-commented-author nil string stream number)))


(defun lyskom-edit-insert-commented-author (conf-stat string stream number)
David Byers's avatar
X    
David Byers committed
305
306
307
308
309
310
311
312
  (lyskom-princ (lyskom-format 'comment-to-by
                               string
                               number
                               (if conf-stat
                                   (lyskom-format 'by conf-stat)
                                 ""))
                stream))

David Kågedal's avatar
David Kågedal committed
313

Per Cederqvist's avatar
.    
Per Cederqvist committed
314
315
316
317
318
319
320
321
322
323
324


(defun lyskom-create-misc-list (&rest misc-pairs)
  "Create a misc-list.
Note that a misc-list is very different from a misc-info-list.
A misc-list is used when creating a new text, and sent to the server.
A misc-info-list is what is received from the server. Although the server
has the same format for the two things, this client uses two quite
different formats.

The arguments to this function is any number of pairs of data. The first
David Byers's avatar
David Byers committed
325
item in each pair should be one of RECPT, CC-RECPT, COMM-TO or FOOTN-TO.
Per Cederqvist's avatar
.    
Per Cederqvist committed
326
327
328
The second item should be the corresponding conf- or text-no.

The result is a list of dotted pairs:
David Byers's avatar
David Byers committed
329
330
331
332
333
	('RECPT . conf-no)
	('CC-RECPT . conf-no)
	('BCC-RECPT . conf-no)
	('COMM-TO . text-no)
	('FOOTN-TO . text-no).
Per Cederqvist's avatar
.    
Per Cederqvist committed
334
First element is a type-tag."
David Byers's avatar
David Byers committed
335
   (let ((result (cons 'MISC-LIST nil)))
Per Cederqvist's avatar
.    
Per Cederqvist committed
336
    (while (not (null misc-pairs))
David Byers's avatar
David Byers committed
337
      (setq result (cons (cons (car misc-pairs)
Per Cederqvist's avatar
.    
Per Cederqvist committed
338
				(car (cdr misc-pairs)))
David Byers's avatar
David Byers committed
339
			  result))
Per Cederqvist's avatar
.    
Per Cederqvist committed
340
      (setq misc-pairs (cdr (cdr misc-pairs))))
David Byers's avatar
David Byers committed
341
    (nreverse result)))
Per Cederqvist's avatar
.    
Per Cederqvist committed
342
343
344
345
346


;;; ================================================================
;;;                   lyskom-edit-mode

Linus Tolke's avatar
Linus Tolke committed
347
348
349
350
351
352
(defvar lyskom-edit-mode-hook nil
  "*List of functions to be called when entering lyskom-edit-mode.
Watch out! None of these functions are allowed to do kill-all-local-variables
because kom-edit-send and other functions depend on some variables to be able
to enter the text in the correct lyskom-process.")

353
354
355
356
357
358
359
360
361
362
363
(defvar lyskom-edit-mode-mode-hook nil
  "*List of functions to be called when entering lyskom-edit-mode.
Watch out! None of these functions are allowed to do kill-all-local-variables
because kom-edit-send and other functions depend on some variables to be able
to enter the text in the correct lyskom-process.

This one differs from lyskom-edit-mode-hook in that it is called before
the lyskom-special key bindings are added.")


(defun lyskom-edit-mode (&optional arg)
Per Cederqvist's avatar
.    
Per Cederqvist committed
364
365
  "\\<lyskom-edit-mode-map>Mode for editing texts for LysKOM.
Commands:
Linus Tolke's avatar
Linus Tolke committed
366
367
368
369
370
371
372
373
\\[kom-edit-send]   sends the text when you are ready. The buffer will be
	  deleted if (and only if) the server accepts the text.
\\[kom-edit-quit]   aborts the editing. You will get back to the LysKOM buffer.

\\[kom-edit-show-commented]   shows the commented text in a temporary buffer.

\\[kom-edit-add-recipient]   asks for another recipient and adds him to the header.
\\[kom-edit-add-copy]   as \\[kom-edit-add-recipient] but adds him as copy-recipient.
374
\\[kom-edit-add-cross-reference]   asks for what to refer to and adds a cross reference to it.
Linus Tolke's avatar
Linus Tolke committed
375

Joel Rosdahl's avatar
Joel Rosdahl committed
376
\\[kom-edit-insert-commented]   inserts the commented or footnoted text.
377
\\[kom-edit-insert-text]   inserts the shown text, you tell the number.
378
\\[kom-edit-insert-link]   asks for what to link to and inserts a link to it.
379
380
381
382
383
384
385
386
387

Even though this is a minor mode, it's not intended to be turned on and off,
so it's not as clean as it ought to be."
  (interactive "P")
  (setq lyskom-edit-mode
        (if (null arg)
            (not lyskom-edit-mode)
          (> (prefix-numeric-value arg) 0)))

388
389
  (lyskom-set-menus 'lyskom-edit-mode lyskom-edit-mode-map)

390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
  (when lyskom-edit-mode
    (lyskom-edit-sending-mode 0)
    (lyskom-edit-sent-mode 0)
    (auto-fill-mode 1)
    (auto-save-mode 1)
    (when (not (local-variable-p 'lyskom-edit-text-sent (current-buffer)))
      (make-local-variable 'lyskom-edit-text-sent)
      (setq lyskom-edit-text-sent nil))
    (make-local-variable 'paragraph-start)
    (make-local-variable 'paragraph-separate)
    (setq paragraph-start (concat "^" 
                                  (regexp-quote 
                                   (substitute-command-keys
                                    (lyskom-get-string 'header-separator)))
                                  "$\\|" paragraph-start))
    (setq paragraph-separate (concat "^" 
                                     (regexp-quote 
                                      (substitute-command-keys
                                       (lyskom-get-string 'header-separator)))
                                     "$\\|" paragraph-separate))
410
411
412
413
    (make-local-variable 'comment-start)
    (make-local-variable 'comment-end)
    (setq comment-start kom-cite-string
	  comment-end "")
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
    (run-hooks 'lyskom-edit-mode-hook)))

(defun lyskom-edit-sending-mode (arg)
  (interactive "P")
  (setq lyskom-edit-sending-mode 
        (if (null arg)
            (not lyskom-edit-sending-mode)
          (> (prefix-numeric-value arg) 0)))

  (when lyskom-edit-sending-mode
    (lyskom-edit-mode 0)
    (lyskom-edit-sent-mode 0)))

(defun lyskom-edit-sent-mode (arg)
  (interactive "P")
  (setq lyskom-edit-sent-mode 
        (if (null arg)
            (not lyskom-edit-sent-mode)
          (> (prefix-numeric-value arg) 0)))

  (when lyskom-edit-sent-mode
    (lyskom-edit-sending-mode 0)
    (lyskom-edit-mode 0)))
Per Cederqvist's avatar
.    
Per Cederqvist committed
437
438
439
440
441
442


;;; ================================================================
;;;   Functions bound to keyboard seqences in lyskom-edit-mode
;;;

David Byers's avatar
   
David Byers committed
443
444
445
446
447
(defvar lyskom-edit-aux-list)
(defvar lyskom-edit-misc-list)
(defvar lyskom-edit-subject)
(defvar lyskom-edit-text)

448
(defun kom-edit-send-anonymous ()
449
450
451
  "Send the text anonymously to the server. Be aware that although the text 
will be truly anonymous, it is easy to slip up in such a way that the author
is evident anyway."
452
  (interactive)
David Byers's avatar
David Byers committed
453
  (lyskom-edit-send 'initiate-create-anonymous-text t))
Per Cederqvist's avatar
.    
Per Cederqvist committed
454
455

(defun kom-edit-send ()
456
457
458
  "Send the text to the server. This command will attempt to send the text
to the server. If something goes wrong, a prompt will be shown allowing you
to edit the message and try to send it again."
Per Cederqvist's avatar
.    
Per Cederqvist committed
459
  (interactive)
David Byers's avatar
David Byers committed
460
   (if (and (lyskom-default-value 'lyskom-is-anonymous)
461
            (lyskom-j-or-n-p 'do-send-anonymous))
David Byers's avatar
David Byers committed
462
463
       (lyskom-edit-send 'initiate-create-anonymous-text t)
     (lyskom-edit-send 'initiate-create-text nil)))
464

465
466
467
(defun lyskom-edit-send (send-function &optional is-anonymous)
  "Send the text to the server by calling SEND-FUNCTION.
If optional IS-ANONYMOUS is non-nil, assume that the text is being submitted
468
469
470
471
anonymously and take actions to avoid revealing the sender.

This runs `kom-send-text-hook' and (for backwards compatibility)
`lyskom-send-text-hook'."
472
  (condition-case err
David Byers's avatar
David Byers committed
473
      (if (or (not lyskom-edit-text-sent)
David Byers's avatar
David Byers committed
474
475
476
	      (j-or-n-p (lyskom-get-string 'already-sent)))
	  (progn 
	    (let ((buffer (current-buffer))
477
478
479
		  (headers nil)
                  (misc-list nil)
                  (subject nil)
480
481
		  (subject-start-pos nil)
		  (body-start-pos nil)
482
483
                  (message nil)
                  (aux-list nil))
David Byers's avatar
David Byers committed
484

485
486
487
488
              ;;
              ;; Run user hooks
              ;; ####: ++++: FIXME: We should quit more graciously.

David Byers's avatar
David Byers committed
489
              (if (not (run-hook-with-args-until-failure 'kom-send-text-hook))
490
491
492
                  (signal 'lyskom-edit-text-abort nil))


David Byers's avatar
David Byers committed
493
494
	      (save-excursion
		(setq headers (lyskom-edit-parse-headers)
495
		      misc-list (apply 'lyskom-create-misc-list 
496
497
498
                                       (lyskom-text-headers->misc-info headers))
                      aux-list (lyskom-text-headers->aux-items headers)
		      subject (lyskom-text-headers->subject headers)))
David Byers's avatar
David Byers committed
499
500

              ;;
501
502
503
              ;; Check that there is a subject
              ;;

David Byers's avatar
David Byers committed
504
505
	      (if (or (null subject)
                      (string= subject ""))
David Byers's avatar
David Byers committed
506
507
		  (let ((old (point)))
		    (goto-char (point-min))
508
		    (re-search-forward (lyskom-get-string 'header-subject)
David Byers's avatar
David Byers committed
509
510
511
				       nil t)
		    (end-of-line)
		    (if (/= (point) old)
512
			(signal 'lyskom-no-subject '(enter-subject-idi)))))
513
514
515
516
517
518
519
520
521
522

              ;;
              ;; Check the recipients
              ;;

              (let ((extra-headers
                     (lyskom-edit-send-check-recipients misc-list
                                                        subject)))
                (if extra-headers
                    (setq misc-list (apply 'lyskom-create-misc-list
523
524
                                           (nconc (elt headers 1)
						  extra-headers)))))
525

David Byers's avatar
David Byers committed
526
527
528
529
530
531
532
533
534
535
536
              ;;
              ;; Check that we don't add ourselves to an anon text
              ;;

              (when (and is-anonymous
                         (rassq lyskom-pers-no (cdr misc-list))
                         (lyskom-j-or-n-p 
                          (lyskom-get-string 'remove-self-sending-anonymous)))
                (rplacd misc-list (delq (rassq lyskom-pers-no (cdr misc-list))
                                        (cdr misc-list))))

David Byers's avatar
David Byers committed
537

538
539
540
541
              ;;
              ;; Transform the message text
              ;;

David Byers's avatar
   
David Byers committed
542
543
544
545
546
547
548
549
550
551
              (let ((lyskom-edit-aux-list aux-list)
                    (lyskom-edit-misc-list misc-list)
                    (lyskom-edit-subject subject)
                    (lyskom-edit-text (lyskom-edit-extract-text)))
                (run-hook-with-args-until-success
                 'lyskom-send-text-transform-hook)
                (setq aux-list lyskom-edit-aux-list)
                (setq misc-list lyskom-edit-misc-list)
                (setq subject lyskom-edit-subject)
                (setq message lyskom-edit-text))
552

David Byers's avatar
David Byers committed
553
	      (save-excursion
554
555
556
557
558
559
560
561
562
                (let* ((full-message
                        (cond ((and lyskom-allow-missing-subject
                                    (or (null subject)
                                        (string= subject ""))
                                    (not (string-match ".*\n" message)))
                               message)
                              (t (concat (or subject "") "\n" message))))
                       (content-type (lyskom-get-aux-item aux-list 1))
                       (charset (and content-type
563
564
565
566
                                     (lyskom-mime-content-type-get
                                      (lyskom-mime-decode-content-type
                                           (aux-item->data (car content-type)))
                                      'charset)))
567
568
569
		       (mime-charset (with-temp-buffer
				       (insert full-message)
				       (lyskom-mime-charset-for-text (point-min) (point-max)))))
570
571
572
573
574

                  ;; If the charset isn't already set, encode the string

                  (if (and mime-charset (null charset))
                      (setq full-message
575
                            (lyskom-mime-encode-string full-message mime-charset))
576
		    (lyskom-error (lyskom-get-string 'too-many-languages-error)))
577
578
579
580
581
582
583
584
585
586

                  ;; Add the charset data to the content type

                  (cond ((> (length content-type) 1)
                         (lyskom-error (lyskom-get-string 'too-many-content-types)))
                        ((null content-type)
                         (setq aux-list
                               (cons (lyskom-create-aux-item 0 1 nil nil
                                                             (lyskom-create-aux-item-flags nil nil nil nil nil nil nil nil)
                                                             0
587
                                                             (format "text/x-kom-basic;charset=%S" mime-charset))
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
                                     aux-list)))
                        ((null charset)
                         (set-aux-item->data (car content-type)
                                             (format "%s;charset=%S"
                                                     (aux-item->data (car content-type))
                                                     mime-charset))))

                  ;; Send the text

                  (lyskom-edit-sending-mode 1)
                  (set-buffer lyskom-buffer)
                  ;; Don't change the prompt if we won't see our own text
                  (if (and kom-created-texts-are-read
                           (not is-anonymous))
                      (setq lyskom-dont-change-prompt t))
                  (setq lyskom-is-writing nil)
                  (lyskom-tell-internat 'kom-tell-send)
David Byers's avatar
David Byers committed
605
606
607
608
609
610
611
612
613
614
615
616
617
618
                  (run-hook-with-args 'kom-create-text-hook
                              full-message
                              misc-list
                              (if (not is-anonymous)
                                  (cons (lyskom-create-aux-item
                                         0 15 0 0
                                         (lyskom-create-aux-item-flags
                                          nil nil nil nil nil nil nil nil)
                                         0 (concat "lyskom.el "
                                                   lyskom-clientversion))
                                        aux-list)
                                aux-list)
                              buffer
                              is-anonymous)
619

620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
                  (funcall send-function
                           'sending
                           'lyskom-create-text-handler
                           full-message
                           misc-list
                           (if (not is-anonymous)
                               (cons (lyskom-create-aux-item
                                      0 15 0 0
                                      (lyskom-create-aux-item-flags
                                       nil nil nil nil nil nil nil nil)
                                      0 (concat "lyskom.el "
                                                lyskom-clientversion))
                                     aux-list)
                             aux-list)
                           buffer
                           is-anonymous))))
David Byers's avatar
David Byers committed
636
            (lyskom-undisplay-buffer)
David Byers's avatar
David Byers committed
637
	    (goto-char (point-max))))
David Byers's avatar
David Byers committed
638
    ;;
639
    ;; Catch no-subject and other things
David Byers's avatar
David Byers committed
640
641
    ;;

642
    (lyskom-edit-text-abort
David Byers's avatar
   
David Byers committed
643
     (and (cdr err) (apply 'lyskom-message (cdr err))))
644
    (lyskom-no-subject
David Byers's avatar
David Byers committed
645
     (lyskom-beep kom-ding-on-no-subject)
David Byers's avatar
David Byers committed
646
647
     (if (cdr-safe (cdr-safe err))
	 (goto-char (car-safe (cdr-safe (cdr-safe err)))))
648
     (lyskom-message "%s" (lyskom-get-string (car (cdr err))))
649
     (condition-case nil
David Byers's avatar
David Byers committed
650
651
         (let ((text ""))
           (save-excursion
David Byers's avatar
David Byers committed
652
             (set-buffer lyskom-buffer)
David Byers's avatar
David Byers committed
653
654
655
656
             (if (and (string= "kom.lysator.liu.se" lyskom-server-name)
                      (eq lyskom-pers-no 698))
                 (setq text "rende, IDI!")))
           (save-excursion (insert text)))
657
658
       (error nil)))
    (lyskom-unknown-header
659
     (lyskom-message "%s" (lyskom-get-string (car (cdr err)))))))
David Byers's avatar
David Byers committed
660

David Byers's avatar
David Byers committed
661
(eval-when-compile (defvar ispell-dictionary nil))
David Byers's avatar
David Byers committed
662
663
664
(eval-when-compile (defvar ispell-message-text-end nil))
(eval-when-compile (defvar ispell-message-start-skip nil))
(eval-when-compile (defvar ispell-message-end-skip nil))
David Byers's avatar
David Byers committed
665
666


David Byers's avatar
David Byers committed
667
;;USER-HOOK: lyskom-ispell-text
668
669
(defun lyskom-ispell-text ()
  "Check spelling of the text body.
David Byers's avatar
David Byers committed
670
Put this in kom-send-text-hook"
671
  (kom-edit-ispell-message)
672
673
674
  t)


David Byers's avatar
David Byers committed
675
676
677
678
679
680
(eval-when-compile
  (defvar ispell-dictionary nil)
  (defvar ispell-message-text-end nil)
  (defvar ispell-message-start-skip nil)
  (defvar ispell-message-end-skip nil))

681
682
683
684
685
686
687
(defalias 'kom-ispell-message 'kom-edit-ispell-message)
(defun kom-edit-ispell-message ()
  "Check spelling of the text. Spelling is checked using ispell
and the dictionary indicated by `kom-ispell-dictionary'. If you
want to check the spelling of every message before sending it,
read the documentation for `lyskom-ispell-text' and 
`kom-send-text-hook'"
688
  (interactive)
David Byers's avatar
David Byers committed
689
  (require 'ispell)
690
691
  (let ((ispell-dictionary (or kom-ispell-dictionary ispell-dictionary))
        (kill-ispell (or (not (boundp 'ispell-dictionary))
692
                         (not (lyskom-string= kom-ispell-dictionary
693
694
695
696
697
698
699
700
                                       ispell-dictionary))))
        (result nil))
    (when kill-ispell (ispell-kill-ispell t))

    ;; Checking code

    (save-excursion
      (goto-char (point-min))
701
      (let* ((internal-messagep (lyskom-edit-find-separator t))
702
703
704
705
706
707
708
709
             (limit 
              (copy-marker
               (cond ((not ispell-message-text-end) (point-max))
                     ((char-or-string-p ispell-message-text-end)
                      (if (re-search-forward ispell-message-text-end nil t)
                          (match-beginning 0)
                        (point-max)))
                     (t (min (point-max) (funcall ispell-message-text-end))))))
David Byers's avatar
David Byers committed
710
711
712
             (cite-regexp 
              (regexp-quote
               (lyskom-default-value 'kom-cite-string)))
713
714
715
716
717
718
719
             (cite-regexp-start (concat "^[ \t]*$\\|" cite-regexp))
             (cite-regexp-end (concat "^\\(" cite-regexp "\\)"))
             (old-case-fold-search case-fold-search)
             (case-fold-search t)
             (ispell-checking-message t)
             (subject-string 
              (concat "^" (regexp-quote (lyskom-get-string 'subject)))))
720
        (lyskom-ignore ispell-checking-message)
721
722
723
724
        (goto-char (point-min))
        (while (if internal-messagep
                   (< (point) internal-messagep)
                 (not (eobp)))
David Byers's avatar
David Byers committed
725
          (if (lyskom-looking-at subject-string)
726
727
728
729
730
731
732
733
734
              (progn (goto-char (match-end 0))
                     (let ((case-fold-search old-case-fold-search))
                       (ispell-region (point)
                                      (progn
                                        (end-of-line)
                                        (point)))))
            (forward-line 1)))

        (while (< (point) limit)
David Byers's avatar
David Byers committed
735
          (while (and (lyskom-looking-at cite-regexp-start)
736
737
738
739
740
741
742
743
                      (< (point) limit)
                      (zerop (forward-line 1))))

          (if (< (point) limit)
              (let* ((start (point))
                     (end-c (and (re-search-forward cite-regexp-end limit 'end)
                                 (match-beginning 0)))
                     (end-fwd (and (goto-char start)
David Byers's avatar
David Byers committed
744
                                   (boundp 'ispell-message-start-skip)
745
                                   (stringp ispell-message-start-skip)
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
                                   (re-search-forward ispell-message-start-skip
                                                      limit 'end)))
                     (end (or (and end-c end-fwd (min end-c end-fwd))
                              end-c 
                              end-fwd
                              (marker-position limit))))
                (goto-char start)
                (setq result (ispell-region start end))
                  (if (and end-fwd (= end end-fwd))
                      (progn (goto-char end)
                             (re-search-forward ispell-message-end-skip 
                                                limit 'end))
                    (goto-char end)))))
          (set-marker limit nil)
          result))

    (when kill-ispell (ispell-kill-ispell t))
    result))

765
766
767
(defun lyskom-is-permitted-author (conf-stat)
  (and conf-stat
       (or (eq 0 (conf-stat->permitted-submitters conf-stat))
David Byers's avatar
David Byers committed
768
769
           (lyskom-is-supervisor (conf-stat->conf-no conf-stat)
                                 lyskom-pers-no))))
770

David Byers's avatar
David Byers committed
771

772
773
774
(defun lyskom-edit-send-check-recipients (misc-list subject) 
  "Check that the recipients of this text are OK. Ask the user to
confirm multiple recipients; check that the author of the commented
David Byers's avatar
David Byers committed
775
776
777
text is a member of some recipient of this text.

Cannot be called from a callback."
778
779
  (let* ((comm-to-list nil)
         (recipient-list nil)
David Byers's avatar
David Byers committed
780
         (text-stat nil)
781
         (collector (make-collector))
782
         (extra-headers nil)
David Byers's avatar
David Byers committed
783
         (buffer (current-buffer))
David Byers's avatar
David Byers committed
784
         (me (save-excursion (set-buffer lyskom-buffer)
785
                             lyskom-pers-no))
David Byers's avatar
David Byers committed
786
787
         (num-me 0)
         (num-real-recpt 0))
David Byers's avatar
David Byers committed
788
    (lyskom-ignore text-stat)       ; Have no idea if its ever used...
789
790
791

    ;;
    ;; List all texts this text is a comment to
David Byers's avatar
David Byers committed
792
    ;; List all recipients of the text
793
794
795
    ;;

    (lyskom-traverse misc (cdr misc-list)
David Byers's avatar
David Byers committed
796
      (cond ((eq (car misc) 'COMM-TO)
797
798
             (setq comm-to-list (cons (cdr misc)
                                      comm-to-list)))
David Byers's avatar
David Byers committed
799
800
            ((memq (car misc) lyskom-recpt-types-list)
             (when (eq (car misc) 'RECPT)
David Byers's avatar
David Byers committed
801
802
               (setq num-real-recpt (1+ num-real-recpt))
               (when (eq (cdr misc) me) (setq num-me (1+ num-me))))
803
804
             (setq recipient-list (cons (cdr misc) recipient-list)))))

David Byers's avatar
David Byers committed
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
    ;;
    ;; Check that there are recipients
    ;;

    (when (null recipient-list)
      (lyskom-error "%s" (lyskom-format 'no-recipients)))

    ;;
    ;; Check for duplicate recipients
    ;;

    (let ((tmp recipient-list))
      (while tmp
        (when (memq (car tmp) (cdr tmp))
          (lyskom-error "%s" (lyskom-format 'duplicate-recipients (car tmp))))
        (setq tmp (cdr tmp))))

David Byers's avatar
David Byers committed
822
823
824
825
826
    ;;
    ;; Check for new comments
    ;;

    (when (save-excursion (set-buffer lyskom-buffer)
David Byers's avatar
David Byers committed
827
828
829
830
831
                          (cond ((null kom-check-for-new-comments) nil)
                                ((functionp kom-check-for-new-comments)
                                 (funcall kom-check-for-new-comments
                                          buffer misc-list subject))
                                (t t)))
832
      (lyskom-message "%s" (lyskom-format 'checking-comments))
David Byers's avatar
David Byers committed
833
834
835
      (save-excursion
        (set-buffer lyskom-buffer)
        (set-collector->value collector nil)
David Byers's avatar
David Byers committed
836

David Byers's avatar
David Byers committed
837
838
839
840
841
842
        (mapcar (lambda (text-stat)
		  (cache-del-text-stat text-stat)
		  (initiate-get-text-stat 'sending 
					  'collector-push
					  text-stat
					  collector))
David Byers's avatar
David Byers committed
843
844
                comm-to-list)
        (lyskom-wait-queue 'sending)
David Byers's avatar
David Byers committed
845

846
	(lyskom-traverse
David Byers's avatar
David Byers committed
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
            text-stat (collector->value collector)
          (when text-stat
            (when (catch 'unread
                    (lyskom-traverse
                        misc-item (text-stat->misc-info-list text-stat)
                      (when (and (eq (misc-info->type misc-item) 'COMM-IN)
                                 (not (lyskom-text-read-at-least-once-p 
                                       (blocking-do
                                        'get-text-stat
                                        (misc-info->comm-in misc-item)))))
                        (throw 'unread t))))
              (unless (lyskom-j-or-n-p
                       (lyskom-format 'have-unread-comment text-stat))
                (signal 'lyskom-edit-text-abort
                        (list "%s"
                              (lyskom-get-string 
                               'please-check-commented-texts))))))))
864
      (lyskom-message "%s" (lyskom-format 'checking-comments-done)))
865
866
    
    
867
868
869
870
    ;;
    ;; Confirm multiple recipients
    ;;
    
David Byers's avatar
David Byers committed
871
872
873
874

    (if (and (lyskom-default-value 'kom-confirm-multiple-recipients)
             (not (eq (lyskom-default-value 'kom-confirm-multiple-recipients)
                      'before))
David Byers's avatar
David Byers committed
875
876
             (> (- num-real-recpt num-me) 1))

877
878
879
880
        (save-excursion
          (goto-char (point-min))
          (if (not 
               (lyskom-j-or-n-p
881
                (lyskom-format 'comment-all-relevant-p)))
882
883
884
885
              (signal 'lyskom-edit-text-abort 
                      (list "%s" 
                            (lyskom-get-string 
                             'please-edit-recipients))))))
886

887
888
889
890
    ;;
    ;; Check that the authors of all commented texts get to see the new text
    ;;

David Byers's avatar
David Byers committed
891
892
893
894
895
896
897
898
    (let ((authors-to-ask-about (lyskom-compute-recipients-commented-authors 
				 comm-to-list 
				 (delq nil 
				       (mapcar (lambda (misc) 
						 (and (memq (car misc) lyskom-recpt-types-list)
						      (cdr misc)))
					       (cdr misc-list))))))
      (when authors-to-ask-about
David Byers's avatar
David Byers committed
899

David Byers's avatar
David Byers committed
900
901
902
903
904
905
906
907
        ;;
        ;; Now authors-to-ask-about contains all authors that we
        ;; want to ask about. So do that.
        ;;

        (lyskom-traverse author authors-to-ask-about
          (let ((send-comments-to
                 (car (lyskom-get-aux-item (conf-stat->aux-items author) 33))))
David Byers's avatar
David Byers committed
908
909
910
911
912
913
914
915
916
917
918
919
920
921
            (when send-comments-to
              (cond ((string-match "^\\([0-9]+\\)\\s-+\\([0-9]+\\)" (aux-item->data send-comments-to))
                     (setq send-comments-to 
                           (cons (string-to-number
                                  (match-string 1 (aux-item->data send-comments-to)))
                                 (string-to-number
                                  (match-string 2 (aux-item->data send-comments-to))))))
                    ((string-match "^\\([0-9]+\\)"
                                   (aux-item->data send-comments-to))
                     (setq send-comments-to
                           (cons (string-to-number
                                  (match-string 1 (aux-item->data send-comments-to)))
                                 0)))
                    (t (setq send-comments-to nil))))
David Byers's avatar
David Byers committed
922

David Byers's avatar
David Byers committed
923
924
925
            (when (lyskom-j-or-n-p 
                   (lyskom-format 'add-recipient-p 
                                  author
David Byers's avatar
David Byers committed
926
                                  (car send-comments-to)))
David Byers's avatar
David Byers committed
927
              (setq extra-headers
David Byers's avatar
David Byers committed
928
929
930
931
932
933
934
935
936
937
938
939
940
941
                    (nconc
                     (list
                      (cond ((and send-comments-to
                                  (eq (cdr send-comments-to) 0)) 'RECPT)
                            ((and send-comments-to
                                  (eq (cdr send-comments-to) 1)) 'CC-RECPT)
                            ((and send-comments-to
                                  (eq (cdr send-comments-to) 15)) 'BCC-RECPT)
                            (t (if (lyskom-j-or-n-p
                                    (lyskom-format 'really-add-as-recpt-q author))
                                   'RECPT
                                 'CC-RECPT)))
                            (conf-stat->conf-no author))
                     extra-headers)))))))
942
    extra-headers))
David Byers's avatar
David Byers committed
943
944
945


;;UNUSED: lyskom-send-enriched
David Byers's avatar
   
David Byers committed
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
(defun lyskom-send-enriched ()
  (let ((content-type (lyskom-get-aux-item lyskom-edit-aux-list 1)))
    (when (or (null content-type)
              (and (= (length content-type) 1)
                   (string-match "^text/enriched" (aux-item->data (car content-type)))))
      (condition-case err
          (let ((buf (lyskom-get-buffer-create 'lyskom-enriched 
                                               "lyskom-enriched" 
                                               t)))
            (unwind-protect
                (save-excursion
                  (set-buffer buf)
                  (insert lyskom-edit-text)
                  (goto-char (point-min))
                  (format-encode-buffer 'text/enriched)
                  (goto-char (point-min))
                  (search-forward "\n\n")
                  (when (and (not (lyskom-string= 
                                   (replace-in-string (buffer-substring (point) (point-max))
                                                      "<<" "<" t)
                                   lyskom-edit-text))
                             (save-excursion
                               (set-buffer lyskom-buffer)
                               (lyskom-j-or-n-p 
                                (lyskom-get-string 'send-formatted))))
                    (setq lyskom-edit-text (buffer-substring (point) (point-max)))
                    (unless content-type
                      (setq lyskom-edit-aux-list 
                            (cons (lyskom-create-aux-item 0 1 nil nil
                                                          (lyskom-create-aux-item-flags nil nil nil nil nil nil nil nil)
                                                          0
                                                          "text/enriched")
                                  lyskom-edit-aux-list)))
                    (setq lyskom-edit-aux-list
                          (cons (lyskom-create-aux-item 0 10002 nil nil
                                                        (lyskom-create-aux-item-flags nil nil nil nil nil nil nil nil)
                                                        0
                                                        (buffer-substring (point-min) (point)))
                                lyskom-edit-aux-list)))
                  'stop-transforming-texts)
              (kill-buffer buf)))
        (error (if (lyskom-j-or-n-p
                    (lyskom-format (lyskom-get-string 'transform-error)
                                   (error-message-string err)))
                   nil
                 (signal 'lyskom-edit-text-abort nil)))))))
David Byers's avatar
David Byers committed
992

Per Cederqvist's avatar
.    
Per Cederqvist committed
993
994
995


(defun kom-edit-quit ()
996
  "Cancel editing the text being written and return to reading LysKOM."
Per Cederqvist's avatar
.    
Per Cederqvist committed
997
998
999
1000
1001
  (interactive)
  (let ((edit-buffer (current-buffer)))
    (goto-char (point-max))
    (setq lyskom-is-writing nil)
    (lyskom-tell-internat 'kom-tell-regret)
David Byers's avatar
X    
David Byers committed
1002
1003
1004
1005
    (lyskom-save-excursion (set-buffer edit-buffer)
                           (delete-auto-save-file-if-necessary))
    (lyskom-undisplay-buffer edit-buffer)
    (kill-buffer edit-buffer))
Per Cederqvist's avatar
.    
Per Cederqvist committed
1006
1007
1008
1009
1010
1011
1012
1013
1014
  (garbage-collect))			;Take care of the garbage.


(defun kom-edit-show-commented ()
  "Show the commented text in another window."
  (interactive)
  (lyskom-edit-get-commented 'lyskom-edit-show-commented))


1015
(defun kom-edit-insert-commented (arg)
1016
1017
1018
1019
1020
  "Insert the commented text, prepending each line with the
text in `kom-cite-string' (defaults to \"> \"). Note that citing
the commented text is not common practise in LysKOM (unlike
e-mail and news) since there is a strong link to the commented
text anyway. Use this command sparingly."
1021
1022
1023
1024
  (interactive "P")
  (lyskom-edit-get-commented
   'lyskom-edit-insert-commented
   (list (cond ((and arg (listp arg)) "")
1025
	       (t nil)))))
Per Cederqvist's avatar
.    
Per Cederqvist committed
1026
1027


1028
(defun kom-edit-insert-buglist ()
1029
  "Insert the commented buglist, Roxen Internet Software style. Excluded from manual."
1030
1031
1032
1033
  (interactive)
  (lyskom-edit-get-commented 'lyskom-edit-insert-buglist))


Per Cederqvist's avatar
.    
Per Cederqvist committed
1034
(defun kom-edit-insert-digit-text ()
1035
  "Prompt for a text to insert. Excluded from manual."
Per Cederqvist's avatar
.    
Per Cederqvist committed
1036
  (interactive)
1037
  (setq unread-command-events (cons last-command-event unread-command-events))
Per Cederqvist's avatar
.    
Per Cederqvist committed
1038
1039
1040
1041
  (call-interactively 'kom-edit-insert-text nil))


(defun kom-edit-insert-text (no)
1042
1043
1044
1045
1046
  "Prompt for a text to insert, prefixing each line with the contents
of `kom-cite-string' (defaults to \"> \"). Note that citing texts is not
commonplace in LysKOM (unlike e-mail and news) since it is easy to
refer to specific texts (see `kom-edit-insert-link' and
`kom-edit-add-cross-reference'). Use this command sparingly."
Linus Tolke's avatar
Linus Tolke committed
1047
1048
1049
  (interactive (list
		(cond
		 ((null current-prefix-arg)
David Byers's avatar
David Byers committed
1050
                  (lyskom-read-number 'which-text-include))
Linus Tolke's avatar
Linus Tolke committed
1051
		 ((prefix-numeric-value current-prefix-arg)))))
David Byers's avatar
David Byers committed
1052
1053
  (let ((buffer (current-buffer))
        (window (selected-window)))
David Byers's avatar
David Byers committed
1054
    (set-buffer lyskom-buffer)
1055
    (lyskom-collect 'edit)
1056
1057
    (initiate-get-text 'edit nil no)
    (initiate-get-text-stat 'edit nil no)
1058
    (lyskom-use 'edit 'lyskom-edit-insert-commented buffer window)
Per Cederqvist's avatar
.    
Per Cederqvist committed
1059
1060
1061
    (set-buffer buffer)
    (sit-for 0)))

1062
1063
1064
1065
1066

(defun lyskom-edit-get-commented (thendo &optional arg-list)
  "Get the commented text and text stat and then do THENDO with it.
This function is called with an argument list TEXT TEXT-STAT BUFFER
WINDOW plus any optional arguments given in ARG-LIST."
Per Cederqvist's avatar
.    
Per Cederqvist committed
1067
1068
1069
  (let ((p (point)))
    (save-excursion
      (let* ((buffer (current-buffer))
David Byers's avatar
David Byers committed
1070
             (window (selected-window))
1071
             (headers (condition-case nil
1072
                          (lyskom-text-headers->misc-info (lyskom-edit-parse-headers))
1073
1074
1075
                        (lyskom-edit-error nil))) ; Ignore these errors
             (no nil))
        (while headers
David Byers's avatar
David Byers committed
1076
          (if (memq (car headers) '(COMM-TO FOOTN-TO))
1077
1078
1079
1080
1081
1082
              (setq no (car (cdr headers))
                    headers nil)
            (setq headers (cdr (cdr headers)))))
        (cond
         (no
          (goto-char p)
David Byers's avatar
David Byers committed
1083
          (set-buffer lyskom-buffer)
1084
1085
1086
          (blocking-do-multiple ((text (get-text no))
                                 (text-stat (get-text-stat no)))
            (set-buffer buffer)
1087
            (apply thendo text text-stat buffer window arg-list)))
1088
1089
1090
         (t
          (lyskom-message "%s" (lyskom-get-string 'no-such-text-m))))))
    (sit-for 0)))
Per Cederqvist's avatar
.    
Per Cederqvist committed
1091
1092


1093
1094
1095
;;; ============================================================
;;; Info node stuff

1096
1097
1098
(defvar Info-current-node)
(defvar Info-current-file)

David Byers's avatar
David Byers committed
1099
;; NOTUSED: kom-yank-info-nodename
1100
1101
1102
1103
1104
1105
(defalias 'kom-yank-info-nodename 'kom-edit-yank-info-nodename)
(defun kom-edit-yank-info-nodename ()
  "When browsing info files, this command will place a reference to the
current info node in the kill ring, from where it can be pasted into
another buffer. This command is useful when you want to refer to an 
info node in a LysKOM text."
1106
1107
1108
1109
1110
1111
  (interactive)
  (kill-new (format "*Note %s: (%s)%s,"
		    Info-current-node
		    (file-name-nondirectory Info-current-file)
		    Info-current-node)))

David Byers's avatar
David Byers committed
1112
1113

;; NOTUSED: kom-insert-last-info-nodename
1114
1115
(defalias 'kom-insert-last-info-nodename 'kom-edit-insert-last-info-nodename)
(defun kom-edit-insert-last-info-nodename ()
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
  "Insert a reference to the most recently visited info node."
  (interactive)
  (condition-case nil
      (let ((link nil))
        (save-excursion
          (set-buffer (get-buffer "*info*"))
          (setq link (format "*Note %s: (%s)%s,"
                             Info-current-node
                             (file-name-nondirectory Info-current-file)
                             Info-current-node)))
        (insert link))
1127
    (error (lyskom-message "%s" (lyskom-get-string 'cant-find-info-node)))))
1128

Per Cederqvist's avatar
.    
Per Cederqvist committed
1129
1130
1131
1132
1133
1134
;;; ================================================================
;;;	  Add recipient, copy-recipient - Addera mottagare 
;;;
;;;  Author: Anders Gertz
;;;  Changed by: Linus Tolke

David Byers's avatar
David Byers committed
1135
(defun kom-edit-add-comment ()
1136
1137
1138
1139
  "Makes this text a comment to another text. Using this command it is
possible to make the text a comment to multiple texts. To remove a 
comment link, simply remove the corresponding line from the headers
in the edit buffer."
David Byers's avatar
David Byers committed
1140
1141
1142
1143
1144
  (interactive)
  (let* ((edit-buffer (current-buffer))
         (insert-at (point-min-marker))
         (text-no (lyskom-read-number (lyskom-get-string 'text-to-comment-q)))
         (text-stat (blocking-do 'get-text-stat text-no)))
1145
    (lyskom-ignore edit-buffer)
David Byers's avatar
David Byers committed
1146
1147
1148
1149
1150
1151
    (lyskom-save-excursion
     (if text-stat
         (lyskom-edit-get-commented-author 
          (blocking-do 'get-text-stat text-no)
          (lyskom-get-string 'comment)
          insert-at text-no)
1152
1153
       (lyskom-error "%s" (lyskom-get-string 'no-such-text-m)))
     (set-marker insert-at nil))))
David Byers's avatar
David Byers committed
1154
1155


Per Cederqvist's avatar
.    
Per Cederqvist committed
1156
(defun kom-edit-add-recipient ()
1157
1158
1159
1160
  "Adds a regular recipient to the text or converts an existing
recipient to a regular recipient. Using this command it is possible to
add any number of regular recipients. To remove a recipient, simply
delete the corresponding header line in the edit buffer."
Per Cederqvist's avatar
.    
Per Cederqvist committed
1161
  (interactive)
1162
  (lyskom-edit-add-recipient/copy 'added-recipient nil 'RECPT))
Per Cederqvist's avatar
.    
Per Cederqvist committed
1163
1164


David Byers's avatar
David Byers committed
1165
(defun kom-edit-add-bcc ()
1166
1167
1168
1169
1170
  "Adds a blind carbon copy recipient to the text, or converts an
existing recipient to blind carbon copy. Using this command it is
possible to add any number of regular recipients. To remove a
recipient, simply delete the corresponding header line in the edit
buffer."
David Byers's avatar
David Byers committed
1171
  (interactive)
1172
  (lyskom-edit-add-recipient/copy 'added-blank-carbon-copy nil 'BCC-RECPT))
David Byers's avatar
David Byers committed
1173
1174


Per Cederqvist's avatar
.    
Per Cederqvist committed
1175
(defun kom-edit-add-copy ()
1176
1177
1178
1179
  "Adds a carbon copy recipient to the text, or converts an existing
recipient to blind carbon copy. Using this command it is possible to
add any number of regular recipients. To remove a recipient, simply
delete the corresponding header line in the edit buffer."
Per Cederqvist's avatar
.    
Per Cederqvist committed
1180
  (interactive)
1181
  (lyskom-edit-add-recipient/copy 'added-carbon-copy nil 'CC-RECPT))
Per Cederqvist's avatar
.    
Per Cederqvist committed
1182

David Byers's avatar
David Byers committed
1183
(defun kom-edit-move-text ()
1184
1185
1186
1187
1188
  "Adds a regular recipient to the text, or converts an existing
recipient to blind carbon copy, and converts all other recipients to
carbonn copy recipients. This command is intended for situations where
a commend is being sent to a different recipient than the commented
text was."
David Byers's avatar
David Byers committed
1189
  (interactive)
1190
  (lyskom-edit-add-recipient/copy 'edit-who-to-move-to-q
David Byers's avatar
David Byers committed
1191
                                  'lyskom-edit-move-recipients))
Per Cederqvist's avatar
.    
Per Cederqvist committed
1192

David Byers's avatar
David Byers committed
1193

David Byers's avatar
David Byers committed
1194
1195
1196
(defun lyskom-edit-move-recipients (conf-stat insert-at edit-buffer)
  (save-excursion
    (set-buffer edit-buffer)
1197
1198
    (let* ((headers (lyskom-edit-parse-headers))
           (subject (lyskom-text-headers->subject headers))
1199
1200
1201
1202
1203
1204
1205
           (miscs (mapcar (lambda (x) (cond ((and (eq (car x) 'RECPT)
						  (not (conf-type->letterbox
							(uconf-stat->conf-type
							 (blocking-do 'get-uconf-stat (cdr x))))))
					     (cons 'CC-RECPT (cdr x)))
					    (t x)))
			  (cdr (lyskom-edit-translate-headers (lyskom-text-headers->misc-info headers)))))
1206
           (aux-list (lyskom-text-headers->aux-items headers))
David Byers's avatar
David Byers committed
1207
1208
1209
1210
1211
1212
           (elem nil))


      ;; If the new target is already a recipient, convert it to the right 
      ;; kind. Otherwise insert the new target after the last comm-to

David Byers's avatar
David Byers committed
1213
      (setq elem (lyskom-edit-find-misc miscs lyskom-recpt-types-list 
David Byers's avatar
David Byers committed
1214
1215
                                        (conf-stat->conf-no conf-stat)))
      (if elem
David Byers's avatar
David Byers committed
1216
          (setcar elem 'RECPT)
David Byers's avatar
David Byers committed
1217
        (lyskom-insert-in-list
David Byers's avatar
David Byers committed
1218
         (cons 'RECPT (conf-stat->conf-no conf-stat))
David Byers's avatar
David Byers committed
1219
         miscs
David Byers's avatar
David Byers committed
1220
         (car (cdr (memq (lyskom-edit-find-misc miscs '(FOOTN-TO COMM-TO) 
David Byers's avatar
David Byers committed
1221
1222
1223
1224
                                                nil t)
                         miscs)))))

      (lyskom-edit-replace-headers subject (cons 'MISC-LIST miscs) aux-list))))
David Byers's avatar
David Byers committed
1225
1226
1227
                                  


David Byers's avatar
David Byers committed
1228
(defun lyskom-edit-do-add-recipient/copy (recpt-type recpt-no edit-buffer)
1229
  (save-excursion
David Byers's avatar
David Byers committed
1230
1231
    (set-buffer edit-buffer)
    (let* ((headers (lyskom-edit-parse-headers))
1232
           (miscs (lyskom-edit-translate-headers (lyskom-text-headers->misc-info headers)))
David Byers's avatar
David Byers committed
1233
           (elem (lyskom-edit-find-misc miscs lyskom-recpt-types-list
David Byers's avatar
David Byers committed
1234
1235
1236
1237
1238
                                        recpt-no)))

      (cond (elem (setcar elem recpt-type))
            (t (setq miscs
                     (append miscs (list (cons recpt-type recpt-no))))))
1239
      (lyskom-edit-replace-headers (lyskom-text-headers->subject headers)
David Byers's avatar
David Byers committed
1240
                                   miscs
1241
                                   (lyskom-text-headers->aux-items headers)))))
David Byers's avatar
David Byers committed
1242
1243


1244
(defun lyskom-edit-add-recipient/copy (prompt &optional what-to-do recpt-type)