;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Copyright (c) 1993 by William M. Perry (wmperry@indiana.edu)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; A lot of how this is done (especially the idea for the assoc list of
;;; file types and functions, came from Scott Snyder's (snyder@fnald0.fnal.gov)
;;; excellent gopher.el
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; First attempt at a gopher to html translator
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun w3-parse-gopher (&optional buff)
  "Parse a gopher listing in buffr BUFF into html.  BUFF defaults to ' *W3*'"
  (save-excursion
    (set-buffer (if buff buff " *W3*"))
    (goto-char (point-min))
    (w3-replace-regexp (regexp-quote "&") "&amp;")
    (w3-replace-regexp (regexp-quote ">") "&gt;")
    (w3-replace-regexp (regexp-quote "<") "&lt;")
    (goto-char (point-min))
    (insert "<OL>\n")
    (while (re-search-forward "^\\([^\\\t\\\n]*\\)\\\t\\([^\\\t\\\n]*\\)\\\t\\([^\\\t\\\n]*\\)\\\t\\([^\\\t\\\n]*\\).*$" nil t)
      (let ((title (buffer-substring (1+ (match-beginning 1)) (match-end 1)))
	    (type  (buffer-substring (match-beginning 1)
				     (1+ (match-beginning 1))))
	    (ref   (buffer-substring (match-beginning 2) (match-end 2)))
	    (serv  (buffer-substring (match-beginning 3) (match-end 3)))
	    (port  (buffer-substring (match-beginning 4) (match-end 4))))
	(replace-match "")
	(insert
	 (format "<LI> <A METHODS=%s HREF=\"gopher://%s:%s/%s\">%s</A>"
		 type serv port ref title))))
    (goto-char (point-max))
    (insert "</OL>\n")))

(defun w3-gopher-retrieve (host port type file)
  "Fetch a gopher object and don't mess with it at all"
  (let ((proc (w3-open-stream "*gopher*" " *W3*"
			      host (if (stringp port) (string-to-int port)
				     port)))
	(buff (current-buffer)))
    (w3-clear-tmp-buffer)
    (setq w3-current-type "gopher"
	  w3-current-port port
	  w3-current-server host
	  w3-current-file file
	  w3-current-last-buffer buff)
    (if (stringp proc)
	(message proc)
      (let ((tmp1 0) (tmp2 0))
	(process-send-string proc (format "%s%s\n" type file))
	(while (memq (process-status proc) '(run open))
	  (if (= 0 (setq tmp2 (% (1+ tmp2) 100)))
	      (message "Reading..%s" (make-string (setq tmp1 (% (1+ tmp1) 50))
						  ?.)))
	  (accept-process-output))
	(condition-case ()
	    (delete-process proc)
	  (error nil))
	(w3-replace-regexp (regexp-quote "\r") "")
	(w3-replace-regexp "^\\\.\\\n" "")
	(w3-replace-regexp "^\\\.\r*$\\\n*" "")
	(w3-replace-regexp "\\\n*Process .*gopher.*\\\n*" "")))))

(defun w3-do-gopher (host port type file &optional source searching)
  "Fetch a gopher object"
  (setq w3-source source)
  (if (not searching)
      (w3-gopher-retrieve host port type file))
  (if (equal type "") (setq type "1"))
  (if searching (setq type "1"))
  (let ((x (if searching 'w3-gopher-index-object
	     (car (cdr (cdr (assoc (string-to-char type)
				   w3-gopher-object-viewers)))))))
    (funcall x)))

(defun w3-gopher-doc ()
  "Handle a normal text document"
  (w3-pass-to-viewer))

(defun w3-gopher-dir ()
  "Handle a gopher directory"
  (setq w3-source source
	w3-doing-gopher t)
  (w3-sentinel nil nil))

(defun w3-gopher-index-object ()
  "Handle a search request in gopher"
  (let ((x (read-string "Enter search request: ")))
    (if (not (equal "" x))
	(w3-do-gopher host port type (format "%s\t%s" file x) source nil))))

(defun w3-gopher-binary-object (host port type file)
  "Retrieve a gopher object and save it to a file"
  (let ((fname (read-file-name "File to save in: ")))
    (w3-gopher-retrieve host port type file)
    (save-excursion
      (set-buffer " *W3*")
      (write-file fname))
    (kill-buffer " *W3*")))

(provide 'w3-gopher)
