comparison lisp/w3/w3.el @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children ac2d302a0011
comparison
equal deleted inserted replaced
-1:000000000000 0:376386a54a3c
1 ;;; w3.el,v --- Main functions for emacs-w3 on all platforms/versions
2 ;; Author: wmperry
3 ;; Created: 1996/06/06 15:03:12
4 ;; Version: 1.550
5 ;; Keywords: faces, help, comm, news, mail, processes, mouse, hypermedia
6
7 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8 ;;; Copyright (c) 1993, 1994, 1995 by William M. Perry (wmperry@spry.com)
9 ;;;
10 ;;; This file is not part of GNU Emacs, but the same permissions apply.
11 ;;;
12 ;;; GNU Emacs is free software; you can redistribute it and/or modify
13 ;;; it under the terms of the GNU General Public License as published by
14 ;;; the Free Software Foundation; either version 2, or (at your option)
15 ;;; any later version.
16 ;;;
17 ;;; GNU Emacs is distributed in the hope that it will be useful,
18 ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ;;; GNU General Public License for more details.
21 ;;;
22 ;;; You should have received a copy of the GNU General Public License
23 ;;; along with GNU Emacs; see the file COPYING. If not, write to
24 ;;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
25 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
26
27 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
28 ;;; This is a major mode for browsing documents written in Hypertext Markup ;;;
29 ;;; Language (HTML). These documents are typicallly part of the World Wide ;;;
30 ;;; Web (WWW), a project to create a global information net in hypertext ;;;
31 ;;; format. ;;;
32 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
33
34 ;;; first start by making sure the load path is properly set. This code
35 ;;; is mostly taken from calc-2.02b
36 ;;;
37 ;;; this allows you to put the following in your .emacs file, instead of
38 ;;; having to know what the load-path for the w3 files is.
39 ;;;
40 ;;; (autoload 'w3 "w3/w3" "WWW Browser" t)
41
42 ;;; If w3 files exist on the load-path, we're all set.
43 (let ((name (and (fboundp 'w3)
44 (eq (car-safe (symbol-function 'w3)) 'autoload)
45 (nth 1 (symbol-function 'w3))))
46 (p load-path))
47 (while (and p (not (file-exists-p
48 (expand-file-name "w3-vars.elc" (car p)))))
49 (setq p (cdr p)))
50 (or p
51 ;;; If w3 is autoloaded using a path name, look there for w3 files.
52 ;;; This works for both relative ("w3/w3.elc") and absolute paths.
53 (and name (file-name-directory name)
54 (let ((p2 load-path)
55 (name2 (concat (file-name-directory name)
56 "w3-vars.elc")))
57 (while (and p2 (not (file-exists-p
58 (expand-file-name name2 (car p2)))))
59 (setq p2 (cdr p2)))
60 (if p2
61 (setq load-path (nconc load-path
62 (list
63 (directory-file-name
64 (file-name-directory
65 (expand-file-name
66 name (car p2)))))))))))
67 )
68
69
70 (load-library "w3-sysdp")
71 (or (featurep 'efs)
72 (featurep 'efs-auto)
73 (condition-case ()
74 (require 'ange-ftp)
75 (error nil)))
76
77 (require 'cl)
78 (require 'w3-vars)
79 (eval-and-compile
80 (require 'w3-draw))
81
82
83 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
84 ;;; Code for printing out roman numerals
85 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
86 (defun w3-decimal-to-roman (n)
87 ;; Convert from decimal to roman numerals
88 (let ((curmod 1000)
89 (str "")
90 (j 7)
91 i2 k curcnt)
92 (while (>= curmod 1)
93 (if (>= n curmod)
94 (progn
95 (setq curcnt (/ n curmod)
96 n (- n (* curcnt curmod)))
97 (if (= 4 (% curcnt 5))
98 (setq i2 (+ j (if (> curcnt 5) 1 0))
99 str (format "%s%c%c" str
100 (aref w3-roman-characters (1- j))
101 (aref w3-roman-characters i2)))
102 (progn
103 (if (>= curcnt 5)
104 (setq str (format "%s%c" str (aref w3-roman-characters j))
105 curcnt (- curcnt 5)))
106 (setq k 0)
107 (while (< k curcnt)
108 (setq str (format "%s%c" str
109 (aref w3-roman-characters (1- j)))
110 k (1+ k)))))))
111 (setq curmod (/ curmod 10)
112 j (- j 2)))
113 str))
114
115 (defun w3-decimal-to-alpha (n)
116 ;; Convert from decimal to alphabetical (a, b, c, ..., aa, ab,...)
117 (cond
118 ((< n 1) (char-to-string ?Z))
119 ((<= n 26) (char-to-string (+ ?A (1- n))))
120 (t (concat (char-to-string (+ ?A (1- (/ n 27))))
121 (w3-decimal-to-alpha (% n 26))))))
122
123
124 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
125 ;;; Functions for compatibility with XMosaic
126 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
127
128 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
129 ;;; Parse out the Mosaic documents-menu file
130 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
131 (defun w3-parse-docs-menu ()
132 ;; Parse the Mosaic documents menu
133 (let ((tmp-menu (append '((separator)) w3-starting-documents
134 '((separator))))
135 real-menu x y name url)
136 (if (or (not (file-exists-p w3-documents-menu-file))
137 (not (file-readable-p w3-documents-menu-file)))
138 nil
139 (save-excursion
140 (set-buffer (get-buffer-create " *w3-temp*"))
141 (erase-buffer)
142 (insert-file-contents w3-documents-menu-file)
143 (goto-char (point-min))
144 (while (not (eobp))
145 (if (not (looking-at "-+$"))
146 (setq x (progn (beginning-of-line) (point))
147 y (progn (end-of-line) (point))
148 name (prog1
149 (buffer-substring x y)
150 (delete-region x (min (1+ y) (point-max))))
151 x (progn (beginning-of-line) (point))
152 y (progn (end-of-line) (point))
153 url (prog1
154 (buffer-substring x y)
155 (delete-region x (min (1+ y) (point-max))))
156 tmp-menu (if (rassoc url tmp-menu) tmp-menu
157 (cons (cons name url) tmp-menu)))
158 (setq tmp-menu (cons '(separator) tmp-menu))
159 (delete-region (point-min) (min (1+ (progn (end-of-line)
160 (point)))
161 (point-max)))))
162 (kill-buffer (current-buffer))))
163 (if (equal (car (car tmp-menu)) "") (setq tmp-menu (cdr tmp-menu)))
164 (while tmp-menu
165 (setq real-menu (cons (if (equal 'separator (car (car tmp-menu)))
166 "--------"
167 (vector (car (car tmp-menu))
168 (list 'w3-fetch
169 (if (listp (cdr (car tmp-menu)))
170 (car (cdr (car tmp-menu)))
171 (cdr (car tmp-menu)))) t))
172 real-menu)
173 tmp-menu (cdr tmp-menu)))
174 (setq w3-navigate-menu (append w3-navigate-menu real-menu
175 (list "-----")))))
176
177
178 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
179 ;;; Functions to pass files off to external viewers
180 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
181 (defun w3-start-viewer (fname cmd &optional view)
182 "Start a subprocess, named FNAME, executing CMD
183 If third arg VIEW is non-nil, show the output in a buffer when
184 the subprocess exits."
185 (if view (save-excursion
186 (set-buffer (get-buffer-create view))
187 (erase-buffer)))
188 (let ((proc
189 (start-process fname view (or shell-file-name
190 (getenv "ESHELL")
191 (getenv "SHELL")
192 "/bin/sh") "-c" cmd)))
193 proc))
194
195 (defun w3-viewer-filter (proc string)
196 ;; A process filter for asynchronous external viewers
197 (let ((buff (get-buffer-create (url-generate-new-buffer-name
198 (symbol-name
199 (read (nth 2 (process-command proc))))))))
200 (save-excursion
201 (set-buffer buff)
202 (erase-buffer)
203 (insert string)
204 (set-process-buffer proc buff)
205 (set-process-filter proc nil))))
206
207 (defun w3-viewer-sentinel (proc string)
208 ;; Delete any temp files left from a viewer process.
209 (let ((fname (process-name proc))
210 (buffr (process-buffer proc))
211 (status (process-exit-status proc)))
212 (if buffr
213 (w3-notify-when-ready buffr))
214 (and (/= 0 status)
215 (funcall url-confirmation-func
216 (format "Viewer for %s failed... save to disk? " fname))
217 (copy-file fname (read-file-name "Save as: ") t))
218 (if (and (file-exists-p fname)
219 (file-writable-p fname))
220 (delete-file fname))))
221
222 (defun w3-notify-when-ready (buff)
223 "Notify the user when BUFF is ready.
224 See the variable `w3-notify' for the different notification behaviors."
225 (if (stringp buff) (setq buff (get-buffer buff)))
226 (cond
227 ((null buff) nil)
228 ((eq w3-notify 'newframe)
229 ;; Since we run asynchronously, perhaps while Emacs is waiting for input,
230 ;; we must not leave a different buffer current.
231 ;; We can't rely on the editor command loop to reselect
232 ;; the selected window's buffer.
233 (save-excursion
234 (set-buffer buff)
235 (make-frame)))
236 ((eq w3-notify 'bully)
237 (pop-to-buffer buff)
238 (delete-other-windows))
239 ((eq w3-notify 'semibully)
240 (switch-to-buffer buff))
241 ((eq w3-notify 'aggressive)
242 (pop-to-buffer buff))
243 ((eq w3-notify 'friendly)
244 (display-buffer buff 'not-this-window))
245 ((eq w3-notify 'polite)
246 (beep)
247 (message "W3 buffer %s is ready." (buffer-name buff)))
248 ((eq w3-notify 'quiet)
249 (message "W3 buffer %s is ready." (buffer-name buff)))
250 (t (message ""))))
251
252 (defun w3-pass-to-viewer ()
253 ;; Pass a w3 buffer to a viewer
254 (set-buffer url-working-buffer)
255 (let* ((info url-current-mime-viewer) ; All the MIME viewer info
256 (view (cdr-safe (assoc "viewer" info))) ; How to view this file
257 (url (url-view-url t))
258 (fmt (cdr-safe (assoc "nametemplate" info)))) ; Template for name
259 (cond
260 (fmt nil)
261 ((cdr-safe (assoc "type" info))
262 (setq fmt (mm-type-to-file (cdr-safe (assoc "type" info))))
263 (if fmt (setq fmt (concat "%s" (car fmt)))
264 (setq fmt (concat "%s" (url-file-extension url-current-file))))))
265 (if (null view)
266 (setq view 'indented-text-mode))
267 (cond
268 ((symbolp view)
269 (if (not (memq view '(w3-prepare-buffer w3-print w3-source
270 w3-default-local-file
271 mm-multipart-viewer)))
272 (let ((bufnam (url-generate-new-buffer-name
273 (file-name-nondirectory
274 (or url-current-file "Unknown")))))
275 (if (string= bufnam "")
276 (setq bufnam (url-generate-new-buffer-name
277 (url-view-url t))))
278 (rename-buffer bufnam)
279 ;; Make the URL show in list-buffers output
280 (make-local-variable 'list-buffers-directory)
281 (setq list-buffers-directory (url-view-url t))
282 (set-buffer-modified-p nil)
283 (buffer-enable-undo)
284 (funcall view)
285 (w3-notify-when-ready bufnam))
286 (funcall view)))
287 ((stringp view)
288 (let ((fname (url-generate-unique-filename fmt)) proc)
289 (if (url-file-directly-accessible-p (url-view-url t))
290 (make-symbolic-link url-current-file fname t)
291 (if (featurep 'mule)
292 (write-region (point-min) (point-max) fname nil nil *noconv*)
293 (write-region (point-min) (point-max) fname)))
294 (if (get-buffer url-working-buffer)
295 (kill-buffer url-working-buffer))
296 (if (string-match "%s" view)
297 (setq view (concat (substring view 0 (match-beginning 0))
298 fname (substring view (match-end 0)))))
299 (if (string-match "%u" view)
300 (setq view (concat (substring view 0 (match-beginning 0))
301 url
302 (substring view (match-end 0)))))
303 (message "Passing to viewer %s " view)
304 (setq proc (w3-start-viewer fname view))
305 (set-process-filter proc 'w3-viewer-filter)
306 (set-process-sentinel proc 'w3-viewer-sentinel)))
307 ((listp view)
308 (set-buffer-modified-p nil)
309 (buffer-enable-undo)
310 (eval view))
311 (t
312 (message "Unknown viewer specified: %s" view)
313 (w3-notify-when-ready url-working-buffer)))))
314
315 (defun w3-save-binary-file ()
316 "Save a buffer to disk - this is used when `w3-dump-to-disk' is non-nil"
317 (interactive)
318 (let ((x (read-file-name "Filename to save as: "
319 (or mm-download-directory "~/")
320 (concat (or mm-download-directory "~/")
321 (url-basepath (or url-current-file "") t))
322 nil
323 (url-basepath (or url-current-file "") t)))
324 (require-final-newline nil))
325 (save-excursion
326 ;; more fixes from the MULE guys
327 (if w3-dump-to-disk
328 (let (jka-compr-compression-info-list
329 jam-zcat-filename-list)
330 (if (featurep 'mule)
331 (let ((mc-flag t))
332 (write-file x *noconv*))
333 (write-file x)))
334 (let ((fnha file-name-handler-alist)
335 (file-name-handler-alist nil))
336 (if (featurep 'mule)
337 (let ((mc-flag t))
338 (write-file x *noconv*))
339 (write-file x))))
340 (kill-buffer (current-buffer)))))
341
342 (defun w3-build-url (protocol)
343 "Build a url for PROTOCOL, return it as a string"
344 (interactive (list (cdr (assoc (completing-read
345 "Protocol: "
346 w3-acceptable-protocols-alist nil t)
347 w3-acceptable-protocols-alist))))
348 (let (user host port file)
349 (cond
350 ((null protocol) (error "Protocol is unknown to me!"))
351 ((string= protocol "news")
352 (setq host (read-string "Enter news server name, or blank for default: ")
353 port (read-string "Enter port number, or blank for default: ")
354 file (read-string "Newgroup name or Message-ID: ")))
355 ((string= protocol "mailto") (setq file (read-string "E-mail address: ")))
356 ((string= protocol "http")
357 (setq host (read-string "Enter server name: ")
358 port (read-string "Enter port number, or blank for default: ")
359 file (read-string "Remote file: "))
360 (and (string= "" port) (setq port nil))
361 (and (string= "" host) (error "Must specify a remote machine!")))
362 ((string= protocol "file")
363 (if (funcall url-confirmation-func "Local file?")
364 (setq file (read-file-name "Local File: " nil nil t))
365 (setq user (read-string "Login as user (blank=anonymous): ")
366 host (read-string "Remote machine name: "))
367 (and (string= user "") (setq user "anonymous"))
368 (and (string= host "") (error "Must specify a remote machine!"))
369 (setq file (read-file-name "File: " (format "/%s@%s:" user host)
370 nil t)
371 file (substring file (length (format "/%s@%s:" user host))))))
372 ((or (string= protocol "telnet")
373 (string= protocol "tn3270"))
374 (setq user (read-string "Login as user (blank=none): ")
375 host (read-string "Remote machine name: ")
376 port (read-string "Port number (blank=23): "))
377 (and (string= "" port) (setq port nil))
378 (and (string= "" user) (setq user nil))
379 (and (string= "" host) (error "Must specify a host machine!")))
380 ((string= protocol "gopher")
381 (setq host (read-string "Enter server name: ")
382 port (read-string "Enter port number, or blank for default: ")
383 file (read-string "Remote file: "))
384 (and (string= "" port) (setq port nil))
385 (and (string= "" host) (error "Must specify a remote machine!"))))
386 (message "%s:%s%s"
387 protocol
388 (if (null host) "" (concat "//" host
389 (if (null port) "" (concat ":" port))))
390 (if (= ?/ (string-to-char file)) file (concat "/" file)))))
391
392 ;;;###autoload
393 (defun w3-open-local (fname)
394 "Find a local file, and interpret it as a hypertext document.
395 It will prompt for an existing file or directory, and retrieve it as a
396 hypertext document. If it is a directory, and url-use-hypertext-dired
397 is non-nil, then an HTML directory listing is created on the fly.
398 Otherwise, dired-mode is used to visit the buffer."
399 (interactive "FLocal file: ")
400 (if (not w3-setup-done) (w3-do-setup))
401 (w3-fetch (concat "file:" fname)))
402
403 ;;;###autoload
404 (defun w3-find-file (fname)
405 "Find a local file, and interpret it as a hypertext document.
406 It will prompt for an existing file or directory, and retrieve it as a
407 hypertext document. If it is a directory, and url-use-hypertext-dired
408 is non-nil, then an HTML directory listing is created on the fly.
409 Otherwise, dired-mode is used to visit the buffer."
410 (interactive "FLocal file: ")
411 (w3-open-local fname))
412
413 ;;;###autoload
414 (defun w3-fetch-other-frame (&optional url)
415 "Attempt to follow the hypertext reference under point in a new frame.
416 With prefix-arg P, ignore viewers and dump the link straight
417 to disk."
418 (interactive (list (w3-read-url-with-default)))
419 (cond
420 ((and (fboundp 'make-frame)
421 (fboundp 'select-frame)
422 (not (eq (device-type) 'tty)))
423 (let ((frm (make-frame)))
424 (select-frame frm)
425 (delete-other-windows)
426 (w3-fetch url)))
427 (t (w3-fetch url))))
428
429 (defun w3-fetch-other-window (&optional url)
430 "Attempt to follow the hypertext reference under point in a new window.
431 With prefix-arg P, ignore viewers and dump the link straight
432 to disk."
433 (interactive (list (w3-read-url-with-default)))
434 (split-window)
435 (w3-fetch url))
436
437 (defun w3-url-completion-function (string predicate function)
438 (if (not w3-setup-done) (w3-do-setup))
439 (cond
440 ((null function)
441 (cond
442 ((get 'url-gethash 'sysdep-defined-this)
443 ;; Cheat! If we know that these are the sysdep-defined version
444 ;; of hashtables, they are an obarray.
445 (try-completion string url-global-history-hash-table predicate))
446 ((url-hashtablep url-global-history-hash-table)
447 (let ((list nil))
448 (url-maphash (function (lambda (key val)
449 (setq list (cons (cons (symbol-name key) val)
450 list))))
451 url-global-history-hash-table)
452 (try-completion string (nreverse list) predicate)))
453 (t nil)))
454 ((eq function t)
455 (cond
456 ((get 'url-gethash 'sysdep-defined-this)
457 ;; Cheat! If we know that these are the sysdep-defined version
458 ;; of hashtables, they are an obarray.
459 (all-completions string url-global-history-hash-table predicate))
460 ((url-hashtablep url-global-history-hash-table)
461 (let ((stub (concat "^" (regexp-quote string)))
462 (retval nil))
463 (url-maphash
464 (function
465 (lambda (url time)
466 (setq url (symbol-name url))
467 (if (string-match stub url)
468 (setq retval (cons url retval)))))
469 url-global-history-hash-table)
470 retval))
471 (t nil)))
472 ((eq function 'lambda)
473 (and (url-hashtablep url-global-history-hash-table)
474 (url-gethash string url-global-history-hash-table)
475 t))))
476
477 (defun w3-read-url-with-default ()
478 (url-do-setup)
479 (let* ((completion-ignore-case t)
480 (default
481 (if (eq major-mode 'w3-mode)
482 (if (and current-prefix-arg (w3-view-this-url t))
483 (w3-view-this-url t)
484 (url-view-url t))
485 (url-get-url-at-point)))
486 (url nil))
487 (if (not default)
488 (setq default "http://www."))
489 (setq url
490 (completing-read "URL: " 'w3-url-completion-function
491 nil nil default))
492 (if (string= url "")
493 (setq url (if (eq major-mode 'w3-mode)
494 (if (and current-prefix-arg (w3-view-this-url t))
495 (w3-view-this-url t)
496 (url-view-url t))
497 (url-get-url-at-point))))
498 url))
499
500 ;;;###autoload
501 (defun w3-fetch (&optional url)
502 "Retrieve a document over the World Wide Web.
503 The World Wide Web is a global hypertext system started by CERN in
504 Switzerland in 1991.
505
506 The document should be specified by its fully specified
507 Uniform Resource Locator. The document will be parsed, printed, or
508 passed to an external viewer as appropriate. Variable
509 `mm-mime-info' specifies viewers for particular file types."
510 (interactive (list (w3-read-url-with-default)))
511 (if (not w3-setup-done) (w3-do-setup))
512 (if (boundp 'w3-working-buffer)
513 (setq w3-working-buffer url-working-buffer))
514 (if (and (boundp 'command-line-args-left)
515 command-line-args-left
516 (string-match url-nonrelative-link (car command-line-args-left)))
517 (setq url (car command-line-args-left)
518 command-line-args-left (cdr command-line-args-left)))
519 (if (equal url "") (error "No document specified!"))
520 ;; legal use for relative URLs ?
521 (if (string-match "^www:[^/].*" url)
522 (setq url (concat (file-name-directory url-current-file)
523 (substring url 4))))
524 ;; In the common case, this is probably cheaper than searching.
525 (while (= (string-to-char url) ? )
526 (setq url (substring url 1)))
527 (cond
528 ((= (string-to-char url) ?#)
529 (w3-relative-link url))
530 ((or (and (interactive-p) current-prefix-arg) w3-dump-to-disk)
531 (w3-download-url url))
532 (t
533 (let ((x (url-view-url t))
534 (lastbuf (current-buffer))
535 (buf (url-buffer-visiting url)))
536 (and x (or (string= "file:nil" x) (string= "" x))
537 (setq x nil))
538 (if (or (not buf)
539 (cond
540 ((not (equal (downcase (or url-request-method "GET")) "get")) t)
541 ((memq w3-reuse-buffers '(no never reload)) t)
542 ((memq w3-reuse-buffers '(yes reuse always)) nil)
543 (t
544 (if (and w3-reuse-buffers (not (eq w3-reuse-buffers 'ask)))
545 (progn
546 (ding)
547 (message
548 "Warning: Invalid value for variable w3-reuse-buffers: %s"
549 (prin1-to-string w3-reuse-buffers))
550 (sit-for 2)))
551 (not (funcall url-confirmation-func
552 (format "Reuse URL in buffer %s? "
553 (buffer-name buf)))))))
554 (let ((cached (url-retrieve url)))
555 (if w3-track-last-buffer
556 (setq w3-last-buffer (get-buffer url-working-buffer)))
557 (if (get-buffer url-working-buffer)
558 (cond
559 ((and url-be-asynchronous (string-match "^http:" url)
560 (not cached))
561 (save-excursion
562 (set-buffer url-working-buffer)
563 (if x
564 (w3-add-urls-to-history x (url-view-url t)))
565 (setq w3-current-last-buffer lastbuf)))
566 (t
567 (w3-add-urls-to-history x url)
568 (w3-sentinel lastbuf)))))
569 (if w3-track-last-buffer
570 (setq w3-last-buffer buf))
571 (let ((w3-notify (if (memq w3-notify '(newframe bully aggressive))
572 w3-notify
573 'aggressive)))
574 (w3-notify-when-ready buf))
575 (if (string-match "#\\(.*\\)" url)
576 (progn
577 (push-mark (point) t)
578 (w3-find-specific-link (url-match url 1))))
579 (message "Reusing URL. To reload, type %s."
580 (substitute-command-keys "\\[w3-reload-document]")))))))
581
582
583 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
584 ;;; History for forward/back buttons
585 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
586 (defvar w3-node-history nil "History for forward and backward jumping")
587
588 (defun w3-plot-course ()
589 "Show a map of where the user has been in this session of W3. !!!!NYI!!!"
590 (interactive)
591 (error "Sorry, w3-plot-course is not yet implemented."))
592
593 (defun w3-forward-in-history ()
594 "Go forward in the history from this page"
595 (interactive)
596 (let* ((thisurl (url-view-url t))
597 (node (assoc (if (string= "" thisurl) (current-buffer) thisurl)
598 w3-node-history))
599 (url (cdr node))
600 (w3-reuse-buffers 'yes))
601 (cond
602 ((null url) (error "No forward found for %s" thisurl))
603 ((and (bufferp url) (buffer-name url))
604 (switch-to-buffer url))
605 ((stringp url)
606 (w3-fetch url))
607 ((bufferp url)
608 (setq w3-node-history (delete node w3-node-history))
609 (error "Killed buffer in history, removed."))
610 (t
611 (error "Something is very wrong with the history!")))))
612
613 (defun w3-backward-in-history ()
614 "Go backward in the history from this page"
615 (interactive)
616 (let* ((thisurl (url-view-url t))
617 (node (rassoc (if (string= thisurl "") (current-buffer) thisurl)
618 w3-node-history))
619 (url (car node))
620 (w3-reuse-buffers 'yes))
621 (cond
622 ((null url) (error "No backward found for %s" thisurl))
623 ((and (bufferp url) (buffer-name url))
624 (switch-to-buffer url))
625 ((stringp url)
626 (w3-fetch url))
627 ((bufferp url)
628 (setq w3-node-history (delete node w3-node-history))
629 (error "Killed buffer in history, removed."))
630 (t
631 (error "Something is very wrong with the history!")))))
632
633 (defun w3-add-urls-to-history (referer url)
634 "REFERER is the url we followed this link from. URL is the link we got to."
635 (let ((node (assoc referer w3-node-history)))
636 (if node
637 (setcdr node url)
638 (setq w3-node-history (cons (cons referer url) w3-node-history)))))
639
640
641 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
642 ;;; Miscellaneous functions
643 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
644 (defun w3-describe-entities ()
645 "Show an DTD fragment listing all the entities currently defined."
646 (interactive)
647 (switch-to-buffer (get-buffer-create "W3 Entities"))
648 (let ((buffer-file-name (concat (make-temp-name "entities") ".dtd")))
649 (set-auto-mode))
650 (erase-buffer)
651 (let (entity)
652 (mapatoms
653 (function
654 (lambda (x)
655 (setq entity (get x 'html-entity-expansion))
656 (if entity
657 (insert (format "<!entity %s %s \"%s\">\n" x (car entity)
658 (cdr entity))))))))
659 (goto-char (point-min)))
660
661 (defun w3-executable-exists-in-path (exec &optional path)
662 (let ((paths (if (consp path)
663 path
664 (mm-string-to-tokens (or path
665 (getenv "PATH")
666 (concat
667 "/usr/bin:/bin:/usr/local/bin:"
668 "/usr/bin/X11:"
669 (expand-file-name "~/bin"))) ?:)))
670 (done nil))
671 (while (and paths (not done))
672 (if (file-exists-p (expand-file-name exec (car paths)))
673 (setq done t))
674 (setq paths (cdr paths)))
675 done))
676
677 (defun w3-document-information (&optional buff)
678 "Display information on the document in buffer BUFF"
679 (interactive)
680 (if (interactive-p)
681 (let ((w3-notify 'friendly))
682 (if (get-buffer "Document Information")
683 (kill-buffer (get-buffer "Document Information")))
684 (w3-fetch "about:document"))
685 (setq buff (or buff (current-buffer)))
686 (save-excursion
687 (set-buffer buff)
688 (let* ((url (url-view-url t))
689 (cur-links w3-current-links)
690 (title (buffer-name))
691 (lastmod (or (cdr-safe (assoc "last-modified"
692 url-current-mime-headers))
693 (and (member url-current-type '("file" "ftp"))
694 (nth 5 (url-file-attributes url)))))
695 (hdrs url-current-mime-headers))
696 (set-buffer (get-buffer-create url-working-buffer))
697 (setq url-current-can-be-cached nil
698 url-current-type "about"
699 url-current-file "document")
700 (erase-buffer)
701 (cond
702 ((stringp lastmod) nil)
703 ((equal '(0 . 0) lastmod) (setq lastmod nil))
704 ((consp lastmod) (setq lastmod (current-time-string lastmod)))
705 (t (setq lastmod nil)))
706 (insert "<html>\n"
707 " <head>\n"
708 " <title>Document Information</title>\n"
709 " </head>\n"
710 " <body\n"
711 " <h1 align=\"center\">Document Information</h1>\n"
712 " <hr>\n"
713 " <pre>\n"
714 " Title: " title "\n"
715 " Location: " url "\n"
716 " Last Modified: " (or lastmod "None Given") "\n"
717 " </pre>\n")
718 (if hdrs
719 (let* ((maxlength (car (sort (mapcar (function (lambda (x)
720 (length (car x))))
721 hdrs)
722 '>)))
723 (fmtstring (format "%%%ds: %%s" maxlength)))
724 (insert " <hr label=\" MetaInformation \" textalign=\"left\">\n"
725 " <pre>\n"
726 (mapconcat
727 (function
728 (lambda (x)
729 (if (/= (length (car x)) 0)
730 (format fmtstring
731 (capitalize (car x))
732 (if (numberp (cdr x))
733 (int-to-string (cdr x))
734 (cdr x))))))
735 (sort hdrs
736 (function
737 (lambda (x y) (string-lessp (car x) (car y)))))
738 "\n")
739 " </pre>\n")))
740 (if cur-links
741 (while cur-links
742 (let* ((tmp (car cur-links))
743 (label (car tmp))
744 (nodes (cdr tmp))
745 (links nil)
746 (maxlength (car (sort (mapcar
747 (function (lambda (x)
748 (length (car x))))
749 nodes)
750 '>)))
751 (fmtstring (format "%%%ds: %%s" maxlength)))
752 (insert " \n"
753 " <hr width=\"50%\" label=\" "
754 label " \" align=\"left\" textalign=\"left\">\n"
755 " <pre>\n")
756 (while nodes
757 (setq label (car (car nodes))
758 links (cdr (car nodes))
759 nodes (cdr nodes))
760 (while links
761 (insert (format " %15s -- <a href=\"%s\">%s</a>\n"
762 label (car links) (car links)))
763 (setq links (cdr links)
764 label "")))
765 (insert " </pre>\n"))
766 (setq cur-links (cdr cur-links))))
767 (insert " </body>\n"
768 "</html>\n")))))
769
770 (defun w3-truncate-menu-item (string)
771 (if (<= (length string) w3-max-menu-width)
772 string
773 (concat (substring string 0 w3-max-menu-width) "$")))
774
775 (defun w3-use-starting-documents ()
776 "Use the list of predefined starting documents from w3-starting-documents"
777 (interactive)
778 (let ((w3-hotlist w3-starting-documents))
779 (w3-use-hotlist)))
780
781 (defun w3-show-starting-documents ()
782 "Show the list of predefined starting documents from w3-starting-documents"
783 (interactive)
784 (if (not w3-setup-done) (w3-do-setup))
785 (w3-fetch "www://auto/starting-points"))
786
787 (defun w3-insert-formatted-url (p)
788 "Insert a formatted url into a buffer. With prefix arg, insert the url
789 under point."
790 (interactive "P")
791 (let (buff str)
792 (cond
793 (p
794 (setq p (widget-at (point)))
795 (or p (error "No url under point"))
796 (setq str (format "<A HREF=\"%s\">%s</A>" (widget-get p 'href)
797 (read-string "Link text: "
798 (buffer-substring
799 (car (widget-get p 'title))
800 (cdr (widget-get p 'title)))))))
801 (t
802 (setq str (format "<A HREF=\"%s\">%s</A>" (url-view-url t)
803 (read-string "Link text: " (buffer-name))))))
804 (setq buff (read-buffer "Insert into buffer: " nil t))
805 (if buff
806 (save-excursion
807 (set-buffer buff)
808 (insert str))
809 (message "Cancelled."))))
810
811 (defun w3-first-n-items (l n)
812 "Return the first N items from list L"
813 (let ((x 0)
814 y)
815 (if (> n (length l))
816 (setq y l)
817 (while (< x n)
818 (setq y (nconc y (list (nth x l)))
819 x (1+ x))))
820 y))
821
822 (defun w3-widget-button-press ()
823 (interactive)
824 (if (widget-at (point))
825 (widget-button-press (point))))
826
827 (defun w3-widget-button-click (e)
828 (interactive "@e")
829 (if (widget-at (event-point e))
830 (widget-button-click e)))
831
832 (defun w3-breakup-menu (menu-desc max-len)
833 (if (> (length menu-desc) max-len)
834 (cons (cons "More..." (w3-first-n-items menu-desc max-len))
835 (w3-breakup-menu (nthcdr max-len menu-desc) max-len))
836 menu-desc))
837
838 ;;;###autoload
839 (defun w3-maybe-follow-link-mouse (e)
840 "Maybe follow a hypertext link under point.
841 If there is no link under point, this will try using
842 url-get-url-at-point"
843 (interactive "e")
844 (save-excursion
845 (mouse-set-point e)
846 (w3-maybe-follow-link)))
847
848 ;;;###autoload
849 (defun w3-maybe-follow-link ()
850 "Maybe follow a hypertext link under point.
851 If there is no link under point, this will try using
852 url-get-url-at-point"
853 (interactive)
854 (require 'w3)
855 (if (not w3-setup-done) (w3-do-setup))
856 (let* ((widget (widget-at (point)))
857 (url1 (and widget (widget-get widget 'href)))
858 (url2 (url-get-url-at-point)))
859 (cond
860 (url1 (w3-follow-link))
861 ((and url2 (string-match url-nonrelative-link url2)) (w3-fetch url2))
862 (t (message "No URL could be found!")))))
863
864 ;;;###autoload
865 (defun w3-follow-url-at-point-other-frame (&optional pt)
866 "Follow the URL under PT, defaults to link under (point)"
867 (interactive "d")
868 (let ((url (url-get-url-at-point pt)))
869 (and url (w3-fetch-other-frame url))))
870
871 ;;;###autoload
872 (defun w3-follow-url-at-point (&optional pt)
873 "Follow the URL under PT, defaults to link under (point)"
874 (interactive "d")
875 (let ((url (url-get-url-at-point pt)))
876 (and url (w3-fetch url))))
877
878 ;;;###autoload
879 (defun w3-batch-fetch ()
880 "Fetch all the URLs on the command line and save them to files in
881 the current directory. The first argument after the -f w3-batch-fetch
882 on the command line should be a string specifying how to save the
883 information retrieved. If it is \"html\", then the page will be
884 unformatted when it is written to disk. If it is \"text\", then the
885 page will be formatted before it is written to disk. If it is
886 \"binary\" it will not mess with the file extensions, and just save
887 the data in raw binary format. If none of those, the default is
888 \"text\", and the first argument is treated as a normal URL."
889 (if (not w3-setup-done) (w3-do-setup))
890 (if (not noninteractive)
891 (error "`w3-batch-fetch' is to be used only with -batch"))
892 (let ((fname "")
893 (curname "")
894 (x 0)
895 (args command-line-args-left)
896 (w3-strict-width 80)
897 (w3-delimit-emphasis nil)
898 (w3-delimit-links nil)
899 (retrieval-function 'w3-fetch)
900 (file-format "text")
901 (header "")
902 (file-extn ".txt"))
903 (setq file-format (downcase (car args)))
904 (cond
905 ((string= file-format "html")
906 (message "Saving all text as raw HTML...")
907 (setq retrieval-function 'url-retrieve
908 file-extn ".html"
909 header "<BASE HREF=\"%s\">"
910 args (cdr args)))
911 ((string= file-format "binary")
912 (message "Saving as raw binary...")
913 (setq retrieval-function 'url-retrieve
914 file-extn ""
915 args (cdr args)))
916 ((string= file-format "text")
917 (setq header "Text from: %s\n---------------\n")
918 (message "Saving all text as formatted...")
919 (setq args (cdr args)))
920 (t
921 (setq header "Text from: %s\n---------------\n")
922 (message "Going with default, saving all text as formatted...")))
923 (while args
924 (funcall retrieval-function (car args))
925 (goto-char (point-min))
926 (if buffer-read-only (toggle-read-only))
927 (insert (format header (car args)))
928 (setq fname (url-basepath url-current-file t))
929 (if (string= file-extn "") nil
930 (setq fname (url-file-extension fname t)))
931 (if (string= (url-strip-leading-spaces fname) "")
932 (setq fname "root"))
933 (setq curname fname)
934 (while (file-exists-p (concat curname file-extn))
935 (setq curname (concat fname x)
936 x (1+ x)))
937 (setq fname (concat curname file-extn))
938 (write-region (point-min) (point-max) fname)
939 (setq args (cdr args)))))
940
941 (defun w3-fix-spaces (x)
942 "Remove spaces/tabs at the beginning of a string,
943 and convert newlines into spaces."
944 (url-convert-newlines-to-spaces
945 (url-strip-leading-spaces
946 (url-eat-trailing-space x))))
947
948 (defun w3-reload-all-files ()
949 "Reload all w3 files"
950 (interactive)
951 (setq w3-setup-done nil
952 url-setup-done nil
953 w3-hotlist nil
954 url-mime-accept-string nil)
955 (let ((x '(w3 w3-mule w3-e19 w3-xem20 mm url w3-xemac w3-toolbar font)))
956 (while x
957 (setq features (delq (car x) features)
958 x (cdr x)))
959 (require 'w3))
960 (w3-do-setup)
961 (url-do-setup)
962 )
963
964 (defun w3-source-document-at-point ()
965 "View source to the document pointed at by link under point"
966 (interactive)
967 (w3-source-document t))
968
969 (defun w3-my-safe-copy-face (old new locale)
970 (let ((fore (face-foreground old))
971 (back (face-background old))
972 (bpxm (face-background-pixmap old))
973 (font (face-font old))
974 (font-spec (get old 'font-specification)))
975 (if (color-specifier-p fore)
976 (setq fore (color-name fore)))
977 (if (color-specifier-p back)
978 (setq back (color-name back)))
979 (if (font-specifier-p font)
980 (setq font (font-name font)))
981 (and fore (set-face-foreground new fore locale))
982 (and back (set-face-background new back locale))
983 (and bpxm (set-face-background-pixmap new bpxm locale))
984 (and (or font-spec font) (set-face-font new (or font-spec font) locale))
985 new))
986
987 (defun w3-source-document (under)
988 "View this document's source"
989 (interactive "P")
990 (let* ((url (if under (w3-view-this-url) (url-view-url t)))
991 (fil (if under nil url-current-file))
992 (tag '$html-source) ; For the stylesheet info
993 (args nil) ; For the stylesheet info
994 (face nil) ; For the stylesheet info
995 (src
996 (cond
997 ((or (null url) (string= url "file:nil"))
998 (error "Not a w3 buffer!"))
999 ((and under (null url)) (error "No link at point!"))
1000 ((and (not under) (equal url-current-mime-type "text/plain"))
1001 (buffer-string))
1002 ((and (not under) w3-current-source) w3-current-source)
1003 (t
1004 (prog2
1005 (url-retrieve url)
1006 (buffer-string)
1007 (setq fil (or fil url-current-file))
1008 (kill-buffer (current-buffer))))))
1009 (tmp (url-generate-new-buffer-name url)))
1010 (if (and url (get-buffer url))
1011 (cond
1012 ((memq w3-reuse-buffers '(no never reload))
1013 (kill-buffer url))
1014 ((memq w3-reuse-buffers '(yes reuse always))
1015 (w3-notify-when-ready (get-buffer url))
1016 (setq url nil))
1017 ((funcall url-confirmation-func
1018 (concat "Source for " url " found, reuse? "))
1019 (w3-notify-when-ready (get-buffer url)))))
1020 (if (not url) nil
1021 (setq face (and w3-current-stylesheet (cdr (w3-face-for-element))))
1022 (set-buffer (get-buffer-create tmp))
1023 (insert src)
1024 (put-text-property (point-min) (point-max) 'face face)
1025 (put-text-property (point-min) (point-max) 'w3-base url)
1026 (goto-char (point-min))
1027 (setq buffer-file-truename nil
1028 buffer-file-name nil)
1029 ;; Null filename bugs `set-auto-mode' in Mule ...
1030 (if (not (featurep 'mule))
1031 (set-auto-mode))
1032 (buffer-enable-undo)
1033 (set-buffer-modified-p nil)
1034 (w3-notify-when-ready (get-buffer tmp))))
1035 (run-hooks 'w3-source-file-hook))
1036
1037 (defun w3-mail-document-under-point ()
1038 "Mail the document pointed to by the hyperlink under point."
1039 (interactive)
1040 (w3-mail-current-document t))
1041
1042 (defun w3-mail-current-document (under &optional format)
1043 "Mail the current-document to someone"
1044 (interactive "P")
1045 (let* ((completion-ignore-case t)
1046 (format (or format
1047 (completing-read
1048 "Format: "
1049 '(("HTML Source")
1050 ("Formatted Text")
1051 ("PostScript")
1052 ("LaTeX Source")
1053 )
1054 nil t)))
1055 (url (cond
1056 ((stringp under) under)
1057 (under (w3-view-this-url t))
1058 (t (url-view-url t))))
1059 (content-type "text/plain; charset=iso-8859-1")
1060 (str
1061 (save-excursion
1062 (cond
1063 ((and (equal "HTML Source" format) under)
1064 (setq content-type "text/html; charset=iso-8859-1")
1065 (let ((url-source t))
1066 (url-retrieve url)))
1067 ((equal "HTML Source" format)
1068 (setq content-type "text/html; charset=iso-8859-1")
1069 (if w3-current-source
1070 (let ((x w3-current-source))
1071 (set-buffer (get-buffer-create url-working-buffer))
1072 (erase-buffer)
1073 (insert x))
1074 (url-retrieve url)))
1075 ((and under (equal "PostScript" format))
1076 (setq content-type "application/postscript")
1077 (w3-fetch url)
1078 (let ((ps-spool-buffer-name " *w3-temp*"))
1079 (if (get-buffer ps-spool-buffer-name)
1080 (kill-buffer ps-spool-buffer-name))
1081 (w3-print-with-ps-print (current-buffer)
1082 'ps-spool-buffer-with-faces)
1083 (set-buffer ps-spool-buffer-name)))
1084 ((equal "PostScript" format)
1085 (let ((ps-spool-buffer-name " *w3-temp*"))
1086 (if (get-buffer ps-spool-buffer-name)
1087 (kill-buffer ps-spool-buffer-name))
1088 (setq content-type "application/postscript")
1089 (w3-print-with-ps-print (current-buffer)
1090 'ps-spool-buffer-with-faces)
1091 (set-buffer ps-spool-buffer-name)))
1092 ((and under (equal "Formatted Text" format))
1093 (setq content-type "text/plain; charset=iso-8859-1")
1094 (w3-fetch url))
1095 ((equal "Formatted Text" format)
1096 (setq content-type "text/plain; charset=iso-8859-1"))
1097 ((and under (equal "LaTeX Source" format))
1098 (let ((old-asynch url-be-asynchronous))
1099 (setq content-type "application/x-latex; charset=iso-8859-1")
1100 (setq-default url-be-asynchronous nil)
1101 (url-retrieve url)
1102 (setq-default url-be-asynchronous old-asynch)
1103 (w3-parse-tree-to-latex (w3-parse-buffer (current-buffer) t)
1104 url)))
1105 ((equal "LaTeX Source" format)
1106 (setq content-type "application/x-latex; charset=iso-8859-1")
1107 (w3-parse-tree-to-latex w3-current-parse url)))
1108 (buffer-string))))
1109 (cond
1110 ((and w3-mutable-windows (fboundp w3-mail-other-window-command))
1111 (funcall w3-mail-other-window-command))
1112 ((fboundp w3-mail-command)
1113 (funcall w3-mail-command))
1114 (w3-mutable-windows (mail-other-window))
1115 (t (mail)))
1116 (mail-subject)
1117 (insert format " from URL " url "\n"
1118 "Mime-Version: 1.0\n"
1119 "Content-transfer-encoding: 8bit\n"
1120 "Content-type: " content-type)
1121
1122 (re-search-forward mail-header-separator nil)
1123 (forward-char 1)
1124 (insert (if (equal "HTML Source" format)
1125 (format "<BASE HREF=\"%s\">" url) "")
1126 str)
1127 (mail-to)))
1128
1129 (defun w3-internal-use-history (hist-item)
1130 ;; Go to the link in the history
1131 (let ((url (nth 0 hist-item))
1132 (buf (nth 1 hist-item))
1133 (pnt (nth 2 hist-item)))
1134 (cond
1135 ((null buf) ; Find a buffer with same url
1136 (let ((x (buffer-list))
1137 (found nil))
1138 (while (and x (not found))
1139 (save-excursion
1140 (set-buffer (car x))
1141 (setq found (string= (url-view-url t) url))
1142 (if (not found) (setq x (cdr x)))))
1143 (cond
1144 (found
1145 (switch-to-buffer (car x))
1146 (if (number-or-marker-p pnt) (goto-char pnt)))
1147 (t
1148 (w3-fetch url)))))
1149 ((buffer-name buf) ; Reuse the old buffer if possible
1150 (switch-to-buffer buf)
1151 (if (number-or-marker-p pnt) (goto-char pnt))
1152 (if (and url (= ?# (string-to-char url))) ; Destination link
1153 (progn
1154 (goto-char (point-min))
1155 (w3-find-specific-link (substring url 1 nil)))))
1156 (url (url-maybe-relative url)) ; Get the link
1157 (t (message "Couldn't understand whats in the history.")))))
1158
1159 (defun w3-relative-link (url)
1160 (if (equal "#" (substring url 0 1))
1161 (progn
1162 (push-mark (point) t)
1163 (goto-char (point-min))
1164 (w3-find-specific-link (substring url 1 nil)))
1165 (w3-fetch (url-expand-file-name url))))
1166
1167 (defun w3-maybe-eval ()
1168 ;; Maybe evaluate a buffer of emacs lisp code
1169 (if (funcall url-confirmation-func "This is emacs-lisp code, evaluate it?")
1170 (eval-buffer (current-buffer))
1171 (emacs-lisp-mode)))
1172
1173 (defun w3-build-continuation ()
1174 ;; Build a series of functions to be run on this file
1175 (save-excursion
1176 (set-buffer url-working-buffer)
1177 (let ((cont w3-default-continuation)
1178 (extn (url-file-extension url-current-file)))
1179 (if (assoc extn url-uncompressor-alist)
1180 (setq extn (url-file-extension
1181 (substring url-current-file 0 (- (length extn))))))
1182 (if w3-source
1183 (setq url-current-mime-viewer '(("viewer" . w3-source))))
1184 (if (not url-current-mime-viewer)
1185 (setq url-current-mime-viewer
1186 (mm-mime-info (or url-current-mime-type
1187 (mm-extension-to-mime extn)) nil 5)))
1188 (if url-current-mime-viewer
1189 (setq cont (append cont '(w3-pass-to-viewer)))
1190 (setq cont (append cont (list w3-default-action))))
1191 cont)))
1192
1193 (defun w3-use-links ()
1194 "Select one of the <LINK> tags from this document and fetch it."
1195 (interactive)
1196 (and (not w3-current-links)
1197 (error "No links defined for this document."))
1198 (w3-fetch "about:document"))
1199
1200 (defun w3-find-this-file ()
1201 "Do a find-file on the currently viewed html document if it is a file: or
1202 ftp: reference"
1203 (interactive)
1204 (cond
1205 ((and (or (null url-current-type) (equal url-current-type "file"))
1206 (eq major-mode 'w3-mode))
1207 (if w3-mutable-windows
1208 (find-file-other-window url-current-file)
1209 (find-file url-current-file)))
1210 ((equal url-current-type "ftp")
1211 (if w3-mutable-windows
1212 (find-file-other-window
1213 (format "/%s@%s:%s" url-current-user url-current-server
1214 url-current-file))
1215 (find-file
1216 (format "/%s@%s:%s" url-current-user url-current-server
1217 url-current-file))))
1218 (t (message "Sorry, I can't get that file so you can alter it."))))
1219
1220 (defun w3-insert-this-url (pref-arg)
1221 "Insert the current url in another buffer, with prefix ARG,
1222 insert URL under point"
1223 (interactive "P")
1224 (let ((thebuf (get-buffer (read-buffer "Insert into buffer: ")))
1225 (oldbuf (current-buffer))
1226 (url (if pref-arg (w3-view-this-url t) (url-view-url t))))
1227 (if (and url (not (equal "Not on a link!" url)))
1228 (progn
1229 (set-buffer thebuf)
1230 (insert url)
1231 (set-buffer oldbuf))
1232 (message "Not on a link!"))))
1233
1234 (defun w3-show-hotlist ()
1235 "View the hotlist in hypertext form"
1236 (interactive)
1237 (if (not w3-setup-done) (w3-do-setup))
1238 (if (not w3-hotlist)
1239 (error "Sorry, no hotlist is in memory.")
1240 (let ((x (url-buffer-visiting "www:/auto/hotlist")))
1241 (while x
1242 (kill-buffer x)
1243 (setq x (url-buffer-visiting "www:/auto/hotlist"))))
1244 (w3-fetch "www://auto/hotlist")))
1245
1246 (defun url-maybe-relative (url)
1247 "Take a url and either fetch it, or resolve relative refs, then fetch it"
1248 (cond
1249 ((not
1250 (string-match url-nonrelative-link url))
1251 (w3-relative-link url))
1252 (t (w3-fetch url))))
1253
1254 (defun w3-in-assoc (elt list)
1255 "Check to see if ELT matches any of the regexps in the car elements of LIST"
1256 (let (rslt)
1257 (while (and list (not rslt))
1258 (and (car (car list))
1259 (stringp (car (car list)))
1260 (not (string= (car (car list)) ""))
1261 (string-match (car (car list)) elt)
1262 (setq rslt (car list)))
1263 (setq list (cdr list)))
1264 rslt))
1265
1266 (defun w3-goto-last-buffer ()
1267 "Go to last WWW buffer visited"
1268 (interactive)
1269 (if w3-current-last-buffer
1270 (w3-notify-when-ready w3-current-last-buffer)
1271 (message "No previous buffer found.")))
1272
1273 (fset 'w3-replace-regexp 'url-replace-regexp)
1274
1275 ;;;###autoload
1276 (defun w3-preview-this-buffer ()
1277 "See what this buffer will look like when its formatted as HTML.
1278 HTML is the HyperText Markup Language used by the World Wide Web to
1279 specify formatting for text. More information on HTML can be found at
1280 ftp.w3.org:/pub/www/doc."
1281 (interactive)
1282 (w3-fetch (concat "www://preview/" (buffer-name))))
1283
1284 (defun w3-edit-source ()
1285 "Edit the html document just retrieved"
1286 (set-buffer url-working-buffer)
1287 (let ((ttl (format "Editing %s Annotation: %s"
1288 (cond
1289 ((eq w3-editing-annotation 'group) "Group")
1290 ((eq w3-editing-annotation 'personal) "Personal")
1291 (t "Unknown"))
1292 (url-basepath url-current-file t)))
1293 (str (buffer-string)))
1294 (set-buffer (get-buffer-create ttl))
1295 (insert str)
1296 (kill-buffer url-working-buffer)))
1297
1298 (defun w3-source ()
1299 "Show the source of a file"
1300 (let ((tmp (buffer-name (generate-new-buffer "Document Source"))))
1301 (set-buffer url-working-buffer)
1302 (kill-buffer tmp)
1303 (rename-buffer tmp)
1304 ;; Make the URL show in list-buffers output
1305 (make-local-variable 'list-buffers-directory)
1306 (setq list-buffers-directory (url-view-url t))
1307 (set-buffer-modified-p nil)
1308 (buffer-enable-undo)
1309 (w3-notify-when-ready (get-buffer tmp))))
1310
1311 (defun w3-sentinel (&optional proc string)
1312 (set-buffer url-working-buffer)
1313 (if (or (stringp proc)
1314 (bufferp proc)) (setq w3-current-last-buffer proc))
1315 (if (boundp 'after-change-functions)
1316 (remove-hook 'after-change-functions 'url-after-change-function))
1317 (if url-be-asynchronous
1318 (progn
1319 (url-clean-text)
1320 (cond
1321 ((not (get-buffer url-working-buffer)) nil)
1322 ((url-mime-response-p) (url-parse-mime-headers)))
1323 (if (not url-current-mime-type)
1324 (setq url-current-mime-type (or (mm-extension-to-mime
1325 (url-file-extension
1326 url-current-file))
1327 "text/html")))))
1328 (let ((x (w3-build-continuation))
1329 (done-mule-conversion nil))
1330 (while x
1331 (if (and (featurep 'mule) (not (eq 'url-uncompress (car x)))
1332 (not done-mule-conversion))
1333 (progn
1334 (if (string-match "^www:" (url-view-url t))
1335 (setq w3-mime-list-for-code-conversion nil))
1336 (w3-convert-code-for-mule url-current-mime-type)
1337 (setq done-mule-conversion t)))
1338 (funcall (car x))
1339 (setq x (cdr x)))))
1340
1341 (defun w3-show-history-list ()
1342 "Format the url-history-list prettily and show it to the user"
1343 (interactive)
1344 (w3-fetch "www://auto/history"))
1345
1346 (defun w3-save-as (&optional type)
1347 "Save a document to the local disk"
1348 (interactive)
1349 (let* ((completion-ignore-case t)
1350 (format (or type (completing-read
1351 "Format: "
1352 '(("HTML Source") ("Formatted Text")
1353 ("LaTeX Source") ("Binary"))
1354 nil t)))
1355 (fname (expand-file-name
1356 (read-file-name "File name: " default-directory)))
1357 (url (url-view-url t)))
1358 (cond
1359 ((equal "Binary" format)
1360 (if (not w3-current-source)
1361 (let ((url-be-asynchronous nil))
1362 (url-retrieve url))))
1363 ((equal "HTML Source" format)
1364 (if (not w3-current-source)
1365 (let ((url-be-asynchronous nil))
1366 (url-retrieve url)) ; Get the document if necessary
1367 (let ((txt w3-current-source))
1368 (set-buffer (get-buffer-create url-working-buffer))
1369 (insert txt)))
1370 (goto-char (point-min))
1371 (insert (format "<BASE HREF=\"%s\">\n" url)))
1372 ((or (equal "Formatted Text" format)
1373 (equal "" format))
1374 nil) ; Do nothing - we have the text already
1375 ((equal "LaTeX Source" format)
1376 (w3-parse-tree-to-latex w3-current-parse url)
1377 (insert-buffer url-working-buffer)))
1378 (write-region (point-min) (point-max) fname)))
1379
1380
1381 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1382 ;;; Functions to parse out <A> tags and replace it with a hyperlink zone
1383 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1384 (defun w3-popup-image-info (url)
1385 (interactive)
1386 (let* ((glyph (cdr-safe (assoc url w3-graphics-list)))
1387 image w h d info)
1388 (save-excursion
1389 (if (or (not glyph) (not (glyphp glyph)))
1390 (error "No information available."))
1391 (setq image (glyph-image-instance glyph))
1392 (if (or (not image) (not (image-instance-p image)))
1393 (error "No information available."))
1394 (setq w (glyph-width glyph)
1395 h (glyph-height glyph)
1396 d (image-instance-depth image)
1397 info (url-popup-info url)
1398 )
1399 (set-buffer (get-buffer-create "*Image Info*"))
1400 (erase-buffer)
1401 (insert
1402 "Information for: " url "\n"
1403 (make-string (1- (window-width)) ?-)
1404 (format "\n%-20s: %s\n" "Type" (image-instance-type image))
1405 (format "%-20s: %d x %d\n" "Dimensions" w h)
1406 (format "%-20s: %d-bit\n" "Color" d))
1407 (set-extent-begin-glyph (make-extent (point) (point)) glyph)
1408 (insert
1409 "\n"
1410 (make-string (1- (window-width)) ?-)
1411 (or info ""))
1412 (display-buffer (current-buffer) t))))
1413
1414 (defun w3-popup-info (&optional url)
1415 "Show information about the link under point. (All SGML attributes)"
1416 (interactive (list (w3-read-url-with-default)))
1417 (let (dat widget)
1418 (if (interactive-p)
1419 nil
1420 (setq widget (widget-at (point))
1421 dat (and widget (widget-get widget 'attributes))))
1422 (if url
1423 (save-excursion
1424 (set-buffer (get-buffer-create "*Header Info*"))
1425 (erase-buffer)
1426 (insert "URL: " url "\n" (make-string (1- (window-width)) ?-) "\n")
1427 (if (and dat (listp dat))
1428 (insert
1429 "Link attributes:\n"
1430 (make-string (1- (window-width)) ?-) "\n"
1431 (mapconcat
1432 (function
1433 (lambda (info)
1434 (format "%20s :== %s" (car info) (or (cdr info) "On"))))
1435 dat "\n")
1436 "\n" (make-string (1- (window-width)) ?-) "\n"))
1437 (insert (save-excursion (url-popup-info url)))
1438 (goto-char (point-min))
1439 (display-buffer (current-buffer) t))
1440 (message "No URL to get information on!"))))
1441
1442 (fset 'w3-document-information-this-url 'w3-popup-info)
1443
1444
1445 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1446 ;;; Functions for logging of bad HTML
1447 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1448 (defun w3-reconstruct-tag (tagname desc)
1449 (concat "<" tagname " "
1450 (mapconcat
1451 (function (lambda (x)
1452 (if (cdr x)
1453 (concat (car x) "=\"" (cdr x) "\"")
1454 (car x)))) desc " ") ">"))
1455
1456 (defun w3-debug-if-found (regexp type desc)
1457 (and w3-debug-html
1458 (save-excursion
1459 (if (re-search-forward regexp nil t)
1460 (w3-log-bad-html type desc)))))
1461
1462 (defun w3-log-bad-html (type desc)
1463 ;; Log bad HTML to the buffer specified by w3-debug-buffer
1464 (if w3-debug-html
1465 (save-excursion
1466 (set-buffer (get-buffer-create w3-debug-buffer))
1467 (goto-char (point-max))
1468 (insert (make-string (1- (window-width)) w3-horizontal-rule-char) "\n")
1469 (cond
1470 ((stringp type) (insert type "\n" desc "\n"))
1471 ((eq type 'bad-quote)
1472 (insert "Unterminated quoting character in SGML attribute value.\n"
1473 desc "\n"))
1474 ((eq type 'no-quote)
1475 (insert "Unquoted SGML attribute value.\n" desc "\n"))
1476 ((eq type 'no-textarea-end)
1477 (insert "Unterminated <textarea> tag.\n"
1478 (w3-reconstruct-tag "textarea" desc) "\n"))
1479 ((eq type 'bad-link-tag)
1480 (insert "Must specify either REL or REV with a <link> tag.\n"
1481 (w3-reconstruct-tag "link" desc) "\n"))
1482 ((eq type 'no-a-end)
1483 (insert "Unterminated <a> tag.\n"
1484 (w3-reconstruct-tag "a" desc) "\n"))
1485 ((eq type 'no-form-end)
1486 (insert "Unterminated <form> tag.\n"
1487 (w3-reconstruct-tag "form" desc) "\n"))
1488 ((eq type 'bad-base-tag)
1489 (insert "Malformed <base> tag.\n"
1490 (w3-reconstruct-tag "base" desc) "\n"))))))
1491
1492
1493 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1494 ;;; Functions to handle formatting an html buffer
1495 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1496 (defun w3-insert-entities-in-string (string)
1497 "Convert HTML markup-start characters to entity references in STRING.
1498 Also replaces the \" character, so that the result may be safely used as
1499 an attribute value in a tag. Returns a new string with the result of the
1500 conversion. Replaces these characters as follows:
1501 & ==> &amp;
1502 < ==> &lt;
1503 > ==> &gt;
1504 \" ==> &quot;"
1505 (if (string-match "[&<>\"]" string)
1506 (save-excursion
1507 (set-buffer (get-buffer-create " *entity*"))
1508 (erase-buffer)
1509 (buffer-disable-undo (current-buffer))
1510 (insert string)
1511 (goto-char (point-min))
1512 (while (progn
1513 (skip-chars-forward "^&<>\"")
1514 (not (eobp)))
1515 (insert (cdr (assq (char-after (point))
1516 '((?\" . "&quot;")
1517 (?& . "&amp;")
1518 (?< . "&lt;")
1519 (?> . "&gt;")))))
1520 (delete-char 1))
1521 (buffer-string))
1522 string))
1523
1524 (defun w3-insert-headers ()
1525 ;; Insert some HTTP/1.0 headers if necessary
1526 (url-lazy-message "Inserting HTTP/1.0 headers...")
1527 (let ((hdrs (if (eq t w3-show-headers) (mapcar 'car url-current-mime-headers)
1528 w3-show-headers))
1529 x y)
1530 (goto-char (setq y (point-max)))
1531 (while hdrs
1532 (if (setq x (w3-in-assoc (car hdrs) url-current-mime-headers))
1533 (insert "<LI> <B>" (car x) "</B>: " (w3-insert-entities-in-string
1534 (if (numberp (cdr x))
1535 (int-to-string (cdr x))
1536 (cdr x)))))
1537 (setq hdrs (cdr hdrs)))
1538 (if (= y (point-max))
1539 nil
1540 (insert "</UL>")
1541 (goto-char y)
1542 (url-lazy-message "Inserting HTTP/1.0 headers... done.")
1543 (insert "<HR><UL>"))))
1544
1545 (defun w3-add-delayed-mpeg (src st &optional width height)
1546 ;; Add a delayed mpeg for the current buffer.
1547 (setq w3-delayed-movies (cons (list src
1548 (set-marker (make-marker) st)
1549 width height)
1550 w3-delayed-movies))
1551 (w3-handle-text (concat "[MPEG(" (url-basepath src t) ")]"))
1552 (put-text-property st (point) 'w3mpeg (list 'w3mpeg src st)))
1553
1554 (defun w3-add-delayed-graphic (src st align alt args)
1555 ;; Add a delayed image for the current buffer.
1556 (setq st (set-marker (make-marker) st)
1557 w3-delayed-images (cons (list src st align alt args)
1558 w3-delayed-images))
1559 (w3-handle-text alt)
1560 (if (string= alt "") nil
1561 (put-text-property st (point) 'w3delayed t)))
1562
1563
1564 (defun w3-load-flavors ()
1565 ;; Load the correct zone/font info for each flavor of emacs
1566 (cond
1567 ((and w3-running-xemacs (eq system-type 'ms-windows))
1568 (error "WinEmacs no longer supported."))
1569 (w3-running-xemacs (require 'w3-xemac))
1570 (w3-running-FSF19 (require 'w3-e19))
1571 (t
1572 (error "Unable to determine the capabilities of this emacs.")))
1573 (cond
1574 ((boundp 'MULE)
1575 (require 'w3-mule))
1576 ((featurep 'mule)
1577 (require 'w3-xem20)
1578 ))
1579 (condition-case ()
1580 (require 'w3-site-init)
1581 (error nil)))
1582
1583 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1584 ;;; Automatic bug submission. ;;;
1585 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1586 (defun w3-submit-bug ()
1587 "Submit a bug on Emacs-w3"
1588 (interactive)
1589 (require 'reporter)
1590 (and (yes-or-no-p "Do you really want to submit a bug on Emacs-w3? ")
1591 (let ((url (url-view-url t))
1592 (vars '(window-system
1593 window-system-version
1594 system-type
1595 ange-ftp-version
1596 url-gateway-method
1597 efs-version
1598 ange-ftp-version
1599 url-version
1600 url-be-asynchronous
1601 url)))
1602 (if (and url (string= url "file:nil")) (setq url nil))
1603 (mapcar
1604 (function
1605 (lambda (x)
1606 (if (not (and (boundp x) (symbol-value x)))
1607 (setq vars (delq x vars))))) vars)
1608 (reporter-submit-bug-report w3-bug-address
1609 (concat "WWW v" w3-version-number " of "
1610 w3-version-date)
1611 vars
1612 nil nil
1613 "Description of Problem:"))))
1614
1615 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1616 ;;; Support for searching ;;;
1617 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1618 (defun w3-nuke-spaces-in-search (x)
1619 "Remove spaces from search strings . . ."
1620 (let ((new ""))
1621 (while (not (equal x ""))
1622 (setq new (concat new (if (= (string-to-char x) 32) "+"
1623 (substring x 0 1)))
1624 x (substring x 1 nil)))
1625 new))
1626
1627 (defun w3-search ()
1628 "Perform a search, if this is a searchable index."
1629 (interactive)
1630 (or w3-current-isindex
1631 (error "Not a searchable index (via <isindex>)"))
1632 (let* (querystring ; The string to send to the server
1633 (data
1634 (cond
1635 ((null w3-current-isindex)
1636 (let ((rels (mapcar
1637 (function
1638 (lambda (data)
1639 (if (assoc "rel" data) data)))
1640 w3-current-links))
1641 val)
1642 (while rels
1643 (if (string-match "useindex"
1644 (or (cdr (assoc "rel" (car rels))) ""))
1645 (setq val (cdr (assoc "href" (car rels)))
1646 rels nil))
1647 (setq rels (cdr rels)))
1648 (cons val "Search on (+ separates keywords): ")))
1649 ((eq w3-current-isindex t)
1650 (cons (url-view-url t) "Search on (+ separates keywords): "))
1651 ((consp w3-current-isindex)
1652 w3-current-isindex)
1653 (t nil)))
1654 index)
1655 (if (null data) (error "Not a searchable index!"))
1656 (setq index (car data))
1657 (setq querystring (w3-nuke-spaces-in-search (read-string (cdr data))))
1658 (if (string-match "\\(.*\\)\\?.*" index)
1659 (setq index (url-match index 1)))
1660 (w3-fetch
1661 (concat index (if (= ?? (string-to-char (substring index -1 nil)))
1662 "" "?") querystring))))
1663
1664 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1665 ;;; Auto documentation, etc ;;;
1666 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1667 (defun w3-help ()
1668 "Print documentation on w3 mode."
1669 (interactive)
1670 (w3-fetch "about:"))
1671
1672 (defun w3-version (&optional here)
1673 "Show the version number of W3 in the minibuffer.
1674 If optional argument HERE is non-nil, insert info at point."
1675 (interactive "P")
1676 (let ((version-string
1677 (format "WWW %s, URL %s, MM %s"
1678 w3-version-number
1679 url-version
1680 mm-version)))
1681 (if here
1682 (insert version-string)
1683 (if (interactive-p)
1684 (message "%s" version-string)
1685 version-string))))
1686
1687 ;;;###autoload
1688 (defun w3 ()
1689 "Retrieve the default World Wide Web home page.
1690 The World Wide Web is a global hypertext system started by CERN in
1691 Switzerland in 1991.
1692
1693 The home page is specified by the variable w3-default-homepage. The
1694 document should be specified by its fully specified Uniform Resource
1695 Locator. The document will be parsed as HTML (if appropriate) and
1696 displayed in a new buffer."
1697 (interactive)
1698 (if (not w3-setup-done) (w3-do-setup))
1699 (if (and w3-track-last-buffer
1700 (bufferp w3-last-buffer)
1701 (buffer-name w3-last-buffer))
1702 (progn
1703 (switch-to-buffer w3-last-buffer)
1704 (message "Reusing buffer. To reload, type %s."
1705 (substitute-command-keys "\\[w3-reload-document]")))
1706 (cond
1707 ((null w3-default-homepage) (call-interactively 'w3-fetch))
1708 ((not (stringp w3-default-homepage))
1709 (error "Invalid setting for w3-default-homepage: %S"
1710 w3-default-homepage))
1711 ((not (string-match ".*:.*" w3-default-homepage))
1712 (w3-fetch (concat "file:" w3-default-homepage)))
1713 (t
1714 (w3-fetch w3-default-homepage)))))
1715
1716 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1717 ;;; Leftover stuff that didn't quite fit into url.el
1718 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1719
1720 (defun w3-generate-error (type data)
1721 ;; Generate an HTML error buffer for error TYPE with data DATA.
1722 (cond
1723 ((equal type "nofile")
1724 (let ((error (save-excursion
1725 (set-buffer (get-buffer-create " *url-error*"))
1726 (buffer-string))))
1727 (if (string= "" error)
1728 (setq error
1729 (format (concat "The file %s could not be found. "
1730 "Either it does not exist, or it "
1731 "is unreadable.") data)))
1732 (insert "<html>\n <head>\n"
1733 " <title>Error</title>\n"
1734 " </head>\n <body>\n"
1735 " <h1>Error accessing " data "</h1>\n"
1736 " <hr>\n <p>"
1737 error
1738 "\n </p>\n")))
1739 ((equal type "nobuf")
1740 (insert "<title>Error</title>\n"
1741 "<H1>No buffer " data " found</h1>\n"
1742 "<HR>\n"
1743 "The buffer " data " could not be found. It has either\n"
1744 "been killed or renamed.\n"))
1745 ((equal type "nohist")
1746 (insert "<TITLE>Error</TITLE>\n"
1747 "<H1>No history items found.</H1>\n"
1748 "<HR>\n"
1749 "There is no history list available at this time. Either\n"
1750 "you have not visited any nodes, or the variable <i>\n"
1751 "url-keep-history</i> is nil.\n"))
1752 )
1753 (insert "<hr>\n"
1754 "If you feel this is a bug in Emacs-W3, <a href=\"mailto:"
1755 w3-bug-address "\">send mail to " w3-bug-address
1756 "</a>\n<hr>"))
1757
1758 (defun w3-generate-auto-html (type)
1759 ;; Generate one of several automatic html pages
1760 (setq url-current-mime-type "text/html"
1761 url-current-mime-headers '(("content-type" . "text/html")))
1762 (cond
1763 ((equal type "hotlist")
1764 (let ((tmp (reverse w3-hotlist)))
1765 (insert "<html>\n\t<head>\n\t\t"
1766 "<title> Hotlist </title>\n\t</head>\n"
1767 "\t<body>\n\t\t<div>\n\t\t\t<h1>Hotlist from " w3-hotlist-file
1768 "</h1>\n\t\t\t<ol>\n")
1769 (while tmp
1770 (insert "\t\t\t\t<li> <a href=\"" (car (cdr (car tmp)))
1771 "\">" (w3-insert-entities-in-string
1772 (car (car tmp))) "</a></li>\n")
1773 (setq tmp (cdr tmp)))
1774 (insert "\n\t\t\t</ol>\n\t\t</div>\n\t</body>\n</html>\n")))
1775 ((equal type "starting-points")
1776 (let ((tmp w3-starting-documents))
1777 (insert "<html>\n\t<head>\n\t\t"
1778 "<title> Starting Points </title>\n\t</head>\n"
1779 "\t<body>\n\t\t<div>\n\t\t\t<h1>Starting Point on the Web"
1780 "</h1>\n\t\t\t<ol>\n")
1781 (while tmp
1782 (insert (format "\t\t\t\t<li> <a href=\"%s\">%s</a></li>\n"
1783 (car (cdr (car tmp)))
1784 (car (car tmp))))
1785 (setq tmp (cdr tmp)))
1786 (insert "\n\t\t\t</ol>\n\t\t</div>\n\t</body>\n</html>\n")))
1787 ((equal type "history")
1788 (if (not url-history-list)
1789 (url-retrieve "www://error/nohist")
1790 (insert "<html>\n\t<head>\n\t\t"
1791 "<title> History List For This Session of W3</title>"
1792 "\n\t</head>\n\t<body>\n\t\t<div>\n\t\t\t<h1>"
1793 "History List For This Session of W3</h1>\n\t\t\t<ol>\n")
1794 (url-maphash
1795 (function
1796 (lambda (url desc)
1797 (insert (format "\t\t\t\t<li> <a href=\"%s\">%s</a>\n"
1798 url (w3-insert-entities-in-string desc)))))
1799 url-history-list)
1800 (insert "\n\t\t\t</ol>\n\t\t</div>\n\t</body>\n</html>\n")))))
1801
1802 (defun w3-internal-handle-preview (buffer)
1803 (setq buffer (get-buffer buffer))
1804 (let ((base (get-text-property (point-min) 'w3-base buffer)))
1805 (if base
1806 (setq base (url-generic-parse-url base)))
1807 (insert-buffer buffer)
1808 (if (not base)
1809 (setq url-current-type "file"
1810 url-current-server nil
1811 url-current-file (buffer-file-name buffer))
1812 (setq url-current-object base
1813 url-current-type (url-type base)
1814 url-current-user (url-user base)
1815 url-current-port (url-port base)
1816 url-current-server (url-host base)
1817 url-current-file (url-filename base)))))
1818
1819 (defun w3-internal-url (url)
1820 ;; Handle internal urls (previewed buffers, etc)
1821 (if (not (string-match "www:/+\\([^/]+\\)/\\(.*\\)" url))
1822 (w3-fetch "www://error/")
1823 (let ((type (url-match url 1))
1824 (data (url-match url 2)))
1825 (set-buffer (get-buffer-create url-working-buffer))
1826 (setq url-current-type "www"
1827 url-current-server type
1828 url-current-file data)
1829 (cond
1830 ((equal type "preview") ; Previewing a document
1831 (if (get-buffer data) ; Buffer still exists
1832 (w3-internal-handle-preview data)
1833 (url-retrieve (concat "www://error/nobuf/" data))))
1834 ((equal type "error") ; Error message
1835 (if (string-match "\\([^/]+\\)/\\(.*\\)" data)
1836 (w3-generate-error (url-match data 1) (url-match data 2))
1837 (w3-generate-error data "")))
1838 ((equal type "auto") ; Hotlist or help stuff
1839 (w3-generate-auto-html data))))))
1840
1841 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1842 ;;; Stuff for good local file handling
1843 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1844 (defun w3-ff (file)
1845 "Find a file in any window already displaying it, otherwise just as
1846 display-buffer, and using this function"
1847 (if (not (eq 'tty (device-type)))
1848 (let ((f (window-frame (display-buffer (find-file-noselect file)))))
1849 (set-mouse-position f 1 0)
1850 (raise-frame f)
1851 (unfocus-frame))
1852 (display-buffer (find-file-noselect file))))
1853
1854 (defun w3-default-local-file()
1855 "Use find-file to open the local file"
1856 (w3-ff url-current-file))
1857
1858 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1859 ;;; Mode definition ;;;
1860 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1861 (defun w3-search-forward (string)
1862 (interactive "sSearch: ")
1863 (setq w3-last-search-item string)
1864 (if (and (not (search-forward string nil t))
1865 (funcall url-confirmation-func
1866 "End of document reached; continue from beginning? "))
1867 (progn
1868 (goto-char (point-min))
1869 (w3-search-forward string))))
1870
1871 (defun w3-search-again ()
1872 (interactive)
1873 (if (and w3-last-search-item
1874 (stringp w3-last-search-item))
1875 (if (and (not (search-forward w3-last-search-item nil t))
1876 (funcall url-confirmation-func
1877 "End of document reached; continue from beginning? "))
1878 (progn
1879 (goto-char (point-min))
1880 (w3-search-again)))))
1881
1882 (defun w3-find-specific-link (link)
1883 (let ((pos (assq (intern link) w3-id-positions)))
1884 (if pos
1885 (progn
1886 (goto-char (cdr pos))
1887 (if (and (eolp) (not (eobp)))
1888 (forward-char 1)))
1889 (error "Link #%s not found." link))))
1890
1891 (defun w3-force-reload-document ()
1892 "Reload the current document. Take it from the network, even if
1893 cached and in local mode."
1894 (let ((url-standalone-mode nil))
1895 (w3-reload-document)))
1896
1897 (defun w3-reload-document ()
1898 "Reload the current document"
1899 (interactive)
1900 (let ((tmp (url-view-url t))
1901 (pnt (point))
1902 (window-start (progn
1903 (move-to-window-line 0)
1904 (point)))
1905 (url-request-extra-headers '(("Pragma" . "no-cache"))))
1906 (kill-buffer (current-buffer))
1907 (w3-fetch tmp)
1908 (goto-char pnt)
1909 (set-window-start (selected-window) (min window-start (point-max)))))
1910
1911 (defun w3-leave-buffer ()
1912 "Bury this buffer, but don't kill it."
1913 (interactive)
1914 (let ((x w3-current-last-buffer))
1915 (bury-buffer nil)
1916 (if (and (bufferp x) (buffer-name x))
1917 (w3-notify-when-ready x))))
1918
1919 (defun w3-quit (&optional mega)
1920 "Quit WWW mode"
1921 (interactive "P")
1922 (if mega
1923 (mapcar
1924 (function
1925 (lambda (x)
1926 (save-excursion
1927 (set-buffer (get-buffer x))
1928 (if (eq major-mode 'w3-mode)
1929 (w3-quit nil)))))
1930 (buffer-list))
1931 (let ((x w3-current-last-buffer))
1932 (and (fboundp 'w3-mpeg-kill-processes) (w3-mpeg-kill-processes))
1933 (kill-buffer (current-buffer))
1934 (if (and (bufferp x) (buffer-name x))
1935 (w3-notify-when-ready x)))))
1936
1937 (defun w3-view-this-url (&optional no-show)
1938 "View the URL of the link under point"
1939 (interactive)
1940 (let* ((widget (widget-at (point)))
1941 (href (and widget (widget-get widget 'href))))
1942 (cond
1943 ((and no-show href)
1944 href)
1945 (href
1946 (message "%s" (url-truncate-url-for-viewing href)))
1947 (no-show
1948 nil)
1949 (t
1950 nil))))
1951
1952 (defun w3-load-delayed-images ()
1953 "Load inlined images that were delayed, if necessary.
1954 This function searches through `w3-delayed-images' and fetches the
1955 appropriate picture for each point in the buffer and inserts it."
1956 (interactive)
1957 (and (fboundp 'w3-insert-graphic)
1958 (let ((buffer-read-only nil))
1959 (mapcar (function (lambda (data) (apply 'w3-insert-graphic data)))
1960 (nreverse w3-delayed-images))))
1961 (setq w3-delayed-images nil))
1962
1963 (defun w3-save-this-url ()
1964 "Save url under point in the kill ring"
1965 (interactive)
1966 (w3-save-url t))
1967
1968 (defun w3-save-url (under-pt)
1969 "Save current url in the kill ring"
1970 (interactive "P")
1971 (let ((x (cond
1972 ((stringp under-pt) under-pt)
1973 (under-pt (w3-view-this-url t))
1974 (t (url-view-url t)))))
1975 (if x
1976 (progn
1977 (setq kill-ring (cons x kill-ring))
1978 (setq kill-ring-yank-pointer kill-ring)
1979 (message "Stored URL in kill-ring.")
1980 (if (fboundp 'w3-store-in-clipboard)
1981 (w3-store-in-clipboard x)))
1982 (error "No URL to store."))))
1983
1984 (fset 'w3-end-of-document 'end-of-buffer)
1985 (fset 'w3-start-of-document 'beginning-of-buffer)
1986
1987 (defun w3-scroll-up (&optional lines)
1988 "Scroll forward in View mode, or exit if end of text is visible.
1989 No arg means whole window full. Arg is number of lines to scroll."
1990 (interactive "P")
1991 (if (and (pos-visible-in-window-p (point-max))
1992 ;; Allow scrolling backward at the end of the buffer.
1993 (or (null lines)
1994 (> lines 0)))
1995 nil
1996 (let ((view-lines (1- (window-height))))
1997 (setq lines
1998 (if lines (prefix-numeric-value lines)
1999 view-lines))
2000 (if (>= lines view-lines)
2001 (scroll-up nil)
2002 (if (>= (- lines) view-lines)
2003 (scroll-down nil)
2004 (scroll-up lines)))
2005 (cond ((pos-visible-in-window-p (point-max))
2006 (goto-char (point-max))
2007 (recenter -1)))
2008 (move-to-window-line -1)
2009 (beginning-of-line))))
2010
2011 (defun w3-mail-document-author ()
2012 "Send mail to the author of this document, if possible."
2013 (interactive)
2014 (let ((x w3-current-links)
2015 (y nil)
2016 (found nil))
2017 (setq found (cdr-safe (assoc "reply-to" url-current-mime-headers)))
2018 (if (and found (not (string-match url-nonrelative-link found)))
2019 (setq found (concat "mailto:" found)))
2020 (while (and x (not found))
2021 (setq y (car x)
2022 x (cdr x)
2023 found (cdr-safe (assoc "made" y))))
2024 (if found
2025 (let ((possible nil))
2026 (setq x (car found)) ; Fallback if no mail(to|server) found
2027 (while found
2028 (if (string-match "^mail[^:]+:" (car found))
2029 (setq possible (cons (car found) possible)))
2030 (setq found (cdr found)))
2031 (case (length possible)
2032 (0 ; No mailto links found
2033 (w3-fetch x)) ; fall back onto first 'made' link
2034 (1 ; Only one found, get it
2035 (w3-fetch (car possible)))
2036 (otherwise
2037 (w3-fetch (completing-read "Choose an address: "
2038 (mapcar 'list possible)
2039 nil t (car possible))))))
2040 (message "Could not automatically determine authors address, sorry.")
2041 (sit-for 1)
2042 (w3-fetch (concat "mailto:"
2043 (read-string "Email address: "
2044 (if url-current-server
2045 (concat "@" url-current-server))))))))
2046
2047 (defun w3-kill-emacs-func ()
2048 "Routine called when exiting emacs. Do miscellaneous clean up."
2049 (and (eq url-keep-history t)
2050 url-global-history-hash-table
2051 (url-write-global-history))
2052 (message "Cleaning up w3 storage...")
2053 (let ((x (nconc
2054 (and (file-exists-p w3-temporary-directory)
2055 (directory-files w3-temporary-directory t "url-tmp.*"))
2056 (and (file-exists-p url-temporary-directory)
2057 (directory-files url-temporary-directory t
2058 (concat "url"
2059 (int-to-string
2060 (user-real-uid)) ".*")))
2061 (and (file-exists-p url-temporary-directory)
2062 (directory-files url-temporary-directory t "url-tmp.*")))))
2063 (while x
2064 (condition-case ()
2065 (delete-file (car x))
2066 (error nil))
2067 (setq x (cdr x))))
2068 (message "Cleaning up w3 storage... done."))
2069
2070 (cond
2071 ((fboundp 'display-warning)
2072 (fset 'w3-warn 'display-warning))
2073 ((fboundp 'warn)
2074 (defun w3-warn (class message &optional level)
2075 (if (and (eq class 'html)
2076 (not w3-debug-html))
2077 nil
2078 (warn "(%s/%s) %s" class (or level 'warning) message))))
2079 (t
2080 (defun w3-warn (class message &optional level)
2081 (if (and (eq class 'html)
2082 (not w3-debug-html))
2083 nil
2084 (save-excursion
2085 (set-buffer (get-buffer-create "*W3-WARNINGS*"))
2086 (goto-char (point-max))
2087 (save-excursion
2088 (insert (format "(%s/%s) %s\n" class (or level 'warning) message)))
2089 (display-buffer (current-buffer)))))))
2090
2091 (defun w3-internal-expander (urlobj defobj)
2092 ;; URL Expansion routine for internally handled routines
2093 (url-identity-expander urlobj defobj))
2094
2095 (defun w3-map-links (function &optional buffer from to maparg)
2096 "Map FUNCTION over the hypertext links which overlap region in BUFFER,
2097 starting at FROM and ending at TO. FUNCTION is called with the arguments
2098 WIDGET and MAPARG.
2099 The arguments FROM, TO, MAPARG, and BUFFER default to the beginning of
2100 BUFFER, the end of BUFFER, nil, and (current-buffer), respectively."
2101 (let ((cur (point-min))
2102 (widget nil)
2103 (url nil))
2104 (while (setq cur (next-single-property-change cur 'button))
2105 (setq widget (widget-at cur))
2106 ;; Check to see if its a push widget, its got the correct callback,
2107 ;; and actually has a URL. Remember the url as a side-effect of the
2108 ;; test for later use.
2109 (if (and (eq (car widget) 'push)
2110 (eq (widget-get widget :notify) 'w3-follow-hyperlink)
2111 (setq url (widget-get widget 'href)))
2112 (funcall function widget maparg)))))
2113
2114 (defun w3-emit-image-warnings-if-necessary ()
2115 (if (and (not w3-delay-image-loads)
2116 (fboundp 'w3-insert-graphic)
2117 (or (not (featurep 'gif))
2118 (not (featurep 'jpeg)))
2119 (not (w3-executable-exists-in-path "ppmtoxpm"))
2120 (not (or
2121 (w3-executable-exists-in-path "pbmtoxbm")
2122 (w3-executable-exists-in-path "ppmtoxbm"))))
2123 (w3-warn
2124 'image
2125 (concat
2126 "Could not find some vital ppm utilities in exec-path.\n"
2127 "This probably means that you will be unable to view any\n"
2128 "inlined images other than: "
2129 (mapconcat
2130 (function
2131 (lambda (x)
2132 (if (featurep x) (concat (symbol-name x) ",\n"))))
2133 '(png jpg gif xpm xbm) "")
2134 "\n\n"
2135 "If you do not have the PPM utilities from either the PBMPLUS\n"
2136 "or NETPBM distributions installed on your machine, then\n"
2137 "please set the variable `w3-delay-image-loads' to t with a\n"
2138 "line like:\n\n"
2139 "\t(setq w3-delay-image-loads t)\n\n"
2140 "in your ~/.emacs file.\n\n"
2141 "You can find the NETPBM utilities in:\n"
2142 "\tftp://ftp.cs.indiana.edu/pub/elisp/w3/images/\n"
2143 ))))
2144
2145 (defun w3-find-default-stylesheets ()
2146 (let* ((lightp (w3-color-light-p 'default))
2147 (longname (if lightp "stylesheet-light" "stylesheet-dark"))
2148 (shortname (if lightp "light.css" "dark.css"))
2149 (directories (list
2150 data-directory
2151 (concat data-directory "w3/")
2152 (file-name-directory (locate-library "w3"))
2153 w3-configuration-directory))
2154 (total-found 0)
2155 (possible (append
2156 (apply
2157 'append
2158 (mapcar
2159 (function
2160 (lambda (dir)
2161 (list
2162 (expand-file-name shortname dir)
2163 (expand-file-name longname dir)
2164 (expand-file-name "stylesheet" dir)
2165 (expand-file-name "default.css" dir))))
2166 directories))
2167 (list w3-default-stylesheet)))
2168 (remember possible)
2169 (old-asynch (default-value 'url-be-asynchronous))
2170 (found nil)
2171 (cur nil)
2172 (url nil))
2173 (setq-default url-be-asynchronous nil)
2174 (while possible
2175 (setq cur (car possible)
2176 possible (cdr possible)
2177 found (and cur (file-exists-p cur) (file-readable-p cur)
2178 (not (file-directory-p cur)) cur))
2179 (if found
2180 (setq total-found (1+ total-found)
2181 w3-user-stylesheet (car
2182 (w3-style-parse-css
2183 (concat "file:" cur) nil
2184 w3-user-stylesheet)))))
2185 (setq-default url-be-asynchronous old-asynch)
2186 (if (= 0 total-found)
2187 (w3-warn
2188 'style
2189 (concat
2190 "No stylesheets found! Check configuration! DANGER DANGER!\n"
2191 "Emacs-W3 checked for its stylesheet in the following places\n"
2192 "and did not find one. This means that some formatting will\n"
2193 "be wrong, and most colors and fonts will not be set up correctly.\n"
2194 "------\n"
2195 (mapconcat 'identity remember "\n")
2196 "------")))))
2197
2198 ;;;###autoload
2199 (defun w3-do-setup ()
2200 "Do setup - this is to avoid conflict with user settings when W3 is
2201 dumped with emacs."
2202 (url-do-setup)
2203 (url-register-protocol 'about 'w3-about 'url-identity-expander)
2204 (url-register-protocol 'www 'w3-internal-url 'w3-internal-expander)
2205 (w3-load-flavors)
2206 (w3-setup-version-specifics)
2207 (setq w3-default-configuration-file (expand-file-name
2208 (or w3-default-configuration-file
2209 "profile")
2210 w3-configuration-directory))
2211
2212
2213 (if (and w3-default-configuration-file
2214 (file-exists-p w3-default-configuration-file))
2215 (condition-case e
2216 (load w3-default-configuration-file nil t)
2217 (error
2218 (let ((buf-name " *Configuration Error*"))
2219 (if (get-buffer buf-name)
2220 (kill-buffer (get-buffer buf-name)))
2221 (display-error e (get-buffer-create buf-name))
2222 (save-excursion
2223 (switch-to-buffer-other-window buf-name)
2224 (shrink-window-if-larger-than-buffer))
2225 (w3-warn 'configuration
2226 (format (eval-when-compile
2227 (concat
2228 "Configuration file `%s' contains an error.\n"
2229 "Please consult the `%s' buffer for details."))
2230 w3-default-configuration-file buf-name))))))
2231
2232 (setq w3-netscape-configuration-file
2233 (cond
2234 (w3-netscape-configuration-file
2235 w3-netscape-configuration-file)
2236 ((memq system-type '(ms-dos ms-windows))
2237 (expand-file-name "~/NETSCAPE.CFG"))
2238 (t (expand-file-name "~/.netscape/preferences"))))
2239
2240 (if (and (eq w3-user-colors-take-precedence 'guess)
2241 (not (eq (device-type) 'tty))
2242 (not (eq (device-class) 'mono)))
2243 (progn
2244 (setq w3-user-colors-take-precedence t)
2245 (w3-warn
2246 'html
2247 "Disabled document color specification because of mono display."))
2248 (setq w3-user-colors-take-precedence nil))
2249
2250 (w3-find-default-stylesheets)
2251 (if (not url-global-history-file)
2252 (setq url-global-history-file
2253 (expand-file-name "history"
2254 w3-configuration-directory)))
2255
2256 (if w3-user-stylesheet
2257 (w3-generate-stylesheet-faces w3-user-stylesheet))
2258
2259 (if (and w3-use-netscape-configuration-file
2260 w3-netscape-configuration-file
2261 (fboundp 'w3-read-netscape-config))
2262 (w3-read-netscape-config w3-netscape-configuration-file))
2263
2264 (add-minor-mode 'w3-netscape-emulation-minor-mode " NS"
2265 w3-netscape-emulation-minor-mode-map)
2266 (add-minor-mode 'w3-annotation-minor-mode " Annotating"
2267 w3-annotation-minor-mode-map)
2268 (add-minor-mode 'w3-lynx-emulation-minor-mode " Lynx"
2269 w3-annotation-minor-mode-map)
2270
2271 (setq url-package-version w3-version-number
2272 url-package-name "Emacs-W3")
2273
2274 (w3-emit-image-warnings-if-necessary)
2275 (if (eq w3-color-use-reducing 'guess)
2276 (setq w3-color-use-reducing
2277 (cond
2278 ((eq (device-type) 'tty) nil)
2279 ((fboundp 'device-class)
2280 (not (and (memq (device-class) '(TrueColor true-color))
2281 (<= 16 (or (device-bitplanes) 0)))))
2282 (t t))))
2283
2284 (cond
2285 ((memq system-type '(ms-dos ms-windows))
2286 (setq w3-documents-menu-file (or w3-documents-menu-file
2287 (expand-file-name "~/mosaic.mnu"))
2288 w3-hotlist-file (or w3-hotlist-file
2289 (expand-file-name "~/mosaic.hot"))
2290 w3-personal-annotation-directory (or w3-personal-annotation-directory
2291 (expand-file-name
2292 "~/mosaic.ann"))))
2293 ((memq system-type '(axp-vms vax-vms))
2294 (setq w3-documents-menu-file
2295 (or w3-documents-menu-file
2296 (expand-file-name "decw$system_defaults:documents.menu"))
2297 w3-hotlist-file (or w3-hotlist-file
2298 (expand-file-name "~/mosaic.hotlist-default"))
2299 w3-personal-annotation-directory
2300 (or w3-personal-annotation-directory
2301 (expand-file-name "~/mosaic-annotations/"))))
2302 (t
2303 (setq w3-documents-menu-file
2304 (or w3-documents-menu-file
2305 (expand-file-name "/usr/local/lib/mosaic/documents.menu"))
2306 w3-hotlist-file (or w3-hotlist-file
2307 (expand-file-name "~/.mosaic-hotlist-default"))
2308 w3-personal-annotation-directory
2309 (or w3-personal-annotation-directory
2310 (expand-file-name "~/.mosaic-personal-annotations")))))
2311
2312 (if (eq w3-delimit-emphasis 'guess)
2313 (setq w3-delimit-emphasis
2314 (and (not w3-running-xemacs)
2315 (not (and w3-running-FSF19
2316 (memq (device-type) '(x ns pm)))))))
2317
2318 (if (eq w3-delimit-links 'guess)
2319 (setq w3-delimit-links
2320 (and (not w3-running-xemacs)
2321 (not (and w3-running-FSF19
2322 (memq (device-type) '(x ns pm)))))))
2323
2324 ; Set up a hook that will save the history list when
2325 ; exiting emacs
2326 (add-hook 'kill-emacs-hook 'w3-kill-emacs-func)
2327
2328 (mm-parse-mailcaps)
2329 (mm-parse-mimetypes)
2330
2331 ; Load in the hotlist if they haven't set it already
2332 (or w3-hotlist (w3-parse-hotlist))
2333
2334 ; Load in their personal annotations if they haven't set them already
2335 (or w3-personal-annotations (w3-parse-personal-annotations))
2336
2337 ; Set the default home page, honoring their defaults, then
2338 ; the standard WWW_HOME, then default to the documentation @ IU
2339 (or w3-default-homepage
2340 (setq w3-default-homepage
2341 (or (getenv "WWW_HOME")
2342 "http://www.cs.indiana.edu/elisp/w3/docs.html")))
2343
2344 ; Set up the documents menu
2345 (w3-parse-docs-menu)
2346
2347 ; Set up the entity definition for PGP and PEM authentication
2348
2349 (run-hooks 'w3-load-hook)
2350 (setq w3-setup-done t))
2351
2352 (defun w3-mark-link-as-followed (ext dat)
2353 ;; Mark a link as followed
2354 (let* ((st (w3-zone-start ext))
2355 (nd (w3-zone-end ext))
2356 (tag 'a)
2357 (args (list (cons 'class "visited")))
2358 (face (cdr (w3-face-for-element))))
2359 (w3-add-zone st nd face dat t)))
2360
2361 (defun w3-only-links ()
2362 (let* (result temp)
2363 (if (widget-at (point-min))
2364 (setq result (list (widget-at (point-min)))))
2365 (setq temp (w3-next-widget (point-min)))
2366 (while temp
2367 (if (widget-get temp 'href)
2368 (setq result (cons temp result)))
2369 (setq temp (w3-next-widget (widget-get temp :to))))
2370 result))
2371
2372 (defun w3-download-callback (fname buff)
2373 (if (and (get-buffer buff) (buffer-name buff))
2374 (save-excursion
2375 (set-buffer buff)
2376 (let ((require-final-newline nil)
2377 (file-name-handler-alist nil)
2378 (write-file-hooks nil)
2379 (write-contents-hooks nil))
2380 (if (featurep 'mule)
2381 (let ((mc-flag t))
2382 (write-file fname nil *noconv*))
2383 (write-file fname))
2384 (message "Download of %s complete." (url-view-url t))
2385 (sit-for 3)
2386 (kill-buffer buff)))))
2387
2388 (defun w3-download-url (url)
2389 (let* ((old-asynch url-be-asynchronous)
2390 (url-inhibit-uncompression t)
2391 (url-mime-accept-string "*/*")
2392 (urlobj (url-generic-parse-url url))
2393 (url-working-buffer
2394 (generate-new-buffer (concat " *" url " download*")))
2395 (stub-fname (url-basepath (or (url-filename urlobj) "") t))
2396 (fname (read-file-name "Filename to save as: "
2397 (or mm-download-directory "~/")
2398 (concat (or mm-download-directory "~/")
2399 stub-fname)
2400 nil
2401 stub-fname)))
2402 (setq-default url-be-asynchronous t)
2403 (save-excursion
2404 (set-buffer url-working-buffer)
2405 (setq url-current-callback-data (list fname (current-buffer))
2406 url-be-asynchronous t
2407 url-current-callback-func 'w3-download-callback)
2408 (url-retrieve url))
2409 (setq-default url-be-asynchronous old-asynch)))
2410
2411 ;;;###autoload
2412 (defun w3-follow-link-other-frame (&optional p)
2413 "Attempt to follow the hypertext reference under point in a new frame.
2414 With prefix-arg P, ignore viewers and dump the link straight
2415 to disk."
2416 (cond
2417 ((and (fboundp 'make-frame)
2418 (fboundp 'select-frame))
2419 (let ((frm (make-frame)))
2420 (select-frame frm)
2421 (w3-follow-link p)))
2422 (t (w3-follow-link p))))
2423
2424 ;;;###autoload
2425 (defun w3-follow-link (&optional p)
2426 "Attempt to follow the hypertext reference under point.
2427 With prefix-arg P, ignore viewers and dump the link straight
2428 to disk."
2429 (interactive "P")
2430 (let* ((widget (widget-at (point)))
2431 (href (and widget (widget-get widget 'href))))
2432 (cond
2433 ((null href) nil)
2434 ((or p w3-dump-to-disk)
2435 (w3-download-url href))
2436 (t
2437 (w3-fetch href)))))
2438
2439 (defun w3-complete-link ()
2440 "Choose a link from the current buffer and follow it"
2441 (interactive)
2442 (let (links-alist
2443 link-at-point
2444 choice
2445 (completion-ignore-case t))
2446 (setq link-at-point (widget-at (point))
2447 link-at-point (and
2448 link-at-point
2449 (widget-get link-at-point 'href)
2450 (w3-fix-spaces
2451 (buffer-substring
2452 (car (widget-get link-at-point 'title))
2453 (cdr (widget-get link-at-point 'title))))))
2454 (w3-map-links (function
2455 (lambda (widget arg)
2456 (setq links-alist (cons
2457 (cons
2458 (w3-fix-spaces
2459 (buffer-substring-no-properties
2460 (widget-get widget :from)
2461 (widget-get widget :to)))
2462 (widget-get widget 'href))
2463 links-alist)))))
2464 (if (not links-alist) (error "No links in current document."))
2465 (setq links-alist (sort links-alist (function
2466 (lambda (x y)
2467 (string< (car x) (car y))))))
2468 ;; Destructively remove duplicate entries from links-alist.
2469 (let ((remaining-links links-alist))
2470 (while remaining-links
2471 (if (equal (car remaining-links) (car (cdr remaining-links)))
2472 (setcdr remaining-links (cdr (cdr remaining-links)))
2473 (setq remaining-links (cdr remaining-links)))))
2474 (setq choice (completing-read
2475 (if link-at-point
2476 (concat "Link (default "
2477 (if (< (length link-at-point) 20)
2478 link-at-point
2479 (concat
2480 (substring link-at-point 0 17) "..."))
2481 "): ")
2482 "Link: ") links-alist nil t))
2483 (if (string= choice "")
2484 (w3-follow-link)
2485 (w3-fetch (cdr (assoc choice links-alist))))))
2486
2487 (defun w3-mode ()
2488 "Mode for viewing HTML documents. If called interactively, will
2489 display the current buffer as HTML.
2490
2491 Current keymap is:
2492 \\{w3-mode-map}"
2493 (interactive)
2494 (or w3-setup-done (w3-do-setup))
2495 (if (interactive-p)
2496 (w3-preview-this-buffer)
2497 (let ((tmp (mapcar (function (lambda (x) (cons x (symbol-value x))))
2498 w3-persistent-variables)))
2499 (kill-all-local-variables)
2500 (use-local-map w3-mode-map)
2501 (setq major-mode 'w3-mode)
2502 (setq mode-name "WWW")
2503 (mapcar (function (lambda (x) (set-variable (car x) (cdr x)))) tmp)
2504 (w3-mode-version-specifics)
2505 (w3-menu-install-menus)
2506 (run-hooks 'w3-mode-hook)
2507 (widget-setup)
2508 (setq url-current-passwd-count 0
2509 mode-line-format w3-modeline-format)
2510 (if (and w3-current-isindex (equal url-current-type "http"))
2511 (setq mode-line-process "-Searchable")))))
2512
2513 (require 'mm)
2514 (require 'url)
2515 (require 'url-hash)
2516 (require 'w3-parse)
2517 (require 'w3-draw)
2518 (require 'w3-auto)
2519 (require 'w3-emulate)
2520 (require 'w3-menu)
2521 (require 'w3-mouse)
2522 (provide 'w3)