(find-function-on-key): Fix previous
[bpt/emacs.git] / lisp / browse-url.el
CommitLineData
5db57514 1;;; browse-url.el --- Pass a URL to a WWW browser
b578f267 2
a43d1a2a 3;; Copyright 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
a69315a1
RS
4
5;; Author: Denis Howe <dbh@doc.ic.ac.uk>
a43d1a2a 6;; Maintainer: Dave Love <fx@gnu.org>
a69315a1 7;; Created: 03 Apr 1995
5db57514 8;; Keywords: hypertext, hypermedia, mouse
a69315a1
RS
9
10;; This file is part of GNU Emacs.
11
12;; GNU Emacs is free software; you can redistribute it and/or modify
b578f267
EN
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.
a69315a1 16
b578f267
EN
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.
a69315a1
RS
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 the
b578f267
EN
24;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25;; Boston, MA 02111-1307, USA.
a69315a1 26
a69315a1
RS
27;;; Commentary:
28
a69315a1
RS
29;; This package provides functions which read a URL (Uniform Resource
30;; Locator) from the minibuffer, defaulting to the URL around point,
31;; and ask a World-Wide Web browser to load it. It can also load the
32;; URL associated with the current buffer. Different browsers use
33;; different methods of remote control so there is one function for
34;; each supported browser. If the chosen browser is not running, it
35;; is started. Currently there is support for:
36
37;; Function Browser Earliest version
a43d1a2a 38;; browse-url-netscape Netscape 1.1b1
837984b1 39;; browse-url-mosaic XMosaic/mMosaic <= 2.4
a69315a1
RS
40;; browse-url-cci XMosaic 2.5
41;; browse-url-w3 w3 0
5db57514 42;; browse-url-w3-gnudoit w3 remotely
a69315a1 43;; browse-url-iximosaic IXI Mosaic ?
96adeb99
RS
44;; browse-url-lynx-* Lynx 0
45;; browse-url-grail Grail 0.3b1
5db57514
RS
46;; browse-url-mmm MMM ?
47;; browse-url-generic arbitrary
a69315a1 48
9d843bef
DL
49;; [The Netscape browser is now free software
50;; <URL:http://www.mozilla.org/>, albeit not GPLed, so it is
51;; reasonable to keep it as the default.]
52
a69315a1 53;; Note that versions of Netscape before 1.1b1 did not have remote
5db57514 54;; control. <URL:http://www.netscape.com/newsref/std/x-remote.html>.
a69315a1 55
9d843bef 56;; Browsers can cache Web pages so it may be necessary to tell them to
96adeb99 57;; reload the current page if it has changed (e.g. if you have edited
a69315a1
RS
58;; it). There is currently no perfect automatic solution to this.
59
60;; Netscape allows you to specify the id of the window you want to
61;; control but which window DO you want to control and how do you
62;; discover its id?
63
64;; If using XMosaic before version 2.5, check the definition of
65;; browse-url-usr1-signal below.
66;; <URL:http://www.ncsa.uiuc.edu/SDG/Software/XMosaic/remote-control.html>
67
68;; XMosaic version 2.5 introduced Common Client Interface allowing you
69;; to control mosaic through Unix sockets.
70;; <URL:http://www.ncsa.uiuc.edu/SDG/Software/XMosaic/CCI/cci-spec.html>
71
72;; William M. Perry's excellent "w3" WWW browser for
73;; Emacs <URL:ftp://cs.indiana.edu/pub/elisp/w3/>
74;; has a function w3-follow-url-at-point, but that
75;; doesn't let you edit the URL like browse-url.
5db57514
RS
76;; The `gnuserv' package that can be used to control it in another
77;; Emacs process is available from
a43d1a2a 78;; <URL:ftp://ftp.splode.com/pub/users/friedman/packages/>.
5db57514
RS
79
80;; Grail is the freely available WWW browser implemented in Python, a
81;; cool object-oriented freely available interpreted language. Grail
82;; 0.3b1 was the first version to have remote control as distributed.
83;; For more information on Grail see
84;; <URL:http://grail.cnri.reston.va.us/> and for more information on
85;; Python see <url:http://www.python.org/>. Grail support in
86;; browse-url.el written by Barry Warsaw <bwarsaw@python.org>.
87
a43d1a2a
DL
88;; MMM is the freely available WWW browser implemented in Objective
89;; Caml, a cool impure functional programming language, by Francois
5db57514
RS
90;; Rouaix. See the MMM home page
91;; <URL:http://pauillac.inria.fr/%7Erouaix/mmm/>.
92
93;; Lynx is now distributed by the FSF. See also
94;; <URL:http://lynx.browser.org/>.
95
96;; Free graphical browsers that could be used by `browse-url-generic'
bc6d0d71
RS
97;; include Chimera <URL:ftp://ftp.cs.unlv.edu/pub/chimera> and
98;; <URL:http://www.unlv.edu/chimera/>, Arena
837984b1
DL
99;; <URL:ftp://ftp.yggdrasil.com/pub/dist/web/arena> and Amaya
100;; <URL:ftp://ftp.w3.org/pub/amaya>. mMosaic
101;; <URL:ftp://sig.enst.fr/pub/multicast/mMosaic/> (with development
102;; support for Java applets and multicast) can be used like Mosaic by
103;; setting `browse-url-mosaic-program' appropriately.
a69315a1 104
9d843bef
DL
105;; I [Denis Howe, not Dave Love] recommend Nelson Minar
106;; <nelson@santafe.edu>'s excellent html-helper-mode.el for editing
107;; HTML and thank Nelson for his many useful comments on this code.
5db57514 108;; <URL:http://www.santafe.edu/%7Enelson/hhm-beta/>
a69315a1 109
59966fb6
RS
110;; See also hm--html-menus <URL:http://www.tnt.uni-hannover.de/%7Emuenkel/
111;; software/own/hm--html-menus/>. For composing correct HTML see also
112;; PSGML the general SGML structure editor package
113;; <URL:ftp://ftp.lysator.liu.se/pub/sgml>; hm--html-menus can be used
114;; with this.
115
a69315a1 116;; This package generalises function html-previewer-process in Marc
a43d1a2a
DL
117;; Andreessen's html-mode (LCD modes/html-mode.el.Z). See also the
118;; ffap.el package. The huge hyperbole package also contains similar
119;; functions.
a69315a1
RS
120
121;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
122;; Help!
123
124;; Can you write and test some code for the Macintrash and Windoze
125;; Netscape remote control APIs? (See the URL above).
126
127;; Do any other browsers have remote control?
128
a69315a1
RS
129;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
130;; Usage
131
132;; To display the URL at or before point:
133;; M-x browse-url-at-point RET
5db57514
RS
134;; or, similarly but with the opportunity to edit the URL extracted from
135;; the buffer, use:
136;; M-x browse-url
a69315a1
RS
137
138;; To display a URL by shift-clicking on it, put this in your ~/.emacs
139;; file:
a5f6b207
RS
140;; (global-set-key [S-mouse-2] 'browse-url-at-mouse)
141;; (Note that using Shift-mouse-1 is not desirable because
142;; that event has a standard meaning in Emacs.)
a69315a1
RS
143
144;; To display the current buffer in a web browser:
145;; M-x browse-url-of-buffer RET
146
5db57514
RS
147;; To display the current region in a web browser:
148;; M-x browse-url-of-region RET
149
a69315a1
RS
150;; In Dired, to display the file named on the current line:
151;; M-x browse-url-of-dired-file RET
152
153;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
154;; Customisation (~/.emacs)
155
96adeb99 156;; To see what variables are available for customization, type
09d8b0bc
DL
157;; `M-x set-variable browse-url TAB'. Better, use
158;; `M-x customize-group browse-url'.
a69315a1 159
96adeb99
RS
160;; Bind the browse-url commands to keys with the `C-c C-z' prefix
161;; (as used by html-helper-mode):
162;; (global-set-key "\C-c\C-z." 'browse-url-at-point)
163;; (global-set-key "\C-c\C-zb" 'browse-url-of-buffer)
5db57514 164;; (global-set-key "\C-c\C-zr" 'browse-url-of-region)
96adeb99
RS
165;; (global-set-key "\C-c\C-zu" 'browse-url)
166;; (global-set-key "\C-c\C-zv" 'browse-url-of-file)
5db57514 167;; (add-hook 'dired-mode-hook
e49172c8
DL
168;; (lambda ()
169;; (local-set-key "\C-c\C-zf" 'browse-url-of-dired-file)))
96adeb99
RS
170
171;; Browse URLs in mail messages by clicking mouse-2:
e49172c8
DL
172;; (add-hook 'rmail-mode-hook (lambda () ; rmail-mode startup
173;; (define-key rmail-mode-map [mouse-2] 'browse-url-at-mouse)))
96adeb99
RS
174
175;; Browse URLs in Usenet messages by clicking mouse-2:
176;; (eval-after-load "gnus"
177;; '(define-key gnus-article-mode-map [mouse-2] 'browse-url-at-mouse))
59966fb6
RS
178;; [The current version of Gnus provides a standard feature to
179;; activate URLs in article buffers for invocation of browse-url with
180;; mouse-2.]
96adeb99
RS
181
182;; Use the Emacs w3 browser when not running under X11:
183;; (or (eq window-system 'x)
5db57514 184;; (setq browse-url-browser-function 'browse-url-w3))
a69315a1
RS
185
186;; To always save modified buffers before displaying the file in a browser:
5db57514 187;; (setq browse-url-save-file t)
a69315a1 188
96adeb99
RS
189;; To get round the Netscape caching problem, you could EITHER have
190;; write-file in html-helper-mode make Netscape reload the document:
a69315a1 191;;
5db57514
RS
192;; (autoload 'browse-url-netscape-reload "browse-url"
193;; "Ask a WWW browser to redisplay the current file." t)
194;; (add-hook 'html-helper-mode-hook
e49172c8 195;; (lambda ()
5db57514 196;; (add-hook 'local-write-file-hooks
e49172c8 197;; (lambda ()
5db57514
RS
198;; (let ((local-write-file-hooks))
199;; (save-buffer))
200;; (browse-url-netscape-reload)
e49172c8
DL
201;; t) ; => file written by hook
202;; t))) ; append to l-w-f-hooks
a69315a1 203;;
96adeb99 204;; OR have browse-url-of-file ask Netscape to load and then reload the
a69315a1
RS
205;; file:
206;;
5db57514 207;; (add-hook 'browse-url-of-file-hook 'browse-url-netscape-reload)
a69315a1 208
96adeb99 209;; You may also want to customise browse-url-netscape-arguments, e.g.
5db57514 210;; (setq browse-url-netscape-arguments '("-install"))
a69315a1 211;;
5db57514 212;; or similarly for the other browsers.
a69315a1 213
5db57514
RS
214;; To invoke different browsers for different URLs:
215;; (setq browse-url-browser-function '(("^mailto:" . browse-url-mail)
216;; ("." . browse-url-netscape)))
a69315a1
RS
217
218;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
219;;; Code:
220
5db57514
RS
221;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
222;; Variables
a69315a1 223
380a0a12 224(eval-when-compile (require 'thingatpt)
e61d8515
DL
225 (require 'term)
226 (require 'w3-auto nil t))
a43d1a2a 227
0a3fc8a2
RS
228(defgroup browse-url nil
229 "Use a web browser to look at a URL."
09d8b0bc 230 :prefix "browse-url-"
f6680f0b 231 :group 'hypermedia)
96adeb99
RS
232
233;;;###autoload
0a3fc8a2 234(defcustom browse-url-browser-function
96adeb99 235 'browse-url-netscape
a69315a1 236 "*Function to display the current buffer in a WWW browser.
0a3fc8a2 237This is used by the `browse-url-at-point', `browse-url-at-mouse', and
1341d237 238`browse-url-of-file' commands.
5db57514
RS
239
240If the value is not a function it should be a list of pairs
a43d1a2a 241(REGEXP . FUNCTION). In this case the function called will be the one
5db57514
RS
242associated with the first REGEXP which matches the current URL. The
243function is passed the URL and any other args of `browse-url'. The last
244regexp should probably be \".\" to specify a default browser."
e49172c8
DL
245 :type '(choice
246 (function-item :tag "Emacs W3" :value browse-url-w3)
247 (function-item :tag "W3 in another Emacs via `gnudoit'"
248 :value browse-url-w3-gnudoit)
249 (function-item :tag "Netscape" :value browse-url-netscape)
250 (function-item :tag "Mosaic" :value browse-url-mosaic)
251 (function-item :tag "Mosaic using CCI" :value browse-url-cci)
252 (function-item :tag "IXI Mosaic" :value browse-url-iximosaic)
253 (function-item :tag "Lynx in an xterm window"
254 :value browse-url-lynx-xterm)
255 (function-item :tag "Lynx in an Emacs window"
256 :value browse-url-lynx-emacs)
257 (function-item :tag "Grail" :value browse-url-grail)
258 (function-item :tag "MMM" :value browse-url-mmm)
259 (function-item :tag "Specified by `Browse Url Generic Program'"
260 :value browse-url-generic)
261 (function :tag "Your own function"))
0a3fc8a2
RS
262 :group 'browse-url)
263
264(defcustom browse-url-netscape-program "netscape"
ac999fb9 265 ;; Info about netscape-remote from Kurt Swanson in gnu.emacs.gnus
a43d1a2a 266 "The name by which to invoke Netscape.
ac999fb9
DL
267
268It is said that source is available for a program `netscape-remote'
269which starts up very much quicker than `netscape' and that it is
270useful to set this variable to the name of a script which invokes that
271program like:
272 #!/bin/sh
273 /usr/local/bin/netscape-remote \"$@\" > /dev/null 2>&1
274"
0a3fc8a2
RS
275 :type 'string
276 :group 'browse-url)
277
278(defcustom browse-url-netscape-arguments nil
a43d1a2a 279 "A list of strings to pass to Netscape as arguments."
0a3fc8a2
RS
280 :type '(repeat (string :tag "Argument"))
281 :group 'browse-url)
282
283(defcustom browse-url-netscape-startup-arguments browse-url-netscape-arguments
a43d1a2a 284 "A list of strings to pass to Netscape when it starts up.
0a3fc8a2 285Defaults to the value of `browse-url-netscape-arguments' at the time
5db57514 286`browse-url' is loaded."
0a3fc8a2
RS
287 :type '(repeat (string :tag "Argument"))
288 :group 'browse-url)
96adeb99 289
a43d1a2a 290;;;###autoload
0a3fc8a2 291(defcustom browse-url-new-window-p nil
e49172c8
DL
292 "*If non-nil, always open a new browser window with appropriate browsers.
293Passing an interactive argument to \\[browse-url], or specific browser
294commands reverses the effect of this variable. Requires Netscape version
2951.1N or later or XMosaic version 2.5 or later if using those browsers."
0a3fc8a2
RS
296 :type 'boolean
297 :group 'browse-url)
298
a43d1a2a 299;;;###autoload
5db57514 300(defcustom browse-url-netscape-display nil
837984b1 301 "*The X display for running Netscape, if not same as Emacs'."
e49172c8 302 :type '(choice string (const :tag "Default" nil))
5db57514
RS
303 :group 'browse-url)
304
837984b1 305(defcustom browse-url-mosaic-program "xmosaic"
a43d1a2a 306 "The name by which to invoke Mosaic (or mMosaic)."
837984b1 307 :type 'string
a43d1a2a 308 :version "20.3"
837984b1
DL
309 :group 'browse-url)
310
0a3fc8a2 311(defcustom browse-url-mosaic-arguments nil
a43d1a2a 312 "A list of strings to pass to Mosaic as arguments."
0a3fc8a2
RS
313 :type '(repeat (string :tag "Argument"))
314 :group 'browse-url)
a69315a1 315
09d8b0bc 316(defcustom browse-url-filename-alist
ac999fb9
DL
317 '(("^/\\(ftp@\\|anonymous@\\)?\\([^:]+\\):/*" . "ftp://\\2/")
318 ;; The above loses the username to avoid the browser prompting for
319 ;; it in anonymous cases. If it's not anonymous the next regexp
320 ;; applies.
321 ("^/\\([^:@]+@\\)?\\([^:]+\\):/*" . "ftp://\\1\\2/")
322 ("^/+" . "file:/"))
a43d1a2a 323 "An alist of (REGEXP . STRING) pairs used by `browse-url-of-file'.
a69315a1 324Any substring of a filename matching one of the REGEXPs is replaced by
ac999fb9
DL
325the corresponding STRING using `replace-match', not treating STRING
326literally. All pairs are applied in the order given. The default
327value converts ange-ftp/EFS-style paths into ftp URLs and prepends
328`file:' to any path beginning with `/'.
5db57514 329
ac999fb9
DL
330For example, adding to the default a specific translation of an ange-ftp
331address to an HTTP URL:
5db57514
RS
332
333 (setq browse-url-filename-alist
334 '((\"/webmaster@webserver:/home/www/html/\" .
335 \"http://www.acme.co.uk/\")
ac999fb9
DL
336 (\"^/\\(ftp@\\|anonymous@\\)?\\([^:]+\\):/*\" . \"ftp://\\2/\")
337 (\"^/\\([^:@]+@\\)?\\([^:]+\\):/*\" . \"ftp://\\1\\2/\")
5db57514 338 (\"^/+\" . \"file:/\")))
09d8b0bc
DL
339"
340 :type '(repeat (cons :format "%v"
e49172c8 341 (regexp :tag "Regexp")
09d8b0bc 342 (string :tag "Replacement")))
ac999fb9 343 :version "20.3"
09d8b0bc 344 :group 'browse-url)
a69315a1 345
a43d1a2a 346;;;###autoload
09d8b0bc
DL
347(defcustom browse-url-save-file nil
348 "*If non-nil, save the buffer before displaying its file.
349Used by the `browse-url-of-file' command."
350 :type 'boolean
351 :group 'browse-url)
a69315a1 352
09d8b0bc 353(defcustom browse-url-of-file-hook nil
a43d1a2a 354 "Run after `browse-url-of-file' has asked a browser to load a file.
a69315a1
RS
355
356Set this to `browse-url-netscape-reload' to force Netscape to load the
09d8b0bc
DL
357file rather than displaying a cached copy."
358 :type 'hook
a43d1a2a 359 :options '(browse-url-netscape-reload)
09d8b0bc 360 :group 'browse-url)
a69315a1
RS
361
362(defvar browse-url-usr1-signal
363 (if (and (boundp 'emacs-major-version)
5db57514 364 (or (> emacs-major-version 19) (>= emacs-minor-version 29)))
96adeb99 365 'SIGUSR1 ; Why did I think this was in lower case before?
5db57514 366 30) ; Check /usr/include/signal.h.
a69315a1 367 "The argument to `signal-process' for sending SIGUSR1 to XMosaic.
00232ce3 368Emacs 19.29 accepts 'SIGUSR1, earlier versions require an integer
a69315a1
RS
369which is 30 on SunOS and 16 on HP-UX and Solaris.")
370
09d8b0bc 371(defcustom browse-url-CCI-port 3003
a43d1a2a 372 "Port to access XMosaic via CCI.
a69315a1 373This can be any number between 1024 and 65535 but must correspond to
09d8b0bc
DL
374the value set in the browser."
375 :type 'integer
376 :group 'browse-url)
a69315a1 377
09d8b0bc 378(defcustom browse-url-CCI-host "localhost"
96adeb99
RS
379 "*Host to access XMosaic via CCI.
380This should be the host name of the machine running XMosaic with CCI
09d8b0bc
DL
381enabled. The port number should be set in `browse-url-CCI-port'."
382 :type 'string
383 :group 'browse-url)
96adeb99
RS
384
385(defvar browse-url-temp-file-name nil)
386(make-variable-buffer-local 'browse-url-temp-file-name)
387
5db57514 388(defcustom browse-url-xterm-program "xterm"
a43d1a2a 389 "The name of the terminal emulator used by `browse-url-lynx-xterm'.
5db57514
RS
390This might, for instance, be a separate colour version of xterm."
391 :type 'string
392 :group 'browse-url)
393
394(defcustom browse-url-xterm-args nil
395 "*A list of strings defining options for `browse-url-xterm-program'.
396These might set its size, for instance."
397 :type '(repeat (string :tag "Argument"))
398 :group 'browse-url)
399
a43d1a2a
DL
400(defcustom browse-url-lynx-emacs-args (and (not window-system)
401 '("-show_cursor"))
402 "A list of strings defining options for Lynx in an Emacs buffer.
403
404The default is none in a window system, otherwise `-show_cursor' to
405indicate the position of the current link in the absence of
406highlighting, assuming the normal default for showing the cursor."
407 :type '(repeat (string :tag "Argument"))
408 :version "20.3"
409 :group 'browse-url)
410
5db57514 411(defcustom browse-url-gnudoit-program "gnudoit"
a43d1a2a 412 "The name of the `gnudoit' program used by `browse-url-w3-gnudoit'."
5db57514
RS
413 :type 'string
414 :group 'browse-url)
415
416(defcustom browse-url-gnudoit-args '("-q")
417 "*A list of strings defining options for `browse-url-gnudoit-program'.
418These might set the port, for instance."
419 :type '(repeat (string :tag "Argument"))
420 :group 'browse-url)
421
a43d1a2a 422;;;###autoload
5db57514
RS
423(defcustom browse-url-generic-program nil
424 "*The name of the browser program used by `browse-url-generic'."
e49172c8 425 :type '(choice string (const :tag "None" nil))
5db57514
RS
426 :group 'browse-url)
427
428(defcustom browse-url-generic-args nil
429 "*A list of strings defining options for `browse-url-generic-program'."
430 :type '(repeat (string :tag "Argument"))
431 :group 'browse-url)
432
406757ff 433(defcustom browse-url-temp-dir temporary-file-directory
a43d1a2a 434 "The name of a directory for browse-url's temporary files.
837984b1
DL
435Such files are generated by functions like `browse-url-of-region'.
436You might want to set this to somewhere with restricted read permissions
437for privacy's sake."
bc6d0d71
RS
438 :type 'string
439 :group 'browse-url)
440
f6680f0b
RS
441(defcustom browse-url-netscape-version
442 3
a43d1a2a 443 "The version of Netscape you are using.
f6680f0b
RS
444This affects how URL reloading is done; the mechanism changed
445incompatibly at version 4."
446 :type 'number
447 :group 'browse-url)
448
09d8b0bc 449(defcustom browse-url-lynx-input-field 'avoid
837984b1
DL
450 "*Action on selecting an existing Lynx buffer at an input field.
451What to do when sending a new URL to an existing Lynx buffer in Emacs
452if the Lynx cursor is on an input field (in which case the `g' command
453would be entered as data). Such fields are recognized by the
454underlines ____. Allowed values: nil: disregard it, 'warn: warn the
455user and don't emit the URL, 'avoid: try to avoid the field by moving
09d8b0bc
DL
456down (this *won't* always work)."
457 :type '(choice (const :tag "Move to try to avoid field" :value avoid)
458 (const :tag "Disregard" :value nil)
459 (const :tag "Warn, don't emit URL" :value warn))
a43d1a2a 460 :version "20.3"
09d8b0bc 461 :group 'browse-url)
837984b1 462
380a0a12
DL
463(defvar browse-url-lynx-input-attempts 10
464 "*How many times to try to move down from a series of lynx input fields.")
837984b1 465
09d8b0bc 466(defcustom browse-url-lynx-input-delay 0.2
380a0a12 467 "How many seconds to wait for lynx between moves down from an input field.")
837984b1 468
96adeb99
RS
469(defvar browse-url-temp-file-list '())
470
a69315a1
RS
471;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
472;; URL input
473
a69315a1 474(defun browse-url-url-at-point ()
6debdec5
RS
475 (let ((url (thing-at-point 'url)))
476 (set-text-properties 0 (length url) nil url)
5db57514
RS
477 url))
478
96adeb99
RS
479;; Having this as a separate function called by the browser-specific
480;; functions allows them to be stand-alone commands, making it easier
481;; to switch between browsers.
482
483(defun browse-url-interactive-arg (prompt)
484 "Read a URL from the minibuffer, prompting with PROMPT.
bc6d0d71 485Default to the URL at or before point. If invoked with a mouse button,
96adeb99 486set point to the position clicked first. Return a list for use in
5db57514 487`interactive' containing the URL and `browse-url-new-window-p' or its
96adeb99 488negation if a prefix argument was given."
a69315a1
RS
489 (let ((event (elt (this-command-keys) 0)))
490 (and (listp event) (mouse-set-point event)))
96adeb99
RS
491 (list (read-string prompt (browse-url-url-at-point))
492 (not (eq (null browse-url-new-window-p)
493 (null current-prefix-arg)))))
a69315a1 494
e61d8515
DL
495;; interactive-p needs to be called at a function's top-level, hence
496;; the macro.
497(defmacro browse-url-maybe-new-window (arg)
498 `(if (interactive-p)
499 'arg
500 browse-url-new-window-p))
837984b1 501
a69315a1
RS
502;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
503;; Browse current buffer
504
8941c0cf 505;;;###autoload
a69315a1
RS
506(defun browse-url-of-file (&optional file)
507 "Ask a WWW browser to display FILE.
508Display the current buffer's file if FILE is nil or if called
96adeb99 509interactively. Turn the filename into a URL with function
5db57514
RS
510`browse-url-file-url'. Pass the URL to a browser using the
511`browse-url' function then run `browse-url-of-file-hook'."
a69315a1 512 (interactive)
5db57514 513 (or file
96adeb99
RS
514 (setq file (buffer-file-name))
515 (error "Current buffer has no file"))
a69315a1
RS
516 (let ((buf (get-file-buffer file)))
517 (if buf
5db57514
RS
518 (save-excursion
519 (set-buffer buf)
520 (cond ((not (buffer-modified-p)))
521 (browse-url-save-file (save-buffer))
522 (t (message "%s modified since last save" file))))))
523 (browse-url (browse-url-file-url file))
a69315a1
RS
524 (run-hooks 'browse-url-of-file-hook))
525
526(defun browse-url-file-url (file)
527 "Return the URL corresponding to FILE.
ac999fb9 528Use variable `browse-url-filename-alist' to map filenames to URLs."
96adeb99
RS
529 ;; URL-encode special chars, do % first
530 (let ((s 0))
531 (while (setq s (string-match "%" file s))
532 (setq file (replace-match "%25" t t file)
533 s (1+ s))))
534 (while (string-match "[*\"()',=;? ]" file)
535 (let ((enc (format "%%%x" (aref file (match-beginning 0)))))
536 (setq file (replace-match enc t t file))))
a69315a1
RS
537 (let ((maps browse-url-filename-alist))
538 (while maps
539 (let* ((map (car maps))
5db57514
RS
540 (from-re (car map))
541 (to-string (cdr map)))
542 (setq maps (cdr maps))
96adeb99 543 (and (string-match from-re file)
ac999fb9 544 (setq file (replace-match to-string t nil file))))))
a69315a1
RS
545 file)
546
8941c0cf 547;;;###autoload
a69315a1
RS
548(defun browse-url-of-buffer (&optional buffer)
549 "Ask a WWW browser to display BUFFER.
5db57514
RS
550Display the current buffer if BUFFER is nil. Display only the
551currently visible part of BUFFER (from a temporary file) if buffer is
552narrowed."
a69315a1
RS
553 (interactive)
554 (save-excursion
96adeb99 555 (and buffer (set-buffer buffer))
a69315a1 556 (let ((file-name
5db57514
RS
557 ;; Ignore real name if restricted
558 (and (= (- (point-max) (point-min)) (buffer-size))
559 (or buffer-file-name
560 (and (boundp 'dired-directory) dired-directory)))))
96adeb99 561 (or file-name
5db57514 562 (progn
96adeb99 563 (or browse-url-temp-file-name
5db57514 564 (setq browse-url-temp-file-name
bc6d0d71
RS
565 (convert-standard-filename
566 (make-temp-name
567 (expand-file-name "burl" browse-url-temp-dir)))))
96adeb99
RS
568 (setq file-name browse-url-temp-file-name)
569 (write-region (point-min) (point-max) file-name nil 'no-message)))
570 (browse-url-of-file file-name))))
a69315a1
RS
571
572(defun browse-url-delete-temp-file (&optional temp-file-name)
573 ;; Delete browse-url-temp-file-name from the file system and from
574 ;; browse-url-temp-file-list. If optional arg TEMP-FILE-NAME is
575 ;; non-nil, delete it instead, but only from the file system --
576 ;; browse-url-temp-file-list is not affected.
577 (let ((file-name (or temp-file-name browse-url-temp-file-name)))
578 (if (and file-name (file-exists-p file-name))
5db57514
RS
579 (progn
580 (delete-file file-name)
581 (if (null temp-file-name)
582 (setq browse-url-temp-file-list
583 (delete browse-url-temp-file-name
584 browse-url-temp-file-list)))))))
a69315a1
RS
585
586(defun browse-url-delete-temp-file-list ()
587 ;; Delete all elements of browse-url-temp-file-list.
588 (while browse-url-temp-file-list
589 (browse-url-delete-temp-file (car browse-url-temp-file-list))
590 (setq browse-url-temp-file-list
5db57514 591 (cdr browse-url-temp-file-list))))
a69315a1
RS
592
593(add-hook 'kill-buffer-hook 'browse-url-delete-temp-file)
594(add-hook 'kill-emacs-hook 'browse-url-delete-temp-file-list)
595
8941c0cf 596;;;###autoload
a69315a1
RS
597(defun browse-url-of-dired-file ()
598 "In Dired, ask a WWW browser to display the file named on this line."
599 (interactive)
600 (browse-url-of-file (dired-get-filename)))
601
5db57514
RS
602;;;###autoload
603(defun browse-url-of-region (min max)
604 "Ask a WWW browser to display the current region."
605 (interactive "r")
606 (save-excursion
607 (save-restriction
f64905b5 608 (narrow-to-region min max)
5db57514
RS
609 (browse-url-of-buffer))))
610
a69315a1 611;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5db57514 612;; Browser-independent commands
96adeb99 613
5db57514 614;; A generic command to call the current browse-url-browser-function
96adeb99 615
5db57514 616;;;###autoload
a43d1a2a 617(defun browse-url (url &rest args)
96adeb99
RS
618 "Ask a WWW browser to load URL.
619Prompts for a URL, defaulting to the URL at or before point. Variable
620`browse-url-browser-function' says which browser to use."
621 (interactive (browse-url-interactive-arg "URL: "))
a43d1a2a 622 (let ((bf browse-url-browser-function) re)
833eadc2
DL
623 (unless (functionp bf)
624 (while (consp bf)
625 (setq re (car (car bf))
626 bf (if (string-match re url)
627 (cdr (car bf)) ; The function
628 (cdr bf))))) ; More pairs
a43d1a2a
DL
629 (or bf (error "No browser in browse-url-browser-function matching URL %s"
630 url))
631 (apply bf url args)))
96adeb99 632
8941c0cf 633;;;###autoload
96adeb99
RS
634(defun browse-url-at-point ()
635 "Ask a WWW browser to load the URL at or before point.
837984b1 636Doesn't let you edit the URL like `browse-url'. Variable
96adeb99
RS
637`browse-url-browser-function' says which browser to use."
638 (interactive)
5db57514 639 (browse-url (browse-url-url-at-point)))
96adeb99 640
78c11a9c
RS
641(defun browse-url-event-buffer (event)
642 (window-buffer (posn-window (event-start event))))
96adeb99 643
78c11a9c
RS
644(defun browse-url-event-point (event)
645 (posn-point (event-start event)))
96adeb99 646
8941c0cf 647;;;###autoload
96adeb99
RS
648(defun browse-url-at-mouse (event)
649 "Ask a WWW browser to load a URL clicked with the mouse.
650The URL is the one around or before the position of the mouse click
651but point is not changed. Doesn't let you edit the URL like
837984b1 652`browse-url'. Variable `browse-url-browser-function' says which browser
96adeb99
RS
653to use."
654 (interactive "e")
655 (save-excursion
78c11a9c
RS
656 (set-buffer (browse-url-event-buffer event))
657 (goto-char (browse-url-event-point event))
96adeb99
RS
658 (let ((url (browse-url-url-at-point)))
659 (if (string-equal url "")
660 (error "No URL found"))
837984b1 661 (browse-url url browse-url-new-window-p))))
96adeb99
RS
662
663;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
664;; Browser-specific commands
665
666;; --- Netscape ---
667
96adeb99 668(defun browse-url-process-environment ()
5db57514
RS
669 "Set DISPLAY in the environment to the X display Netscape is running on.
670This is either the value of variable `browse-url-netscape-display' if
671non-nil, or the same display as Emacs if different from the current
672environment, otherwise just use the current environment."
673 (let ((display (or browse-url-netscape-display (browse-url-emacs-display))))
96adeb99 674 (if display
5db57514 675 (cons (concat "DISPLAY=" display) process-environment)
96adeb99
RS
676 process-environment)))
677
5db57514
RS
678(defun browse-url-emacs-display ()
679 "Return the X display Emacs is running on.
837984b1 680This is nil if the display is the same as the DISPLAY environment variable.
5db57514 681
a43d1a2a
DL
682Actually Emacs could be using several displays; this just returns the
683one showing the selected frame."
684 (let ((display (cdr-safe (assq 'display (frame-parameters)))))
685 (and (not (equal display (getenv "DISPLAY")))
686 display)))
a69315a1 687
96adeb99 688;;;###autoload
a69315a1
RS
689(defun browse-url-netscape (url &optional new-window)
690 "Ask the Netscape WWW browser to load URL.
691
692Default to the URL around or before point. The strings in variable
693`browse-url-netscape-arguments' are also passed to Netscape.
694
695When called interactively, if variable `browse-url-new-window-p' is
696non-nil, load the document in a new Netscape window, otherwise use a
697random existing one. A non-nil interactive prefix argument reverses
5db57514 698the effect of `browse-url-new-window-p'.
a69315a1
RS
699
700When called non-interactively, optional second argument NEW-WINDOW is
5db57514 701used instead of `browse-url-new-window-p'."
96adeb99 702 (interactive (browse-url-interactive-arg "Netscape URL: "))
9d843bef
DL
703 ;; URL encode any `confusing' characters in the URL. This needs to
704 ;; include at least commas; presumably also close parens.
705 (while (string-match "[,)]" url)
706 (setq url (replace-match
ddff3d80 707 (format "%%%x" (string-to-char (match-string 0 url))) t t url)))
96adeb99
RS
708 (let* ((process-environment (browse-url-process-environment))
709 (process (apply 'start-process
710 (concat "netscape " url) nil
6be23be6 711 browse-url-netscape-program
5db57514 712 (append browse-url-netscape-arguments
78557fbf 713 (if (eq window-system 'w32)
5db57514
RS
714 (list url)
715 (if new-window '("-noraise"))
a43d1a2a
DL
716 (list "-remote"
717 (concat "openURL(" url
837984b1 718 (if (browse-url-maybe-new-window
e61d8515 719 new-window)
837984b1 720 ",new-window")
5db57514 721 ")")))))))
96adeb99 722 (set-process-sentinel process
5db57514
RS
723 (list 'lambda '(process change)
724 (list 'browse-url-netscape-sentinel 'process url)))))
96adeb99
RS
725
726(defun browse-url-netscape-sentinel (process url)
727 "Handle a change to the process communicating with Netscape."
728 (or (eq (process-exit-status process) 0)
729 (let* ((process-environment (browse-url-process-environment)))
730 ;; Netscape not running - start it
5db57514 731 (message "Starting Netscape...")
96adeb99 732 (apply 'start-process (concat "netscape" url) nil
6be23be6 733 browse-url-netscape-program
96adeb99 734 (append browse-url-netscape-startup-arguments (list url))))))
a69315a1
RS
735
736(defun browse-url-netscape-reload ()
837984b1
DL
737 "Ask Netscape to reload its current document.
738How depends on `browse-url-netscape-version'."
a69315a1 739 (interactive)
f6680f0b
RS
740 ;; Backwards incompatibility reported by
741 ;; <peter.kruse@psychologie.uni-regensburg.de>.
742 (browse-url-netscape-send (if (>= browse-url-netscape-version 4)
743 "xfeDoCommand(reload)"
744 "reload")))
a69315a1 745
96adeb99 746(defun browse-url-netscape-send (command)
a69315a1 747 "Send a remote control command to Netscape."
96adeb99
RS
748 (let* ((process-environment (browse-url-process-environment)))
749 (apply 'start-process "netscape" nil
6be23be6 750 browse-url-netscape-program
5db57514 751 (append browse-url-netscape-arguments
96adeb99
RS
752 (list "-remote" command)))))
753
754;; --- Mosaic ---
a69315a1 755
96adeb99
RS
756;;;###autoload
757(defun browse-url-mosaic (url &optional new-window)
758 ;; new-window ignored
a69315a1 759 "Ask the XMosaic WWW browser to load URL.
837984b1
DL
760
761Default to the URL around or before point. The strings in variable
762`browse-url-mosaic-arguments' are also passed to Mosaic and the
763program is invoked according to the variable
764`browse-url-mosaic-program'.
765
766When called interactively, if variable `browse-url-new-window-p' is
767non-nil, load the document in a new Mosaic window, otherwise use a
768random existing one. A non-nil interactive prefix argument reverses
769the effect of `browse-url-new-window-p'.
770
771When called non-interactively, optional second argument NEW-WINDOW is
772used instead of `browse-url-new-window-p'."
a69315a1
RS
773 (interactive (browse-url-interactive-arg "Mosaic URL: "))
774 (let ((pidfile (expand-file-name "~/.mosaicpid"))
380a0a12 775 pid)
a69315a1 776 (if (file-readable-p pidfile)
5db57514
RS
777 (save-excursion
778 (find-file pidfile)
779 (goto-char (point-min))
780 (setq pid (read (current-buffer)))
781 (kill-buffer nil)))
a69315a1 782 (if (and pid (zerop (signal-process pid 0))) ; Mosaic running
5db57514
RS
783 (save-excursion
784 (find-file (format "/tmp/Mosaic.%d" pid))
785 (erase-buffer)
e61d8515 786 (insert (if (browse-url-maybe-new-window new-window)
837984b1
DL
787 "newwin\n"
788 "goto\n")
789 url "\n")
5db57514
RS
790 (save-buffer)
791 (kill-buffer nil)
792 ;; Send signal SIGUSR to Mosaic
96adeb99 793 (message "Signalling Mosaic...")
5db57514
RS
794 (signal-process pid browse-url-usr1-signal)
795 ;; Or you could try:
796 ;; (call-process "kill" nil 0 nil "-USR1" (int-to-string pid))
96adeb99 797 (message "Signalling Mosaic...done")
5db57514 798 )
a69315a1
RS
799 ;; Mosaic not running - start it
800 (message "Starting Mosaic...")
837984b1 801 (apply 'start-process "xmosaic" nil browse-url-mosaic-program
5db57514 802 (append browse-url-mosaic-arguments (list url)))
a5f6b207 803 (message "Starting Mosaic...done"))))
a69315a1 804
96adeb99
RS
805;; --- Grail ---
806
807;;;###autoload
808(defvar browse-url-grail
809 (concat (or (getenv "GRAILDIR") "~/.grail") "/user/rcgrail.py")
a43d1a2a 810 "Location of Grail remote control client script `rcgrail.py'.
96adeb99
RS
811Typically found in $GRAILDIR/rcgrail.py, or ~/.grail/user/rcgrail.py.")
812
813;;;###autoload
5db57514 814(defun browse-url-grail (url &optional new-window)
96adeb99
RS
815 "Ask the Grail WWW browser to load URL.
816Default to the URL around or before point. Runs the program in the
817variable `browse-url-grail'."
818 (interactive (browse-url-interactive-arg "Grail URL: "))
819 (message "Sending URL to Grail...")
820 (save-excursion
821 (set-buffer (get-buffer-create " *Shell Command Output*"))
822 (erase-buffer)
823 ;; don't worry about this failing.
380a0a12
DL
824 (if new-window
825 (call-process browse-url-grail nil 0 nil "-b" url)
826 (call-process browse-url-grail nil 0 nil url))
96adeb99
RS
827 (message "Sending URL to Grail... done")))
828
829;; --- Mosaic using CCI ---
830
380a0a12 831;;;###autoload
a69315a1
RS
832(defun browse-url-cci (url &optional new-window)
833 "Ask the XMosaic WWW browser to load URL.
834Default to the URL around or before point.
835
836This function only works for XMosaic version 2.5 or later. You must
837select `CCI' from XMosaic's File menu, set the CCI Port Address to the
838value of variable `browse-url-CCI-port', and enable `Accept requests'.
839
840When called interactively, if variable `browse-url-new-window-p' is
841non-nil, load the document in a new browser window, otherwise use a
842random existing one. A non-nil interactive prefix argument reverses
5db57514 843the effect of `browse-url-new-window-p'.
a69315a1
RS
844
845When called non-interactively, optional second argument NEW-WINDOW is
5db57514 846used instead of `browse-url-new-window-p'."
96adeb99 847 (interactive (browse-url-interactive-arg "Mosaic URL: "))
a69315a1 848 (open-network-stream "browse-url" " *browse-url*"
96adeb99 849 browse-url-CCI-host browse-url-CCI-port)
a69315a1
RS
850 ;; Todo: start browser if fails
851 (process-send-string "browse-url"
5db57514 852 (concat "get url (" url ") output "
e61d8515 853 (if (browse-url-maybe-new-window new-window)
837984b1
DL
854 "new"
855 "current")
856 "\r\n"))
a69315a1
RS
857 (process-send-string "browse-url" "disconnect\r\n")
858 (delete-process "browse-url"))
859
96adeb99
RS
860;; --- IXI Mosaic ---
861
862;;;###autoload
863(defun browse-url-iximosaic (url &optional new-window)
864 ;; new-window ignored
a69315a1
RS
865 "Ask the IXIMosaic WWW browser to load URL.
866Default to the URL around or before point."
867 (interactive (browse-url-interactive-arg "IXI Mosaic URL: "))
868 (start-process "tellw3b" nil "tellw3b"
5db57514 869 "-service WWW_BROWSER ixi_showurl " url))
a69315a1 870
96adeb99
RS
871;; --- W3 ---
872
873;;;###autoload
874(defun browse-url-w3 (url &optional new-window)
a69315a1 875 "Ask the w3 WWW browser to load URL.
e49172c8
DL
876Default to the URL around or before point.
877
878When called interactively, if variable `browse-url-new-window-p' is
879non-nil, load the document in a new window. A non-nil interactive
880prefix argument reverses the effect of `browse-url-new-window-p'.
881
882When called non-interactively, optional second argument NEW-WINDOW is
883used instead of `browse-url-new-window-p'."
a69315a1 884 (interactive (browse-url-interactive-arg "W3 URL: "))
e61d8515
DL
885 (require 'w3) ; w3-fetch-other-window not autoloaded
886 (if (browse-url-maybe-new-window new-window)
887 (w3-fetch-other-window url)
837984b1 888 (w3-fetch url)))
a69315a1 889
5db57514
RS
890;;;###autoload
891(defun browse-url-w3-gnudoit (url &optional new-window)
892 ;; new-window ignored
893 "Ask another Emacs running gnuserv to load the URL using the W3 browser.
894The `browse-url-gnudoit-program' program is used with options given by
895`browse-url-gnudoit-args'. Default to the URL around or before point."
896 (interactive (browse-url-interactive-arg "W3 URL: "))
897 (apply 'start-process (concat "gnudoit:" url) nil
898 browse-url-gnudoit-program
899 (append browse-url-gnudoit-args (list (concat "(w3-fetch \"" url "\")") "(raise-frame)"))))
900
96adeb99
RS
901;; --- Lynx in an xterm ---
902
903;;;###autoload
904(defun browse-url-lynx-xterm (url &optional new-window)
905 ;; new-window ignored
906 "Ask the Lynx WWW browser to load URL.
907Default to the URL around or before point. A new Lynx process is run
5db57514
RS
908in an Xterm window using the Xterm program named by `browse-url-xterm-program'
909with possible additional arguments `browse-url-xterm-args'."
96adeb99 910 (interactive (browse-url-interactive-arg "Lynx URL: "))
a43d1a2a
DL
911 (apply #'start-process `(,(concat "lynx" url) nil ,browse-url-xterm-program
912 ,@browse-url-xterm-args "-e" "lynx" ,url)))
96adeb99 913
96adeb99
RS
914;; --- Lynx in an Emacs "term" window ---
915
916;;;###autoload
837984b1 917(defun browse-url-lynx-emacs (url &optional new-buffer)
96adeb99 918 "Ask the Lynx WWW browser to load URL.
837984b1 919Default to the URL around or before point. With a prefix argument, run
e49172c8
DL
920a new Lynx process in a new buffer.
921
922When called interactively, if variable `browse-url-new-window-p' is
923non-nil, load the document in a new lynx in a new term window,
924otherwise use any existing one. A non-nil interactive prefix argument
925reverses the effect of `browse-url-new-window-p'.
926
927When called non-interactively, optional second argument NEW-WINDOW is
928used instead of `browse-url-new-window-p'."
96adeb99 929 (interactive (browse-url-interactive-arg "Lynx URL: "))
837984b1
DL
930 (let* ((system-uses-terminfo t) ; Lynx uses terminfo
931 ;; (term-term-name "vt100") ; ??
932 (buf (get-buffer "*lynx*"))
933 (proc (and buf (get-buffer-process buf)))
934 (n browse-url-lynx-input-attempts))
e61d8515 935 (if (and (browse-url-maybe-new-window new-buffer) buf)
837984b1
DL
936 ;; Rename away the OLD buffer. This isn't very polite, but
937 ;; term insists on working in a buffer named *lynx* and would
938 ;; choke on *lynx*<1>
939 (progn (set-buffer buf)
940 (rename-uniquely)))
e61d8515 941 (if (or (browse-url-maybe-new-window new-buffer)
837984b1
DL
942 (not buf)
943 (not proc)
944 (not (memq (process-status proc) '(run stop))))
945 ;; start a new lynx
a43d1a2a
DL
946 (progn
947 (setq buf
948 (apply #'make-term
949 `("lynx" "lynx" nil ,@browse-url-lynx-emacs-args ,url)))
950 (switch-to-buffer buf)
951 (term-char-mode)
952 (set-process-sentinel
953 (get-buffer-process buf)
954 ;; Don't leave around a dead one (especially because of its
955 ;; munged keymap.)
956 (lambda (process event)
957 (if (not (memq (process-status process) '(run stop)))
958 (let ((buf (process-buffer process)))
959 (if buf (kill-buffer buf)))))))
837984b1
DL
960 ;; send the url to lynx in the old buffer
961 (let ((win (get-buffer-window buf t)))
962 (if win
963 (select-window win)
964 (switch-to-buffer buf)))
965 (if (eq (following-char) ?_)
966 (cond ((eq browse-url-lynx-input-field 'warn)
967 (error "Please move out of the input field first."))
968 ((eq browse-url-lynx-input-field 'avoid)
969 (while (and (eq (following-char) ?_) (> n 0))
970 (term-send-down) ; down arrow
971 (sit-for browse-url-lynx-input-delay))
972 (if (eq (following-char) ?_)
973 (error "Cannot move out of the input field, sorry.")))))
974 (term-send-string proc (concat "g" ; goto
975 "\C-u" ; kill default url
976 url
977 "\r")))))
8bc9b4f1 978
5db57514
RS
979;; --- MMM ---
980
981;;;###autoload
982(defun browse-url-mmm (url &optional new-window)
983 "Ask the MMM WWW browser to load URL.
984Default to the URL around or before point."
985 (interactive (browse-url-interactive-arg "MMM URL: "))
986 (message "Sending URL to MMM...")
987 (save-excursion
988 (set-buffer (get-buffer-create " *Shell Command Output*"))
989 (erase-buffer)
990 ;; mmm_remote just SEGVs if the file isn't there...
991 (if (or (file-exists-p (expand-file-name "~/.mmm_remote"))
992 ;; location in v 0.4:
993 (file-exists-p (expand-file-name "~/.mmm/remote")))
994 (call-process "mmm_remote" nil 0 nil url)
995 (call-process "mmm" nil 0 nil "-external" url))
996 (message "Sending URL to MMM... done")))
997
998;; --- mailto ---
999
1000;;;###autoload
59966fb6 1001(defun browse-url-mail (url &optional new-window)
5db57514 1002 "Open a new mail message buffer within Emacs.
59966fb6
RS
1003Default to using the mailto: URL around or before point as the
1004recipient's address. Supplying a non-nil interactive prefix argument
1005will cause the mail to be composed in another window rather than the
e49172c8
DL
1006current one.
1007
1008When called interactively, if variable `browse-url-new-window-p' is
1009non-nil use `compose-mail-other-window', otherwise `compose-mail'. A
1010non-nil interactive prefix argument reverses the effect of
1011`browse-url-new-window-p'.
1012
1013When called non-interactively, optional second argument NEW-WINDOW is
1014used instead of `browse-url-new-window-p'."
5db57514
RS
1015 (interactive (browse-url-interactive-arg "Mailto URL: "))
1016 (save-excursion
685a6f2e 1017 (let ((to (if (string-match "^mailto:" url)
5db57514 1018 (substring url 7)
59966fb6 1019 url)))
e61d8515 1020 (if (browse-url-maybe-new-window new-window)
e58883dd
RS
1021 (compose-mail-other-window to nil nil nil
1022 (list 'insert-buffer (current-buffer)))
1023 (compose-mail to nil nil nil nil
1024 (list 'insert-buffer (current-buffer)))))))
5db57514
RS
1025
1026;; --- Random browser ---
1027
1028;;;###autoload
1029(defun browse-url-generic (url &optional new-window)
1030 ;; new-window ignored
1031 "Ask the WWW browser defined by `browse-url-generic-program' to load URL.
1032Default to the URL around or before point. A fresh copy of the
1033browser is started up in a new process with possible additional arguments
1034`browse-url-generic-args'. This is appropriate for browsers which
1035don't offer a form of remote control."
1036 (interactive (browse-url-interactive-arg "URL: "))
1037 (if (not browse-url-generic-program)
1038 (error "No browser defined (`browse-url-generic-program')"))
1039 (apply 'start-process (concat browse-url-generic-program url) nil
1040 browse-url-generic-program
1041 (append browse-url-generic-args (list url))))
1042
a69315a1
RS
1043(provide 'browse-url)
1044
1045;;; browse-url.el ends here