home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / editors / emacs / xemacs / xemacs-1.006 / xemacs-1 / lib / xemacs-19.13 / lisp / w3 / w3.el < prev    next >
Encoding:
Text File  |  1995-08-31  |  111.8 KB  |  3,322 lines

  1. ;;; w3.el,v --- Main functions for emacs-w3 on all platforms/versions
  2. ;; Author: wmperry
  3. ;; Created: 1995/08/30 20:36:17
  4. ;; Version: 1.446
  5. ;; Keywords: faces, help, comm, news, mail, processes, mouse, hypermedia
  6.  
  7. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  8. ;;; Copyright (c) 1993, 1994, 1995 by William M. Perry (wmperry@spry.com)
  9. ;;;
  10. ;;; This file is not part of GNU Emacs, but the same permissions apply.
  11. ;;;
  12. ;;; GNU Emacs is free software; you can redistribute it and/or modify
  13. ;;; it under the terms of the GNU General Public License as published by
  14. ;;; the Free Software Foundation; either version 2, or (at your option)
  15. ;;; any later version.
  16. ;;;
  17. ;;; GNU Emacs is distributed in the hope that it will be useful,
  18. ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20. ;;; GNU General Public License for more details.
  21. ;;;
  22. ;;; You should have received a copy of the GNU General Public License
  23. ;;; along with GNU Emacs; see the file COPYING.  If not, write to
  24. ;;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  25. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  26.  
  27. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  28. ;;; This is a major mode for browsing documents written in Hypertext Markup ;;;
  29. ;;; Language (HTML).  These documents are typicallly part of the World Wide ;;;
  30. ;;; Web (WWW), a project to create a global information net in hypertext    ;;;
  31. ;;; format.                                                    ;;;
  32. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  33.  
  34. ;;; first start by making sure the load path is properly set.  This code
  35. ;;; is mostly taken from calc-2.02b
  36. ;;;
  37. ;;; this allows you to put the following in your .emacs file, instead of
  38. ;;; having to know what the load-path for the w3 files is.
  39. ;;;
  40. ;;;     (autoload 'w3 "w3/w3" "WWW Browser" t)
  41.  
  42. ;;; If w3 files exist on the load-path, we're all set.
  43. (let ((name (and (fboundp 'w3)
  44.          (eq (car-safe (symbol-function 'w3)) 'autoload)
  45.          (nth 1 (symbol-function 'w3))))
  46.       (p load-path))
  47.   (while (and p (not (file-exists-p
  48.               (expand-file-name "w3-vars.elc" (car p)))))
  49.     (setq p (cdr p)))
  50.   (or p
  51. ;;; If w3 is autoloaded using a path name, look there for w3 files.
  52. ;;; This works for both relative ("w3/w3.elc") and absolute paths.
  53.       (and name (file-name-directory name)
  54.        (let ((p2 load-path)
  55.          (name2 (concat (file-name-directory name)
  56.                 "w3-vars.elc")))
  57.          (while (and p2 (not (file-exists-p
  58.                   (expand-file-name name2 (car p2)))))
  59.            (setq p2 (cdr p2)))
  60.          (if p2
  61.          (setq load-path (nconc load-path
  62.                     (list
  63.                      (directory-file-name
  64.                       (file-name-directory
  65.                        (expand-file-name
  66.                         name (car p2)))))))))))
  67.   )
  68.  
  69.  
  70. (load-library "w3-sysdp.el")
  71. (or (featurep 'efs)
  72.     (featurep 'efs-auto)
  73.     (require 'ange-ftp))
  74. (require 'w3-vars)
  75.  
  76.  
  77. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  78. ;;; FORMS processing for html+
  79. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  80. (or (boundp 'MULE) (fset 'string-width 'length))
  81.  
  82. (defun w3-truncate-string (str len &optional pad)
  83.   "Truncate string STR so that string-width of STR is not greater than LEN.
  84. If width of the truncated string is less than LEN, and if a character PAD is
  85. defined, add padding end of it."
  86.   (if (boundp 'MULE)
  87.       (let ((cl (string-to-char-list str)) (n 0) (sw 0))
  88.     (if (<= (string-width str) len) str
  89.       (while (<= (setq sw (+ (char-width (nth n cl)) sw)) len)
  90.         (setq n (1+ n)))
  91.       (string-match (make-string n ?.) str)
  92.       (setq str (substring str 0 (match-end 0))))
  93.     (if pad (concat str (make-string (- len (string-width str)) pad)) str))
  94.     (concat (if (> (length str) len) (substring str 0 len) str)
  95.         (if (or (null pad) (> (length str) len))
  96.         ""
  97.           (make-string (- len (length str)) pad)))))
  98.  
  99. (defun w3-form-format-int (&rest args)
  100.   (w3-truncate-string (or (nth 0 args) "") (nth 1 args) ?_))
  101.  
  102. (fset 'w3-form-format-url 'w3-form-format-int)
  103. (fset 'w3-form-format-float 'w3-form-format-int)
  104. (fset 'w3-form-format-date 'w3-form-format-int)
  105.  
  106. (defun w3-form-format-reset (&rest args)
  107.   (if (string= (nth 0 args) "") "Reset fields" (nth 0 args)))
  108.  
  109. (defun w3-form-format-password (&rest args)
  110.   (let ((value (or (nth 0 args) ""))
  111.     (size (nth 1 args)))
  112.     (concat (if (>= (length value) size) (make-string size ?*)
  113.           (make-string (length value) ?*))
  114.         (if (>= (length value) size) ""
  115.           (make-string (- size (length value)) ?.)))))
  116.  
  117. (defun w3-form-format-checkbox (&rest args)
  118.   (concat "[" (if (nth 2 args) "X" " ") "]"))
  119.  
  120. (fset 'w3-form-format-radio 'w3-form-format-checkbox)
  121.  
  122. (defun w3-form-format-submit (&rest args)
  123.   (if (string= (nth 0 args) "") "Submit this form" (nth 0 args)))
  124.  
  125. (defun w3-form-format-text (&rest args)
  126.   (w3-truncate-string (nth 0 args) (nth 1 args) ?_))
  127.  
  128. (defun w3-form-format-textarea (&rest args)
  129.   "Multiline text entry")
  130.  
  131. (defun w3-form-format-image (&rest args)
  132.   (car (nth 2 args)))
  133.   
  134. (fset 'w3-form-format- 'w3-form-format-text)
  135. (fset 'w3-form-format-unknown 'w3-form-format-text)
  136.  
  137. (defun w3-do-text-entry (formobj zone)
  138.   (let ((data (list formobj zone (current-buffer)))
  139.     (buff (get-buffer-create (format "%d:%s" (nth 9 formobj)
  140.                      (nth 3 formobj)))))
  141.     (switch-to-buffer-other-window buff)
  142.     (indented-text-mode)
  143.     (erase-buffer)
  144.     (and (nth 5 formobj) (w3-insert (nth 5 formobj)))
  145.     (setq w3-current-last-buffer data)
  146.     (message "Press C-c C-c when finished with text entry.")
  147.     (local-set-key "\C-c\C-c" 'w3-finish-text-entry)))
  148.  
  149. (defun w3-finish-text-entry ()
  150.   (interactive)
  151.   (if w3-current-last-buffer
  152.       (let* ((formobj (nth 0 w3-current-last-buffer))
  153.          (zone (nth 1 w3-current-last-buffer))
  154.          (buff (nth 2 w3-current-last-buffer))
  155.          (actn (nth 1 formobj))
  156.          (type (nth 2 formobj))
  157.          (name (nth 3 formobj))
  158.          (deft (nth 4 formobj))
  159.          (valu (buffer-string))
  160.          (chkd (nth 6 formobj))
  161.          (size (nth 7 formobj))
  162.          (maxl (nth 8 formobj))
  163.          (ident (nth 9 formobj))
  164.          (options (nth 10 formobj))
  165.          (st nil)
  166.          (nd nil))
  167.     (local-set-key "\C-c\C-c" 'undefined)
  168.     (kill-buffer (current-buffer))
  169.     (condition-case ()
  170.         (delete-window)
  171.       (error nil))
  172.     (if (not (and buff (bufferp buff) (buffer-name buff)))
  173.         (message "Could not find the form buffer for this text!")
  174.       (switch-to-buffer buff)
  175.       (if buffer-read-only (toggle-read-only))
  176.       (setq st (w3-zone-start zone)
  177.         nd (w3-zone-end zone))
  178.       (w3-delete-zone zone)
  179.       (w3-add-zone st nd w3-node-style
  180.                (list 'w3form actn type name deft valu chkd
  181.                  size maxl ident options) t)))
  182.     (if (not buffer-read-only) (toggle-read-only))
  183.     nil))
  184.  
  185. (defun w3-do-form-entry (formobj zone)
  186. ;;; Read in a form entry field.
  187. ;;;FORMOBJ is the data returned by w3-zone-at, and contains all the information
  188. ;;;        about the entry area (size, type, value, etc)
  189. ;;;ZONE is the actual zone object.  This should be able to be passed to
  190. ;;;     w3-delete-zone."
  191.   (let* ((actn (nth 1 formobj))
  192.      (type (nth 2 formobj))
  193.      (name (nth 3 formobj))
  194.      (deft (nth 4 formobj))
  195.      (valu (nth 5 formobj))
  196.      (chkd (nth 6 formobj))
  197.      (size (nth 7 formobj))
  198.      (maxl (nth 8 formobj))
  199.      (ident (nth 9 formobj))
  200.      (options (nth 10 formobj))
  201.      (id (nth 11 formobj))
  202.      (st (w3-zone-start zone))
  203.      (nd (w3-zone-end zone))
  204.      (submit-it nil)
  205.      (formatfun (intern (concat "w3-form-format-" (downcase type)))))
  206.     (if (not (member type '("SUBMIT" "IMAGE")))
  207.     (progn
  208.       (if (equal "TEXTAREA" type)
  209.           (progn
  210.         (if (not buffer-read-only) (toggle-read-only))
  211.         (w3-do-text-entry formobj zone)))
  212.       (save-excursion
  213.         (if (not (fboundp formatfun))
  214.         (setq formatfun 'w3-form-format-unknown))
  215.         (if buffer-read-only (toggle-read-only))
  216.         (cond
  217.          ((equal "CHECKBOX" type) (setq chkd (not chkd)))
  218.          ((equal "RADIO" type) nil)
  219.          ((equal "TEXTAREA" type) nil)
  220.          ((equal "RESET" type) (w3-revert-form ident))
  221.          (t (setq valu
  222.               (w3-read-correct-format type name options
  223.                           ident valu maxl))))
  224.         (if (and maxl (not (consp maxl)) (> (length valu) maxl))
  225.         (progn
  226.           (setq valu (substring valu 0 maxl))
  227.           (message "Truncated to %d chars (%s)" maxl valu)))
  228.         (cond
  229.          ((equal "RESET" type) nil)
  230.          ((equal "RADIO" type) (w3-set-radio-button zone))
  231.          ((equal "TEXTAREA" type) nil)
  232.          (t
  233.           (w3-delete-zone zone)
  234.           (delete-region st nd)
  235.           (goto-char st)
  236.           (w3-insert (funcall formatfun valu size chkd))
  237.           (w3-add-zone st (point) w3-node-style
  238.                (list 'w3form actn type name deft valu chkd
  239.                  size maxl ident options id) t)
  240.           (set-buffer-modified-p nil)
  241.           (if (not buffer-read-only) (toggle-read-only))
  242.           (if w3-running-FSF19 (setq w3-zones-list (w3-only-links)))
  243.            (if (boundp 'MULE) (w3-mule-attribute-zones w3-zones-list))
  244.           ))
  245.         (cond
  246.          ((null name) (setq submit-it nil))
  247.          ((string-match "^isindex$" name) (setq submit-it 'isindex))
  248.          ((string-match "^internal-gopher$" name) (setq submit-it 'gopher))
  249.          ((string-match "^internal-wais$" name) (setq submit-it 'wais))
  250.          ((equal (length (w3-zones-matching ident)) 1)
  251.           (setq submit-it t)))))
  252.       (let* ((name (cdr chkd))
  253.          (local-hidden-forms
  254.           (if (string= type "IMAGE")
  255.           (append (list
  256.                (list 'w3form actn "HIDDEN" (concat name ".x") "0"
  257.                  "0" nil nil nil ident nil)
  258.                (list 'w3form actn "HIDDEN" (concat name ".y") "0"
  259.                  "0" nil nil nil ident nil))
  260.               w3-hidden-forms))))
  261.     (setq w3-submit-button (if (string= type "IMAGE") nil zone))
  262.     (w3-submit-form ident nil actn)))
  263.     (if submit-it (w3-submit-form ident submit-it actn))))
  264.  
  265. (defun w3-zones-matching (actn &optional raw)
  266.   ;; Return a list of data entry zones in form number ACTN
  267.   ;; With optional second argument raw, don't grab the data of the zone, but
  268.   ;; return the actual zone."
  269.   (let* ((big (w3-all-zones))
  270.      (data nil)
  271.      (result nil))
  272.     ;; Gag Puke Retch
  273.     ;; Sort the list so truly _IDIOTIC_ and _BRAIN DEAD_ people who don't
  274.     ;; know how to write decent form interface scripts and rely on the order
  275.     ;; of the elements being submitted don't screw us over.
  276.     (setq big (sort big (function
  277.              (lambda (x y)
  278.                (< (w3-zone-start x) (w3-zone-start y))))))
  279.     (while big
  280.       (setq data (w3-zone-data (car big)))
  281.       (if (and (eq (nth 0 data) 'w3form) ; Its a form field
  282.            (equal (nth 9 data) actn) ; Its in our form
  283.            (not (string= (nth 2 data) "IMAGE")) ; Don't want images
  284.            (not (string= (nth 2 data) "RESET")) ; Don't want resets
  285.            )
  286.       (setq result (cons (if raw (car big) data) result)))
  287.       (setq big (cdr big)))
  288.     (if raw
  289.     nil
  290.       (setq big (or (and (boundp 'local-hidden-forms)
  291.              (symbol-value 'local-hidden-forms))
  292.             w3-hidden-forms))
  293.       (while big
  294.     (setq data (car big))
  295.     (if (and (eq (nth 0 data) 'w3form) (equal (nth 9 data) actn))
  296.         (setq result (cons data result)))
  297.     (setq big (cdr big))))
  298.     result))
  299.  
  300. (defun w3-revert-form (actn)
  301.   (save-excursion
  302.     (let* ((zones (w3-zones-matching actn t))
  303.        actn data type name deft valu chkd size maxl idnt strt end cur
  304.        options id formatfun
  305.        )
  306.       (if buffer-read-only (toggle-read-only))
  307.       (mapcar
  308.        (function
  309.     (lambda (cur)
  310.       (setq data (w3-zone-data cur)
  311.         actn (nth 1 data)
  312.         type (nth 2 data)
  313.         name (nth 3 data)
  314.         deft (nth 4 data)
  315.         valu (nth 5 data)
  316.         chkd (nth 6 data)
  317.         size (nth 7 data)
  318.         maxl (nth 8 data)
  319.         idnt (nth 9 data)
  320.         options (nth 10 data)
  321.         id (nth 11 data)
  322.         strt (w3-zone-start cur)
  323.         end  (w3-zone-end cur)
  324.         formatfun (intern (concat "w3-form-format-" (downcase type))))
  325.       (if (not (fboundp formatfun))
  326.           (setq formatfun 'w3-form-format-unknown))
  327.       (cond
  328.        ((or (member type '("SUBMIT" "RESET"))) nil)
  329.        (t
  330.         (if (member type '("RADIO" "CHECKBOX"))
  331.         (setq chkd deft)
  332.           (setq valu deft))
  333.         (w3-delete-zone cur)
  334.         (delete-region strt end)
  335.         (goto-char strt)
  336.         (w3-insert (funcall formatfun valu size chkd))
  337.         (w3-add-zone strt (point) w3-node-style
  338.              (list 'w3form actn type name deft valu chkd
  339.                    size maxl idnt options id) t))))) zones)
  340.       (if (not buffer-read-only) (toggle-read-only)))
  341.     (if w3-running-FSF19
  342.     (setq w3-zones-list (w3-only-links)))
  343.     (if (boundp 'MULE) (w3-mule-attribute-zones w3-zones-list))
  344.     ))
  345.  
  346. (defun w3-form-encode-make-mime-part (id data separator)
  347.   (concat separator "\nContent-id: " id
  348.       "\nContent-length: " (length data)
  349.       "\n\n" data))
  350.  
  351. (defun w3-form-encode-multipart/x-www-form-data (formobjs isindex-query)
  352.   ;; Create a multipart form submission.
  353.   ;; Returns a cons of two strings.  Car is the separator used.
  354.   ;; cdr is the body of the MIME message."
  355.   (let ((separator "---some-separator-for-www-form-data"))
  356.     (cons separator
  357.       (mapconcat
  358.        (function
  359.         (lambda (formobj)
  360.           (cond
  361.            ((and (member (nth 2 formobj) '("CHECKBOX" "RADIO"))
  362.              (nth 6 formobj))
  363.         (w3-form-encode-make-mime-part (or (nth 3 formobj)
  364.                            (nth 2 formobj)
  365.                            "unknown")
  366.                            (nth 5 formobj) separator))
  367.            ((and (member (nth 2 formobj) '("CHECKBOX" "RADIO"))
  368.              (not (nth 6 formobj)))
  369.         "")
  370.            ((member (nth 2 formobj)
  371.                         '("RESET" "SUBMIT" "CHECKBOX" "RADIO"))
  372.                 (let ((submit-button-data
  373.                        (if w3-submit-button
  374.                            (w3-zone-data w3-submit-button))))
  375.                   (if (and submit-button-data
  376.                            (nth 3 submit-button-data))
  377.                       (prog1
  378.                           (w3-form-encode-make-mime-part
  379.                            (nth 3 submit-button-data)
  380.                            (nth 5 submit-button-data)
  381.                            separator)
  382.                         (setq w3-submit-button nil))
  383.                     "")))
  384.            ((and (string= (nth 2 formobj) "OPTION")
  385.              (assoc (nth 5 formobj) (nth 6 formobj)))
  386.         (w3-form-encode-make-mime-part (or (nth 3 formobj)
  387.                            (nth 2 formobj)
  388.                            "unknown")
  389.                            (cdr (assoc (nth 5 formobj)
  390.                                (nth 6 formobj)))
  391.                            separator))
  392.            ((string= (nth 2 formobj) "FILE")
  393.         (let ((dat nil)
  394.               (fname (nth 5 formobj)))
  395.           (save-excursion
  396.             (set-buffer (get-buffer-create " *w3-temp*"))
  397.             (erase-buffer)
  398.             (setq dat
  399.               (condition-case ()
  400.                   (mm-insert-file-contents fname)
  401.                 (error (concat "Error accessing " fname)))))
  402.           (w3-form-encode-make-mime-part (or (nth 3 formobj)
  403.                              (nth 2 formobj)
  404.                              "unknown")
  405.                          dat separator)))
  406.            (t
  407.         (w3-form-encode-make-mime-part (or (nth 3 formobj)
  408.                            (nth 2 formobj)
  409.                            "unknown")
  410.                            (nth 5 formobj)
  411.                            separator)))))
  412.        formobjs "\n"))))
  413.  
  414. (fset 'w3-form-encode-multipart/form-data
  415.       'w3-form-encode-multipart/x-www-form-data)
  416.  
  417. (defun w3-form-encode (result &optional isindex-query enctype)
  418.   "Create a string suitably encoded for a URL request."
  419.   (let ((func (intern (concat "w3-form-encode-" enctype))))
  420.     (if (fboundp func) (funcall func result isindex-query))))
  421.  
  422. (defun w3-form-encode-text/plain (result &optional isindex-query)
  423.   (let ((query ""))
  424.     (setq query
  425.       (mapconcat
  426.        (function
  427.         (lambda (formobj)
  428.           (cond
  429.            ((and (member (nth 2 formobj) '("CHECKBOX" "RADIO"))
  430.              (nth 6 formobj))
  431.         (concat "\n" (or (nth 3 formobj) (nth 2 formobj)) " "
  432.             (nth 5 formobj)))
  433.            ((member (nth 2 formobj)
  434.                         '("RESET" "SUBMIT" "CHECKBOX" "RADIO"))
  435.                 (let ((submit-button-data
  436.                        (if w3-submit-button
  437.                            (w3-zone-data w3-submit-button))))
  438.                   (if (and submit-button-data (nth 3 submit-button-data))
  439.                       (prog1
  440.                           (concat "\n" (nth 3 submit-button-data) " "
  441.                                   (nth 5 submit-button-data))
  442.                         (setq w3-submit-button nil))
  443.                     "")))
  444.            ((string= (nth 2 formobj) "TEXTAREA")
  445.         (concat "\n" (or (nth 3 formobj) (nth 2 formobj)) " "
  446.             (mapconcat
  447.              (function
  448.               (lambda (x)
  449.                 (if (= x ?\n) "," (char-to-string x))))
  450.              (nth 5 formobj) "")))
  451.            ((and (string= (nth 2 formobj) "OPTION")
  452.              (assoc (nth 5 formobj) (nth 6 formobj)))
  453.         (concat "\n" (or (nth 3 formobj) (nth 2 formobj)) " "
  454.             (cdr (assoc (nth 5 formobj) (nth 6 formobj)))))
  455.            (t
  456.         (concat "\n" (or (nth 3 formobj) (nth 2 formobj)) " "
  457.             (nth 5 formobj)))))) result ""))
  458.     (if (string= query "") nil
  459.       (setq query (substring query 1 nil)))
  460.     query))
  461.  
  462. (defun w3-form-encode-application/x-gopher-query (result &optional isindex)
  463.   (concat "\t" (nth 5 (car result))))
  464.  
  465. (defun w3-form-encode-application/x-www-form-urlencoded (result &optional isindex-query)
  466.   (let ((query ""))
  467.     (cond
  468.      ((eq isindex-query 'isindex)    ; Isindex handling by hypertext
  469.       (while result
  470.     (if (equal (downcase (or (nth 3 (car result)) "")) "isindex")
  471.         (setq query (url-hexify-string (nth 5 (car result)))
  472.           result nil))
  473.     (setq result (cdr result))))
  474.      (t                    ; Normal submission of form
  475.                     ; This is a little convoluted, but
  476.                     ; gets only checkboxes that are set
  477.                     ; and ignores submit & reset buttons
  478.       (setq query
  479.         (mapconcat
  480.          (function
  481.           (lambda (formobj)
  482.         (cond
  483.          ((and (member (nth 2 formobj) '("CHECKBOX" "RADIO"))
  484.                (nth 6 formobj))
  485.           (concat "&" (or (nth 3 formobj) (nth 2 formobj)) "="
  486.               (url-hexify-string (nth 5 formobj))))
  487.          ((and (member (nth 2 formobj) '("CHECKBOX" "RADIO"))
  488.                (not (nth 6 formobj))) "")
  489.          ((member (nth 2 formobj)
  490.                           '("RESET" "SUBMIT" "CHECKBOX" "RADIO"))
  491.                   (let ((submit-button-data
  492.                          (if w3-submit-button
  493.                              (w3-zone-data w3-submit-button))))
  494.                     (if (and submit-button-data (nth 3 submit-button-data))
  495.                         (prog1
  496.                             (concat "&"
  497.                                     (nth 3 submit-button-data)
  498.                                     "="
  499.                                     (url-hexify-string
  500.                                      (nth 5 submit-button-data)))
  501.                           (setq w3-submit-button nil))
  502.                       "")))
  503.          ((and (string= (nth 2 formobj) "OPTION")
  504.                (assoc (nth 5 formobj) (nth 6 formobj)))
  505.           (concat "&" (or (nth 3 formobj) (nth 2 formobj)) "="
  506.               (url-hexify-string
  507.                (cdr (assoc (nth 5 formobj) (nth 6 formobj))))))
  508.          ((string= (nth 2 formobj) "FILE")
  509.           (let ((dat nil)
  510.             (fname (nth 5 formobj)))
  511.             (save-excursion
  512.               (set-buffer (get-buffer-create " *w3-temp*"))
  513.               (erase-buffer)
  514.               (setq dat
  515.                 (condition-case ()
  516.                 (progn
  517.                   (mm-insert-file-contents fname)
  518.                   (buffer-string))
  519.                   (error (concat "Error accessing " fname)))))
  520.             (concat "&" (or (nth 3 formobj) (nth 2 formobj) "unknown")
  521.                 "=" (url-hexify-string dat))))
  522.          (t
  523.           (concat "&" (or (nth 3 formobj) (nth 2 formobj)) "="
  524.               (url-hexify-string (nth 5 formobj)))))))
  525.          result ""))
  526.       (if (string= "" query) ""
  527.     (setq query (substring query 1 nil)))))
  528.     query))
  529.  
  530. (defun w3-form-encode-application/gopher-ask-block (result)
  531.   (let ((query ""))
  532.     ;;; gopher+ will expect all the checkboxes/etc, even if they are
  533.     ;;; not turned on.  Should still ignore RADIO boxes that are not
  534.     ;;; active though.
  535.   (while result
  536.     (if (and (not (and (string= (nth 2 (car result)) "RADIO")
  537.                (not (nth 6 (car result)))))
  538.          (not (member (nth 2 (car result)) '("SUBMIT" "RESET"))))
  539.     (setq query (format "%s\r\n%s" query (nth 5 (car result)))))
  540.     (setq result (cdr result)))
  541.   (concat query "\r\n.\r\n")))
  542.  
  543. (defun w3-submit-form (ident isindex &optional actn)
  544.   ;; Submit form entry fields matching ACTN as their action identifier.
  545.   (let* ((result (reverse (w3-zones-matching ident)))
  546.      (enctype (cdr (assoc "enctype" actn)))
  547.      (query (w3-form-encode result isindex enctype))
  548.      (themeth (upcase (cdr (assoc "method" actn))))
  549.      (theurl (cdr (assoc "action" actn))))
  550.     (if (and (string= "GET" themeth)
  551.          (string-match "\\([^\\?]*\\)\\?" theurl))
  552.     (setq theurl (url-match theurl 1)))
  553.     (cond
  554.      ((eq isindex 'gopher) (w3-fetch (concat theurl query)))
  555.      ((eq isindex 'wais)
  556.       (url-perform-wais-query url-current-server url-current-port
  557.                  url-current-file
  558.                  (if (equal (substring query 0 14)
  559.                     "internal-wais=")
  560.                  (substring query 14) query))
  561.       (w3-sentinel))
  562.      ((string= "GOPHER-ASK" themeth)
  563.       (setq query (w3-form-encode-ask-block result))
  564.       (w3-fetch (concat theurl (url-hexify-string (concat "\t+\t1\n+-1\r\n"
  565.                              query)))))
  566.      ((or (string= "POST" themeth)
  567.       (string= "PUT" themeth))
  568.       (if (consp query)
  569.       (setq enctype (concat enctype "; separator=\"" (substring (car query) 3 nil)
  570.                 "\"")
  571.         query (cdr query)))
  572.       (let ((url-request-method themeth)
  573.         (url-request-data query)
  574.         (url-request-extra-headers
  575.          (cons (cons "Content-type" enctype) url-request-extra-headers)))
  576.     (w3-fetch theurl)))
  577.      ((string= "GET" themeth)
  578.       (let ((theurl (concat theurl "?" query)))
  579.     (w3-fetch theurl)))
  580.      (t (message "Unknown submit method: %s" themeth)))))
  581.  
  582. (defun w3-matching-radios (ext)
  583.   ;; Return a list of all zones containing radio buttons with the same name
  584.   ;; as that in EXT.
  585.   (let* ((big (w3-all-zones))
  586.      (idnt (nth 9 (w3-zone-data ext)))
  587.      (name (nth 3 (w3-zone-data ext)))
  588.      data cur result)
  589.     (mapcar
  590.      (function
  591.       (lambda (cur)
  592.     (setq data (w3-zone-data cur))
  593.     (if (and
  594.          (eq (nth 0 data) 'w3form)
  595.          (equal (nth 9 data) idnt)
  596.          (equal (nth 3 data) name))
  597.         (setq result (cons cur result))))) big)
  598.     result))
  599.  
  600. (defun w3-set-radio-button (ext)
  601.   ;; Set the radio button at EXT to be on.  Will automatically
  602.   ;; toggle other radio butons with the same name to be off.
  603.   (save-excursion
  604.     (let* ((result (w3-matching-radios ext))
  605.        (idnt (nth 9 (w3-zone-data ext)))
  606.        (name (nth 3 (w3-zone-data ext)))
  607.        actn type deft valu chkd size maxl strt end data options id)
  608.       (while result
  609.     (setq data (w3-zone-data (car result))
  610.           actn (nth 1 data)
  611.           type (nth 2 data)
  612.           name (nth 3 data)
  613.           deft (nth 4 data)
  614.           valu (nth 5 data)
  615.           chkd (nth 6 data)
  616.           size (nth 7 data)
  617.           maxl (nth 8 data)
  618.           idnt (nth 9 data)
  619.           options (nth 10 data)
  620.           id (nth 11 data)
  621.           strt (w3-zone-start (car result))
  622.           end (w3-zone-end (car result)))
  623.     (cond
  624.      ((and chkd (not (w3-zone-eq
  625.               ext (car result)))) ; Not supposed to be chkd
  626.       (w3-delete-zone (car result))          ; but is.
  627.       (goto-char strt)
  628.       (delete-region strt end)
  629.       (setq chkd nil)
  630.       (w3-insert (funcall 'w3-form-format-radio valu size chkd))
  631.       (w3-add-zone strt (point) w3-node-style
  632.                (list 'w3form actn type name deft valu chkd size maxl
  633.                  idnt options id) t))
  634.      ((and (not chkd) (w3-zone-eq
  635.                ext (car result))) ; Supposed to be chkd
  636.       (w3-delete-zone (car result))       ; but isn't.
  637.       (goto-char strt)
  638.       (delete-region strt end)
  639.       (setq chkd t)
  640.       (w3-insert (funcall 'w3-form-format-radio valu size chkd))
  641.       (w3-add-zone strt (point) w3-node-style
  642.                (list 'w3form actn type name deft valu chkd size maxl
  643.                  idnt options id) t))
  644.      (t nil)) ; not supposed to be checked, and isn't
  645.     (setq result (cdr result))))
  646.     (if (not buffer-read-only) (toggle-read-only))
  647.     (if w3-running-FSF19 (setq w3-zones-list (w3-only-links)))
  648.     (if (boundp 'MULE) (w3-mule-attribute-zones w3-zones-list))
  649.     ))
  650.  
  651.  
  652. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  653. ;;; Type checking for FORMS
  654. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  655.  
  656. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  657. ;;; Date checking, taken from edb.el
  658. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  659.  
  660. (defconst weekday-alist
  661.  '(("Sunday" . 0) ("Monday" . 1) ("Tuesday" . 2) ("Wednesday" . 3)
  662.    ("Thursday" . 4) ("Friday" . 5) ("Saturday" . 6)
  663.    ("Tues" . 2) ("Thurs" . 4)
  664.    ("Sun" . 0) ("Mon" . 1) ("Tue" . 2) ("Wed" . 3)
  665.    ("Thu" . 4) ("Fri" . 5) ("Sat" . 6)))
  666.  
  667. (defconst full-monthname-alist
  668.   '(("January" . 1) ("February" . 2) ("March" . 3) ("April" . 4)
  669.     ("May" . 5) ("June" . 6) ("July" . 7) ("August" . 8)
  670.     ("September" . 9) ("October" . 10) ("November" . 11) ("December" . 12)))
  671.  
  672. (defconst monthabbrev-alist
  673.   '(("Jan" . 1) ("Feb" . 2) ("Mar" . 3) ("Apr" . 4) ("May" . 5) ("Jun" . 6)
  674.     ("Jul" . 7) ("Aug" . 8) ("Sep" . 9) ("Oct" . 10) ("Nov" . 11) ("Dec" . 12))
  675.   )
  676.  
  677. (defconst monthname-alist
  678.   (append monthabbrev-alist
  679.       full-monthname-alist
  680.       '(("Sept" . 9))))
  681.  
  682. (defconst monthname-regexp
  683.   (concat "\\("
  684.       (mapconcat (function car)
  685.              monthname-alist
  686.              "\\|")
  687.       "\\)\\.?"))
  688.  
  689. (defconst weekday-regexp
  690.   (concat "\\("
  691.       (mapconcat (function car)
  692.              weekday-alist
  693.              "\\|")
  694.       "\\)\\.?"))
  695.  
  696. (defconst monthnumber-regexp "\\(0?[1-9]\\|1[0-2]\\)")
  697. (defconst monthnumber-regexp-two-char "\\(0[1-9]\\|1[0-2]\\)")
  698.  
  699. (defconst monthday-regexp "\\(0?[1-9]\\|[12][0-9]\\|3[01]\\)")
  700. (defconst monthday-regexp-two-char "\\([0-2][0-9]\\|3[01]\\)")
  701.  
  702. (defconst full-year-regexp "[0-2][0-9][0-9][0-9]")
  703. (defconst short-year-regexp "[0-9][0-9]")
  704.  
  705. (defconst year-regexp (concat "\\(" full-year-regexp
  706.                   "\\|" short-year-regexp "\\)"))
  707.  
  708. (defconst elt-separator-regexp "[ -.,/']+")
  709.  
  710. (defconst date-regexps
  711.   (list
  712.    ;; MMDDYY
  713.    (cons (concat monthname-regexp
  714.          elt-separator-regexp
  715.          monthday-regexp
  716.          "\\("
  717.          elt-separator-regexp
  718.          year-regexp
  719.          "\\)?")
  720.      '(4 nil 1 2))
  721.    (cons (concat monthnumber-regexp
  722.          elt-separator-regexp
  723.          monthday-regexp
  724.          "\\("
  725.          elt-separator-regexp
  726.          year-regexp
  727.          "\\)?")
  728.      '(4 1 nil 2))
  729.    ;; DDMMYY
  730.    (cons (concat monthday-regexp
  731.          elt-separator-regexp
  732.          monthname-regexp
  733.          "\\("
  734.          elt-separator-regexp
  735.          year-regexp
  736.          "\\)?")
  737.      '(4 nil 2 1))
  738.    (cons (concat "\\("
  739.          monthday-regexp
  740.          elt-separator-regexp
  741.          "\\)?"
  742.          monthname-regexp
  743.          elt-separator-regexp
  744.          year-regexp)
  745.      '(4 nil 3 2))
  746.    (cons (concat monthday-regexp
  747.          elt-separator-regexp
  748.          monthnumber-regexp
  749.          elt-separator-regexp
  750.          "\\(" full-year-regexp "\\)")
  751.      '(3 2 nil 1))
  752.    ;; YYMMDD
  753.    ;; Using year-regexp instead of full-year-regexp is ambiguous (consider
  754.    ;; 11-11-11), but we already tried MMDDYY and it failed.
  755.    (cons (concat year-regexp
  756.          elt-separator-regexp
  757.          monthname-regexp
  758.          elt-separator-regexp
  759.          monthday-regexp)
  760.      '(1 nil 2 3))
  761.    (cons (concat year-regexp
  762.          elt-separator-regexp
  763.          monthnumber-regexp
  764.          elt-separator-regexp
  765.          monthday-regexp)
  766.      '(1 2 nil 3))
  767.    ;; YYMMDD, no separators
  768.    ;; This is ambiguous.
  769.    (cons (concat year-regexp
  770.          monthnumber-regexp-two-char "?"
  771.          monthday-regexp-two-char "?")
  772.      '(1 2 nil 3))
  773.    ;; WWMMDDYY
  774.    (cons (concat weekday-regexp
  775.          elt-separator-regexp
  776.          monthname-regexp
  777.          elt-separator-regexp
  778.          monthday-regexp
  779.          "\\("
  780.          elt-separator-regexp
  781.          year-regexp
  782.          "\\)?")
  783.      '(5 nil 2 3))
  784.    ;; WWDDMMYY
  785.    (cons (concat weekday-regexp
  786.          elt-separator-regexp
  787.          monthday-regexp
  788.          elt-separator-regexp
  789.          monthname-regexp
  790.          "\\("
  791.          elt-separator-regexp
  792.          year-regexp
  793.          "\\)?")
  794.      '(5 nil 3 2))
  795.    ;; ctime
  796.    (cons (concat
  797.       weekday-regexp
  798.       " "
  799.       monthname-regexp
  800.       "  ?"
  801.       monthday-regexp
  802.       ;; time of day
  803.       " [0-9:]+ "
  804.       "\\(" full-year-regexp "\\)")
  805.      '(4 nil 2 3))
  806.    )
  807.   "Assoc list of regexps and match locators.
  808. A match locator is a list of four numbers indicating which submatch of the
  809. regexp contains the year, month number, month name, and day of the month.
  810. The list elements may be nil if that information is not available.")
  811.  
  812. (defun w3-datep (date-string)
  813.   (let ((regexp-alist date-regexps)
  814.     result)
  815.     (if (zerop (length date-string))    ;if empty string,
  816.     (setq result t)            ;empty date is kosher
  817.       ;; regexp-alist is nulled if a match is found
  818.       (progn
  819.     (while regexp-alist
  820.       (if (string-match (concat "^" (car (car regexp-alist)) "$")
  821.                 date-string)
  822.           (setq regexp-alist nil
  823.             result t)
  824.         ;; string-match failed
  825.         (setq regexp-alist (cdr regexp-alist))))))
  826.     result))
  827.  
  828. (defun w3-intp (str)
  829.   (string-match "^[0-9]+$" str))
  830.  
  831. (defun w3-floatp (str)
  832.   (let (x y)
  833.     (if (string-match "^\\([0-9]+\\)\\.\\([0-9]+\\)$" str)
  834.     (progn
  835.       (setq x (substring str (match-beginning 1) (match-end 1))
  836.         y (substring str (match-beginning 2) (match-end 2)))
  837.       (and (w3-intp x) (w3-intp y)))
  838.       (w3-intp str))))
  839.  
  840. (defun w3-urlp (str)
  841.   (string-match url-nonrelative-link str))
  842.  
  843. (defun w3-optionp (val)
  844.   (if (null val)
  845.       (progn
  846.     (message "Please make a selection from the menu")
  847.     nil)
  848.     t))
  849.  
  850. (defun w3-textp (str) t)        ; don't care whats in a text field
  851. (fset 'w3-p 'w3-textp)            ; for default of "" to be text
  852. (fset 'w3-passwordp 'w3-textp)        ; don't care whats in a paswd either
  853. (fset 'w3-textareap 'w3-textp)        ; try this - might work
  854. (fset 'w3-rangep 'w3-textp)        ; Range is already checked in rcf
  855.  
  856. (defun w3-filep (fname)
  857.   (and (file-exists-p fname) (file-readable-p fname)))
  858.  
  859. (defun w3-read-correct-format (type name options num value maxl)
  860.   ;; Read in a FORMS entry with type TYPE, and do typechecking
  861.   ;; will not exit the function until correct type has been entered.
  862.   (let ((func (intern (concat "w3-" (downcase type) "p")))
  863.     (valu value) exitp)
  864.     (while (not exitp)
  865.       (cond
  866.        ((or (equal "TEXT" type)
  867.         (equal "" type))
  868.     (setq valu (read-string "Enter text: " valu)))
  869.        ((equal "FILE" type)
  870.     (setq valu (expand-file-name (read-file-name "Send file: " "~/"
  871.                              (or valu "/nonexistent")
  872.                              t (or valu "~/")))))
  873.        ((or (equal "FLOAT" type)
  874.         (equal "INT" type))
  875.     (setq valu (read-string "Enter numeric value: " valu)))
  876.        ((equal "PASSWORD" type)
  877.     (setq valu (funcall url-passwd-entry-func "Enter password:" valu)))
  878.        ((equal "OPTION" type)
  879.     (if (or (and (boundp 'last-input-event)
  880.              (listp last-input-event)
  881.              (fboundp 'w3-x-popup-menu))
  882.         (and (boundp 'last-input-event)
  883.              (fboundp 'button-event-p)
  884.              (button-event-p last-input-event)
  885.              (fboundp 'w3-x-popup-menu)))
  886.         (setq valu (w3-x-popup-menu last-input-event
  887.                     (list "WWW"
  888.                           (cons "Select An Item"
  889.                             options))))
  890.       (setq valu
  891.         (let* ((completion-ignore-case t)
  892.                (prompt
  893.             (concat "Please choose (default: " valu "): "))
  894.                (dat (completing-read prompt options nil t)))
  895.           (if (string= dat "") valu dat))))
  896.     (if (consp valu) (setq valu (car valu))))
  897.        ((equal "RANGE" type)
  898.     (let ((done nil)
  899.           (min (car maxl))
  900.           (max (cdr maxl))
  901.           (tmp ))
  902.       (setq tmp (min min max)
  903.         max (max min max)
  904.         min tmp)
  905.       (while (not done)
  906.         (setq valu (string-to-int
  907.             (read-string (concat "Value (" min " - " max "): ")))
  908.           done (and (<= valu max) (>= valu min)))
  909.         (if (not done)
  910.         (progn
  911.           (message "Please enter a number between %d and %d!" min
  912.                max)
  913.           (sit-for 2))))
  914.       (setq valu (int-to-string valu))))
  915.        ((equal "DATE" type)
  916.     (setq valu (read-string "Enter date: " valu)))
  917.        ((equal "URL" type)
  918.     (setq valu (read-string "Enter valid URL: " valu)))
  919.        (t
  920.     (setq valu (read-string "Enter text: " valu))))
  921.       (if (not (fboundp func)) (setq func 'w3-textp))
  922.       (if (funcall func valu)
  923.       (setq exitp t)
  924.     (progn
  925.       (message "Wrong format for type %s, try again." (downcase type))
  926.       (sit-for 2))))
  927.     valu))
  928.  
  929.  
  930. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  931. ;;; Code for printing out roman numerals
  932. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  933. (defun w3-decimal-to-roman (n)
  934.   ;; Convert from decimal to roman numerals
  935.   (let ((curmod 1000)
  936.     (str "")
  937.     (j 7)
  938.     i2 k curcnt)
  939.     (while (>= curmod 1)
  940.       (if (>= n curmod)
  941.       (progn
  942.         (setq curcnt (/ n curmod)
  943.           n (- n (* curcnt curmod)))
  944.         (if (= 4 (% curcnt 5))
  945.         (setq i2 (+ j (if (> curcnt 5) 1 0))
  946.               str (format "%s%c%c" str
  947.                   (aref w3-roman-characters (1- j))
  948.                   (aref w3-roman-characters i2)))
  949.           (progn
  950.         (if (>= curcnt 5)
  951.             (setq str (format "%s%c" str (aref w3-roman-characters j))
  952.               curcnt (- curcnt 5)))
  953.         (setq k 0)
  954.         (while (< k curcnt)
  955.           (setq str (format "%s%c" str
  956.                     (aref w3-roman-characters (1- j)))
  957.             k (1+ k)))))))
  958.       (setq curmod (/ curmod 10)
  959.         j (- j 2)))
  960.     str))
  961.  
  962. (defun w3-decimal-to-alpha (n)
  963.   ;; Convert from decimal to alphabetical (a, b, c, ..., aa, ab,...)
  964.   (cond
  965.    ((< n 1) (char-to-string ?Z))
  966.    ((<= n 26) (char-to-string (+ ?A (1- n))))
  967.    (t (concat (char-to-string (+ ?A (1- (/ n 27))))
  968.           (w3-decimal-to-alpha (% n 26))))))
  969.  
  970.  
  971. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  972. ;;; Functions for formatting nested lists in html
  973. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  974. (defun w3-expand-list (data)
  975.   ;; Expand a list that has been hidden.
  976.   (let ((buffer-read-only nil))
  977.     (w3-unhide-zone (nth 1 data) (nth 2 data))))
  978.  
  979. (defun w3-rehide-list (data)
  980.   ;; Hide a list that was viewable.
  981.   (let ((buffer-read-only nil))
  982.     (w3-hide-zone (nth 1 data) (nth 2 data))))
  983.  
  984.  
  985. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  986. ;;; Functions for compatibility with XMosaic
  987. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  988.  
  989. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  990. ;;; Parse out the Mosaic documents-menu file
  991. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  992. (defun w3-parse-docs-menu ()
  993.   ;; Parse the Mosaic documents menu
  994.   (let ((tmp-menu (append '((separator)) w3-starting-documents
  995.               '((separator))))
  996.     real-menu x y name url)
  997.     (if (or (not (file-exists-p w3-documents-menu-file))
  998.         (not (file-readable-p w3-documents-menu-file)))
  999.     (message "No documents menu found... continuing.")
  1000.       (save-excursion
  1001.     (set-buffer (get-buffer-create " *w3-temp*"))
  1002.     (erase-buffer)
  1003.     (mm-insert-file-contents w3-documents-menu-file)
  1004.     (goto-char (point-min))
  1005.     (while (not (eobp))
  1006.       (if (not (looking-at "-+$"))
  1007.           (setq x (progn (beginning-of-line) (point))
  1008.             y (progn (end-of-line) (point))
  1009.             name (prog1
  1010.                  (buffer-substring x y)
  1011.                (delete-region x (min (1+ y) (point-max))))
  1012.             x (progn (beginning-of-line) (point))
  1013.             y (progn (end-of-line) (point))
  1014.             url (prog1
  1015.                 (buffer-substring x y)
  1016.               (delete-region x (min (1+ y) (point-max))))
  1017.             tmp-menu (if (rassoc url tmp-menu) tmp-menu
  1018.                    (cons (cons name url) tmp-menu)))
  1019.         (setq tmp-menu (cons '(separator) tmp-menu))
  1020.         (delete-region (point-min) (min (1+ (progn (end-of-line)
  1021.                                (point)))
  1022.                         (point-max)))))
  1023.     (kill-buffer (current-buffer))))
  1024.     (if (equal (car (car tmp-menu)) "") (setq tmp-menu (cdr tmp-menu)))
  1025.     (while tmp-menu
  1026.       (setq real-menu (cons (if (equal 'separator (car (car tmp-menu)))
  1027.                 "--------"
  1028.                   (vector (car (car tmp-menu))
  1029.                       (list 'w3-fetch
  1030.                         (if (listp (cdr (car tmp-menu)))
  1031.                         (car (cdr (car tmp-menu)))
  1032.                           (cdr (car tmp-menu)))) t))
  1033.                 real-menu)
  1034.         tmp-menu (cdr tmp-menu)))
  1035.     (setq w3-navigate-menu (append w3-navigate-menu real-menu
  1036.                    (list "-----")))))
  1037.  
  1038. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1039. ;;; Private annotation support
  1040. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1041. (defun w3-parse-personal-annotations ()
  1042.   ;; Read in personal annotation file
  1043.   (if (and
  1044.        (file-exists-p (format "%s/LOG" w3-personal-annotation-directory))
  1045.        (file-readable-p (format "%s/LOG" w3-personal-annotation-directory)))
  1046.       (save-excursion
  1047.     (setq w3-personal-annotations nil);; nuke the old list
  1048.     (let ((start nil)
  1049.           (end nil)
  1050.           (txt nil)
  1051.           (url nil)
  1052.           (num nil))
  1053.       (set-buffer (get-buffer-create " *panno*"))
  1054.       (erase-buffer)
  1055.       (mm-insert-file-contents
  1056.        (format "%s/LOG" w3-personal-annotation-directory))
  1057.       (goto-char (point-min))
  1058.       (w3-replace-regexp "\n+" "\n")
  1059.       (goto-char (point-min))
  1060.       ;; nuke the header lines
  1061.       (delete-region (point-min) (progn (forward-line 2) (point)))
  1062.       (cond
  1063.        ((eobp) nil)            ; Empty LOG file
  1064.        (t
  1065.         (if (/= (char-after (1- (point-max))) ?\n)
  1066.         (save-excursion
  1067.           (goto-char (point-max))
  1068.           (w3-insert "\n")))
  1069.         (while (not (eobp))
  1070.           (setq start (point)
  1071.             end (prog2 (end-of-line) (point) (forward-char 1))
  1072.             txt (buffer-substring start end)
  1073.             url (substring txt 0 (string-match " " txt))
  1074.             num (url-split
  1075.              (substring txt (1+ (string-match " " txt)) nil)
  1076.              "[ \t]"))
  1077.           (while num
  1078.         (setq w3-personal-annotations
  1079.               (cons
  1080.                (list url
  1081.                  (list (car (car num))
  1082.                    (w3-grok-annotation-format
  1083.                     (car (car num)))))
  1084.                w3-personal-annotations)
  1085.               num (cdr num))))))
  1086.       (kill-buffer " *panno*")))))
  1087.  
  1088. (defun w3-grok-annotation-format (anno)
  1089.   ;; Grab the title from an annotation
  1090.   (let ((fname  (format "%s/PAN-%s.html"
  1091.             w3-personal-annotation-directory anno)))
  1092.     (save-excursion
  1093.       (set-buffer (get-buffer-create " *annotmp*"))
  1094.       (erase-buffer)
  1095.       (if (file-exists-p fname)
  1096.       (mm-insert-file-contents fname))
  1097.       (goto-char (point-min))
  1098.       (prog1
  1099.       (if (re-search-forward "<title>\\(.*\\)</title>" nil t)
  1100.           (buffer-substring (match-beginning 1) (match-end 1))
  1101.         (if (or w3-running-FSF19
  1102.             w3-running-xemacs
  1103.             w3-running-epoch)
  1104.         (concat "Annotation on "
  1105.             (current-time-string (nth 5 (file-attributes fname))))
  1106.           "No title"))
  1107.     (kill-buffer " *annotmp*")))))
  1108.  
  1109. (defun w3-fetch-personal-annotations ()
  1110.   ;; Grab any personal annotations for the current url
  1111.   (let ((url  (url-view-url t))
  1112.     (anno w3-personal-annotations)
  1113.     (annolist nil))
  1114.     (if (assoc url anno)
  1115.     (while anno
  1116.       (if (equal (car (car anno)) url)
  1117.           (setq annolist
  1118.             (cons
  1119.              (format "<A HREF=\"file:%s%s/PAN-%s.html\">%s</A>"
  1120.                  (if (= ?/ (string-to-char
  1121.                     w3-personal-annotation-directory)) ""
  1122.                    "/")
  1123.                  w3-personal-annotation-directory
  1124.                  (car (car (cdr (car anno))))
  1125.                  (car (cdr (car (cdr (car anno))))))
  1126.              annolist)))
  1127.       (setq anno (cdr anno))))
  1128.     annolist))
  1129.  
  1130. (defun w3-is-personal-annotation (url)
  1131.   ;; Is URL a personal annotation?
  1132.   (string-match "file:/.*/PAN-.*\\.html" url))
  1133.  
  1134. (defun w3-delete-personal-annotation ()
  1135.   "Delete a personal annotation."
  1136.   (interactive)
  1137.   (if (w3-is-personal-annotation (url-view-url t))
  1138.       (let ((num nil)
  1139.         (annotated-url nil)
  1140.         (anno w3-personal-annotations))
  1141.     (string-match "file:/.*/PAN-\\(.*\\)\\.html" (url-view-url t))
  1142.     (setq num (substring (url-view-url t) (match-beginning 1)
  1143.                  (match-end 1)))
  1144.     (while anno
  1145.       (if (equal num (car (car (cdr (car anno)))))
  1146.           (setq annotated-url (car (car anno))))
  1147.       (setq anno (cdr anno)))
  1148.     (if annotated-url
  1149.         (save-excursion
  1150.           (set-buffer (get-buffer-create " *annotmp*"))
  1151.           (erase-buffer)
  1152.           (mm-insert-file-contents (format "%s/LOG"
  1153.                         w3-personal-annotation-directory))
  1154.           (replace-regexp (format "[ \t]+\\b%s\\b[ \t]*" num) " ")
  1155.           (goto-char (point-min))
  1156.           (delete-matching-lines (format "^%s +$" annotated-url))
  1157.           (let ((make-backup-files nil)
  1158.             (version-control nil)
  1159.             (require-final-newline t))
  1160.         (write-region (point-min) (point-max)
  1161.                   (format "%s/LOG"
  1162.                       w3-personal-annotation-directory)))
  1163.           (kill-buffer " *annotmp*")
  1164.           (setq anno w3-personal-annotations
  1165.             w3-personal-annotations nil)
  1166.           (while anno
  1167.         (if (not (string= num (car (car (cdr (car anno))))))
  1168.             (setq w3-personal-annotations
  1169.               (cons (car anno) w3-personal-annotations)))
  1170.         (setq anno (cdr anno)))
  1171.           (delete-file (format "%s/PAN-%s.html"
  1172.                    w3-personal-annotation-directory num)))
  1173.       (message "Couldn't find url that this is annotating!")))
  1174.     (message "This isn't a personal annotation.")))
  1175.  
  1176. (defun w3-personal-annotation-add ()
  1177.   "Add an annotation to this document."
  1178.   (interactive)
  1179.   (let ((url (url-view-url t))
  1180.     (buf (get-buffer-create "*Personal Annotation*"))
  1181.     (title (read-string "Title: "
  1182.                 (format "Annotation by %s on %s"
  1183.                     (user-real-login-name)
  1184.                     (current-time-string)))))
  1185.     (set-buffer buf)
  1186.     (if w3-mutable-windows (pop-to-buffer buf) (switch-to-buffer buf))
  1187.     (erase-buffer)
  1188.     (if (and w3-annotation-mode (fboundp w3-annotation-mode))
  1189.     (funcall w3-annotation-mode)
  1190.       (message "%S is undefined, using %s" w3-annotation-mode
  1191.            default-major-mode)
  1192.       (funcall default-major-mode))
  1193.     (w3-annotation-minor-mode 1)
  1194.     (setq w3-current-annotation (cons url title))
  1195.     (insert "<html>\n"
  1196.         " <head>\n"
  1197.         "  <title>" title "</title>"
  1198.         " </head>\n"
  1199.         "  <h1>" title "</h1>\n"
  1200.         "  <p>\n"
  1201.         "   <address>" (user-full-name) url-personal-mail-address
  1202.         "</address>\n"
  1203.         "   <address>" (current-time-string) "</address>\n"
  1204.         "  </p>\n"
  1205.         "  <pre>\n")
  1206.     (save-excursion
  1207.       (insert "\n\n\n  </pre>\n"
  1208.           "</html>"))
  1209.     (message "Hit C-cC-c to send this annotation.")))
  1210.  
  1211. (defun w3-annotation-minor-mode (&optional arg)
  1212.   "Minimal minor mode for entering annotations.  Just rebinds C-cC-c to
  1213. finish the annotation."
  1214.   (interactive "P")
  1215.   (cond
  1216.    ((null arg) (setq w3-annotation-minor-mode (not w3-annotation-minor-mode)))
  1217.    ((= 0 arg)  (setq w3-annotation-minor-mode nil))
  1218.    (t          (setq w3-annotation-minor-mode t)))
  1219.   (cond
  1220.    ((or w3-running-FSF19 w3-running-xemacs))
  1221.    (t (local-set-key "\C-c\C-c" 'w3-personal-annotation-finish)))
  1222.   )
  1223.  
  1224. (defun w3-annotation-find-highest-number ()
  1225.   ;; Find the highest annotation number in this buffer
  1226.   (let (x)
  1227.     (goto-char (point-min))
  1228.     (while (re-search-forward "[^ \t\n]*[ \t]\\(.*\\)" nil t)
  1229.       (setq x (nconc (mapcar (function (lambda (x) (string-to-int (car x))))
  1230.                  (url-split (buffer-substring (match-beginning 1)
  1231.                              (match-end 1))
  1232.                        "[ \t]")) x)))
  1233.     (if (not x) (setq x '(0)))
  1234.     (1+ (car (sort x '>)))))
  1235.  
  1236. (defun w3-personal-annotation-finish ()
  1237.   "Finish doing a personal annotation."
  1238.   (interactive)
  1239.   (cond
  1240.    ((or w3-running-FSF19 w3-running-xemacs))
  1241.    (t (local-set-key "\C-c\C-c" 'undefined)))
  1242.   (if (or (not w3-personal-annotation-directory)
  1243.       (not (file-exists-p w3-personal-annotation-directory))
  1244.       (not (file-directory-p w3-personal-annotation-directory)))
  1245.       (error "No personal annotation directory!")
  1246.     (let ((url (car w3-current-annotation))
  1247.       (txt (buffer-string))
  1248.       (title (cdr w3-current-annotation))
  1249.       (fname nil)
  1250.       (num nil))
  1251.       (save-excursion
  1252.     (not-modified)
  1253.     (kill-buffer (current-buffer))
  1254.     (set-buffer (get-buffer-create " *annotmp*"))
  1255.     (erase-buffer)
  1256.     (if (file-exists-p        ; Insert current LOG file if
  1257.                     ; it exists.
  1258.          (format "%s/LOG" w3-personal-annotation-directory))
  1259.         (mm-insert-file-contents
  1260.          (format "%s/LOG" w3-personal-annotation-directory))
  1261.       (progn            ; Otherwise, create a file
  1262.         (goto-char (point-min))    ; that conforms to first
  1263.                     ; annotation format from NCSA
  1264.         (w3-insert "ncsa-mosaic-personal-annotation-log-format-1\n")
  1265.         (w3-insert "Personal\n")))
  1266.     (goto-char (point-min))
  1267.     (setq num (int-to-string (w3-annotation-find-highest-number))
  1268.           fname (format "%s/PAN-%s.html"
  1269.                 w3-personal-annotation-directory num))
  1270.     (goto-char (point-min))
  1271.     (if (re-search-forward (regexp-quote url) nil t)
  1272.         (progn
  1273.           (end-of-line)
  1274.           (w3-insert " "))
  1275.       (goto-char (point-max))
  1276.       (w3-insert "\n" url " "))
  1277.     (w3-insert num)
  1278.     (let ((make-backup-files nil)
  1279.           (version-control nil)
  1280.           (require-final-newline t))
  1281.       (write-region (point-min) (point-max)
  1282.             (format "%s/LOG" w3-personal-annotation-directory))
  1283.       (erase-buffer)
  1284.       (w3-insert w3-annotation-marker txt)
  1285.       (write-region (point-min) (point-max) fname))
  1286.     (setq w3-personal-annotations
  1287.           (cons (list url (list num title)) w3-personal-annotations))))))
  1288.  
  1289. (defun w3-annotation-add ()
  1290.   "Add an annotation to the current document."
  1291.   (interactive)
  1292.   (w3-personal-annotation-add))
  1293.  
  1294.  
  1295. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1296. ;;; Functions to pass files off to external viewers
  1297. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1298. (defun w3-start-viewer (fname cmd &optional view)
  1299.   "Start a subprocess, named FNAME, executing CMD
  1300. If third arg VIEW is non-nil, show the output in a buffer when
  1301. the subprocess exits."
  1302.   (if view (save-excursion
  1303.          (set-buffer (get-buffer-create view))
  1304.          (erase-buffer)))
  1305.   (let ((proc
  1306.      (start-process fname view (or shell-file-name
  1307.                        (getenv "ESHELL")
  1308.                        (getenv "SHELL")
  1309.                        "/bin/sh") "-c" cmd)))
  1310.     proc))
  1311.  
  1312. (defun w3-viewer-filter (proc string)
  1313.   ;; A process filter for asynchronous external viewers
  1314.   (let ((buff (get-buffer-create (url-generate-new-buffer-name
  1315.                   (symbol-name
  1316.                    (read (nth 2 (process-command proc))))))))
  1317.     (save-excursion
  1318.       (set-buffer buff)
  1319.       (erase-buffer)
  1320.       (insert string)
  1321.       (set-process-buffer proc buff)
  1322.       (set-process-filter proc nil))))
  1323.  
  1324. (defun w3-viewer-sentinel (proc string)
  1325.   ;; Delete any temp files left from a viewer process.
  1326.   (let ((fname (process-name proc))
  1327.     (buffr (process-buffer proc)))
  1328.     (if (and (file-exists-p fname)
  1329.          (file-writable-p fname))
  1330.     (delete-file fname))
  1331.     (if buffr
  1332.     (if w3-mutable-windows
  1333.         (pop-to-buffer buffr)
  1334.       (switch-to-buffer buffr)))))
  1335.  
  1336. (defun w3-notify-when-ready (buff)
  1337.   "Notify the user when BUFF is ready.
  1338. See the variable `w3-notify' for the different notification behaviors."
  1339.   (if (stringp buff) (setq buff (get-buffer buff)))
  1340.   (cond
  1341.    ((null buff) nil)
  1342.    ((eq w3-notify 'newframe)
  1343.     ;; Since we run asynchronously, perhaps while Emacs is waiting for input,
  1344.     ;; we must not leave a different buffer current.
  1345.     ;; We can't rely on the editor command loop to reselect
  1346.     ;; the selected window's buffer.
  1347.     (save-excursion
  1348.       (set-buffer buff)
  1349.       (make-frame)))
  1350.    ((eq w3-notify 'bully)
  1351.     (pop-to-buffer buff)
  1352.     (delete-other-windows))
  1353.    ((eq w3-notify 'aggressive)
  1354.     (pop-to-buffer buff))
  1355.    ((eq w3-notify 'friendly)
  1356.     (display-buffer buff 'not-this-window))
  1357.    ((eq w3-notify 'polite)
  1358.     (beep)
  1359.     (message "W3 buffer %s is ready." (buffer-name buff)))
  1360.    ((eq w3-notify 'quiet)
  1361.     (message "W3 buffer %s is ready." (buffer-name buff)))
  1362.    (t (message ""))))
  1363.  
  1364. (defun w3-pass-to-viewer ()
  1365.   ;; Pass a w3 buffer to a viewer
  1366.   (set-buffer url-working-buffer)
  1367.   (let* ((info  url-current-mime-viewer)        ; All the MIME viewer info
  1368.      (view (cdr-safe (assoc "viewer" info))) ; How to view this file
  1369.      (url (url-view-url t))
  1370.      (fmt  (cdr-safe (assoc "nametemplate" info)))) ; Template for name
  1371.     (cond
  1372.      (fmt nil)
  1373.      ((cdr-safe (assoc "type" info))
  1374.       (setq fmt (mm-type-to-file (cdr-safe (assoc "type" info))))
  1375.       (if fmt (setq fmt (concat "%s" (car fmt)))
  1376.     (setq fmt (concat "%s" (url-file-extension url-current-file))))))
  1377.     (if (null view)
  1378.     (setq view 'indented-text-mode))
  1379.     (cond
  1380.      ((symbolp view)
  1381.       (if (not (memq view '(w3-prepare-buffer w3-print w3-source
  1382.                           w3-default-local-file
  1383.                           mm-multipart-viewer)))
  1384.       (let ((bufnam (url-generate-new-buffer-name
  1385.              (file-name-nondirectory
  1386.               (or url-current-file "Unknown")))))
  1387.         (if (string= bufnam "")
  1388.         (setq bufnam (url-generate-new-buffer-name
  1389.                   (url-view-url t))))
  1390.         (rename-buffer bufnam)
  1391.         (set-buffer-modified-p nil)
  1392.         (buffer-enable-undo)
  1393.         (funcall view)
  1394.         (w3-notify-when-ready bufnam))
  1395.     (funcall view)))
  1396.      ((stringp view)
  1397.       (let ((fname (url-generate-unique-filename fmt)) proc)
  1398.     (if (url-file-directly-accessible-p (url-view-url t))
  1399.         (make-symbolic-link url-current-file fname t)
  1400.       (if (boundp 'MULE)
  1401.           (write-region (point-min) (point-max) fname nil nil *noconv*)
  1402.         (write-region (point-min) (point-max) fname)))
  1403.     (if (get-buffer url-working-buffer)
  1404.         (kill-buffer url-working-buffer))
  1405.     (if (string-match "%s" view)
  1406.         (setq view (concat (substring view 0 (match-beginning 0))
  1407.                    fname (substring view (match-end 0)))))
  1408.     (if (string-match "%u" view)
  1409.         (setq view (concat (substring view 0 (match-beginning 0))
  1410.                    url
  1411.                    (substring view (match-end 0)))))
  1412.     (message "Passing to viewer %s " view)
  1413.     (setq proc (w3-start-viewer fname view))
  1414.     (set-process-filter proc 'w3-viewer-filter)
  1415.     (set-process-sentinel proc 'w3-viewer-sentinel)))
  1416.      ((listp view)
  1417.       (set-buffer-modified-p nil)
  1418.       (buffer-enable-undo)
  1419.       (eval view))
  1420.      (t
  1421.       (message "Unknown viewer specified: %s" view)
  1422.       (w3-notify-when-ready url-working-buffer)))))
  1423.  
  1424. (defun w3-save-binary-file ()
  1425.   "Save a buffer to disk - this is used when `w3-dump-to-disk' is non-nil"
  1426.   (interactive)
  1427.   (let ((x (read-file-name "Filename to save as: "
  1428.                (or mm-download-directory "~/")
  1429.                (concat (or mm-download-directory "~/")
  1430.                    (url-basepath (or url-current-file "") t))
  1431.                nil
  1432.                (url-basepath (or url-current-file "") t))))
  1433.     (save-excursion
  1434.       ;; more fixes from the MULE guys
  1435.       (if w3-dump-to-disk
  1436.       (let (jka-compr-compression-info-list
  1437.         jam-zcat-filename-list)
  1438.         (if (boundp 'MULE)
  1439.         (let ((mc-flag t))
  1440.           (write-file x *noconv*))
  1441.           (write-file x)))
  1442.     (if (boundp 'MULE)
  1443.         (let ((mc-flag t))
  1444.           (write-file x *noconv*))
  1445.       (write-file x)))
  1446.       (kill-buffer (current-buffer)))))
  1447.  
  1448. (defun w3-build-url (protocol)
  1449.   "Build a url for PROTOCOL, return it as a string"
  1450.   (interactive (list (cdr (assoc (completing-read
  1451.                   "Protocol: "
  1452.                   w3-acceptable-protocols-alist nil t)
  1453.                  w3-acceptable-protocols-alist))))
  1454.   (let (user host port file)
  1455.     (cond
  1456.      ((null protocol) (error "Protocol is unknown to me!"))
  1457.      ((string= protocol "news")
  1458.       (setq host (read-string "Enter news server name, or blank for default: ")
  1459.         port (read-string "Enter port number, or blank for default: ")
  1460.         file (read-string "Newgroup name or Message-ID: ")))
  1461.      ((string= protocol "mailto") (setq file (read-string "E-mail address: ")))
  1462.      ((string= protocol "http")
  1463.       (setq host (read-string "Enter server name: ")
  1464.         port (read-string "Enter port number, or blank for default: ")
  1465.         file (read-string "Remote file: "))
  1466.       (and (string= "" port) (setq port nil))
  1467.       (and (string= "" host) (error "Must specify a remote machine!")))
  1468.      ((string= protocol "file")
  1469.       (if (funcall url-confirmation-func "Local file?")
  1470.       (setq file (read-file-name "Local File: " nil nil t))
  1471.     (setq user (read-string "Login as user (blank=anonymous): ")
  1472.           host (read-string "Remote machine name: "))
  1473.     (and (string= user "") (setq user "anonymous"))
  1474.     (and (string= host "") (error "Must specify a remote machine!"))
  1475.     (setq file (read-file-name "File: " (format "/%s@%s:" user host)
  1476.                    nil t)
  1477.           file (substring file (length (format "/%s@%s:" user host))))))
  1478.      ((or (string= protocol "telnet")
  1479.       (string= protocol "tn3270"))
  1480.       (setq user (read-string "Login as user (blank=none): ")
  1481.         host (read-string "Remote machine name: ")
  1482.         port (read-string "Port number (blank=23): "))
  1483.       (and (string= "" port) (setq port nil))
  1484.       (and (string= "" user) (setq user nil))
  1485.       (and (string= "" host) (error "Must specify a host machine!")))
  1486.      ((string= protocol "gopher")
  1487.       (setq host (read-string "Enter server name: ")
  1488.         port (read-string "Enter port number, or blank for default: ")
  1489.         file (read-string "Remote file: "))
  1490.       (and (string= "" port) (setq port nil))
  1491.       (and (string= "" host) (error "Must specify a remote machine!"))))
  1492.     (message "%s:%s%s"
  1493.          protocol
  1494.          (if (null host) "" (concat "//" host
  1495.                     (if (null port) "" (concat ":" port))))
  1496.          (if (= ?/ (string-to-char file)) file (concat "/" file)))))
  1497.  
  1498. ;;;###autoload
  1499. (defun w3-open-local (fname)
  1500.   "Find a local file, and interpret it as a hypertext document.
  1501. It will prompt for an existing file or directory, and retrieve it as a
  1502. hypertext document.  If it is a directory, and url-use-hypertext-dired
  1503. is non-nil, then an HTML directory listing is created on the fly.
  1504. Otherwise, dired-mode is used to visit the buffer."
  1505.   (interactive "FLocal file: ")
  1506.   (if (not w3-setup-done) (w3-do-setup))
  1507.   (w3-fetch (concat "file:" fname)))
  1508.  
  1509. ;;;###autoload
  1510. (defun w3-fetch-other-frame (&optional url)
  1511.   "Attempt to follow the hypertext reference under point in a new frame.
  1512. With prefix-arg P, ignore viewers and dump the link straight
  1513. to disk."
  1514.   (interactive (list (w3-read-url-with-default)))
  1515.   (cond
  1516.    ((and (fboundp 'make-frame)
  1517.      (fboundp 'select-frame)
  1518.      (not (eq (device-type) 'tty)))
  1519.     (let ((frm (make-frame)))
  1520.       (select-frame frm)
  1521.       (w3-fetch url)))
  1522.    (t (w3-fetch url))))
  1523.  
  1524. (defun w3-read-url-with-default ()
  1525.   (if (not w3-setup-done) (w3-do-setup))
  1526.   (let* ((completion-ignore-case t)
  1527.      (default
  1528.        (if (eq major-mode 'w3-mode)
  1529.            (if (and current-prefix-arg (w3-view-this-url t))
  1530.            (w3-view-this-url t)
  1531.          (url-view-url t))
  1532.          (url-get-url-at-point)))
  1533.      (url nil))
  1534.     (setq url
  1535.       (completing-read "URL: "
  1536.                url-global-history-completion-list nil nil default))
  1537.     (if (string= url "")
  1538.     (setq url (if (eq major-mode 'w3-mode)
  1539.               (if (and current-prefix-arg (w3-view-this-url t))
  1540.               (w3-view-this-url t)
  1541.             (url-view-url t))
  1542.             (url-get-url-at-point))))
  1543.     url))
  1544.  
  1545. ;;;###autoload
  1546. (defun w3-fetch (&optional url)
  1547.   "Retrieve a document over the World Wide Web.
  1548. The World Wide Web is a global hypertext system started by CERN in
  1549. Switzerland in 1991.
  1550.  
  1551. The document should be specified by its fully specified
  1552. Uniform Resource Locator.  The document will be parsed, printed, or
  1553. passed to an external viewer as appropriate.  Variable
  1554. `mm-mime-info' specifies viewers for particular file types."
  1555.   (interactive (list (w3-read-url-with-default)))
  1556.   (if (boundp 'w3-working-buffer)
  1557.       (setq w3-working-buffer url-working-buffer))
  1558.   (if (and (boundp 'command-line-args-left)
  1559.        command-line-args-left
  1560.        (string-match url-nonrelative-link (car command-line-args-left)))
  1561.       (setq url (car command-line-args-left)
  1562.         command-line-args-left (cdr command-line-args-left)))
  1563.   (if (equal url "") (error "No document specified!"))
  1564.   ;; In the common case, this is probably cheaper than searching.
  1565.   (while (= (string-to-char url) ? )
  1566.     (setq url (substring url 1)))
  1567.   (if (= (string-to-char url) ?#)
  1568.       (w3-relative-link url)
  1569.     (let ((x (url-view-url t))
  1570.       (lastbuf (current-buffer))
  1571.       (buf (url-buffer-visiting url)))
  1572.       (if (not w3-setup-done) (w3-do-setup))
  1573.       (and x (or (string= "file:nil" x) (string= "" x))
  1574.        (setq x nil))
  1575.       (if (or (not buf)
  1576.           (cond
  1577.            ((not (equal (downcase (or url-request-method "GET")) "get")) t)
  1578.            ((memq w3-reuse-buffers '(no never reload)) t)
  1579.            ((memq w3-reuse-buffers '(yes reuse always)) nil)
  1580.            (t
  1581.         (if (and w3-reuse-buffers (not (eq w3-reuse-buffers 'ask)))
  1582.             (progn
  1583.               (ding)
  1584.               (message
  1585.                "Warning: Invalid value for variable w3-reuse-buffers: %s"
  1586.                (prin1-to-string w3-reuse-buffers))
  1587.               (sit-for 2)))
  1588.         (not (funcall url-confirmation-func
  1589.                   (format "Reuse URL in buffer %s? "
  1590.                       (buffer-name buf)))))))
  1591.       (let ((cached (url-retrieve url)))
  1592.         (if x
  1593.         (w3-add-urls-to-history x url))
  1594.         (if w3-track-last-buffer
  1595.         (setq w3-last-buffer (get-buffer url-working-buffer)))
  1596.         (if (get-buffer url-working-buffer)
  1597.         (cond
  1598.          ((and url-be-asynchronous (string-match "^http:" url)
  1599.                (not cached))
  1600.           (save-excursion
  1601.             (set-buffer url-working-buffer)
  1602.             (setq w3-current-last-buffer lastbuf)))
  1603.          (t (w3-sentinel lastbuf)))))
  1604.     (if w3-track-last-buffer 
  1605.         (setq w3-last-buffer buf))
  1606.     (switch-to-buffer buf)
  1607.     (if (string-match "#\\(.*\\)" url)
  1608.         (w3-find-specific-link (url-match url 1)))
  1609.     (message "Reusing URL.  To reload, type %s."
  1610.          (substitute-command-keys "\\[w3-reload-document]"))))))
  1611.  
  1612.  
  1613. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1614. ;;; History for forward/back buttons
  1615. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1616. (defvar w3-node-history nil "History for forward and backward jumping")
  1617.  
  1618. (defun w3-plot-course ()
  1619.   "Show a map of where the user has been in this session of W3. !!!!NYI!!!"
  1620.   (interactive)
  1621.   (error "Sorry, w3-plot-course is not yet implemented."))
  1622.  
  1623. (defun w3-forward-in-history ()
  1624.   "Go forward in the history from this page"
  1625.   (interactive)
  1626.   (let* ((thisurl (url-view-url t))
  1627.      (node (assoc (if (string= "" thisurl) (current-buffer) thisurl)
  1628.               w3-node-history))
  1629.      (url (cdr node))
  1630.      (w3-reuse-buffers 'yes))
  1631.     (cond
  1632.      ((null url) (error "No forward found for %s" thisurl))
  1633.      ((and (bufferp url) (buffer-name url))
  1634.       (switch-to-buffer url))
  1635.      ((stringp url)
  1636.       (w3-fetch url))
  1637.      ((bufferp url)
  1638.       (setq w3-node-history (delete node w3-node-history))
  1639.       (error "Killed buffer in history, removed."))
  1640.      (t
  1641.       (error "Something is very wrong with the history!")))))
  1642.  
  1643. (defun w3-backward-in-history ()
  1644.   "Go backward in the history from this page"
  1645.   (interactive)
  1646.   (let* ((thisurl (url-view-url t))
  1647.      (node (rassoc (if (string= thisurl "") (current-buffer) thisurl)
  1648.               w3-node-history))
  1649.      (url (car node))
  1650.      (w3-reuse-buffers 'yes))
  1651.     (cond
  1652.      ((null url) (error "No backward found for %s" thisurl))
  1653.      ((and (bufferp url) (buffer-name url))
  1654.       (switch-to-buffer url))
  1655.      ((stringp url)
  1656.       (w3-fetch url))
  1657.      ((bufferp url)
  1658.       (setq w3-node-history (delete node w3-node-history))
  1659.       (error "Killed buffer in history, removed."))
  1660.      (t
  1661.       (error "Something is very wrong with the history!")))))
  1662.  
  1663. (defun w3-add-urls-to-history (referer url)
  1664.   "REFERER is the url we followed this link from.  URL is the link we got to."
  1665.   (let ((node (assoc referer w3-node-history)))
  1666.     (if node
  1667.     (setcdr node url)
  1668.       (setq w3-node-history (cons (cons referer url) w3-node-history)))))
  1669.  
  1670.  
  1671. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1672. ;;; Miscellaneous functions
  1673. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1674. (defun w3-executable-exists-in-path (exec &optional path)
  1675.   (let ((paths (if (consp path)
  1676.            path
  1677.          (mm-string-to-tokens (or path
  1678.                       (getenv "PATH")
  1679.                       (concat
  1680.                        "/usr/bin:/bin:/usr/local/bin:"
  1681.                        "/usr/bin/X11:"
  1682.                        (expand-file-name "~/bin"))) ?:)))
  1683.     (done nil))
  1684.     (while (and paths (not done))
  1685.       (if (file-exists-p (expand-file-name exec (car paths)))
  1686.       (setq done t))
  1687.       (setq paths (cdr paths)))
  1688.     done))
  1689.  
  1690. (defun w3-document-information (&optional buff)
  1691.   "Display information on the document in buffer BUFF"
  1692.   (interactive)
  1693.   (setq buff (or buff (current-buffer)))
  1694.   (save-excursion
  1695.     (set-buffer buff)
  1696.     (let* ((url (url-view-url t))
  1697.        (cur-links w3-current-links)
  1698.        (title (buffer-name))
  1699.        (lastmod (or (cdr-safe (assoc "last-modified"
  1700.                      url-current-mime-headers))
  1701.             (and (member url-current-type '("file" "ftp"))
  1702.                  (nth 7 (url-file-attributes url)))))
  1703.        (hdrs url-current-mime-headers))
  1704.       (set-buffer (get-buffer-create "Document Info"))
  1705.       (erase-buffer)
  1706.       (cond
  1707.        ((stringp lastmod) nil)
  1708.        ((equal '(0 . 0) lastmod) (setq lastmod ""))
  1709.        ((consp lastmod) (setq lastmod (current-time-string lastmod)))
  1710.        (t (setq lastmod "")))
  1711.       (insert "        Title: " title   "\n"
  1712.           "     Location: " url     "\n")
  1713.       (if lastmod (insert "Last Modified: " lastmod "\n"))
  1714.       (if hdrs
  1715.       (let* ((maxlength (car (sort (mapcar (function (lambda (x)
  1716.                                (length (car x))))
  1717.                            hdrs)
  1718.                        '>)))
  1719.          (fmtstring (format "%%%ds: %%s" maxlength)))
  1720.         
  1721.         (insert
  1722.          (make-string (1- (window-width)) ?-)
  1723.          "\nMetaInformation:\n"
  1724.          (mapconcat
  1725.           (function
  1726.            (lambda (x)
  1727.          (if (/= (length (car x)) 0)
  1728.              (format fmtstring
  1729.                  (capitalize (car x))
  1730.                  (if (numberp (cdr x))
  1731.                  (int-to-string (cdr x))
  1732.                    (cdr x))))))
  1733.           (sort hdrs
  1734.             (function (lambda (x y) (string-lessp (car x) (car y)))))
  1735.           "\n") "\n")))
  1736.       (if cur-links
  1737.       (progn
  1738.         (insert (make-string (1- (window-width)) ?-)
  1739.             "Document-defined link relations:\n")
  1740.         (mapcar
  1741.          (function
  1742.           (lambda (x)
  1743.         (insert (car x) ":\n")
  1744.         (mapcar (function
  1745.              (lambda (x)
  1746.                (insert (format "  %15s -- %s\n" (car x) (cdr x)))))
  1747.             (cdr x))))
  1748.          cur-links)))
  1749.       (goto-char (point-min))
  1750.       (display-buffer "Document Info"))))
  1751.  
  1752. (defun w3-truncate-menu-item (string)
  1753.   (if (<= (length string) w3-max-menu-width)
  1754.       string
  1755.     (concat (substring string 0 w3-max-menu-width) "$")))
  1756.  
  1757. (defun w3-use-starting-documents ()
  1758.   "Use the list of predefined starting documents from w3-starting-documents"
  1759.   (interactive)
  1760.   (let ((w3-hotlist w3-starting-documents))
  1761.     (w3-use-hotlist)))
  1762.  
  1763. (defun w3-show-starting-documents ()
  1764.   "Show the list of predefined starting documents from w3-starting-documents"
  1765.   (interactive)
  1766.   (if (not w3-setup-done) (w3-do-setup))
  1767.   (w3-fetch "www://auto/starting-points"))
  1768.  
  1769. (defun w3-insert-formatted-url (p)
  1770.   "Insert a formatted url into a buffer.  With prefix arg, insert the url
  1771. under point."
  1772.   (interactive "P")
  1773.   (let (buff str)
  1774.     (cond
  1775.      (p
  1776.       (setq p (w3-view-this-url t))
  1777.       (or p (error "No url under point"))
  1778.       (setq str (format "<A HREF=\"%s\">%s</A>" p
  1779.             (read-string "Link text: "
  1780.                      (nth 3 (w3-zone-data
  1781.                          (w3-zone-at (point))))))))
  1782.      (t
  1783.       (setq str (format "<A HREF=\"%s\">%s</A>" (url-view-url t)
  1784.             (read-string "Link text: " (buffer-name))))))
  1785.     (setq buff (read-buffer "Insert into buffer: " nil t))
  1786.     (if buff
  1787.     (save-excursion
  1788.       (set-buffer buff)
  1789.       (w3-insert str))
  1790.       (message "Cancelled."))))
  1791.  
  1792. (defun w3-first-n-items (l n)
  1793.   "Return the first N items from list L"
  1794.   (let ((x 0)
  1795.     y)
  1796.     (if (> n (length l))
  1797.     (setq y l)
  1798.       (while (< x n)
  1799.     (setq y (nconc y (list (nth x l)))
  1800.           x (1+ x))))
  1801.     y))
  1802.  
  1803. (defun w3-breakup-menu (menu-desc max-len)
  1804.   (if (> (length menu-desc) max-len)
  1805.       (cons (cons "More..." (w3-first-n-items menu-desc max-len))
  1806.         (w3-breakup-menu (nthcdr max-len menu-desc) max-len))
  1807.     menu-desc))
  1808.  
  1809. ;;;###autoload
  1810. (defun w3-maybe-follow-link-mouse (e)
  1811.   "Maybe follow a hypertext link under point.
  1812. If there is no link under point, this will try using
  1813. url-get-url-at-point"
  1814.   (interactive "e")
  1815.   (save-excursion
  1816.     (mouse-set-point e)
  1817.     (w3-maybe-follow-link)))
  1818.  
  1819. ;;;###autoload
  1820. (defun w3-maybe-follow-link ()
  1821.   "Maybe follow a hypertext link under point.
  1822. If there is no link under point, this will try using
  1823. url-get-url-at-point"
  1824.   (interactive)
  1825.   (require 'w3)
  1826.   (if (not w3-setup-done) (w3-do-setup))
  1827.   (let* ((zn  (w3-zone-at (point)))
  1828.          (url1 (and zn (w3-zone-data zn)))
  1829.          (url2 (url-get-url-at-point)))
  1830.     (cond
  1831.       (url1 (w3-follow-link))
  1832.       ((and url2 (string-match url-nonrelative-link url2)) (w3-fetch url2))
  1833.       (t (message "w3-maybe-follow-link got confused.")))))
  1834.  
  1835. ;;;###autoload
  1836. (defun w3-follow-url-at-point-other-frame (&optional pt)
  1837.   "Follow the URL under PT, defaults to link under (point)"
  1838.   (interactive "d")
  1839.   (w3-fetch-other-frame (url-get-url-at-point pt)))
  1840.  
  1841. ;;;###autoload
  1842. (defun w3-follow-url-at-point (&optional pt)
  1843.   "Follow the URL under PT, defaults to link under (point)"
  1844.   (interactive "d")
  1845.   (w3-fetch (url-get-url-at-point pt)))
  1846.  
  1847. ;;;###autoload
  1848. (defun w3-batch-fetch ()
  1849.   "Fetch all the URLs on the command line and save them to files in
  1850. the current directory.  The first argument after the -f w3-batch-fetch
  1851. on the command line should be a string specifying how to save the
  1852. information retrieved.  If it is \"html\", then the page will be
  1853. unformatted when it is written to disk.  If it is \"text\", then the
  1854. page will be formatted before it is written to disk.  If it is
  1855. \"binary\" it will not mess with the file extensions, and just save
  1856. the data in raw binary format.  If none of those, the default is
  1857. \"text\", and the first argument is treated as a normal URL."
  1858.   (if (not w3-setup-done) (w3-do-setup))
  1859.   (if (not noninteractive)
  1860.       (error "`w3-batch-fetch' is to be used only with -batch"))
  1861.   (let ((fname "")
  1862.         (curname "")
  1863.     (x 0)
  1864.     (args command-line-args-left)
  1865.     (w3-strict-width 80)
  1866.     (w3-delimit-emphasis nil)
  1867.     (w3-delimit-links nil)
  1868.     (retrieval-function 'w3-fetch)
  1869.     (file-format "text")
  1870.     (header "")
  1871.     (file-extn ".txt"))
  1872.     (setq file-format (downcase (car args)))
  1873.     (cond
  1874.      ((string= file-format "html")
  1875.       (message "Saving all text as raw HTML...")
  1876.       (setq retrieval-function 'url-retrieve
  1877.         file-extn ".html"
  1878.         header "<BASE HREF=\"%s\">"
  1879.         args (cdr args)))
  1880.      ((string= file-format "binary")
  1881.       (message "Saving as raw binary...")
  1882.       (setq retrieval-function 'url-retrieve
  1883.         file-extn ""
  1884.         args (cdr args)))
  1885.      ((string= file-format "text")
  1886.       (setq header "Text from: %s\n---------------\n")
  1887.       (message "Saving all text as formatted...")
  1888.       (setq args (cdr args)))
  1889.      (t
  1890.       (setq header "Text from: %s\n---------------\n")
  1891.       (message "Going with default, saving all text as formatted...")))
  1892.     (while args
  1893.       (funcall retrieval-function (car args))
  1894.       (goto-char (point-min))
  1895.       (if buffer-read-only (toggle-read-only))
  1896.       (insert (format header (car args)))
  1897.       (setq fname (url-basepath url-current-file t))
  1898.       (if (string= file-extn "") nil
  1899.     (setq fname (url-file-extension fname t)))
  1900.       (if (string= (url-strip-leading-spaces fname) "")
  1901.       (setq fname "root"))
  1902.       (setq curname fname)
  1903.       (while (file-exists-p (concat curname file-extn))
  1904.     (setq curname (concat fname x)
  1905.           x (1+ x)))
  1906.       (setq fname (concat curname file-extn))
  1907.       (write-region (point-min) (point-max) fname)
  1908.       (setq args (cdr args)))))
  1909.  
  1910. (defun w3-fix-spaces (x)
  1911.   "Remove spaces/tabs at the beginning of a string,
  1912. and convert newlines into spaces."
  1913.   (url-convert-newlines-to-spaces
  1914.    (url-strip-leading-spaces
  1915.     (url-eat-trailing-space x))))
  1916.  
  1917. (defun w3-reload-all-files ()
  1918.   "Reload all w3 files"
  1919.   (interactive)
  1920.   (setq w3-setup-done nil
  1921.     url-setup-done nil
  1922.     w3-hotlist nil
  1923.     url-mime-accept-string nil)
  1924.   (let ((x '(w3 w3-mule w3-emacs w3-e19 w3-epoch mm url w3-next
  1925.         w3-mac w3-dos)))
  1926.     (while x
  1927.       (setq features (delq (car x) features)
  1928.         x (cdr x)))
  1929.     (require 'w3))
  1930.   (w3-do-setup)
  1931.   (url-do-setup)
  1932.   )
  1933.  
  1934. (defun w3-source-document-at-point ()
  1935.   "View source to the document pointed at by link under point"
  1936.   (interactive)
  1937.   (w3-source-document t))
  1938.  
  1939. (defun w3-source-document (under)
  1940.   "View this document's source"
  1941.   (interactive "P")
  1942.   (let* ((url (if under (w3-view-this-url) (url-view-url t)))
  1943.      (fil (if under nil url-current-file))
  1944.      (src
  1945.       (cond
  1946.        ((or (null url) (string= url "file:nil"))
  1947.         (error "Not a w3 buffer!"))
  1948.        ((and under (null url)) (error "No link at point!"))
  1949.        ((and (not under) w3-current-source) w3-current-source)
  1950.        (t
  1951.         (prog2
  1952.         (url-retrieve url)
  1953.         (buffer-string)
  1954.           (setq fil (or fil url-current-file))
  1955.           (kill-buffer (current-buffer))))))
  1956.      (tmp (url-generate-new-buffer-name url)))
  1957.     (if (and url (get-buffer url)
  1958.          (funcall url-confirmation-func
  1959.               (concat "Source for " url " found, reuse? ")))
  1960.     (progn
  1961.       (if w3-mutable-windows (pop-to-buffer url) (switch-to-buffer url))
  1962.       (setq url nil)))
  1963.     (if (not url) nil
  1964.       (set-buffer (get-buffer-create tmp))
  1965.       (insert src)
  1966.       (goto-char (point-min))
  1967.       (setq buffer-file-truename fil
  1968.         buffer-file-name fil)
  1969.       ;; This taken out because it causes call-process to die a hideous
  1970.       ;; death and not let you do anything like M-| lpr in the source
  1971.       ;; buffers.
  1972.       ;; (setq default-directory (or (file-name-directory fil) "~/"))
  1973.       (set-auto-mode)
  1974.       (buffer-enable-undo)
  1975.       (set-buffer-modified-p nil)
  1976.       (if w3-mutable-windows (pop-to-buffer tmp) (switch-to-buffer tmp))))
  1977.   (run-hooks 'w3-source-file-hook))
  1978.  
  1979. (defun w3-mail-document-under-point ()
  1980.   "Mail the document pointed to by the hyperlink under point."
  1981.   (interactive)
  1982.   (w3-mail-current-document t))
  1983.  
  1984. (defun w3-mail-current-document (under &optional format)
  1985.   "Mail the current-document to someone"
  1986.   (interactive "P")
  1987.   (let* ((completion-ignore-case t)
  1988.      (format (or format
  1989.              (completing-read
  1990.               "Format: "
  1991.               '(("HTML Source")
  1992.             ("Formatted Text")
  1993.             ("PostScript")
  1994.             ("LaTeX Source")
  1995.             )
  1996.           nil t)))
  1997.      (url (cond
  1998.            ((stringp under) under)
  1999.            (under (w3-view-this-url t))
  2000.            (t (url-view-url t))))
  2001.      (content-type "text/plain; charset=iso-8859-1")
  2002.      (str
  2003.       (save-excursion
  2004.         (cond
  2005.          ((and (equal "HTML Source" format) under)
  2006.           (setq content-type "text/html; charset=iso-8859-1")
  2007.           (let ((url-source t))
  2008.         (url-retrieve url)))
  2009.          ((equal "HTML Source" format)
  2010.           (setq content-type "text/html; charset=iso-8859-1")
  2011.           (if w3-current-source
  2012.           (let ((x w3-current-source))
  2013.             (set-buffer (get-buffer-create url-working-buffer))
  2014.             (erase-buffer)
  2015.             (insert x))
  2016.         (url-retrieve url)))
  2017.          ((and under (equal "PostScript" format))
  2018.           (setq content-type "application/postscript")
  2019.           (w3-fetch url)
  2020.           (let ((ps-spool-buffer-name " *w3-temp*"))
  2021.         (if (get-buffer ps-spool-buffer-name)
  2022.             (kill-buffer ps-spool-buffer-name))
  2023.         (w3-print-with-ps-print (current-buffer)
  2024.                     'ps-spool-buffer-with-faces)
  2025.         (set-buffer ps-spool-buffer-name)))
  2026.          ((equal "PostScript" format)
  2027.           (let ((ps-spool-buffer-name " *w3-temp*"))
  2028.         (if (get-buffer ps-spool-buffer-name)
  2029.             (kill-buffer ps-spool-buffer-name))
  2030.         (setq content-type "application/postscript")
  2031.         (w3-print-with-ps-print (current-buffer)
  2032.                     'ps-spool-buffer-with-faces)
  2033.         (set-buffer ps-spool-buffer-name)))
  2034.          ((and under (equal "Formatted Text" format))
  2035.           (setq content-type "text/plain; charset=iso-8859-1")
  2036.           (w3-fetch url))
  2037.          ((equal "Formatted Text" format)
  2038.           (setq content-type "text/plain; charset=iso-8859-1"))
  2039.          ((and under (equal "LaTeX Source" format))
  2040.           (setq content-type "application/x-latex; charset=iso-8859-1")
  2041.           (url-retrieve url)
  2042.           (w3-convert-html-to-latex))
  2043.          ((equal "LaTeX Source" format)
  2044.           (setq content-type "application/x-latex; charset=iso-8859-1")
  2045.           (if w3-current-source
  2046.           (let ((x w3-current-source))
  2047.             (set-buffer (get-buffer-create url-working-buffer))
  2048.             (erase-buffer)
  2049.             (insert x))
  2050.         (url-retrieve url))
  2051.           (w3-convert-html-to-latex)))
  2052.         (buffer-string))))
  2053.     (cond
  2054.      ((and w3-mutable-windows (fboundp w3-mail-other-window-command))
  2055.       (funcall w3-mail-other-window-command))
  2056.      ((fboundp w3-mail-command)
  2057.       (funcall w3-mail-command))
  2058.      (w3-mutable-windows (mail-other-window))
  2059.      (t (mail)))
  2060.     (mail-subject)
  2061.     (insert format " from URL " url "\n"
  2062.         "Mime-Version: 1.0\n"
  2063.         "Content-transfer-encoding: 8bit\n"
  2064.         "Content-type: " content-type)
  2065.  
  2066.     (re-search-forward mail-header-separator nil)
  2067.     (forward-char 1)
  2068.     (insert (if (equal "HTML Source" format)
  2069.         (format "<BASE HREF=\"%s\">" url) "")
  2070.         str)
  2071.     (mail-to)))
  2072.  
  2073. (defun w3-internal-use-history (hist-item)
  2074.   ;; Go to the link in the history
  2075.   (let ((url (nth 0 hist-item))
  2076.     (buf (nth 1 hist-item))
  2077.     (pnt (nth 2 hist-item)))
  2078.     (cond
  2079.      ((null buf)            ; Find a buffer with same url
  2080.       (let ((x (buffer-list))
  2081.         (found nil))
  2082.     (while (and x (not found))
  2083.       (save-excursion
  2084.         (set-buffer (car x))
  2085.         (setq found (string= (url-view-url t) url))
  2086.         (if (not found) (setq x (cdr x)))))
  2087.     (cond
  2088.      (found
  2089.       (switch-to-buffer (car x))
  2090.       (if (number-or-marker-p pnt) (goto-char pnt)))
  2091.      (t
  2092.       (w3-fetch url)))))
  2093.      ((buffer-name buf)            ; Reuse the old buffer if possible
  2094.       (switch-to-buffer buf)
  2095.       (if (number-or-marker-p pnt) (goto-char pnt))
  2096.       (if (and url (= ?# (string-to-char url)))    ; Destination link
  2097.       (progn
  2098.         (goto-char (point-min))
  2099.         (w3-find-specific-link (substring url 1 nil)))))
  2100.      (url (url-maybe-relative url))        ; Get the link
  2101.      (t (message "Couldn't understand whats in the history.")))))
  2102.  
  2103. (defun w3-relative-link (url)
  2104.   (if (equal "#" (substring url 0 1))
  2105.       (progn
  2106.     (push-mark (point) t)
  2107.     (goto-char (point-min))
  2108.     (w3-find-specific-link (substring url 1 nil)))
  2109.     (w3-fetch (url-expand-file-name url))))
  2110.  
  2111. (defun w3-maybe-eval ()
  2112.   ;; Maybe evaluate a buffer of emacs lisp code
  2113.   (if (funcall url-confirmation-func "This is emacs-lisp code, evaluate it?")
  2114.       (eval-buffer (current-buffer))
  2115.     (emacs-lisp-mode)))
  2116.  
  2117. (defun w3-build-continuation ()
  2118.   ;; Build a series of functions to be run on this file
  2119.   (save-excursion
  2120.     (set-buffer url-working-buffer)
  2121.     (let ((cont w3-default-continuation)
  2122.       (extn (url-file-extension url-current-file)))
  2123.       (if (assoc extn url-uncompressor-alist)
  2124.       (setq extn (url-file-extension
  2125.               (substring url-current-file 0 (- (length extn))))))
  2126.       (if w3-source
  2127.       (setq url-current-mime-viewer '(("viewer" . w3-source))))
  2128.       (if (not url-current-mime-viewer)
  2129.       (setq url-current-mime-viewer
  2130.         (mm-mime-info (or url-current-mime-type
  2131.                   (mm-extension-to-mime extn)) nil 5)))
  2132.       (if url-current-mime-viewer
  2133.       (setq cont (append cont '(w3-pass-to-viewer)))
  2134.     (setq cont (append cont (list w3-default-action))))
  2135.       cont)))
  2136.  
  2137. (defun w3-use-links ()
  2138.   "Select one of the <LINK> tags from this document and fetch it."
  2139.   (interactive)
  2140.   (and (not w3-current-links)
  2141.        (error "No links defined for this document."))
  2142.   (let* ((completion-ignore-case t)
  2143.      (type (cond
  2144.         ((= 0 (length w3-current-links))
  2145.          (error "No links defined for this document."))
  2146.         ((= 1 (length w3-current-links))
  2147.          (car (car w3-current-links)))
  2148.         (t (completing-read "Type of relation: "
  2149.                     '(("Parent of") ("Child of"))))))
  2150.                   
  2151.      (table (cdr-safe (assoc type w3-current-links))))
  2152.     (if (equal type "") (setq type "Parent of"))
  2153.     (if table
  2154.     (let ((url (cdr (assoc (completing-read (concat type ": ")
  2155.                         table nil t) table))))
  2156.       (if (string= url "")
  2157.           nil
  2158.         (w3-fetch url)))
  2159.       (error "No links found."))))
  2160.  
  2161. (defun w3-find-this-file ()
  2162.   "Do a find-file on the currently viewed html document if it is a file: or
  2163. ftp: reference"
  2164.   (interactive)
  2165.   (cond
  2166.    ((and (or (null url-current-type) (equal url-current-type "file"))
  2167.      (eq major-mode 'w3-mode))
  2168.     (if w3-mutable-windows
  2169.     (find-file-other-window url-current-file)
  2170.       (find-file url-current-file)))
  2171.    ((equal url-current-type "ftp")
  2172.     (if w3-mutable-windows
  2173.     (find-file-other-window
  2174.      (format "/%s@%s:%s" url-current-user url-current-server
  2175.          url-current-file))
  2176.       (find-file
  2177.        (format "/%s@%s:%s" url-current-user url-current-server
  2178.            url-current-file))))
  2179.    (t (message "Sorry, I can't get that file so you can alter it."))))
  2180.  
  2181. (defun w3-insert-this-url (pref-arg)
  2182.   "Insert the current url in another buffer, with prefix ARG,
  2183. insert URL under point"
  2184.   (interactive "P")
  2185.   (let ((thebuf (get-buffer (read-buffer "Insert into buffer: ")))
  2186.     (oldbuf (current-buffer))
  2187.     (url (if pref-arg (w3-view-this-url t) (url-view-url t))))
  2188.     (if (not (equal "Not on a link!" url))
  2189.     (progn
  2190.       (set-buffer thebuf)
  2191.       (w3-insert url)
  2192.       (set-buffer oldbuf)))))
  2193.  
  2194. (defun w3-show-hotlist ()
  2195.   "View the hotlist in hypertext form"
  2196.   (interactive)
  2197.   (if (not w3-setup-done) (w3-do-setup))
  2198.   (if (not w3-hotlist)
  2199.       (error "Sorry, no hotlist is in memory.")
  2200.     (let ((x (url-buffer-visiting "www:/auto/hotlist")))
  2201.       (while x
  2202.     (kill-buffer x)
  2203.     (setq x (url-buffer-visiting "www:/auto/hotlist"))))
  2204.     (w3-fetch "www://auto/hotlist")))
  2205.  
  2206. (defun url-maybe-relative (url)
  2207.   "Take a url and either fetch it, or resolve relative refs, then fetch it"
  2208.   (cond
  2209.    ((not
  2210.      (string-match url-nonrelative-link url))
  2211.     (w3-relative-link url))
  2212.    (t (w3-fetch url))))
  2213.  
  2214. (defun w3-in-assoc (elt list)
  2215.   "Check to see if ELT matches any of the regexps in the car elements of LIST"
  2216.   (let (rslt)
  2217.     (while (and list (not rslt))
  2218.       (and (car (car list))
  2219.        (stringp (car (car list)))
  2220.        (not (string= (car (car list)) ""))
  2221.        (string-match (car (car list)) elt)
  2222.        (setq rslt (car list)))
  2223.       (setq list (cdr list)))
  2224.     rslt))
  2225.  
  2226. (defun w3-goto-last-buffer ()
  2227.   "Go to last WWW buffer visited"
  2228.   (interactive)
  2229.   (if w3-current-last-buffer
  2230.       (if w3-mutable-windows
  2231.       (pop-to-buffer w3-current-last-buffer)
  2232.     (switch-to-buffer w3-current-last-buffer))
  2233.     (message "No previous buffer found.")))
  2234.  
  2235. (fset 'w3-replace-regexp 'url-replace-regexp)
  2236.  
  2237. ;;;###autoload
  2238. (defun w3-preview-this-buffer ()
  2239.   "See what this buffer will look like when its formatted as HTML.
  2240. HTML is the HyperText Markup Language used by the World Wide Web to
  2241. specify formatting for text.  More information on HTML can be found at
  2242. ftp.w3.org:/pub/www/doc."
  2243.   (interactive)
  2244.   (w3-fetch (concat "www://preview/" (buffer-name))))
  2245.  
  2246. (defun w3-edit-source ()
  2247.   "Edit the html document just retrieved"
  2248.   (set-buffer url-working-buffer)
  2249.   (let ((ttl (format "Editing %s Annotation: %s"
  2250.              (cond
  2251.               ((eq w3-editing-annotation 'group) "Group")
  2252.               ((eq w3-editing-annotation 'personal) "Personal")
  2253.               (t "Unknown"))
  2254.              (url-basepath url-current-file t)))
  2255.     (str (buffer-string)))
  2256.     (set-buffer (get-buffer-create ttl))
  2257.     (w3-insert str)
  2258.     (kill-buffer url-working-buffer)))
  2259.  
  2260. (defun w3-source ()
  2261.   "Show the source of a file"
  2262.   (let ((tmp (buffer-name (generate-new-buffer "Document Source"))))
  2263.     (set-buffer url-working-buffer)
  2264.     (kill-buffer tmp)
  2265.     (rename-buffer tmp)
  2266.     (set-buffer-modified-p nil)
  2267.     (buffer-enable-undo)
  2268.     (if w3-mutable-windows (pop-to-buffer tmp) (switch-to-buffer tmp))))
  2269.  
  2270. (defun w3-sentinel (&optional proc string)
  2271.   (set-buffer url-working-buffer)
  2272.   (if (or (stringp proc)
  2273.       (bufferp proc)) (setq w3-current-last-buffer proc))
  2274.   (if (boundp 'after-change-functions)
  2275.       (remove-hook 'after-change-functions 'url-after-change-function))
  2276.   (if url-be-asynchronous
  2277.       (progn
  2278.     (url-clean-text)
  2279.     (cond
  2280.      ((not (get-buffer url-working-buffer)) nil)
  2281.      ((url-mime-response-p) (url-parse-mime-headers)))
  2282.     (if (not url-current-mime-type)
  2283.         (setq url-current-mime-type (mm-extension-to-mime
  2284.                      (url-file-extension
  2285.                       url-current-file))))))
  2286.   (let ((x (w3-build-continuation))
  2287.     (done-mule-conversion nil))
  2288.     (while x
  2289.       (if (and (boundp 'MULE) (not (eq 'url-uncompress (car x)))
  2290.            (not done-mule-conversion))
  2291.       (progn
  2292.         (w3-convert-code-for-mule url-current-mime-type)
  2293.         (setq done-mule-conversion t)))
  2294.       (funcall (car x))
  2295.       (setq x (cdr x)))))
  2296.  
  2297. (defun w3-show-history-list ()
  2298.   "Format the url-history-list prettily and show it to the user"
  2299.   (interactive)
  2300.   (w3-fetch "www://auto/history"))
  2301.  
  2302. (defun w3-save-as (&optional type)
  2303.   "Save a document to the local disk"
  2304.   (interactive)
  2305.   (let* ((completion-ignore-case t)
  2306.      (format (or type (completing-read
  2307.                "Format: "
  2308.                '(("HTML Source") ("Formatted Text")
  2309.                  ("LaTeX Source") ("Binary"))
  2310.                nil t)))
  2311.     (fname (expand-file-name
  2312.         (read-file-name "File name: " default-directory)))
  2313.     (url (url-view-url t)))
  2314.     (cond
  2315.      ((equal "Binary" format)
  2316.       (if (not w3-current-source)
  2317.       (let ((url-be-asynchronous nil))
  2318.         (url-retrieve url))))
  2319.      ((equal "HTML Source" format)
  2320.       (if (not w3-current-source)
  2321.       (let ((url-be-asynchronous nil))
  2322.         (url-retrieve url))        ; Get the document if necessary
  2323.     (let ((txt w3-current-source))
  2324.       (set-buffer (get-buffer-create url-working-buffer))
  2325.       (insert txt)))
  2326.       (goto-char (point-min))
  2327.       (insert (format "<BASE HREF=\"%s\">\n" url)))
  2328.      ((or (equal "Formatted Text" format)
  2329.       (equal "" format))
  2330.       nil)                ; Do nothing - we have the text already
  2331.      ((equal "LaTeX Source" format)
  2332.       (if (not w3-current-source)
  2333.       (let ((url-be-asynchronous nil))
  2334.         (url-retrieve url))        ; Get the file
  2335.     (let ((txt w3-current-source))
  2336.       (set-buffer (get-buffer-create url-working-buffer))
  2337.       (insert txt)))
  2338.       (w3-convert-html-to-latex)))    ; Convert to LaTeX
  2339.     (write-region (point-min) (point-max) fname)))
  2340.  
  2341.  
  2342. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2343. ;;; Functions to parse out <A> tags and replace it with a hyperlink zone
  2344. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2345. (defun w3-popup-info (&optional url)
  2346.   "Show information about the link under point. (All SGML attributes)"
  2347.   (interactive)
  2348.   (let* ((ext (w3-zone-at (point)))
  2349.      (dat (and ext (w3-zone-data ext))))
  2350.     (setq url (or url (nth 2 dat))
  2351.       dat (nth 4 dat))
  2352.     (if url
  2353.      (save-excursion
  2354.        (set-buffer (get-buffer-create "*Header Info*"))
  2355.        (erase-buffer)
  2356.        (if (and dat (listp dat))
  2357.            (insert
  2358.         "Link attributes:\n"
  2359.         (make-string (1- (window-width)) ?-) "\n"
  2360.         (mapconcat
  2361.          (function
  2362.           (lambda (info)
  2363.             (format "%20s :== %s" (car info) (or (cdr info) "On"))))
  2364.          dat "\n")
  2365.         "\n" (make-string (1- (window-width)) ?-) "\n"))
  2366.        (insert (save-excursion (url-popup-info url)))
  2367.        (goto-char (point-min))
  2368.        (display-buffer (current-buffer) t))
  2369.       (message "No URL to get information on!"))))
  2370.  
  2371. (fset 'w3-document-information-this-url 'w3-popup-info)
  2372.  
  2373.  
  2374. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2375. ;;; Functions for logging of bad HTML
  2376. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2377. (defun w3-reconstruct-tag (tagname desc)
  2378.   (concat "<" tagname " "
  2379.       (mapconcat
  2380.        (function (lambda (x)
  2381.                (if (cdr x)
  2382.                (concat (car x) "=\"" (cdr x) "\"")
  2383.              (car x)))) desc " ") ">"))
  2384.  
  2385. (defun w3-debug-if-found (regexp type desc)
  2386.   (and w3-debug-html
  2387.        (save-excursion
  2388.      (if (re-search-forward regexp nil t)
  2389.          (w3-log-bad-html type desc)))))
  2390.  
  2391. (defun w3-log-bad-html (type desc)
  2392.   ;; Log bad HTML to the buffer specified by w3-debug-buffer
  2393.   (if w3-debug-html
  2394.       (save-excursion
  2395.     (set-buffer (get-buffer-create w3-debug-buffer))
  2396.     (goto-char (point-max))
  2397.     (insert (make-string (1- (window-width)) w3-horizontal-rule-char) "\n")
  2398.     (cond
  2399.      ((stringp type) (insert type "\n" desc "\n"))
  2400.      ((eq type 'bad-quote)
  2401.       (insert "Unterminated quoting character in SGML attribute value.\n"
  2402.           desc "\n"))
  2403.      ((eq type 'no-quote)
  2404.       (insert "Unquoted SGML attribute value.\n" desc "\n"))
  2405.      ((eq type 'no-textarea-end)
  2406.       (insert "Unterminated <textarea> tag.\n"
  2407.           (w3-reconstruct-tag "textarea" desc) "\n"))
  2408.      ((eq type 'bad-link-tag)
  2409.       (insert "Must specify either REL or REV with a <link> tag.\n"
  2410.           (w3-reconstruct-tag "link" desc) "\n"))
  2411.      ((eq type 'no-a-end)
  2412.       (insert "Unterminated <a> tag.\n"
  2413.           (w3-reconstruct-tag "a" desc) "\n"))
  2414.      ((eq type 'no-form-end)
  2415.       (insert "Unterminated <form> tag.\n"
  2416.           (w3-reconstruct-tag "form" desc) "\n"))
  2417.      ((eq type 'bad-base-tag)
  2418.       (insert "Malformed <base> tag.\n"
  2419.           (w3-reconstruct-tag "base" desc) "\n"))))))
  2420.  
  2421.  
  2422. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2423. ;;; Functions to handle formatting an html buffer
  2424. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2425. (defun w3-handle-personal-annotations ()
  2426.   ;; Take care of personal annotations
  2427.   (url-lazy-message "Finding personal annotations...")
  2428.   (let ((annos (w3-fetch-personal-annotations)))
  2429.     (if annos
  2430.     (progn
  2431.       (goto-char (cond
  2432.               ((eq w3-annotation-position 'bottom) (point-max))
  2433.               ((eq w3-annotation-position 'top) (point-min))
  2434.               (t (message "Bad value for w3-annotation-position")
  2435.              (point-max))))
  2436.       (w3-insert"<P><HR>\n<H1>Personal Annotations</H1><P><UL>")
  2437.       (while annos
  2438.         (w3-insert "\n<LI> " (car annos))
  2439.         (setq annos (cdr annos)))
  2440.       (w3-insert "</UL><HR>"))))
  2441.   (url-lazy-message "Finding personal annotations... done."))
  2442.  
  2443. (defun w3-insert-headers ()
  2444.   ;; Insert some HTTP/1.0 headers if necessary
  2445.   (url-lazy-message "Inserting HTTP/1.0 headers...")
  2446.   (let ((hdrs (if (eq t w3-show-headers) (mapcar 'car url-current-mime-headers)
  2447.         w3-show-headers))
  2448.     x y)
  2449.     (goto-char (setq y (point-max)))
  2450.     (while hdrs
  2451.       (if (setq x (w3-in-assoc (car hdrs) url-current-mime-headers))
  2452.       (w3-insert "<LI> <B>" (car x) "</B>: " (w3-insert-entities-in-string
  2453.                           (if (numberp (cdr x))
  2454.                               (int-to-string (cdr x))
  2455.                             (cdr x)))))
  2456.       (setq hdrs (cdr hdrs)))
  2457.     (if (= y (point-max))
  2458.     nil
  2459.       (w3-insert "</UL>")
  2460.       (goto-char y)
  2461.       (url-lazy-message "Inserting HTTP/1.0 headers... done.")
  2462.       (w3-insert "<HR><UL>"))))
  2463.  
  2464. (defun w3-add-delayed-mpeg (src st &optional width height)
  2465.   ;; Add a delayed mpeg for the current buffer.
  2466.   (setq w3-delayed-movies (cons (list src
  2467.                       (set-marker (make-marker) st)
  2468.                       width height)
  2469.                 w3-delayed-movies))
  2470.   (w3-handle-text (concat "[MPEG(" (url-basepath src t) ")]"))
  2471.   (w3-add-zone st (point) nil (list 'w3mpeg src st)))
  2472.  
  2473. (defun w3-add-delayed-graphic (src st align alt)
  2474.   ;; Add a delayed image for the current buffer.
  2475.   (setq st (set-marker (make-marker) st)
  2476.     w3-delayed-images (cons (list src st align alt)
  2477.                 w3-delayed-images))
  2478.   (w3-handle-text alt)
  2479.   (if (string= alt "") nil
  2480.     (w3-add-zone st (point) nil (list 'w3delayed src st align alt))))
  2481.  
  2482.  
  2483. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2484. ;;; Shared graphics routines
  2485. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2486. (defun w3-convert-graphic-to-useable-format (buf fname xbm)
  2487.   "Convert the image data in buffer BUF into a format useable by
  2488. lemacs or epoch.  Second arg FNAME is the filename to redirect output
  2489. into.  If third arg XBM is t, convert it to an Xbitmap, otherwise
  2490. convert it to an XPM (recommended, as they can do color).  Returns a
  2491. filename containing the bitmap specification"
  2492.   (save-excursion
  2493.     (set-buffer buf)
  2494.     (setq buffer-file-name nil)
  2495.     (let (converter)
  2496.       (if (not url-current-mime-type)
  2497.       (setq url-current-mime-type (mm-extension-to-mime
  2498.                        (url-file-extension url-current-file))))
  2499.       (setq converter (assoc url-current-mime-type w3-graphic-converter-alist))
  2500.       (if (not converter)
  2501.       (message "Cannot convert %s to www/present!" url-current-mime-type)
  2502.     (message "Converting %s (%s)..."
  2503.          (url-basepath url-current-file t) url-current-mime-type)
  2504.     (shell-command-on-region
  2505.      (point-min) (point-max)
  2506.      (concat (format (cdr converter)
  2507.              (concat
  2508.               (cond
  2509.                ((null w3-color-use-reducing) "")
  2510.                ((eq w3-color-filter 'ppmquant)
  2511.                 (concat "ppmquant " (int-to-string
  2512.                          (* w3-color-max-red
  2513.                             w3-color-max-green
  2514.                             w3-color-max-blue))
  2515.                     " | "))
  2516.                ((eq w3-color-filter 'ppmdither)
  2517.                 (concat
  2518.                  (if w3-ppmdither-is-buggy
  2519.                  "pnmdepth 255 | "
  2520.                    "")
  2521.                  "ppmdither -red "
  2522.                  (int-to-string w3-color-max-red)
  2523.                  " -green "
  2524.                  (int-to-string w3-color-max-green)
  2525.                  " -blue "
  2526.                  (int-to-string w3-color-max-blue)
  2527.                  " | "))
  2528.                ((stringp w3-color-filter)
  2529.                 (concat w3-color-filter " | "))
  2530.                (t ""))
  2531.               (if xbm w3-ppmtoxbm-command w3-ppmtoxpm-command)))
  2532.          "> " fname) t)))))
  2533.  
  2534. (defun w3-load-flavors ()
  2535.   ;; Load the correct zone/font info for each flavor of emacs
  2536.   (cond
  2537.    ((and w3-running-xemacs (eq system-type 'ms-windows)) (require 'w3-wemac))
  2538.    (w3-running-xemacs (require 'w3-xemac))
  2539.    (w3-running-epoch  (require 'w3-epoch))
  2540.    (w3-running-FSF19  (require 'w3-e19))
  2541.    (t                 (require 'w3-emacs)))
  2542.   (if (boundp 'MULE) (require 'w3-mule))
  2543.   (condition-case ()
  2544.       (require 'w3-site-init)
  2545.     (error nil)))
  2546.  
  2547. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2548. ;;; Automatic bug submission.                                               ;;;
  2549. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2550. (defun w3-submit-bug ()
  2551.   "Submit a bug on Emacs-w3"
  2552.   (interactive)
  2553.   (require 'reporter)
  2554.   (and (yes-or-no-p "Do you really want to submit a bug on Emacs-w3? ")
  2555.        (let ((url (url-view-url t))
  2556.          (beta-version (featurep 'w3-beta))
  2557.          (vars '(window-system
  2558.              window-system-version
  2559.              beta-version
  2560.              system-type
  2561.              ange-ftp-version
  2562.              url-gateway-method
  2563.              efs-version
  2564.              ange-ftp-version
  2565.              url-version
  2566.              url-be-asynchronous
  2567.              url)))
  2568.      (if (and url (string= url "file:nil")) (setq url nil))
  2569.      (mapcar
  2570.       (function
  2571.        (lambda (x)
  2572.          (if (not (and (boundp x) (symbol-value x)))
  2573.          (setq vars (delq x vars))))) vars)
  2574.      (reporter-submit-bug-report w3-bug-address
  2575.                      (concat "WWW v" w3-version-number " of "
  2576.                          w3-version-date)
  2577.                      vars
  2578.                      nil nil
  2579.                      "Description of Problem:"))))
  2580.  
  2581. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2582. ;;; Support for searching                            ;;;
  2583. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2584. (defun w3-nuke-spaces-in-search (x)
  2585.   "Remove spaces from search strings . . ."
  2586.   (let ((new ""))
  2587.     (while (not (equal x ""))
  2588.       (setq new (concat new (if (= (string-to-char x) 32) "+"
  2589.                   (substring x 0 1)))
  2590.         x (substring x 1 nil)))
  2591.     new))
  2592.  
  2593. (defun w3-search ()
  2594.   "Perform a search, if this is a searchable index."
  2595.   (interactive)
  2596.   (or w3-current-isindex
  2597.       (error "Not a searchable index (via <isindex>)"))
  2598.   (let* (querystring            ; The string to send to the server
  2599.      (data
  2600.       (cond
  2601.        ((null w3-current-isindex)
  2602.         (let ((rels (mapcar
  2603.              (function
  2604.               (lambda (data)
  2605.                 (if (assoc "rel" data) data)))
  2606.              w3-current-links))
  2607.           val)
  2608.           (while rels
  2609.         (if (string-match "useindex"
  2610.                   (or (cdr (assoc "rel" (car rels))) ""))
  2611.             (setq val (cdr (assoc "href" (car rels)))
  2612.               rels nil))
  2613.         (setq rels (cdr rels)))
  2614.           (cons val "Search on (+ separates keywords): ")))
  2615.        ((eq w3-current-isindex t)
  2616.         (cons (url-view-url t) "Search on (+ separates keywords): "))
  2617.        ((consp w3-current-isindex)
  2618.         w3-current-isindex)
  2619.        (t nil)))
  2620.      index)
  2621.     (if (null data) (error "Not a searchable index!"))
  2622.     (setq index (car data))
  2623.     (setq querystring (w3-nuke-spaces-in-search (read-string (cdr data))))
  2624.     (if (string-match "\\(.*\\)\\?.*" index)
  2625.     (setq index (url-match index 1)))
  2626.     (w3-fetch
  2627.      (concat index (if (= ?? (string-to-char (substring index -1 nil)))
  2628.                "" "?") querystring))))
  2629.  
  2630. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2631. ;;; Auto documentation, etc                                                 ;;;
  2632. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2633. (defun w3-help ()
  2634.   "Print documentation on w3 mode."
  2635.   (interactive)
  2636.   (w3-fetch "about:"))
  2637.  
  2638. (defun w3-version ()
  2639.   "Show the version # of W3 in the minibuffer"
  2640.   (interactive)
  2641.   (message "WWW %s, URL %s, MM %s" w3-version-number url-version mm-version))
  2642.  
  2643. ;;;###autoload
  2644. (defun w3 ()
  2645.   "Retrieve the default World Wide Web home page.
  2646. The World Wide Web is a global hypertext system started by CERN in
  2647. Switzerland in 1991.
  2648.  
  2649. The home page is specified by the variable w3-default-homepage.  The
  2650. document should be specified by its fully specified Uniform Resource
  2651. Locator.  The document will be parsed as HTML (if appropriate) and
  2652. displayed in a new buffer."
  2653.   (interactive)
  2654.   (if (not w3-setup-done) (w3-do-setup))
  2655.   (if (and w3-track-last-buffer
  2656.        (bufferp w3-last-buffer)
  2657.        (buffer-name w3-last-buffer))
  2658.       (progn
  2659.     (switch-to-buffer w3-last-buffer)
  2660.     (message "Reusing buffer.  To reload, type %s."
  2661.          (substitute-command-keys "\\[w3-reload-document]")))
  2662.     (cond
  2663.      ((null w3-default-homepage) (call-interactively 'w3-fetch))
  2664.      ((not (stringp w3-default-homepage))
  2665.       (error "Invalid setting for w3-default-homepage: %S"
  2666.          w3-default-homepage))
  2667.      ((not (string-match ".*:.*" w3-default-homepage))
  2668.       (w3-fetch (concat "file:" w3-default-homepage)))
  2669.      (t
  2670.       (w3-fetch w3-default-homepage)))))
  2671.  
  2672. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2673. ;;; Leftover stuff that didn't quite fit into url.el
  2674. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2675.  
  2676. (defun w3-generate-error (type data)
  2677.   ;; Generate an HTML error buffer for error TYPE with data DATA.
  2678.   (cond
  2679.    ((equal type "nofile")
  2680.     (let ((error (save-excursion
  2681.           (set-buffer (get-buffer-create " *url-error*"))
  2682.           (buffer-string))))
  2683.       (if (string= "" error)
  2684.       (setq error
  2685.         (format (concat "The file %s could not be found.  "
  2686.                 "Either it does not exist, or it "
  2687.                 "is unreadable.") data)))
  2688.       (insert "<html>\n <head>\n"
  2689.         "  <title>Error</title>\n"
  2690.         " </head>\n <body>\n"
  2691.         "  <h1>Error accessing " data "</h1>\n"
  2692.         "  <hr>\n  <p>"
  2693.         error
  2694.         "\n  </p>\n")))
  2695.    ((equal type "nobuf")
  2696.     (insert "<title>Error</title>\n"
  2697.         "<H1>No buffer " data " found</h1>\n"
  2698.         "<HR>\n"
  2699.         "The buffer " data " could not be found.  It has either\n"
  2700.         "been killed or renamed.\n"))
  2701.    ((equal type "nohist")
  2702.     (insert "<TITLE>Error</TITLE>\n"
  2703.         "<H1>No history items found.</H1>\n"
  2704.         "<HR>\n"
  2705.         "There is no history list available at this time.  Either\n"
  2706.         "you have not visited any nodes, or the variable <i>\n"
  2707.         "url-keep-history</i> is nil.\n"))
  2708.    )
  2709.   (insert "<hr>\n"
  2710.       "If you feel this is a bug, <a href=\"mailto:"
  2711.       w3-bug-address "\">send mail to " w3-bug-address
  2712.       "</a>\n<hr>"))
  2713.  
  2714. (defun w3-generate-auto-html (type)
  2715.   ;; Generate one of several automatic html pages
  2716.   (setq url-current-mime-type "text/html"
  2717.     url-current-mime-headers '(("content-type" . "text/html")))
  2718.   (cond
  2719.    ((equal type "hotlist")
  2720.     (let ((tmp (reverse w3-hotlist)))
  2721.       (insert "<html>\n\t<head>\n\t\t"
  2722.           "<title> Hotlist </title>\n\t</head>\n"
  2723.           "\t<body>\n\t\t<div1>\n\t\t\t<h1>Hotlist from " w3-hotlist-file
  2724.           "</h1>\n\t\t\t<ol>\n")
  2725.       (while tmp
  2726.     (insert  "\t\t\t\t<li> <a href=\"" (car (cdr (car tmp)))
  2727.          "\">" (car (car tmp)) "</a></li>\n")
  2728.     (setq tmp (cdr tmp)))
  2729.       (insert "\n\t\t\t</ol>\n\t\t</div1>\n\t</body>\n</html>")))
  2730.    ((equal type "starting-points")
  2731.     (let ((tmp w3-starting-documents))
  2732.       (insert "<html>\n\t<head>\n\t\t"
  2733.           "<title> Starting Points </title>\n\t</head>\n"
  2734.           "\t<body>\n\t\t<div1>\n\t\t\t<h1>Starting Point on the Web"
  2735.           "</h1>\n\t\t\t<ol>\n")
  2736.       (while tmp
  2737.     (insert (format "\t\t\t\t<li> <a href=\"%s\">%s</a></li>\n"
  2738.             (car (cdr (car tmp)))
  2739.             (car (car tmp))))
  2740.     (setq tmp (cdr tmp)))
  2741.       (insert "\n\t\t\t</ol>\n\t\t</div1>\n\t</body>\n</html>")))
  2742.    ((equal type "history")
  2743.     (if (not url-history-list)
  2744.     (url-retrieve "www://error/nohist")
  2745.       (let ((urls url-history-list))
  2746.     (insert "<html>\n\t<head>\n\t\t"
  2747.         "<title> History List For This Session of W3</title>"
  2748.         "\n\t</head>\n\t<body>\n\t\t<div1>\n\t\t\t<h1>"
  2749.         "History List For This Session of W3</h1>\n\t\t\t<ol>\n")
  2750.     (while urls
  2751.       (insert (format "\t\t\t\t<li> <a href=\"%s\">%s</A>\n"
  2752.               (car (car urls)) (cdr (car urls))))
  2753.       (setq urls (cdr urls)))
  2754.     (insert "\n\t\t\t</ol>\n\t\t</div1>\n\t</body>\n</html>"))))))
  2755.  
  2756. (defun w3-internal-url (url)
  2757.   ;; Handle internal urls (previewed buffers, etc)
  2758.   (string-match "www:/+\\([^/]+\\)/\\(.*\\)" url)
  2759.   (let ((type (url-match url 1))
  2760.     (data (url-match url 2)))
  2761.     (set-buffer (get-buffer-create url-working-buffer))
  2762.     (setq url-current-type "www"
  2763.       url-current-server type
  2764.       url-current-file data)
  2765.     (cond
  2766.      ((equal type "preview")        ; Previewing a document
  2767.       (if (get-buffer data)        ; Buffer still exists
  2768.       (insert-buffer data)        ; Insert the document
  2769.     (url-retrieve (concat "www://error/nobuf/" data))))
  2770.      ((equal type "error")        ; Error message
  2771.       (if (string-match "\\([^/]+\\)/\\(.*\\)" data)
  2772.       (w3-generate-error (url-match data 1) (url-match data 2))
  2773.     (w3-generate-error data "")))
  2774.      ((equal type "auto")        ; Hotlist or help stuff
  2775.       (w3-generate-auto-html data)))))
  2776.  
  2777. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2778. ;;; Stuff for good local file handling
  2779. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2780. (defun w3-ff (file)
  2781.   "Find a file in any window already displaying it, otherwise just as
  2782. display-buffer, and using this function"
  2783.   (if (not (eq 'tty (device-type)))
  2784.       (let ((f (window-frame (display-buffer (find-file-noselect file)))))
  2785.     (set-mouse-position f 1 0)
  2786.     (raise-frame f)
  2787.     (unfocus-frame))
  2788.     (display-buffer (find-file-noselect file))))
  2789.  
  2790. (defun w3-default-local-file()
  2791.   "Use find-file to open the local file"
  2792.   (w3-ff url-current-file))
  2793.  
  2794. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2795. ;;; Mode definition                                ;;;
  2796. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2797. (defun w3-force-reload-document ()
  2798.   "Reload the current document.  Take it from the network, even if
  2799. cached and in local mode."
  2800.   (let ((url-standalone-mode nil))
  2801.     (w3-reload-document)))
  2802.  
  2803. (defun w3-reload-document ()
  2804.   "Reload the current document"
  2805.   (interactive)
  2806.   (let ((tmp (url-view-url t))
  2807.     (pnt (point))
  2808.     (window-start (progn
  2809.             (move-to-window-line 0)
  2810.             (point)))
  2811.     (url-request-extra-headers '(("Pragma" . "no-cache"))))
  2812.     (kill-buffer (current-buffer))
  2813.     (w3-fetch tmp)
  2814.     (goto-char pnt)
  2815.     (set-window-start (selected-window) (min window-start (point-max)))))
  2816.  
  2817. (defun w3-leave-buffer ()
  2818.   "Bury this buffer, but don't kill it."
  2819.   (interactive)
  2820.   (let ((x w3-current-last-buffer))
  2821.     (bury-buffer nil)
  2822.     (if (and (bufferp x) (buffer-name x))
  2823.     (if w3-mutable-windows (pop-to-buffer x) (switch-to-buffer x)))))
  2824.  
  2825. (defun w3-quit ()
  2826.   "Quit WWW mode"
  2827.   (interactive)
  2828.   (let ((x w3-current-last-buffer))
  2829.     (and (fboundp 'w3-mpeg-kill-processes) (w3-mpeg-kill-processes))
  2830.     (kill-buffer (current-buffer))
  2831.     (if (and (bufferp x) (buffer-name x))
  2832.     (if w3-mutable-windows (pop-to-buffer x) (switch-to-buffer x)))))
  2833.  
  2834. (defun w3-view-this-url (&optional no-show)
  2835.   "View the URL of the link under point"
  2836.   (interactive)
  2837.   (let* ((ext (w3-zone-at (point)))
  2838.      (data (and ext (w3-zone-data ext))))
  2839.     (cond
  2840.      ((eq (car data) 'w3)
  2841.       (if (not no-show)
  2842.       (if (nth 2 data)
  2843.           (message "%s" (nth 2 data)))
  2844.     (nth 2 data)))
  2845.      ((eq (car data) 'w3form)
  2846.       (if (not no-show)
  2847.       (message "Form entry (name=%s, type=%s)" (nth 3 data)
  2848.            (if (equal "" (nth 2 data)) "TEXT" (nth 2 data))) nil))
  2849.      ((eq (car data) 'w3graphic)
  2850.       (if (not no-show) (message "Inlined image (%s)" (nth 1 data)) nil))
  2851.      (t (if (not no-show) (message "No link at point.")
  2852.       nil)))))
  2853.  
  2854. (defun w3-load-delayed-images ()
  2855.     "Load inlined images that were delayed, if necessary.
  2856. This function searches through `w3-delayed-images' and fetches the
  2857. appropriate picture for each point in the buffer and inserts it."
  2858.   (interactive)
  2859.   (and (fboundp 'w3-insert-graphic)
  2860.        (let ((buffer-read-only nil))
  2861.      (mapcar (function (lambda (data) (apply 'w3-insert-graphic data)))
  2862.          (nreverse w3-delayed-images))))
  2863.   (setq w3-delayed-images nil))
  2864.  
  2865. (defun w3-save-this-url ()
  2866.   "Save url under point in the kill ring"
  2867.   (interactive)
  2868.   (w3-save-url t))
  2869.  
  2870. (defun w3-save-url (under-pt)
  2871.   "Save current url in the kill ring"
  2872.   (interactive "P")
  2873.   (let ((x (cond
  2874.         ((stringp under-pt) under-pt)
  2875.         (under-pt (w3-view-this-url t))
  2876.         (t (url-view-url t)))))
  2877.     (if x
  2878.     (progn
  2879.       (setq kill-ring (cons x kill-ring))
  2880.       (setq kill-ring-yank-pointer kill-ring)
  2881.       (message "Stored URL in kill-ring.")
  2882.       (if (fboundp 'w3-store-in-x-clipboard)
  2883.           (w3-store-in-x-clipboard x)))
  2884.       (error "No URL to store."))))
  2885.  
  2886. (fset 'w3-end-of-document 'end-of-buffer)
  2887. (fset 'w3-start-of-document 'beginning-of-buffer)
  2888.  
  2889. (defun w3-scroll-up (&optional lines)
  2890.   "Scroll forward in View mode, or exit if end of text is visible.
  2891. No arg means whole window full.  Arg is number of lines to scroll."
  2892.   (interactive "P")
  2893.   (if (and (pos-visible-in-window-p (point-max))
  2894.        ;; Allow scrolling backward at the end of the buffer.
  2895.        (or (null lines)
  2896.            (> lines 0)))
  2897.       nil
  2898.     (let ((view-lines (1- (window-height))))
  2899.       (setq lines
  2900.         (if lines (prefix-numeric-value lines)
  2901.           view-lines))
  2902.       (if (>= lines view-lines)
  2903.       (scroll-up nil)
  2904.     (if (>= (- lines) view-lines)
  2905.         (scroll-down nil)
  2906.       (scroll-up lines)))
  2907.       (cond ((pos-visible-in-window-p (point-max))
  2908.          (goto-char (point-max))
  2909.          (recenter -1)))
  2910.       (move-to-window-line -1)
  2911.       (beginning-of-line))))
  2912.  
  2913. (defun w3-mail-document-author ()
  2914.   "Send mail to the author of this document, if possible."
  2915.   (interactive)
  2916.   (let ((x w3-current-links)
  2917.     (y nil)
  2918.     (found nil))
  2919.     (setq found (cdr-safe (assoc "reply-to" url-current-mime-headers)))
  2920.     (if (and found (not (string-match url-nonrelative-link found)))
  2921.     (setq found (concat "mailto:" found)))
  2922.     (while (and x (not found))
  2923.       (setq y (car x)
  2924.         x (cdr x)
  2925.         found (cdr-safe (assoc "made" y))))
  2926.     (if found (w3-fetch found)
  2927.       (error "Cannot find the 'made' link for this document, sorry."))))
  2928.  
  2929. (defun w3-kill-emacs-func ()
  2930.   "Routine called when exiting emacs.  Do miscellaneous clean up."
  2931.   (and (eq url-keep-history t)
  2932.        url-history-list
  2933.        (url-write-global-history))
  2934.   (message "Cleaning up w3 storage...")
  2935.   (let ((x (nconc
  2936.         (and (file-exists-p w3-temporary-directory)
  2937.          (directory-files w3-temporary-directory t "url-tmp.*"))
  2938.         (and (file-exists-p url-temporary-directory)
  2939.          (directory-files url-temporary-directory t
  2940.                   (concat "url"
  2941.                       (int-to-string
  2942.                        (user-real-uid)) ".*")))
  2943.         (and (file-exists-p url-temporary-directory)
  2944.          (directory-files url-temporary-directory t "url-tmp.*")))))
  2945.     (while x
  2946.       (condition-case ()
  2947.       (delete-file (car x))
  2948.     (error nil))
  2949.       (setq x (cdr x))))
  2950.   (message "Cleaning up w3 storage... done.")
  2951.   (and w3-old-kill-emacs-hook (funcall w3-old-kill-emacs-hook)))
  2952.  
  2953. (cond
  2954.  ((fboundp 'display-warning)
  2955.   (fset 'w3-warn 'display-warning))
  2956.  ((fboundp 'warn)
  2957.   (defun w3-warn (class message &optional level)
  2958.     (if (and (eq class 'html)
  2959.          (not w3-debug-html))
  2960.     nil
  2961.       (warn "(%s/%s) %s" class (or level 'warning) message))))
  2962.  (t
  2963.   (defun w3-warn (class message &optional level)
  2964.     (if (and (eq class 'html)
  2965.          (not w3-debug-html))
  2966.     nil
  2967.       (save-excursion
  2968.     (set-buffer (get-buffer-create "*W3-WARNINGS*"))
  2969.     (goto-char (point-max))
  2970.     (save-excursion
  2971.       (insert (format "(%s/%s) %s\n" class (or level 'warning) message)))
  2972.     (display-buffer (current-buffer)))))))
  2973.  
  2974. (defun w3-do-setup ()
  2975.   "Do setup - this is to avoid conflict with user settings when W3 is
  2976. dumped with emacs."
  2977.   (url-do-setup)
  2978.   (url-register-protocol 'about 'w3-about 'url-identity-expander)
  2979.   (url-register-protocol 'www 'w3-internal-url 'url-identity-expander)
  2980.            
  2981.   (setq w3-netscape-configuration-file
  2982.     (cond
  2983.      (w3-netscape-configuration-file
  2984.       w3-netscape-configuration-file)
  2985.      ((memq system-type '(ms-dos ms-windows))
  2986.       (expand-file-name "~/NETSCAPE.CFG"))
  2987.      (t (expand-file-name "~/.MCOM-preferences"))))
  2988.  
  2989.   (if (eq w3-user-colors-take-precedence 'guess)
  2990.       (progn
  2991.     (setq w3-user-colors-take-precedence (and
  2992.                           (not (eq (device-type) 'tty))
  2993.                           (not (eq (device-class) 'mono))))
  2994.     (w3-warn
  2995.      'html
  2996.      "Disabled document color specification because of mono display.")))
  2997.  
  2998.   (setq w3-default-stylesheet
  2999.     (cond
  3000.      (w3-default-stylesheet w3-default-stylesheet)
  3001.      ((memq system-type '(ms-dos ms-windows os2))
  3002.       (expand-file-name "~/w3.sty"))
  3003.      (t
  3004.       (expand-file-name "~/.w3.sty"))))
  3005.  
  3006.   (if (not (string-match url-nonrelative-link w3-default-stylesheet))
  3007.       (if (and (file-exists-p w3-default-stylesheet)
  3008.            (file-readable-p w3-default-stylesheet))
  3009.       (setq w3-default-stylesheet (concat "file:"
  3010.                           (if (= ?/
  3011.                              (string-to-char
  3012.                               w3-default-stylesheet))
  3013.                           ""
  3014.                         "/") w3-default-stylesheet))
  3015.     (setq w3-default-stylesheet nil)))
  3016.   
  3017.   (if w3-default-stylesheet
  3018.       (setq w3-user-stylesheet
  3019.         (w3-parse-arena-style-sheet w3-default-stylesheet)))
  3020.  
  3021.   (if (and w3-use-netscape-configuration-file
  3022.        w3-netscape-configuration-file
  3023.        (fboundp 'w3-read-netscape-config))
  3024.       (w3-read-netscape-config w3-netscape-configuration-file))
  3025.       
  3026.   (setq w3-default-configuration-file
  3027.     (cond
  3028.      (w3-default-configuration-file w3-default-configuration-file)
  3029.      ((memq system-type '(ms-dos ms-windows))
  3030.       (expand-file-name "~/w3.ini"))
  3031.      (t (expand-file-name "~/.w3"))))
  3032.  
  3033.   (if (and w3-default-configuration-file
  3034.        (file-exists-p w3-default-configuration-file)
  3035.        (file-readable-p w3-default-configuration-file))
  3036.       (load-file w3-default-configuration-file))
  3037.  
  3038.   (if (not (assq 'w3-annotation-minor-mode minor-mode-alist))
  3039.       (setq minor-mode-alist (cons '(w3-annotation-minor-mode " Annotating")
  3040.                    minor-mode-alist)))
  3041.   (if (and (boundp 'minor-mode-map-alist)
  3042.        (not (assq 'w3-annotation-minor-mode minor-mode-map-alist)))
  3043.       (setq minor-mode-map-alist (cons (cons 'w3-annotation-minor-mode
  3044.                          w3-annotation-minor-mode-map)
  3045.                        minor-mode-map-alist)))
  3046.   (setq url-package-version w3-version-number
  3047.     url-package-name "Emacs-W3")
  3048.  
  3049.   (w3-load-flavors)
  3050.   (w3-setup-version-specifics)
  3051.   ; Create the fonts, etc in windowing systems
  3052.   (w3-create-faces)
  3053.  
  3054.   (if (and (not w3-delay-image-loads)
  3055.        (fboundp 'w3-insert-graphic)
  3056.        (not (w3-executable-exists-in-path "ppmtoxpm"))
  3057.        (not (or
  3058.          (w3-executable-exists-in-path "pbmtoxbm")
  3059.          (w3-executable-exists-in-path "ppmtoxbm"))))
  3060.       (w3-warn
  3061.        'image
  3062.        (concat
  3063.     "Could not find some vital ppm utilities in exec-path.\n"
  3064.     "This probably means that you will be unable to view any\n"
  3065.     "inlined images other than X-Bitmaps or X-Pixmaps, which are\n"
  3066.     "now rarely used on the World Wide Web.\n\n"
  3067.     "If you do not have the PPM utilities from either the PBMPLUS\n"
  3068.     "or NETPBM distributions installed on your machine, then\n"
  3069.     "please set the variable `w3-delay-image-loads' to t with a\n"
  3070.     "line like:\n\n"
  3071.     "\t(setq w3-delay-image-loads t)\n\n"
  3072.     "in your ~/.emacs file.  Or as an alternative, please modify\n"
  3073.     "the `w3-graphic-converter-alist' variable to disallow all images\n"
  3074.     "but XBMs and XPMs, like so:\n\n"
  3075.     "\t(setq w3-graphic-converter-alist\n"
  3076.     "\t\t'(\n"
  3077.     "\t\t\t(\"image/x-xbitmap\" . \"cat \")\n"
  3078.     "\t\t\t(\"image/xbitmap\" . \"cat \")\n"
  3079.     "\t\t\t(\"image/xbm\" . \"cat \")\n"
  3080.     "\t\t\t(\"image/x-xpixmap\" . \"cat \")\n"
  3081.     "\t\t))\n\n"
  3082.     "You can find the NETPBM utilities in:\n"
  3083.     "\tftp://ftp.cs.indiana.edu/pub/elisp/w3/images/\n"
  3084.     )))
  3085.  
  3086.   (if (eq w3-color-use-reducing 'guess)
  3087.       (setq w3-color-use-reducing
  3088.         (cond
  3089.          ((eq (device-type) 'tty) nil)
  3090.          ((fboundp 'device-class)
  3091.           (not (and (memq (device-class) '(TrueColor true-color))
  3092.             (<= 16 (or (device-bitplanes) 0)))))
  3093.          (t t))))
  3094.            
  3095.   (cond
  3096.    ((memq system-type '(ms-dos ms-windows))
  3097.     (setq w3-documents-menu-file (or w3-documents-menu-file
  3098.                      (expand-file-name "~/mosaic.mnu"))
  3099.       w3-hotlist-file (or w3-hotlist-file
  3100.                   (expand-file-name "~/mosaic.hot"))
  3101.       w3-personal-annotation-directory (or w3-personal-annotation-directory
  3102.                            (expand-file-name
  3103.                         "~/mosaic.ann"))))
  3104.    ((memq system-type '(axp-vms vax-vms))
  3105.     (setq w3-documents-menu-file
  3106.       (or w3-documents-menu-file
  3107.           (expand-file-name "decw$system_defaults:documents.menu"))
  3108.       w3-hotlist-file (or w3-hotlist-file
  3109.                   (expand-file-name "~/mosaic.hotlist-default"))
  3110.       w3-personal-annotation-directory
  3111.       (or w3-personal-annotation-directory
  3112.           (expand-file-name "~/mosaic-annotations/"))))
  3113.    (t 
  3114.     (setq w3-documents-menu-file
  3115.       (or w3-documents-menu-file
  3116.           (expand-file-name "/usr/local/lib/mosaic/documents.menu"))
  3117.       w3-hotlist-file (or w3-hotlist-file
  3118.                   (expand-file-name "~/.mosaic-hotlist-default"))
  3119.       w3-personal-annotation-directory
  3120.       (or w3-personal-annotation-directory
  3121.           (expand-file-name "~/.mosaic-personal-annotations")))))
  3122.   
  3123.   ; Set up delimiting based on device-type and value of
  3124.   ; w3-emacs19-hack-faces-p
  3125.   (if (eq w3-delimit-emphasis 'guess)
  3126.       (setq w3-delimit-emphasis
  3127.         (and (not w3-running-xemacs)
  3128.          (not w3-running-epoch)
  3129.          (not (and w3-running-FSF19
  3130.                (or
  3131.                 (memq (device-type) '(x ns pm))
  3132.                 w3-emacs19-hack-faces-p))))))
  3133.  
  3134.   (if (eq w3-delimit-links 'guess)
  3135.       (setq w3-delimit-links
  3136.         (and (not w3-running-xemacs)
  3137.          (not w3-running-epoch)
  3138.          (not (and w3-running-FSF19
  3139.                (or (memq (device-type) '(x ns pm))
  3140.                    w3-emacs19-hack-faces-p))))))
  3141.  
  3142.   ; Set up a hook that will save the history list when
  3143.   ; exiting emacs
  3144.   (if (or w3-running-xemacs w3-running-FSF19)
  3145.       (add-hook 'kill-emacs-hook 'w3-kill-emacs-func)
  3146.     (setq w3-old-kill-emacs-hook kill-emacs-hook
  3147.       kill-emacs-hook 'w3-kill-emacs-func))
  3148.  
  3149.   (mm-parse-mailcaps)
  3150.   (mm-parse-mimetypes)
  3151.  
  3152.   ; Load in the hotlist if they haven't set it already
  3153.   (or w3-hotlist (w3-parse-hotlist))
  3154.  
  3155.   ; Load in their personal annotations if they haven't set them already
  3156.   (or w3-personal-annotations (w3-parse-personal-annotations))
  3157.  
  3158.   ; Set the default home page, honoring their defaults, then
  3159.   ; the standard WWW_HOME, then default to the documentation @ IU
  3160.   (or w3-default-homepage
  3161.       (setq w3-default-homepage
  3162.         (or (getenv "WWW_HOME")
  3163.         "http://www.cs.indiana.edu/elisp/w3/docs.html")))
  3164.  
  3165.   ; Set up the documents menu
  3166.   (w3-parse-docs-menu)
  3167.  
  3168.   ; Set up the entity definition for PGP and PEM authentication
  3169.  
  3170.   (run-hooks 'w3-load-hook)
  3171.   (setq w3-setup-done t))
  3172.  
  3173. (defun w3-mark-link-as-followed (ext dat)
  3174.   ;; Mark a link as followed, by removing the old extent EXT, and replacing
  3175.   ;; it with a new extent with the w3-visited-node-style face.
  3176.   (if (not w3-emacs19-hack-faces-p)
  3177.       (let ((st (w3-zone-start ext))
  3178.         (nd (w3-zone-end ext)))
  3179.     (w3-delete-zone ext)
  3180.     (w3-add-zone st nd w3-visited-node-style dat t)
  3181.     (if w3-delimit-links
  3182.         (progn
  3183. ;;;      (goto-char nd)
  3184. ;;;      (delete-region nd (- nd (length (car w3-link-end-delimiter))))
  3185. ;;;      (insert (cdr w3-link-end-delimiter))
  3186. ;;;      (goto-char st)
  3187. ;;;      (delete-region st (+ st (length (car w3-link-start-delimiter))))
  3188. ;;;      (insert (cdr w3-link-start-delimiter))
  3189.       )))))
  3190.  
  3191. (defun w3-download-url (url)
  3192.   (let ((url-be-asynchronous nil)
  3193.     (url-inhibit-uncompression t))
  3194.     (url-retrieve url)
  3195.     (if (get-buffer url-working-buffer)
  3196.     (w3-save-binary-file))))
  3197.  
  3198. ;;;###autoload
  3199. (defun w3-follow-link-other-frame (&optional p)
  3200.   "Attempt to follow the hypertext reference under point in a new frame.
  3201. With prefix-arg P, ignore viewers and dump the link straight
  3202. to disk."
  3203.   (cond
  3204.    ((and (fboundp 'make-frame)
  3205.      (fboundp 'select-frame))
  3206.     (let ((frm (make-frame)))
  3207.       (select-frame frm)
  3208.       (w3-follow-link p)))
  3209.    (t (w3-follow-link p))))
  3210.  
  3211. ;;;###autoload
  3212. (defun w3-follow-link (&optional p)
  3213.   "Attempt to follow the hypertext reference under point.
  3214. With prefix-arg P, ignore viewers and dump the link straight
  3215. to disk."
  3216.   (interactive "P")
  3217.   (let* ((ext (w3-zone-at (point)))
  3218.      (dat (and ext (w3-zone-data ext))))
  3219.     (cond
  3220.      ((null dat) (message "No link, form entry, or image at point."))
  3221.      ((and (or p w3-dump-to-disk) (eq (car dat) 'w3))
  3222.       (if (stringp (nth 2 dat))
  3223.       (w3-download-url (nth 2 dat))))
  3224.      ((eq (car dat) 'w3)
  3225.       (let ((buffer-read-only nil))
  3226.     (w3-mark-link-as-followed ext dat))
  3227.       (if (stringp (nth 2 dat)) (w3-fetch (nth 2 dat)) (message "No link.")))
  3228.      ((eq (car dat) 'w3form) (w3-do-form-entry dat ext))
  3229.      ((eq (car dat) 'w3graphic) (w3-fetch (nth 1 dat)))
  3230.      ((eq (car dat) 'w3expandlist) (w3-expand-list dat))
  3231.      ((eq (car dat) 'w3delayed)
  3232.       (apply 'w3-load-single-delayed-graphic
  3233.          (w3-zone-start ext) (w3-zone-end ext) (cdr dat))
  3234.       (w3-delete-zone ext))
  3235.      ((eq (car dat) 'w3mpeg)
  3236.       (apply 'w3-load-single-delayed-mpeg
  3237.          (w3-zone-start ext) (w3-zone-end ext) (cdr dat)))
  3238.      (t (message "Confused about what type of link is at point: %s" (car dat)))
  3239.      )))
  3240.  
  3241. (defun w3-complete-link ()
  3242.   "Choose a link from the current buffer and follow it"
  3243.   (interactive)
  3244.   (let (links-alist
  3245.     link-at-point
  3246.     choice
  3247.     (completion-ignore-case t))
  3248.     (setq link-at-point (w3-zone-at (point))
  3249.       link-at-point (and
  3250.              link-at-point
  3251.              (eq 'w3 (car-safe (w3-zone-data link-at-point)))
  3252.              (nth 2 (w3-zone-data link-at-point))
  3253.              (w3-fix-spaces
  3254.               (buffer-substring (w3-zone-start link-at-point)
  3255.                         (w3-zone-end link-at-point)))))
  3256.     (w3-map-links (function
  3257.            (lambda (data st nd arg)
  3258.              (if (and (nth 2 data)
  3259.                   (not (equal "" (nth 2 data))))
  3260.              (setq links-alist (cons
  3261.                         (cons
  3262.                          (w3-fix-spaces
  3263.                           (buffer-substring st nd))
  3264.                          (nth 2 data)) links-alist))))))
  3265.     (if (not links-alist) (error "No links in current document."))
  3266.     (setq links-alist (sort links-alist (function
  3267.                      (lambda (x y)
  3268.                        (string< (car x) (car y))))))
  3269.     ;; Destructively remove duplicate entries from links-alist.
  3270.     (let ((remaining-links links-alist))
  3271.       (while remaining-links
  3272.     (if (equal (car remaining-links) (car (cdr remaining-links)))
  3273.         (setcdr remaining-links (cdr (cdr remaining-links)))
  3274.       (setq remaining-links (cdr remaining-links)))))
  3275.     (setq choice (completing-read
  3276.           (if link-at-point
  3277.               (concat "Link (default "
  3278.                   (if (< (length link-at-point) 20)
  3279.                   link-at-point
  3280.                 (concat
  3281.                  (substring link-at-point 0 17) "..."))
  3282.                   "): ")
  3283.             "Link: ") links-alist nil t))
  3284.     (if (string= choice "")
  3285.     (w3-follow-link)
  3286.       (w3-fetch (cdr (assoc choice links-alist))))))
  3287.  
  3288. (defun w3-mode ()
  3289.   "Mode for viewing HTML documents.  If called interactively, will
  3290. display the current buffer as HTML.
  3291.  
  3292. Current keymap is:
  3293. \\{w3-mode-map}"
  3294.   (interactive)
  3295.   (or w3-setup-done (w3-do-setup))
  3296.   (if (interactive-p)
  3297.       (w3-preview-this-buffer)
  3298.     (let ((tmp (mapcar (function (lambda (x) (cons x (symbol-value x))))
  3299.                w3-persistent-variables)))
  3300.       (kill-all-local-variables)
  3301.       (use-local-map w3-mode-map)
  3302.       (setq major-mode 'w3-mode)
  3303.       (setq mode-name "WWW")
  3304.       (mapcar (function (lambda (x) (set-variable (car x) (cdr x)))) tmp)
  3305.       (run-hooks 'w3-mode-hook)
  3306.       (w3-mode-version-specifics)
  3307.       (setq url-current-passwd-count 0
  3308.         mode-line-format w3-modeline-format)
  3309.       (if (and w3-current-isindex (equal url-current-type "http"))
  3310.       (setq mode-line-process "-Searchable")))))
  3311.  
  3312. (require 'mm)
  3313. (require 'url)
  3314. (require 'w3-beta)
  3315. (require 'w3-parse)
  3316. (require 'w3-draw)
  3317. (require 'w3-style)
  3318. (require 'w3-print)
  3319. (require 'w3-about)
  3320. (require 'w3-hot)
  3321. (provide 'w3)
  3322.