]> code.delx.au - gnu-emacs/blob - lisp/gnus-uu.el
Comment change.
[gnu-emacs] / lisp / gnus-uu.el
1 ;;; gnus-uu.el --- extract, view or save (uu)encoded files from gnus
2
3 ;; Copyright (C) 1985, 1986, 1987, 1993, 1994 Free Software Foundation, Inc.
4
5 ;; Author: Lars Ingebrigtsen <larsi@ifi.uio.no>
6 ;; Created: 2 Oct 1993
7 ;; Version: v2.5.2
8 ;; Last Modified: 1994/04/13
9 ;; Keyword: news
10
11 ;; This file is part of GNU Emacs.
12
13 ;; GNU Emacs is free software; you can redistribute it and/or modify
14 ;; it under the terms of the GNU General Public License as published by
15 ;; the Free Software Foundation; either version 2, or (at your option)
16 ;; any later version.
17
18 ;; GNU Emacs is distributed in the hope that it will be useful,
19 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 ;; GNU General Public License for more details.
22
23 ;; You should have received a copy of the GNU General Public License
24 ;; along with GNU Emacs; see the file COPYING. If not, write to
25 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
26
27 ;;; Commentary:
28
29 ;; All gnus-uu commands start with `C-c C-v'.
30 ;;
31 ;; Typing `C-c C-v C-v' (`gnus-uu-decode-and-view') in the summary
32 ;; buffer will try to find all articles in the same series, uudecode
33 ;; them and view the resulting file(s).
34 ;;
35 ;; gnus-uu guesses what articles are in the series according to the
36 ;; following simple rule: The subjects must be identical, except for
37 ;; the last two numbers of the line.
38 ;;
39 ;; For example: If you choose a subject called "cat.gif (2/3)" gnus-uu
40 ;; will find all the articles that matches "^cat.gif
41 ;; ([0-9]+/[0-9]+).*$". Subjects that are nonstandard, like "cat.gif
42 ;; (2/3) Part 6 of a series", will not be properly recognized by 'C-c
43 ;; C-v C-v', and you have to mark the articles manually with '#'.
44 ;;
45 ;; Typing `C-c C-v v' (`gnus-uu-decode-and-save') will do the same as
46 ;; `C-c C-v C-v', except that it will not display the resulting file,
47 ;; but save it instead.
48 ;;
49 ;; Typing `C-c C-v s' (`gnus-uu-shar-and-save') does the same as `C-c
50 ;; C-v v', and `C-c C-v C-s' (`gnus-uu-shar-and-view') does the same
51 ;; as `C-c C-v C-v', except that they unshar files instead, i. e. run
52 ;; them through /bin/sh. Most shar files can be viewed and/or saved
53 ;; with the normal uudecode commands, which is much safer, as no
54 ;; foreign code is run.
55 ;;
56 ;; `#' (`gnus-uu-mark-article') marks an article for later
57 ;; decoding/unsharing/saving/viewing. The files will be decoded in the
58 ;; sequence they were marked. To decode the files after you've marked
59 ;; the articles you are interested in, type the corresponding key
60 ;; strokes as the normal decoding commands, but put a `M-' in the last
61 ;; keystroke. For instance, to perform a standard uudecode and view,
62 ;; you would type `C-c C-v C-v'. To perform a marked uudecode and
63 ;; view, say `C-v C-v M-C-v'. All the other view and save commands are
64 ;; handled the same way; marked uudecode and save is then `C-c C-v
65 ;; M-v'.
66 ;;
67 ;; `M-#' (`gnus-uu-unmark-article') will remove the mark from a
68 ;; previosly marked article.
69 ;;
70 ;; `C-c C-v C-u' (`gnus-uu-unmark-all-articles') will remove the mark from
71 ;; all marked articles.
72 ;;
73 ;; `C-c C-v C-r' (`gnus-uu-mark-by-regexp') will prompt for a regular
74 ;; expression and mark (forward) all articles matching that regular
75 ;; expression.
76 ;;
77 ;; There's an additional way to reach the decoding functions to make
78 ;; future expansions easier: `C-c C-v C-m'
79 ;; (`gnus-uu-multi-decode-and-view') and the corresponding save, marked
80 ;; view and marked save keystrokes, `C-c C-v m', `C-c C-v M-C-m' and
81 ;; `C-c C-v M-m' respectively. You will be prompted for decoding
82 ;; method, like uudecode, shar, binhex or plain save. Note that
83 ;; methods like binhex and save doesn't have view modes; even if you
84 ;; issue a view command (`C-c C-v C-m' and "binhex"), gnus-uu will
85 ;; just save the resulting binhex file.
86 ;;
87 ;; `C-c C-v C-b' (`gnus-uu-decode-and-show-in-buffer') will decode the
88 ;; current article and display the results in an emacs buffer. This
89 ;; might be useful if there's jsut some text in the current article
90 ;; that has been uuencoded by some perverse poster.
91 ;;
92 ;; `C-c C-v a' (`gnus-uu-decode-and-save-all-articles') looks at all the
93 ;; articles in the current newsgroup and tries to uudecode everything
94 ;; it can find. The user will be prompted for a directory where the
95 ;; resulting files (if any) will be stored. `C-c C-v M-a' only looks
96 ;; at unread article. `C-c C-v w' does the same as `C-c C-v a', but
97 ;; also marks as read all articles it has peeked through, even if they
98 ;; weren't uuencoded articles. `C-c C-v M-w' is, as you might have
99 ;; guessed, similar to `C-c C-v M-a'.
100 ;;
101 ;; `C-c C-v C-l' (`gnus-uu-edit-begin-line') lets you edit the begin
102 ;; line of the current buffer. Useful to change an incorrect suffix or
103 ;; an incorrect begin line.
104 ;;
105 ;;
106 ;; When using the view commands, `C-c C-v C-v' for instance, gnus-uu
107 ;; will (normally, see below) try to view the file according to the
108 ;; rules given in `gnus-uu-default-view-rules' and
109 ;; `gnus-uu-user-view-rules'. If it recognises the file, it will
110 ;; display it immediately. If the file is some sort of archive,
111 ;; gnus-uu will attempt to unpack the archive and see if any of the
112 ;; files in the archive can be viewed. For instance, if you have a
113 ;; gzipped tar file "pics.tar.gz" containing the files "pic1.jpg" and
114 ;; "pic2.gif", gnus-uu will uncompress and detar the main file, and
115 ;; then view the two pictures. This unpacking process is recursive, so
116 ;; if the archive contains archives of archives, it'll all be
117 ;; unpacked.
118 ;;
119 ;; If the view command doesn't recognise the file type, or can't view
120 ;; it because you don't have the viewer, or can't view *any* of the
121 ;; files in the archive, the user will be asked if she wishes to have
122 ;; the file saved somewhere. Note that if the decoded file is an
123 ;; archive, and gnus-uu manages to view some of the files in the
124 ;; archive, it won't tell the user that there were some files that
125 ;; were unviewable. See "Interactive view" for a different approach.
126 ;;
127 ;;
128 ;; Note that gnus-uu adds a function to `gnus-exit-group-hook' to
129 ;; clear the list of marked articles and check for any generated files
130 ;; that might have escaped deletion if the user typed `C-g'.
131 ;;
132 ;;
133 ;; `C-c C-v C-a' (`gnus-uu-toggle-asynchronous') toggles the
134 ;; `gnus-uu-asynchronous' variable. See below for explanation.
135 ;;
136 ;; `C-c C-v C-q' (`gnus-uu-toggle-query') toggles the
137 ;; `gnus-uu-ask-before-view' variable. See below for explanation.
138 ;;
139 ;; `C-c C-v C-p' (`gnus-uu-toggle-always-ask') toggles the
140 ;; `gnus-uu-view-and-save' variable. See below for explanation.
141 ;;
142 ;; `C-c C-v C-k' (`gnus-uu-toggle-kill-carriage-return') toggles the
143 ;; `gnus-uu-kill-carriage-return' variable. See below for explanation.
144 ;;
145 ;; `C-c C-v C-i' (`gnus-uu-toggle-interactive-view') toggles interactive
146 ;; mode. If it is turned on, gnus-uu won't view files immediately but
147 ;; give you a buffer with the default commands and files and lets you
148 ;; edit the commands and execute them at leisure.
149 ;;
150 ;; `C-c C-v C-t' (`gnus-uu-toggle-any-variable') is an interface to the
151 ;; five toggle commands listed above.
152 ;;
153 ;; `gnus-uu-toggle-correct-stripped-articles' toggles whether to check
154 ;; and correct uuencoded articles that may have had trailing spaces
155 ;; stripped by mailers.
156 ;;
157 ;;
158 ;; Customization
159 ;;
160 ;; To load this file when starting gnus, put sumething like the
161 ;; following in your .emacs file:
162 ;;
163 ;; (setq gnus-group-mode-hook
164 ;; '(lambda () (load "gnus-uu")))
165 ;;
166 ;; To make gnus-uu use, for instance, "xli" to view JPEGs and GIFs,
167 ;; put this in your .emacs file:
168 ;;
169 ;; (setq gnus-uu-user-view-rules
170 ;; (list
171 ;; '("jpg$\\|gif$" "xli")
172 ;; ))
173 ;;
174 ;; This variable is a list where each list item is a list containing
175 ;; two strings. The first string is a regular expression. If the file
176 ;; name is matched by this expression, the command given in the
177 ;; second string is executed on this file. If the command contains
178 ;; "%s", the file will be inserted there in the command string. Eg.
179 ;; "giftoppm %s | xv -" will result in the file name being inserted at
180 ;; the "%s".
181 ;;
182 ;; If you don't want to display certain file types, like if you
183 ;; haven't got sound capabilities, you could put something like
184 ;;
185 ;; (setq gnus-uu-user-view-rules
186 ;; (list
187 ;; '("au$\\|voc$\\|wav$" nil)
188 ;; ))
189 ;;
190 ;; in your .emacs file.
191 ;;
192 ;; There's a similar variable called `gnus-uu-user-archive-rules'
193 ;; which gives a list of unarcers to use when looking inside archives
194 ;; for files to display.
195 ;;
196 ;; If you don't want gnus-uu to look inside archives for files to
197 ;; display, say
198 ;;
199 ;; (setq gnus-uu-do-not-unpack-archives t)
200 ;;
201 ;;
202 ;; If you want gnus-uu to ask you if you want to save a file after
203 ;; viewing, say
204 ;;
205 ;; (setq gnus-uu-view-and-save t)
206 ;;
207 ;;
208 ;; If you don't want to wait for the viewing command to finish before
209 ;; returning to emacs, say
210 ;;
211 ;; (setq gnus-uu-asynchronous t)
212 ;;
213 ;;
214 ;; This can be useful if you're viewing long .mod files, for instance,
215 ;; which often takes several minutes. Note, however, that since
216 ;; gnus-uu doesn't ask, and if you are viewing an archive with lots of
217 ;; viewable files, you'll get them all up more or less at once, which
218 ;; can be confusing, to say the least. To get gnus-uu to ask you
219 ;; before viewing a file, say
220 ;;
221 ;; (setq gnus-uu-ask-before-view t)
222 ;;
223 ;; You can set this variable even if you're not using asynchronous
224 ;; viewing, of course.
225 ;;
226 ;; If the articles has been posted by some numbscull with a PC (isn't
227 ;; that a bit redundant, though?) and there's lots of carriage returns
228 ;; everywhere, say
229 ;;
230 ;; (setq gnus-uu-kill-carriage-return t)
231 ;;
232 ;; If you want gnus-uu to ignore the default file rules when viewing,
233 ;; for instance if there's several file types that you can't view, set
234 ;; `gnus-uu-ignore-default-view-rules' to t. There's a similar
235 ;; variable to disable the default unarchive rule list,
236 ;; `gnus-uu-ignore-default-archive-rules'.
237 ;;
238 ;; If you want a more interactive approach to file viewing, say
239 ;;
240 ;; (setq gnus-uu-use-interactive-view t)
241 ;;
242 ;; If this variable is set, whenever you type `C-c C-v C-v' (or any of
243 ;; the other view commands), gnus-uu will present you with a buffer
244 ;; with the default actions and file names after decoding. You can
245 ;; edit the command lines and execute them in a convenient fashion.
246 ;; The output from the commands will be displayed in a small window at
247 ;; the bottom of the emacs window. End interactive mode by typing `C-c
248 ;; C-c' in the view window.
249 ;;
250 ;; If you want gnus-uu to unmark articles that you have asked to
251 ;; decode, but can't be decoded (if, for instance, the articles aren't
252 ;; uuencoded files or the posting is incomplete), say
253 ;;
254 ;; (setq gnus-uu-unmark-articles-not-decoded t)
255 ;;
256 ;;
257 ;; History
258 ;;
259 ;; v1.0: First version released Oct 2 1992.
260 ;;
261 ;; v1.1: Changed `C-c C-r' to `C-c C-e' and `C-c C-p' to `C-c C-k'.
262 ;; Changed (setq gnus-exit-group-hook) to (add-hook). Removed
263 ;; checking for "Re:" for finding parts.
264 ;;
265 ;; v2.2: Fixed handling of currupted archives. Changed uudecoding to
266 ;; an asynchronous process to avoid loading tons of data into emacs
267 ;; buffers. No longer reads articles emacs already have aboard. Fixed
268 ;; a firmer support for shar files. Made regexp searches for files
269 ;; more convenient. Added `C-c C-l' for editing uucode begin
270 ;; lines. Added multi-system decoder entry point. Added interactive
271 ;; view mode. Added function for decoding and saving all uuencoded
272 ;; articles in the current newsgroup.
273 ;;
274 ;; v2.3: After suggestions I have changed all the gnus-uu key bindings
275 ;; to avoid hogging all the user keys (C-c LETTER). Also added
276 ;; (provide) and fixed some saving stuff. First posted version to
277 ;; gnu.emacs.sources.
278 ;;
279 ;; v2.4: Fixed some more in the save-all category. Automatic fixing of
280 ;; uucode "begin" lines: names on the form of "dir/file" are
281 ;; translated into "dir-file". Added a function for fixing stripped
282 ;; uucode articles. Added binhex save.
283 ;;
284 ;; v2.5: First version copyrighted by FSF. Changed lots of
285 ;; documentation strings.
286 ;;
287 ;; v2.5.1: Added uuencode/posting code to post binary files.
288 ;;
289 ;;
290 ;; Default keymap overview:
291 ;;
292 ;; All commands start with `C-c C-v'. The difference is in the third
293 ;; keystroke. All view commands are `C-LETTER'. All save commands are
294 ;; just `LETTER'. All marked commands are the same as the unmarked
295 ;; commands, except that they have `M-' before in the last keystroke.
296 ;;
297 ;; `C-c C-v C-v' gnus-uu-decode-and-view
298 ;; `C-c C-v v' gnus-uu-decode-and-save
299 ;; `C-c C-v C-s' gnus-uu-shar-and-view
300 ;; `C-c C-v s' gnus-uu-shar-and-save
301 ;; `C-c C-v C-m' gnus-uu-multi-decode-and-view
302 ;; `C-c C-v m' gnus-uu-multi-decode-and-save
303 ;;
304 ;; `C-c C-v C-b' gnus-uu-decode-and-show-in-buffer
305 ;; `C-c C-v C-l' gnus-uu-edit-begin-line
306 ;; `C-c C-v M-a' gnus-uu-decode-and-save-all-unread-articles
307 ;; `C-c C-v a' gnus-uu-decode-and-save-all-articles
308 ;; `C-c C-v M-w' gnus-uu-decode-and-save-all-unread-articles-and-mark
309 ;; `C-c C-v w' gnus-uu-decode-and-save-all-articles-and-mark
310 ;;
311 ;; `#' gnus-uu-mark-article
312 ;; `M-#' gnus-uu-unmark-article
313 ;; `C-c C-v C-u' gnus-uu-unmark-all-articles
314 ;; `C-c C-v C-r' gnus-uu-mark-by-regexp
315 ;; `C-c C-v M-C-v' gnus-uu-marked-decode-and-view
316 ;; `C-c C-v M-v' gnus-uu-marked-decode-and-save
317 ;; `C-c C-v M-C-s' gnus-uu-marked-shar-and-view
318 ;; `C-c C-v M-s' gnus-uu-marked-shar-and-save
319 ;; `C-c C-v M-C-m' gnus-uu-marked-multi-decode-and-view
320 ;; `C-c C-v M-m' gnus-uu-marked-multi-decode-and-save
321 ;;
322 ;; `C-c C-v C-a' gnus-uu-toggle-asynchronous
323 ;; `C-c C-v C-q' gnus-uu-toggle-query
324 ;; `C-c C-v C-p' gnus-uu-toggle-always-ask
325 ;; `C-c C-v C-k' gnus-uu-toggle-kill-carriage-return
326 ;; `C-c C-v C-i' gnus-uu-toggle-interactive-view
327 ;; `C-c C-v C-t' gnus-uu-toggle-any-variable
328
329 ;;; Code:
330
331 (require 'gnus)
332 (require 'gnuspost)
333
334 ;; Binding of keys to the gnus-uu functions.
335
336 (defvar gnus-uu-ctl-map nil)
337 (define-prefix-command 'gnus-uu-ctl-map)
338 (define-key gnus-summary-mode-map "\C-c\C-v" gnus-uu-ctl-map)
339
340 (define-key gnus-uu-ctl-map "\C-v" 'gnus-uu-decode-and-view)
341 (define-key gnus-uu-ctl-map "v" 'gnus-uu-decode-and-save)
342 (define-key gnus-uu-ctl-map "\C-s" 'gnus-uu-shar-and-view)
343 (define-key gnus-uu-ctl-map "s" 'gnus-uu-shar-and-save)
344 (define-key gnus-uu-ctl-map "\C-m" 'gnus-uu-multi-decode-and-view)
345 (define-key gnus-uu-ctl-map "m" 'gnus-uu-multi-decode-and-save)
346
347 (define-key gnus-uu-ctl-map "\C-b" 'gnus-uu-decode-and-show-in-buffer)
348
349 (define-key gnus-summary-mode-map "#" 'gnus-uu-mark-article)
350 (define-key gnus-summary-mode-map "\M-#" 'gnus-uu-unmark-article)
351 (define-key gnus-uu-ctl-map "\C-u" 'gnus-uu-unmark-all-articles)
352 (define-key gnus-uu-ctl-map "\C-r" 'gnus-uu-mark-by-regexp)
353
354 (define-key gnus-uu-ctl-map "\M-\C-v" 'gnus-uu-marked-decode-and-view)
355 (define-key gnus-uu-ctl-map "\M-v" 'gnus-uu-marked-decode-and-save)
356 (define-key gnus-uu-ctl-map "\M-\C-s" 'gnus-uu-marked-shar-and-view)
357 (define-key gnus-uu-ctl-map "\M-s" 'gnus-uu-marked-shar-and-save)
358 (define-key gnus-uu-ctl-map "\M-\C-m" 'gnus-uu-marked-multi-decode-and-view)
359 (define-key gnus-uu-ctl-map "\M-m" 'gnus-uu-marked-multi-decode-and-save)
360
361 (define-key gnus-uu-ctl-map "\C-a" 'gnus-uu-toggle-asynchronous)
362 (define-key gnus-uu-ctl-map "\C-q" 'gnus-uu-toggle-query)
363 (define-key gnus-uu-ctl-map "\C-p" 'gnus-uu-toggle-always-ask)
364 (define-key gnus-uu-ctl-map "\C-k" 'gnus-uu-toggle-kill-carriage-return)
365 (define-key gnus-uu-ctl-map "\C-i" 'gnus-uu-toggle-interactive-view)
366 (define-key gnus-uu-ctl-map "\C-t" 'gnus-uu-toggle-any-variable)
367
368 (define-key gnus-uu-ctl-map "\C-l" 'gnus-uu-edit-begin-line)
369
370 (define-key gnus-uu-ctl-map "\M-a" 'gnus-uu-decode-and-save-all-unread-articles)
371 (define-key gnus-uu-ctl-map "a" 'gnus-uu-decode-and-save-all-articles)
372 (define-key gnus-uu-ctl-map "\M-w" 'gnus-uu-decode-and-save-all-unread-articles-and-mark)
373 (define-key gnus-uu-ctl-map "w" 'gnus-uu-decode-and-save-all-articles-and-mark)
374
375 ;(load "rnewspost")
376 ;(define-key news-reply-mode-map "\C-c\C-v" 'gnus-uu-uuencode-and-post)
377
378 ;; Dummy function gnus-uu
379
380 (defun gnus-uu ()
381 "gnus-uu is a package for uudecoding and viewing articles.
382
383 By default, all gnus-uu keystrokes begin with `C-c C-v'.
384
385 There four decoding commands categories:
386 All commands for viewing are `C-c C-v C-LETTER'.
387 All commands for saving are `C-c C-v LETTER'.
388 All commands for marked viewing are `C-c C-v C-M-LETTER'.
389 All commands for marked saving are `C-c C-v M-LETTER'.
390
391 \\<gnus-summary-mode-map>\\[gnus-uu-decode-and-view]\tDecode and view articles
392 \\[gnus-uu-decode-and-save]\tDecode and save articles
393 \\[gnus-uu-shar-and-view]\tUnshar and view articles
394 \\[gnus-uu-shar-and-save]\tUnshar and save articles
395 \\[gnus-uu-multi-decode-and-view]\tChoose a decoding method, decode and view articles
396 \\[gnus-uu-multi-decode-and-save]\tChoose a decoding method, decode and save articles
397
398 \\[gnus-uu-decode-and-show-in-buffer]\tDecode the current article and view the result in a buffer
399 \\[gnus-uu-edit-begin-line]\tEdit the 'begin' line of an uuencoded article
400
401 \\[gnus-uu-decode-and-save-all-unread-articles]\tDecode and save all unread articles
402 \\[gnus-uu-decode-and-save-all-articles]\tDecode and save all articles
403 \\[gnus-uu-decode-and-save-all-unread-articles-and-mark]\tDecode and save all unread articles and catch up
404 \\[gnus-uu-decode-and-save-all-articles-and-mark]\tDecode and save all articles and catch up
405
406 \\[gnus-uu-mark-article]\tMark the current article for decoding
407 \\[gnus-uu-unmark-article]\tUnmark the current article
408 \\[gnus-uu-unmark-all-articles]\tUnmark all articles
409 \\[gnus-uu-mark-by-regexp]\tMark articles for decoding by regexp
410 \\[gnus-uu-marked-decode-and-view]\tDecode and view marked articles
411 \\[gnus-uu-marked-decode-and-save]\tDecode and save marked articles
412 \\[gnus-uu-marked-shar-and-view]\tUnshar and view marked articles
413 \\[gnus-uu-marked-shar-and-save]\tUnshar and save marked articles
414 \\[gnus-uu-marked-multi-decode-and-view]\tChoose decoding method, decode and view marked articles
415 \\[gnus-uu-marked-multi-decode-and-save]\tChoose decoding method, decode and save marked articles
416
417 \\[gnus-uu-toggle-asynchronous]\tToggle asynchronous viewing mode
418 \\[gnus-uu-toggle-query]\tToggle whether to ask before viewing a file
419 \\[gnus-uu-toggle-always-ask]\tToggle whether to ask to save a file after viewing
420 \\[gnus-uu-toggle-kill-carriage-return]\tToggle whether to strip trailing carriage returns
421 \\[gnus-uu-toggle-interactive-view]\tToggle whether to use interactive viewing mode
422 \\[gnus-uu-toggle-any-variable]\tToggle any of the things above
423
424 User configurable variables:
425
426 Rule Variables
427
428 gnus-uu uses \"rule\" variables to decide how to view a file. All
429 these variables are of the form
430
431 (list '(regexp1 command2)
432 '(regexp2 command2)
433 ...)
434
435 `gnus-uu-user-view-rules'
436 This variable is consulted first when viewing files. If you wish
437 to use, for instance, sox to convert an .au sound file, you could
438 say something like:
439
440 (setq gnus-uu-user-view-rules
441 (list '(\"\\\\.au$\" \"sox %s -t .aiff > /dev/audio\")))
442
443 `gnus-uu-user-view-rules-end'
444 This variable is consulted if gnus-uu couldn't make any matches
445 from the user and default view rules.
446
447 `gnus-uu-user-interactive-view-rules'
448 This is the variable used instead of `gnus-uu-user-view-rules'
449 when in interactive mode.
450
451 `gnus-uu-user-interactive-view-rules-end'
452 This variable is used instead of `gnus-uu-user-view-rules-end'
453 when in interactive mode.
454
455 `gnus-uu-user-archive-rules`
456 This variable can be used to say what comamnds should be used to
457 unpack archives.
458
459
460 Other Variables
461
462 `gnus-uu-tmp-dir'
463 Where gnus-uu does its work.
464
465 `gnus-uu-do-not-unpack-archives'
466 Non-nil means that gnus-uu won't peek inside archives looking for
467 files to dispay.
468
469 `gnus-uu-view-and-save'
470 Non-nil means that the user will always be asked to save a file
471 after viewing it.
472
473 `gnus-uu-asynchronous'
474 Non-nil means that files will be viewed asynchronously.
475
476 `gnus-uu-ask-before-view'
477 Non-nil means that gnus-uu will ask you before viewing each file
478
479 `gnus-uu-ignore-default-view-rules'
480 Non-nil means that gnus-uu will ignore the default viewing rules.
481
482 `gnus-uu-ignore-default-archive-rules'
483 Non-nil means that gnus-uu will ignore the default archive
484 unpacking commands.
485
486 `gnus-uu-kill-carriage-return'
487 Non-nil means that gnus-uu will strip all carriage returns from
488 articles.
489
490 `gnus-uu-unmark-articles-not-decoded'
491 Non-nil means that gnus-uu will mark articles that were
492 unsuccessfully decoded as unread.
493
494 `gnus-uu-output-window-height'
495 This variable says how tall the output buffer window is to be
496 when using interactive view mode.
497
498 `gnus-uu-correct-stripped-uucode'
499 Non-nil means that gnus-uu will *try* to fix uuencoded files that
500 have had traling spaces deleted.
501
502 `gnus-uu-use-interactive-view'
503 Non-nil means that gnus-uu will use interactive viewing mode."
504 (interactive)
505 )
506
507 ;; Default viewing action rules
508
509 (defvar gnus-uu-default-view-rules
510 (list
511 '("\\.\\(jpe?g\\|gif\\|tiff?\\|p[pgb]m\\|xwd\\|xbm\\|pcx\\)$" "xv")
512 '("\\.tga$" "tgatoppm %s | xv -")
513 '("\\.te?xt$\\|\\.doc$\\|read.*me" "xterm -e less")
514 '("\\.fli$" "xflick")
515 '("\\.\\(wav\\|aiff\\|hcom\\|u[blw]\\|s[bfw]\\|voc\\|smp\\)$"
516 "sox -v .5 %s -t .au -u - > /dev/audio")
517 '("\\.au$" "cat %s > /dev/audio")
518 '("\\.mod$" "str32")
519 '("\\.ps$" "ghostview")
520 '("\\.dvi$" "xdvi")
521 '("\\.1$" "xterm -e man -l")
522 '("\\.html$" "xmosaic")
523 '("\\.mpe?g$" "mpeg_play")
524 '("\\.\\(tar\\|arj\\|zip\\|zoo\\|arc\\|gz\\|Z\\|lzh\\|ar\\)$"
525 "gnus-uu-archive"))
526
527 "Default actions to be taken when the user asks to view a file.
528 To change the behaviour, you can either edit this variable or set
529 `gnus-uu-user-view-rules' to something useful.
530
531 For example:
532
533 To make gnus-uu use 'xli' to display JPEG and GIF files, put the
534 following in your .emacs file
535
536 (setq gnus-uu-user-view-rules (list '(\"jpg$\\\\|gif$\" \"xli\")))
537
538 Both these variables are lists of lists with two string elements. The
539 first string is a regular expression. If the file name matches this
540 regular expression, the command in the second string is executed with
541 the file as an argument.
542
543 If the command string contains \"%s\", the file name will be inserted
544 at that point in the command string. If there's no \"%s\" in the
545 command string, the file name will be appended to the command string
546 before executing.
547
548 There are several user variables to tailor the behaviour of gnus-uu to
549 your needs. First we have `gnus-uu-user-view-rules', which is the
550 variable gnus-uu first consults when trying to decide how to view a
551 file. If this variable contains no matches, gnus-uu examines the
552 default rule vaiable provided in this package. If gnus-uu finds no
553 match here, it uses `gnus-uu-user-view-rules-end' to try to make a
554 match.
555
556 Unless, of course, you are using the interactive view mode. Then
557 `gnus-uu-user-interactive-view-rules' and
558 `gnus-uu-user-interactive-view-rules-end' will be used instead.")
559
560 (defvar gnus-uu-user-view-rules nil
561 "Variable detailing what actions are to be taken to view a file.
562 See the documentation on the `gnus-uu-default-view-rules' variable for
563 details.")
564
565 (defvar gnus-uu-user-view-rules-end nil
566 "Variable saying what actions are to be taken if no rule matched the file name.
567 See the documentation on the `gnus-uu-default-view-rules' variable for
568 details.")
569
570 (defvar gnus-uu-user-interactive-view-rules nil
571 "Variable detailing what actions are to be taken to view a file when using interactive mode.
572 See the documentation on the `gnus-uu-default-view-rules' variable for
573 details.")
574
575 (defvar gnus-uu-user-interactive-view-rules-end nil
576 "Variable saying what actions are to be taken if no rule matched the file name when using interactive mode.
577 See the documentation on the `gnus-uu-default-view-rules' variable for
578 details.")
579
580 (defvar gnus-uu-default-interactive-view-rules-begin
581 (list
582 '("\\.te?xt$\\|\\.doc$\\|read.*me\\|\\.c?$\\|\\.h$\\|\\.bat$\\|\\.asm$\\|makefile" "cat %s | sed s/
583 //g")
584 '("\\.pas$" "cat %s | sed s/
585 //g")
586 ))
587
588
589 ;; Default unpacking commands
590
591 (defvar gnus-uu-default-archive-rules
592 (list '("\\.tar$" "tar xf")
593 '("\\.zip$" "unzip")
594 '("\\.ar$" "ar x")
595 '("\\.arj$" "unarj x")
596 '("\\.zoo$" "zoo -e")
597 '("\\.lzh$" "lha x")
598 '("\\.Z$" "uncompress")
599 '("\\.gz$" "gunzip")
600 '("\\.arc$" "arc -x"))
601 )
602
603 (defvar gnus-uu-user-archive-rules nil
604 "A list that can be set to override the default archive unpacking commands.
605 To use, for instance, 'untar' to unpack tar files and 'zip -x' to
606 unpack zip files, say the following:
607 (setq gnus-uu-user-archive-rules
608 (list '(\"\\\\.tar$\" \"untar\")
609 '(\"\\\\.zip$\" \"zip -x\")))"
610 )
611
612
613 ;; Various variables users may set
614
615 (defvar gnus-uu-tmp-dir "/tmp/"
616 "Variable saying where gnus-uu is to do its work.
617 Default is \"/tmp/\".")
618
619 (defvar gnus-uu-do-not-unpack-archives nil
620 "Non-nil means that gnus-uu won't peek inside archives looking for files to dispay.
621 Default is nil.")
622
623 (defvar gnus-uu-view-and-save nil
624 "Non-nil means that the user will always be asked to save a file after viewing it.
625 If the variable is nil, the suer will only be asked to save if the
626 viewing is unsuccessful. Default is nil.")
627
628 (defvar gnus-uu-asynchronous nil
629 "Non-nil means that files will be viewed asynchronously.
630 Default is nil.")
631
632 (defvar gnus-uu-ask-before-view nil
633 "Non-nil means that gnus-uu will ask you before viewing each file.
634 Especially useful when `gnus-uu-asynchronous' is set. Default is
635 nil.")
636
637 (defvar gnus-uu-ignore-default-view-rules nil
638 "Non-nil means that gnus-uu will ignore the default viewing rules.
639 Only the user viewing rules will be consulted. Default is nil.")
640
641 (defvar gnus-uu-ignore-default-archive-rules nil
642 "Non-nil means that gnus-uu will ignore the default archive unpacking commands.
643 Only the user unpacking commands will be consulted. Default is nil.")
644
645 (defvar gnus-uu-kill-carriage-return t
646 "Non-nil means that gnus-uu will strip all carriage returns from articles.
647 Default is t.")
648
649 (defvar gnus-uu-unmark-articles-not-decoded nil
650 "Non-nil means that gnus-uu will mark articles that were unsuccessfully decoded as unread.
651 Default is nil.")
652
653 (defvar gnus-uu-output-window-height 20
654 "This variable says how tall the output buffer window is to be when using interactive view mode.
655 Change it at your convenience. Default is 20.")
656
657 (defvar gnus-uu-correct-stripped-uucode nil
658 "Non-nil means that gnus-uu will *try* to fix uuencoded files that have had traling spaces deleted.
659 Default is nil.")
660
661 (defvar gnus-uu-use-interactive-view nil
662 "Non-nil means that gnus-uu will use interactive viewing mode.
663 Gnus-uu will create a special buffer where the user may choose
664 interactively which files to view and how. Default is nil.")
665
666
667 ;; Internal variables
668
669 (defconst gnus-uu-begin-string "^begin[ \t]+[0-7][0-7][0-7][ \t]+\\(.*\\)$")
670 (defconst gnus-uu-end-string "^end[ \t]*$")
671 (defconst gnus-uu-body-line
672 "^M.............................................................?$")
673 (defconst gnus-uu-shar-begin-string "^#! */bin/sh")
674
675 (defvar gnus-uu-shar-file-name nil)
676 (defconst gnus-uu-shar-name-marker "begin [0-7][0-7][0-7][ \t]+\\(\\(\\w\\|\\.\\)*\\b\\)")
677 (defvar gnus-uu-shar-directory nil)
678
679 (defvar gnus-uu-file-name nil)
680 (defconst gnus-uu-uudecode-process nil)
681
682 (defvar gnus-uu-interactive-file-list nil)
683 (defvar gnus-uu-marked-article-list nil)
684 (defvar gnus-uu-generated-file-list nil)
685
686 (defconst gnus-uu-interactive-buffer-name "*gnus-uu interactive*")
687 (defconst gnus-uu-output-buffer-name "*Gnus UU Output*")
688 (defconst gnus-uu-result-buffer "*Gnus UU Result Buffer*")
689
690 (defconst gnus-uu-error-during-unarching nil)
691
692 ;; Interactive functions
693
694 ;; UUdecode and view
695
696 (defun gnus-uu-decode-and-view ()
697 "UUdecodes and 'views' (if possible) the resulting file.
698 'Viewing' can be any action at all, as defined in the
699 `gnus-uu-file-action-list' variable. Running 'xv' on gifs and 'cat
700 >/dev/audio' on au files are popular actions. If the file can't be
701 viewed, the user is asked if she would like to save the file instead."
702 (interactive)
703 (gnus-uu-decode-and-view-or-save t nil))
704
705 (defun gnus-uu-decode-and-save ()
706 "Decodes and saves the resulting file."
707 (interactive)
708 (gnus-uu-decode-and-view-or-save nil nil))
709
710 (defun gnus-uu-marked-decode-and-view ()
711 "Decodes and views articles marked.
712 The marked equivalent to `gnus-uu-decode-and-view'."
713 (interactive)
714 (gnus-uu-decode-and-view-or-save t t))
715
716 (defun gnus-uu-marked-decode-and-save ()
717 "Decodes and saves articles marked.
718 The marked equivalent to `gnus-uu-decode-and-save'."
719 (interactive)
720 (gnus-uu-decode-and-view-or-save nil t))
721
722
723 ;; Unshar and view
724
725 (defun gnus-uu-shar-and-view ()
726 "Unshars and views articles.
727 The shar equivalent of `gnus-uu-decode-and-view'."
728 (interactive)
729 (gnus-uu-unshar-and-view-or-save t nil))
730
731 (defun gnus-uu-shar-and-save ()
732 "Unshars and saves files.
733 The shar equivalent to `gnus-uu-decode-and-save'."
734 (interactive)
735 (gnus-uu-unshar-and-view-or-save nil nil))
736
737 (defun gnus-uu-marked-shar-and-view ()
738 "Unshars and views articles marked.
739 The marked equivalent to `gnus-uu-shar-and-view'."
740 (interactive)
741 (gnus-uu-unshar-and-view-or-save t t))
742
743 (defun gnus-uu-marked-shar-and-save ()
744 "Unshars and saves articles marked.
745 The marked equivalent to `gnus-uu-shar-and-save'."
746 (interactive)
747 (gnus-uu-unshar-and-view-or-save nil t))
748
749
750 ;; Decode and show in buffer
751
752 (defun gnus-uu-decode-and-show-in-buffer ()
753 "Uudecodes the current article and displays the result in a buffer.
754 Might be useful if someone has, for instance, some text uuencoded in
755 their sigs. (Stranger things have happened.)"
756 (interactive)
757 (let ((uu-buffer (get-buffer-create gnus-uu-output-buffer-name))
758 list-of-articles file-name)
759 (save-excursion
760 (and
761 (setq list-of-articles (list gnus-current-article))
762 (gnus-uu-grab-articles list-of-articles 'gnus-uu-uustrip-article-as)
763 (setq file-name (gnus-uu-decode gnus-uu-tmp-dir))
764 (progn
765 (save-excursion
766 (set-buffer uu-buffer)
767 (erase-buffer)
768 (insert-file-contents file-name))
769 (set-window-buffer (get-buffer-window gnus-article-buffer)
770 uu-buffer)
771 (message (format "Showing file %s in buffer" file-name))
772 (delete-file file-name))))))
773
774
775 ;; Toggle commands
776
777 (defun gnus-uu-toggle-asynchronous ()
778 "This function toggles asynchronous viewing."
779 (interactive)
780 (if (setq gnus-uu-asynchronous (not gnus-uu-asynchronous))
781 (message "gnus-uu will now view files asynchronously")
782 (message "gnus-uu will now view files synchronously")))
783
784 (defun gnus-uu-toggle-query ()
785 "This function toggles whether to ask before viewing or not."
786 (interactive)
787 (if (setq gnus-uu-ask-before-view (not gnus-uu-ask-before-view))
788 (message "gnus-uu will now ask before viewing")
789 (message "gnus-uu will now view without asking first")))
790
791 (defun gnus-uu-toggle-always-ask ()
792 "This function toggles whether to always ask to save a file after viewing."
793 (interactive)
794 (if (setq gnus-uu-view-and-save (not gnus-uu-view-and-save))
795 (message "gnus-uu will now ask to save the file after viewing")
796 (message "gnus-uu will now not ask to save after successful viewing")))
797
798 (defun gnus-uu-toggle-interactive-view ()
799 "This function toggles whether to use interactive view."
800 (interactive)
801 (if (setq gnus-uu-use-interactive-view (not gnus-uu-use-interactive-view))
802 (message "gnus-uu will now use interactive view")
803 (message "gnus-uu will now use non-interactive view")))
804
805 (defun gnus-uu-toggle-unmark-undecoded ()
806 "This function toggles whether to unmark articles not decoded."
807 (interactive)
808 (if (setq gnus-uu-unmark-articles-not-decoded
809 (not gnus-uu-unmark-articles-not-decoded))
810 (message "gnus-uu will now unmark articles not decoded")
811 (message "gnus-uu will now not unmark articles not decoded")))
812
813 (defun gnus-uu-toggle-kill-carriage-return ()
814 "This function toggles the stripping of carriage returns from the articles."
815 (interactive)
816 (if (setq gnus-uu-kill-carriage-return (not gnus-uu-kill-carriage-return))
817 (message "gnus-uu will now strip carriage returns")
818 (message "gnus-uu won't strip carriage returns")))
819
820 (defun gnus-uu-toggle-correct-stripped-uucode ()
821 "This function toggles whether to correct stripped uucode."
822 (interactive)
823 (if (setq gnus-uu-correct-stripped-uucode
824 (not gnus-uu-correct-stripped-uucode))
825 (message "gnus-uu will now correct stripped uucode")
826 (message "gnus-uu won't check and correct stripped uucode")))
827
828 (defun gnus-uu-toggle-any-variable ()
829 "This function ask what variable the user wants to toggle."
830 (interactive)
831 (let (rep)
832 (message "(a)sync, (q)uery, (p)ask, (k)ill CR, (i)nteractive, (u)nmark, (c)orrect")
833 (setq rep (read-char))
834 (if (= rep ?a)
835 (gnus-uu-toggle-asynchronous))
836 (if (= rep ?q)
837 (gnus-uu-toggle-query))
838 (if (= rep ?p)
839 (gnus-uu-toggle-always-ask))
840 (if (= rep ?k)
841 (gnus-uu-toggle-kill-carriage-return))
842 (if (= rep ?u)
843 (gnus-uu-toggle-unmark-undecoded))
844 (if (= rep ?c)
845 (gnus-uu-toggle-correct-stripped-uucode))
846 (if (= rep ?i)
847 (gnus-uu-toggle-interactive-view))))
848
849
850 ;; Edit line
851
852 (defun gnus-uu-edit-begin-line ()
853 "Edit the begin line of the current article."
854 (interactive)
855 (let ((buffer-read-only nil)
856 begin b)
857 (save-excursion
858 (set-buffer gnus-article-buffer)
859 (goto-line 1)
860 (if (not (re-search-forward "begin " nil t))
861 (progn (message "No begin line in the current article") (sit-for 2))
862 (beginning-of-line)
863 (setq b (point))
864 (end-of-line)
865 (setq begin (buffer-substring b (point)))
866 (setq begin (read-string "" begin))
867 (setq buffer-read-only nil)
868 (delete-region b (point))
869 (insert-string begin)))))
870
871 ;; Multi functions
872
873 (defun gnus-uu-multi-decode-and-view ()
874 "Choose a method of decoding and then decode and view.
875 This function lets the user decide what method to use for decoding.
876 Other than that, it's equivalent to the other decode-and-view
877 functions."
878 (interactive)
879 (gnus-uu-multi-decode-and-view-or-save t nil))
880
881 (defun gnus-uu-multi-decode-and-save ()
882 "Choose a method of decoding and then decode and save.
883 This function lets the user decide what method to use for decoding.
884 Other than that, it's equivalent to the other decode-and-save
885 functions."
886 (interactive)
887 (gnus-uu-multi-decode-and-view-or-save nil nil))
888
889 (defun gnus-uu-marked-multi-decode-and-view ()
890 "Choose a method of decoding and then decode and view the marked articles.
891 This function lets the user decide what method to use for decoding.
892 Other than that, it's equivalent to the other marked decode-and-view
893 functions."
894 (interactive)
895 (gnus-uu-multi-decode-and-view-or-save t t))
896
897 (defun gnus-uu-marked-multi-decode-and-save ()
898 "Choose a method of decoding and then decode and save the marked articles.
899 This function lets the user decide what method to use for decoding.
900 Other than that, it's equivalent to the other marked decode-and-save
901 functions."
902 (interactive)
903 (gnus-uu-multi-decode-and-view-or-save t t))
904
905 (defun gnus-uu-multi-decode-and-view-or-save (view marked)
906 (let (decode-type)
907 (message "(u)udecode, (s)har, s(a)ve, (b)inhex: ")
908 (setq decode-type (read-char))
909 (if (= decode-type ?
910 ) (setq decode-type ?u))
911 (if (= decode-type ?u)
912 (gnus-uu-decode-and-view-or-save view marked)
913 (if (= decode-type ?s)
914 (gnus-uu-unshar-and-view-or-save view marked)
915 (if (= decode-type ?b)
916 (gnus-uu-binhex-and-save view marked)
917 (if (= decode-type ?a)
918 (gnus-uu-save-articles view marked)
919 (message (format "Unknown decode method '%c'." decode-type))
920 (sit-for 2)))))))
921
922
923 ;; uuencode and post
924
925 (defconst gnus-uu-uuencode-post-length 90)
926
927 (defun gnus-uu-post ()
928 (interactive)
929 (let ((uuencode-buffer-name "*uuencode buffer*")
930 (send-buffer-name "*uuencode send buffer*")
931 (top-string "[ cut here %s (%s %d/%d) %s gnus-uu ]")
932 file uubuf short-file length parts header i end beg
933 beg-line minlen buf post-buf whole-len)
934 (setq file (read-file-name
935 "What file do you want to uuencode and post? " "~/Unrd.jpg"))
936 (if (not (file-exists-p file))
937 (message "%s: No such file" file)
938 (save-excursion
939 (setq post-buf (current-buffer))
940 (set-buffer (setq uubuf (get-buffer-create uuencode-buffer-name)))
941 (erase-buffer)
942 (if (string-match "^~/" file)
943 (setq file (concat "$HOME" (substring file 1))))
944 (if (string-match "/[^/]*$" file)
945 (setq short-file (substring file (1+ (match-beginning 0))))
946 (setq short-file file))
947 (call-process "sh" nil uubuf nil "-c"
948 (format "uuencode %s %s" file short-file))
949 (goto-char 1)
950 (forward-line 1)
951 (while (re-search-forward " " nil t)
952 (replace-match "`"))
953 (setq length (count-lines 1 (point-max)))
954 (setq parts (/ length gnus-uu-uuencode-post-length))
955 (if (not (< (% length gnus-uu-uuencode-post-length) 4))
956 (setq parts (1+ parts)))
957 (message "Det er %d parts" parts))
958 (goto-char 1)
959 (search-forward mail-header-separator nil t)
960 (beginning-of-line)
961 (forward-line 1)
962 (setq header (buffer-substring 1 (point)))
963 (goto-char 1)
964 (if (re-search-forward "^Subject: " nil t)
965 (progn
966 (end-of-line)
967 (insert (format " (0/%d)" parts))))
968 ; (save-excursion
969 ; (set-buffer (get-buffer-create "*tull"))
970 ; (erase-buffer)
971 ; (goto-char (point-max))
972 ; (insert-buffer send-buffer-name))
973 (gnus-inews-news)
974
975 (save-excursion
976 (setq i 1)
977 (setq beg 1)
978 (while (not (> i parts))
979 (set-buffer (get-buffer-create send-buffer-name))
980 (erase-buffer)
981 (insert header)
982 (insert "\n")
983 (setq whole-len
984 (- 62 (length (format top-string "" short-file i parts ""))))
985 (setq minlen (/ whole-len 2))
986 (setq
987 beg-line
988 (format top-string
989 (make-string minlen ?-)
990 short-file i parts
991 (make-string (if (= 0 (% whole-len 2)) (1- minlen) minlen) ?-)))
992 (insert beg-line)
993 (insert "\n")
994 (goto-char 1)
995 (if (re-search-forward "^Subject: " nil t)
996 (progn
997 (end-of-line)
998 (insert (format " (%d/%d)" i parts))))
999 (goto-char (point-max))
1000 (save-excursion
1001 (set-buffer uubuf)
1002 (goto-char beg)
1003 (if (= i parts)
1004 (goto-char (point-max))
1005 (forward-line gnus-uu-uuencode-post-length))
1006 (setq end (point)))
1007 (insert-buffer-substring uubuf beg end)
1008 (insert beg-line)
1009 (insert "\n")
1010 (setq beg end)
1011 (setq i (1+ i))
1012 ; (save-excursion
1013 ; (set-buffer (get-buffer-create "*tull"))
1014 ; (goto-char (point-max))
1015 ; (insert-buffer send-buffer-name))
1016 (gnus-inews-news)
1017 ))
1018 (and (setq buf (get-buffer send-buffer-name))
1019 (kill-buffer buf))
1020 (and (setq buf (get-buffer uuencode-buffer-name))
1021 (kill-buffer buf)))))
1022
1023
1024
1025 ;; Decode and all files
1026
1027 (defconst gnus-uu-rest-of-articles nil)
1028 (defconst gnus-uu-do-sloppy-uudecode nil)
1029 (defvar gnus-uu-current-save-dir nil)
1030
1031 (defun gnus-uu-decode-and-save-all-unread-articles ()
1032 "Try to decode all unread articles and saves the result.
1033 This function reads all unread articles in the current group and sees
1034 whether it can uudecode the articles. The user will be prompted for an
1035 directory to put the resulting (if any) files."
1036 (interactive)
1037 (gnus-uu-decode-and-save-articles t t))
1038
1039 (defun gnus-uu-decode-and-save-all-articles ()
1040 "Try to decode all articles and saves the result.
1041 Does the same as `gnus-uu-decode-and-save-all-unread-articles', except
1042 that it grabs all articles visible, unread or not."
1043 (interactive)
1044 (gnus-uu-decode-and-save-articles nil t))
1045
1046 (defun gnus-uu-decode-and-save-all-unread-articles-and-mark ()
1047 "Try to decode all unread articles and saves the result and marks everything as read.
1048 Does the same as `gnus-uu-decode-and-save-all-unread-articles', except that
1049 it marks everything as read, even if it couldn't decode the articles."
1050 (interactive)
1051 (gnus-uu-decode-and-save-articles t nil))
1052
1053 (defun gnus-uu-decode-and-save-all-articles-and-mark ()
1054 "Try to decode all articles and saves the result and marks everything as read.
1055 Does the same as `gnus-uu-decode-and-save-all-articles', except that
1056 it marks everything as read, even if it couldn't decode the articles."
1057 (interactive)
1058 (gnus-uu-decode-and-save-articles nil nil))
1059
1060 (defun gnus-uu-decode-and-save-articles (&optional unread unmark)
1061 (let ((gnus-uu-unmark-articles-not-decoded unmark)
1062 (filest "")
1063 where dir did unmark saved-list)
1064 (setq gnus-uu-do-sloppy-uudecode t)
1065 (setq dir (gnus-uu-read-directory "Where do you want the files? "))
1066 (message "Grabbing...")
1067 (setq gnus-uu-rest-of-articles
1068 (gnus-uu-get-list-of-articles "^." nil unread))
1069 (setq gnus-uu-file-name nil)
1070 (while (and gnus-uu-rest-of-articles
1071 (gnus-uu-grab-articles gnus-uu-rest-of-articles
1072 'gnus-uu-uustrip-article-as))
1073 (if gnus-uu-file-name
1074 (progn
1075 (setq saved-list (cons gnus-uu-file-name saved-list))
1076 (rename-file (concat gnus-uu-tmp-dir gnus-uu-file-name)
1077 (concat dir gnus-uu-file-name) t)
1078 (setq did t)
1079 (setq gnus-uu-file-name nil))))
1080 (if (not did)
1081 ()
1082 (while saved-list
1083 (setq filest (concat filest " " (car saved-list)))
1084 (setq saved-list (cdr saved-list)))
1085 (message "Saved%s" filest)))
1086 (setq gnus-uu-do-sloppy-uudecode nil))
1087
1088
1089 ;; Work functions
1090
1091 (defun gnus-uu-decode-and-view-or-save (view marked)
1092 (gnus-uu-initialize)
1093 (let (file decoded)
1094 (save-excursion
1095 (if (gnus-uu-decode-and-strip nil marked)
1096 (progn
1097 (setq decoded t)
1098 (setq file (concat gnus-uu-tmp-dir gnus-uu-file-name))
1099 (if view
1100 (gnus-uu-view-file file)
1101 (gnus-uu-save-file file)))))
1102
1103 (gnus-uu-summary-next-subject)
1104
1105 (if gnus-uu-error-during-unarching
1106 (gnus-uu-clean-up)
1107 (if (and gnus-uu-use-interactive-view view decoded)
1108 (gnus-uu-do-interactive)))
1109
1110 (if (or (not gnus-uu-use-interactive-view) (not decoded))
1111 (gnus-uu-clean-up))))
1112
1113
1114 ; Unshars and views/saves marked/unmarked articles.
1115
1116 (defun gnus-uu-unshar-and-view-or-save (view marked)
1117 (gnus-uu-initialize)
1118 (let (tar-file files decoded)
1119 (save-excursion
1120 (setq gnus-uu-shar-directory
1121 (make-temp-name (concat gnus-uu-tmp-dir "gnusuush")))
1122 (make-directory gnus-uu-shar-directory)
1123 (gnus-uu-add-file gnus-uu-shar-directory)
1124 (if (gnus-uu-decode-and-strip t marked)
1125 (progn
1126 (setq decoded t)
1127 (setq files (directory-files gnus-uu-shar-directory t))
1128 (setq gnus-uu-generated-file-list
1129 (append files gnus-uu-generated-file-list))
1130 (if (> (length files) 3)
1131 (progn
1132 (setq tar-file
1133 (concat
1134 (make-temp-name (concat gnus-uu-tmp-dir "gnusuuar"))
1135 ".tar"))
1136 (gnus-uu-add-file tar-file)
1137 (call-process "sh" nil
1138 (get-buffer-create gnus-uu-output-buffer-name)
1139 nil "-c"
1140 (format "cd %s ; tar cf %s * ; cd .. ; rm -r %s"
1141 gnus-uu-shar-directory
1142 tar-file
1143 gnus-uu-shar-directory))
1144 (if view
1145 (gnus-uu-view-file tar-file)
1146 (gnus-uu-save-file tar-file)))
1147 (if view
1148 (gnus-uu-view-file (elt files 2))
1149 (gnus-uu-save-file (elt files 2)))))))
1150
1151 (gnus-uu-summary-next-subject)
1152
1153 (if (and gnus-uu-use-interactive-view view decoded)
1154 (gnus-uu-do-interactive))
1155
1156 (if (or (not gnus-uu-use-interactive-view) (not decoded))
1157 (gnus-uu-clean-up))))
1158
1159
1160 (defconst gnus-uu-saved-article-name nil)
1161 (defun gnus-uu-save-articles (view marked)
1162 (let (list-of-articles)
1163 (save-excursion
1164 (if (not marked)
1165 (setq list-of-articles (gnus-uu-get-list-of-articles))
1166 (setq list-of-articles (reverse gnus-uu-marked-article-list))
1167 (setq gnus-uu-marked-article-list nil))
1168 (if (not list-of-articles)
1169 (progn
1170 (message "No list of articles")
1171 (sit-for 2))
1172 (setq gnus-uu-saved-article-name
1173 (concat gnus-uu-tmp-dir
1174 (read-file-name "Enter file name: " gnus-newsgroup-name
1175 gnus-newsgroup-name)))
1176 (gnus-uu-add-file gnus-uu-saved-article-name)
1177 (if (gnus-uu-grab-articles list-of-articles 'gnus-uu-save-article)
1178 (gnus-uu-save-file gnus-uu-saved-article-name))))))
1179
1180
1181 (defun gnus-uu-save-article (buffer in-state)
1182 (save-excursion
1183 (set-buffer buffer)
1184 (call-process-region
1185 1 (point-max) "sh" nil (get-buffer-create gnus-uu-output-buffer-name)
1186 nil "-c" (concat "cat >> " gnus-uu-saved-article-name)))
1187 'ok)
1188
1189
1190 ;; Binhex
1191 (defconst gnus-uu-binhex-body-line
1192 "^................................................................$")
1193 (defconst gnus-uu-binhex-begin-line
1194 "^:...............................................................$")
1195 (defconst gnus-uu-binhex-end-line
1196 ":$")
1197 (defvar gnus-uu-binhex-article-name nil)
1198
1199
1200 (defun gnus-uu-binhex-and-save (view marked)
1201 (let (list-of-articles)
1202 (save-excursion
1203 (if (not marked)
1204 (setq list-of-articles (gnus-uu-get-list-of-articles))
1205 (setq list-of-articles (reverse gnus-uu-marked-article-list))
1206 (setq gnus-uu-marked-article-list nil))
1207 (if (not list-of-articles)
1208 (progn
1209 (message "No list of articles")
1210 (sit-for 2))
1211 (setq gnus-uu-binhex-article-name
1212 (concat gnus-uu-tmp-dir
1213 (read-file-name "Enter binhex file name: "
1214 gnus-newsgroup-name
1215 gnus-newsgroup-name)))
1216 (gnus-uu-add-file gnus-uu-binhex-article-name)
1217 (if (gnus-uu-grab-articles list-of-articles 'gnus-uu-binhex-article)
1218 (gnus-uu-save-file gnus-uu-binhex-article-name))))))
1219
1220
1221 (defun gnus-uu-binhex-article (buffer in-state)
1222 (let ((state 'ok)
1223 start-char)
1224 (save-excursion
1225 (set-buffer buffer)
1226 (goto-char 1)
1227 (if (not (re-search-forward (concat gnus-uu-binhex-begin-line "\\|"
1228 gnus-uu-binhex-body-line) nil t))
1229 (setq state 'wrong-type)
1230 (beginning-of-line)
1231 (setq start-char (point))
1232 (if (looking-at gnus-uu-binhex-begin-line)
1233 (setq state 'begin)
1234 (setq state 'middle))
1235 (goto-char (point-max))
1236 (re-search-backward (concat gnus-uu-binhex-body-line "\\|"
1237 gnus-uu-binhex-end-line) nil t)
1238 (if (looking-at gnus-uu-binhex-end-line)
1239 (if (eq state 'begin)
1240 (setq state 'begin-and-end)
1241 (setq state 'end)))
1242 (beginning-of-line)
1243 (forward-line 1)
1244 (append-to-file start-char (point) gnus-uu-binhex-article-name)))
1245 state))
1246
1247
1248 ;; Internal view commands
1249
1250 ; This function takes two parameters. The first is name of the file to
1251 ; be viewed. `gnus-uu-view-file' will look for an action associated
1252 ; with the file type of the file. If it finds an appropriate action,
1253 ; the file will be attempted displayed.
1254 ;
1255 ; The second parameter specifies if the user is to be asked whether to
1256 ; save the file if viewing is unsuccessful. t means "do not ask."
1257 ;
1258 ; Note that the file given will be deleted by this function, one way
1259 ; or another. If `gnus-uu-asynchronous' is set, it won't be deleted
1260 ; right away, but sometime later. If the user is offered to save the
1261 ; file, it'll be moved to wherever the user wants it.
1262
1263 ; `gnus-uu-view-file' returns t if viewing is successful.
1264
1265 (defun gnus-uu-view-file (file-name &optional dont-ask)
1266 (let (action did-view
1267 (didnt-want t)
1268 (do-view t))
1269 (setq action
1270 (gnus-uu-choose-action
1271 file-name
1272 (append
1273 (if (and gnus-uu-use-interactive-view
1274 gnus-uu-user-interactive-view-rules)
1275 gnus-uu-user-interactive-view-rules
1276 gnus-uu-user-view-rules)
1277 (if (or gnus-uu-ignore-default-view-rules
1278 (not gnus-uu-use-interactive-view))
1279 ()
1280 gnus-uu-default-interactive-view-rules-begin)
1281 (if gnus-uu-ignore-default-view-rules
1282 nil
1283 gnus-uu-default-view-rules)
1284 (if (and gnus-uu-use-interactive-view
1285 gnus-uu-user-interactive-view-rules-end)
1286 gnus-uu-user-interactive-view-rules-end
1287 gnus-uu-user-view-rules-end))))
1288
1289 (if (and gnus-uu-use-interactive-view
1290 (not (string= (or action "") "gnus-uu-archive")))
1291 (gnus-uu-enter-interactive-file (or action "") file-name)
1292
1293 (if action
1294 (if (string= action "gnus-uu-archive")
1295 (setq did-view (gnus-uu-treat-archive file-name))
1296
1297 (if gnus-uu-ask-before-view
1298 (setq didnt-want
1299 (or (not
1300 (setq do-view
1301 (y-or-n-p
1302 (format "Do you want to view %s? "
1303 file-name))))
1304 didnt-want)))
1305
1306 (if do-view
1307 (setq did-view
1308 (if gnus-uu-asynchronous
1309 (gnus-uu-call-asynchronous file-name action)
1310 (gnus-uu-call-synchronous file-name action))))))
1311
1312 (if (and (not dont-ask) (not gnus-uu-use-interactive-view))
1313 (progn
1314 (if (and
1315 didnt-want
1316 (or (not action)
1317 (and (string= action "gnus-uu-archive")
1318 (not did-view))))
1319 (progn
1320 (message
1321 (format "Could find no rule for %s" file-name))
1322 (sit-for 2)))
1323 (and (or (not did-view) gnus-uu-view-and-save)
1324 (y-or-n-p
1325 (format "Do you want to save the file %s? "
1326 file-name))
1327 (gnus-uu-save-file file-name))))
1328
1329 (if (and (file-exists-p file-name)
1330 (not gnus-uu-use-interactive-view)
1331 (or
1332 (not (and gnus-uu-asynchronous did-view))
1333 (string= action "gnus-uu-archive")))
1334 (delete-file file-name)))
1335
1336 did-view))
1337
1338
1339 ; `gnus-uu-call-synchronous' takes two parameters: The name of the
1340 ; file to be displayed and the command to display it with. Returns t
1341 ; on success and nil if the file couldn't be displayed.
1342
1343 (defun gnus-uu-call-synchronous (file-name action)
1344 (let (did-view command)
1345 (save-excursion
1346 (set-buffer (get-buffer-create gnus-uu-output-buffer-name))
1347 (erase-buffer)
1348 (setq command (gnus-uu-command action file-name))
1349 (message (format "Viewing with '%s'" command))
1350 (if (not (= 0 (call-process "sh" nil t nil "-c" command)))
1351 (progn
1352 (goto-char 1)
1353 (while (re-search-forward "\n" nil t)
1354 (replace-match " "))
1355 (message (concat "Error: " (buffer-substring 1 (point-max))))
1356 (sit-for 2))
1357 (message "")
1358 (setq did-view t)))
1359 did-view))
1360
1361 ; `gnus-uu-call-asyncronous' takes two parameters: The name of the
1362 ; file to be displayed and the command to display it with. Since the
1363 ; view command is executed asynchronously, it's kinda hard to decide
1364 ; whether the command succeded or not, so this function always returns
1365 ; t. It also adds "; rm -f file-name" to the end of the execution
1366 ; string, so the file will be removed after viewing has ended.
1367
1368 (defun gnus-uu-call-asynchronous (file-name action)
1369 (let (command file tmp-file start)
1370 (while (string-match "/" file-name start)
1371 (setq start (1+ (match-beginning 0))))
1372 (setq file (substring file-name start))
1373 (setq tmp-file (concat gnus-uu-tmp-dir file))
1374 (if (string= tmp-file file-name)
1375 ()
1376 (rename-file file-name tmp-file t)
1377 (setq file-name tmp-file))
1378
1379 (setq command (gnus-uu-command action file-name))
1380 (setq command (format "%s ; rm -f %s" command file-name))
1381 (message (format "Viewing with %s" command))
1382 (start-process "gnus-uu-view" nil "sh" "-c" command)
1383 t))
1384
1385
1386 ; `gnus-uu-decode-and-strip' does all the main work. It finds out what
1387 ; articles to grab, grabs them, strips the result and decodes. If any
1388 ; of these operations fail, it returns nil, t otherwise. If shar is
1389 ; t, it will pass this on to `gnus-uu-grab-articles', which will
1390 ; (probably) unshar the articles. If use-marked is non-nil, it won't
1391 ; try to find articles, but use the marked list.
1392
1393 (defun gnus-uu-decode-and-strip (&optional shar use-marked)
1394 (let (list-of-articles)
1395 (save-excursion
1396
1397 (if use-marked
1398 (progn (if (eq gnus-uu-marked-article-list ())
1399 (message "No articles marked")
1400 (setq list-of-articles (reverse gnus-uu-marked-article-list))
1401 (gnus-uu-unmark-all-articles)))
1402 (setq list-of-articles (gnus-uu-get-list-of-articles)))
1403
1404 (and list-of-articles
1405 (gnus-uu-grab-articles list-of-articles
1406 (if shar
1407 'gnus-uu-unshar-article
1408 'gnus-uu-uustrip-article-as))))))
1409
1410
1411 ; Takes a string and puts a \ in front of every special character;
1412 ; ignores any leading "version numbers" thingies that they use in the
1413 ; comp.binaries groups, and either replaces anything that looks like
1414 ; "2/3" with "[0-9]+/[0-9]+" or, if it can't find something like that,
1415 ; replaces the last two numbers with "[0-9]+". This, in my experience,
1416 ; should get most postings of a series."
1417
1418 (defun gnus-uu-reginize-string (string)
1419 (let ((count 2)
1420 (vernum "v[0-9]+[a-z][0-9]+:")
1421 reg beg)
1422 (save-excursion
1423 (set-buffer (get-buffer-create gnus-uu-output-buffer-name))
1424 (erase-buffer)
1425 (insert (regexp-quote string))
1426 (setq beg 1)
1427
1428 (setq case-fold-search nil)
1429 (goto-char 1)
1430 (if (looking-at vernum)
1431 (progn
1432 (replace-match vernum t t)
1433 (setq beg (length vernum))))
1434
1435 (goto-char beg)
1436 (if (re-search-forward "[ \t]*[0-9]+/[0-9]+" nil t)
1437 (replace-match " [0-9]+/[0-9]+")
1438
1439 (goto-char beg)
1440 (if (re-search-forward "[0-9]+[ \t]*of[ \t]*[0-9]+" nil t)
1441 (replace-match "[0-9]+ of [0-9]+")
1442
1443 (end-of-line)
1444 (while (and (re-search-backward "[0-9]" nil t) (> count 0))
1445 (while (and
1446 (looking-at "[0-9]")
1447 (< 1 (goto-char (1- (point))))))
1448 (re-search-forward "[0-9]+" nil t)
1449 (replace-match "[0-9]+")
1450 (backward-char 5)
1451 (setq count (1- count)))))
1452
1453 (goto-char beg)
1454 (while (re-search-forward "[ \t]+" nil t)
1455 (replace-match "[ \t]*" t t))
1456
1457 (buffer-substring 1 (point-max)))))
1458
1459
1460 ; Finds all articles that matches the regular expression given.
1461 ; Returns the resulting list.
1462
1463 (defun gnus-uu-get-list-of-articles (&optional subject mark-articles only-unread)
1464 (let (beg end reg-subject list-of-subjects list-of-numbers art-num)
1465 (save-excursion
1466
1467 ; If the subject is not given, this function looks at the current subject
1468 ; and takes that.
1469
1470 (if subject
1471 (setq reg-subject subject)
1472 (end-of-line)
1473 (setq end (point))
1474 (beginning-of-line)
1475 (if (not (re-search-forward "\\] " end t))
1476 (progn (message "No valid subject chosen") (sit-for 2))
1477 (setq subject (buffer-substring (point) end))
1478 (setq reg-subject
1479 (concat "\\[.*\\] " (gnus-uu-reginize-string subject)))))
1480
1481 ; (message reg-subject)(sleep-for 2)
1482
1483 (if reg-subject
1484 (progn
1485
1486 ; Collect all subjects matching reg-subject.
1487
1488 (let ((case-fold-search t))
1489 (setq case-fold-search t)
1490 (goto-char 1)
1491 (while (re-search-forward reg-subject nil t)
1492 (beginning-of-line)
1493 (setq beg (point))
1494 (if (or (not only-unread) (looking-at " \\|-"))
1495 (progn
1496 (end-of-line)
1497 (setq list-of-subjects (cons
1498 (buffer-substring beg (point))
1499 list-of-subjects)))
1500 (end-of-line))))
1501
1502 ; Expand all numbers in all the subjects: (hi9 -> hi0009, etc).
1503
1504 (setq list-of-subjects (gnus-uu-expand-numbers list-of-subjects))
1505
1506 ; Sort the subjects.
1507
1508 (setq list-of-subjects (sort list-of-subjects 'gnus-uu-string<))
1509
1510 ; Get the article numbers from the sorted list of subjects.
1511
1512 (while list-of-subjects
1513 (setq art-num (gnus-uu-article-number (car list-of-subjects)))
1514 (if mark-articles (gnus-summary-mark-as-read art-num ?#))
1515 (setq list-of-numbers (cons art-num list-of-numbers))
1516 (setq list-of-subjects (cdr list-of-subjects)))
1517
1518 (setq list-of-numbers (nreverse list-of-numbers))
1519
1520 (if (not list-of-numbers)
1521 (progn
1522 (message (concat "No subjects matched " subject))
1523 (sit-for 2)))))
1524
1525 list-of-numbers)))
1526
1527
1528 ; Takes a list of strings and "expands" all numbers in all the
1529 ; strings. That is, this function makes all numbers equal length by
1530 ; prepending lots of zeroes before each number. This is to ease later
1531 ; sorting to find out what sequence the articles are supposed to be
1532 ; decoded in. Returns the list of expanded strings.
1533
1534 (defun gnus-uu-expand-numbers (string-list)
1535 (let (string out-list pos num)
1536 (save-excursion
1537 (set-buffer (get-buffer-create gnus-uu-output-buffer-name))
1538 (while string-list
1539 (erase-buffer)
1540 (setq string (car string-list))
1541 (setq string-list (cdr string-list))
1542 (insert string)
1543 (goto-char 1)
1544 (while (re-search-forward "[ \t]+" nil t)
1545 (replace-match " "))
1546 (goto-char 1)
1547 (while (re-search-forward "[A-Za-z]" nil t)
1548 (replace-match "a" t t))
1549
1550 (goto-char 1)
1551 (if (not (search-forward "] " nil t))
1552 ()
1553 (while (re-search-forward "[0-9]+" nil t)
1554 (replace-match
1555 (format "%06d"
1556 (string-to-int (buffer-substring
1557 (match-beginning 0) (match-end 0))))))
1558 (setq string (buffer-substring 1 (point-max)))
1559 (setq out-list (cons string out-list)))))
1560 out-list))
1561
1562
1563 ; Used in a sort for finding out what string is bigger, but ignoring
1564 ; everything before the subject part.
1565
1566 (defun gnus-uu-string< (string1 string2)
1567 (string< (substring string1 (string-match "\\] " string1))
1568 (substring string2 (string-match "\\] " string2))))
1569
1570
1571 ;; gnus-uu-grab-article
1572 ;
1573 ; This is the general multi-article treatment function. It takes a
1574 ; list of articles to be grabbed and a function to apply to each
1575 ; article. It puts the result in `gnus-uu-result-buffer'.
1576 ;
1577 ; The function to be called should take two parameters. The first is
1578 ; the buffer that has the article that should be treated. The function
1579 ; should leave the result in this buffer as well. This result is then
1580 ; appended on to the `gnus-uu-result-buffer'.
1581 ;
1582 ; The second parameter is the state of the list of articles, and can
1583 ; have three values: 'start, 'middle and 'end.
1584 ;
1585 ; The function can have several return values:
1586 ; 'error if there was an error while treating.
1587 ; 'end if the last article has been sighted.
1588 ; 'begin-and-end if the article is both the beginning and
1589 ; the end. All these three return values results in
1590 ; `gnus-uu-grab-articles' stopping traversing of the list
1591 ; of articles.
1592 ; 'middle if the article is a "middle" article.
1593 ; 'ok if everything is ok.
1594
1595 (defvar gnus-uu-has-been-grabbed nil)
1596
1597 (defun gnus-uu-unmark-list-of-grabbed (&optional dont-unmark-last-article)
1598 (let (art)
1599 (if (or (not gnus-uu-has-been-grabbed)
1600 (not gnus-uu-unmark-articles-not-decoded))
1601 ()
1602 (if dont-unmark-last-article
1603 (progn
1604 (setq art (car gnus-uu-has-been-grabbed))
1605 (setq gnus-uu-has-been-grabbed (cdr gnus-uu-has-been-grabbed))))
1606 (while gnus-uu-has-been-grabbed
1607 (gnus-summary-mark-as-unread (car gnus-uu-has-been-grabbed) t)
1608 (setq gnus-uu-has-been-grabbed (cdr gnus-uu-has-been-grabbed)))
1609 (if dont-unmark-last-article
1610 (setq gnus-uu-has-been-grabbed (list art))))))
1611
1612
1613 ; This function takes a list of articles and a function to apply to
1614 ; each article grabbed. The result of the function is appended on to
1615 ; `gnus-uu-result-buffer'.
1616 ;
1617 ; This function returns t if the grabbing and the process-function
1618 ; has been successful and nil otherwise."
1619
1620 (defun gnus-uu-grab-articles (list-of-articles process-function)
1621 (let ((result-buffer (get-buffer-create gnus-uu-result-buffer))
1622 (state 'first)
1623 (process-state 'ok)
1624 (result t)
1625 (wrong-type t)
1626 (has-been-begin nil)
1627 (article nil))
1628
1629 (save-excursion
1630 (set-buffer result-buffer)
1631 (erase-buffer))
1632 (setq gnus-uu-has-been-grabbed nil)
1633 (while (and list-of-articles
1634 (not (eq process-state 'end))
1635 (not (eq process-state 'begin-and-end))
1636 (not (eq process-state 'error)))
1637 (setq article (car list-of-articles))
1638 (setq list-of-articles (cdr list-of-articles))
1639 (setq gnus-uu-has-been-grabbed (cons article gnus-uu-has-been-grabbed))
1640
1641 (if (eq list-of-articles ()) (setq state 'last))
1642
1643 (message (format "Getting article %d" article))
1644 (if (not (= (or gnus-current-article 0) article))
1645 (gnus-summary-display-article article))
1646 (gnus-summary-mark-as-read article)
1647
1648 (save-excursion
1649 (set-buffer gnus-article-buffer)
1650 (widen))
1651
1652 (setq process-state (funcall process-function gnus-article-buffer state))
1653
1654 (if (or (eq process-state 'begin) (eq process-state 'begin-and-end)
1655 (eq process-state 'ok))
1656 (setq has-been-begin t))
1657
1658 (if (not (eq process-state 'wrong-type))
1659 (setq wrong-type nil)
1660 (if gnus-uu-unmark-articles-not-decoded
1661 (gnus-summary-mark-as-unread article t)))
1662
1663 (if gnus-uu-do-sloppy-uudecode
1664 (setq wrong-type nil))
1665
1666 (if (and (not has-been-begin)
1667 (not gnus-uu-do-sloppy-uudecode)
1668 (or (eq process-state 'end)
1669 (eq process-state 'middle)))
1670 (progn
1671 (setq process-state 'error)
1672 (message "No begin part at the beginning")
1673 (sit-for 2))
1674 (setq state 'middle)))
1675
1676 (if (and (not has-been-begin) (not gnus-uu-do-sloppy-uudecode))
1677 (progn
1678 (setq result nil)
1679 (message "Wrong type file")
1680 (sit-for 2))
1681 (if (eq process-state 'error)
1682 (setq result nil)
1683 (if (not (or (eq process-state 'ok)
1684 (eq process-state 'end)
1685 (eq process-state 'begin-and-end)))
1686 (progn
1687 (if (not gnus-uu-do-sloppy-uudecode)
1688 (progn
1689 (message "End of articles reached before end of file")
1690 (sit-for 2)))
1691 (gnus-uu-unmark-list-of-grabbed)
1692 (setq result nil)))))
1693 (setq gnus-uu-rest-of-articles list-of-articles)
1694 result))
1695
1696
1697 (defun gnus-uu-uudecode-sentinel (process event)
1698 ; (message "Process '%s' has received event '%s'" process event)
1699 ; (sit-for 2)
1700 (delete-process (get-process process)))
1701
1702
1703 (defun gnus-uu-uustrip-article-as (process-buffer in-state)
1704 (let ((state 'ok)
1705 (process-connection-type nil)
1706 start-char pst name-beg name-end buf-state)
1707 (save-excursion
1708 (set-buffer process-buffer)
1709 (setq buf-state buffer-read-only)
1710 (setq buffer-read-only nil)
1711
1712 (goto-char 1)
1713
1714 (if gnus-uu-kill-carriage-return
1715 (progn
1716 (while (search-forward "
1717 " nil t)
1718 (delete-backward-char 1))
1719 (goto-char 1)))
1720
1721 (if (not (re-search-forward gnus-uu-begin-string nil t))
1722 (if (not (re-search-forward gnus-uu-body-line nil t))
1723 (setq state 'wrong-type)))
1724
1725 (if (eq state 'wrong-type)
1726 ()
1727 (beginning-of-line)
1728 (setq start-char (point))
1729
1730 (if (looking-at gnus-uu-begin-string)
1731 (progn
1732 (setq name-end (match-end 1))
1733 (goto-char (setq name-beg (match-beginning 1)))
1734 (while (re-search-forward "/" name-end t)
1735 (replace-match "-"))
1736 (setq gnus-uu-file-name (buffer-substring name-beg name-end))
1737 (and gnus-uu-uudecode-process
1738 (setq pst (process-status
1739 (or gnus-uu-uudecode-process "nevair")))
1740 (if (or (eq pst 'stop) (eq pst 'run))
1741 (progn
1742 (delete-process gnus-uu-uudecode-process)
1743 (gnus-uu-unmark-list-of-grabbed t))))
1744 (setq gnus-uu-uudecode-process
1745 (start-process
1746 "*uudecode*"
1747 (get-buffer-create gnus-uu-output-buffer-name)
1748 "sh" "-c"
1749 (format "cd %s ; uudecode" gnus-uu-tmp-dir)))
1750 (set-process-sentinel
1751 gnus-uu-uudecode-process 'gnus-uu-uudecode-sentinel)
1752 (setq state 'begin)
1753 (gnus-uu-add-file (concat gnus-uu-tmp-dir gnus-uu-file-name)))
1754 (setq state 'middle))
1755
1756 (goto-char (point-max))
1757
1758 (re-search-backward
1759 (concat gnus-uu-body-line "\\|" gnus-uu-end-string) nil t)
1760 (beginning-of-line)
1761
1762 (if (looking-at gnus-uu-end-string)
1763 (if (eq state 'begin)
1764 (setq state 'begin-and-end)
1765 (setq state 'end)))
1766 (forward-line 1)
1767
1768 ; (message "Ja: %s" state)(sit-for 0)(sleep-for 2)
1769
1770 (and gnus-uu-uudecode-process
1771 (setq pst (process-status (or gnus-uu-uudecode-process "nevair")))
1772 (if (or (eq pst 'run) (eq pst 'stop))
1773 (progn
1774 (if gnus-uu-correct-stripped-uucode
1775 (progn
1776 (gnus-uu-check-correct-stripped-uucode
1777 start-char (point))
1778 (goto-char (point-max))
1779 (re-search-backward
1780 (concat gnus-uu-body-line "\\|" gnus-uu-end-string)
1781 nil t)
1782 (forward-line 1)))
1783 (condition-case err
1784 (process-send-region gnus-uu-uudecode-process
1785 start-char (point))
1786 (error
1787 (progn
1788 (message "Her var en uuerror")
1789 (sleep-for 2)
1790 (setq state 'wrong-type)
1791 (delete-process gnus-uu-uudecode-process)))))
1792 (setq state 'wrong-type)))
1793 (if (not gnus-uu-uudecode-process)
1794 (setq state 'wrong-type)))
1795
1796 (setq buffer-read-only buf-state))
1797 state))
1798
1799
1800 ; This function is used by `gnus-uu-grab-articles' to treat
1801 ; a shared article.
1802
1803 (defun gnus-uu-unshar-article (process-buffer in-state)
1804 (let ((state 'ok)
1805 start-char)
1806 (save-excursion
1807 (set-buffer process-buffer)
1808 (goto-char 1)
1809 (if (not (re-search-forward gnus-uu-shar-begin-string nil t))
1810 (setq state 'wrong-type)
1811 (beginning-of-line)
1812 (setq start-char (point))
1813 (call-process-region
1814 start-char (point-max) "sh" nil
1815 (get-buffer-create gnus-uu-output-buffer-name) nil
1816 "-c" (concat "cd " gnus-uu-shar-directory " ; sh"))))
1817 state))
1818
1819
1820 ; Returns the name of what the shar file is going to unpack.
1821
1822 (defun gnus-uu-find-name-in-shar ()
1823 (let ((oldpoint (point))
1824 res)
1825 (goto-char 1)
1826 (if (re-search-forward gnus-uu-shar-name-marker nil t)
1827 (setq res (buffer-substring (match-beginning 1) (match-end 1))))
1828 (goto-char oldpoint)
1829 res))
1830
1831
1832 ; Returns the article number of the given subject.
1833
1834 (defun gnus-uu-article-number (subject)
1835 (let (end)
1836 (string-match "[0-9]+[^0-9]" subject 1)
1837 (setq end (match-end 0))
1838 (string-to-int
1839 (substring subject (string-match "[0-9]" subject 1) end))))
1840
1841
1842 ; UUdecodes everything in the buffer and returns the name of the
1843 ; resulting file.
1844
1845 (defun gnus-uu-decode (directory)
1846 (let ((command (concat "cd " directory " ; uudecode"))
1847 file-name)
1848 (save-excursion
1849 (message "Uudecoding...")
1850 (set-buffer (get-buffer-create gnus-uu-result-buffer))
1851 (setq file-name (concat gnus-uu-tmp-dir gnus-uu-file-name))
1852 (gnus-uu-add-file file-name)
1853 (call-process-region 1 (point-max) "sh" nil t nil "-c" command)
1854 file-name)))
1855
1856
1857 ; `gnus-uu-choose-action' chooses what action to perform given the name
1858 ; and `gnus-uu-file-action-list'. Returns either nil if no action is
1859 ; found, or the name of the command to run if such a rule is found.
1860
1861 (defun gnus-uu-choose-action (file-name file-action-list)
1862 (let ((action-list (copy-sequence file-action-list))
1863 rule action)
1864 (while (not (or (eq action-list ()) action))
1865 (setq rule (car action-list))
1866 (setq action-list (cdr action-list))
1867 (if (string-match (car rule) file-name)
1868 (setq action (car (cdr rule)))))
1869 action))
1870
1871
1872 ; Moves the file from the tmp directory to where the user wants it.
1873
1874 (defun gnus-uu-save-file (from-file-name &optional default-dir ignore-existing)
1875 (let (dir file-name command)
1876 (string-match "/[^/]*$" from-file-name)
1877 (setq file-name (substring from-file-name (1+ (match-beginning 0))))
1878 (if default-dir
1879 (setq dir default-dir)
1880 (setq dir (gnus-uu-read-directory "Where do you want the file? ")))
1881 (if (and (not ignore-existing) (file-exists-p (concat dir file-name)))
1882 (progn
1883 (message (concat "There already is a file called " file-name))
1884 (sit-for 2)
1885 (setq file-name
1886 (read-file-name "Give a new name: " dir (concat dir file-name)
1887 nil file-name)))
1888 (setq file-name (concat dir file-name)))
1889 (rename-file from-file-name file-name t)))
1890
1891
1892 (defun gnus-uu-read-directory (prompt &optional default)
1893 (let (dir ok create)
1894 (while (not ok)
1895 (setq ok t)
1896 (setq dir (if default default
1897 (read-file-name prompt gnus-uu-current-save-dir
1898 gnus-uu-current-save-dir)))
1899 (while (string-match "/$" dir)
1900 (setq dir (substring dir 0 (match-beginning 0))))
1901 (if (file-exists-p dir)
1902 (if (not (file-directory-p dir))
1903 (progn
1904 (setq ok nil)
1905 (message "%s is a file" dir)
1906 (sit-for 2)))
1907 (setq create ?o)
1908 (while (not (or (= create ?y) (= create ?n)))
1909 (message "%s: No such directory. Do you want to create it? (y/n)"
1910 dir)
1911 (setq create (read-char)))
1912 (if (= create ?y) (make-directory dir))))
1913 (setq gnus-uu-current-save-dir (concat dir "/"))))
1914
1915
1916 ; Unpacks an archive and views all the files in it. Returns t if
1917 ; viewing one or more files is successful.
1918
1919 (defun gnus-uu-treat-archive (file-name)
1920 (let ((arc-dir (make-temp-name
1921 (concat gnus-uu-tmp-dir "gnusuu")))
1922 action command files file did-view short-file-name)
1923 (setq action (gnus-uu-choose-action
1924 file-name (append gnus-uu-user-archive-rules
1925 (if gnus-uu-ignore-default-archive-rules
1926 nil
1927 gnus-uu-default-archive-rules))))
1928 (if (not action)
1929 (progn (message (format "No unpackers for the file %s" file-name))
1930 (sit-for 2))
1931 (string-match "/[^/]*$" file-name)
1932 (setq short-file-name (substring file-name (1+ (match-beginning 0))))
1933 (setq command (format "%s %s %s ; cd %s ; %s "
1934 (if (or (string= action "uncompress")
1935 (string= action "gunzip"))
1936 "cp"
1937 "mv")
1938 (gnus-uu-command "" file-name) arc-dir
1939 arc-dir
1940 (gnus-uu-command action short-file-name)))
1941
1942 (make-directory arc-dir)
1943 (gnus-uu-add-file arc-dir)
1944
1945 (save-excursion
1946 (set-buffer (get-buffer-create gnus-uu-output-buffer-name))
1947 (erase-buffer))
1948
1949 (message (format "Unpacking with %s..." action))
1950 (sleep-for 1)
1951
1952 (if (= 0 (call-process "sh" nil
1953 (get-buffer-create gnus-uu-output-buffer-name)
1954 nil "-c" command))
1955 (message "")
1956 (message "Error during unpacking of archive")
1957 (sit-for 0) (sleep-for 2)
1958 (setq gnus-uu-error-during-unarching t))
1959
1960 (if (not (or (string= action "uncompress")
1961 (string= action "gunzip")))
1962 (call-process "sh" nil (get-buffer gnus-uu-output-buffer-name)
1963 nil "-c" (format "mv %s %s"
1964 (gnus-uu-command "" (concat arc-dir "/" short-file-name))
1965 gnus-uu-tmp-dir)))
1966 (gnus-uu-add-file (concat gnus-uu-tmp-dir short-file-name))
1967
1968 (setq did-view
1969 (or (gnus-uu-show-directory arc-dir gnus-uu-use-interactive-view)
1970 did-view))
1971
1972 (if (and (not gnus-uu-use-interactive-view)
1973 (file-directory-p arc-dir))
1974 (delete-directory arc-dir)))
1975
1976 did-view))
1977
1978
1979 ; Tries to view all the files in the given directory. Returns t if
1980 ; viewing one or more files is successful.
1981
1982 (defun gnus-uu-show-directory (dir &optional dont-delete-files)
1983 (let (files file did-view)
1984 (setq files (directory-files dir t))
1985 (setq gnus-uu-generated-file-list
1986 (append files gnus-uu-generated-file-list))
1987 (while files
1988 (setq file (car files))
1989 (setq files (cdr files))
1990 (if (and (not (string-match "/\\.$" file))
1991 (not (string-match "/\\.\\.$" file)))
1992 (progn
1993 (set-file-modes file 448)
1994 (if (file-directory-p file)
1995 (setq did-view (or (gnus-uu-show-directory file
1996 dont-delete-files)
1997 did-view))
1998 (setq did-view (or (gnus-uu-view-file file t) did-view))
1999 (if (and (not dont-delete-files) (file-exists-p file))
2000 (delete-file file))))))
2001 (if (not dont-delete-files) (delete-directory dir))
2002 did-view))
2003
2004
2005 ;; Manual marking
2006
2007 (defun gnus-uu-enter-mark-in-list ()
2008 (let (article beg)
2009 (beginning-of-line)
2010 (setq beg (point))
2011 (end-of-line)
2012 (setq article (gnus-uu-article-number
2013 (buffer-substring beg (point))))
2014 (message (format "Adding article %d to list" article))
2015 (setq gnus-uu-marked-article-list
2016 (cons article gnus-uu-marked-article-list))))
2017
2018 (defun gnus-uu-mark-article ()
2019 "Marks the current article to be decoded later."
2020 (interactive)
2021 (gnus-uu-enter-mark-in-list)
2022 (gnus-summary-mark-as-read nil ?#)
2023 (gnus-summary-next-subject 1 nil))
2024
2025 (defun gnus-uu-unmark-article ()
2026 "Unmarks the current article."
2027 (interactive)
2028 (let ((in (copy-sequence gnus-uu-marked-article-list))
2029 out article beg found
2030 (old-point (point)))
2031 (beginning-of-line)
2032 (setq beg (point))
2033 (end-of-line)
2034 (setq article (gnus-uu-article-number (buffer-substring beg (point))))
2035 (message (format "Removing article %d" article))
2036 (while in
2037 (if (not (= (car in) article))
2038 (setq out (cons (car in) out))
2039 (setq found t)
2040 (message (format "Removing article %d" article)))
2041 (setq in (cdr in)))
2042 (if (not found) (message "Not a marked article."))
2043 (setq gnus-uu-marked-article-list (reverse out))
2044 (gnus-summary-mark-as-unread nil t)
2045 (gnus-summary-next-subject 1 nil)))
2046
2047
2048 (defun gnus-uu-unmark-all-articles ()
2049 "Removes the mark from all articles marked for decoding."
2050 (interactive)
2051 (let ((articles (copy-sequence gnus-uu-marked-article-list)))
2052 (while articles
2053 (gnus-summary-goto-subject (car articles))
2054 (gnus-summary-mark-as-unread nil t)
2055 (setq articles (cdr articles)))
2056 (setq gnus-uu-marked-article-list ())))
2057
2058 (defun gnus-uu-mark-by-regexp ()
2059 "Asks for a regular expression and marks all articles that match."
2060 (interactive)
2061 (let (exp)
2062 (setq exp (read-from-minibuffer "Enter regular expression: "))
2063 (setq gnus-uu-marked-article-list
2064 (reverse (gnus-uu-get-list-of-articles exp t)))
2065 (message "")))
2066
2067
2068 ;; Various
2069
2070 (defun gnus-uu-check-correct-stripped-uucode (start end)
2071 (let (found beg length short)
2072 (if (not gnus-uu-correct-stripped-uucode)
2073 ()
2074 (goto-char start)
2075
2076 (if (re-search-forward " \\|`" end t)
2077 (progn
2078 (goto-char start)
2079 (while (not (eobp))
2080 (progn
2081 (if (looking-at "\n") (replace-match ""))
2082 (forward-line 1))))
2083
2084 (while (not (eobp))
2085 (if (looking-at (concat gnus-uu-begin-string "\\|"
2086 gnus-uu-end-string))
2087 ()
2088 (if (not found)
2089 (progn
2090 (beginning-of-line)
2091 (setq beg (point))
2092 (end-of-line)
2093 (setq length (- (point) beg))))
2094 (setq found t)
2095 (beginning-of-line)
2096 (setq beg (point))
2097 (end-of-line)
2098 (if (not (= length (- (point) beg)))
2099 (insert (make-string (- length (- (point) beg)) ? ))))
2100 (forward-line 1))))))
2101
2102 (defun gnus-uu-initialize ()
2103 (setq gnus-uu-error-during-unarching nil)
2104 (if (not gnus-uu-use-interactive-view)
2105 ()
2106 (save-excursion
2107 (setq gnus-uu-interactive-file-list nil)
2108 (set-buffer (get-buffer-create gnus-uu-interactive-buffer-name))
2109 (erase-buffer)
2110 (gnus-uu-mode)
2111 (insert
2112 "# Press return to execute a command.
2113 # Press `C-c C-c' to exit interactive view.
2114
2115 "))))
2116
2117
2118 ; Kills the temporary uu buffers, kills any processes, etc.
2119
2120 (defun gnus-uu-clean-up ()
2121 (let (buf pst)
2122 (setq gnus-uu-do-sloppy-uudecode nil)
2123 (and gnus-uu-uudecode-process
2124 (setq pst (process-status (or gnus-uu-uudecode-process "nevair")))
2125 (if (or (eq pst 'stop) (eq pst 'run))
2126 (delete-process gnus-uu-uudecode-process)))
2127 (and (not gnus-uu-asynchronous)
2128 (setq buf (get-buffer gnus-uu-output-buffer-name))
2129 (kill-buffer buf))
2130 (and (setq buf (get-buffer gnus-uu-result-buffer))
2131 (kill-buffer buf))))
2132
2133
2134 ; `gnus-uu-check-for-generated-files' deletes any generated files that
2135 ; hasn't been deleted, if, for instance, the user terminated decoding
2136 ; with `C-g'.
2137
2138 (defun gnus-uu-check-for-generated-files ()
2139 (let (file)
2140 (while gnus-uu-generated-file-list
2141 (setq file (car gnus-uu-generated-file-list))
2142 (setq gnus-uu-generated-file-list (cdr gnus-uu-generated-file-list))
2143 (if (not (string-match "/\\.[\\.]?$" file))
2144 (progn
2145 (if (file-directory-p file)
2146 (delete-directory file)
2147 (if (file-exists-p file)
2148 (delete-file file))))))))
2149
2150
2151 ; Add a file to be checked (and deleted if it still exists upon
2152 ; exiting the newsgroup) to a list
2153 (defun gnus-uu-add-file (file)
2154 (setq gnus-uu-generated-file-list
2155 (cons file gnus-uu-generated-file-list)))
2156
2157
2158 ; Go to the next unread subject. If there is no further unread
2159 ; subjects, go to the last subject in the buffer.
2160 (defun gnus-uu-summary-next-subject ()
2161 (if (not (gnus-summary-search-forward t))
2162 (progn
2163 (goto-char 1)
2164 (sit-for 0)
2165 (goto-char (point-max))
2166 (forward-line -1)
2167 (beginning-of-line)
2168 (search-forward ":" nil t)))
2169 (sit-for 0)
2170 (gnus-summary-recenter))
2171
2172 ; Inputs an action and a file and returns a full command, putting
2173 ; ticks round the file name and escaping any ticks in the file name.
2174 (defun gnus-uu-command (action file)
2175 (let ((ofile ""))
2176 (while (string-match "`\\|\"\\|\\$\\|\\\\" file)
2177 (progn
2178 (setq ofile
2179 (concat ofile (substring file 0 (match-beginning 0)) "\\"
2180 (substring file (match-beginning 0) (match-end 0))))
2181 (setq file (substring file (1+ (match-beginning 0))))))
2182 (setq ofile (concat "\"" ofile file "\""))
2183 (if (string-match "%s" action)
2184 (format action ofile)
2185 (concat action " " ofile))))
2186
2187
2188 ;; Initializing
2189
2190 (add-hook 'gnus-exit-group-hook
2191 '(lambda ()
2192 (gnus-uu-clean-up)
2193 (setq gnus-uu-marked-article-list nil)
2194 (gnus-uu-check-for-generated-files)))
2195
2196
2197 ;; Interactive exec mode
2198
2199 (defvar gnus-uu-output-window nil)
2200 (defvar gnus-uu-mode-hook nil)
2201 (defvar gnus-uu-mode-map nil)
2202
2203 (defun gnus-uu-do-interactive ()
2204 (let (int-buffer out-buf)
2205 (set-buffer
2206 (setq int-buffer (get-buffer gnus-uu-interactive-buffer-name)))
2207 (switch-to-buffer-other-window int-buffer)
2208 (pop-to-buffer int-buffer)
2209 (setq gnus-uu-output-window
2210 (split-window nil (- (window-height) gnus-uu-output-window-height)))
2211 (set-window-buffer gnus-uu-output-window
2212 (setq out-buf
2213 (get-buffer-create gnus-uu-output-buffer-name)))
2214 (save-excursion (set-buffer out-buf) (erase-buffer))
2215 (goto-char 1)
2216 (forward-line 3)
2217 (run-hooks 'gnus-uu-mode-hook)))
2218
2219
2220 (defun gnus-uu-enter-interactive-file (action file)
2221 (let (command)
2222 (save-excursion
2223 (setq gnus-uu-interactive-file-list
2224 (cons file gnus-uu-interactive-file-list))
2225 (set-buffer (get-buffer gnus-uu-interactive-buffer-name))
2226 (setq command (gnus-uu-command action file))
2227 (insert (format "%s\n" command)))))
2228
2229
2230 (defun gnus-uu-interactive-execute ()
2231 "Executes the command on the current line in interactive mode."
2232 (interactive)
2233 (let (beg out-buf command)
2234 (beginning-of-line)
2235 (setq beg (point))
2236 (end-of-line)
2237 (setq command (buffer-substring beg (point)))
2238 (setq out-buf (get-buffer-create gnus-uu-output-buffer-name))
2239 (save-excursion
2240 (set-buffer out-buf)
2241 (erase-buffer)
2242 (insert (format "$ %s \n\n" command)))
2243 (message "Executing...")
2244 (if gnus-uu-asynchronous
2245 (start-process "gnus-uu-view" out-buf "sh" "-c" command)
2246 (call-process "sh" nil out-buf nil "-c" command)
2247 (message ""))
2248 (forward-line 1)
2249 (beginning-of-line)))
2250
2251
2252 (defun gnus-uu-interactive-end ()
2253 "This function exits interactive view mode and returns to summary mode."
2254 (interactive)
2255 (let (buf)
2256 (delete-window gnus-uu-output-window)
2257 (gnus-uu-clean-up)
2258 (if (not gnus-uu-asynchronous) (gnus-uu-check-for-generated-files))
2259 (setq buf (get-buffer gnus-uu-interactive-buffer-name))
2260 (if gnus-article-buffer (switch-to-buffer gnus-article-buffer))
2261 (if buf (kill-buffer buf))
2262 (pop-to-buffer gnus-summary-buffer)))
2263
2264
2265 (if gnus-uu-mode-map
2266 ()
2267 (setq gnus-uu-mode-map (make-sparse-keymap))
2268 (define-key gnus-uu-mode-map "\C-c\C-x" 'gnus-uu-interactive-execute)
2269 (define-key gnus-uu-mode-map "\C-c\C-v" 'gnus-uu-interactive-execute)
2270 (define-key gnus-uu-mode-map "\C-m" 'gnus-uu-interactive-execute)
2271 (define-key gnus-uu-mode-map "\C-c\C-c" 'gnus-uu-interactive-end)
2272 (define-key gnus-uu-mode-map "\C-cs"
2273 'gnus-uu-interactive-save-current-file)
2274 (define-key gnus-uu-mode-map "\C-c\C-s"
2275 'gnus-uu-interactive-save-current-file-silent)
2276 (define-key gnus-uu-mode-map "\C-c\C-w" 'gnus-uu-interactive-save-all-files)
2277 (define-key gnus-uu-mode-map "\C-c\C-o" 'gnus-uu-interactive-save-original-file))
2278
2279
2280 (defun gnus-uu-interactive-save-original-file ()
2281 "Saves the file from whence the file on the current line came from."
2282 (interactive)
2283 (let (file)
2284 (if (file-exists-p
2285 (setq file (concat gnus-uu-tmp-dir
2286 (or gnus-uu-file-name gnus-uu-shar-file-name))))
2287 (gnus-uu-save-file file)
2288 (message "Already saved."))))
2289
2290
2291 (defun gnus-uu-interactive-save-current-file-silent ()
2292 "Saves the file referred to on the current line in the current directory."
2293 (interactive)
2294 (gnus-uu-interactive-save-current-file t))
2295
2296 (defun gnus-uu-interactive-save-current-file (&optional dont-ask silent)
2297 "Saves the file referred to on the current line."
2298 (interactive)
2299 (let (files beg line file)
2300 (setq files (copy-sequence gnus-uu-interactive-file-list))
2301 (beginning-of-line)
2302 (setq beg (point))
2303 (end-of-line)
2304 (setq line (buffer-substring beg (point)))
2305 (while (and files
2306 (not (string-match
2307 (concat "" (regexp-quote (setq file (car files))) "")
2308 line)))
2309 (setq files (cdr files)))
2310 (beginning-of-line)
2311 (forward-line 1)
2312 (if (not files)
2313 (if (not silent)
2314 (progn (message "Could not find file") (sit-for 2)))
2315 (gnus-uu-save-file file (if dont-ask gnus-uu-current-save-dir nil) silent)
2316 (delete-region beg (point)))))
2317
2318
2319 (defun gnus-uu-interactive-save-all-files ()
2320 "Saves all files referred to in the interactive buffer."
2321 (interactive)
2322 (let (dir)
2323 (goto-char 1)
2324 (setq dir (gnus-uu-read-directory "Where do you want the files? "))
2325 (while (not (eobp))
2326 (gnus-uu-interactive-save-current-file t t))))
2327
2328 (defun gnus-uu-mode ()
2329 "Major mode for editing view commands in gnus-uu.
2330
2331 Commands:
2332 \\<gnus-uu-mode-map>Return, C-c C-v, C-c C-x Execute the current command
2333 \\[gnus-uu-interactive-end] End interactive mode
2334 \\[gnus-uu-interactive-save-current-file] Save the current file
2335 \\[gnus-uu-interactive-save-current-file-silent] Save the current file without asking
2336 where to put it
2337 \\[gnus-uu-interactive-save-all-files] Save all files
2338 \\[gnus-uu-interactive-save-original-file] Save the original file: If the files
2339 originated in an archive, the archive
2340 file is saved.
2341 "
2342 (interactive)
2343 (kill-all-local-variables)
2344 (use-local-map gnus-uu-mode-map)
2345 (setq mode-name "gnus-uu")
2346 (setq major-mode 'gnus-uu-mode)
2347 )
2348
2349 (define-key gnus-uu-mode-map "\C-c\C-x" 'gnus-uu-interactive-execute)
2350 (define-key gnus-uu-mode-map "\C-c\C-v" 'gnus-uu-interactive-execute)
2351 (define-key gnus-uu-mode-map "\C-m" 'gnus-uu-interactive-execute)
2352 (define-key gnus-uu-mode-map "\C-c\C-c" 'gnus-uu-interactive-end)
2353 (define-key gnus-uu-mode-map "\C-cs"
2354 'gnus-uu-interactive-save-current-file)
2355 (define-key gnus-uu-mode-map "\C-c\C-s"
2356 'gnus-uu-interactive-save-current-file-silent)
2357 (define-key gnus-uu-mode-map "\C-c\C-a" 'gnus-uu-interactive-save-all-files)
2358 (define-key gnus-uu-mode-map "\C-c\C-o" 'gnus-uu-interactive-save-original-file)
2359
2360 (provide 'gnus-uu)
2361
2362 ;; gnus-uu.el ends here