2013-06-10 11:46:27 +00:00
|
|
|
;;; eww.el --- Emacs Web Wowser
|
|
|
|
|
|
|
|
;; Copyright (C) 2013 Free Software Foundation, Inc.
|
|
|
|
|
|
|
|
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
|
|
|
|
;; Keywords: html
|
|
|
|
|
|
|
|
;; This file is part of GNU Emacs.
|
|
|
|
|
|
|
|
;; GNU Emacs is free software: you can redistribute it and/or modify
|
|
|
|
;; it under the terms of the GNU General Public License as published by
|
|
|
|
;; the Free Software Foundation, either version 3 of the License, or
|
|
|
|
;; (at your option) any later version.
|
|
|
|
|
|
|
|
;; GNU Emacs is distributed in the hope that it will be useful,
|
|
|
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
;; GNU General Public License for more details.
|
|
|
|
|
|
|
|
;; You should have received a copy of the GNU General Public License
|
|
|
|
;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
;;; Commentary:
|
|
|
|
|
|
|
|
;;; Code:
|
|
|
|
|
|
|
|
(eval-when-compile (require 'cl))
|
|
|
|
(require 'shr)
|
|
|
|
(require 'url)
|
2013-06-10 14:11:01 +00:00
|
|
|
(require 'mm-url)
|
2013-06-10 11:46:27 +00:00
|
|
|
|
2013-06-16 22:20:55 +00:00
|
|
|
(defgroup eww nil
|
|
|
|
"Emacs Web Wowser"
|
|
|
|
:version "24.4"
|
|
|
|
:group 'hypermedia
|
|
|
|
:prefix "eww-")
|
|
|
|
|
|
|
|
(defcustom eww-header-line-format "%t: %u"
|
|
|
|
"Header line format.
|
|
|
|
- %t is replaced by the title.
|
|
|
|
- %u is replaced by the URL."
|
|
|
|
:group 'eww
|
|
|
|
:type 'string)
|
|
|
|
|
2013-06-10 11:46:27 +00:00
|
|
|
(defvar eww-current-url nil)
|
2013-06-16 22:20:55 +00:00
|
|
|
(defvar eww-current-title ""
|
|
|
|
"Title of current page.")
|
2013-06-10 11:46:27 +00:00
|
|
|
(defvar eww-history nil)
|
|
|
|
|
2013-06-11 03:09:59 +00:00
|
|
|
;;;###autoload
|
2013-06-10 11:46:27 +00:00
|
|
|
(defun eww (url)
|
|
|
|
"Fetch URL and render the page."
|
|
|
|
(interactive "sUrl: ")
|
2013-06-13 06:07:43 +00:00
|
|
|
(unless (string-match-p "\\`[a-zA-Z][-a-zA-Z0-9+.]*://" url)
|
|
|
|
(setq url (concat "http://" url)))
|
2013-06-10 11:46:27 +00:00
|
|
|
(url-retrieve url 'eww-render (list url)))
|
|
|
|
|
2013-06-13 06:07:43 +00:00
|
|
|
(defun eww-detect-charset (html-p)
|
|
|
|
(let ((case-fold-search t)
|
|
|
|
(pt (point)))
|
|
|
|
(or (and html-p
|
|
|
|
(re-search-forward
|
|
|
|
"<meta[\t\n\r ]+[^>]*charset=\\([^\t\n\r \"/>]+\\)" nil t)
|
|
|
|
(goto-char pt)
|
|
|
|
(match-string 1))
|
|
|
|
(and (looking-at
|
|
|
|
"[\t\n\r ]*<\\?xml[\t\n\r ]+[^>]*encoding=\"\\([^\"]+\\)")
|
|
|
|
(match-string 1)))))
|
|
|
|
|
2013-06-10 11:46:27 +00:00
|
|
|
(defun eww-render (status url &optional point)
|
2013-06-16 22:20:55 +00:00
|
|
|
(let ((redirect (plist-get status :redirect)))
|
|
|
|
(when redirect
|
|
|
|
(setq url redirect)))
|
2013-06-10 11:46:27 +00:00
|
|
|
(let* ((headers (eww-parse-headers))
|
2013-06-16 22:20:55 +00:00
|
|
|
(shr-target-id
|
|
|
|
(and (string-match "#\\(.*\\)" url)
|
|
|
|
(match-string 1 url)))
|
2013-06-10 11:46:27 +00:00
|
|
|
(content-type
|
|
|
|
(mail-header-parse-content-type
|
|
|
|
(or (cdr (assoc "content-type" headers))
|
|
|
|
"text/plain")))
|
|
|
|
(charset (intern
|
|
|
|
(downcase
|
|
|
|
(or (cdr (assq 'charset (cdr content-type)))
|
2013-06-13 06:07:43 +00:00
|
|
|
(eww-detect-charset (equal (car content-type)
|
|
|
|
"text/html"))
|
2013-06-10 11:46:27 +00:00
|
|
|
"utf8"))))
|
|
|
|
(data-buffer (current-buffer)))
|
|
|
|
(unwind-protect
|
|
|
|
(progn
|
|
|
|
(cond
|
|
|
|
((equal (car content-type) "text/html")
|
|
|
|
(eww-display-html charset url))
|
|
|
|
((string-match "^image/" (car content-type))
|
|
|
|
(eww-display-image))
|
|
|
|
(t
|
|
|
|
(eww-display-raw charset)))
|
2013-06-16 22:20:55 +00:00
|
|
|
(cond
|
|
|
|
(point
|
|
|
|
(goto-char point))
|
|
|
|
(shr-target-id
|
|
|
|
(let ((point (next-single-property-change
|
|
|
|
(point-min) 'shr-target-id)))
|
|
|
|
(when point
|
|
|
|
(goto-char (1+ point)))))))
|
2013-06-10 11:46:27 +00:00
|
|
|
(kill-buffer data-buffer))))
|
|
|
|
|
|
|
|
(defun eww-parse-headers ()
|
|
|
|
(let ((headers nil))
|
2013-06-13 06:07:43 +00:00
|
|
|
(goto-char (point-min))
|
2013-06-10 11:46:27 +00:00
|
|
|
(while (and (not (eobp))
|
|
|
|
(not (eolp)))
|
|
|
|
(when (looking-at "\\([^:]+\\): *\\(.*\\)")
|
|
|
|
(push (cons (downcase (match-string 1))
|
|
|
|
(match-string 2))
|
|
|
|
headers))
|
|
|
|
(forward-line 1))
|
|
|
|
(unless (eobp)
|
|
|
|
(forward-line 1))
|
|
|
|
headers))
|
|
|
|
|
|
|
|
(defun eww-display-html (charset url)
|
|
|
|
(unless (eq charset 'utf8)
|
|
|
|
(decode-coding-region (point) (point-max) charset))
|
|
|
|
(let ((document
|
|
|
|
(list
|
|
|
|
'base (list (cons 'href url))
|
|
|
|
(libxml-parse-html-region (point) (point-max)))))
|
|
|
|
(eww-setup-buffer)
|
|
|
|
(setq eww-current-url url)
|
2013-06-16 22:20:55 +00:00
|
|
|
(eww-update-header-line-format)
|
2013-06-10 14:11:01 +00:00
|
|
|
(let ((inhibit-read-only t)
|
2013-06-16 22:20:55 +00:00
|
|
|
(shr-width nil)
|
2013-06-10 14:11:01 +00:00
|
|
|
(shr-external-rendering-functions
|
2013-06-16 22:20:55 +00:00
|
|
|
'((title . eww-tag-title)
|
|
|
|
(form . eww-tag-form)
|
2013-06-10 14:11:01 +00:00
|
|
|
(input . eww-tag-input)
|
2013-06-16 22:20:55 +00:00
|
|
|
(textarea . eww-tag-textarea)
|
|
|
|
(body . eww-tag-body)
|
2013-06-12 01:38:23 +00:00
|
|
|
(select . eww-tag-select))))
|
2013-06-10 14:11:01 +00:00
|
|
|
(shr-insert-document document)
|
|
|
|
(eww-convert-widgets))
|
2013-06-10 11:46:27 +00:00
|
|
|
(goto-char (point-min))))
|
|
|
|
|
2013-06-16 22:20:55 +00:00
|
|
|
(defun eww-update-header-line-format ()
|
|
|
|
(if eww-header-line-format
|
|
|
|
(setq header-line-format (format-spec eww-header-line-format
|
|
|
|
`((?u . ,eww-current-url)
|
|
|
|
(?t . ,eww-current-title))))
|
|
|
|
(setq header-line-format nil)))
|
|
|
|
|
|
|
|
(defun eww-tag-title (cont)
|
|
|
|
(setq eww-current-title "")
|
|
|
|
(dolist (sub cont)
|
|
|
|
(when (eq (car sub) 'text)
|
|
|
|
(setq eww-current-title (concat eww-current-title (cdr sub)))))
|
|
|
|
(eww-update-header-line-format))
|
|
|
|
|
|
|
|
(defun eww-tag-body (cont)
|
|
|
|
(let* ((start (point))
|
|
|
|
(fgcolor (cdr (or (assq :fgcolor cont)
|
|
|
|
(assq :text cont))))
|
|
|
|
(bgcolor (cdr (assq :bgcolor cont)))
|
|
|
|
(shr-stylesheet (list (cons 'color fgcolor)
|
|
|
|
(cons 'background-color bgcolor))))
|
|
|
|
(shr-generic cont)
|
|
|
|
(eww-colorize-region start (point) fgcolor bgcolor)))
|
|
|
|
|
|
|
|
(defun eww-colorize-region (start end fg &optional bg)
|
|
|
|
(when (or fg bg)
|
|
|
|
(let ((new-colors (shr-color-check fg bg)))
|
|
|
|
(when new-colors
|
|
|
|
(when fg
|
|
|
|
(eww-put-color start end :foreground (cadr new-colors)))
|
|
|
|
(when bg
|
|
|
|
(eww-put-color start end :background (car new-colors)))))))
|
|
|
|
|
|
|
|
(defun eww-put-color (start end type color)
|
|
|
|
(shr-put-color-1 start end type color))
|
|
|
|
|
2013-06-10 11:46:27 +00:00
|
|
|
(defun eww-display-raw (charset)
|
|
|
|
(let ((data (buffer-substring (point) (point-max))))
|
|
|
|
(eww-setup-buffer)
|
|
|
|
(let ((inhibit-read-only t))
|
|
|
|
(insert data))
|
|
|
|
(goto-char (point-min))))
|
|
|
|
|
|
|
|
(defun eww-display-image ()
|
|
|
|
(let ((data (buffer-substring (point) (point-max))))
|
|
|
|
(eww-setup-buffer)
|
|
|
|
(let ((inhibit-read-only t))
|
|
|
|
(shr-put-image data nil))
|
|
|
|
(goto-char (point-min))))
|
|
|
|
|
|
|
|
(defun eww-setup-buffer ()
|
|
|
|
(pop-to-buffer (get-buffer-create "*eww*"))
|
2013-06-10 14:11:01 +00:00
|
|
|
(remove-overlays)
|
|
|
|
(setq widget-field-list nil)
|
2013-06-10 11:46:27 +00:00
|
|
|
(let ((inhibit-read-only t))
|
|
|
|
(erase-buffer))
|
|
|
|
(eww-mode))
|
|
|
|
|
|
|
|
(defvar eww-mode-map
|
|
|
|
(let ((map (make-sparse-keymap)))
|
|
|
|
(suppress-keymap map)
|
|
|
|
(define-key map "q" 'eww-quit)
|
2013-06-10 22:12:47 +00:00
|
|
|
(define-key map "g" 'eww-reload)
|
2013-06-10 11:46:27 +00:00
|
|
|
(define-key map [tab] 'widget-forward)
|
|
|
|
(define-key map [backtab] 'widget-backward)
|
|
|
|
(define-key map [delete] 'scroll-down-command)
|
|
|
|
(define-key map "\177" 'scroll-down-command)
|
|
|
|
(define-key map " " 'scroll-up-command)
|
|
|
|
(define-key map "p" 'eww-previous-url)
|
|
|
|
;;(define-key map "n" 'eww-next-url)
|
|
|
|
map))
|
|
|
|
|
2013-06-13 06:07:43 +00:00
|
|
|
(define-derived-mode eww-mode nil "eww"
|
2013-06-10 11:46:27 +00:00
|
|
|
"Mode for browsing the web.
|
|
|
|
|
|
|
|
\\{eww-mode-map}"
|
|
|
|
(set (make-local-variable 'eww-current-url) 'author)
|
2013-06-13 06:07:43 +00:00
|
|
|
(set (make-local-variable 'browse-url-browser-function) 'eww-browse-url))
|
2013-06-10 11:46:27 +00:00
|
|
|
|
|
|
|
(defun eww-browse-url (url &optional new-window)
|
2013-06-13 14:31:52 +00:00
|
|
|
(let ((url-request-extra-headers
|
|
|
|
(append '(("User-Agent" . "eww/1.0"))
|
|
|
|
url-request-extra-headers)))
|
|
|
|
(push (list eww-current-url (point))
|
|
|
|
eww-history)
|
|
|
|
(eww url)))
|
2013-06-10 11:46:27 +00:00
|
|
|
|
|
|
|
(defun eww-quit ()
|
|
|
|
"Exit the Emacs Web Wowser."
|
|
|
|
(interactive)
|
|
|
|
(setq eww-history nil)
|
|
|
|
(kill-buffer (current-buffer)))
|
|
|
|
|
|
|
|
(defun eww-previous-url ()
|
|
|
|
"Go to the previously displayed page."
|
|
|
|
(interactive)
|
|
|
|
(when (zerop (length eww-history))
|
|
|
|
(error "No previous page"))
|
|
|
|
(let ((prev (pop eww-history)))
|
|
|
|
(url-retrieve (car prev) 'eww-render (list (car prev) (cadr prev)))))
|
|
|
|
|
2013-06-10 22:12:47 +00:00
|
|
|
(defun eww-reload ()
|
|
|
|
"Reload the current page."
|
|
|
|
(interactive)
|
|
|
|
(url-retrieve eww-current-url 'eww-render
|
|
|
|
(list eww-current-url (point))))
|
|
|
|
|
2013-06-10 14:11:01 +00:00
|
|
|
;; Form support.
|
|
|
|
|
|
|
|
(defvar eww-form nil)
|
|
|
|
|
|
|
|
(defun eww-tag-form (cont)
|
|
|
|
(let ((eww-form
|
|
|
|
(list (assq :method cont)
|
|
|
|
(assq :action cont)))
|
|
|
|
(start (point)))
|
|
|
|
(shr-ensure-paragraph)
|
|
|
|
(shr-generic cont)
|
2013-06-14 03:22:26 +00:00
|
|
|
(unless (bolp)
|
|
|
|
(insert "\n"))
|
|
|
|
(insert "\n")
|
2013-06-10 22:28:35 +00:00
|
|
|
(when (> (point) start)
|
|
|
|
(put-text-property start (1+ start)
|
|
|
|
'eww-form eww-form))))
|
2013-06-10 14:11:01 +00:00
|
|
|
|
|
|
|
(defun eww-tag-input (cont)
|
2013-06-10 22:12:47 +00:00
|
|
|
(let* ((start (point))
|
|
|
|
(type (downcase (or (cdr (assq :type cont))
|
|
|
|
"text")))
|
|
|
|
(widget
|
|
|
|
(cond
|
|
|
|
((equal type "submit")
|
2013-06-14 11:16:26 +00:00
|
|
|
(list 'push-button
|
|
|
|
:notify 'eww-submit
|
|
|
|
:name (cdr (assq :name cont))
|
|
|
|
:value (cdr (assq :value cont))
|
|
|
|
:eww-form eww-form
|
|
|
|
(or (cdr (assq :value cont)) "Submit")))
|
2013-06-10 22:12:47 +00:00
|
|
|
((or (equal type "radio")
|
|
|
|
(equal type "checkbox"))
|
|
|
|
(list 'checkbox
|
|
|
|
:notify 'eww-click-radio
|
|
|
|
:name (cdr (assq :name cont))
|
|
|
|
:checkbox-value (cdr (assq :value cont))
|
2013-06-12 01:38:23 +00:00
|
|
|
:checkbox-type type
|
2013-06-10 22:12:47 +00:00
|
|
|
:eww-form eww-form
|
|
|
|
(cdr (assq :checked cont))))
|
|
|
|
((equal type "hidden")
|
|
|
|
(list 'hidden
|
|
|
|
:name (cdr (assq :name cont))
|
|
|
|
:value (cdr (assq :value cont))))
|
|
|
|
(t
|
2013-06-14 11:16:26 +00:00
|
|
|
(list 'editable-field
|
|
|
|
:size (string-to-number
|
|
|
|
(or (cdr (assq :size cont))
|
|
|
|
"40"))
|
|
|
|
:value (or (cdr (assq :value cont)) "")
|
|
|
|
:secret (and (equal type "password") ?*)
|
|
|
|
:action 'eww-submit
|
|
|
|
:name (cdr (assq :name cont))
|
|
|
|
:eww-form eww-form)))))
|
|
|
|
(nconc eww-form (list widget))
|
|
|
|
(unless (eq (car widget) 'hidden)
|
2013-06-14 03:22:26 +00:00
|
|
|
(apply 'widget-create widget)
|
|
|
|
(put-text-property start (point) 'eww-widget widget))))
|
2013-06-12 01:38:23 +00:00
|
|
|
|
2013-06-16 22:20:55 +00:00
|
|
|
(defun eww-tag-textarea (cont)
|
|
|
|
(let* ((start (point))
|
|
|
|
(widget
|
|
|
|
(list 'text
|
|
|
|
:size (string-to-number
|
|
|
|
(or (cdr (assq :cols cont))
|
|
|
|
"40"))
|
|
|
|
:value (or (cdr (assq 'text cont)) "")
|
|
|
|
:action 'eww-submit
|
|
|
|
:name (cdr (assq :name cont))
|
|
|
|
:eww-form eww-form)))
|
|
|
|
(nconc eww-form (list widget))
|
|
|
|
(apply 'widget-create widget)
|
|
|
|
(put-text-property start (point) 'eww-widget widget)))
|
|
|
|
|
2013-06-12 01:38:23 +00:00
|
|
|
(defun eww-tag-select (cont)
|
|
|
|
(shr-ensure-paragraph)
|
|
|
|
(let ((menu (list 'menu-choice
|
|
|
|
:name (cdr (assq :name cont))
|
|
|
|
:eww-form eww-form))
|
|
|
|
(options nil)
|
|
|
|
(start (point)))
|
|
|
|
(dolist (elem cont)
|
|
|
|
(when (eq (car elem) 'option)
|
|
|
|
(when (cdr (assq :selected (cdr elem)))
|
|
|
|
(nconc menu (list :value
|
|
|
|
(cdr (assq :value (cdr elem))))))
|
|
|
|
(push (list 'item
|
|
|
|
:value (cdr (assq :value (cdr elem)))
|
|
|
|
:tag (cdr (assq 'text (cdr elem))))
|
|
|
|
options)))
|
2013-06-13 14:31:52 +00:00
|
|
|
;; If we have no selected values, default to the first value.
|
|
|
|
(unless (plist-get (cdr menu) :value)
|
|
|
|
(nconc menu (list :value (nth 2 (car options)))))
|
2013-06-12 01:38:23 +00:00
|
|
|
(nconc menu options)
|
|
|
|
(apply 'widget-create menu)
|
|
|
|
(put-text-property start (point) 'eww-widget menu)
|
|
|
|
(shr-ensure-paragraph)))
|
2013-06-10 14:11:01 +00:00
|
|
|
|
2013-06-10 22:12:47 +00:00
|
|
|
(defun eww-click-radio (widget &rest ignore)
|
|
|
|
(let ((form (plist-get (cdr widget) :eww-form))
|
|
|
|
(name (plist-get (cdr widget) :name)))
|
2013-06-12 01:38:23 +00:00
|
|
|
(when (equal (plist-get (cdr widget) :type) "radio")
|
|
|
|
(if (widget-value widget)
|
|
|
|
;; Switch all the other radio buttons off.
|
|
|
|
(dolist (overlay (overlays-in (point-min) (point-max)))
|
|
|
|
(let ((field (plist-get (overlay-properties overlay) 'button)))
|
|
|
|
(when (and (eq (plist-get (cdr field) :eww-form) form)
|
|
|
|
(equal name (plist-get (cdr field) :name)))
|
|
|
|
(unless (eq field widget)
|
|
|
|
(widget-value-set field nil)))))
|
|
|
|
(widget-value-set widget t)))
|
2013-06-10 22:12:47 +00:00
|
|
|
(eww-fix-widget-keymap)))
|
|
|
|
|
|
|
|
(defun eww-submit (widget &rest ignore)
|
|
|
|
(let ((form (plist-get (cdr widget) :eww-form))
|
2013-06-10 14:11:01 +00:00
|
|
|
values)
|
2013-06-10 22:12:47 +00:00
|
|
|
(dolist (overlay (sort (overlays-in (point-min) (point-max))
|
|
|
|
(lambda (o1 o2)
|
|
|
|
(< (overlay-start o1) (overlay-start o2)))))
|
|
|
|
(let ((field (or (plist-get (overlay-properties overlay) 'field)
|
2013-06-14 11:16:26 +00:00
|
|
|
(plist-get (overlay-properties overlay) 'button))))
|
2013-06-10 22:12:47 +00:00
|
|
|
(when (eq (plist-get (cdr field) :eww-form) form)
|
|
|
|
(let ((name (plist-get (cdr field) :name)))
|
2013-06-10 14:11:01 +00:00
|
|
|
(when name
|
2013-06-10 22:12:47 +00:00
|
|
|
(cond
|
|
|
|
((eq (car field) 'checkbox)
|
|
|
|
(when (widget-value field)
|
|
|
|
(push (cons name (plist-get (cdr field) :checkbox-value))
|
|
|
|
values)))
|
|
|
|
((eq (car field) 'push-button)
|
|
|
|
;; We want the values from buttons if we hit a button,
|
2013-06-14 11:16:26 +00:00
|
|
|
;; if it's the first button in the DOM after the field
|
|
|
|
;; hit ENTER on.
|
|
|
|
(when (and (eq (car widget) 'push-button)
|
|
|
|
(eq widget field))
|
2013-06-10 22:12:47 +00:00
|
|
|
(push (cons name (widget-value field))
|
|
|
|
values)))
|
|
|
|
(t
|
|
|
|
(push (cons name (widget-value field))
|
|
|
|
values))))))))
|
|
|
|
(dolist (elem form)
|
|
|
|
(when (and (consp elem)
|
|
|
|
(eq (car elem) 'hidden))
|
|
|
|
(push (cons (plist-get (cdr elem) :name)
|
|
|
|
(plist-get (cdr elem) :value))
|
|
|
|
values)))
|
2013-06-14 11:16:26 +00:00
|
|
|
;; If we hit ENTER in a non-button field, include the value of the
|
|
|
|
;; first submit button after it.
|
|
|
|
(unless (eq (car widget) 'push-button)
|
|
|
|
(let ((rest form)
|
|
|
|
(name (plist-get (cdr widget) :name)))
|
|
|
|
(when rest
|
|
|
|
(while (and rest
|
|
|
|
(or (not (consp (car rest)))
|
|
|
|
(not (equal name (plist-get (cdar rest) :name)))))
|
|
|
|
(pop rest)))
|
|
|
|
(while rest
|
|
|
|
(let ((elem (pop rest)))
|
|
|
|
(when (and (consp (car rest))
|
|
|
|
(eq (car elem) 'push-button))
|
|
|
|
(push (cons (plist-get (cdr elem) :name)
|
|
|
|
(plist-get (cdr elem) :value))
|
|
|
|
values)
|
|
|
|
(setq rest nil))))))
|
2013-06-16 22:20:55 +00:00
|
|
|
(if (and (stringp (cdr (assq :method form)))
|
|
|
|
(equal (downcase (cdr (assq :method form))) "post"))
|
|
|
|
(let ((url-request-method "POST")
|
|
|
|
(url-request-extra-headers
|
|
|
|
'(("Content-Type" . "application/x-www-form-urlencoded")))
|
|
|
|
(url-request-data (mm-url-encode-www-form-urlencoded values)))
|
|
|
|
(eww-browse-url (shr-expand-url (cdr (assq :action form))
|
|
|
|
eww-current-url)))
|
|
|
|
(eww-browse-url
|
|
|
|
(concat
|
|
|
|
(if (cdr (assq :action form))
|
|
|
|
(shr-expand-url (cdr (assq :action form))
|
|
|
|
eww-current-url)
|
|
|
|
eww-current-url)
|
|
|
|
"?"
|
|
|
|
(mm-url-encode-www-form-urlencoded values))))))
|
2013-06-10 14:11:01 +00:00
|
|
|
|
|
|
|
(defun eww-convert-widgets ()
|
|
|
|
(let ((start (point-min))
|
|
|
|
widget)
|
2013-06-12 01:38:23 +00:00
|
|
|
;; Some widgets come from different buffers (rendered for tables),
|
|
|
|
;; so we need to nix out the list of widgets and recreate them.
|
|
|
|
(setq widget-field-list nil
|
|
|
|
widget-field-new nil)
|
2013-06-10 14:11:01 +00:00
|
|
|
(while (setq start (next-single-property-change start 'eww-widget))
|
|
|
|
(setq widget (get-text-property start 'eww-widget))
|
|
|
|
(goto-char start)
|
2013-06-10 22:12:47 +00:00
|
|
|
(let ((end (next-single-property-change start 'eww-widget)))
|
|
|
|
(dolist (overlay (overlays-in start end))
|
2013-06-12 01:38:23 +00:00
|
|
|
(when (or (plist-get (overlay-properties overlay) 'button)
|
|
|
|
(plist-get (overlay-properties overlay) 'field))
|
2013-06-10 22:12:47 +00:00
|
|
|
(delete-overlay overlay)))
|
|
|
|
(delete-region start end))
|
2013-06-14 03:22:26 +00:00
|
|
|
(when (and widget
|
|
|
|
(not (eq (car widget) 'hidden)))
|
|
|
|
(apply 'widget-create widget)))
|
2013-06-10 22:12:47 +00:00
|
|
|
(widget-setup)
|
|
|
|
(eww-fix-widget-keymap)))
|
|
|
|
|
|
|
|
(defun eww-fix-widget-keymap ()
|
|
|
|
(dolist (overlay (overlays-in (point-min) (point-max)))
|
|
|
|
(when (plist-get (overlay-properties overlay) 'button)
|
|
|
|
(overlay-put overlay 'local-map widget-keymap))))
|
2013-06-10 14:11:01 +00:00
|
|
|
|
2013-06-10 11:46:27 +00:00
|
|
|
(provide 'eww)
|
|
|
|
|
|
|
|
;;; eww.el ends here
|