[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Current status of backend patch
- From: Kiyokazu SUTO <suto@xxxxxxxxxxxxxxx>
- Date: 26 Mar 2001 01:32:59 +0900
- X-ml-name: emacs-w3m
- X-mail-count: 00364
- References: <010323223707.M0111732@apricot.d4.bsd.nes.nec.co.jp><20010325-031901-17a13.suto@ks-and-ks.ne.jp><20010326002244R.1000@pine.kuee.kyoto-u.ac.jp>
Citation (with leading "> " of each line) from article:
<20010326002244R.1000@pine.kuee.kyoto-u.ac.jp>
by TSUCHIYA Masatoshi <tsuchiya@pine.kuee.kyoto-u.ac.jp> :
> [*] 多言語化 w3m.
> 詳細については http://pub.ks-and-ks.ne.jp/prog/w3mmee/ を参照。
えーと「多言語化」とすると誤解を招きそうです。私がやっているのは可能な
限り沢山の文字の符号化を同時に扱えるようにするだけで、あまり「言語」を
扱っているという意識はないので。また「多言語化w3m」という場合は、坂本
氏の
Multilingualization of w3m (w3m-m17n):
http://www2u.biglobe.ne.jp/~hsaka/w3m/index.html
を指すことになっています。
> その最初の成果として、改良された backend patch が [w3m-dev 01827] に投
バタバタして申し訳無いですが、早速バグフィックスパッチを2個投稿してい
ます。…などと言っているうちに、showProgress中の端末の有無のチェックが
甘くてsegmentation faultするというバグが発覚したので^^;、これからまた
修正します。
> ## このパッチって、どの枝の差分なんでしょう? > 須藤さん
オリジナル用の枝はw3m-0_2です。オリジナルそのものにはw3m-0_2_1というタ
グが振ってあります。
> (1) head / get コマンドで redirect 先の実際の URI が表示されるようにし
> て欲しい。
>
> ex) http://www-nagao.kuee.kyoto-u.ac.jp/member/tsuchiya/emacs-w3m/
> -> http://namazu.org/~tsuchiya/emacs-w3m/
擬似(?)ヘッダとして
w3m-current-url: http://namazu.org/~tsuchiya/emacs-w3m/
のように出力する、というのでよろしいでしょうか。
> (2) <select> タグを処理できないでしょうか。例えば、以下のような HTML
> を -halfdump すると、
selectの候補はform_list構造体の中に記録されているのでhalfdump imageを
作る途中で出力するのは難しそうです。最後のtitleの後に出力される_formの
中で
<_form fid=… option_label=… option_value=… …>
という形で出力する、というのでは如何ですか。
ところで前に書いたbackend版w3m.elですが、↓に添付しますので何かに使っ
ていただけるとありがたいです。非同期にbackend modeのw3mと通信する部分
だけで、まったくテストしていないので申し訳無いんですが。
--
須藤 清一 <suto@ks-and-ks.ne.jp>
http://pub.ks-and-ks.ne.jp/pgp-public-key.html
;;; Handle process asynchronously
(defconst w3m-backend-process-name "w3m-backend")
(defconst w3m-backend-prompt-regex "^w3m>\s *\\'")
(defconst w3m-backend-buffer-name " *w3m-backend*")
(defvar w3m-backend-request-head nil)
(defvar w3m-backend-request-tail nil)
(defvar w3m-backend-result-beginning (make-marker))
(defvar w3m-backend-result-nextline (make-marker))
(defvar w3m-backend-result-length nil)
(defvar w3m-backend-input-prompt nil)
(defvar w3m-backend-input-default nil)
(defvar w3m-backend-status 'dead)
(defvar w3m-backend-receiver nil)
(defvar w3m-backend-url nil)
(defvar w3m-backend-sync-box nil)
(defvar w3m-backend-result-hook nil)
(make-variable-buffer-local 'w3m-backend-result-hook)
(defun w3m-backend-arg-to-string (arg)
(if (stringp arg)
arg
(print1-to-string (eval arg))))
(defun w3m-backend-start-process (&rest requests)
"Start w3m-command in backend mode."
(save-excursion
(set-buffer (w3m-get-buffer-create w3m-backend-buffer-name))
(erase-buffer)
(setq w3m-backend-request-head nil
w3m-backend-request-tail nil
w3m-backend-status nil
w3m-backend-receiver nil)
(let* ((coding-system-for-read 'binary)
(coding-system-for-write w3m-coding-system)
(default-process-coding-system (cons 'binary w3m-coding-system))
(process-connection-type w3m-process-connection-type)
(proc (apply (function start-process)
w3m-backend-process-name
(current-buffer)
w3m-command
(mapcar (function w3m-backend-arg-to-string) w3m-backend-arguments))))
(if proc
(progn (set-process-filter proc (function w3m-backend-filter))
(set-process-sentinel proc (function w3m-backend-sentinel))
(apply (function w3m-backend-process-request) proc (current-buffer) requests)))
proc)))
(defun w3m-backend-process-send-string (proc req)
(let ((b (point-max)) e)
(goto-char b)
(insert req)
(setq e (point))
(if (< b e)
(progn (backward-char)
(if (char-equal (char-after (point)) ?\n)
(progn (goto-char e) (insert "\n"))
(goto-char e)))
(insert "\n"))
(setq w3m-backend-status 'head
w3m-backend-input-prompt nil
w3m-backend-input-default nil
w3m-backend-result-length 0)
(process-send-region proc b (point))
(move-marker w3m-backend-result-nextline (point))
(move-marker w3m-backend-result-beginning (point))))
(defun w3m-backend-process-request (proc buf &rest requests)
(cond ((and (not proc) (eq w3m-backend-status 'dead))
(apply (function w3m-backend-start-process) requests))
((and (or proc
(setq proc (get-process w3m-backend-process-name)))
(or buf
(setq buf (process-buffer proc))))
(let (req)
(while requests
(setq req (list (car requests))
requests (cdr requests))
(if w3m-backend-request-tail
(progn (setcdr w3m-backend-request-tail req)
(setq w3m-backend-request-tail req))
(setq w3m-backend-request-head req
w3m-backend-request-tail req)))
(unless w3m-backend-sync-box
(save-excursion
(set-buffer buf)
(goto-char (point-max))
(if (and w3m-backend-request-head
(not w3m-backend-status)
(re-search-backward w3m-backend-prompt-regex (point-min) t))
(progn (setq req (car w3m-backend-request-head)
w3m-backend-request-head (cdr w3m-backend-request-head))
(unless w3m-backend-request-head
(setq w3m-backend-request-tail nil))
(setq w3m-backend-receiver (nth 0 req)
w3m-backend-url (nth 1 req)
req (nth 2 req))
(cond ((stringp req)
(w3m-backend-process-send-string proc req))
((and req (listp req))
(w3m-backend-process-send-string
proc
(apply (function concat)
(w3m-backend-arg-to-string (car req))
(mapcar
(function (lambda (arg) (concat " " (w3m-backend-arg-to-string arg))))
(cdr req)))))
((functionp req) (funcall req proc buf)))))))))))
(defun w3m-backend-process-sync-request (proc buf url req)
(and (or proc
(setq proc (if (eq w3m-backend-status 'dead)
(funcall (function w3m-backend-start-process))
(get-process w3m-backend-process-name))))
(let ((box (list)))
(w3m-backend-process-request
proc buf
(list (` (lambda (b e)
(setcdr (quote (, box)) (list b e))
(setcar (quote (, box)) (current-buffer))
(setq w3m-backend-sync-box (quote (, box)))))
url seq))
(while (and (eq (process-status proc) 'run) (not (eq w3m-backend-sync-box box)))
(accept-process-output proc))
(setq w3m-backend-sync-box nil)
box)))
(defun w3m-backend-filter (proc str)
(if (buffer-name (process-buffer proc))
(with-current-buffer (process-buffer proc)
(let ((buffer-read-only nil)
(case-fold-search nil))
(goto-char (process-mark process))
(insert str)
(cond ((eq w3m-backend-status 'head)
(let ((continuep (string< "" str)))
(while continuep
(goto-char (marker-position w3m-backend-result-nextline))
(cond ((looking-at "w3m-content-length:[ \t]*\\([0-9]+\\).*\n")
(setq w3m-backend-result-length
(string-to-number
(buffer-substring (match-beginning 1) (match-end 1))))
(move-marker w3m-backend-result-nextline (match-end 0)))
((looking-at "w3m-urgent-messages:[ \t]*\\(.*\\)\n")
(w3m-message (buffer-substring (match-beginning 1) (match-end 1)))
(delete-region (match-beginning 0) (match-end 0)))
((looking-at "w3m-input-prompt:[ \t]*\\(.*\\)\n")
(setq w3m-backend-input-prompt (buffer-substring (match-beginning 1) (match-end 1)))
(delete-region (match-beginning 0) (match-end 0)))
((looking-at "w3m-input-default:[ \t]*\\(.*\\)\n")
(setq w3m-backend-input-default (buffer-substring (match-beginning 1) (match-end 1)))
(delete-region (match-beginning 0) (match-end 0)))
((looking-at "w3m>.*\\'")
(if w3m-backend-input-prompt
(progn (delete-region (match-beginning 0) (match-end 0))
(cond ((string-match "\\<Password:" w3m-backend-input-prompt)
(setq w3m-process-passwd
(or (nth 1 (w3m-exec-get-user w3m-backend-url))
(read-passwd w3m-backend-input-prompt)))
(condition-case nil
(process-send-string proc (concat w3m-process-passwd "\n"))
(error nil)))
((string-match "\\<Username:" w3m-backend-input-prompt)
(setq w3m-process-user
(or (nth 0 (w3m-exec-get-user w3m-backend-url))
(read-from-minibuffer w3m-backend-input-prompt w3m-backend-input-default)))
(condition-case nil
(process-send-string proc (concat w3m-process-user "\n"))
(error nil)))
((string< "" w3m-backend-input-prompt)
(condition-case nil
(process-send-string
proc
(concat
(read-from-minibuffer w3m-backend-input-prompt w3m-backend-input-default)
"\n"))
(error nil)))
(t
(setq w3m-backend-status nil
continuep nil)
(w3m-backend-process-request proc nil))))
(w3m-backend-call-receiver (match-beginning 0))))
((looking-at "\\(.*\\)\n")
(move-marker w3m-backend-result-nextline (match-end 0))
(if (= (match-beginning 1) (match-end 1))
(setq w3m-backend-status 'body)))
(t (setq continuep nil))))))
((eq w3m-backend-status 'body)
(if (>= (- (point) (marker-position w3m-backend-result-nextline)) w3m-backend-result-length)
(w3m-backend-call-receiver
(+ (marker-position w3m-backend-result-nextline) w3m-backend-result-length)))))))))
(defun w3m-backend-call-receiver (e)
(let ((b (marker-position w3m-backend-result-beginning)))
(cond ((bufferp w3m-backend-receiver)
(let ((cur (current-buffer)) hb he)
(set-buffer w3m-backend-receiver)
(setq hb (point))
(insert-buffer-substring cur b e)
(if (functionp w3m-backend-result-hook)
(funcall w3m-backend-result-hook hb (point)))
(set-buffer cur)))
((functionp w3m-backend-receiver)
(funcall w3m-backend-receiver b e)))
(setq w3m-backend-status nil)
(delete-region (point-min) e)))
(defun w3m-backend-sentinel (proc event)
(if (string-match "^finished\\|^exited" event)
(setq w3m-backend-status 'dead)))
;;; Retrieve data via HTTP:
(defun w3m-async-cache-contents (url buffer &optional beg end)
"Store URL's contents which is placed in the BUFFER.
Return symbol to identify its cache data."
(w3m-cache-setup)
(let ((ident (intern url w3m-cache-hashtb)))
(w3m-cache-remove url)
;; Remove the oldest article, if necessary.
(and (numberp w3m-keep-cache-size)
(>= (length w3m-cache-articles) w3m-keep-cache-size)
(w3m-cache-remove-oldest))
;; Insert the new article.
(or (and beg end)
(save-excursion
(set-buffer buffer)
(or beg (setq beg (point-min)))
(or end (setq end (point-max)))))
(save-excursion
(set-buffer w3m-cache-buffer)
(let (buffer-read-only)
(goto-char (point-max))
(unless (bolp) (insert "\n"))
(let ((b (point)))
(insert-buffer-substring buffer beg end)
;; Tag the beginning of the article with the ident.
(when (> (point-max) b)
(put-text-property b (1+ b) 'w3m-cache ident)
(setq w3m-cache-articles (cons ident w3m-cache-articles))
ident))))))
(defun w3m-async-cache-request-contents (url &optional buffer)
"Insert URL's data to the BUFFER if BUFFER is a buffer,
or passed to BUFFER if BUFFER is a function.
If URL's data is found in the cache, return t. Otherwise return nil.
When BUFFER is nil, all data will be inserted in the current buffer."
(w3m-cache-setup)
(let ((ident (intern url w3m-cache-hashtb)))
(when (memq ident w3m-cache-articles)
;; It was in the cache.
(let (beg end type charset)
(save-excursion
(set-buffer w3m-cache-buffer)
(if (setq beg (text-property-any
(point-min) (point-max) 'w3m-cache ident))
;; Find the end (i. e., the beginning of the next article).
(setq end (next-single-property-change
(1+ beg) 'w3m-cache (current-buffer) (point-max)))
;; It wasn't in the cache after all.
(setq w3m-cache-articles (delq ident w3m-cache-articles))))
(and beg
end
(save-excursion
(let (buffer-read-only)
(cond ((functionp buffer)
(funcall buffer w3m-cache-buffer beg end))
((buffep buffer)
(set-buffer buffer)
(insert-buffer-substring w3m-cache-buffer beg end))
(t
(insert-buffer-substring w3m-cache-buffer beg end))))
t))))))
(defun w3m-w3m-async-attributes-internal (cbuf cb ce)
(let (type charset len enc time id)
(save-excursion
(set-buffer cbuf)
(goto-char cb)
(let ((continuep t) name)
(while (and continuep (< (point) ce))
(cond ((char-equal (char-after) ?\n) (setq continuep nil))
((looking-at "\\([^:\n]+\\):[ \t] *\\(.*\\)\n")
(setq name (intern-soft (downcase (buffer-substring (match-beginning 1) (match-end 1)))))
(cond ((eq name 'w3m-content-type)
(setq type (buffer-substring (match-beginning 2) (match-end 2))))
((eq name 'w3m-content-charset)
(setq charset (buffer-substring (match-beginning 2) (match-end 2))))
((eq name 'w3m-content-length)
(setq len (string-to-number (buffer-substring (match-beginning 2) (match-end 2)))))
((eq name 'content-encoding)
(setq enc (buffer-substring (match-beginning 2) (match-end 2))))
((eq name 'last-modified)
(setq time (apply (function encode-time)
(w3m-time-parse-string (buffer-substring (match-beginning 2) (match-end 2))))))
((eq name 'w3m-buffer-id)
(setq id (buffer-substring (match-beginning 2) (match-end 2)))))
(goto-char (match-end 0)))
(t (re-search-forward "\n" ce 1))))
(list type charset len enc time id)))))
(defun w3m-w3m-async-attributes (receiver url &optional no-cache)
"Pass url and a list of attributes of URL to RECEIVER.
The list is nil if retirieval of header is failed. Otherwise,
list elements are:
0. Type of contents.
1. Charset of contents.
2. Size in bytes.
3. Encoding of contents.
4. Last modification time.
5. Identifier in w3m of buffer.
If optional argument NO-CACHE is non-nil, cache is not used."
(or (and (not no-cache)
(w3m-cache-request-contents
url
(` (lambda (cbuf cb ce)
(funcall (function (, receiver))
(quote (, url))
(w3m-w3m-async-attributes-internal cbuf cb ce))))))
(w3m-backend-process-request
nil nil
(` (lambda (b e)
(w3m-cache-contents (quote (, url)) (current-buffer) b e)
(funcall (function (, receiver))
(quote (, url))
(w3m-w3m-async-attributes-internal (current-buffer) b e)))
(, url)
(, (concat "get " url))))))
(defun w3m-w3m-async-retrieve-internal (receiver url no-decode buf b e)
(let* ((headers (w3m-w3m-async-attributes-internal buf b e))
(type (car headers))
(charset (nth 1 headers))
(length (nth 2 headers))
(bob (save-excursion
(set-buffer buf)
(goto-char b)
(re-search-forward "^\n" e 1)
(point))))
(w3m-with-work-buffer
(delete-region (point-min) (point-max))
(set-buffer-multibyte nil)
(insert-buffer-substring buf bob e)
(when (string= "text/html" type)
;; Remove cookies.
(goto-char (point-min))
(while (and (not (eobp))
(looking-at "Received cookie: "))
(forward-line 1))
(skip-chars-forward " \t\r\f\n")
(if (or (looking-at "<!DOCTYPE")
(looking-at "<HTML>")) ; for eGroups.
(delete-region (point-min) (point))))
(and (string-match "^text/" type)
(not no-decode)
(w3m-decode-buffer type charset))
(funcall receiver type))))
(defun w3m-w3m-async-retrieve (receiver url &optional no-decode no-cache)
"Retrieve content of URL with w3m, insert it to the working buffer,
and then call RECEIVER with content-type of URL as string. If NO-DECODE,
set the multibyte flag of the working buffer to nil."
(or (and (not no-cache)
(w3m-cache-request-contents
url
(` (lambda (cbuf cb ce)
(w3m-w3m-async-retrieve-internal
(function (, receiver)) (quote (, url)) (quote (, no-decode))
cbuf cb ce)))))
(w3m-backend-process-request
nil nil
(` (lambda (b e)
(w3m-cache-contents (quote (, url)) (current-buffer) b e)
(w3m-w3m-async-retrieve-internal
(function (, receiver)) (quote (, url)) (quote (, no-decode))
(current-buffer) b e))
(, url)
(, (concat "get " url))))))
(defun w3m-async-retrieve (receiver url &optional no-decode no-cache)
"Retrieve content of URL and insert it to the working buffer.
This function will pass content-type of URL as string to RECEIVER
when retrieval succeed. If NO-DECODE, set the multibyte flag of
the working buffer to nil."
(cond
((string-match "^about:" url)
(let (func)
(if (and (string-match "^about://\\([^/]+\\)/" url)
(setq func (intern-soft
(concat "w3m-about-" (match-string 1 url))))
(fboundp func))
(funcall func receiver url no-decode no-cache)
(w3m-about receiver url no-decode no-cache))))
((string-match "^cid:" url)
(let ((func (cdr (assq major-mode w3m-cid-retrieve-function-alist))))
(when func
(funcall func receiver url no-decode no-cache))))
(t
(w3m-w3m-async-retrieve receiver url no-decode no-cache))))
(defun w3m-async-download-internal (type url filename)
(if type
(let ((buffer-file-coding-system 'binary)
(file-coding-system 'binary)
(coding-system-for-write 'binary)
jka-compr-compression-info-list
jam-zcat-filename-list
format-alist)
(if (or (not (file-exists-p filename))
(y-or-n-p (format "File(%s) is already exists. Overwrite? " filename)))
(write-region (point-min) (point-max) filename)))
(error "Unknown URL: %s" url)))
(defun w3m-async-download (url &optional filename no-cache)
(unless filename
(setq filename (w3m-read-file-name nil nil url)))
(w3m-async-retrieve
(` (lambda (type) (w3m-download-internal type (quote (, url)) (quote (, filename)))))
t no-cache))
(defun w3m-async-attributes (receiver url &optional no-cache)
"Pass a list of attributes of URL to RECEIVER.
Value is nil if retirieval of header is failed. Otherwise, list
elements are:
0. Type of contents.
1. Charset of contents.
2. Size in bytes.
3. Encoding of contents.
4. Last modification time.
5. Identifier of buffer in w3m.
If optional argument NO-CACHE is non-nil, cache is not used."
(cond
((string-match "^about:" url)
(funcall receiver (list "text/html" nil nil nil nil)))
(t
(w3m-w3m-async-attributes receiver url no-cache))))
(provide 'w3m-async)