diff lisp/w3/w3.el @ 70:131b0175ea99 r20-0b30

Import from CVS: tag r20-0b30
author cvs
date Mon, 13 Aug 2007 09:02:59 +0200
parents 8d2a9b52c682
children 1ce6082ce73f
line wrap: on
line diff
--- a/lisp/w3/w3.el	Mon Aug 13 09:00:04 2007 +0200
+++ b/lisp/w3/w3.el	Mon Aug 13 09:02:59 2007 +0200
@@ -1,14 +1,13 @@
 ;;; w3.el --- Main functions for emacs-w3 on all platforms/versions
 ;; Author: wmperry
-;; Created: 1997/03/26 00:02:30
-;; Version: 1.103
+;; Created: 1996/08/19 03:30:47
+;; Version: 1.22
 ;; Keywords: faces, help, comm, news, mail, processes, mouse, hypermedia
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;; Copyright (c) 1993 - 1996 by William M. Perry (wmperry@cs.indiana.edu)
-;;; Copyright (c) 1996, 1997 Free Software Foundation, Inc.
 ;;;
-;;; This file is part of GNU Emacs.
+;;; 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
@@ -21,9 +20,8 @@
 ;;; 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, Inc., 59 Temple Place - Suite 330,
-;;; Boston, MA 02111-1307, USA.
+;;; along with GNU Emacs; see the file COPYING.  If not, write to
+;;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -69,9 +67,7 @@
   )
 
 
-(require 'w3-sysdp)
-(require 'mule-sysdp)
-
+(load-library "w3-sysdp")
 (or (featurep 'efs)
     (featurep 'efs-auto)
     (condition-case ()
@@ -79,10 +75,9 @@
       (error nil)))
 
 (require 'cl)
-(require 'css)
 (require 'w3-vars)
 (eval-and-compile
-  (require 'w3-display))
+  (require 'w3-draw))
 
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -127,16 +122,75 @@
 
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; 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.
+  "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)))
-  (start-process fname view shell-file-name shell-command-switch cmd))
+  (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
@@ -183,9 +237,7 @@
     (pop-to-buffer buff)
     (delete-other-windows))
    ((eq w3-notify 'semibully)
-    (condition-case nil
-	(switch-to-buffer buff)
-      (error (message "W3 buffer %s is ready." (buffer-name buff)))))
+    (switch-to-buffer buff))
    ((eq w3-notify 'aggressive)
     (pop-to-buffer buff))
    ((eq w3-notify 'friendly)
@@ -208,10 +260,8 @@
      (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-filename url-current-object)))))))
+      (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
@@ -221,8 +271,7 @@
 					      mm-multipart-viewer)))
 	  (let ((bufnam (url-generate-new-buffer-name
 			 (file-name-nondirectory
-			  (or (url-filename url-current-object)
-			      "Unknown")))))
+			  (or url-current-file "Unknown")))))
 	    (if (string= bufnam "")
 		(setq bufnam (url-generate-new-buffer-name
 			      (url-view-url t))))
@@ -237,10 +286,11 @@
 	(funcall view)))
      ((stringp view)
       (let ((fname (url-generate-unique-filename fmt))
-	    (proc nil))
+	    (proc nil)
+	    (file-coding-system url-mule-no-coding-system))
 	(if (url-file-directly-accessible-p (url-view-url t))
-	    (make-symbolic-link (url-filename url-current-object) fname t)
-	  (mule-write-region-no-coding-system (point-min) (point-max) fname))
+	    (make-symbolic-link url-current-file fname t)
+	  (write-region (point-min) (point-max) fname))
 	(if (get-buffer url-working-buffer)
 	    (kill-buffer url-working-buffer))
 	(setq view (mm-viewer-unescape view fname url))
@@ -273,16 +323,69 @@
 			       (file-name-nondirectory (url-view-url t)))))
 	(require-final-newline nil))
     (set-buffer old-buff)
-    (mule-write-region-no-coding-system (point-min) (point-max) file)
+    (let ((mc-flag t)
+	  (file-coding-system url-mule-no-coding-system))
+      (write-region (point-min) (point-max) file))
     (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."
+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: ")
-  (setq fname (expand-file-name fname))
   (if (not w3-setup-done) (w3-do-setup))
   (w3-fetch (concat "file:" fname)))
 
