diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/w3/w3.el	Mon Aug 13 08:45:50 2007 +0200
@@ -0,0 +1,2522 @@
+;;; w3.el,v --- Main functions for emacs-w3 on all platforms/versions
+;; Author: wmperry
+;; Created: 1996/06/06 15:03:12
+;; Version: 1.550
+;; Keywords: faces, help, comm, news, mail, processes, mouse, hypermedia
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Copyright (c) 1993, 1994, 1995 by William M. Perry (wmperry@spry.com)
+;;;
+;;; This file is not part of GNU Emacs, but the same permissions apply.
+;;;
+;;; GNU Emacs is free software; you can redistribute it and/or modify
+;;; it under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation; either version 2, or (at your option)
+;;; any later version.
+;;;
+;;; GNU Emacs is distributed in the hope that it will be useful,
+;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with GNU Emacs; see the file COPYING.  If not, write to
+;;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; This is a major mode for browsing documents written in Hypertext Markup ;;;
+;;; Language (HTML).  These documents are typicallly part of the World Wide ;;;
+;;; Web (WWW), a project to create a global information net in hypertext    ;;;
+;;; format.				                                    ;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; first start by making sure the load path is properly set.  This code
+;;; is mostly taken from calc-2.02b
+;;;
+;;; this allows you to put the following in your .emacs file, instead of
+;;; having to know what the load-path for the w3 files is.
+;;;
+;;;     (autoload 'w3 "w3/w3" "WWW Browser" t)
+
+;;; If w3 files exist on the load-path, we're all set.
+(let ((name (and (fboundp 'w3)
+		 (eq (car-safe (symbol-function 'w3)) 'autoload)
+		 (nth 1 (symbol-function 'w3))))
+      (p load-path))
+  (while (and p (not (file-exists-p
+		      (expand-file-name "w3-vars.elc" (car p)))))
+    (setq p (cdr p)))
+  (or p
+;;; If w3 is autoloaded using a path name, look there for w3 files.
+;;; This works for both relative ("w3/w3.elc") and absolute paths.
+      (and name (file-name-directory name)
+	   (let ((p2 load-path)
+		 (name2 (concat (file-name-directory name)
+				"w3-vars.elc")))
+	     (while (and p2 (not (file-exists-p
+				  (expand-file-name name2 (car p2)))))
+	       (setq p2 (cdr p2)))
+	     (if p2
+		 (setq load-path (nconc load-path
+					(list
+					 (directory-file-name
+					  (file-name-directory
+					   (expand-file-name
+					    name (car p2)))))))))))
+  )
+
+
+(load-library "w3-sysdp")
+(or (featurep 'efs)
+    (featurep 'efs-auto)
+    (condition-case ()
+	(require 'ange-ftp)
+      (error nil)))
+
+(require 'cl)
+(require 'w3-vars)
+(eval-and-compile
+  (require 'w3-draw))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Code for printing out roman numerals
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defun w3-decimal-to-roman (n)
+  ;; Convert from decimal to roman numerals
+  (let ((curmod 1000)
+	(str "")
+	(j 7)
+	i2 k curcnt)
+    (while (>= curmod 1)
+      (if (>= n curmod)
+	  (progn
+	    (setq curcnt (/ n curmod)
+		  n (- n (* curcnt curmod)))
+	    (if (= 4 (% curcnt 5))
+		(setq i2 (+ j (if (> curcnt 5) 1 0))
+		      str (format "%s%c%c" str
+				  (aref w3-roman-characters (1- j))
+				  (aref w3-roman-characters i2)))
+	      (progn
+		(if (>= curcnt 5)
+		    (setq str (format "%s%c" str (aref w3-roman-characters j))
+			  curcnt (- curcnt 5)))
+		(setq k 0)
+		(while (< k curcnt)
+		  (setq str (format "%s%c" str
+				    (aref w3-roman-characters (1- j)))
+			k (1+ k)))))))
+      (setq curmod (/ curmod 10)
+	    j (- j 2)))
+    str))
+
+(defun w3-decimal-to-alpha (n)
+  ;; Convert from decimal to alphabetical (a, b, c, ..., aa, ab,...)
+  (cond
+   ((< n 1) (char-to-string ?Z))
+   ((<= n 26) (char-to-string (+ ?A (1- n))))
+   (t (concat (char-to-string (+ ?A (1- (/ n 27))))
+	      (w3-decimal-to-alpha (% n 26))))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Functions for compatibility with XMosaic
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Parse out the Mosaic documents-menu file
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defun w3-parse-docs-menu ()
+  ;; Parse the Mosaic documents menu
+  (let ((tmp-menu (append '((separator)) w3-starting-documents
+			  '((separator))))
+	real-menu x y name url)
+    (if (or (not (file-exists-p w3-documents-menu-file))
+	    (not (file-readable-p w3-documents-menu-file)))
+	nil
+      (save-excursion
+	(set-buffer (get-buffer-create " *w3-temp*"))
+	(erase-buffer)
+	(insert-file-contents w3-documents-menu-file)
+	(goto-char (point-min))
+	(while (not (eobp))
+	  (if (not (looking-at "-+$"))
+	      (setq x (progn (beginning-of-line) (point))
+		    y (progn (end-of-line) (point))
+		    name (prog1
+			     (buffer-substring x y)
+			   (delete-region x (min (1+ y) (point-max))))
+		    x (progn (beginning-of-line) (point))
+		    y (progn (end-of-line) (point))
+		    url (prog1
+			    (buffer-substring x y)
+			  (delete-region x (min (1+ y) (point-max))))
+		    tmp-menu (if (rassoc url tmp-menu) tmp-menu
+			       (cons (cons name url) tmp-menu)))
+	    (setq tmp-menu (cons '(separator) tmp-menu))
+	    (delete-region (point-min) (min (1+ (progn (end-of-line)
+						       (point)))
+					    (point-max)))))
+	(kill-buffer (current-buffer))))
+    (if (equal (car (car tmp-menu)) "") (setq tmp-menu (cdr tmp-menu)))
+    (while tmp-menu
+      (setq real-menu (cons (if (equal 'separator (car (car tmp-menu)))
+				"--------"
+			      (vector (car (car tmp-menu))
+				      (list 'w3-fetch
+					    (if (listp (cdr (car tmp-menu)))
+						(car (cdr (car tmp-menu)))
+					      (cdr (car tmp-menu)))) t))
+			    real-menu)
+	    tmp-menu (cdr tmp-menu)))
+    (setq w3-navigate-menu (append w3-navigate-menu real-menu
+				   (list "-----")))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Functions to pass files off to external viewers
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defun w3-start-viewer (fname cmd &optional view)
+  "Start a subprocess, named FNAME, executing CMD
+If third arg VIEW is non-nil, show the output in a buffer when
+the subprocess exits."
+  (if view (save-excursion
+	     (set-buffer (get-buffer-create view))
+	     (erase-buffer)))
+  (let ((proc
+	 (start-process fname view (or shell-file-name
+				       (getenv "ESHELL")
+				       (getenv "SHELL")
+				       "/bin/sh") "-c" cmd)))
+    proc))
+
+(defun w3-viewer-filter (proc string)
+  ;; A process filter for asynchronous external viewers
+  (let ((buff (get-buffer-create (url-generate-new-buffer-name
+				  (symbol-name
+				   (read (nth 2 (process-command proc))))))))
+    (save-excursion
+      (set-buffer buff)
+      (erase-buffer)
+      (insert string)
+      (set-process-buffer proc buff)
+      (set-process-filter proc nil))))
+
+(defun w3-viewer-sentinel (proc string)
+  ;; Delete any temp files left from a viewer process.
+  (let ((fname (process-name proc))
+	(buffr (process-buffer proc))
+	(status (process-exit-status proc)))
+    (if buffr
+	(w3-notify-when-ready buffr))
+    (and (/= 0 status)
+	 (funcall url-confirmation-func
+		  (format "Viewer for %s failed... save to disk? " fname))
+	 (copy-file fname (read-file-name "Save as: ") t))
+    (if (and (file-exists-p fname)
+	     (file-writable-p fname))
+	(delete-file fname))))
+
+(defun w3-notify-when-ready (buff)
+  "Notify the user when BUFF is ready.
+See the variable `w3-notify' for the different notification behaviors."
+  (if (stringp buff) (setq buff (get-buffer buff)))
+  (cond
+   ((null buff) nil)
+   ((eq w3-notify 'newframe)
+    ;; Since we run asynchronously, perhaps while Emacs is waiting for input,
+    ;; we must not leave a different buffer current.
+    ;; We can't rely on the editor command loop to reselect
+    ;; the selected window's buffer.
+    (save-excursion
+      (set-buffer buff)
+      (make-frame)))
+   ((eq w3-notify 'bully)
+    (pop-to-buffer buff)
+    (delete-other-windows))
+   ((eq w3-notify 'semibully)
+    (switch-to-buffer buff))
+   ((eq w3-notify 'aggressive)
+    (pop-to-buffer buff))
+   ((eq w3-notify 'friendly)
+    (display-buffer buff 'not-this-window))
+   ((eq w3-notify 'polite)
+    (beep)
+    (message "W3 buffer %s is ready." (buffer-name buff)))
+   ((eq w3-notify 'quiet)
+    (message "W3 buffer %s is ready." (buffer-name buff)))
+   (t (message ""))))
+
+(defun w3-pass-to-viewer ()
+  ;; Pass a w3 buffer to a viewer
+  (set-buffer url-working-buffer)
+  (let* ((info  url-current-mime-viewer) 	   ; All the MIME viewer info
+	 (view (cdr-safe (assoc "viewer" info))) ; How to view this file
+	 (url (url-view-url t))
+	 (fmt  (cdr-safe (assoc "nametemplate" info)))) ; Template for name
+    (cond
+     (fmt nil)
+     ((cdr-safe (assoc "type" info))
+      (setq fmt (mm-type-to-file (cdr-safe (assoc "type" info))))
+      (if fmt (setq fmt (concat "%s" (car fmt)))
+	(setq fmt (concat "%s" (url-file-extension url-current-file))))))
+    (if (null view)
+	(setq view 'indented-text-mode))
+    (cond
+     ((symbolp view)
+      (if (not (memq view '(w3-prepare-buffer w3-print w3-source
+					      w3-default-local-file
+					      mm-multipart-viewer)))
+	  (let ((bufnam (url-generate-new-buffer-name
+			 (file-name-nondirectory
+			  (or url-current-file "Unknown")))))
+	    (if (string= bufnam "")
+		(setq bufnam (url-generate-new-buffer-name
+			      (url-view-url t))))
+	    (rename-buffer bufnam)
+	    ;; Make the URL show in list-buffers output
+	    (make-local-variable 'list-buffers-directory)
+	    (setq list-buffers-directory (url-view-url t))
+	    (set-buffer-modified-p nil)
+	    (buffer-enable-undo)
+	    (funcall view)
+	    (w3-notify-when-ready bufnam))
+	(funcall view)))
+     ((stringp view)
+      (let ((fname (url-generate-unique-filename fmt)) proc)
+	(if (url-file-directly-accessible-p (url-view-url t))
+	    (make-symbolic-link url-current-file fname t)
+	  (if (featurep 'mule)
+	      (write-region (point-min) (point-max) fname nil nil *noconv*)
+	    (write-region (point-min) (point-max) fname)))
+	(if (get-buffer url-working-buffer)
+	    (kill-buffer url-working-buffer))
+	(if (string-match "%s" view)
+	    (setq view (concat (substring view 0 (match-beginning 0))
+			       fname (substring view (match-end 0)))))
+	(if (string-match "%u" view)
+	    (setq view (concat (substring view 0 (match-beginning 0))
+			       url
+			       (substring view (match-end 0)))))
+	(message "Passing to viewer %s " view)
+	(setq proc (w3-start-viewer fname view))
+	(set-process-filter proc 'w3-viewer-filter)
+	(set-process-sentinel proc 'w3-viewer-sentinel)))
+     ((listp view)
+      (set-buffer-modified-p nil)
+      (buffer-enable-undo)
+      (eval view))
+     (t
+      (message "Unknown viewer specified: %s" view)
+      (w3-notify-when-ready url-working-buffer)))))
+
+(defun w3-save-binary-file ()
+  "Save a buffer to disk - this is used when `w3-dump-to-disk' is non-nil"
+  (interactive)
+  (let ((x (read-file-name "Filename to save as: "
+			   (or mm-download-directory "~/")
+			   (concat (or mm-download-directory "~/")
+				   (url-basepath (or url-current-file "") t))
+			   nil
+			   (url-basepath (or url-current-file "") t)))
+        (require-final-newline nil))
+    (save-excursion
+      ;; more fixes from the MULE guys
+      (if w3-dump-to-disk
+	  (let (jka-compr-compression-info-list
+		jam-zcat-filename-list)
+	    (if (featurep 'mule)
+		(let ((mc-flag t))
+		  (write-file x *noconv*))
+	      (write-file x)))
+	(let ((fnha file-name-handler-alist)
+	      (file-name-handler-alist nil))
+	  (if (featurep 'mule)
+	      (let ((mc-flag t))
+		(write-file x *noconv*))
+	    (write-file x))))
+      (kill-buffer (current-buffer)))))
+
+(defun w3-build-url (protocol)
+  "Build a url for PROTOCOL, return it as a string"
+  (interactive (list (cdr (assoc (completing-read
+				  "Protocol: "
+				  w3-acceptable-protocols-alist nil t)
+				 w3-acceptable-protocols-alist))))
+  (let (user host port file)
+    (cond
+     ((null protocol) (error "Protocol is unknown to me!"))
+     ((string= protocol "news")
+      (setq host (read-string "Enter news server name, or blank for default: ")
+	    port (read-string "Enter port number, or blank for default: ")
+	    file (read-string "Newgroup name or Message-ID: ")))
+     ((string= protocol "mailto") (setq file (read-string "E-mail address: ")))
+     ((string= protocol "http")
+      (setq host (read-string "Enter server name: ")
+	    port (read-string "Enter port number, or blank for default: ")
+	    file (read-string "Remote file: "))
+      (and (string= "" port) (setq port nil))
+      (and (string= "" host) (error "Must specify a remote machine!")))
+     ((string= protocol "file")
+      (if (funcall url-confirmation-func "Local file?")
+	  (setq file (read-file-name "Local File: " nil nil t))
+	(setq user (read-string "Login as user (blank=anonymous): ")
+	      host (read-string "Remote machine name: "))
+	(and (string= user "") (setq user "anonymous"))
+	(and (string= host "") (error "Must specify a remote machine!"))
+	(setq file (read-file-name "File: " (format "/%s@%s:" user host)
+				   nil t)
+	      file (substring file (length (format "/%s@%s:" user host))))))
+     ((or (string= protocol "telnet")
+	  (string= protocol "tn3270"))
+      (setq user (read-string "Login as user (blank=none): ")
+	    host (read-string "Remote machine name: ")
+	    port (read-string "Port number (blank=23): "))
+      (and (string= "" port) (setq port nil))
+      (and (string= "" user) (setq user nil))
+      (and (string= "" host) (error "Must specify a host machine!")))
+     ((string= protocol "gopher")
+      (setq host (read-string "Enter server name: ")
+	    port (read-string "Enter port number, or blank for default: ")
+	    file (read-string "Remote file: "))
+      (and (string= "" port) (setq port nil))
+      (and (string= "" host) (error "Must specify a remote machine!"))))
+    (message "%s:%s%s"
+	     protocol
+	     (if (null host) "" (concat "//" host
+					(if (null port) "" (concat ":" port))))
+	     (if (= ?/ (string-to-char file)) file (concat "/" file)))))
+
+;;;###autoload
+(defun w3-open-local (fname)
+  "Find a local file, and interpret it as a hypertext document.
+It will prompt for an existing file or directory, and retrieve it as a
+hypertext document.  If it is a directory, and url-use-hypertext-dired
+is non-nil, then an HTML directory listing is created on the fly.
+Otherwise, dired-mode is used to visit the buffer."
+  (interactive "FLocal file: ")
+  (if (not w3-setup-done) (w3-do-setup))
+  (w3-fetch (concat "file:" fname)))
+
+;;;###autoload
+(defun w3-find-file (fname)
+  "Find a local file, and interpret it as a hypertext document.
+It will prompt for an existing file or directory, and retrieve it as a
+hypertext document.  If it is a directory, and url-use-hypertext-dired
+is non-nil, then an HTML directory listing is created on the fly.
+Otherwise, dired-mode is used to visit the buffer."
+  (interactive "FLocal file: ")
+  (w3-open-local fname))
+ 
+;;;###autoload
+(defun w3-fetch-other-frame (&optional url)
+  "Attempt to follow the hypertext reference under point in a new frame.
+With prefix-arg P, ignore viewers and dump the link straight
+to disk."
+  (interactive (list (w3-read-url-with-default)))
+  (cond
+   ((and (fboundp 'make-frame)
+	 (fboundp 'select-frame)
+	 (not (eq (device-type) 'tty)))
+    (let ((frm (make-frame)))
+      (select-frame frm)
+      (delete-other-windows)
+      (w3-fetch url)))
+   (t (w3-fetch url))))
+
+(defun w3-fetch-other-window (&optional url)
+  "Attempt to follow the hypertext reference under point in a new window.
+With prefix-arg P, ignore viewers and dump the link straight
+to disk."
+  (interactive (list (w3-read-url-with-default)))
+  (split-window)
+  (w3-fetch url))
+
+(defun w3-url-completion-function (string predicate function)
+  (if (not w3-setup-done) (w3-do-setup))
+  (cond
+   ((null function)
+    (cond
+     ((get 'url-gethash 'sysdep-defined-this)
+      ;; Cheat!  If we know that these are the sysdep-defined version
+      ;; of hashtables, they are an obarray.
+      (try-completion string url-global-history-hash-table predicate))
+     ((url-hashtablep url-global-history-hash-table)
+      (let ((list nil))
+	(url-maphash (function (lambda (key val)
+				 (setq list (cons (cons (symbol-name key) val)
+						  list))))
+		     url-global-history-hash-table)
+	(try-completion string (nreverse list) predicate)))
+     (t nil)))
+   ((eq function t)
+    (cond
+     ((get 'url-gethash 'sysdep-defined-this)
+      ;; Cheat!  If we know that these are the sysdep-defined version
+      ;; of hashtables, they are an obarray.
+      (all-completions string url-global-history-hash-table predicate))
+     ((url-hashtablep url-global-history-hash-table)
+      (let ((stub (concat "^" (regexp-quote string)))
+	    (retval nil))
+	(url-maphash
+	 (function
+	  (lambda (url time)
+	    (setq url (symbol-name url))
+	    (if (string-match stub url)
+		(setq retval (cons url retval)))))
+	 url-global-history-hash-table)
+	retval))
+     (t nil)))
+   ((eq function 'lambda)
+    (and (url-hashtablep url-global-history-hash-table)
+	 (url-gethash string url-global-history-hash-table)
+	 t))))
+
+(defun w3-read-url-with-default ()
+  (url-do-setup)
+  (let* ((completion-ignore-case t)
+	 (default
+	   (if (eq major-mode 'w3-mode)
+	       (if (and current-prefix-arg (w3-view-this-url t))
+		   (w3-view-this-url t)
+		 (url-view-url t))
+	     (url-get-url-at-point)))
+	 (url nil))
+    (if (not default)
+	(setq default "http://www."))
+    (setq url
+	  (completing-read "URL: "  'w3-url-completion-function
+			   nil nil default))
+    (if (string= url "")
+	(setq url (if (eq major-mode 'w3-mode)
+		      (if (and current-prefix-arg (w3-view-this-url t))
+			  (w3-view-this-url t)
+			(url-view-url t))
+		    (url-get-url-at-point))))
+    url))
+
+;;;###autoload
+(defun w3-fetch (&optional url)
+  "Retrieve a document over the World Wide Web.
+The World Wide Web is a global hypertext system started by CERN in
+Switzerland in 1991.
+
+The document should be specified by its fully specified
+Uniform Resource Locator.  The document will be parsed, printed, or
+passed to an external viewer as appropriate.  Variable
+`mm-mime-info' specifies viewers for particular file types."
+  (interactive (list (w3-read-url-with-default)))
+  (if (not w3-setup-done) (w3-do-setup))
+  (if (boundp 'w3-working-buffer)
+      (setq w3-working-buffer url-working-buffer))
+  (if (and (boundp 'command-line-args-left)
+	   command-line-args-left
+	   (string-match url-nonrelative-link (car command-line-args-left)))
+      (setq url (car command-line-args-left)
+	    command-line-args-left (cdr command-line-args-left)))
+  (if (equal url "") (error "No document specified!"))
+  ;; legal use for relative URLs ?
+  (if (string-match "^www:[^/].*" url)
+      (setq url (concat (file-name-directory url-current-file)
+ 			(substring url 4))))
+  ;; In the common case, this is probably cheaper than searching.
+  (while (= (string-to-char url) ? )
+    (setq url (substring url 1)))
+  (cond
+   ((= (string-to-char url) ?#)
+    (w3-relative-link url))
+   ((or (and (interactive-p) current-prefix-arg) w3-dump-to-disk)
+    (w3-download-url url))
+   (t
+    (let ((x (url-view-url t))
+	  (lastbuf (current-buffer))
+	  (buf (url-buffer-visiting url)))
+      (and x (or (string= "file:nil" x) (string= "" x))
+	   (setq x nil))
+      (if (or (not buf)
+	      (cond
+	       ((not (equal (downcase (or url-request-method "GET")) "get")) t)
+	       ((memq w3-reuse-buffers '(no never reload)) t)
+	       ((memq w3-reuse-buffers '(yes reuse always)) nil)
+	       (t
+		(if (and w3-reuse-buffers (not (eq w3-reuse-buffers 'ask)))
+		    (progn
+		      (ding)
+		      (message
+		       "Warning: Invalid value for variable w3-reuse-buffers: %s"
+		       (prin1-to-string w3-reuse-buffers))
+		      (sit-for 2)))
+		(not (funcall url-confirmation-func
+			      (format "Reuse URL in buffer %s? "
+				      (buffer-name buf)))))))
+	  (let ((cached (url-retrieve url)))
+	    (if w3-track-last-buffer
+		(setq w3-last-buffer (get-buffer url-working-buffer)))
+	    (if (get-buffer url-working-buffer)
+		(cond
+		 ((and url-be-asynchronous (string-match "^http:" url)
+		       (not cached))
+		  (save-excursion
+		    (set-buffer url-working-buffer)
+		    (if x
+			(w3-add-urls-to-history x (url-view-url t)))
+		    (setq w3-current-last-buffer lastbuf)))
+		 (t
+		  (w3-add-urls-to-history x url)
+		  (w3-sentinel lastbuf)))))
+	(if w3-track-last-buffer
+	    (setq w3-last-buffer buf))
+	(let ((w3-notify (if (memq w3-notify '(newframe bully aggressive))
+			     w3-notify
+			   'aggressive)))
+	  (w3-notify-when-ready buf))
+	(if (string-match "#\\(.*\\)" url)
+	    (progn
+	      (push-mark (point) t)
+	      (w3-find-specific-link (url-match url 1))))
+	(message "Reusing URL.  To reload, type %s."
+		 (substitute-command-keys "\\[w3-reload-document]")))))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; History for forward/back buttons
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defvar w3-node-history nil "History for forward and backward jumping")
+
+(defun w3-plot-course ()
+  "Show a map of where the user has been in this session of W3. !!!!NYI!!!"
+  (interactive)
+  (error "Sorry, w3-plot-course is not yet implemented."))
+
+(defun w3-forward-in-history ()
+  "Go forward in the history from this page"
+  (interactive)
+  (let* ((thisurl (url-view-url t))
+	 (node (assoc (if (string= "" thisurl) (current-buffer) thisurl)
+		      w3-node-history))
+	 (url (cdr node))
+	 (w3-reuse-buffers 'yes))
+    (cond
+     ((null url) (error "No forward found for %s" thisurl))
+     ((and (bufferp url) (buffer-name url))
+      (switch-to-buffer url))
+     ((stringp url)
+      (w3-fetch url))
+     ((bufferp url)
+      (setq w3-node-history (delete node w3-node-history))
+      (error "Killed buffer in history, removed."))
+     (t
+      (error "Something is very wrong with the history!")))))
+
+(defun w3-backward-in-history ()
+  "Go backward in the history from this page"
+  (interactive)
+  (let* ((thisurl (url-view-url t))
+	 (node (rassoc (if (string= thisurl "") (current-buffer) thisurl)
+			  w3-node-history))
+	 (url (car node))
+	 (w3-reuse-buffers 'yes))
+    (cond
+     ((null url) (error "No backward found for %s" thisurl))
+     ((and (bufferp url) (buffer-name url))
+      (switch-to-buffer url))
+     ((stringp url)
+      (w3-fetch url))
+     ((bufferp url)
+      (setq w3-node-history (delete node w3-node-history))
+      (error "Killed buffer in history, removed."))
+     (t
+      (error "Something is very wrong with the history!")))))
+
+(defun w3-add-urls-to-history (referer url)
+  "REFERER is the url we followed this link from.  URL is the link we got to."
+  (let ((node (assoc referer w3-node-history)))
+    (if node
+	(setcdr node url)
+      (setq w3-node-history (cons (cons referer url) w3-node-history)))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Miscellaneous functions
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defun w3-describe-entities ()
+  "Show an DTD fragment listing all the entities currently defined."
+  (interactive)
+  (switch-to-buffer (get-buffer-create "W3 Entities"))
+  (let ((buffer-file-name (concat (make-temp-name "entities") ".dtd")))
+    (set-auto-mode))
+  (erase-buffer)
+  (let (entity)
+    (mapatoms
+     (function
+      (lambda (x)
+	(setq entity (get x 'html-entity-expansion))
+	(if entity
+	    (insert (format "<!entity %s %s \"%s\">\n" x (car entity)
+			    (cdr entity))))))))
+  (goto-char (point-min)))
+
+(defun w3-executable-exists-in-path (exec &optional path)
+  (let ((paths (if (consp path)
+		   path
+		 (mm-string-to-tokens (or path
+					  (getenv "PATH")
+					  (concat
+					   "/usr/bin:/bin:/usr/local/bin:"
+					   "/usr/bin/X11:"
+					   (expand-file-name "~/bin"))) ?:)))
+	(done nil))
+    (while (and paths (not done))
+      (if (file-exists-p (expand-file-name exec (car paths)))
+	  (setq done t))
+      (setq paths (cdr paths)))
+    done))
+
+(defun w3-document-information (&optional buff)
+  "Display information on the document in buffer BUFF"
+  (interactive)
+  (if (interactive-p)
+      (let ((w3-notify 'friendly))
+	(if (get-buffer "Document Information")
+	    (kill-buffer (get-buffer "Document Information")))
+	(w3-fetch "about:document"))
+    (setq buff (or buff (current-buffer)))
+    (save-excursion
+      (set-buffer buff)
+      (let* ((url (url-view-url t))
+	     (cur-links w3-current-links)
+	     (title (buffer-name))
+	     (lastmod (or (cdr-safe (assoc "last-modified"
+					   url-current-mime-headers))
+			  (and (member url-current-type '("file" "ftp"))
+			       (nth 5 (url-file-attributes url)))))
+	     (hdrs url-current-mime-headers))
+	(set-buffer (get-buffer-create url-working-buffer))
+	(setq url-current-can-be-cached nil
+	      url-current-type "about"
+	      url-current-file "document")
+	(erase-buffer)
+	(cond
+	 ((stringp lastmod) nil)
+	 ((equal '(0 . 0) lastmod) (setq lastmod nil))
+	 ((consp lastmod) (setq lastmod (current-time-string lastmod)))
+	 (t (setq lastmod nil)))
+	(insert "<html>\n"
+		" <head>\n"
+		"  <title>Document Information</title>\n"
+		" </head>\n"
+		" <body\n"
+		"  <h1 align=\"center\">Document Information</h1>\n"
+		"  <hr>\n"
+		"  <pre>\n"
+		"           Title: " title "\n"
+		"        Location: " url "\n"
+		"   Last Modified: " (or lastmod "None Given") "\n"
+		"  </pre>\n")
+	(if hdrs
+	    (let* ((maxlength (car (sort (mapcar (function (lambda (x)
+							     (length (car x))))
+						 hdrs)
+					 '>)))
+		   (fmtstring (format "%%%ds: %%s" maxlength)))
+	      (insert "  <hr label=\" MetaInformation \" textalign=\"left\">\n"
+		      "  <pre>\n"
+		      (mapconcat
+		       (function
+			(lambda (x)
+			  (if (/= (length (car x)) 0)
+			      (format fmtstring
+				      (capitalize (car x))
+				      (if (numberp (cdr x))
+					  (int-to-string (cdr x))
+					(cdr x))))))
+		       (sort hdrs
+			     (function
+			      (lambda (x y) (string-lessp (car x) (car y)))))
+		       "\n")
+		      "  </pre>\n")))
+	(if cur-links
+	    (while cur-links
+	      (let* ((tmp (car cur-links))
+		     (label (car tmp))
+		     (nodes (cdr tmp))
+		     (links nil)
+		     (maxlength (car (sort (mapcar
+					    (function (lambda (x)
+							(length (car x))))
+						   nodes)
+					   '>)))
+		     (fmtstring (format "%%%ds: %%s" maxlength)))
+		(insert "  \n"
+			"  <hr width=\"50%\" label=\" "
+			label " \" align=\"left\" textalign=\"left\">\n"
+			"  <pre>\n")
+		(while nodes
+		  (setq label (car (car nodes))
+			links (cdr (car nodes))
+			nodes (cdr nodes))
+		  (while links
+		    (insert (format "  %15s -- <a href=\"%s\">%s</a>\n"
+				    label (car links) (car links)))
+		    (setq links (cdr links)
+			  label "")))
+		(insert "  </pre>\n"))
+	      (setq cur-links (cdr cur-links))))
+	(insert " </body>\n"
+		"</html>\n")))))
+
+(defun w3-truncate-menu-item (string)
+  (if (<= (length string) w3-max-menu-width)
+      string
+    (concat (substring string 0 w3-max-menu-width) "$")))
+
+(defun w3-use-starting-documents ()
+  "Use the list of predefined starting documents from w3-starting-documents"
+  (interactive)
+  (let ((w3-hotlist w3-starting-documents))
+    (w3-use-hotlist)))
+
+(defun w3-show-starting-documents ()
+  "Show the list of predefined starting documents from w3-starting-documents"
+  (interactive)
+  (if (not w3-setup-done) (w3-do-setup))
+  (w3-fetch "www://auto/starting-points"))
+
+(defun w3-insert-formatted-url (p)
+  "Insert a formatted url into a buffer.  With prefix arg, insert the url
+under point."
+  (interactive "P")
+  (let (buff str)
+    (cond
+     (p
+      (setq p (widget-at (point)))
+      (or p (error "No url under point"))
+      (setq str (format "<A HREF=\"%s\">%s</A>" (widget-get p 'href)
+			(read-string "Link text: "
+				     (buffer-substring
+				      (car (widget-get p 'title))
+				      (cdr (widget-get p 'title)))))))
+     (t
+      (setq str (format "<A HREF=\"%s\">%s</A>" (url-view-url t)
+			(read-string "Link text: " (buffer-name))))))
+    (setq buff (read-buffer "Insert into buffer: " nil t))
+    (if buff
+	(save-excursion
+	  (set-buffer buff)
+	  (insert str))
+      (message "Cancelled."))))
+
+(defun w3-first-n-items (l n)
+  "Return the first N items from list L"
+  (let ((x 0)
+	y)
+    (if (> n (length l))
+	(setq y l)
+      (while (< x n)
+	(setq y (nconc y (list (nth x l)))
+	      x (1+ x))))
+    y))
+
+(defun w3-widget-button-press ()
+  (interactive)
+  (if (widget-at (point))
+      (widget-button-press (point))))
+
+(defun w3-widget-button-click (e)
+  (interactive "@e")
+  (if (widget-at (event-point e))
+      (widget-button-click e)))
+   
+(defun w3-breakup-menu (menu-desc max-len)
+  (if (> (length menu-desc) max-len)
+      (cons (cons "More..." (w3-first-n-items menu-desc max-len))
+	    (w3-breakup-menu (nthcdr max-len menu-desc) max-len))
+    menu-desc))
+
+;;;###autoload
+(defun w3-maybe-follow-link-mouse (e)
+  "Maybe follow a hypertext link under point.
+If there is no link under point, this will try using
+url-get-url-at-point"
+  (interactive "e")
+  (save-excursion
+    (mouse-set-point e)
+    (w3-maybe-follow-link)))
+
+;;;###autoload
+(defun w3-maybe-follow-link ()
+  "Maybe follow a hypertext link under point.
+If there is no link under point, this will try using
+url-get-url-at-point"
+  (interactive)
+  (require 'w3)
+  (if (not w3-setup-done) (w3-do-setup))
+  (let* ((widget (widget-at (point)))
+         (url1 (and widget (widget-get widget 'href)))
+         (url2 (url-get-url-at-point)))
+    (cond
+      (url1 (w3-follow-link))
+      ((and url2 (string-match url-nonrelative-link url2)) (w3-fetch url2))
+      (t (message "No URL could be found!")))))
+
+;;;###autoload
+(defun w3-follow-url-at-point-other-frame (&optional pt)
+  "Follow the URL under PT, defaults to link under (point)"
+  (interactive "d")
+  (let ((url (url-get-url-at-point pt)))
+    (and url (w3-fetch-other-frame url))))
+
+;;;###autoload
+(defun w3-follow-url-at-point (&optional pt)
+  "Follow the URL under PT, defaults to link under (point)"
+  (interactive "d")
+  (let ((url (url-get-url-at-point pt)))
+    (and url (w3-fetch url))))
+
+;;;###autoload
+(defun w3-batch-fetch ()
+  "Fetch all the URLs on the command line and save them to files in
+the current directory.  The first argument after the -f w3-batch-fetch
+on the command line should be a string specifying how to save the
+information retrieved.  If it is \"html\", then the page will be
+unformatted when it is written to disk.  If it is \"text\", then the
+page will be formatted before it is written to disk.  If it is
+\"binary\" it will not mess with the file extensions, and just save
+the data in raw binary format.  If none of those, the default is
+\"text\", and the first argument is treated as a normal URL."
+  (if (not w3-setup-done) (w3-do-setup))
+  (if (not noninteractive)
+      (error "`w3-batch-fetch' is to be used only with -batch"))
+  (let ((fname "")
+        (curname "")
+	(x 0)
+	(args command-line-args-left)
+	(w3-strict-width 80)
+	(w3-delimit-emphasis nil)
+	(w3-delimit-links nil)
+	(retrieval-function 'w3-fetch)
+	(file-format "text")
+	(header "")
+	(file-extn ".txt"))
+    (setq file-format (downcase (car args)))
+    (cond
+     ((string= file-format "html")
+      (message "Saving all text as raw HTML...")
+      (setq retrieval-function 'url-retrieve
+	    file-extn ".html"
+	    header "<BASE HREF=\"%s\">"
+	    args (cdr args)))
+     ((string= file-format "binary")
+      (message "Saving as raw binary...")
+      (setq retrieval-function 'url-retrieve
+	    file-extn ""
+	    args (cdr args)))
+     ((string= file-format "text")
+      (setq header "Text from: %s\n---------------\n")
+      (message "Saving all text as formatted...")
+      (setq args (cdr args)))
+     (t
+      (setq header "Text from: %s\n---------------\n")
+      (message "Going with default, saving all text as formatted...")))
+    (while args
+      (funcall retrieval-function (car args))
+      (goto-char (point-min))
+      (if buffer-read-only (toggle-read-only))
+      (insert (format header (car args)))
+      (setq fname (url-basepath url-current-file t))
+      (if (string= file-extn "") nil
+	(setq fname (url-file-extension fname t)))
+      (if (string= (url-strip-leading-spaces fname) "")
+	  (setq fname "root"))
+      (setq curname fname)
+      (while (file-exists-p (concat curname file-extn))
+	(setq curname (concat fname x)
+	      x (1+ x)))
+      (setq fname (concat curname file-extn))
+      (write-region (point-min) (point-max) fname)
+      (setq args (cdr args)))))
+
+(defun w3-fix-spaces (x)
+  "Remove spaces/tabs at the beginning of a string,
+and convert newlines into spaces."
+  (url-convert-newlines-to-spaces
+   (url-strip-leading-spaces
+    (url-eat-trailing-space x))))
+
+(defun w3-reload-all-files ()
+  "Reload all w3 files"
+  (interactive)
+  (setq w3-setup-done nil
+	url-setup-done nil
+	w3-hotlist nil
+	url-mime-accept-string nil)
+  (let ((x '(w3 w3-mule w3-e19 w3-xem20 mm url w3-xemac w3-toolbar font)))
+    (while x
+      (setq features (delq (car x) features)
+	    x (cdr x)))
+    (require 'w3))
+  (w3-do-setup)
+  (url-do-setup)
+  )
+
+(defun w3-source-document-at-point ()
+  "View source to the document pointed at by link under point"
+  (interactive)
+  (w3-source-document t))
+
+(defun w3-my-safe-copy-face (old new locale)
+  (let ((fore (face-foreground old))
+	(back (face-background old))
+	(bpxm (face-background-pixmap old))
+	(font (face-font old))
+	(font-spec (get old 'font-specification)))
+    (if (color-specifier-p fore)
+	(setq fore (color-name fore)))
+    (if (color-specifier-p back)
+	(setq back (color-name back)))
+    (if (font-specifier-p font)
+	(setq font (font-name font)))
+    (and fore (set-face-foreground new fore locale))
+    (and back (set-face-background new back locale))
+    (and bpxm (set-face-background-pixmap new bpxm locale))
+    (and (or font-spec font) (set-face-font new (or font-spec font) locale))
+    new))
+
+(defun w3-source-document (under)
+  "View this document's source"
+  (interactive "P")
+  (let* ((url (if under (w3-view-this-url) (url-view-url t)))
+	 (fil (if under nil url-current-file))
+	 (tag '$html-source)		; For the stylesheet info
+	 (args nil)			; For the stylesheet info
+	 (face nil)			; For the stylesheet info
+	 (src
+	  (cond
+	   ((or (null url) (string= url "file:nil"))
+	    (error "Not a w3 buffer!"))
+	   ((and under (null url)) (error "No link at point!"))
+	   ((and (not under) (equal url-current-mime-type "text/plain"))
+	    (buffer-string))
+	   ((and (not under) w3-current-source) w3-current-source)
+	   (t
+	    (prog2
+		(url-retrieve url)
+		(buffer-string)
+	      (setq fil (or fil url-current-file))
+	      (kill-buffer (current-buffer))))))
+	 (tmp (url-generate-new-buffer-name url)))
+    (if (and url (get-buffer url))
+	(cond
+	 ((memq w3-reuse-buffers '(no never reload))
+	  (kill-buffer url))
+	 ((memq w3-reuse-buffers '(yes reuse always))
+	  (w3-notify-when-ready (get-buffer url))
+	  (setq url nil))
+	 ((funcall url-confirmation-func
+		   (concat "Source for " url " found, reuse? "))
+	  (w3-notify-when-ready (get-buffer url)))))
+    (if (not url) nil
+      (setq face (and w3-current-stylesheet (cdr (w3-face-for-element))))
+      (set-buffer (get-buffer-create tmp))
+      (insert src)
+      (put-text-property (point-min) (point-max) 'face face)
+      (put-text-property (point-min) (point-max) 'w3-base url)
+      (goto-char (point-min))
+      (setq buffer-file-truename nil
+	    buffer-file-name nil)
+      ;; Null filename bugs `set-auto-mode' in Mule ... 
+      (if (not (featurep 'mule))
+ 	  (set-auto-mode))
+      (buffer-enable-undo)
+      (set-buffer-modified-p nil)
+      (w3-notify-when-ready (get-buffer tmp))))
+  (run-hooks 'w3-source-file-hook))
+
+(defun w3-mail-document-under-point ()
+  "Mail the document pointed to by the hyperlink under point."
+  (interactive)
+  (w3-mail-current-document t))
+
+(defun w3-mail-current-document (under &optional format)
+  "Mail the current-document to someone"
+  (interactive "P")
+  (let* ((completion-ignore-case t)
+	 (format (or format
+		     (completing-read
+		      "Format: "
+		      '(("HTML Source")
+			("Formatted Text")
+			("PostScript")
+			("LaTeX Source")
+			)
+		  nil t)))
+	 (url (cond
+	       ((stringp under) under)
+	       (under (w3-view-this-url t))
+	       (t (url-view-url t))))
+	 (content-type "text/plain; charset=iso-8859-1")
+	 (str
+	  (save-excursion
+	    (cond
+	     ((and (equal "HTML Source" format) under)
+	      (setq content-type "text/html; charset=iso-8859-1")
+	      (let ((url-source t))
+		(url-retrieve url)))
+	     ((equal "HTML Source" format)
+	      (setq content-type "text/html; charset=iso-8859-1")
+	      (if w3-current-source
+		  (let ((x w3-current-source))
+		    (set-buffer (get-buffer-create url-working-buffer))
+		    (erase-buffer)
+		    (insert x))
+		(url-retrieve url)))
+	     ((and under (equal "PostScript" format))
+	      (setq content-type "application/postscript")
+	      (w3-fetch url)
+	      (let ((ps-spool-buffer-name " *w3-temp*"))
+		(if (get-buffer ps-spool-buffer-name)
+		    (kill-buffer ps-spool-buffer-name))
+		(w3-print-with-ps-print (current-buffer)
+					'ps-spool-buffer-with-faces)
+		(set-buffer ps-spool-buffer-name)))
+	     ((equal "PostScript" format)
+	      (let ((ps-spool-buffer-name " *w3-temp*"))
+		(if (get-buffer ps-spool-buffer-name)
+		    (kill-buffer ps-spool-buffer-name))
+		(setq content-type "application/postscript")
+		(w3-print-with-ps-print (current-buffer)
+					'ps-spool-buffer-with-faces)
+		(set-buffer ps-spool-buffer-name)))
+	     ((and under (equal "Formatted Text" format))
+	      (setq content-type "text/plain; charset=iso-8859-1")
+	      (w3-fetch url))
+	     ((equal "Formatted Text" format)
+	      (setq content-type "text/plain; charset=iso-8859-1"))
+	     ((and under (equal "LaTeX Source" format))
+	      (let ((old-asynch url-be-asynchronous))
+		(setq content-type "application/x-latex; charset=iso-8859-1")
+		(setq-default url-be-asynchronous nil)
+		(url-retrieve url)
+		(setq-default url-be-asynchronous old-asynch)
+		(w3-parse-tree-to-latex (w3-parse-buffer (current-buffer) t)
+					url)))
+	     ((equal "LaTeX Source" format)
+	      (setq content-type "application/x-latex; charset=iso-8859-1")
+	      (w3-parse-tree-to-latex w3-current-parse url)))
+	    (buffer-string))))
+    (cond
+     ((and w3-mutable-windows (fboundp w3-mail-other-window-command))
+      (funcall w3-mail-other-window-command))
+     ((fboundp w3-mail-command)
+      (funcall w3-mail-command))
+     (w3-mutable-windows (mail-other-window))
+     (t (mail)))
+    (mail-subject)
+    (insert format " from URL " url "\n"
+	    "Mime-Version: 1.0\n"
+	    "Content-transfer-encoding: 8bit\n"
+	    "Content-type: " content-type)
+
+    (re-search-forward mail-header-separator nil)
+    (forward-char 1)
+    (insert (if (equal "HTML Source" format)
+		(format "<BASE HREF=\"%s\">" url) "")
+	    str)
+    (mail-to)))
+
+(defun w3-internal-use-history (hist-item)
+  ;; Go to the link in the history
+  (let ((url (nth 0 hist-item))
+	(buf (nth 1 hist-item))
+	(pnt (nth 2 hist-item)))
+    (cond
+     ((null buf)			; Find a buffer with same url
+      (let ((x (buffer-list))
+	    (found nil))
+	(while (and x (not found))
+	  (save-excursion
+	    (set-buffer (car x))
+	    (setq found (string= (url-view-url t) url))
+	    (if (not found) (setq x (cdr x)))))
+	(cond
+	 (found
+	  (switch-to-buffer (car x))
+	  (if (number-or-marker-p pnt) (goto-char pnt)))
+	 (t
+	  (w3-fetch url)))))
+     ((buffer-name buf)			; Reuse the old buffer if possible
+      (switch-to-buffer buf)
+      (if (number-or-marker-p pnt) (goto-char pnt))
+      (if (and url (= ?# (string-to-char url)))	; Destination link
+	  (progn
+	    (goto-char (point-min))
+	    (w3-find-specific-link (substring url 1 nil)))))
+     (url (url-maybe-relative url))		; Get the link
+     (t (message "Couldn't understand whats in the history.")))))
+
+(defun w3-relative-link (url)
+  (if (equal "#" (substring url 0 1))
+      (progn
+	(push-mark (point) t)
+	(goto-char (point-min))
+	(w3-find-specific-link (substring url 1 nil)))
+    (w3-fetch (url-expand-file-name url))))
+
+(defun w3-maybe-eval ()
+  ;; Maybe evaluate a buffer of emacs lisp code
+  (if (funcall url-confirmation-func "This is emacs-lisp code, evaluate it?")
+      (eval-buffer (current-buffer))
+    (emacs-lisp-mode)))
+
+(defun w3-build-continuation ()
+  ;; Build a series of functions to be run on this file
+  (save-excursion
+    (set-buffer url-working-buffer)
+    (let ((cont w3-default-continuation)
+	  (extn (url-file-extension url-current-file)))
+      (if (assoc extn url-uncompressor-alist)
+	  (setq extn (url-file-extension
+		      (substring url-current-file 0 (- (length extn))))))
+      (if w3-source
+	  (setq url-current-mime-viewer '(("viewer" . w3-source))))
+      (if (not url-current-mime-viewer)
+	  (setq url-current-mime-viewer
+		(mm-mime-info (or url-current-mime-type
+				  (mm-extension-to-mime extn)) nil 5)))
+      (if url-current-mime-viewer
+	  (setq cont (append cont '(w3-pass-to-viewer)))
+	(setq cont (append cont (list w3-default-action))))
+      cont)))
+
+(defun w3-use-links ()
+  "Select one of the <LINK> tags from this document and fetch it."
+  (interactive)
+  (and (not w3-current-links)
+       (error "No links defined for this document."))
+  (w3-fetch "about:document"))
+
+(defun w3-find-this-file ()
+  "Do a find-file on the currently viewed html document if it is a file: or
+ftp: reference"
+  (interactive)
+  (cond
+   ((and (or (null url-current-type) (equal url-current-type "file"))
+	 (eq major-mode 'w3-mode))
+    (if w3-mutable-windows
+	(find-file-other-window url-current-file)
+      (find-file url-current-file)))
+   ((equal url-current-type "ftp")
+    (if w3-mutable-windows
+	(find-file-other-window
+	 (format "/%s@%s:%s" url-current-user url-current-server
+		 url-current-file))
+      (find-file
+       (format "/%s@%s:%s" url-current-user url-current-server
+	       url-current-file))))
+   (t (message "Sorry, I can't get that file so you can alter it."))))
+
+(defun w3-insert-this-url (pref-arg)
+  "Insert the current url in another buffer, with prefix ARG,
+insert URL under point"
+  (interactive "P")
+  (let ((thebuf (get-buffer (read-buffer "Insert into buffer: ")))
+	(oldbuf (current-buffer))
+	(url (if pref-arg (w3-view-this-url t) (url-view-url t))))
+    (if (and url (not (equal "Not on a link!" url)))
+	(progn
+	  (set-buffer thebuf)
+	  (insert url)
+	  (set-buffer oldbuf))
+      (message "Not on a link!"))))
+
+(defun w3-show-hotlist ()
+  "View the hotlist in hypertext form"
+  (interactive)
+  (if (not w3-setup-done) (w3-do-setup))
+  (if (not w3-hotlist)
+      (error "Sorry, no hotlist is in memory.")
+    (let ((x (url-buffer-visiting "www:/auto/hotlist")))
+      (while x
+	(kill-buffer x)
+	(setq x (url-buffer-visiting "www:/auto/hotlist"))))
+    (w3-fetch "www://auto/hotlist")))
+
+(defun url-maybe-relative (url)
+  "Take a url and either fetch it, or resolve relative refs, then fetch it"
+  (cond
+   ((not
+     (string-match url-nonrelative-link url))
+    (w3-relative-link url))
+   (t (w3-fetch url))))
+
+(defun w3-in-assoc (elt list)
+  "Check to see if ELT matches any of the regexps in the car elements of LIST"
+  (let (rslt)
+    (while (and list (not rslt))
+      (and (car (car list))
+	   (stringp (car (car list)))
+	   (not (string= (car (car list)) ""))
+	   (string-match (car (car list)) elt)
+	   (setq rslt (car list)))
+      (setq list (cdr list)))
+    rslt))
+
+(defun w3-goto-last-buffer ()
+  "Go to last WWW buffer visited"
+  (interactive)
+  (if w3-current-last-buffer
+      (w3-notify-when-ready w3-current-last-buffer)
+    (message "No previous buffer found.")))
+
+(fset 'w3-replace-regexp 'url-replace-regexp)
+
+;;;###autoload
+(defun w3-preview-this-buffer ()
+  "See what this buffer will look like when its formatted as HTML.
+HTML is the HyperText Markup Language used by the World Wide Web to
+specify formatting for text.  More information on HTML can be found at
+ftp.w3.org:/pub/www/doc."
+  (interactive)
+  (w3-fetch (concat "www://preview/" (buffer-name))))
+
+(defun w3-edit-source ()
+  "Edit the html document just retrieved"
+  (set-buffer url-working-buffer)
+  (let ((ttl (format "Editing %s Annotation: %s"
+		     (cond
+		      ((eq w3-editing-annotation 'group) "Group")
+		      ((eq w3-editing-annotation 'personal) "Personal")
+		      (t "Unknown"))
+		     (url-basepath url-current-file t)))
+	(str (buffer-string)))
+    (set-buffer (get-buffer-create ttl))
+    (insert str)
+    (kill-buffer url-working-buffer)))
+
+(defun w3-source ()
+  "Show the source of a file"
+  (let ((tmp (buffer-name (generate-new-buffer "Document Source"))))
+    (set-buffer url-working-buffer)
+    (kill-buffer tmp)
+    (rename-buffer tmp)
+    ;; Make the URL show in list-buffers output
+    (make-local-variable 'list-buffers-directory)
+    (setq list-buffers-directory (url-view-url t))
+    (set-buffer-modified-p nil)
+    (buffer-enable-undo)
+    (w3-notify-when-ready (get-buffer tmp))))
+
+(defun w3-sentinel (&optional proc string)
+  (set-buffer url-working-buffer)
+  (if (or (stringp proc)
+	  (bufferp proc)) (setq w3-current-last-buffer proc))
+  (if (boundp 'after-change-functions)
+      (remove-hook 'after-change-functions 'url-after-change-function))
+  (if url-be-asynchronous
+      (progn
+	(url-clean-text)
+	(cond
+	 ((not (get-buffer url-working-buffer)) nil)
+	 ((url-mime-response-p) (url-parse-mime-headers)))
+	(if (not url-current-mime-type)
+	    (setq url-current-mime-type (or (mm-extension-to-mime
+					     (url-file-extension
+					      url-current-file))
+					    "text/html")))))
+  (let ((x (w3-build-continuation))
+	(done-mule-conversion nil))
+    (while x
+      (if (and (featurep 'mule) (not (eq 'url-uncompress (car x)))
+	       (not done-mule-conversion))
+	  (progn
+            (if (string-match "^www:" (url-view-url t))
+                (setq w3-mime-list-for-code-conversion nil))
+	    (w3-convert-code-for-mule url-current-mime-type)
+	    (setq done-mule-conversion t)))
+      (funcall (car x))
+      (setq x (cdr x)))))
+
+(defun w3-show-history-list ()
+  "Format the url-history-list prettily and show it to the user"
+  (interactive)
+  (w3-fetch "www://auto/history"))
+
+(defun w3-save-as (&optional type)
+  "Save a document to the local disk"
+  (interactive)
+  (let* ((completion-ignore-case t)
+	 (format (or type (completing-read
+			   "Format: "
+			   '(("HTML Source") ("Formatted Text")
+			     ("LaTeX Source") ("Binary"))
+			   nil t)))
+	(fname (expand-file-name
+		(read-file-name "File name: " default-directory)))
+	(url (url-view-url t)))
+    (cond
+     ((equal "Binary" format)
+      (if (not w3-current-source)
+	  (let ((url-be-asynchronous nil))
+	    (url-retrieve url))))
+     ((equal "HTML Source" format)
+      (if (not w3-current-source)
+	  (let ((url-be-asynchronous nil))
+	    (url-retrieve url))		; Get the document if necessary
+	(let ((txt w3-current-source))
+	  (set-buffer (get-buffer-create url-working-buffer))
+	  (insert txt)))
+      (goto-char (point-min))
+      (insert (format "<BASE HREF=\"%s\">\n" url)))
+     ((or (equal "Formatted Text" format)
+	  (equal "" format))
+      nil)				; Do nothing - we have the text already
+     ((equal "LaTeX Source" format)
+      (w3-parse-tree-to-latex w3-current-parse url)
+      (insert-buffer url-working-buffer)))
+    (write-region (point-min) (point-max) fname)))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Functions to parse out <A> tags and replace it with a hyperlink zone
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defun w3-popup-image-info (url)
+  (interactive)
+  (let* ((glyph (cdr-safe (assoc url w3-graphics-list)))
+       image w h d info)
+    (save-excursion
+      (if (or (not glyph) (not (glyphp glyph)))
+        (error "No information available."))
+      (setq image (glyph-image-instance glyph))
+      (if (or (not image) (not (image-instance-p image)))
+        (error "No information available."))
+      (setq w (glyph-width glyph)
+          h (glyph-height glyph)
+          d (image-instance-depth image)
+          info (url-popup-info url)
+          )
+      (set-buffer (get-buffer-create "*Image Info*"))
+      (erase-buffer)
+      (insert
+       "Information for: " url "\n"
+       (make-string (1- (window-width)) ?-)
+       (format "\n%-20s: %s\n" "Type" (image-instance-type image))
+       (format "%-20s: %d x %d\n" "Dimensions" w h)
+       (format "%-20s: %d-bit\n" "Color" d))
+      (set-extent-begin-glyph (make-extent (point) (point)) glyph)
+      (insert
+       "\n"
+       (make-string (1- (window-width)) ?-)
+       (or info ""))
+      (display-buffer (current-buffer) t))))
+               
+(defun w3-popup-info (&optional url)
+  "Show information about the link under point. (All SGML attributes)"
+  (interactive (list (w3-read-url-with-default)))
+  (let (dat widget)
+    (if (interactive-p)
+	nil
+      (setq widget (widget-at (point))
+	    dat (and widget (widget-get widget 'attributes))))
+    (if url
+	(save-excursion
+	  (set-buffer (get-buffer-create "*Header Info*"))
+	  (erase-buffer)
+	  (insert "URL: " url "\n" (make-string (1- (window-width)) ?-) "\n")
+	  (if (and dat (listp dat))
+	      (insert
+	       "Link attributes:\n"
+	       (make-string (1- (window-width)) ?-) "\n"
+	       (mapconcat
+		(function
+		 (lambda (info)
+		   (format "%20s :== %s" (car info) (or (cdr info) "On"))))
+		dat "\n")
+	       "\n" (make-string (1- (window-width)) ?-) "\n"))
+	  (insert (save-excursion (url-popup-info url)))
+	  (goto-char (point-min))
+	  (display-buffer (current-buffer) t))
+      (message "No URL to get information on!"))))
+
+(fset 'w3-document-information-this-url 'w3-popup-info)
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Functions for logging of bad HTML
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defun w3-reconstruct-tag (tagname desc)
+  (concat "<" tagname " "
+	  (mapconcat
+	   (function (lambda (x)
+		       (if (cdr x)
+			   (concat (car x) "=\"" (cdr x) "\"")
+			 (car x)))) desc " ") ">"))
+
+(defun w3-debug-if-found (regexp type desc)
+  (and w3-debug-html
+       (save-excursion
+	 (if (re-search-forward regexp nil t)
+	     (w3-log-bad-html type desc)))))
+
+(defun w3-log-bad-html (type desc)
+  ;; Log bad HTML to the buffer specified by w3-debug-buffer
+  (if w3-debug-html
+      (save-excursion
+	(set-buffer (get-buffer-create w3-debug-buffer))
+	(goto-char (point-max))
+	(insert (make-string (1- (window-width)) w3-horizontal-rule-char) "\n")
+	(cond
+	 ((stringp type) (insert type "\n" desc "\n"))
+	 ((eq type 'bad-quote)
+	  (insert "Unterminated quoting character in SGML attribute value.\n"
+		  desc "\n"))
+	 ((eq type 'no-quote)
+	  (insert "Unquoted SGML attribute value.\n" desc "\n"))
+	 ((eq type 'no-textarea-end)
+	  (insert "Unterminated <textarea> tag.\n"
+		  (w3-reconstruct-tag "textarea" desc) "\n"))
+	 ((eq type 'bad-link-tag)
+	  (insert "Must specify either REL or REV with a <link> tag.\n"
+		  (w3-reconstruct-tag "link" desc) "\n"))
+	 ((eq type 'no-a-end)
+	  (insert "Unterminated <a> tag.\n"
+		  (w3-reconstruct-tag "a" desc) "\n"))
+	 ((eq type 'no-form-end)
+	  (insert "Unterminated <form> tag.\n"
+		  (w3-reconstruct-tag "form" desc) "\n"))
+	 ((eq type 'bad-base-tag)
+	  (insert "Malformed <base> tag.\n"
+		  (w3-reconstruct-tag "base" desc) "\n"))))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Functions to handle formatting an html buffer
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defun w3-insert-entities-in-string (string)
+  "Convert HTML markup-start characters to entity references in STRING.
+  Also replaces the \" character, so that the result may be safely used as
+  an attribute value in a tag.  Returns a new string with the result of the
+  conversion.  Replaces these characters as follows:
+    &  ==>  &amp;
+    <  ==>  &lt;
+    >  ==>  &gt;
+    \"  ==>  &quot;"
+  (if (string-match "[&<>\"]" string)
+      (save-excursion
+	(set-buffer (get-buffer-create " *entity*"))
+	(erase-buffer)
+	(buffer-disable-undo (current-buffer))
+	(insert string)
+	(goto-char (point-min))
+	(while (progn
+		 (skip-chars-forward "^&<>\"")
+		 (not (eobp)))
+	  (insert (cdr (assq (char-after (point))
+			     '((?\" . "&quot;")
+			       (?& . "&amp;")
+			       (?< . "&lt;")
+			       (?> . "&gt;")))))
+	  (delete-char 1))
+	(buffer-string))
+    string))
+
+(defun w3-insert-headers ()
+  ;; Insert some HTTP/1.0 headers if necessary
+  (url-lazy-message "Inserting HTTP/1.0 headers...")
+  (let ((hdrs (if (eq t w3-show-headers) (mapcar 'car url-current-mime-headers)
+		w3-show-headers))
+	x y)
+    (goto-char (setq y (point-max)))
+    (while hdrs
+      (if (setq x (w3-in-assoc (car hdrs) url-current-mime-headers))
+	  (insert "<LI> <B>" (car x) "</B>: " (w3-insert-entities-in-string
+					       (if (numberp (cdr x))
+						   (int-to-string (cdr x))
+						 (cdr x)))))
+      (setq hdrs (cdr hdrs)))
+    (if (= y (point-max))
+	nil
+      (insert "</UL>")
+      (goto-char y)
+      (url-lazy-message "Inserting HTTP/1.0 headers... done.")
+      (insert "<HR><UL>"))))
+
+(defun w3-add-delayed-mpeg (src st &optional width height)
+  ;; Add a delayed mpeg for the current buffer.
+  (setq w3-delayed-movies (cons (list src
+				      (set-marker (make-marker) st)
+				      width height)
+				w3-delayed-movies))
+  (w3-handle-text (concat "[MPEG(" (url-basepath src t) ")]"))
+  (put-text-property st (point) 'w3mpeg (list 'w3mpeg src st)))
+
+(defun w3-add-delayed-graphic (src st align alt args)
+  ;; Add a delayed image for the current buffer.
+  (setq st (set-marker (make-marker) st)
+	w3-delayed-images (cons (list src st align alt args)
+				w3-delayed-images))
+  (w3-handle-text alt)
+  (if (string= alt "") nil
+    (put-text-property st (point) 'w3delayed t)))
+
+
+(defun w3-load-flavors ()
+  ;; Load the correct zone/font info for each flavor of emacs
+  (cond
+   ((and w3-running-xemacs (eq system-type 'ms-windows))
+    (error "WinEmacs no longer supported."))
+   (w3-running-xemacs (require 'w3-xemac))
+   (w3-running-FSF19  (require 'w3-e19))
+   (t
+    (error "Unable to determine the capabilities of this emacs.")))
+  (cond
+   ((boundp 'MULE)
+    (require 'w3-mule))
+   ((featurep 'mule)
+    (require 'w3-xem20)
+    ))
+  (condition-case ()
+      (require 'w3-site-init)
+    (error nil)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Automatic bug submission.                                               ;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defun w3-submit-bug ()
+  "Submit a bug on Emacs-w3"
+  (interactive)
+  (require 'reporter)
+  (and (yes-or-no-p "Do you really want to submit a bug on Emacs-w3? ")
+       (let ((url (url-view-url t))
+	     (vars '(window-system
+		     window-system-version
+		     system-type
+		     ange-ftp-version
+		     url-gateway-method
+		     efs-version
+		     ange-ftp-version
+		     url-version
+		     url-be-asynchronous
+		     url)))
+	 (if (and url (string= url "file:nil")) (setq url nil))
+	 (mapcar
+	  (function
+	   (lambda (x)
+	     (if (not (and (boundp x) (symbol-value x)))
+		 (setq vars (delq x vars))))) vars)
+	 (reporter-submit-bug-report w3-bug-address
+				     (concat "WWW v" w3-version-number " of "
+					     w3-version-date)
+				     vars
+				     nil nil
+				     "Description of Problem:"))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Support for searching						    ;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defun w3-nuke-spaces-in-search (x)
+  "Remove spaces from search strings . . ."
+  (let ((new ""))
+    (while (not (equal x ""))
+      (setq new (concat new (if (= (string-to-char x) 32) "+"
+			      (substring x 0 1)))
+	    x (substring x 1 nil)))
+    new))
+
+(defun w3-search ()
+  "Perform a search, if this is a searchable index."
+  (interactive)
+  (or w3-current-isindex
+      (error "Not a searchable index (via <isindex>)"))
+  (let* (querystring			; The string to send to the server
+	 (data
+	  (cond
+	   ((null w3-current-isindex)
+	    (let ((rels (mapcar
+			 (function
+			  (lambda (data)
+			    (if (assoc "rel" data) data)))
+			 w3-current-links))
+		  val)
+	      (while rels
+		(if (string-match "useindex"
+				  (or (cdr (assoc "rel" (car rels))) ""))
+		    (setq val (cdr (assoc "href" (car rels)))
+			  rels nil))
+		(setq rels (cdr rels)))
+	      (cons val "Search on (+ separates keywords): ")))
+	   ((eq w3-current-isindex t)
+	    (cons (url-view-url t) "Search on (+ separates keywords): "))
+	   ((consp w3-current-isindex)
+	    w3-current-isindex)
+	   (t nil)))
+	 index)
+    (if (null data) (error "Not a searchable index!"))
+    (setq index (car data))
+    (setq querystring (w3-nuke-spaces-in-search (read-string (cdr data))))
+    (if (string-match "\\(.*\\)\\?.*" index)
+	(setq index (url-match index 1)))
+    (w3-fetch
+     (concat index (if (= ?? (string-to-char (substring index -1 nil)))
+		       "" "?") querystring))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Auto documentation, etc                                                 ;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defun w3-help ()
+  "Print documentation on w3 mode."
+  (interactive)
+  (w3-fetch "about:"))
+
+(defun w3-version (&optional here)
+  "Show the version number of W3 in the minibuffer.
+If optional argument HERE is non-nil, insert info at point."
+  (interactive "P")
+  (let ((version-string 
+         (format "WWW %s, URL %s, MM %s" 
+                 w3-version-number 
+                 url-version
+                 mm-version)))
+    (if here 
+        (insert version-string)
+      (if (interactive-p)
+          (message "%s" version-string)
+        version-string))))
+
+;;;###autoload
+(defun w3 ()
+  "Retrieve the default World Wide Web home page.
+The World Wide Web is a global hypertext system started by CERN in
+Switzerland in 1991.
+
+The home page is specified by the variable w3-default-homepage.  The
+document should be specified by its fully specified Uniform Resource
+Locator.  The document will be parsed as HTML (if appropriate) and
+displayed in a new buffer."
+  (interactive)
+  (if (not w3-setup-done) (w3-do-setup))
+  (if (and w3-track-last-buffer
+	   (bufferp w3-last-buffer)
+	   (buffer-name w3-last-buffer))
+      (progn
+	(switch-to-buffer w3-last-buffer)
+	(message "Reusing buffer.  To reload, type %s."
+		 (substitute-command-keys "\\[w3-reload-document]")))
+    (cond
+     ((null w3-default-homepage) (call-interactively 'w3-fetch))
+     ((not (stringp w3-default-homepage))
+      (error "Invalid setting for w3-default-homepage: %S"
+	     w3-default-homepage))
+     ((not (string-match ".*:.*" w3-default-homepage))
+      (w3-fetch (concat "file:" w3-default-homepage)))
+     (t
+      (w3-fetch w3-default-homepage)))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Leftover stuff that didn't quite fit into url.el
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun w3-generate-error (type data)
+  ;; Generate an HTML error buffer for error TYPE with data DATA.
+  (cond
+   ((equal type "nofile")
+    (let ((error (save-excursion
+		  (set-buffer (get-buffer-create " *url-error*"))
+		  (buffer-string))))
+      (if (string= "" error)
+	  (setq error
+		(format (concat "The file %s could not be found.  "
+				"Either it does not exist, or it "
+				"is unreadable.") data)))
+      (insert "<html>\n <head>\n"
+	    "  <title>Error</title>\n"
+	    " </head>\n <body>\n"
+	    "  <h1>Error accessing " data "</h1>\n"
+	    "  <hr>\n  <p>"
+	    error
+	    "\n  </p>\n")))
+   ((equal type "nobuf")
+    (insert "<title>Error</title>\n"
+	    "<H1>No buffer " data " found</h1>\n"
+	    "<HR>\n"
+	    "The buffer " data " could not be found.  It has either\n"
+	    "been killed or renamed.\n"))
+   ((equal type "nohist")
+    (insert "<TITLE>Error</TITLE>\n"
+	    "<H1>No history items found.</H1>\n"
+	    "<HR>\n"
+	    "There is no history list available at this time.  Either\n"
+	    "you have not visited any nodes, or the variable <i>\n"
+	    "url-keep-history</i> is nil.\n"))
+   )
+  (insert "<hr>\n"
+	  "If you feel this is a bug in Emacs-W3, <a href=\"mailto:"
+	  w3-bug-address "\">send mail to " w3-bug-address
+	  "</a>\n<hr>"))
+
+(defun w3-generate-auto-html (type)
+  ;; Generate one of several automatic html pages
+  (setq url-current-mime-type "text/html"
+	url-current-mime-headers '(("content-type" . "text/html")))
+  (cond
+   ((equal type "hotlist")
+    (let ((tmp (reverse w3-hotlist)))
+      (insert "<html>\n\t<head>\n\t\t"
+	      "<title> Hotlist </title>\n\t</head>\n"
+	      "\t<body>\n\t\t<div>\n\t\t\t<h1>Hotlist from " w3-hotlist-file
+	      "</h1>\n\t\t\t<ol>\n")
+      (while tmp
+	(insert  "\t\t\t\t<li> <a href=\"" (car (cdr (car tmp)))
+		 "\">" (w3-insert-entities-in-string
+			(car (car tmp))) "</a></li>\n")
+	(setq tmp (cdr tmp)))
+      (insert "\n\t\t\t</ol>\n\t\t</div>\n\t</body>\n</html>\n")))
+   ((equal type "starting-points")
+    (let ((tmp w3-starting-documents))
+      (insert "<html>\n\t<head>\n\t\t"
+	      "<title> Starting Points </title>\n\t</head>\n"
+	      "\t<body>\n\t\t<div>\n\t\t\t<h1>Starting Point on the Web"
+	      "</h1>\n\t\t\t<ol>\n")
+      (while tmp
+	(insert (format "\t\t\t\t<li> <a href=\"%s\">%s</a></li>\n"
+			(car (cdr (car tmp)))
+			(car (car tmp))))
+	(setq tmp (cdr tmp)))
+      (insert "\n\t\t\t</ol>\n\t\t</div>\n\t</body>\n</html>\n")))
+   ((equal type "history")
+    (if (not url-history-list)
+	(url-retrieve "www://error/nohist")
+      (insert "<html>\n\t<head>\n\t\t"
+	      "<title> History List For This Session of W3</title>"
+	      "\n\t</head>\n\t<body>\n\t\t<div>\n\t\t\t<h1>"
+	      "History List For This Session of W3</h1>\n\t\t\t<ol>\n")
+      (url-maphash
+       (function
+	(lambda (url desc)
+	  (insert (format "\t\t\t\t<li> <a href=\"%s\">%s</a>\n"
+			  url (w3-insert-entities-in-string desc)))))
+       url-history-list)
+      (insert "\n\t\t\t</ol>\n\t\t</div>\n\t</body>\n</html>\n")))))
+
+(defun w3-internal-handle-preview (buffer)
+  (setq buffer (get-buffer buffer))
+  (let ((base (get-text-property (point-min) 'w3-base buffer)))
+    (if base
+	(setq base (url-generic-parse-url base)))
+    (insert-buffer buffer)
+    (if (not base)
+	(setq url-current-type "file"
+	      url-current-server nil
+	      url-current-file (buffer-file-name buffer))
+      (setq url-current-object base
+	    url-current-type (url-type base)
+	    url-current-user (url-user base)
+	    url-current-port (url-port base)
+	    url-current-server (url-host base)
+	    url-current-file (url-filename base)))))
+
+(defun w3-internal-url (url)
+  ;; Handle internal urls (previewed buffers, etc)
+  (if (not (string-match "www:/+\\([^/]+\\)/\\(.*\\)" url))
+      (w3-fetch "www://error/")
+    (let ((type (url-match url 1))
+	  (data (url-match url 2)))
+      (set-buffer (get-buffer-create url-working-buffer))
+      (setq url-current-type "www"
+	    url-current-server type
+	    url-current-file data)
+      (cond
+       ((equal type "preview")		; Previewing a document
+	(if (get-buffer data)		; Buffer still exists
+	    (w3-internal-handle-preview data)
+	  (url-retrieve (concat "www://error/nobuf/" data))))
+       ((equal type "error")		; Error message
+	(if (string-match "\\([^/]+\\)/\\(.*\\)" data)
+	    (w3-generate-error (url-match data 1) (url-match data 2))
+	  (w3-generate-error data "")))
+       ((equal type "auto")		; Hotlist or help stuff
+	(w3-generate-auto-html data))))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Stuff for good local file handling
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defun w3-ff (file)
+  "Find a file in any window already displaying it, otherwise just as
+display-buffer, and using this function"
+  (if (not (eq 'tty (device-type)))
+      (let ((f (window-frame (display-buffer (find-file-noselect file)))))
+	(set-mouse-position f 1 0)
+	(raise-frame f)
+	(unfocus-frame))
+    (display-buffer (find-file-noselect file))))
+
+(defun w3-default-local-file()
+  "Use find-file to open the local file"
+  (w3-ff url-current-file))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Mode definition							    ;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defun w3-search-forward (string)
+  (interactive "sSearch: ")
+  (setq w3-last-search-item string)
+  (if (and (not (search-forward string nil t))
+	   (funcall url-confirmation-func
+		    "End of document reached; continue from beginning? "))
+      (progn
+	(goto-char (point-min))
+	(w3-search-forward string))))
+
+(defun w3-search-again ()
+  (interactive)
+  (if (and w3-last-search-item
+	   (stringp w3-last-search-item))
+      (if (and (not (search-forward w3-last-search-item nil t))
+	       (funcall url-confirmation-func
+			"End of document reached; continue from beginning? "))
+	  (progn
+	    (goto-char (point-min))
+	    (w3-search-again)))))
+
+(defun w3-find-specific-link (link)
+  (let ((pos (assq (intern link) w3-id-positions)))
+    (if pos
+	(progn
+	  (goto-char (cdr pos))
+	  (if (and (eolp) (not (eobp)))
+	      (forward-char 1)))
+      (error "Link #%s not found." link))))
+
+  (defun w3-force-reload-document ()
+  "Reload the current document.  Take it from the network, even if
+cached and in local mode."
+  (let ((url-standalone-mode nil))
+    (w3-reload-document)))
+
+(defun w3-reload-document ()
+  "Reload the current document"
+  (interactive)
+  (let ((tmp (url-view-url t))
+	(pnt (point))
+	(window-start (progn
+			(move-to-window-line 0)
+			(point)))
+	(url-request-extra-headers '(("Pragma" . "no-cache"))))
+    (kill-buffer (current-buffer))
+    (w3-fetch tmp)
+    (goto-char pnt)
+    (set-window-start (selected-window) (min window-start (point-max)))))
+
+(defun w3-leave-buffer ()
+  "Bury this buffer, but don't kill it."
+  (interactive)
+  (let ((x w3-current-last-buffer))
+    (bury-buffer nil)
+    (if (and (bufferp x) (buffer-name x))
+	(w3-notify-when-ready x))))
+
+(defun w3-quit (&optional mega)
+  "Quit WWW mode"
+  (interactive "P")
+  (if mega
+      (mapcar
+       (function
+	(lambda (x)
+	  (save-excursion
+	    (set-buffer (get-buffer x))
+	    (if (eq major-mode 'w3-mode)
+		(w3-quit nil)))))
+       (buffer-list))
+    (let ((x w3-current-last-buffer))
+      (and (fboundp 'w3-mpeg-kill-processes) (w3-mpeg-kill-processes))
+      (kill-buffer (current-buffer))
+      (if (and (bufferp x) (buffer-name x))
+	  (w3-notify-when-ready x)))))
+
+(defun w3-view-this-url (&optional no-show)
+  "View the URL of the link under point"
+  (interactive)
+  (let* ((widget (widget-at (point)))
+	 (href (and widget (widget-get widget 'href))))
+    (cond
+     ((and no-show href)
+      href)
+     (href
+      (message "%s" (url-truncate-url-for-viewing href)))
+     (no-show
+      nil)
+     (t
+      nil))))
+
+(defun w3-load-delayed-images ()
+    "Load inlined images that were delayed, if necessary.
+This function searches through `w3-delayed-images' and fetches the
+appropriate picture for each point in the buffer and inserts it."
+  (interactive)
+  (and (fboundp 'w3-insert-graphic)
+       (let ((buffer-read-only nil))
+	 (mapcar (function (lambda (data) (apply 'w3-insert-graphic data)))
+		 (nreverse w3-delayed-images))))
+  (setq w3-delayed-images nil))
+
+(defun w3-save-this-url ()
+  "Save url under point in the kill ring"
+  (interactive)
+  (w3-save-url t))
+
+(defun w3-save-url (under-pt)
+  "Save current url in the kill ring"
+  (interactive "P")
+  (let ((x (cond
+	    ((stringp under-pt) under-pt)
+	    (under-pt (w3-view-this-url t))
+	    (t (url-view-url t)))))
+    (if x
+	(progn
+	  (setq kill-ring (cons x kill-ring))
+	  (setq kill-ring-yank-pointer kill-ring)
+	  (message "Stored URL in kill-ring.")
+	  (if (fboundp 'w3-store-in-clipboard)
+	      (w3-store-in-clipboard x)))
+      (error "No URL to store."))))
+
+(fset 'w3-end-of-document 'end-of-buffer)
+(fset 'w3-start-of-document 'beginning-of-buffer)
+
+(defun w3-scroll-up (&optional lines)
+  "Scroll forward in View mode, or exit if end of text is visible.
+No arg means whole window full.  Arg is number of lines to scroll."
+  (interactive "P")
+  (if (and (pos-visible-in-window-p (point-max))
+	   ;; Allow scrolling backward at the end of the buffer.
+	   (or (null lines)
+	       (> lines 0)))
+      nil
+    (let ((view-lines (1- (window-height))))
+      (setq lines
+	    (if lines (prefix-numeric-value lines)
+	      view-lines))
+      (if (>= lines view-lines)
+	  (scroll-up nil)
+	(if (>= (- lines) view-lines)
+	    (scroll-down nil)
+	  (scroll-up lines)))
+      (cond ((pos-visible-in-window-p (point-max))
+	     (goto-char (point-max))
+	     (recenter -1)))
+      (move-to-window-line -1)
+      (beginning-of-line))))
+
+(defun w3-mail-document-author ()
+  "Send mail to the author of this document, if possible."
+  (interactive)
+  (let ((x w3-current-links)
+	(y nil)
+	(found nil))
+    (setq found (cdr-safe (assoc "reply-to" url-current-mime-headers)))
+    (if (and found (not (string-match url-nonrelative-link found)))
+	(setq found (concat "mailto:" found)))
+    (while (and x (not found))
+      (setq y (car x)
+	    x (cdr x)
+	    found (cdr-safe (assoc "made" y))))
+    (if found
+	(let ((possible nil))
+	  (setq x (car found))		; Fallback if no mail(to|server) found
+	  (while found
+	    (if (string-match "^mail[^:]+:" (car found))
+		(setq possible (cons (car found) possible)))
+	    (setq found (cdr found)))
+	  (case (length possible)
+	    (0				; No mailto links found
+	     (w3-fetch x))		; fall back onto first 'made' link
+	    (1				; Only one found, get it
+	     (w3-fetch (car possible)))
+	    (otherwise
+	     (w3-fetch (completing-read "Choose an address: "
+					(mapcar 'list possible)
+					nil t (car possible))))))
+      (message "Could not automatically determine authors address, sorry.")
+      (sit-for 1)
+      (w3-fetch (concat "mailto:"
+			(read-string "Email address: "
+				     (if url-current-server
+					 (concat "@" url-current-server))))))))
+
+(defun w3-kill-emacs-func ()
+  "Routine called when exiting emacs.  Do miscellaneous clean up."
+  (and (eq url-keep-history t)
+       url-global-history-hash-table
+       (url-write-global-history))
+  (message "Cleaning up w3 storage...")
+  (let ((x (nconc
+	    (and (file-exists-p w3-temporary-directory)
+		 (directory-files w3-temporary-directory t "url-tmp.*"))
+	    (and (file-exists-p url-temporary-directory)
+		 (directory-files url-temporary-directory t
+				  (concat "url"
+					  (int-to-string
+					   (user-real-uid)) ".*")))
+	    (and (file-exists-p url-temporary-directory)
+		 (directory-files url-temporary-directory t "url-tmp.*")))))
+    (while x
+      (condition-case ()
+	  (delete-file (car x))
+	(error nil))
+      (setq x (cdr x))))
+  (message "Cleaning up w3 storage... done."))
+
+(cond
+ ((fboundp 'display-warning)
+  (fset 'w3-warn 'display-warning))
+ ((fboundp 'warn)
+  (defun w3-warn (class message &optional level)
+    (if (and (eq class 'html)
+	     (not w3-debug-html))
+	nil
+      (warn "(%s/%s) %s" class (or level 'warning) message))))
+ (t
+  (defun w3-warn (class message &optional level)
+    (if (and (eq class 'html)
+	     (not w3-debug-html))
+	nil
+      (save-excursion
+	(set-buffer (get-buffer-create "*W3-WARNINGS*"))
+	(goto-char (point-max))
+	(save-excursion
+	  (insert (format "(%s/%s) %s\n" class (or level 'warning) message)))
+	(display-buffer (current-buffer)))))))
+
+(defun w3-internal-expander (urlobj defobj)
+  ;; URL Expansion routine for internally handled routines
+  (url-identity-expander urlobj defobj))
+
+(defun w3-map-links (function &optional buffer from to maparg)
+  "Map FUNCTION over the hypertext links which overlap region in BUFFER,
+starting at FROM and ending at TO.  FUNCTION is called with the arguments
+WIDGET and MAPARG.
+The arguments FROM, TO, MAPARG, and BUFFER default to the beginning of
+BUFFER, the end of BUFFER, nil, and (current-buffer), respectively."
+  (let ((cur (point-min))
+	(widget nil)
+	(url nil))
+    (while (setq cur (next-single-property-change cur 'button))
+      (setq widget (widget-at cur))
+      ;; Check to see if its a push widget, its got the correct callback,
+      ;; and actually has a URL.  Remember the url as a side-effect of the
+      ;; test for later use.
+      (if (and (eq (car widget) 'push)
+	       (eq (widget-get widget :notify) 'w3-follow-hyperlink)
+	       (setq url (widget-get widget 'href)))
+	  (funcall function widget maparg)))))
+
+(defun w3-emit-image-warnings-if-necessary ()
+  (if (and (not w3-delay-image-loads)
+	   (fboundp 'w3-insert-graphic)
+	   (or (not (featurep 'gif))
+	       (not (featurep 'jpeg)))
+	   (not (w3-executable-exists-in-path "ppmtoxpm"))
+	   (not (or
+		 (w3-executable-exists-in-path "pbmtoxbm")
+		 (w3-executable-exists-in-path "ppmtoxbm"))))
+      (w3-warn
+       'image
+       (concat
+	"Could not find some vital ppm utilities in exec-path.\n"
+	"This probably means that you will be unable to view any\n"
+	"inlined images other than: "
+	(mapconcat
+	 (function
+	  (lambda (x)
+	    (if (featurep x) (concat (symbol-name x) ",\n"))))
+	 '(png jpg gif xpm xbm) "")
+	"\n\n"
+	"If you do not have the PPM utilities from either the PBMPLUS\n"
+	"or NETPBM distributions installed on your machine, then\n"
+	"please set the variable `w3-delay-image-loads' to t with a\n"
+	"line like:\n\n"
+	"\t(setq w3-delay-image-loads t)\n\n"
+	"in your ~/.emacs file.\n\n"
+	"You can find the NETPBM utilities in:\n"
+	"\tftp://ftp.cs.indiana.edu/pub/elisp/w3/images/\n"
+	))))
+
+(defun w3-find-default-stylesheets ()
+  (let* ((lightp (w3-color-light-p 'default))
+	 (longname (if lightp "stylesheet-light" "stylesheet-dark"))
+	 (shortname (if lightp "light.css" "dark.css"))
+	 (directories (list
+		       data-directory
+		       (concat data-directory "w3/")
+		       (file-name-directory (locate-library "w3"))
+		       w3-configuration-directory))
+	 (total-found 0)
+	 (possible (append
+		    (apply
+		     'append
+		     (mapcar
+		      (function
+		       (lambda (dir)
+			 (list
+			  (expand-file-name shortname dir)
+			  (expand-file-name longname dir)
+			  (expand-file-name "stylesheet" dir)
+			  (expand-file-name "default.css" dir))))
+		      directories))
+		    (list w3-default-stylesheet)))
+	 (remember possible)
+	 (old-asynch (default-value 'url-be-asynchronous))
+	 (found nil)
+	 (cur nil)
+	 (url nil))
+    (setq-default url-be-asynchronous nil)
+    (while possible
+      (setq cur (car possible)
+	    possible (cdr possible)
+	    found (and cur (file-exists-p cur) (file-readable-p cur)
+		       (not (file-directory-p cur)) cur))
+      (if found
+	  (setq total-found (1+ total-found)
+		w3-user-stylesheet (car
+				    (w3-style-parse-css
+				     (concat "file:" cur) nil
+				     w3-user-stylesheet)))))
+    (setq-default url-be-asynchronous old-asynch)
+    (if (= 0 total-found)
+	(w3-warn
+	 'style
+	 (concat
+	 "No stylesheets found!  Check configuration! DANGER DANGER!\n"
+	 "Emacs-W3 checked for its stylesheet in the following places\n"
+	 "and did not find one.  This means that some formatting will\n"
+	 "be wrong, and most colors and fonts will not be set up correctly.\n"
+	 "------\n"
+	 (mapconcat 'identity remember "\n")
+	 "------")))))
+
+;;;###autoload
+(defun w3-do-setup ()
+  "Do setup - this is to avoid conflict with user settings when W3 is
+dumped with emacs."
+  (url-do-setup)
+  (url-register-protocol 'about 'w3-about 'url-identity-expander)
+  (url-register-protocol 'www 'w3-internal-url 'w3-internal-expander)
+  (w3-load-flavors)
+  (w3-setup-version-specifics)
+  (setq w3-default-configuration-file (expand-file-name 
+				       (or w3-default-configuration-file
+					   "profile")
+				       w3-configuration-directory))
+					   
+
+  (if (and w3-default-configuration-file
+	   (file-exists-p w3-default-configuration-file))
+      (condition-case e
+	  (load w3-default-configuration-file nil t)
+	(error
+	 (let ((buf-name " *Configuration Error*"))
+	   (if (get-buffer buf-name)
+	       (kill-buffer (get-buffer buf-name)))
+	   (display-error e (get-buffer-create buf-name))
+	   (save-excursion
+	     (switch-to-buffer-other-window buf-name)
+	     (shrink-window-if-larger-than-buffer))
+	   (w3-warn 'configuration
+		    (format (eval-when-compile
+			      (concat
+			       "Configuration file `%s' contains an error.\n"
+			       "Please consult the `%s' buffer for details."))
+			    w3-default-configuration-file buf-name))))))
+	       
+  (setq w3-netscape-configuration-file
+	(cond
+	 (w3-netscape-configuration-file
+	  w3-netscape-configuration-file)
+	 ((memq system-type '(ms-dos ms-windows))
+	  (expand-file-name "~/NETSCAPE.CFG"))
+	 (t (expand-file-name "~/.netscape/preferences"))))
+
+  (if (and (eq w3-user-colors-take-precedence 'guess)
+	   (not (eq (device-type) 'tty))
+	   (not (eq (device-class) 'mono)))
+      (progn
+	(setq w3-user-colors-take-precedence t)
+	(w3-warn
+	 'html
+	 "Disabled document color specification because of mono display."))
+    (setq w3-user-colors-take-precedence nil))
+
+  (w3-find-default-stylesheets)
+  (if (not url-global-history-file)
+      (setq url-global-history-file
+	    (expand-file-name "history"
+			      w3-configuration-directory)))
+
+  (if w3-user-stylesheet
+      (w3-generate-stylesheet-faces w3-user-stylesheet))
+
+  (if (and w3-use-netscape-configuration-file
+	   w3-netscape-configuration-file
+	   (fboundp 'w3-read-netscape-config))
+      (w3-read-netscape-config w3-netscape-configuration-file))
+      
+  (add-minor-mode 'w3-netscape-emulation-minor-mode " NS"
+		  w3-netscape-emulation-minor-mode-map)
+  (add-minor-mode 'w3-annotation-minor-mode " Annotating"
+		  w3-annotation-minor-mode-map)
+  (add-minor-mode 'w3-lynx-emulation-minor-mode " Lynx"
+		  w3-annotation-minor-mode-map)
+  
+  (setq url-package-version w3-version-number
+	url-package-name "Emacs-W3")
+
+  (w3-emit-image-warnings-if-necessary)
+  (if (eq w3-color-use-reducing 'guess)
+      (setq w3-color-use-reducing
+	    (cond
+	     ((eq (device-type) 'tty) nil)
+	     ((fboundp 'device-class)
+	      (not (and (memq (device-class) '(TrueColor true-color))
+			(<= 16 (or (device-bitplanes) 0)))))
+	     (t t))))
+		   
+  (cond
+   ((memq system-type '(ms-dos ms-windows))
+    (setq w3-documents-menu-file (or w3-documents-menu-file
+				     (expand-file-name "~/mosaic.mnu"))
+	  w3-hotlist-file (or w3-hotlist-file
+			      (expand-file-name "~/mosaic.hot"))
+	  w3-personal-annotation-directory (or w3-personal-annotation-directory
+					       (expand-file-name
+						"~/mosaic.ann"))))
+   ((memq system-type '(axp-vms vax-vms))
+    (setq w3-documents-menu-file
+	  (or w3-documents-menu-file
+	      (expand-file-name "decw$system_defaults:documents.menu"))
+	  w3-hotlist-file (or w3-hotlist-file
+			      (expand-file-name "~/mosaic.hotlist-default"))
+	  w3-personal-annotation-directory
+	  (or w3-personal-annotation-directory
+	      (expand-file-name "~/mosaic-annotations/"))))
+   (t 
+    (setq w3-documents-menu-file
+	  (or w3-documents-menu-file
+	      (expand-file-name "/usr/local/lib/mosaic/documents.menu"))
+	  w3-hotlist-file (or w3-hotlist-file
+			      (expand-file-name "~/.mosaic-hotlist-default"))
+	  w3-personal-annotation-directory
+	  (or w3-personal-annotation-directory
+	      (expand-file-name "~/.mosaic-personal-annotations")))))
+  
+  (if (eq w3-delimit-emphasis 'guess)
+      (setq w3-delimit-emphasis
+	    (and (not w3-running-xemacs)
+		 (not (and w3-running-FSF19
+			   (memq (device-type) '(x ns pm)))))))
+
+  (if (eq w3-delimit-links 'guess)
+      (setq w3-delimit-links
+	    (and (not w3-running-xemacs)
+		 (not (and w3-running-FSF19
+			   (memq (device-type) '(x ns pm)))))))
+
+  ; Set up a hook that will save the history list when
+  ; exiting emacs
+  (add-hook 'kill-emacs-hook 'w3-kill-emacs-func)
+
+  (mm-parse-mailcaps)
+  (mm-parse-mimetypes)
+
+  ; Load in the hotlist if they haven't set it already
+  (or w3-hotlist (w3-parse-hotlist))
+
+  ; Load in their personal annotations if they haven't set them already
+  (or w3-personal-annotations (w3-parse-personal-annotations))
+
+  ; Set the default home page, honoring their defaults, then
+  ; the standard WWW_HOME, then default to the documentation @ IU
+  (or w3-default-homepage
+      (setq w3-default-homepage
+	    (or (getenv "WWW_HOME")
+		"http://www.cs.indiana.edu/elisp/w3/docs.html")))
+
+  ; Set up the documents menu
+  (w3-parse-docs-menu)
+
+  ; Set up the entity definition for PGP and PEM authentication
+
+  (run-hooks 'w3-load-hook)
+  (setq w3-setup-done t))
+
+(defun w3-mark-link-as-followed (ext dat)
+  ;; Mark a link as followed
+  (let* ((st (w3-zone-start ext))
+	 (nd (w3-zone-end ext))
+	 (tag 'a)
+	 (args (list (cons 'class "visited")))
+	 (face (cdr (w3-face-for-element))))
+    (w3-add-zone st nd face dat t)))
+
+(defun w3-only-links ()
+  (let* (result temp)
+    (if (widget-at (point-min))
+	(setq result (list (widget-at (point-min)))))
+    (setq temp (w3-next-widget (point-min)))
+    (while temp
+      (if (widget-get temp 'href)
+	  (setq result (cons temp result)))
+      (setq temp (w3-next-widget (widget-get temp :to))))
+    result))
+
+(defun w3-download-callback (fname buff)
+  (if (and (get-buffer buff) (buffer-name buff))
+      (save-excursion
+	(set-buffer buff)
+	(let ((require-final-newline nil)
+	      (file-name-handler-alist nil)
+	      (write-file-hooks nil)
+	      (write-contents-hooks nil))
+	  (if (featurep 'mule)
+	      (let ((mc-flag t))
+		(write-file fname nil *noconv*))
+	    (write-file fname))
+	  (message "Download of %s complete." (url-view-url t))
+	  (sit-for 3)
+	  (kill-buffer buff)))))
+
+(defun w3-download-url (url)
+  (let* ((old-asynch url-be-asynchronous)
+	 (url-inhibit-uncompression t)
+	 (url-mime-accept-string "*/*")
+	 (urlobj (url-generic-parse-url url))
+	 (url-working-buffer
+	  (generate-new-buffer (concat " *" url " download*")))
+	 (stub-fname (url-basepath (or (url-filename urlobj) "") t))
+	 (fname (read-file-name "Filename to save as: "
+				(or mm-download-directory "~/")
+				(concat (or mm-download-directory "~/")
+					stub-fname)
+				nil
+				stub-fname)))
+    (setq-default url-be-asynchronous t)
+    (save-excursion
+      (set-buffer url-working-buffer)
+      (setq url-current-callback-data (list fname (current-buffer))
+	    url-be-asynchronous t
+	    url-current-callback-func 'w3-download-callback)
+      (url-retrieve url))
+    (setq-default url-be-asynchronous old-asynch)))
+
+;;;###autoload
+(defun w3-follow-link-other-frame (&optional p)
+  "Attempt to follow the hypertext reference under point in a new frame.
+With prefix-arg P, ignore viewers and dump the link straight
+to disk."
+  (cond
+   ((and (fboundp 'make-frame)
+	 (fboundp 'select-frame))
+    (let ((frm (make-frame)))
+      (select-frame frm)
+      (w3-follow-link p)))
+   (t (w3-follow-link p))))
+
+;;;###autoload
+(defun w3-follow-link (&optional p)
+  "Attempt to follow the hypertext reference under point.
+With prefix-arg P, ignore viewers and dump the link straight
+to disk."
+  (interactive "P")
+  (let* ((widget (widget-at (point)))
+	 (href (and widget (widget-get widget 'href))))
+    (cond
+     ((null href) nil)
+     ((or p w3-dump-to-disk)
+      (w3-download-url href))
+     (t
+      (w3-fetch href)))))
+
+(defun w3-complete-link ()
+  "Choose a link from the current buffer and follow it"
+  (interactive)
+  (let (links-alist
+	link-at-point
+	choice
+	(completion-ignore-case t))
+    (setq link-at-point (widget-at (point))
+	  link-at-point (and
+			 link-at-point
+			 (widget-get link-at-point 'href)
+			 (w3-fix-spaces
+			  (buffer-substring
+			   (car (widget-get link-at-point 'title))
+			   (cdr (widget-get link-at-point 'title))))))
+    (w3-map-links (function
+		   (lambda (widget arg)
+		     (setq links-alist	(cons
+					 (cons
+					  (w3-fix-spaces
+					   (buffer-substring-no-properties
+					    (widget-get widget :from)
+					    (widget-get widget :to)))
+					  (widget-get widget 'href))
+					 links-alist)))))
+    (if (not links-alist) (error "No links in current document."))
+    (setq links-alist (sort links-alist (function
+					 (lambda (x y)
+					   (string< (car x) (car y))))))
+    ;; Destructively remove duplicate entries from links-alist.
+    (let ((remaining-links links-alist))
+      (while remaining-links
+	(if (equal (car remaining-links) (car (cdr remaining-links)))
+	    (setcdr remaining-links (cdr (cdr remaining-links)))
+	  (setq remaining-links (cdr remaining-links)))))
+    (setq choice (completing-read
+		  (if link-at-point
+		      (concat "Link (default "
+			      (if (< (length link-at-point) 20)
+				  link-at-point
+				(concat
+				 (substring link-at-point 0 17) "..."))
+			      "): ")
+		    "Link: ") links-alist nil t))
+    (if (string= choice "")
+	(w3-follow-link)
+      (w3-fetch (cdr (assoc choice links-alist))))))
+
+(defun w3-mode ()
+  "Mode for viewing HTML documents.  If called interactively, will
+display the current buffer as HTML.
+
+Current keymap is:
+\\{w3-mode-map}"
+  (interactive)
+  (or w3-setup-done (w3-do-setup))
+  (if (interactive-p)
+      (w3-preview-this-buffer)
+    (let ((tmp (mapcar (function (lambda (x) (cons x (symbol-value x))))
+		       w3-persistent-variables)))
+      (kill-all-local-variables)
+      (use-local-map w3-mode-map)
+      (setq major-mode 'w3-mode)
+      (setq mode-name "WWW")
+      (mapcar (function (lambda (x) (set-variable (car x) (cdr x)))) tmp)
+      (w3-mode-version-specifics)
+      (w3-menu-install-menus)
+      (run-hooks 'w3-mode-hook)
+      (widget-setup)
+      (setq url-current-passwd-count 0
+	    mode-line-format w3-modeline-format)
+      (if (and w3-current-isindex (equal url-current-type "http"))
+	  (setq mode-line-process "-Searchable")))))
+
+(require 'mm)
+(require 'url)
+(require 'url-hash)
+(require 'w3-parse)
+(require 'w3-draw)
+(require 'w3-auto)
+(require 'w3-emulate)
+(require 'w3-menu)
+(require 'w3-mouse)
+(provide 'w3)