1
;;; Commands to move around within a VM message
2
;;; Copyright (C) 1989-1997 Kyle E. Jones
4
;;; This program is free software; you can redistribute it and/or modify
5
;;; it under the terms of the GNU General Public License as published by
6
;;; the Free Software Foundation; either version 1, or (at your option)
9
;;; This program is distributed in the hope that it will be useful,
10
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
11
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
;;; GNU General Public License for more details.
14
;;; You should have received a copy of the GNU General Public License
15
;;; along with this program; if not, write to the Free Software
16
;;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
(defun vm-scroll-forward (&optional arg)
21
"Scroll forward a screenful of text.
22
If the current message is being previewed, the message body is revealed.
23
If at the end of the current message, moves to the next message iff the
24
value of vm-auto-next-message is non-nil.
25
Prefix argument N means scroll forward N lines."
27
(let ((mp-changed (vm-follow-summary-cursor))
30
(vm-select-folder-buffer)
31
(vm-check-for-killed-summary)
32
(vm-check-for-killed-presentation)
33
(vm-error-if-folder-empty)
34
(setq needs-decoding (and vm-display-using-mime
36
(not (vm-mime-plain-message-p
37
(car vm-message-pointer)))
38
vm-auto-decode-mime-messages
39
(eq vm-system-state 'previewing)))
40
(and vm-presentation-buffer
41
(set-buffer vm-presentation-buffer))
43
(w (vm-get-visible-buffer-window (current-buffer))))
45
(not (vm-frame-totally-visible-p (vm-window-frame w))))
47
(vm-display (current-buffer) t
48
'(vm-scroll-forward vm-scroll-backward)
49
(list this-command 'reading-message))
50
;; window start sticks to end of clip region when clip
51
;; region moves back past it in the buffer. fix it.
52
(setq w (vm-get-visible-buffer-window (current-buffer)))
53
(if (= (window-start w) (point-max))
54
(set-window-start w (point-min)))
55
(setq was-invisible t))))
56
(if (or mp-changed was-invisible needs-decoding
57
(and (eq vm-system-state 'previewing)
58
(pos-visible-in-window-p
60
(vm-get-visible-buffer-window (current-buffer)))))
62
(if (not was-invisible)
63
(let ((w (vm-get-visible-buffer-window (current-buffer)))
65
(setq old-w-start (window-start w))
66
;; save-excursion to avoid possible buffer change
67
(save-excursion (vm-select-frame (window-frame w)))
68
(vm-raise-frame (window-frame w))
69
(vm-display nil nil '(vm-scroll-forward vm-scroll-backward)
70
(list this-command 'reading-message))
71
(setq w (vm-get-visible-buffer-window (current-buffer)))
72
(and w (set-window-start w old-w-start))))
73
(cond ((eq vm-system-state 'previewing)
74
(vm-show-current-message)
75
;; The window start marker sometimes drifts forward
76
;; because of something that vm-show-current-message
77
;; does. In Emacs 20, replacing ASCII chars with
78
;; multibyte chars seems to cause it, but I _think_
79
;; the drift can happen in Emacs 19 and even
80
;; XEmacs for different reasons. So we reset the
81
;; start marker here, since it is an easy fix.
82
(let ((w (vm-get-visible-buffer-window (current-buffer))))
83
(set-window-start w (point-min)))))
85
(let ((vmp vm-message-pointer)
86
(msg-buf (current-buffer))
88
w old-w old-w-height old-w-start result)
89
(if (eq vm-system-state 'previewing)
90
(vm-show-current-message))
91
(setq vm-system-state 'reading)
92
(setq old-w (vm-get-visible-buffer-window msg-buf)
93
old-w-height (window-height old-w)
94
old-w-start (window-start old-w))
95
(setq w (vm-get-visible-buffer-window msg-buf))
96
(vm-select-frame (window-frame w))
97
(vm-raise-frame (window-frame w))
98
(vm-display nil nil '(vm-scroll-forward vm-scroll-backward)
99
(list this-command 'reading-message))
100
(setq w (vm-get-visible-buffer-window msg-buf))
102
(error "current window configuration hides the message buffer.")
103
(setq h-diff (- (window-height w) old-w-height)))
104
;; must restore this since it gets clobbered by window
105
;; teardown and rebuild done by the window config stuff.
106
(set-window-start w old-w-start)
107
(setq old-w (selected-window))
111
(let ((next-screen-context-lines
112
(+ next-screen-context-lines h-diff)))
113
(while (eq (setq result (vm-scroll-forward-internal arg))
115
(cond ((and (not (eq result 'next-message))
116
vm-honor-page-delimiters)
118
(goto-char (max (window-start w)
119
(vm-text-of (car vmp))))
120
;; This is needed because in some cases
121
;; the scroll-up call in vm-howl-if-emo
122
;; does not signal end-of-buffer when
123
;; it should unless we do this. This
124
;; sit-for most likely removes the need
125
;; for the (scroll-up 0) below, but
126
;; since the voodoo has worked this
127
;; long, it's probably best to let it
130
;; This voodoo is required! For some
131
;; reason the 18.52 emacs display
132
;; doesn't immediately reflect the
133
;; clip region change that occurs
134
;; above without this mantra.
136
(select-window old-w))
138
(cond ((eq result 'next-message)
140
((eq result 'end-of-message)
141
(let ((vm-message-pointer vmp))
142
(vm-emit-eom-blurb)))
144
(and (> (prefix-numeric-value arg) 0)
145
(vm-howl-if-eom)))))))
146
(if (not vm-startup-message-displayed)
147
(vm-display-startup-message)))
149
(defun vm-scroll-forward-internal (arg)
150
(let ((direction (prefix-numeric-value arg))
151
(w (selected-window)))
152
(condition-case error-data
153
(progn (scroll-up arg) nil)
154
;; this looks like it should work, but doesn't because the
155
;; redisplay code is schizophrenic when it comes to updates. A
156
;; window position may no longer be visible but
157
;; pos-visible-in-window-p will still say it is because it was
158
;; visible before some window size change happened.
160
;; (if (and (> direction 0)
161
;; (pos-visible-in-window-p
162
;; (vm-text-end-of (car vm-message-pointer))))
163
;; (signal 'end-of-buffer nil)
167
(if (or (and (< direction 0)
168
(> (point-min) (vm-text-of (car vm-message-pointer))))
169
(and (>= direction 0)
171
(vm-text-end-of (car vm-message-pointer)))))
177
(set-window-start w (point))
182
(looking-at page-delimiter))))
185
(set-window-start w (point))
187
(if (eq (car error-data) 'end-of-buffer)
188
(if vm-auto-next-message
190
(set-window-point w (point))
191
'end-of-message)))))))
193
;; exploratory scrolling, what a concept.
195
;; we do this because pos-visible-in-window-p checks the current
196
;; window configuration, while this exploratory scrolling forces
197
;; Emacs to recompute the display, giving us an up to the moment
198
;; answer about where the end of the message is going to be
199
;; visible when redisplay finally does occur.
200
(defun vm-howl-if-eom ()
201
(let ((w (get-buffer-window (current-buffer))))
204
(save-window-excursion
206
(let ((next-screen-context-lines 0))
209
(save-window-excursion
210
;; scroll-fix.el replaces scroll-up and
211
;; doesn't behave properly when it hits
212
;; end of buffer. It does this!
214
;; (message (get 'beginning-of-buffer 'error-message))
215
(let ((scroll-in-place-replace-original nil))
219
(= (vm-text-end-of (car vm-message-pointer)) (point-max))
220
(vm-emit-eom-blurb))))
222
(defun vm-emit-eom-blurb ()
223
(let ((vm-summary-uninteresting-senders-arrow "")
224
(case-fold-search nil))
225
(message (if (and (stringp vm-summary-uninteresting-senders)
226
(string-match vm-summary-uninteresting-senders
227
(vm-su-from (car vm-message-pointer))))
228
"End of message %s to %s"
229
"End of message %s from %s")
230
(vm-number-of (car vm-message-pointer))
231
(vm-summary-sprintf "%F" (car vm-message-pointer)))))
233
(defun vm-scroll-backward (&optional arg)
234
"Scroll backward a screenful of text.
235
Prefix N scrolls backward N lines."
237
(vm-scroll-forward (cond ((null arg) '-)
238
((consp arg) (list (- (car arg))))
239
((numberp arg) (- arg))
243
(defun vm-scroll-forward-one-line (&optional count)
244
"Scroll forward one line.
245
Prefix arg N means scroll forward N lines.
246
Negative arg means scroll backward."
248
(vm-scroll-forward count))
250
(defun vm-scroll-backward-one-line (&optional count)
251
"Scroll backward one line.
252
Prefix arg N means scroll backward N lines.
253
Negative arg means scroll forward."
255
(vm-scroll-forward (- count)))
257
(defun vm-highlight-headers ()
259
((and vm-xemacs-p vm-use-lucid-highlighting)
260
(require 'highlight-headers)
261
;; disable the url marking stuff, since VM has its own interface.
262
(let ((highlight-headers-mark-urls nil)
263
(highlight-headers-regexp (or vm-highlighted-header-regexp
264
highlight-headers-regexp)))
265
(highlight-headers (point-min) (point-max) t)))
268
(map-extents (function
270
(if (extent-property e 'vm-highlight)
273
(current-buffer) (point-min) (point-max))
274
(goto-char (point-min))
275
(while (vm-match-header)
276
(cond ((vm-match-header vm-highlighted-header-regexp)
277
(setq e (make-extent (vm-matched-header-contents-start)
278
(vm-matched-header-contents-end)))
279
(set-extent-property e 'face vm-highlighted-header-face)
280
(set-extent-property e 'vm-highlight t)))
281
(goto-char (vm-matched-header-end)))))
282
((fboundp 'overlay-put)
284
(setq o-lists (overlay-lists)
287
(and (overlay-get (car p) 'vm-highlight)
288
(delete-overlay (car p)))
290
(setq p (cdr o-lists))
292
(and (overlay-get (car p) 'vm-highlight)
293
(delete-overlay (car p)))
295
(goto-char (point-min))
296
(while (vm-match-header)
297
(cond ((vm-match-header vm-highlighted-header-regexp)
298
(setq p (make-overlay (vm-matched-header-contents-start)
299
(vm-matched-header-contents-end)))
300
(overlay-put p 'face vm-highlighted-header-face)
301
(overlay-put p 'vm-highlight t)))
302
(goto-char (vm-matched-header-end)))))))
304
(defun vm-energize-urls ()
305
;; Don't search too long in large regions. If the region is
306
;; large, search just the head and the tail of the region since
307
;; they tend to contain the interesting text.
308
(let ((search-limit vm-url-search-limit)
310
(if (and search-limit (> (- (point-max) (point-min)) search-limit))
311
(setq search-pairs (list (cons (point-min)
312
(+ (point-min) (/ search-limit 2)))
313
(cons (- (point-max) (/ search-limit 2))
315
(setq search-pairs (list (cons (point-min) (point-max)))))
319
(map-extents (function
321
(if (extent-property e 'vm-url)
324
(current-buffer) (point-min) (point-max))
326
(goto-char (car (car search-pairs)))
327
(while (re-search-forward vm-url-regexp (cdr (car search-pairs)) t)
329
(while (null (match-beginning n))
331
(setq e (make-extent (match-beginning n) (match-end n)))
332
(set-extent-property e 'vm-url t)
333
(if vm-highlight-url-face
334
(set-extent-property e 'face vm-highlight-url-face))
336
(let ((keymap (make-sparse-keymap))
339
(goto-char (match-beginning n))
340
(looking-at "mailto:"))
341
'vm-menu-popup-mailto-url-browser-menu
342
'vm-menu-popup-url-browser-menu)))
343
(define-key keymap 'button2 'vm-mouse-send-url-at-event)
344
(if vm-popup-menu-on-mouse-3
345
(define-key keymap 'button3 popup-function))
346
(define-key keymap "\r"
347
(function (lambda () (interactive)
348
(vm-mouse-send-url-at-position (point)))))
349
(set-extent-property e 'vm-button t)
350
(set-extent-property e 'keymap keymap)
351
(set-extent-property e 'balloon-help 'vm-url-help)
352
(set-extent-property e 'highlight t))))
353
(setq search-pairs (cdr search-pairs)))))
355
(fboundp 'overlay-put))
357
(setq o-lists (overlay-lists)
360
(and (overlay-get (car p) 'vm-url)
361
(delete-overlay (car p)))
363
(setq p (cdr o-lists))
365
(and (overlay-get (car p) 'vm-url)
366
(delete-overlay (car p)))
369
(goto-char (car (car search-pairs)))
370
(while (re-search-forward vm-url-regexp (cdr (car search-pairs)) t)
372
(while (null (match-beginning n))
374
(setq o (make-overlay (match-beginning n) (match-end n)))
375
(overlay-put o 'vm-url t)
376
(if vm-highlight-url-face
377
(overlay-put o 'face vm-highlight-url-face))
379
(let ((keymap (make-sparse-keymap))
382
(goto-char (match-beginning n))
383
(looking-at "mailto:"))
384
'vm-menu-popup-mailto-url-browser-menu
385
'vm-menu-popup-url-browser-menu)))
386
(overlay-put o 'vm-button t)
387
(overlay-put o 'mouse-face 'highlight)
388
(setq keymap (nconc keymap (current-local-map)))
389
(if vm-popup-menu-on-mouse-3
390
(define-key keymap [mouse-3] popup-function))
391
(define-key keymap "\r"
392
(function (lambda () (interactive)
393
(vm-mouse-send-url-at-position (point)))))
394
(overlay-put o 'local-map keymap))))
395
(setq search-pairs (cdr search-pairs))))))))
397
(defun vm-energize-headers ()
400
(let ((search-tuples '(("^From:" vm-menu-author-menu)
401
("^Subject:" vm-menu-subject-menu)))
402
regexp menu keymap e)
403
(map-extents (function
405
(if (extent-property e 'vm-header)
408
(current-buffer) (point-min) (point-max))
410
(goto-char (point-min))
411
(setq regexp (nth 0 (car search-tuples))
412
menu (symbol-value (nth 1 (car search-tuples))))
413
(while (re-search-forward regexp nil t)
414
(save-excursion (goto-char (match-beginning 0)) (vm-match-header))
415
(setq e (make-extent (vm-matched-header-contents-start)
416
(vm-matched-header-contents-end)))
417
(set-extent-property e 'vm-header t)
418
(setq keymap (make-sparse-keymap))
419
;; Might as well make button2 do what button3 does in
420
;; this case, since there is no default 'select'
422
(define-key keymap 'button2
423
(list 'lambda () '(interactive)
424
(list 'popup-menu (list 'quote menu))))
425
(if vm-popup-menu-on-mouse-3
426
(define-key keymap 'button3
427
(list 'lambda () '(interactive)
428
(list 'popup-menu (list 'quote menu)))))
429
(set-extent-property e 'keymap keymap)
430
(set-extent-property e 'balloon-help 'vm-mouse-3-help)
431
(set-extent-property e 'highlight t))
432
(setq search-tuples (cdr search-tuples)))))
434
(fboundp 'overlay-put))
435
(let ((search-tuples '(("^From:" vm-menu-fsfemacs-author-menu)
436
("^Subject:" vm-menu-fsfemacs-subject-menu)))
439
(setq o-lists (overlay-lists)
442
(and (overlay-get (car p) 'vm-header)
443
(delete-overlay (car p)))
445
(setq p (cdr o-lists))
447
(and (overlay-get (car p) 'vm-header)
448
(delete-overlay (car p)))
451
(goto-char (point-min))
452
(setq regexp (nth 0 (car search-tuples))
453
menu (symbol-value (nth 1 (car search-tuples))))
454
(while (re-search-forward regexp nil t)
455
(goto-char (match-end 0))
456
(save-excursion (goto-char (match-beginning 0)) (vm-match-header))
457
(setq o (make-overlay (vm-matched-header-contents-start)
458
(vm-matched-header-contents-end)))
459
(overlay-put o 'vm-header menu)
460
(overlay-put o 'mouse-face 'highlight))
461
(setq search-tuples (cdr search-tuples)))))))
463
(defun vm-display-xface ()
464
(cond (vm-xemacs-p (vm-display-xface-xemacs))
466
(and (stringp vm-uncompface-program)
467
(fboundp 'create-image)))
468
(vm-display-xface-fsfemacs))))
470
(defun vm-display-xface-xemacs ()
471
(let ((case-fold-search t) e g h)
472
(if (map-extents (function
474
(if (extent-property e 'vm-xface)
477
(current-buffer) (point-min) (point-max))
479
(goto-char (point-min))
480
(if (find-face 'vm-xface)
482
(make-face 'vm-xface)
483
(set-face-background 'vm-xface "white")
484
(set-face-foreground 'vm-xface "black"))
485
(if (re-search-forward "^X-Face:" nil t)
487
(goto-char (match-beginning 0))
489
(setq h (concat "X-Face: " (vm-matched-header-contents)))
490
(setq g (intern h vm-xface-cache))
492
(setq g (symbol-value g))
495
(list 'global (cons '(tty) [nothing]))
496
(list 'global (cons '(win) (vector 'xface ':data h))))))
497
(setq g (symbol-value g))
498
;; XXX broken. Gives extra pixel lines at the
499
;; bottom of the glyph in 19.12
500
;;(set-glyph-baseline g 100)
501
(set-glyph-face g 'vm-xface))
502
(setq e (make-extent (vm-vheaders-of (car vm-message-pointer))
503
(vm-vheaders-of (car vm-message-pointer))))
504
(set-extent-property e 'vm-xface t)
505
(set-extent-begin-glyph e g))))))
507
(defun vm-display-xface-fsfemacs ()
509
(let ((case-fold-search t) i g h ooo)
510
(setq ooo (overlays-in (point-min) (point-max)))
512
(if (overlay-get (car ooo) 'vm-xface)
513
(delete-overlay (car ooo)))
514
(setq ooo (cdr ooo)))
515
(goto-char (point-min))
516
(if (re-search-forward "^X-Face:" nil t)
518
(goto-char (match-beginning 0))
520
(setq h (vm-matched-header-contents))
521
(setq g (intern h vm-xface-cache))
523
(setq g (symbol-value g))
524
(setq i (vm-convert-xface-to-fsfemacs-image-instantiator h))
527
(setq g (symbol-value g)))
528
(t (throw 'done nil))))
529
(let ((pos (vm-vheaders-of (car vm-message-pointer)))
531
;; An image must replace the normal display of at
532
;; least one character. Since we want to put the
533
;; image at the beginning of the visible headers
534
;; section, it will obscure the first character of
535
;; that section. To display that character we add
536
;; an after-string that contains the character.
537
;; Kludge city, but it works.
538
(setq o (make-overlay (+ 0 pos) (+ 1 pos)))
539
(overlay-put o 'vm-xface t)
540
(overlay-put o 'evaporate t)
541
(overlay-put o 'after-string
542
(char-to-string (char-after pos)))
543
(overlay-put o 'display g)))))))
545
(defun vm-convert-xface-to-fsfemacs-image-instantiator (data)
546
(let ((work-buffer nil)
551
(if (not (stringp vm-uncompface-program))
553
(setq work-buffer (vm-make-work-buffer))
554
(set-buffer work-buffer)
557
(apply 'call-process-region
558
(point-min) (point-max)
559
vm-uncompface-program t t nil
560
(if vm-uncompface-accepts-dash-x '("-X") nil)))
561
(if (not (eq retval 0))
563
(if vm-uncompface-accepts-dash-x
565
(list 'image ':type 'xbm
569
':data (buffer-string))))
570
(if (not (stringp vm-icontopbm-program))
572
(goto-char (point-min))
573
(insert "/* Width=48, Height=48 */\n");
576
(point-min) (point-max)
577
vm-icontopbm-program t t nil))
578
(if (not (eq retval 0))
580
(list 'image ':type 'pbm
584
':data (buffer-string))))
585
(and work-buffer (kill-buffer work-buffer))))))
587
(defun vm-url-help (object)
589
"Use mouse button 2 to send the URL to %s.
590
Use mouse button 3 to choose a Web browser for the URL."
591
(cond ((stringp vm-url-browser) vm-url-browser)
592
((eq vm-url-browser 'w3-fetch)
594
((eq vm-url-browser 'w3-fetch-other-frame)
596
((eq vm-url-browser 'vm-mouse-send-url-to-mosaic)
598
((eq vm-url-browser 'vm-mouse-send-url-to-netscape)
600
(t (symbol-name vm-url-browser)))))
602
(defun vm-energize-urls-in-message-region (&optional start end)
604
(or start (setq start (vm-headers-of (car vm-message-pointer))))
605
(or end (setq end (vm-text-end-of (car vm-message-pointer))))
607
(if (or vm-highlight-url-face vm-url-browser)
610
(narrow-to-region start end)
611
(vm-energize-urls)))))
613
(defun vm-highlight-headers-maybe ()
614
;; highlight the headers
615
(if (or vm-highlighted-header-regexp
616
(and vm-xemacs-p vm-use-lucid-highlighting))
619
(narrow-to-region (vm-headers-of (car vm-message-pointer))
620
(vm-text-end-of (car vm-message-pointer)))
621
(vm-highlight-headers))))
623
(defun vm-energize-headers-and-xfaces ()
624
;; energize certain headers
625
(if (and vm-use-menus (vm-menu-support-possible-p))
628
(narrow-to-region (vm-headers-of (car vm-message-pointer))
629
(vm-text-of (car vm-message-pointer)))
630
(vm-energize-headers)))
631
;; display xfaces, if we can
632
(if (and vm-display-xfaces
633
(or (and vm-xemacs-p (featurep 'xface))
634
(and vm-fsfemacs-p (fboundp 'create-image)
635
(stringp vm-uncompface-program))))
638
(narrow-to-region (vm-headers-of (car vm-message-pointer))
639
(vm-text-of (car vm-message-pointer)))
640
(vm-display-xface))))
642
(defun vm-narrow-for-preview (&optional just-passing-through)
644
;; hide as much of the message body as vm-preview-lines specifies
646
(vm-vheaders-of (car vm-message-pointer))
647
(cond ((not (eq vm-preview-lines t))
649
(vm-text-end-of (car vm-message-pointer))
651
(goto-char (vm-text-of (car vm-message-pointer)))
652
(forward-line (if (natnump vm-preview-lines) vm-preview-lines 0))
653
;; KLUDGE CITY: Under XEmacs, an extent's begin-glyph
654
;; will be displayed even if the extent is at the end
655
;; of a narrowed region. Thus a message containing
656
;; only an image will have the image displayed at
657
;; preview time even if vm-preview-lines is 0 provided
658
;; vm-mime-decode-for-preview is non-nil. We kludge
659
;; a fix for this by moving everything on the preview
660
;; cutoff line one character forward, but only if
661
;; we're doing MIME decode for preview.
662
(if (and (not just-passing-through)
664
vm-mail-buffer ; in presentation buffer
665
vm-auto-decode-mime-messages
666
vm-mime-decode-for-preview
667
;; can't do the kludge unless we know that
668
;; when the message is exposed it will be
669
;; decoded and thereby remove the kludge.
670
(not (vm-mime-plain-message-p (car vm-message-pointer))))
671
(let ((buffer-read-only nil))
675
(t (vm-text-end-of (car vm-message-pointer))))))
677
(defun vm-preview-current-message ()
678
;; Set just-passing-through if the user will never see the
679
;; message in the previewed state. Save some time later by not
680
;; doing preview action that the user will never see anyway.
681
(let ((just-passing-through
682
(or (null vm-preview-lines)
683
(and (not vm-preview-read-messages)
684
(not (vm-new-flag (car vm-message-pointer)))
685
(not (vm-unread-flag (car vm-message-pointer)))))))
686
(vm-save-buffer-excursion
687
(setq vm-system-state 'previewing
690
(vm-make-virtual-copy (car vm-message-pointer)))
692
;; run the message select hooks.
694
(vm-select-folder-buffer)
695
(vm-run-message-hook (car vm-message-pointer) 'vm-select-message-hook)
696
(and vm-select-new-message-hook (vm-new-flag (car vm-message-pointer))
697
(vm-run-message-hook (car vm-message-pointer)
698
'vm-select-new-message-hook))
699
(and vm-select-unread-message-hook
700
(vm-unread-flag (car vm-message-pointer))
701
(vm-run-message-hook (car vm-message-pointer)
702
'vm-select-unread-message-hook)))
704
(vm-narrow-for-preview just-passing-through)
705
(if (or vm-mime-display-function
706
(natnump vm-fill-paragraphs-containing-long-lines)
707
(and vm-display-using-mime vm-auto-decode-mime-messages
708
(not (vm-mime-plain-message-p (car vm-message-pointer)))))
709
(let ((layout (vm-mm-layout (car vm-message-pointer))))
710
(vm-make-presentation-copy (car vm-message-pointer))
711
(vm-save-buffer-excursion
712
(vm-replace-buffer-in-windows (current-buffer)
713
vm-presentation-buffer))
714
(set-buffer vm-presentation-buffer)
715
(setq vm-system-state 'previewing)
716
(vm-narrow-for-preview))
717
(setq vm-presentation-buffer nil)
718
(and vm-presentation-buffer-handle
719
(vm-replace-buffer-in-windows vm-presentation-buffer-handle
722
;; at this point the current buffer is the presentation buffer
723
;; if we're using one for this message.
724
(vm-unbury-buffer (current-buffer))
726
(if (and vm-display-using-mime
727
vm-auto-decode-mime-messages
728
vm-mime-decode-for-preview
729
(not just-passing-through)
731
(not (vm-buffer-variable-value vm-mail-buffer
733
(not vm-mime-decoded))
734
(not (vm-mime-plain-message-p (car vm-message-pointer))))
735
(if (eq vm-preview-lines 0)
737
(vm-decode-mime-message-headers (car vm-message-pointer))
739
(vm-highlight-headers-maybe)
740
(vm-energize-headers-and-xfaces))
741
;; restrict the things that are auto-displayed, since
742
;; decode-for-preview is meant to allow a numeric
743
;; vm-preview-lines to be useful in the face of multipart
745
(let ((vm-auto-displayed-mime-content-type-exceptions
746
(cons "message/external-body"
747
vm-auto-displayed-mime-content-type-exceptions))
748
(vm-mime-external-content-types-alist nil))
751
(vm-decode-mime-message)
752
;; reset vm-mime-decoded so that when the user
753
;; opens the message completely, the full MIME
754
;; display will happen.
756
(vm-set-buffer-variable vm-mail-buffer
757
'vm-mime-decoded nil)))
758
(vm-mime-error (vm-set-mime-layout-of (car vm-message-pointer)
760
(message "%s" (car (cdr data)))))
761
(vm-narrow-for-preview)))
762
(vm-energize-urls-in-message-region)
763
(vm-highlight-headers-maybe)
764
(vm-energize-headers-and-xfaces))
766
(if (and vm-honor-page-delimiters (not just-passing-through))
768
(goto-char (vm-text-of (car vm-message-pointer)))
769
;; If we have a window, set window start appropriately.
770
(let ((w (vm-get-visible-buffer-window (current-buffer))))
772
(progn (set-window-start w (point-min))
773
(set-window-point w (vm-text-of (car vm-message-pointer))))))
774
(if just-passing-through
775
(vm-show-current-message)
776
(vm-update-summary-and-mode-line)))))
778
(defun vm-show-current-message ()
779
(and vm-display-using-mime
780
vm-auto-decode-mime-messages
782
(not (vm-buffer-variable-value vm-mail-buffer 'vm-mime-decoded))
783
(not vm-mime-decoded))
784
(not (vm-mime-plain-message-p (car vm-message-pointer)))
786
(vm-decode-mime-message)
787
(vm-mime-error (vm-set-mime-layout-of (car vm-message-pointer)
789
(message "%s" (car (cdr data))))))
790
(if (and (natnump vm-fill-paragraphs-containing-long-lines)
791
(vm-mime-plain-message-p (car vm-message-pointer)))
792
(let ((needmsg (> (- (vm-text-end-of (car vm-message-pointer))
793
(vm-text-of (car vm-message-pointer)))
796
(message "Searching for paragraphs to fill..."))
797
(vm-fill-paragraphs-containing-long-lines
798
vm-fill-paragraphs-containing-long-lines
799
(vm-text-of (car vm-message-pointer))
800
(vm-text-end-of (car vm-message-pointer)))
802
(message "Searching for paragraphs to fill... done"))))
803
(vm-save-buffer-excursion
806
(goto-char (point-min))
808
(narrow-to-region (point) (vm-text-end-of (car vm-message-pointer))))
809
(if vm-honor-page-delimiters
811
(if (looking-at page-delimiter)
813
(vm-narrow-to-page))))
814
;; don't mark the message as read if the user can't see it!
815
(if (vm-get-visible-buffer-window (current-buffer))
818
(setq vm-system-state 'showing)
820
(vm-set-buffer-variable vm-mail-buffer 'vm-system-state
822
;; We could be in the presentation buffer here. Since
823
;; the presentation buffer's message pointer and sole
824
;; message are a mockup, they will cause trouble if
825
;; passed into the undo/update system. So we switch
826
;; into the real message buffer to do attribute
828
(vm-select-folder-buffer)
829
(cond ((vm-new-flag (car vm-message-pointer))
830
(vm-set-new-flag (car vm-message-pointer) nil)))
831
(cond ((vm-unread-flag (car vm-message-pointer))
832
(vm-set-unread-flag (car vm-message-pointer) nil))))
833
(vm-update-summary-and-mode-line)
835
(vm-update-summary-and-mode-line))))
837
(defun vm-expose-hidden-headers ()
838
"Toggle exposing and hiding message headers that are normally not visible."
840
(vm-follow-summary-cursor)
841
(vm-select-folder-buffer)
842
(vm-check-for-killed-summary)
843
(vm-check-for-killed-presentation)
844
(vm-error-if-folder-empty)
845
(and vm-presentation-buffer
846
(set-buffer vm-presentation-buffer))
847
(vm-display (current-buffer) t '(vm-expose-hidden-headers)
848
'(vm-expose-hidden-headers reading-message))
849
(let* ((exposed (= (point-min) (vm-start-of (car vm-message-pointer)))))
851
(goto-char (point-max))
854
(narrow-to-region (point) (vm-vheaders-of (car vm-message-pointer)))
855
(narrow-to-region (point) (vm-start-of (car vm-message-pointer))))
856
(goto-char (point-min))
858
(setq w (vm-get-visible-buffer-window (current-buffer)))
859
(and w (set-window-point w (point-min)))
861
(= (window-start w) (vm-vheaders-of (car vm-message-pointer)))
863
(set-window-start w (vm-start-of (car vm-message-pointer)))))
864
(if vm-honor-page-delimiters
865
(vm-narrow-to-page))))
867
(defun vm-widen-page ()
868
(if (or (> (point-min) (vm-text-of (car vm-message-pointer)))
869
(/= (point-max) (vm-text-end-of (car vm-message-pointer))))
870
(narrow-to-region (vm-vheaders-of (car vm-message-pointer))
871
(if (or (vm-new-flag (car vm-message-pointer))
872
(vm-unread-flag (car vm-message-pointer)))
873
(vm-text-of (car vm-message-pointer))
874
(vm-text-end-of (car vm-message-pointer))))))
876
(defun vm-narrow-to-page ()
878
(if (not (and vm-page-end-overlay
879
(overlay-buffer vm-page-end-overlay)))
880
(let ((g vm-page-continuation-glyph))
881
(setq vm-page-end-overlay (make-overlay (point) (point)))
882
(vm-set-extent-property vm-page-end-overlay 'vm-glyph g)
883
(vm-set-extent-property vm-page-end-overlay 'before-string g)
884
(overlay-put vm-page-end-overlay 'evaporate nil))))
886
(if (not (and vm-page-end-overlay
887
(extent-end-position vm-page-end-overlay)))
888
(let ((g vm-page-continuation-glyph))
889
(cond ((not (glyphp g))
890
(setq g (make-glyph g))
891
(set-glyph-face g 'italic)))
892
(setq vm-page-end-overlay (make-extent (point) (point)))
893
(vm-set-extent-property vm-page-end-overlay 'vm-glyph g)
894
(vm-set-extent-property vm-page-end-overlay 'begin-glyph g)
895
(set-extent-property vm-page-end-overlay 'detachable nil)))))
897
(let (min max (e vm-page-end-overlay))
898
(if (or (bolp) (not (save-excursion
900
(looking-at page-delimiter))))
906
(cond ((/= (point) (vm-text-end-of (car vm-message-pointer)))
907
(vm-set-extent-property e vm-begin-glyph-property
908
(vm-extent-property e 'vm-glyph))
909
(vm-set-extent-endpoints e (point) (point)))
911
(vm-set-extent-property e vm-begin-glyph-property nil)))
913
(narrow-to-region min max))))
915
(defun vm-beginning-of-message ()
916
"Moves to the beginning of the current message."
918
(vm-follow-summary-cursor)
919
(vm-select-folder-buffer)
920
(vm-check-for-killed-summary)
921
(vm-check-for-killed-presentation)
922
(vm-error-if-folder-empty)
923
(and vm-presentation-buffer
924
(set-buffer vm-presentation-buffer))
927
(vm-display (current-buffer) t '(vm-beginning-of-message)
928
'(vm-beginning-of-message reading-message))
929
(vm-save-buffer-excursion
930
(let ((osw (selected-window)))
933
(select-window (vm-get-visible-buffer-window (current-buffer)))
934
(goto-char (point-min)))
935
(if (not (eq osw (selected-window)))
936
(select-window osw)))))
937
(if vm-honor-page-delimiters
938
(vm-narrow-to-page)))
940
(defun vm-end-of-message ()
941
"Moves to the end of the current message, exposing and flagging it read
944
(vm-follow-summary-cursor)
945
(vm-select-folder-buffer)
946
(vm-check-for-killed-summary)
947
(vm-check-for-killed-presentation)
948
(vm-error-if-folder-empty)
949
(and vm-presentation-buffer
950
(set-buffer vm-presentation-buffer))
951
(if (eq vm-system-state 'previewing)
952
(vm-show-current-message))
953
(setq vm-system-state 'reading)
956
(vm-display (current-buffer) t '(vm-end-of-message)
957
'(vm-end-of-message reading-message))
958
(vm-save-buffer-excursion
959
(let ((osw (selected-window)))
962
(select-window (vm-get-visible-buffer-window (current-buffer)))
963
(goto-char (point-max)))
964
(if (not (eq osw (selected-window)))
965
(select-window osw)))))
966
(if vm-honor-page-delimiters
967
(vm-narrow-to-page)))
969
(defun vm-move-to-next-button (count)
970
"Moves to the next button in the current message.
971
Prefix argument N means move to the Nth next button.
972
Negative N means move to the Nth previous button.
973
If there is no next button, an error is signaled and point is not moved.
975
A button is a highlighted region of text where pressing RETURN
976
will produce an action. If the message is being previewed, it is
977
exposed and marked as read."
979
(vm-follow-summary-cursor)
980
(vm-select-folder-buffer)
981
(vm-check-for-killed-summary)
982
(vm-check-for-killed-presentation)
983
(vm-error-if-folder-empty)
984
(and vm-presentation-buffer
985
(set-buffer vm-presentation-buffer))
986
(if (eq vm-system-state 'previewing)
987
(vm-show-current-message))
988
(setq vm-system-state 'reading)
990
(vm-display (current-buffer) t '(vm-move-to-next-button)
991
'(vm-move-to-next-button reading-message))
992
(select-window (vm-get-visible-buffer-window (current-buffer)))
994
(vm-move-to-xxxx-button (vm-abs count) (>= count 0))
995
(if vm-honor-page-delimiters
996
(vm-narrow-to-page))))
998
(defun vm-move-to-previous-button (count)
999
"Moves to the previous button in the current message.
1000
Prefix argument N means move to the Nth previous button.
1001
Negative N means move to the Nth next button.
1002
If there is no previous button, an error is signaled and point is not moved.
1004
A button is a highlighted region of text where pressing RETURN
1005
will produce an action. If the message is being previewed, it is
1006
exposed and marked as read."
1008
(vm-follow-summary-cursor)
1009
(vm-select-folder-buffer)
1010
(vm-check-for-killed-summary)
1011
(vm-check-for-killed-presentation)
1012
(vm-error-if-folder-empty)
1013
(and vm-presentation-buffer
1014
(set-buffer vm-presentation-buffer))
1015
(if (eq vm-system-state 'previewing)
1016
(vm-show-current-message))
1017
(setq vm-system-state 'reading)
1019
(vm-display (current-buffer) t '(vm-move-to-previous-button)
1020
'(vm-move-to-previous-button reading-message))
1021
(select-window (vm-get-visible-buffer-window (current-buffer)))
1023
(vm-move-to-xxxx-button (vm-abs count) (< count 0))
1024
(if vm-honor-page-delimiters
1025
(vm-narrow-to-page))))
1027
(defun vm-move-to-xxxx-button (count next)
1028
(let ((old-point (point))
1029
(endp (if next 'eobp 'bobp))
1030
(extent-end-position (if vm-xemacs-p
1032
'extent-end-position
1033
'extent-start-position)
1037
(next-extent-change (if vm-xemacs-p
1040
'previous-extent-change)
1042
'next-overlay-change
1043
'previous-overlay-change)))
1045
(while (and (> count 0) (not (funcall endp)))
1046
(goto-char (funcall next-extent-change (+ (point) (if next 0 -1))))
1047
(setq e (vm-extent-at (point)))
1050
(if (vm-extent-property e 'vm-button)
1051
(vm-decrement count))
1052
(goto-char (funcall extent-end-position e)))))
1054
(goto-char (vm-extent-start-position e))
1055
(goto-char old-point)
1056
(error "No more buttons"))))