@@ -290,7 +393,9 @@
 (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."
+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))
  
@@ -318,68 +423,58 @@
   (split-window)
   (w3-fetch url))
 
-;; Ripped off from red gnus
-(defun w3-find-etc-directory (package &optional file)
-  "Go through the path and find the \".../etc/PACKAGE\" directory.
-If FILE, find the \".../etc/PACKAGE\" file instead."
-  (let ((path load-path)
-	dir result)
-    ;; We try to find the dir by looking at the load path,
-    ;; stripping away the last component and adding "etc/".
-    (while path
-      (if (and (car path)
-	       (file-exists-p
-		(setq dir (concat
-			   (file-name-directory
-			    (directory-file-name (car path)))
-			   "etc/" package 
-			   (if file "" "/"))))
-	       (or file (file-directory-p dir)))
-	  (setq result dir
-		path nil)
-	(setq path (cdr path))))
-    result))
-
 (defun w3-url-completion-function (string predicate function)
   (if (not w3-setup-done) (w3-do-setup))
   (cond
-   ((eq function nil)
-    (let ((list nil))
-      (cl-maphash (function (lambda (key val)
-			      (setq list (cons (cons key val)
-					       list))))
-		  url-global-history-hash-table)
-      (try-completion string (nreverse list) predicate)))
+   ((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)
-    (let ((stub (concat "^" (regexp-quote string)))
-	  (retval nil))
-      (cl-maphash
-       (function
-	(lambda (url time)
-	  (if (string-match stub url)
-	      (setq retval (cons url retval)))))
-       url-global-history-hash-table)
-      retval))
+    (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-global-history-hash-table
-	 (cl-gethash string url-global-history-hash-table)
-	 t))
-   (t
-    (error "w3-url-completion-function very confused."))))
+    (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
-	   (cond
-	    ((null w3-fetch-with-default) nil)
-	    ((eq major-mode 'w3-mode)
-	     (or (and current-prefix-arg (w3-view-this-url t))
-		 (url-view-url t)))
-	    ((url-get-url-at-point)
-	     (url-get-url-at-point))
-	    (t "http://www.")))
+	   (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))
@@ -392,10 +487,15 @@
     url))
 
 ;;;###autoload
-(defun w3-fetch (&optional url target)
+(defun w3-fetch (&optional url)
   "Retrieve a document over the World Wide Web.
-Defaults to URL of the current document, if any.
-With prefix argument, use the URL of the hyperlink under point instead."
+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)
@@ -408,20 +508,11 @@
   (if (equal url "") (error "No document specified!"))
   ;; legal use for relative URLs ?
   (if (string-match "^www:[^/].*" url)
-      (setq url (concat (file-name-directory (url-filename
-					      url-current-object))
+      (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)))
-  (or target (setq target w3-base-target))
-  (if (stringp target)
-      (setq target (intern (downcase target))))
-  (and target
-       (let ((window-distance (cdr-safe (assq target w3-target-window-distances))))
-	 (if (numberp window-distance)
-	     (other-window window-distance)
-	   (error "target %S not found." target))))
   (cond
    ((= (string-to-char url) ?#)
     (w3-relative-link url))
@@ -431,6 +522,8 @@
     (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)
@@ -447,21 +540,20 @@
 		(not (funcall url-confirmation-func
 			      (format "Reuse URL in buffer %s? "
 				      (buffer-name buf)))))))
-	  (let* ((status (url-retrieve url))
-		 (cached (car status))
-		 (url-working-buffer (cdr status)))
+	  (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 (not cached))
+		 ((and url-be-asynchronous (string-match "^http:" url)
+		       (not cached))
 		  (save-excursion
 		    (set-buffer url-working-buffer)
 		    (if x
-			(w3-history-push x (url-view-url t)))
+			(w3-add-urls-to-history x (url-view-url t)))
 		    (setq w3-current-last-buffer lastbuf)))
 		 (t
-		  (w3-history-push x url)
+		  (w3-add-urls-to-history x url)
 		  (w3-sentinel lastbuf)))))
 	(if w3-track-last-buffer
 	    (setq w3-last-buffer buf))
@@ -474,69 +566,66 @@
 	    (progn
 	      (push-mark (point) t)
 	      (w3-find-specific-link (url-match url 1))))
