Mercurial > hg > xemacs-beta
comparison lisp/vm/vm-page.el @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children | 859a2309aef8 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:376386a54a3c |
---|---|
1 ;;; Commands to move around within a VM message | |
2 ;;; Copyright (C) 1989, 1990, 1991, 1993, 1994 Kyle E. Jones | |
3 ;;; | |
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) | |
7 ;;; any later version. | |
8 ;;; | |
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. | |
13 ;;; | |
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. | |
17 | |
18 (provide 'vm-page) | |
19 | |
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." | |
26 (interactive "P") | |
27 (let ((mp-changed (vm-follow-summary-cursor)) | |
28 (was-invisible nil)) | |
29 (vm-select-folder-buffer) | |
30 (vm-check-for-killed-summary) | |
31 (vm-error-if-folder-empty) | |
32 (if (null (vm-get-visible-buffer-window (current-buffer))) | |
33 (let ((point (point))) | |
34 (vm-display (current-buffer) t | |
35 '(vm-scroll-forward vm-scroll-backward) | |
36 (list this-command 'reading-message)) | |
37 ;; window start sticks to end of clip region when clip | |
38 ;; region moves back past it in the buffer. fix it. | |
39 (let ((w (vm-get-visible-buffer-window (current-buffer)))) | |
40 (if (= (window-start w) (point-max)) | |
41 (set-window-start w (point-min)))) | |
42 (setq was-invisible t))) | |
43 (if (or mp-changed was-invisible | |
44 (and (eq vm-system-state 'previewing) | |
45 (pos-visible-in-window-p | |
46 (point-max) | |
47 (vm-get-visible-buffer-window (current-buffer))))) | |
48 (progn | |
49 (if (not was-invisible) | |
50 (let ((w (vm-get-visible-buffer-window (current-buffer))) | |
51 old-w-start) | |
52 (setq old-w-start (window-start w)) | |
53 (vm-display nil nil '(vm-scroll-forward vm-scroll-backward) | |
54 (list this-command 'reading-message)) | |
55 (setq w (vm-get-visible-buffer-window (current-buffer))) | |
56 (and w (set-window-start w old-w-start)))) | |
57 (if (eq vm-system-state 'previewing) | |
58 (vm-show-current-message)) | |
59 (vm-howl-if-eom)) | |
60 (let ((vmp vm-message-pointer) | |
61 (msg-buf (current-buffer)) | |
62 (h-diff 0) | |
63 w old-w old-w-height old-w-start result) | |
64 (if (eq vm-system-state 'previewing) | |
65 (vm-show-current-message)) | |
66 (setq vm-system-state 'reading) | |
67 (setq old-w (vm-get-visible-buffer-window msg-buf) | |
68 old-w-height (window-height old-w) | |
69 old-w-start (window-start old-w)) | |
70 (vm-display nil nil '(vm-scroll-forward vm-scroll-backward) | |
71 (list this-command 'reading-message)) | |
72 (setq w (vm-get-visible-buffer-window msg-buf)) | |
73 (if (null w) | |
74 (error "current window configuration hides the message buffer.") | |
75 (setq h-diff (- (window-height w) old-w-height))) | |
76 ;; must restore this since it gets clobbered by window | |
77 ;; teardown and rebuild done by the window config stuff. | |
78 (set-window-start w old-w-start) | |
79 (setq old-w (selected-window)) | |
80 (unwind-protect | |
81 (progn | |
82 (select-window w) | |
83 (let ((next-screen-context-lines | |
84 (+ next-screen-context-lines h-diff))) | |
85 (while (eq (setq result (vm-scroll-forward-internal arg)) | |
86 'tryagain)) | |
87 (cond ((and (not (eq result 'next-message)) | |
88 vm-honor-page-delimiters) | |
89 (vm-narrow-to-page) | |
90 ;; This voodoo is required! For some | |
91 ;; reason the 18.52 emacs display | |
92 ;; doesn't immediately reflect the | |
93 ;; clip region change that occurs | |
94 ;; above without this mantra. | |
95 (scroll-up 0))))) | |
96 (select-window old-w)) | |
97 (set-buffer msg-buf) | |
98 (cond ((eq result 'next-message) | |
99 (vm-next-message)) | |
100 ((eq result 'end-of-message) | |
101 (let ((vm-message-pointer vmp)) | |
102 (vm-emit-eom-blurb))) | |
103 (t | |
104 (and (> (prefix-numeric-value arg) 0) | |
105 (vm-howl-if-eom))))))) | |
106 (if (not (or vm-startup-message-displayed vm-inhibit-startup-message)) | |
107 (vm-display-startup-message))) | |
108 | |
109 (defun vm-scroll-forward-internal (arg) | |
110 (let ((direction (prefix-numeric-value arg)) | |
111 (w (selected-window))) | |
112 (condition-case error-data | |
113 (progn (scroll-up arg) nil) | |
114 (error | |
115 (if (or (and (< direction 0) | |
116 (> (point-min) (vm-text-of (car vm-message-pointer)))) | |
117 (and (>= direction 0) | |
118 (/= (point-max) | |
119 (vm-text-end-of (car vm-message-pointer))))) | |
120 (progn | |
121 (vm-widen-page) | |
122 (if (>= direction 0) | |
123 (progn | |
124 (forward-page 1) | |
125 (set-window-start w (point)) | |
126 nil ) | |
127 (if (or (bolp) | |
128 (not (save-excursion | |
129 (beginning-of-line) | |
130 (looking-at page-delimiter)))) | |
131 (forward-page -1)) | |
132 (beginning-of-line) | |
133 (set-window-start w (point)) | |
134 'tryagain)) | |
135 (if (eq (car error-data) 'end-of-buffer) | |
136 (if vm-auto-next-message | |
137 'next-message | |
138 (set-window-point w (point)) | |
139 'end-of-message))))))) | |
140 | |
141 ;; exploratory scrolling, what a concept. | |
142 ;; | |
143 ;; we do this because pos-visible-in-window-p checks the current | |
144 ;; window configuration, while this exploratory scrolling forces | |
145 ;; Emacs to recompute the display, giving us an up to the moment | |
146 ;; answer about where the end of the message is going to be | |
147 ;; visible when redisplay finally does occur. | |
148 (defun vm-howl-if-eom () | |
149 (let ((w (vm-get-visible-buffer-window (current-buffer)))) | |
150 (and w | |
151 (save-excursion | |
152 (save-window-excursion | |
153 (condition-case () | |
154 (let ((next-screen-context-lines 0)) | |
155 (select-window w) | |
156 (save-excursion | |
157 (save-window-excursion | |
158 ;; scroll-fix.el replaces scroll-up and | |
159 ;; doesn't behave properly when it hits | |
160 ;; end of buffer. It does this! | |
161 ;; (ding) | |
162 ;; (message (get 'beginning-of-buffer 'error-message)) | |
163 (let ((scroll-in-place-replace-original nil)) | |
164 (scroll-up nil)))) | |
165 nil) | |
166 (error t)))) | |
167 (= (vm-text-end-of (car vm-message-pointer)) (point-max)) | |
168 (vm-emit-eom-blurb)))) | |
169 | |
170 (defun vm-emit-eom-blurb () | |
171 (if (vm-full-name-of (car vm-message-pointer)) | |
172 (vm-unsaved-message "End of message %s from %s" | |
173 (vm-number-of (car vm-message-pointer)) | |
174 (vm-full-name-of (car vm-message-pointer))) | |
175 (vm-unsaved-message "End of message %s" | |
176 (vm-number-of (car vm-message-pointer))))) | |
177 | |
178 (defun vm-scroll-backward (arg) | |
179 "Scroll backward a screenful of text. | |
180 Prefix N scrolls backward N lines." | |
181 (interactive "P") | |
182 (vm-scroll-forward (cond ((null arg) '-) | |
183 ((consp arg) (list (- (car arg)))) | |
184 ((numberp arg) (- arg)) | |
185 ((symbolp arg) nil) | |
186 (t arg)))) | |
187 | |
188 (defun vm-highlight-headers () | |
189 (cond | |
190 ((and (vm-xemacs-p) vm-use-lucid-highlighting) | |
191 (require 'highlight-headers) | |
192 ;; disable the url marking stuff, since VM has its own interface. | |
193 (let ((highlight-headers-mark-urls nil) | |
194 (highlight-headers-regexp (or vm-highlighted-header-regexp | |
195 highlight-headers-regexp))) | |
196 (highlight-headers (point-min) (point-max) t))) | |
197 ((vm-xemacs-p) | |
198 (let (e) | |
199 (map-extents (function | |
200 (lambda (e ignore) | |
201 (if (extent-property e 'vm-highlight) | |
202 (delete-extent e)) | |
203 nil)) | |
204 (current-buffer) (point-min) (point-max)) | |
205 (goto-char (point-min)) | |
206 (while (vm-match-header) | |
207 (cond ((vm-match-header vm-highlighted-header-regexp) | |
208 (setq e (make-extent (vm-matched-header-contents-start) | |
209 (vm-matched-header-contents-end))) | |
210 (set-extent-property e 'face vm-highlighted-header-face) | |
211 (set-extent-property e 'vm-highlight t))) | |
212 (goto-char (vm-matched-header-end))))) | |
213 ((fboundp 'overlay-put) | |
214 (let (o-lists p) | |
215 (setq o-lists (overlay-lists) | |
216 p (car o-lists)) | |
217 (while p | |
218 (and (overlay-get (car p) 'vm-highlight) | |
219 (delete-overlay (car p))) | |
220 (setq p (cdr p))) | |
221 (setq p (cdr o-lists)) | |
222 (while p | |
223 (and (overlay-get (car p) 'vm-highlight) | |
224 (delete-overlay (car p))) | |
225 (setq p (cdr p))) | |
226 (goto-char (point-min)) | |
227 (while (vm-match-header) | |
228 (cond ((vm-match-header vm-highlighted-header-regexp) | |
229 (setq p (make-overlay (vm-matched-header-contents-start) | |
230 (vm-matched-header-contents-end))) | |
231 (overlay-put p 'face vm-highlighted-header-face) | |
232 (overlay-put p 'vm-highlight t))) | |
233 (goto-char (vm-matched-header-end))))))) | |
234 | |
235 (defun vm-energize-urls () | |
236 ;; Don't search too long in large regions. If the region is | |
237 ;; large, search just the head and the tail of the region since | |
238 ;; they tend to contain the interesting text. | |
239 (let ((search-limit vm-url-search-limit) | |
240 (search-pairs)) | |
241 (if (and search-limit (> (- (point-max) (point-min)) search-limit)) | |
242 (setq search-pairs (list (cons (point-min) | |
243 (+ (point-min) (/ search-limit 2))) | |
244 (cons (- (point-max) (/ search-limit 2)) | |
245 (point-max)))) | |
246 (setq search-pairs (list (cons (point-min) (point-max))))) | |
247 (cond | |
248 ((vm-xemacs-p) | |
249 (let (e) | |
250 (map-extents (function | |
251 (lambda (e ignore) | |
252 (if (extent-property e 'vm-url) | |
253 (delete-extent e)) | |
254 nil)) | |
255 (current-buffer) (point-min) (point-max)) | |
256 (while search-pairs | |
257 (goto-char (car (car search-pairs))) | |
258 (while (re-search-forward vm-url-regexp (cdr (car search-pairs)) t) | |
259 (setq e (make-extent (match-beginning 0) (match-end 0))) | |
260 (set-extent-property e 'vm-url t) | |
261 (if vm-highlight-url-face | |
262 (set-extent-property e 'face vm-highlight-url-face)) | |
263 (if vm-url-browser | |
264 (let ((keymap (make-sparse-keymap))) | |
265 (define-key keymap 'button2 'vm-mouse-send-url-at-event) | |
266 (define-key keymap 'button3 'vm-menu-popup-url-browser-menu) | |
267 (define-key keymap "\r" | |
268 (function (lambda () (interactive) | |
269 (vm-mouse-send-url-at-position (point))))) | |
270 (set-extent-property e 'keymap keymap) | |
271 (set-extent-property e 'balloon-help 'vm-url-help) | |
272 (set-extent-property e 'highlight t)))) | |
273 (setq search-pairs (cdr search-pairs))))) | |
274 ((and (vm-fsfemacs-19-p) | |
275 (fboundp 'overlay-put)) | |
276 (let (o-lists o p) | |
277 (setq o-lists (overlay-lists) | |
278 p (car o-lists)) | |
279 (while p | |
280 (and (overlay-get (car p) 'vm-url) | |
281 (delete-overlay (car p))) | |
282 (setq p (cdr p))) | |
283 (setq p (cdr o-lists)) | |
284 (while p | |
285 (and (overlay-get (car p) 'vm-url) | |
286 (delete-overlay (car p))) | |
287 (setq p (cdr p))) | |
288 (while search-pairs | |
289 (goto-char (car (car search-pairs))) | |
290 (while (re-search-forward vm-url-regexp (cdr (car search-pairs)) t) | |
291 (setq o (make-overlay (match-beginning 0) (match-end 0))) | |
292 (overlay-put o 'vm-url t) | |
293 (if vm-highlight-url-face | |
294 (overlay-put o 'face vm-highlight-url-face)) | |
295 (if vm-url-browser | |
296 (overlay-put o 'mouse-face 'highlight))) | |
297 (setq search-pairs (cdr search-pairs)))))))) | |
298 | |
299 (defun vm-energize-headers () | |
300 (cond | |
301 ((vm-xemacs-p) | |
302 (let ((search-tuples '(("^From:" vm-menu-author-menu) | |
303 ("^Subject:" vm-menu-subject-menu))) | |
304 regexp menu keymap e) | |
305 (map-extents (function | |
306 (lambda (e ignore) | |
307 (if (extent-property e 'vm-header) | |
308 (delete-extent e)) | |
309 nil)) | |
310 (current-buffer) (point-min) (point-max)) | |
311 (while search-tuples | |
312 (goto-char (point-min)) | |
313 (setq regexp (nth 0 (car search-tuples)) | |
314 menu (symbol-value (nth 1 (car search-tuples)))) | |
315 (while (re-search-forward regexp nil t) | |
316 (save-excursion (goto-char (match-beginning 0)) (vm-match-header)) | |
317 (setq e (make-extent (vm-matched-header-contents-start) | |
318 (vm-matched-header-contents-end))) | |
319 (set-extent-property e 'vm-header t) | |
320 (setq keymap (make-sparse-keymap)) | |
321 ;; Might as well make button2 do what button3 does in | |
322 ;; this case, since there is no default 'select' | |
323 ;; action. | |
324 (define-key keymap 'button2 | |
325 (list 'lambda () '(interactive) | |
326 (list 'popup-menu (list 'quote menu)))) | |
327 (define-key keymap 'button3 | |
328 (list 'lambda () '(interactive) | |
329 (list 'popup-menu (list 'quote menu)))) | |
330 (set-extent-property e 'keymap keymap) | |
331 (set-extent-property e 'balloon-help 'vm-mouse-3-help) | |
332 (set-extent-property e 'highlight t)) | |
333 (setq search-tuples (cdr search-tuples))))) | |
334 ((and (vm-fsfemacs-19-p) | |
335 (fboundp 'overlay-put)) | |
336 (let ((search-tuples '(("^From:" vm-menu-fsfemacs-author-menu) | |
337 ("^Subject:" vm-menu-fsfemacs-subject-menu))) | |
338 regexp menu | |
339 o-lists o p) | |
340 (setq o-lists (overlay-lists) | |
341 p (car o-lists)) | |
342 (while p | |
343 (and (overlay-get (car p) 'vm-header) | |
344 (delete-overlay (car p))) | |
345 (setq p (cdr p))) | |
346 (setq p (cdr o-lists)) | |
347 (while p | |
348 (and (overlay-get (car p) 'vm-header) | |
349 (delete-overlay (car p))) | |
350 (setq p (cdr p))) | |
351 (while search-tuples | |
352 (goto-char (point-min)) | |
353 (setq regexp (nth 0 (car search-tuples)) | |
354 menu (symbol-value (nth 1 (car search-tuples)))) | |
355 (while (re-search-forward regexp nil t) | |
356 (goto-char (match-end 0)) | |
357 (save-excursion (goto-char (match-beginning 0)) (vm-match-header)) | |
358 (setq o (make-overlay (vm-matched-header-contents-start) | |
359 (vm-matched-header-contents-end))) | |
360 (overlay-put o 'vm-header menu) | |
361 (overlay-put o 'mouse-face 'highlight)) | |
362 (setq search-tuples (cdr search-tuples))))))) | |
363 | |
364 (defun vm-display-xface () | |
365 (let ((case-fold-search t) e g h) | |
366 (if (map-extents (function | |
367 (lambda (e ignore) | |
368 (if (extent-property e 'vm-xface) | |
369 t | |
370 nil))) | |
371 (current-buffer) (point-min) (point-max)) | |
372 nil | |
373 (goto-char (point-min)) | |
374 (if (find-face 'vm-xface) | |
375 nil | |
376 (make-face 'vm-xface) | |
377 (set-face-background 'vm-xface "white") | |
378 (set-face-foreground 'vm-xface "black")) | |
379 (if (re-search-forward "^X-Face:" nil t) | |
380 (progn | |
381 (goto-char (match-beginning 0)) | |
382 (vm-match-header) | |
383 (setq h (vm-matched-header)) | |
384 (setq g (intern h vm-xface-cache)) | |
385 (if (boundp g) | |
386 (setq g (symbol-value g)) | |
387 (set g (make-glyph h)) | |
388 (setq g (symbol-value g)) | |
389 ;; XXX broken. Gives extra pixel lines at the | |
390 ;; bottom of the glyph in 19.12 | |
391 ;;(set-glyph-baseline g 100) | |
392 (set-glyph-face g 'vm-xface)) | |
393 (setq e (make-extent (vm-vheaders-of (car vm-message-pointer)) | |
394 (vm-vheaders-of (car vm-message-pointer)))) | |
395 (set-extent-property e 'vm-xface t) | |
396 (set-extent-begin-glyph e g)))))) | |
397 | |
398 (defun vm-url-help (object) | |
399 (format | |
400 "Use mouse button 2 to send the URL to %s. | |
401 Use mouse button 3 to choose a Web browser for the URL." | |
402 (cond ((stringp vm-url-browser) vm-url-browser) | |
403 ((eq vm-url-browser 'w3-fetch) | |
404 "Emacs W3") | |
405 ((eq vm-url-browser 'w3-fetch-other-frame) | |
406 "Emacs W3") | |
407 ((eq vm-url-browser 'vm-mouse-send-url-to-mosaic) | |
408 "Mosaic") | |
409 ((eq vm-url-browser 'vm-mouse-send-url-to-netscape) | |
410 "Netscape") | |
411 (t (symbol-name vm-url-browser))))) | |
412 | |
413 (defun vm-preview-current-message () | |
414 (setq vm-system-state 'previewing) | |
415 (if vm-real-buffers | |
416 (vm-make-virtual-copy (car vm-message-pointer))) | |
417 (widen) | |
418 ;; hide as much of the message body as vm-preview-lines specifies | |
419 (narrow-to-region | |
420 (vm-vheaders-of (car vm-message-pointer)) | |
421 (cond ((not (eq vm-preview-lines t)) | |
422 (min | |
423 (vm-text-end-of (car vm-message-pointer)) | |
424 (save-excursion | |
425 (goto-char (vm-text-of (car vm-message-pointer))) | |
426 (forward-line (if (natnump vm-preview-lines) vm-preview-lines 0)) | |
427 (point)))) | |
428 (t (vm-text-end-of (car vm-message-pointer))))) | |
429 ;; highlight the headers | |
430 (if (or vm-highlighted-header-regexp | |
431 (and (vm-xemacs-p) vm-use-lucid-highlighting)) | |
432 (save-restriction | |
433 (widen) | |
434 (narrow-to-region (vm-headers-of (car vm-message-pointer)) | |
435 (vm-text-end-of (car vm-message-pointer))) | |
436 (vm-highlight-headers))) | |
437 ;; energize the URLs | |
438 (if (or vm-highlight-url-face vm-url-browser) | |
439 (save-restriction | |
440 (widen) | |
441 (narrow-to-region (vm-headers-of (car vm-message-pointer)) | |
442 (vm-text-end-of (car vm-message-pointer))) | |
443 (vm-energize-urls))) | |
444 ;; energize certain headers | |
445 (if (and vm-use-menus (vm-menu-support-possible-p)) | |
446 (save-restriction | |
447 (widen) | |
448 (narrow-to-region (vm-headers-of (car vm-message-pointer)) | |
449 (vm-text-of (car vm-message-pointer))) | |
450 (vm-energize-headers))) | |
451 | |
452 ;; display xfaces, if we can | |
453 (if (and vm-display-xfaces | |
454 (vm-xemacs-p) | |
455 (vm-multiple-frames-possible-p) | |
456 (featurep 'xface)) | |
457 (save-restriction | |
458 (widen) | |
459 (narrow-to-region (vm-headers-of (car vm-message-pointer)) | |
460 (vm-text-of (car vm-message-pointer))) | |
461 (vm-display-xface))) | |
462 | |
463 (vm-run-message-hook (car vm-message-pointer) 'vm-select-message-hook) | |
464 (and vm-select-new-message-hook (vm-new-flag (car vm-message-pointer)) | |
465 (vm-run-message-hook (car vm-message-pointer) | |
466 'vm-select-new-message-hook)) | |
467 (and vm-select-unread-message-hook (vm-unread-flag (car vm-message-pointer)) | |
468 (vm-run-message-hook (car vm-message-pointer) | |
469 'vm-select-unread-message-hook)) | |
470 | |
471 (if vm-honor-page-delimiters | |
472 (vm-narrow-to-page)) | |
473 (goto-char (vm-text-of (car vm-message-pointer))) | |
474 ;; If we have a window, set window start appropriately. | |
475 (let ((w (vm-get-visible-buffer-window (current-buffer)))) | |
476 (if w | |
477 (progn (set-window-start w (point-min)) | |
478 (set-window-point w (vm-text-of (car vm-message-pointer)))))) | |
479 (if (or (null vm-preview-lines) | |
480 (and (not vm-preview-read-messages) | |
481 (not (vm-new-flag (car vm-message-pointer))) | |
482 (not (vm-unread-flag (car vm-message-pointer))))) | |
483 (vm-show-current-message) | |
484 (vm-update-summary-and-mode-line))) | |
485 | |
486 (defun vm-show-current-message () | |
487 (save-excursion | |
488 (save-excursion | |
489 (goto-char (point-min)) | |
490 (widen) | |
491 (narrow-to-region (point) (vm-text-end-of (car vm-message-pointer)))) | |
492 (if vm-honor-page-delimiters | |
493 (progn | |
494 (if (looking-at page-delimiter) | |
495 (forward-page 1)) | |
496 (vm-narrow-to-page)))) | |
497 ;; don't mark the message as read if the user can't see it! | |
498 (if (vm-get-visible-buffer-window (current-buffer)) | |
499 (progn | |
500 (setq vm-system-state 'showing) | |
501 (cond ((vm-new-flag (car vm-message-pointer)) | |
502 (vm-set-new-flag (car vm-message-pointer) nil))) | |
503 (cond ((vm-unread-flag (car vm-message-pointer)) | |
504 (vm-set-unread-flag (car vm-message-pointer) nil))) | |
505 (vm-update-summary-and-mode-line) | |
506 (vm-howl-if-eom)) | |
507 (vm-update-summary-and-mode-line))) | |
508 | |
509 (defun vm-expose-hidden-headers () | |
510 "Toggle exposing and hiding message headers that are normally not visible." | |
511 (interactive) | |
512 (vm-follow-summary-cursor) | |
513 (vm-select-folder-buffer) | |
514 (vm-check-for-killed-summary) | |
515 (vm-error-if-folder-empty) | |
516 (vm-display (current-buffer) t '(vm-expose-hidden-headers) | |
517 '(vm-expose-hidden-headers reading-message)) | |
518 (let* ((exposed (= (point-min) (vm-start-of (car vm-message-pointer))))) | |
519 (vm-widen-page) | |
520 (goto-char (point-max)) | |
521 (widen) | |
522 (if exposed | |
523 (narrow-to-region (point) (vm-vheaders-of (car vm-message-pointer))) | |
524 (narrow-to-region (point) (vm-start-of (car vm-message-pointer)))) | |
525 (goto-char (point-min)) | |
526 (let (w) | |
527 (setq w (vm-get-visible-buffer-window (current-buffer))) | |
528 (and w (set-window-point w (point-min))) | |
529 (and w | |
530 (= (window-start w) (vm-vheaders-of (car vm-message-pointer))) | |
531 (not exposed) | |
532 (set-window-start w (vm-start-of (car vm-message-pointer))))) | |
533 (if vm-honor-page-delimiters | |
534 (vm-narrow-to-page)))) | |
535 | |
536 (defun vm-widen-page () | |
537 (if (or (> (point-min) (vm-text-of (car vm-message-pointer))) | |
538 (/= (point-max) (vm-text-end-of (car vm-message-pointer)))) | |
539 (narrow-to-region (vm-vheaders-of (car vm-message-pointer)) | |
540 (if (or (vm-new-flag (car vm-message-pointer)) | |
541 (vm-unread-flag (car vm-message-pointer))) | |
542 (vm-text-of (car vm-message-pointer)) | |
543 (vm-text-end-of (car vm-message-pointer)))))) | |
544 | |
545 (defun vm-narrow-to-page () | |
546 (save-excursion | |
547 (let (min max (omin (point-min)) (omax (point-max))) | |
548 (if (or (bolp) (not (save-excursion | |
549 (beginning-of-line) | |
550 (looking-at page-delimiter)))) | |
551 (forward-page -1)) | |
552 (setq min (point)) | |
553 (forward-page 1) | |
554 (beginning-of-line) | |
555 (setq max (point)) | |
556 (narrow-to-region min max)))) | |
557 | |
558 (defun vm-beginning-of-message () | |
559 "Moves to the beginning of the current message." | |
560 (interactive) | |
561 (vm-follow-summary-cursor) | |
562 (vm-select-folder-buffer) | |
563 (vm-check-for-killed-summary) | |
564 (vm-error-if-folder-empty) | |
565 (vm-widen-page) | |
566 (push-mark) | |
567 (vm-display (current-buffer) t '(vm-beginning-of-message) | |
568 '(vm-beginning-of-message reading-message)) | |
569 (let ((osw (selected-window))) | |
570 (unwind-protect | |
571 (progn | |
572 (select-window (vm-get-visible-buffer-window (current-buffer))) | |
573 (goto-char (point-min))) | |
574 (if (not (eq osw (selected-window))) | |
575 (select-window osw)))) | |
576 (if vm-honor-page-delimiters | |
577 (vm-narrow-to-page))) | |
578 | |
579 (defun vm-end-of-message () | |
580 "Moves to the end of the current message, exposing and flagging it read | |
581 as necessary." | |
582 (interactive) | |
583 (vm-follow-summary-cursor) | |
584 (vm-select-folder-buffer) | |
585 (vm-check-for-killed-summary) | |
586 (vm-error-if-folder-empty) | |
587 (if (eq vm-system-state 'previewing) | |
588 (vm-show-current-message)) | |
589 (setq vm-system-state 'reading) | |
590 (vm-widen-page) | |
591 (push-mark) | |
592 (vm-display (current-buffer) t '(vm-end-of-message) | |
593 '(vm-end-of-message reading-message)) | |
594 (let ((osw (selected-window))) | |
595 (unwind-protect | |
596 (progn | |
597 (select-window (vm-get-visible-buffer-window (current-buffer))) | |
598 (goto-char (point-max))) | |
599 (if (not (eq osw (selected-window))) | |
600 (select-window osw)))) | |
601 (if vm-honor-page-delimiters | |
602 (vm-narrow-to-page))) |