-	(or (w3-maybe-fetch-frames)
-	    (message "Reusing URL.  To reload, type %s."
-		     (substitute-command-keys "\\[w3-reload-document]"))))))))
+	(message "Reusing URL.  To reload, type %s."
+		 (substitute-command-keys "\\[w3-reload-document]")))))))
 
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;; History for forward/back buttons
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defvar w3-history-stack nil
-  "History stack viewing history.
-This is an assoc list, with the oldest items first.
-Each element is a cons cell of (url . timeobj), where URL
-is the normalized URL (default ports removed, etc), and TIMEOBJ is
-a standard Emacs time.  See the `current-time' function documentation
-for information on this format.")
+(defvar w3-node-history nil "History for forward and backward jumping")
 
-(defun w3-history-find-url-internal (url)
-  "Search in the history list for URL.
-Returns a cons cell, where the car is the 'back' node, and
-the cdr is the 'next' node."
-  (let* ((node (assoc url w3-history-stack))
-	 (next (cadr (memq node w3-history-stack)))
-	 (last nil)
-	 (temp nil)
-	 (todo w3-history-stack))
-    ;; Last node is a little harder to find without using back links
-    (while (and (not last) todo)
-      (if (string= (caar todo) url)
-	  (setq last (or temp 'none))
-	(setq temp (pop todo))))
-    (cons (if (not (symbolp last)) last)
-	  next)))
+(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-history-forward ()
+(defun w3-forward-in-history ()
   "Go forward in the history from this page"
   (interactive)
-  (let ((next (cadr (w3-history-find-url-internal (url-view-url t))))
-	(w3-reuse-buffers 'yes))
-    (if next
-	(w3-fetch next))))
+  (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-history-backward ()
+(defun w3-backward-in-history ()
   "Go backward in the history from this page"
   (interactive)
-  (let ((last (caar (w3-history-find-url-internal (url-view-url t))))
-	(w3-reuse-buffers 'yes))
-    (if last
-	(w3-fetch last))))
+  (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-history-push (referer url)
+(defun w3-add-urls-to-history (referer url)
   "REFERER is the url we followed this link from.  URL is the link we got to."
-  (if (not referer)
-      (setq w3-history-stack (list (cons url (current-time))))
-    (let ((node (memq (assoc referer w3-history-stack) w3-history-stack)))
-      (if node
-	  (setcdr node (list (cons url (current-time))))
-	(setq w3-history-stack (append w3-history-stack
-				       (list
-					(cons url (current-time)))))))))
-
-(defalias 'w3-add-urls-to-history 'w3-history-push)
-(defalias 'w3-backward-in-history 'w3-history-backward)
-(defalias 'w3-forward-in-history 'w3-history-forward)
+  (let ((node (assoc referer w3-node-history)))
+    (if node
+	(setcdr node url)
+      (setq w3-node-history (cons (cons referer url) w3-node-history)))))
 
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -589,50 +678,41 @@
       (let* ((url (url-view-url t))
 	     (cur-links w3-current-links)
 	     (title (buffer-name))
-	     (case-fold-search t)
-	     (possible-lastmod (save-excursion
-				 (goto-char (point-min))
-				 (if (re-search-forward "^Last modified:\\(.*\\)" nil t)
-				     (buffer-substring (match-beginning 1)
-						       (match-end 1)))))
-	     (attributes (url-file-attributes url))
 	     (lastmod (or (cdr-safe (assoc "last-modified"
 					   url-current-mime-headers))
-			  (nth 5 attributes)))
-	     (hdrs url-current-mime-headers)
-	     (size (or (cdr (assoc "content-length" url-current-mime-headers))
-		       (buffer-size)))
-	     (info w3-current-metainfo))
+			  (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)
+	(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 possible-lastmod))
+	 ((equal '(0 . 0) lastmod) (setq lastmod nil))
 	 ((consp lastmod) (setq lastmod (current-time-string lastmod)))
-	 (t (setq lastmod possible-lastmod)))
+	 (t (setq lastmod nil)))
 	(insert "<html>\n"
 		" <head>\n"
 		"  <title>Document Information</title>\n"
 		" </head>\n"
 		" <body\n"
-		"  <table border>\n"
-		"   <tr><th colspan=2>Document Information</th></tr>\n"
-		"   <tr><td>Title:</td><td>" title "</td></tr>\n"
-		"   <tr><td>Location:</td><td>" url "</td></tr>\n"
-		"   <tr><td>Size:</td><td>" (url-pretty-length
-					     (if (stringp size)
-						 (string-to-int size)
-					       size)) "</td></tr>\n"
-		"   <tr><td>Last Modified:</td><td>" (or lastmod "None Given")
-		"</td></tr>\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 "   <tr><td align=right>%%%ds:</td><td>%%s</td></tr>" maxlength)))
-	      (insert "  <tr><th>MetaInformation</th></tr>\n"
+		   (fmtstring (format "%%%ds: %%s" maxlength)))
+	      (insert "  <hr label=\" MetaInformation \" textalign=\"left\">\n"
+		      "  <pre>\n"
 		      (mapconcat
 		       (function
 			(lambda (x)
@@ -645,27 +725,36 @@
 		       (sort hdrs
 			     (function
 			      (lambda (x y) (string-lessp (car x) (car y)))))
-		       "\n"))))
-
-	;; FIXME!!! Need to reimplement showing rel/rev links for the new
-	;; storage format.
-	
-	(if info
-	    (let* ((maxlength (car (sort (mapcar (function (lambda (x)
-							     (length (car x))))
-						 info)
-					 '>)))
-		   (fmtstring (format "   <tr><td>%%%ds:</td><td>%%s</td></tr>" maxlength)))
-	      (insert "   <tr><th>Miscellaneous Variables</th></tr>\n")
-	      (while info
-		(insert (format fmtstring (capitalize (caar info))
-				(cdar info)) "\n")
-		(setq info (cdr info))
-		)
-	      )
-	  )
-	(insert "  </table>\n"
-		" </body>\n"
+		       "\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)
@@ -673,6 +762,18 @@
       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."
@@ -682,13 +783,13 @@
      (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)
+      (setq str (format "<A HREF=\"%s\">%s</A>" (widget-get p 'href)
 			(read-string "Link text: "
 				     (buffer-substring
                                       (widget-get p :from)
                                       (widget-get p :to))))))
      (t
-      (setq str (format "<a href=\"%s\">%s</a>" (url-view-url 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
@@ -715,14 +816,8 @@
 
 (defun w3-widget-button-click (e)
   (interactive "@e")
-  (cond
-   ((and (event-point e)
-	 (widget-at (event-point e)))
-    (widget-button-click e))
-   ((and (fboundp 'event-glyph)
-	 (event-glyph e)
-	 (glyph-property (event-glyph e) 'widget))
-    (widget-button-click 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)
@@ -770,6 +865,69 @@
   (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."
@@ -784,7 +942,7 @@
 	url-setup-done nil
 	w3-hotlist nil
 	url-mime-accept-string nil)
-  (let ((x '(w3 mule-sysdp w3-e19 mm url w3-xemac w3-toolbar font)))
+  (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)))
@@ -798,14 +956,36 @@
   (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
-	   ((null url)
-	    (error "No URL found!"))
+	   ((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))
@@ -814,6 +994,7 @@
 	    (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))
@@ -827,18 +1008,18 @@
 		   (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 url
-	    buffer-file-name url)
+      (setq buffer-file-truename nil
+	    buffer-file-name nil)
       ;; Null filename bugs `set-auto-mode' in Mule ...
       (condition-case ()
  	  (set-auto-mode)
 	(error nil))
-      (setq buffer-file-truename nil
-	    buffer-file-name nil)
       (buffer-enable-undo)
       (set-buffer-modified-p nil)
       (w3-notify-when-ready (get-buffer tmp))))
@@ -862,7 +1043,6 @@
 			("LaTeX Source")
 			)
 		  nil t)))
-	 (case-fold-search t)
 	 (url (cond
 	       ((stringp under) under)
 	       (under (w3-view-this-url t))
@@ -889,14 +1069,16 @@
 	      (let ((ps-spool-buffer-name " *w3-temp*"))
 		(if (get-buffer ps-spool-buffer-name)
 		    (kill-buffer ps-spool-buffer-name))
-		(ps-spool-buffer-with-faces)
+		(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")
-		(ps-spool-buffer-with-faces)
+		(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")
@@ -909,31 +1091,30 @@
 		(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))
+		(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))))
-    (funcall url-mail-command)
+    (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)
-    (if (and (boundp 'mime/editor-mode-flag) mime/editor-mode-flag)
-        (insert format " from <URL: " url ">")
-      (insert format " from <URL: " url ">\n"
-              "Mime-Version: 1.0\n"
-              "Content-transfer-encoding: 8bit\n"
-              "Content-type: " content-type))
+    (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)
-    (if (and (boundp 'mime/editor-mode-flag) mime/editor-mode-flag)
-        (insert (format mime-tag-format content-type) "\n"))
-    (save-excursion
-      (insert str))
-    (cond ((equal "HTML Source" format)
-           (if (or (search-forward "<head>" nil t)
-		   (search-forward "<html>" nil t))
-	       (insert "\n"))
-           (insert (format "<base href=\"%s\">" url))))
+    (insert (if (equal "HTML Source" format)
+		(format "<BASE HREF=\"%s\">" url) "")
+	    str)
     (mail-to)))
 
 (defun w3-internal-use-history (hist-item)
@@ -985,12 +1166,10 @@
   (save-excursion
     (set-buffer url-working-buffer)
     (let ((cont w3-default-continuation)
-	  (extn (url-file-extension
-		 (url-filename url-current-object))))
+	  (extn (url-file-extension url-current-file)))
       (if (assoc extn url-uncompressor-alist)
 	  (setq extn (url-file-extension
-		      (substring (url-filename url-current-object)
-				 0 (- (length extn))))))
+		      (substring url-current-file 0 (- (length extn))))))
       (if w3-source
 	  (setq url-current-mime-viewer '(("viewer" . w3-source))))
       (if (not url-current-mime-viewer)
@@ -999,7 +1178,7 @@
 				  (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-prepare-buffer))))
+	(setq cont (append cont (list w3-default-action))))
       cont)))
 
 (defun w3-use-links ()
@@ -1013,19 +1192,21 @@
   "Do a find-file on the currently viewed html document if it is a file: or
 ftp: reference"
   (interactive)
-  (or url-current-object
-      (error "Not a URL-based buffer"))
-  (let ((type (url-type url-current-object)))
-    (cond
-     ((equal type "file")
-      (find-file (url-filename url-current-object)))
-     ((equal type "ftp")
+  (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-user url-current-object)
-	       (url-host url-current-object)
-	       (url-filename url-current-object))))
-     (t (message "Sorry, I can't get that file so you can alter it.")))))
+       (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,
@@ -1091,6 +1272,20 @@
   (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"))))
@@ -1104,23 +1299,12 @@
     (buffer-enable-undo)
     (w3-notify-when-ready (get-buffer tmp))))
 
-(defvar w3-mime-list-for-code-conversion
-  '("text/plain" "text/html")
-  "List of MIME types that require Mules' code conversion.")
-
-(defun w3-convert-code-for-mule (mmtype)
-  "Convert current data into the appropriate coding system"
-  (and (or (not mmtype)
-	   (member mmtype w3-mime-list-for-code-conversion))
-       (mule-code-convert-region
-	(point-min) (point-max)
-	(mule-detect-coding-version (point-min) (point-max)))))
-
 (defun w3-sentinel (&optional proc string)
   (set-buffer url-working-buffer)
   (if (or (stringp proc)
 	  (bufferp proc)) (setq w3-current-last-buffer proc))
-  (remove-hook 'after-change-functions 'url-after-change-function)
+  (if (boundp 'after-change-functions)
+      (remove-hook 'after-change-functions 'url-after-change-function))
   (if url-be-asynchronous
       (progn
 	(url-clean-text)
@@ -1130,16 +1314,20 @@
 	(if (not url-current-mime-type)
 	    (setq url-current-mime-type (or (mm-extension-to-mime
 					     (url-file-extension
-					      (url-filename
-					       url-current-object)))
+					      url-current-file))
 					    "text/html")))))
-  (if (not (string-match "^www:" (or (url-view-url t) "")))
-      (w3-convert-code-for-mule url-current-mime-type))
-      
   (let ((x (w3-build-continuation))
-	(url (url-view-url t)))
+	(done-mule-conversion nil))
     (while x
-      (funcall (pop 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"
@@ -1149,49 +1337,36 @@
 (defun w3-save-as (&optional type)
   "Save a document to the local disk"
   (interactive)
-  (save-excursion
-    (let* ((completion-ignore-case t)
-	   (format (or type (completing-read
-			     "Format: "
-			     '(("HTML Source")
-			       ("Formatted Text")
-			       ("LaTeX Source")
-			       ("PostScript")
-			       ("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))
-	    (erase-buffer)
-	    (insert txt)))
-	(goto-char (point-min))
-	(if (re-search-forward "<head>" nil t)
-	    (insert "\n"))
-	(insert (format "<BASE HREF=\"%s\">\n" url)))
-       ((or (equal "Formatted Text" format)
-	    (equal "" format))
-	nil)				; Do nothing - we have the text already
-       ((equal "PostScript" format)
-	(let ((ps-spool-buffer-name " *w3-temp*"))
-	  (if (get-buffer ps-spool-buffer-name)
-	      (kill-buffer ps-spool-buffer-name))
-	  (ps-spool-buffer-with-faces)
-	  (set-buffer ps-spool-buffer-name)))
-       ((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))))
+  (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)))
 
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -1229,8 +1404,7 @@
                
 (defun w3-popup-info (&optional url)
   "Show information about the link under point. (All SGML attributes)"
-  (interactive (list (or (w3-view-this-url t)
-			 (w3-read-url-with-default))))
+  (interactive (list (w3-read-url-with-default)))
   (let (dat widget)
     (if (interactive-p)
 	nil
@@ -1310,6 +1484,27 @@
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;; Functions to handle formatting an html buffer
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(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>: " (url-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-graphic (widget)
   ;; Add a delayed image for the current buffer.
   (setq w3-delayed-images (cons widget w3-delayed-images)))
@@ -1324,11 +1519,12 @@
    (w3-running-FSF19  (require 'w3-e19))
    (t
     (error "Unable to determine the capabilities of this emacs.")))
-  (if (featurep 'emacspeak)
-      (condition-case ()
-	  (progn
-	    (require 'dtk-css-speech)
-	    (require 'w3-speak))))
+  (cond
+   ((boundp 'MULE)
+    (require 'w3-mule))
+   ((featurep 'mule)
+    (require 'w3-xem20)
+    ))
   (condition-case ()
       (require 'w3-site-init)
     (error nil)))
@@ -1382,23 +1578,25 @@
 (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 (cdr-safe (assq 'rel w3-current-links)))
-		  val cur)
+	    (let ((rels (mapcar
+			 (function
+			  (lambda (data)
+			    (if (assoc "rel" data) data)))
+			 w3-current-links))
+		  val)
 	      (while rels
-		(setq cur (car rels)
-		      rels (cdr rels))
-		(if (and (or (string-match "^isindex$" (car cur))
-			     (string-match "^index$" (car cur)))
-			 (plist-get (cadr cur) 'href))
-		    (setq val (plist-get (cadr cur) 'href)
+		(if (string-match "useindex"
+				  (or (cdr (assoc "rel" (car rels))) ""))
+		    (setq val (cdr (assoc "href" (car rels)))
 			  rels nil))
-		)
-	      (if val
-		  (cons val "Search on (+ separates keywords): "))))
+		(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)
@@ -1472,7 +1670,6 @@
 
 (defun w3-generate-error (type data)
   ;; Generate an HTML error buffer for error TYPE with data DATA.
-  (setq url-current-mime-type "text/html")
   (cond
    ((equal type "nofile")
     (let ((error (save-excursion
@@ -1526,6 +1723,18 @@
 			(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")
@@ -1533,7 +1742,7 @@
 	      "<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")
-      (cl-maphash
+      (url-maphash
        (function
 	(lambda (url desc)
 	  (insert (format "\t\t\t\t<li> <a href=\"%s\">%s</a>\n"
@@ -1547,13 +1756,16 @@
     (if base
 	(setq base (url-generic-parse-url base)))
     (insert-buffer buffer)
-    (let ((inhibit-read-only t))
-      (set-text-properties (point-min) (point-max) nil))
     (if (not base)
-	(setq url-current-object
-	      (url-generic-parse-url (concat "file:"
-					     (buffer-file-name buffer))))
-      (setq url-current-object 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)
@@ -1562,6 +1774,9 @@
     (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
@@ -1589,7 +1804,7 @@
 
 (defun w3-default-local-file()
   "Use find-file to open the local file"
-  (w3-ff (url-filename url-current-object)))
+  (w3-ff url-current-file))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;; Mode definition							    ;;;
@@ -1681,8 +1896,6 @@
       (message "%s" (url-truncate-url-for-viewing href)))
      (no-show
       nil)
-     (widget
-      (widget-echo-help (point)))
      (t
       nil))))
 
@@ -1752,19 +1965,18 @@
 	(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 (list (concat "mailto:" 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)
-	      (href nil))
+	(let ((possible nil))
 	  (setq x (car found))		; Fallback if no mail(to|server) found
 	  (while found
-	    (setq href (plist-get (pop found) 'href))
-	    (if (and href (string-match "^mail[^:]+:" href))
-		(setq possible (cons href possible))))
+	    (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
@@ -1774,7 +1986,12 @@
 	     (w3-fetch (completing-read "Choose an address: "
 					(mapcar 'list possible)
 					nil t (car possible))))))
-      (message "Could not automatically determine authors address, sorry."))))
+      (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."
@@ -1832,19 +2049,16 @@
 BUFFER, the end of BUFFER, nil, and (current-buffer), respectively."
   (let ((cur (point-min))
 	(widget nil)
-	(parent nil))
+	(url nil))
     (while (setq cur (next-single-property-change cur 'button))
-      (setq widget (widget-at cur)
-	    parent (and widget (widget-get widget :parent)))
+      (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.
-      (cond
-       ((and widget (widget-get widget 'href))
-	(funcall function widget maparg))
-       ((and parent (widget-get parent 'href))
-	(funcall function parent maparg))
-       (t nil)))))
+      (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)
@@ -1883,20 +2097,15 @@
   (setq w3-user-stylesheet nil
 	w3-face-cache nil)
   (w3-find-default-stylesheets)
-  )
-
-(defvar w3-loaded-stylesheets nil
-  "A list of all the stylesheets Emacs-W3 loaded at startup.")
+  (w3-style-post-process-stylesheet w3-user-stylesheet))
 
 (defun w3-find-default-stylesheets ()
-  (setq w3-loaded-stylesheets nil)
   (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/")
-		       (expand-file-name "../../w3" data-directory)
 		       (file-name-directory (locate-library "w3"))
 		       w3-configuration-directory))
 	 (total-found 0)
@@ -1926,9 +2135,10 @@
 		       (not (file-directory-p cur)) cur))
       (if found
 	  (setq total-found (1+ total-found)
-		w3-loaded-stylesheets (cons cur w3-loaded-stylesheets)
-		w3-user-stylesheet (css-parse (concat "file:" cur) nil
-				     w3-user-stylesheet))))
+		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
@@ -1957,8 +2167,7 @@
 				       w3-configuration-directory))
 					   
 
-  (if (and init-file-user
-	   w3-default-configuration-file
+  (if (and w3-default-configuration-file
 	   (file-exists-p w3-default-configuration-file))
       (condition-case e
 	  (load w3-default-configuration-file nil t)
@@ -1977,6 +2186,14 @@
 			       "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)))
@@ -1992,32 +2209,71 @@
 	    (expand-file-name "history"
 			      w3-configuration-directory)))
 
+  (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-lynx-emulation-minor-mode-map)
+		  w3-annotation-minor-mode-map)
   
   (setq url-package-version w3-version-number
 	url-package-name "Emacs-W3")
 
-  (w3-setup-terminal-chars)
-
   (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-hotlist-file (or w3-hotlist-file
+    (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-hotlist-file (or w3-hotlist-file
+    (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-hotlist-file (or w3-hotlist-file
+    (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)
@@ -2028,6 +2284,9 @@
   ; 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
@@ -2035,6 +2294,9 @@
 	    (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)
@@ -2042,7 +2304,12 @@
 
 (defun w3-mark-link-as-followed (ext dat)
   ;; Mark a link as followed
-  (message "Reimplement w3-mark-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)
@@ -2063,10 +2330,8 @@
 	      (file-name-handler-alist nil)
 	      (write-file-hooks nil)
 	      (write-contents-hooks nil)
-	      (enable-multibyte-characters t) ; mule 2.4
-	      (buffer-file-coding-system mule-no-coding-system) ; mule 2.4
-	      (file-coding-system mule-no-coding-system) ; mule 2.3
-	      (mc-flag t))		; mule 2.3
+	      (mc-flag t)
+	      (file-coding-system url-mule-no-coding-system))
 	  (write-file fname)
 	  (message "Download of %s complete." (url-view-url t))
 	  (sit-for 3)
@@ -2079,14 +2344,13 @@
 	 (urlobj (url-generic-parse-url url))
 	 (url-working-buffer
 	  (generate-new-buffer (concat " *" url " download*")))
-	 (stub-fname (url-basepath (or (url-filename urlobj) "") t))
-	 (dir (or mm-download-directory "~/"))
-	 (fname (expand-file-name
-		 (read-file-name "Filename to save as: "
-				 dir
-				 stub-fname
-				 nil
-				 stub-fname) dir)))
+	 (stub-fname (url-remove-compressed-extensions
+		      (url-basepath (or (url-filename urlobj) "") t)))
+	 (fname (read-file-name "Filename to save as: "
+				(or mm-download-directory "~/")
+				stub-fname
+				nil
+				stub-fname)))
     (setq-default url-be-asynchronous t)
     (save-excursion
       (set-buffer url-working-buffer)
@@ -2124,19 +2388,6 @@
      (t
       (w3-fetch href)))))
 
-;;; FIXME!  Need to rewrite these so that we can pass a predicate to 
-(defun w3-widget-forward (arg)
-  "Move point to the next field or button.
-With optional ARG, move across that many fields."
-  (interactive "p")
-  (widget-forward arg))
-
-(defun w3-widget-backward (arg)
-  "Move point to the previous field or button.
-With optional ARG, move across that many fields."
-  (interactive "p")
-  (w3-widget-forward (- arg)))
-
 (defun w3-complete-link ()
   "Choose a link from the current buffer and follow it"
   (interactive)
@@ -2148,24 +2399,20 @@
 	  link-at-point (and
 			 link-at-point
 			 (widget-get link-at-point 'href)
-			 (widget-get link-at-point :from)
-			 (widget-get link-at-point :to)
 			 (w3-fix-spaces
 			  (buffer-substring
-			   (widget-get link-at-point :from)
-			   (widget-get link-at-point :to)))))
+			   (car (widget-get link-at-point 'title))
+			   (cdr (widget-get link-at-point 'title))))))
     (w3-map-links (function
 		   (lambda (widget arg)
-		     (if (and (widget-get widget :from)
-			      (widget-get widget :to))
-			 (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))))))
+		     (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)
@@ -2185,15 +2432,20 @@
 				 (substring link-at-point 0 17) "..."))
 			      "): ")
 		    "Link: ") links-alist nil t))
-    (let ((match (try-completion choice links-alist)))
-      (cond
-       ((eq t match)			; We have an exact match
-	(setq choice (cdr (assoc choice links-alist))))
-       ((stringp match)
-	(setq choice (cdr (assoc match links-alist))))
-       (t (setq choice nil)))
-      (if choice
-	  (w3-fetch choice)))))
+    (if (string= choice "")
+	(w3-follow-link)
+      (w3-fetch (cdr (assoc choice links-alist))))))
+
+(defun w3-widget-motion-hook (widget)
+  (assert widget nil "Bad data to w3-widget-motion-hook!  Bad hook bad!")
+  (case w3-echo-link
+    (text
+     (message "%s" (w3-fix-spaces (buffer-substring (widget-get widget :from)
+						    (widget-get widget :to)))))
+    (url
+     (if (widget-get widget 'href)
+	 (message "%s" (widget-get widget 'href))))
+    (otherwise nil)))
 
 (defun w3-mode ()
   "Mode for viewing HTML documents.  If called interactively, will
@@ -2207,27 +2459,27 @@
       (w3-preview-this-buffer)
     (let ((tmp (mapcar (function (lambda (x) (cons x (symbol-value x))))
 		       w3-persistent-variables)))
-      ;; Oh gross, this kills buffer-local faces in XEmacs
-      ;;(kill-all-local-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)
-      (setq url-current-passwd-count 0
-	    inhibit-read-only nil
-	    truncate-lines t
-	    mode-line-format w3-modeline-format)
+      (make-local-hook 'widget-motion-hook)
+      (add-hook 'widget-motion-hook 'w3-widget-motion-hook)
       (run-hooks 'w3-mode-hook)
       (widget-setup)
-      (if w3-current-isindex
+      (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-display)
+(require 'w3-draw)
 (require 'w3-auto)
 (require 'w3-emulate)
 (require 'w3-menu)