Initial Commit
[packages] / xemacs-packages / mail-lib / browse-url.el
1 ;;; browse-url.el --- pass a URL to a WWW browser
2
3 ;; Copyright (C) 1995, 96, 97, 98, 99, 2000, 2001, 2002, 2003, 2005
4 ;;   Free Software Foundation, Inc.
5
6 ;; Author: Denis Howe <dbh@doc.ic.ac.uk>
7 ;; Maintainer: XEmacs Development Team
8 ;; Created: 03 Apr 1995
9 ;; Keywords: hypertext, hypermedia, mouse
10
11 ;; This file is part of XEmacs.
12
13 ;; XEmacs is free software; you can redistribute it and/or modify
14 ;; it under the terms of the GNU General Public License as published by
15 ;; the Free Software Foundation; either version 2, or (at your option)
16 ;; any later version.
17
18 ;; XEmacs is distributed in the hope that it will be useful,
19 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 ;; GNU General Public License for more details.
22
23 ;; You should have received a copy of the GNU General Public License
24 ;; along with XEmacs; see the file COPYING.  If not, write to the
25 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
26 ;; Boston, MA 02111-1307, USA.
27
28 ;;; Synched up with:  Version 1.32 in CVS
29
30 ;;; Commentary:
31
32 ;; This package provides functions which read a URL (Uniform Resource
33 ;; Locator) from the minibuffer, defaulting to the URL around point,
34 ;; and ask a World-Wide Web browser to load it.  It can also load the
35 ;; URL associated with the current buffer.  Different browsers use
36 ;; different methods of remote control so there is one function for
37 ;; each supported browser.  If the chosen browser is not running, it
38 ;; is started.  Currently there is support for the following browsers,
39 ;; some of them probably now obsolete:
40
41 ;; Function                           Browser     Earliest version
42 ;; browse-url-seamonkey               SeaMonkey   1st tried with 1.0.4
43 ;; browse-url-mozilla                 Mozilla     Don't know
44 ;; browse-url-firefox                 Firefox     Don't know (1st tried with 1.0.1)
45 ;; browse-url-galeon                  Galeon      Don't know
46 ;; browse-url-epiphany                Epiphany    Don't know
47 ;; browse-url-netscape                Netscape    1.1b1
48 ;; browse-url-mosaic                  XMosaic/mMosaic <= 2.4
49 ;; browse-url-cci                     XMosaic     2.5
50 ;; browse-url-w3                      w3          0
51 ;; browse-url-w3-gnudoit              w3 remotely
52 ;; browse-url-w3m                     w3m         0.2.1, probably
53 ;; browse-url-w3m-gnudoit             w3m remotely 0.2.1, probably
54 ;; browse-url-iximosaic               IXI Mosaic  ?
55 ;; browse-url-lynx-*                  Lynx           0
56 ;; browse-url-grail                   Grail       0.3b1
57 ;; browse-url-mmm                     MMM         ?
58 ;; browse-url-generic                 arbitrary
59 ;; browse-url-default-windows-browser MS-Windows browser
60 ;; browse-url-default-macosx-browser  Mac OS X browser
61 ;; browse-url-default-xdg-browser     freedesktop.org browser
62 ;; browse-url-gnome-moz               GNOME interface to Mozilla
63 ;; browse-url-kde                     KDE konqueror (kfm)
64 ;; browse-url-opera                   Opera
65
66 ;; [A version of the Netscape browser is now free software
67 ;; <URL:http://www.mozilla.org/>, albeit not GPLed, so it is
68 ;; reasonable to have that as the default.]
69
70 ;; Note that versions of Netscape before 1.1b1 did not have remote
71 ;; control.  <URL:http://www.netscape.com/newsref/std/x-remote.html>.
72
73 ;; Browsers can cache Web pages so it may be necessary to tell them to
74 ;; reload the current page if it has changed (e.g. if you have edited
75 ;; it).  There is currently no perfect automatic solution to this.
76
77 ;; Netscape allows you to specify the id of the window you want to
78 ;; control but which window DO you want to control and how do you
79 ;; discover its id?
80
81 ;; If using XMosaic before version 2.5, check the definition of
82 ;; browse-url-usr1-signal below.
83 ;; <URL:http://www.ncsa.uiuc.edu/SDG/Software/XMosaic/remote-control.html>
84
85 ;; XMosaic version 2.5 introduced Common Client Interface allowing you
86 ;; to control mosaic through Unix sockets.
87 ;; <URL:http://www.ncsa.uiuc.edu/SDG/Software/XMosaic/CCI/cci-spec.html>
88
89 ;; William M. Perry's excellent "w3" WWW browser for
90 ;; Emacs <URL:ftp://cs.indiana.edu/pub/elisp/w3/>
91 ;; has a function w3-follow-url-at-point, but that
92 ;; doesn't let you edit the URL like browse-url.
93 ;; The `gnuserv' package that can be used to control it in another
94 ;; Emacs process is available from
95 ;; <URL:ftp://ftp.splode.com/pub/users/friedman/packages/>.
96
97 ;; Grail is the freely available WWW browser implemented in Python, a
98 ;; cool object-oriented freely available interpreted language.  Grail
99 ;; 0.3b1 was the first version to have remote control as distributed.
100 ;; For more information on Grail see
101 ;; <URL:http://grail.cnri.reston.va.us/> and for more information on
102 ;; Python see <url:http://www.python.org/>.  Grail support in
103 ;; browse-url.el written by Barry Warsaw <bwarsaw@python.org>.
104
105 ;; MMM is a semi-free WWW browser implemented in Objective Caml, an
106 ;; interesting impure functional programming language.  See
107 ;; <URL:http://pauillac.inria.fr/%7Erouaix/mmm/>.
108
109 ;; Lynx is now distributed by the FSF.  See also
110 ;; <URL:http://lynx.browser.org/>.
111
112 ;; Free graphical browsers that could be used by `browse-url-generic'
113 ;; include Chimera <URL:ftp://ftp.cs.unlv.edu/pub/chimera> and
114 ;; <URL:http://www.unlv.edu/chimera/>, Arena
115 ;; <URL:ftp://ftp.yggdrasil.com/pub/dist/web/arena> and Amaya
116 ;; <URL:ftp://ftp.w3.org/pub/amaya>.  mMosaic
117 ;; <URL:ftp://ftp.enst.fr/pub/mbone/mMosaic/>,
118 ;; <URL:http://www.enst.fr/~dauphin/mMosaic/> (with development
119 ;; support for Java applets and multicast) can be used like Mosaic by
120 ;; setting `browse-url-mosaic-program' appropriately.
121
122 ;; I [Denis Howe, not Dave Love] recommend Nelson Minar
123 ;; <nelson@santafe.edu>'s excellent html-helper-mode.el for editing
124 ;; HTML and thank Nelson for his many useful comments on this code.
125 ;; <URL:http://www.santafe.edu/%7Enelson/hhm-beta/>
126
127 ;; See also hm--html-menus <URL:http://www.tnt.uni-hannover.de/%7Emuenkel/
128 ;; software/own/hm--html-menus/>.  For composing correct HTML see also
129 ;; PSGML the general SGML structure editor package
130 ;; <URL:ftp://ftp.lysator.liu.se/pub/sgml>; hm--html-menus can be used
131 ;; with this.
132
133 ;; This package generalises function html-previewer-process in Marc
134 ;; Andreessen's html-mode (LCD modes/html-mode.el.Z).  See also the
135 ;; ffap.el package.  The huge hyperbole package also contains similar
136 ;; functions.
137
138 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
139 ;; Help!
140
141 ;; Can you write and test some code for the Macintrash and Windoze
142 ;; Netscape remote control APIs?  (See the URL above).
143
144 ;; Do any other browsers have remote control?
145
146 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
147 ;; Usage
148
149 ;; To display the URL at or before point:
150 ;; M-x browse-url-at-point RET
151 ;; or, similarly but with the opportunity to edit the URL extracted from
152 ;; the buffer, use:
153 ;; M-x browse-url
154
155 ;; To display a URL by shift-clicking on it, put this in your ~/.emacs
156 ;; file:
157 ;;      (global-set-key [S-mouse-2] 'browse-url-at-mouse)
158 ;; (Note that using Shift-mouse-1 is not desirable because
159 ;; that event has a standard meaning in Emacs.)
160
161 ;; To display the current buffer in a web browser:
162 ;; M-x browse-url-of-buffer RET
163
164 ;; To display the current region in a web browser:
165 ;; M-x browse-url-of-region RET
166
167 ;; In Dired, to display the file named on the current line:
168 ;; M-x browse-url-of-dired-file RET
169
170 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
171 ;; Customisation (~/.emacs)
172
173 ;; To see what variables are available for customization, type
174 ;; `M-x set-variable browse-url TAB'.  Better, use
175 ;; `M-x customize-group browse-url'.
176
177 ;; Bind the browse-url commands to keys with the `C-c C-z' prefix
178 ;; (as used by html-helper-mode):
179 ;;      (global-set-key "\C-c\C-z." 'browse-url-at-point)
180 ;;      (global-set-key "\C-c\C-zb" 'browse-url-of-buffer)
181 ;;      (global-set-key "\C-c\C-zr" 'browse-url-of-region)
182 ;;      (global-set-key "\C-c\C-zu" 'browse-url)
183 ;;      (global-set-key "\C-c\C-zv" 'browse-url-of-file)
184 ;;      (add-hook 'dired-mode-hook
185 ;;                (lambda ()
186 ;;                   (local-set-key "\C-c\C-zf" 'browse-url-of-dired-file)))
187
188 ;; Browse URLs in mail messages under RMAIL by clicking mouse-2:
189 ;;      (add-hook 'rmail-mode-hook (lambda () ; rmail-mode startup
190 ;;        (define-key rmail-mode-map [mouse-2] 'browse-url-at-mouse)))
191 ;; Alternatively, add `goto-address' to `rmail-show-message-hook'.
192
193 ;; Gnus provides a standard feature to activate URLs in article
194 ;; buffers for invocation of browse-url.
195
196 ;; Use the Emacs w3 browser when not running under X11:
197 ;;      (or (eq window-system 'x)
198 ;;          (setq browse-url-browser-function 'browse-url-w3))
199
200 ;; To always save modified buffers before displaying the file in a browser:
201 ;;      (setq browse-url-save-file t)
202
203 ;; To get round the Netscape caching problem, you could EITHER have
204 ;; write-file in html-helper-mode make Netscape reload the document:
205 ;;
206 ;;      (autoload 'browse-url-netscape-reload "browse-url"
207 ;;        "Ask a WWW browser to redisplay the current file." t)
208 ;;      (add-hook 'html-helper-mode-hook
209 ;;                (lambda ()
210 ;;                   (add-hook 'local-write-file-hooks
211 ;;                             (lambda ()
212 ;;                                (let ((local-write-file-hooks))
213 ;;                                  (save-buffer))
214 ;;                                (browse-url-netscape-reload)
215 ;;                                t)                    ; => file written by hook
216 ;;                             t)))                     ; append to l-w-f-hooks
217 ;;
218 ;; OR have browse-url-of-file ask Netscape to load and then reload the
219 ;; file:
220 ;;
221 ;;      (add-hook 'browse-url-of-file-hook 'browse-url-netscape-reload)
222
223 ;; You may also want to customise browse-url-netscape-arguments, e.g.
224 ;;      (setq browse-url-netscape-arguments '("-install"))
225 ;;
226 ;; or similarly for the other browsers.
227
228 ;; To invoke different browsers for different URLs:
229 ;;      (setq browse-url-browser-function '(("^mailto:" . browse-url-mail)
230 ;;                                          ("." . browse-url-netscape)))
231
232 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
233 ;;; Code:
234
235 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
236 ;; Variables
237
238 (eval-when-compile (require 'thingatpt)
239                    (require 'term)
240                    (require 'executable))
241
242 (defgroup browse-url nil
243   "Use a web browser to look at a URL."
244   :prefix "browse-url-"
245   :link '(emacs-commentary-link "browse-url")
246   :group 'hypermedia)
247
248 ;;;###autoload
249 (defcustom browse-url-browser-function
250   (cond
251    ((memq system-type '(windows-nt ms-dos cygwin32)) ;; XEmacs change
252     'browse-url-default-windows-browser)
253    ((memq system-type '(darwin)) 'browse-url-default-macosx-browser)
254    ;; XEmacs TODO: add 'browse-url-default-xdg-browser here, but how to detect
255    ;; a freedesktop.org desktop?  executable-find xdg-open is not the way.
256    (t 'browse-url-default-browser))
257   "*Function to display the current buffer in a WWW browser.
258 This is used by the `browse-url-at-point', `browse-url-at-mouse', and
259 `browse-url-of-file' commands.
260
261 If the value is not a function it should be a list of pairs
262 \(REGEXP . FUNCTION).  In this case the function called will be the one
263 associated with the first REGEXP which matches the current URL.  The
264 function is passed the URL and any other args of `browse-url'.  The last
265 regexp should probably be \".\" to specify a default browser."
266   :type '(choice
267           (function-item :tag "Emacs W3" :value  browse-url-w3)
268           (function-item :tag "W3 in another Emacs via `gnudoit'"
269                          :value  browse-url-w3-gnudoit)
270           (function-item :tag "Emacs W3M" :value  browse-url-w3)
271           (function-item :tag "W3M in another Emacs via `gnudoit'"
272                          :value  browse-url-w3-gnudoit)
273           (function-item :tag "SeaMonkey" :value browse-url-seamonkey)
274           (function-item :tag "Mozilla" :value  browse-url-mozilla)
275           (function-item :tag "Firefox" :value browse-url-firefox)
276           (function-item :tag "Galeon" :value  browse-url-galeon)
277           (function-item :tag "Epiphany" :value  browse-url-epiphany)
278           (function-item :tag "Netscape" :value  browse-url-netscape)
279           (function-item :tag "Mosaic" :value  browse-url-mosaic)
280           (function-item :tag "Mosaic using CCI" :value  browse-url-cci)
281           (function-item :tag "IXI Mosaic" :value  browse-url-iximosaic)
282           (function-item :tag "Lynx in an xterm window"
283                          :value browse-url-lynx-xterm)
284           (function-item :tag "Lynx in an Emacs window"
285                          :value browse-url-lynx-emacs)
286           (function-item :tag "Grail" :value  browse-url-grail)
287           (function-item :tag "MMM" :value  browse-url-mmm)
288           (function-item :tag "KDE" :value browse-url-kde)
289           (function-item :tag "Opera" :value browse-url-opera) ;; XEmacs
290           (function-item :tag "Specified by `Browse Url Generic Program'"
291                          :value browse-url-generic)
292           (function-item :tag "Default Windows browser"
293                          :value browse-url-default-windows-browser)
294           (function-item :tag "Default Mac OS X browser"
295                          :value browse-url-default-macosx-browser)
296           ;; XEmacs addition
297           (function-item :tag "Default freedesktop.org browser"
298                          :value browse-url-default-xdg-browser)
299           (function-item :tag "GNOME invoking Mozilla"
300                          :value browse-url-gnome-moz)
301           (function-item :tag "Default browser"
302                          :value browse-url-default-browser)
303           (function :tag "Your own function")
304           ;; XEmacs: Emacs has an `alist' custom type here, but custom
305           ;; in XEmacs is buggy and cannot handle it, so we don't
306           ;; include the following:
307           ;; (alist :tag "Regexp/function association list"
308           ;;        :key-type regexp :value-type function))
309           )
310   :group 'browse-url)
311
312 (defcustom browse-url-netscape-program "netscape"
313   ;; Info about netscape-remote from Karl Berry.
314   "*The name by which to invoke Netscape.
315
316 The free program `netscape-remote' from
317 <URL:http://home.netscape.com/newsref/std/remote.c> is said to start
318 up very much quicker than `netscape'.  Reported to compile on a GNU
319 system, given vroot.h from the same directory, with cc flags
320  -DSTANDALONE -L/usr/X11R6/lib -lXmu -lX11."
321   :type 'string
322   :group 'browse-url)
323
324 (defcustom browse-url-netscape-arguments nil
325   "*A list of strings to pass to Netscape as arguments."
326   :type '(repeat (string :tag "Argument"))
327   :group 'browse-url)
328
329 (defcustom browse-url-netscape-startup-arguments browse-url-netscape-arguments
330   "*A list of strings to pass to Netscape when it starts up.
331 Defaults to the value of `browse-url-netscape-arguments' at the time
332 `browse-url' is loaded."
333   :type '(repeat (string :tag "Argument"))
334   :group 'browse-url)
335
336 ;;;###autoload
337 (defcustom browse-url-browser-display nil
338   "*The X display for running the browser, if not same as Emacs'."
339   :type '(choice string (const :tag "Default" nil))
340   :group 'browse-url)
341
342 ;;;###autoload
343 (defcustom browse-url-seamonkey-program "seamonkey"
344   "*The name by which to invoke SeaMonkey."
345   :type 'string
346   :group 'browse-url)
347
348 (defcustom browse-url-seamonkey-arguments nil
349   "*A list of strings to pass to SeaMonkey as arguments."
350   :type '(repeat (string :tag "Argument"))
351   :group 'browse-url)
352
353 (defcustom browse-url-seamonkey-startup-arguments browse-url-seamonkey-arguments
354   "*A list of strings to pass to SeaMonkey when it starts up.
355 Defaults to the value of `browse-url-seamonkey-arguments' at the time
356 `browse-url' is loaded."
357   :type '(repeat (string :tag "Argument"))
358   :group 'browse-url)
359
360 ;;;###autoload
361 (defcustom browse-url-mozilla-program "mozilla"
362   "*The name by which to invoke Mozilla."
363   :type 'string
364   :group 'browse-url)
365
366 (defcustom browse-url-mozilla-arguments nil
367   "*A list of strings to pass to Mozilla as arguments."
368   :type '(repeat (string :tag "Argument"))
369   :group 'browse-url)
370
371 (defcustom browse-url-mozilla-startup-arguments browse-url-mozilla-arguments
372   "*A list of strings to pass to Mozilla when it starts up.
373 Defaults to the value of `browse-url-mozilla-arguments' at the time
374 `browse-url' is loaded."
375   :type '(repeat (string :tag "Argument"))
376   :group 'browse-url)
377
378 ;;;###autoload
379 (defcustom browse-url-firefox-program "firefox"
380   "*The name by which to invoke Firefox."
381   :type 'string
382   :group 'browse-url)
383
384 (defcustom browse-url-firefox-arguments nil
385   "*A list of strings to pass to Firefox as arguments."
386   :type '(repeat (string :tag "Argument"))
387   :group 'browse-url)
388
389 (defcustom browse-url-firefox-startup-arguments browse-url-firefox-arguments
390   "*A list of strings to pass to Firefox when it starts up.
391 Defaults to the value of `browse-url-firefox-arguments' at the time
392 `browse-url' is loaded."
393   :type '(repeat (string :tag "Argument"))
394   :group 'browse-url)
395
396 ;;;###autoload
397 (defcustom browse-url-galeon-program "galeon"
398   "*The name by which to invoke Galeon."
399   :type 'string
400   :group 'browse-url)
401
402 (defcustom browse-url-galeon-arguments nil
403   "*A list of strings to pass to Galeon as arguments."
404   :type '(repeat (string :tag "Argument"))
405   :group 'browse-url)
406
407 (defcustom browse-url-galeon-startup-arguments browse-url-galeon-arguments
408   "*A list of strings to pass to Galeon when it starts up.
409 Defaults to the value of `browse-url-galeon-arguments' at the time
410 `browse-url' is loaded."
411   :type '(repeat (string :tag "Argument"))
412   :group 'browse-url)
413
414 (defcustom browse-url-epiphany-program "epiphany"
415   "*The name by which to invoke Epiphany."
416 :type 'string
417 :group 'browse-url)
418
419 (defcustom browse-url-epiphany-arguments nil
420   "*A list of strings to pass to Epiphany as arguments."
421 :type '(repeat (string :tag "Argument"))
422 :group 'browse-url)
423
424 (defcustom browse-url-epiphany-startup-arguments browse-url-epiphany-arguments
425   "*A list of strings to pass to Epiphany when it starts up.
426 Defaults to the value of `browse-url-epiphany-arguments' at the time
427 `browse-url' is loaded."
428 :type '(repeat (string :tag "Argument"))
429 :group 'browse-url)
430
431 (defcustom browse-url-seamonkey-new-window-is-tab nil
432   "*Whether to open up new windows in a tab or a new window.
433 If non-nil, then open the URL in a new tab rather than a new window if
434 `browse-url-seamonkey' is asked to open it in a new window."
435   :type 'boolean
436   :group 'browse-url)
437
438 (defcustom browse-url-mozilla-new-window-is-tab nil
439   "*Whether to open up new windows in a tab or a new window.
440 If non-nil, then open the URL in a new tab rather than a new window if
441 `browse-url-mozilla' is asked to open it in a new window."
442   :type 'boolean
443   :group 'browse-url)
444
445 (defcustom browse-url-firefox-new-window-is-tab nil
446   "*Whether to open up new windows in a tab or a new window.
447 If non-nil, then open the URL in a new tab rather than a new window if
448 `browse-url-firefox' is asked to open it in a new window."
449   :type 'boolean
450   :group 'browse-url)
451
452 (defcustom browse-url-galeon-new-window-is-tab nil
453   "*Whether to open up new windows in a tab or a new window.
454 If non-nil, then open the URL in a new tab rather than a new window if
455 `browse-url-galeon' is asked to open it in a new window."
456   :type 'boolean
457   :group 'browse-url)
458
459 (defcustom browse-url-epiphany-new-window-is-tab nil
460   "*Whether to open up new windows in a tab or a new window.
461 If non-nil, then open the URL in a new tab rather than a new window if
462 `browse-url-epiphany' is asked to open it in a new window."
463 :type 'boolean
464 :group 'browse-url)
465
466 (defcustom browse-url-netscape-new-window-is-tab nil
467   "*Whether to open up new windows in a tab or a new window.
468 If non-nil, then open the URL in a new tab rather than a new window if
469 `browse-url-netscape' is asked to open it in a new window."
470   :type 'boolean
471   :group 'browse-url)
472
473 ;;;###autoload
474 (defcustom browse-url-new-window-flag nil
475   "*If non-nil, always open a new browser window with appropriate browsers.
476 Passing an interactive argument to \\[browse-url], or specific browser
477 commands reverses the effect of this variable.  Requires Netscape version
478 1.1N or later or XMosaic version 2.5 or later if using those browsers."
479   :type 'boolean
480   :group 'browse-url)
481
482 ;; XEmacs backwards compatibility
483 ;;;###autoload
484 (defvaralias 'browse-url-new-window-p 'browse-url-new-window-flag)
485    
486 (defcustom browse-url-mosaic-program "xmosaic"
487   "*The name by which to invoke Mosaic (or mMosaic)."
488   :type 'string
489   :group 'browse-url)
490
491 (defcustom browse-url-mosaic-arguments nil
492   "*A list of strings to pass to Mosaic as arguments."
493   :type '(repeat (string :tag "Argument"))
494   :group 'browse-url)
495
496 (defcustom browse-url-mosaic-pidfile "~/.mosaicpid"
497   "*The name of the pidfile created by Mosaic."
498   :type 'string
499   :group 'browse-url)
500
501 (defcustom browse-url-filename-alist
502   (\`                                   ; Backquote syntax won't work.
503    (("^/\\(ftp@\\|anonymous@\\)?\\([^:]+\\):/*" . "ftp://\\2/")
504     ;; The above loses the username to avoid the browser prompting for
505     ;; it in anonymous cases.  If it's not anonymous the next regexp
506     ;; applies.
507     ("^/\\([^:@]+@\\)?\\([^:]+\\):/*" . "ftp://\\1\\2/")
508     (,@ (if (memq system-type '(windows-nt ms-dos cygwin32)) ;; XEmacs change
509             '(("^\\([a-zA-Z]:\\)[\\/]" . "file:\\1/")
510               ("^[\\/][\\/]+" . "file://"))))
511     ("^/+" . "file:/")))
512   "An alist of (REGEXP . STRING) pairs used by `browse-url-of-file'.
513 Any substring of a filename matching one of the REGEXPs is replaced by
514 the corresponding STRING using `replace-match', not treating STRING
515 literally.  All pairs are applied in the order given.  The default
516 value converts ange-ftp/EFS-style file names into ftp URLs and prepends
517 `file:' to any file name beginning with `/'.
518
519 For example, adding to the default a specific translation of an ange-ftp
520 address to an HTTP URL:
521
522     (setq browse-url-filename-alist
523           '((\"/webmaster@webserver:/home/www/html/\" .
524              \"http://www.acme.co.uk/\")
525             (\"^/\\(ftp@\\|anonymous@\\)?\\([^:]+\\):/*\" . \"ftp://\\2/\")
526             (\"^/\\([^:@]+@\\)?\\([^:]+\\):/*\" . \"ftp://\\1\\2/\")
527             (\"^/+\" . \"file:/\")))
528 "
529   :type '(repeat (cons :format "%v"
530                        (regexp :tag "Regexp")
531                        (string :tag "Replacement")))
532   :group 'browse-url)
533
534 ;;;###autoload
535 (defcustom browse-url-save-file nil
536   "*If non-nil, save the buffer before displaying its file.
537 Used by the `browse-url-of-file' command."
538   :type 'boolean
539   :group 'browse-url)
540
541 (defcustom browse-url-of-file-hook nil
542   "*Run after `browse-url-of-file' has asked a browser to load a file.
543
544 Set this to `browse-url-netscape-reload' to force Netscape to load the
545 file rather than displaying a cached copy."
546   :type 'hook
547   :options '(browse-url-netscape-reload)
548   :group 'browse-url)
549
550 (defcustom browse-url-CCI-port 3003
551   "*Port to access XMosaic via CCI.
552 This can be any number between 1024 and 65535 but must correspond to
553 the value set in the browser."
554   :type 'integer
555   :group 'browse-url)
556
557 (defcustom browse-url-CCI-host "localhost"
558   "*Host to access XMosaic via CCI.
559 This should be the host name of the machine running XMosaic with CCI
560 enabled.  The port number should be set in `browse-url-CCI-port'."
561   :type 'string
562   :group 'browse-url)
563
564 (defvar browse-url-temp-file-name nil)
565 (make-variable-buffer-local 'browse-url-temp-file-name)
566
567 (defcustom browse-url-xterm-program "xterm"
568   "*The name of the terminal emulator used by `browse-url-lynx-xterm'.
569 This might, for instance, be a separate colour version of xterm."
570   :type 'string
571   :group 'browse-url)
572
573 (defcustom browse-url-xterm-args nil
574   "*A list of strings defining options for `browse-url-xterm-program'.
575 These might set its size, for instance."
576   :type '(repeat (string :tag "Argument"))
577   :group 'browse-url)
578
579 (defcustom browse-url-lynx-emacs-args (and (not window-system)
580                                            '("-show_cursor"))
581   "*A list of strings defining options for Lynx in an Emacs buffer.
582
583 The default is none in a window system, otherwise `-show_cursor' to
584 indicate the position of the current link in the absence of
585 highlighting, assuming the normal default for showing the cursor."
586   :type '(repeat (string :tag "Argument"))
587   :group 'browse-url)
588
589 (defcustom browse-url-gnudoit-program "gnuclient" ;; XEmacs
590   "*The name of the `gnudoit' program.
591 Used by `browse-url-w3-gnudoit' and `browse-url-w3m-gnudoit'."
592   :type 'string
593   :group 'browse-url)
594
595 (defcustom browse-url-gnudoit-args '("-batch" "-eval") ;; XEmacs
596   "*A list of strings defining options for `browse-url-gnudoit-program'.
597 These might set the port, for instance."
598   :type '(repeat (string :tag "Argument"))
599   :group 'browse-url)
600
601 ;;;###autoload
602 (defcustom browse-url-generic-program nil
603   "*The name of the browser program used by `browse-url-generic'."
604   :type '(choice string (const :tag "None" nil))
605   :group 'browse-url)
606
607 (defcustom browse-url-generic-args nil
608   "*A list of strings defining options for `browse-url-generic-program'."
609   :type '(repeat (string :tag "Argument"))
610   :group 'browse-url)
611
612 (defcustom browse-url-temp-dir (temp-directory) ;; XEmacs change
613   "*The name of a directory for browse-url's temporary files.
614 Such files are generated by functions like `browse-url-of-region'.
615 You might want to set this to somewhere with restricted read permissions
616 for privacy's sake."
617   :type 'string
618   :group 'browse-url)
619
620 (defcustom browse-url-netscape-version
621   3
622   "*The version of Netscape you are using.
623 This affects how URL reloading is done; the mechanism changed
624 incompatibly at version 4."
625   :type 'number
626   :group 'browse-url)
627
628 (defcustom browse-url-lynx-input-field 'avoid
629   "*Action on selecting an existing Lynx buffer at an input field.
630 What to do when sending a new URL to an existing Lynx buffer in Emacs
631 if the Lynx cursor is on an input field (in which case the `g' command
632 would be entered as data).  Such fields are recognized by the
633 underlines ____.  Allowed values: nil: disregard it, 'warn: warn the
634 user and don't emit the URL, 'avoid: try to avoid the field by moving
635 down (this *won't* always work)."
636   :type '(choice (const :tag "Move to try to avoid field" :value avoid)
637                  (const :tag "Disregard" :value nil)
638                  (const :tag "Warn, don't emit URL" :value warn))
639   :group 'browse-url)
640
641 (defcustom browse-url-lynx-input-attempts 10
642   "*How many times to try to move down from a series of lynx input fields."
643 :type 'integer
644 :group 'browse-url)
645
646 (defcustom browse-url-lynx-input-delay 0.2
647   "*How many seconds to wait for lynx between moves down from an input field."
648 :type 'number
649 :group 'browse-url)
650
651 (defcustom browse-url-kde-program "kfmclient"
652   "*The name by which to invoke the KDE web browser."
653   :type 'string
654   :group 'browse-url)
655
656 (defcustom browse-url-kde-args '("openURL")
657   "*A list of strings defining options for `browse-url-kde-program'."
658   :type '(repeat (string :tag "Argument"))
659   :group 'browse-url)
660
661 (defcustom browse-url-opera-program "opera"
662   "*The name by which to invoke Opera."
663   :type 'string
664   :group 'browse-url)
665
666 (defcustom browse-url-opera-arguments '()
667   "*A list of strings to pass to Opera as arguments."
668   :type '(repeat (string :tag "Argument"))
669   :group 'browse-url)
670
671 (defcustom browse-url-opera-startup-arguments browse-url-opera-arguments
672   "*A list of strings to pass to Opera when it starts up.
673 Defaults to the value of `browse-url-opera-arguments' at the time
674 `browse-url' is loaded."
675   :type '(repeat (string :tag "Argument"))
676   :group 'browse-url)
677
678 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
679 ;; URL input
680
681 (defun browse-url-url-at-point ()
682   (let ((url (thing-at-point 'url)))
683     (unless (zerop (length url)) ;; XEmacs bug workaround,
684                                  ;; `set-text-properties' in XEmacs <=
685                                  ;; 21.4.6 doesn't handle 0-0.
686       (set-text-properties 0 (length url) nil url))
687     url))
688
689 ;; Having this as a separate function called by the browser-specific
690 ;; functions allows them to be stand-alone commands, making it easier
691 ;; to switch between browsers.
692
693 (defun browse-url-interactive-arg (prompt)
694   "Read a URL from the minibuffer, prompting with PROMPT.
695 Default to the URL at or before point.  If invoked with a mouse button,
696 set point to the position clicked first.  Return a list for use in
697 `interactive' containing the URL and `browse-url-new-window-flag' or its
698 negation if a prefix argument was given."
699   (let ((event (elt (this-command-keys) 0)))
700     (and (listp event) (mouse-set-point event)))
701   (list (read-string prompt (browse-url-url-at-point))
702         (not (eq (null browse-url-new-window-flag)
703                  (null current-prefix-arg)))))
704
705 ;; interactive-p needs to be called at a function's top-level, hence
706 ;; the macro.
707 (defmacro browse-url-maybe-new-window (arg)
708   `(if (not (interactive-p))
709        ,arg
710      browse-url-new-window-flag))
711
712 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
713 ;; Browse current buffer
714
715 ;;;###autoload
716 (defun browse-url-of-file (&optional file)
717   "Ask a WWW browser to display FILE.
718 Display the current buffer's file if FILE is nil or if called
719 interactively.  Turn the filename into a URL with function
720 `browse-url-file-url'.  Pass the URL to a browser using the
721 `browse-url' function then run `browse-url-of-file-hook'."
722   (interactive)
723   (or file
724       (setq file (buffer-file-name))
725       (error "Current buffer has no file"))
726   (let ((buf (get-file-buffer file)))
727     (if buf
728         (save-excursion
729           (set-buffer buf)
730           (cond ((not (buffer-modified-p)))
731                 (browse-url-save-file (save-buffer))
732                 (t (message "%s modified since last save" file))))))
733   (browse-url (browse-url-file-url file))
734   (run-hooks 'browse-url-of-file-hook))
735
736 (defun browse-url-file-url (file)
737   "Return the URL corresponding to FILE.
738 Use variable `browse-url-filename-alist' to map filenames to URLs."
739   ;; URL-encode special chars, do % first
740   (let ((s 0))
741     (while (setq s (string-match "%" file s))
742       (setq file (replace-match "%25" t t file)
743             s (1+ s))))
744   (while (string-match "[*\"()',=;? ]" file)
745     (let ((enc (format "%%%x" (aref file (match-beginning 0)))))
746       (setq file (replace-match enc t t file))))
747   (dolist (map browse-url-filename-alist)
748     (when (and map (string-match (car map) file))
749       (setq file (replace-match (cdr map) t nil file))))
750   file)
751
752 ;;;###autoload
753 (defun browse-url-of-buffer (&optional buffer)
754   "Ask a WWW browser to display BUFFER.
755 Display the current buffer if BUFFER is nil.  Display only the
756 currently visible part of BUFFER (from a temporary file) if buffer is
757 narrowed."
758   (interactive)
759   (save-excursion
760     (and buffer (set-buffer buffer))
761     (let ((file-name
762            ;; Ignore real name if restricted
763            (and (= (- (point-max) (point-min)) (buffer-size))
764                 (or buffer-file-name
765                     (and (boundp 'dired-directory) dired-directory)))))
766       (or file-name
767           (progn
768             (or browse-url-temp-file-name
769                 (setq browse-url-temp-file-name
770                       (convert-standard-filename
771                        (make-temp-name ;; XEmacs doesn't have make-temp-file
772                         (expand-file-name "burl" browse-url-temp-dir)))))
773             (setq file-name browse-url-temp-file-name)
774             (write-region (point-min) (point-max) file-name nil 'no-message)))
775       (browse-url-of-file file-name))))
776
777 (defun browse-url-delete-temp-file (&optional temp-file-name)
778   "Delete `browse-url-temp-file-name' from the file system.
779 If the optional argument TEMP-FILE-NAME is non-nil, delete it instead."
780   (let ((file-name (or temp-file-name browse-url-temp-file-name)))
781     (if (and file-name (file-exists-p file-name))
782         (delete-file file-name))))
783
784 (add-hook 'kill-buffer-hook 'browse-url-delete-temp-file)
785
786 ;;;###autoload
787 (defun browse-url-of-dired-file ()
788   "In Dired, ask a WWW browser to display the file named on this line."
789   (interactive)
790   (browse-url-of-file (dired-get-filename)))
791
792 ;;;###autoload
793 (defun browse-url-of-region (min max)
794   "Ask a WWW browser to display the current region."
795   (interactive "r")
796   (save-excursion
797     (save-restriction
798       (narrow-to-region min max)
799       (browse-url-of-buffer))))
800
801 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
802 ;; Browser-independent commands
803
804 ;; A generic command to call the current browse-url-browser-function
805
806 ;;;###autoload
807 (defun browse-url (url &rest args)
808   "Ask a WWW browser to load URL.
809 Prompts for a URL, defaulting to the URL at or before point.  Variable
810 `browse-url-browser-function' says which browser to use."
811   (interactive (browse-url-interactive-arg "URL: "))
812   (unless (interactive-p)
813     (setq args (or args (list browse-url-new-window-flag))))
814   (if (functionp browse-url-browser-function)
815       (apply browse-url-browser-function url args)
816     ;; The `function' can be an alist; look down it for first match
817     ;; and apply the function (which might be a lambda).
818     (catch 'done
819       (dolist (bf browse-url-browser-function)
820         (when (string-match (car bf) url)
821           (apply (cdr bf) url args)
822           (throw 'done t)))
823       (error "No browse-url-browser-function matching URL %s"
824              url))))
825
826 ;;;###autoload
827 (defun browse-url-at-point (&optional arg)
828   "Ask a WWW browser to load the URL at or before point.
829 Doesn't let you edit the URL like `browse-url'.  Variable
830 `browse-url-browser-function' says which browser to use."
831   (interactive "P")
832   (let ((url (browse-url-url-at-point)))
833     (if url
834         (browse-url url (if arg
835                             (not browse-url-new-window-flag)
836                           browse-url-new-window-flag))
837       (error "No URL found"))))
838
839 ;;;###autoload
840 (defun browse-url-at-mouse (event)
841   "Ask a WWW browser to load a URL clicked with the mouse.
842 The URL is the one around or before the position of the mouse click
843 but point is not changed.  Doesn't let you edit the URL like
844 `browse-url'.  Variable `browse-url-browser-function' says which browser
845 to use."
846   (interactive "e")
847   (save-excursion
848     (mouse-set-point event)
849     ;; This handles browse-url-new-window-flag properly
850     ;; when it gets no arg.
851     (browse-url-at-point)))
852
853 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
854 ;; Browser-specific commands
855
856 ;; --- Default MS-Windows browser ---
857
858 (defun browse-url-default-windows-browser (url &optional new-window)
859   (interactive (browse-url-interactive-arg "URL: "))
860   (if (featurep 'xemacs) ;; XEmacs change
861       (mswindows-shell-execute "open" url)
862     (w32-shell-execute "open" url)))
863
864 (defun browse-url-default-macosx-browser (url &optional new-window)
865   (interactive (browse-url-interactive-arg "URL: "))
866   (start-process (concat "open " url) nil "open" url))
867
868 ;; XEmacs addition
869 ;;;###autoload
870 (defcustom browse-url-xdg-open-program "xdg-open"
871   "*The name by which to invoke xdg-open."
872   :type 'string
873   :group 'browse-url)
874
875 ;; XEmacs addition
876 ;;;###autoload
877 (defun browse-url-default-xdg-browser (url &optional new-window)
878   (interactive (browse-url-interactive-arg "URL: "))
879   (let ((process-environment (browse-url-process-environment))
880         (process-connection-type nil))
881     (start-process (concat browse-url-xdg-open-program " " url) nil
882                    browse-url-xdg-open-program url)))
883
884 ;; --- Netscape ---
885
886 (defun browse-url-process-environment ()
887   "Set DISPLAY in the environment to the X display the browser will use.
888 This is either the value of variable `browse-url-browser-display' if
889 non-nil, or the same display as Emacs if different from the current
890 environment, otherwise just use the current environment."
891   (let ((display (or browse-url-browser-display (browse-url-emacs-display))))
892     (if display
893         (cons (concat "DISPLAY=" display) process-environment)
894       process-environment)))
895
896 (defun browse-url-emacs-display ()
897   "Return the X display Emacs is running on.
898 This is nil if the display is the same as the DISPLAY environment variable.
899
900 Actually Emacs could be using several displays; this just returns the
901 one showing the selected frame."
902   (let ((display (cdr-safe (assq 'display (frame-parameters)))))
903     (and (not (equal display (getenv "DISPLAY")))
904          display)))
905
906 ;;;###autoload
907 (defun browse-url-default-browser (url &rest args)
908   "Find a suitable browser and ask it to load URL.
909 Default to the URL around or before point.
910
911 When called interactively, if variable `browse-url-new-window-flag' is
912 non-nil, load the document in a new window, if possible, otherwise use
913 a random existing one.  A non-nil interactive prefix argument reverses
914 the effect of `browse-url-new-window-flag'.
915
916 When called non-interactively, optional second argument NEW-WINDOW is
917 used instead of `browse-url-new-window-flag'.
918
919 The order attempted is freedesktop.org default, gnome-moz-remote, Mozilla,
920 Firefox, SeaMonkey, Galeon, Konqueror, Netscape, Opera, Mosaic, IXI Mosaic,
921 emacs-w3m, Lynx in an xterm, MMM, and then W3."
922   (apply
923     (cond
924      ;; XEmacs addition
925      ((executable-find browse-url-xdg-open-program)
926       'browse-url-default-xdg-browser)
927      ((executable-find browse-url-gnome-moz-program) 'browse-url-gnome-moz)
928      ((executable-find browse-url-mozilla-program) 'browse-url-mozilla)
929      ((executable-find browse-url-firefox-program) 'browse-url-firefox)
930      ((executable-find browse-url-seamonkey-program) 'browse-url-seamonkey)
931      ((executable-find browse-url-galeon-program) 'browse-url-galeon)
932      ((executable-find browse-url-kde-program) 'browse-url-kde)
933      ((executable-find browse-url-netscape-program) 'browse-url-netscape)
934      ((executable-find browse-url-opera-program) 'browse-url-opera)
935      ((executable-find browse-url-mosaic-program) 'browse-url-mosaic)
936      ((executable-find "tellw3b") 'browse-url-iximosaic)
937      ((fboundp 'w3m-goto-url-new-session) 'browse-url-w3m)
938      ((executable-find browse-url-xterm-program) 'browse-url-lynx-xterm)
939      ((executable-find "mmm") 'browse-url-mmm)
940      (t 'browse-url-w3))
941      url args))
942
943 ;;;###autoload
944 (defun browse-url-netscape (url &optional new-window)
945   "Ask the Netscape WWW browser to load URL.
946 Default to the URL around or before point.  The strings in variable
947 `browse-url-netscape-arguments' are also passed to Netscape.
948
949 When called interactively, if variable `browse-url-new-window-flag' is
950 non-nil, load the document in a new Netscape window, otherwise use a
951 random existing one.  A non-nil interactive prefix argument reverses
952 the effect of `browse-url-new-window-flag'.
953
954 If `browse-url-netscape-new-window-is-tab' is non-nil, then
955 whenever a document would otherwise be loaded in a new window, it
956 is loaded in a new tab in an existing window instead.
957
958 When called non-interactively, optional second argument NEW-WINDOW is
959 used instead of `browse-url-new-window-flag'."
960   (interactive (browse-url-interactive-arg "URL: "))
961   ;; URL encode any `confusing' characters in the URL.  This needs to
962   ;; include at least commas; presumably also close parens.
963   (while (string-match "[,)]" url)
964     (setq url (replace-match
965                (format "%%%x" (string-to-char (match-string 0 url))) t t url)))
966   (let* ((process-environment (browse-url-process-environment))
967          (process
968           (apply 'start-process
969                  (concat "netscape " url) nil
970                  browse-url-netscape-program
971                  (append
972                   browse-url-netscape-arguments
973                   (if (eq (console-type) 'mswindows) ;; XEmacs change
974                       (list url)
975                     (append
976                      (if new-window '("-noraise"))
977                      (list "-remote"
978                            (concat "openURL(" url
979                                    (if (browse-url-maybe-new-window
980                                         new-window)
981                                        (if browse-url-netscape-new-window-is-tab
982                                            ",new-tab"
983                                          ",new-window"))
984                                    ")"))))))))
985     (set-process-sentinel process
986                           `(lambda (process change)
987                              (browse-url-netscape-sentinel process ,url)))))
988
989 (defun browse-url-netscape-sentinel (process url)
990   "Handle a change to the process communicating with Netscape."
991   (or (eq (process-exit-status process) 0)
992       (let* ((process-environment (browse-url-process-environment)))
993         ;; Netscape not running - start it
994         (message "Starting Netscape...")
995         (apply 'start-process (concat "netscape" url) nil
996                browse-url-netscape-program
997                (append browse-url-netscape-startup-arguments (list url))))))
998
999 (defun browse-url-netscape-reload ()
1000   "Ask Netscape to reload its current document.
1001 How depends on `browse-url-netscape-version'."
1002   (interactive)
1003   ;; Backwards incompatibility reported by
1004   ;; <peter.kruse@psychologie.uni-regensburg.de>.
1005   (browse-url-netscape-send (if (>= browse-url-netscape-version 4)
1006                                 "xfeDoCommand(reload)"
1007                                 "reload")))
1008
1009 (defun browse-url-netscape-send (command)
1010   "Send a remote control command to Netscape."
1011   (let* ((process-environment (browse-url-process-environment)))
1012     (apply 'start-process "netscape" nil
1013            browse-url-netscape-program
1014            (append browse-url-netscape-arguments
1015                    (list "-remote" command)))))
1016
1017 ;;;###autoload
1018 (defun browse-url-seamonkey (url &optional new-window)
1019   "Ask the SeaMonkey WWW browser to load URL.
1020 Default to the URL around or before point.  The strings in variable
1021 `browse-url-seamonkey-arguments' are also passed to SeaMonkey.
1022
1023 When called interactively, if variable `browse-url-new-window-flag' is
1024 non-nil, load the document in a new SeaMonkey window, otherwise use a
1025 random existing one.  A non-nil interactive prefix argument reverses
1026 the effect of `browse-url-new-window-flag'.
1027
1028 If `browse-url-seamonkey-new-window-is-tab' is non-nil, then whenever a
1029 document would otherwise be loaded in a new window, it is loaded in a
1030 new tab in an existing window instead.
1031
1032 When called non-interactively, optional second argument NEW-WINDOW is
1033 used instead of `browse-url-new-window-flag'.
1034
1035 On MS-Windows systems the optional `new-window' parameter is ignored.
1036 SeaMonkey for Windows does not support the \"-remote\" command line
1037 parameter. Therefore the `browse-url-new-window-flag', 
1038 `browse-url-new-window-flag' and `browse-url-seamonkey-new-window-is-tab'
1039 are ignored as well. SeaMonkey on Windows will always open the
1040 requested URL in a new window."
1041   (interactive (browse-url-interactive-arg "URL: "))
1042   ;; URL encode any `confusing' characters in the URL.  This needs to
1043   ;; include at least commas; presumably also close parens.
1044   (while (string-match "[,)]" url)
1045     (setq url (replace-match
1046                (format "%%%x" (string-to-char (match-string 0 url))) t t url)))
1047   (let* ((process-environment (browse-url-process-environment))
1048          (process
1049           (apply 'start-process
1050                  (concat "seamonkey " url) nil
1051                  browse-url-seamonkey-program
1052                  (append
1053                   browse-url-seamonkey-arguments
1054           (if (or (featurep 'dos-w32)
1055                   (string-match "win32" system-configuration))
1056               (list url)
1057             (list "-remote"
1058                   (concat "openURL("
1059                           url
1060                           (if (browse-url-maybe-new-window
1061                                new-window)
1062                               (if browse-url-seamonkey-new-window-is-tab
1063                                   ",new-tab"
1064                                 ",new-window"))
1065                           ")")))))))
1066     (set-process-sentinel process
1067                           `(lambda (process change)
1068                              (browse-url-seamonkey-sentinel process ,url)))))
1069
1070 (defun browse-url-seamonkey-sentinel (process url)
1071   "Handle a change to the process communicating with SeaMonkey."
1072   (or (eq (process-exit-status process) 0)
1073       (let* ((process-environment (browse-url-process-environment)))
1074         ;; SeaMonkey is not running - start it
1075         (message "Starting SeaMonkey...")
1076         (apply 'start-process (concat "seamonkey " url) nil
1077                browse-url-seamonkey-program
1078                (append browse-url-seamonkey-startup-arguments (list url))))))
1079
1080 ;;;###autoload
1081 (defun browse-url-mozilla (url &optional new-window)
1082   "Ask the Mozilla WWW browser to load URL.
1083 Default to the URL around or before point.  The strings in variable
1084 `browse-url-mozilla-arguments' are also passed to Mozilla.
1085
1086 When called interactively, if variable `browse-url-new-window-flag' is
1087 non-nil, load the document in a new Mozilla window, otherwise use a
1088 random existing one.  A non-nil interactive prefix argument reverses
1089 the effect of `browse-url-new-window-flag'.
1090
1091 If `browse-url-mozilla-new-window-is-tab' is non-nil, then whenever a
1092 document would otherwise be loaded in a new window, it is loaded in a
1093 new tab in an existing window instead.
1094
1095 When called non-interactively, optional second argument NEW-WINDOW is
1096 used instead of `browse-url-new-window-flag'.
1097
1098 On MS-Windows systems the optional `new-window' parameter is ignored.
1099 Mozilla for Windows does not support the \"-remote\" command line
1100 parameter. Therefore the `browse-url-new-window-flag', 
1101 `browse-url-new-window-flag' and `browse-url-mozilla-new-window-is-tab'
1102 are ignored as well. Mozilla on Windows will always open the
1103 requested URL in a new window."
1104   (interactive (browse-url-interactive-arg "URL: "))
1105   ;; URL encode any `confusing' characters in the URL.  This needs to
1106   ;; include at least commas; presumably also close parens.
1107   (while (string-match "[,)]" url)
1108     (setq url (replace-match
1109                (format "%%%x" (string-to-char (match-string 0 url))) t t url)))
1110   (let* ((process-environment (browse-url-process-environment))
1111          (process
1112           (apply 'start-process
1113                  (concat "mozilla " url) nil
1114                  browse-url-mozilla-program
1115                  (append
1116                   browse-url-mozilla-arguments
1117           (if (or (featurep 'dos-w32)
1118                   (string-match "win32" system-configuration))
1119               (list url)
1120             (list "-remote"
1121                   (concat "openURL("
1122                           url
1123                           (if (browse-url-maybe-new-window
1124                                new-window)
1125                               (if browse-url-mozilla-new-window-is-tab
1126                                   ",new-tab"
1127                                 ",new-window"))
1128                           ")")))))))
1129     (set-process-sentinel process
1130                           `(lambda (process change)
1131                              (browse-url-mozilla-sentinel process ,url)))))
1132
1133 (defun browse-url-mozilla-sentinel (process url)
1134   "Handle a change to the process communicating with Mozilla."
1135   (or (eq (process-exit-status process) 0)
1136       (let* ((process-environment (browse-url-process-environment)))
1137         ;; Mozilla is not running - start it
1138         (message "Starting Mozilla...")
1139         (apply 'start-process (concat "mozilla " url) nil
1140                browse-url-mozilla-program
1141                (append browse-url-mozilla-startup-arguments (list url))))))
1142
1143 ;;;###autoload
1144 (defun browse-url-firefox (url &optional new-window)
1145   "Ask the Firefox WWW browser to load URL.
1146 Default to the URL around or before point.  The strings in variable
1147 `browse-url-firefox-arguments' are also passed to Firefox.
1148
1149 When called interactively, if variable `browse-url-new-window-flag' is
1150 non-nil, load the document in a new Firefox window, otherwise use a
1151 random existing one.  A non-nil interactive prefix argument reverses
1152 the effect of `browse-url-new-window-flag'.
1153
1154 If `browse-url-firefox-new-window-is-tab' is non-nil, then whenever a
1155 document would otherwise be loaded in a new window, it is loaded in a
1156 new tab in an existing window instead.
1157
1158 When called non-interactively, optional second argument NEW-WINDOW is
1159 used instead of `browse-url-new-window-flag'.
1160
1161 On MS-Windows systems the optional `new-window' parameter is ignored.
1162 Firefox for Windows does not support the \"-remote\" command line
1163 parameter. Therefore the `browse-url-new-window-flag', 
1164 `browse-url-new-window-flag' and `browse-url-firefox-new-window-is-tab'
1165 are ignored as well. Firefox on Windows will always open the
1166 requested URL in a new window."
1167   (interactive (browse-url-interactive-arg "URL: "))
1168   ;; URL encode any `confusing' characters in the URL.  This needs to
1169   ;; include at least commas; presumably also close parens.
1170   (while (string-match "[,)]" url)
1171     (setq url (replace-match
1172                (format "%%%x" (string-to-char (match-string 0 url))) t t url)))
1173   (let* ((process-environment (browse-url-process-environment))
1174          (process
1175           (apply 'start-process
1176                  (concat "firefox " url) nil
1177                  browse-url-firefox-program
1178                  (append
1179                   browse-url-firefox-arguments
1180           (if (or (featurep 'dos-w32)
1181                   (string-match "win32" system-configuration))
1182               (list url)
1183             (list "-remote"
1184                   (concat "openURL("
1185                           url
1186                           (if (browse-url-maybe-new-window
1187                                new-window)
1188                               (if browse-url-firefox-new-window-is-tab
1189                                   ",new-tab"
1190                                 ",new-window"))
1191                           ")")))))))
1192     (set-process-sentinel process
1193                           `(lambda (process change)
1194                              (browse-url-firefox-sentinel process ,url)))))
1195
1196 (defun browse-url-firefox-sentinel (process url)
1197   "Handle a change to the process communicating with Firefox."
1198   (or (eq (process-exit-status process) 0)
1199       (let* ((process-environment (browse-url-process-environment)))
1200         ;; Firefox is not running - start it
1201         (message "Starting Firefox...")
1202         (apply 'start-process (concat "firefox " url) nil
1203                browse-url-firefox-program
1204                (append browse-url-firefox-startup-arguments (list url))))))
1205
1206 ;;;###autoload
1207 (defun browse-url-galeon (url &optional new-window)
1208   "Ask the Galeon WWW browser to load URL.
1209 Default to the URL around or before point.  The strings in variable
1210 `browse-url-galeon-arguments' are also passed to Galeon.
1211
1212 When called interactively, if variable `browse-url-new-window-flag' is
1213 non-nil, load the document in a new Galeon window, otherwise use a
1214 random existing one.  A non-nil interactive prefix argument reverses
1215 the effect of `browse-url-new-window-flag'.
1216
1217 If `browse-url-galeon-new-window-is-tab' is non-nil, then whenever a
1218 document would otherwise be loaded in a new window, it is loaded in a
1219 new tab in an existing window instead.
1220
1221 When called non-interactively, optional second argument NEW-WINDOW is
1222 used instead of `browse-url-new-window-flag'."
1223   (interactive (browse-url-interactive-arg "URL: "))
1224   ;; URL encode any `confusing' characters in the URL.  This needs to
1225   ;; include at least commas; presumably also close parens.
1226   (while (string-match "[,)]" url)
1227     (setq url (replace-match
1228                (format "%%%x" (string-to-char (match-string 0 url))) t t url)))
1229   (let* ((process-environment (browse-url-process-environment))
1230          (process (apply 'start-process
1231                          (concat "galeon " url)
1232                          nil
1233                          browse-url-galeon-program
1234                          (append
1235                           browse-url-galeon-arguments
1236                           (if (browse-url-maybe-new-window new-window)
1237                               (if browse-url-galeon-new-window-is-tab
1238                                   '("--new-tab")
1239                                 '("--new-window" "--noraise"))
1240                             '("--existing"))
1241                           (list url)))))
1242     (set-process-sentinel process
1243                           `(lambda (process change)
1244                              (browse-url-galeon-sentinel process ,url)))))
1245
1246 (defun browse-url-galeon-sentinel (process url)
1247   "Handle a change to the process communicating with Galeon."
1248   (or (eq (process-exit-status process) 0)
1249       (let* ((process-environment (browse-url-process-environment)))
1250         ;; Galeon is not running - start it
1251         (message "Starting Galeon...")
1252         (apply 'start-process (concat "galeon " url) nil
1253                browse-url-galeon-program
1254                (append browse-url-galeon-startup-arguments (list url))))))
1255
1256 (defun browse-url-epiphany (url &optional new-window)
1257   "Ask the Epiphany WWW browser to load URL.
1258 Default to the URL around or before point.  The strings in variable
1259 `browse-url-galeon-arguments' are also passed to Epiphany.
1260
1261 When called interactively, if variable `browse-url-new-window-flag' is
1262 non-nil, load the document in a new Epiphany window, otherwise use a
1263 random existing one.  A non-nil interactive prefix argument reverses
1264 the effect of `browse-url-new-window-flag'.
1265
1266 If `browse-url-epiphany-new-window-is-tab' is non-nil, then whenever a
1267 document would otherwise be loaded in a new window, it is loaded in a
1268 new tab in an existing window instead.
1269
1270 When called non-interactively, optional second argument NEW-WINDOW is
1271 used instead of `browse-url-new-window-flag'."
1272   (interactive (browse-url-interactive-arg "URL: "))
1273   ;; URL encode any `confusing' characters in the URL.  This needs to
1274   ;; include at least commas; presumably also close parens.
1275   (while (string-match "[,)]" url)
1276     (setq url (replace-match
1277                (format "%%%x" (string-to-char (match-string 0 url))) t t url)))
1278   (let* ((process-environment (browse-url-process-environment))
1279          (process (apply 'start-process
1280                          (concat "epiphany " url)
1281                          nil
1282                          browse-url-epiphany-program
1283                          (append
1284                           browse-url-epiphany-arguments
1285                           (if (browse-url-maybe-new-window new-window)
1286                               (if browse-url-epiphany-new-window-is-tab
1287                                   '("--new-tab")
1288                                 '("--new-window" "--noraise"))
1289                             '("--existing"))
1290                           (list url)))))
1291     (set-process-sentinel process
1292                           `(lambda (process change)
1293                              (browse-url-epiphany-sentinel process ,url)))))
1294
1295 (defun browse-url-epiphany-sentinel (process url)
1296   "Handle a change to the process communicating with Epiphany."
1297   (or (eq (process-exit-status process) 0)
1298       (let* ((process-environment (browse-url-process-environment)))
1299         ;; Epiphany is not running - start it
1300         (message "Starting Epiphany...")
1301         (apply 'start-process (concat "epiphany " url) nil
1302                browse-url-epiphany-program
1303                (append browse-url-epiphany-startup-arguments (list url))))))
1304
1305 ;; GNOME means of invoking either Mozilla or Netscape.
1306 (defvar browse-url-gnome-moz-program "gnome-moz-remote")
1307 (defcustom browse-url-gnome-moz-arguments '()
1308   "*A list of strings passed to the GNOME mozilla viewer as arguments."
1309   :type '(repeat (string :tag "Argument"))
1310   :group 'browse-url)
1311
1312 ;;;###autoload
1313 (defun browse-url-gnome-moz (url &optional new-window)
1314   "Ask Mozilla/Netscape to load URL via the GNOME program `gnome-moz-remote'.
1315 Default to the URL around or before point.  The strings in variable
1316 `browse-url-gnome-moz-arguments' are also passed.
1317
1318 When called interactively, if variable `browse-url-new-window-flag' is
1319 non-nil, load the document in a new browser window, otherwise use an
1320 existing one.  A non-nil interactive prefix argument reverses the
1321 effect of `browse-url-new-window-flag'.
1322
1323 When called non-interactively, optional second argument NEW-WINDOW is
1324 used instead of `browse-url-new-window-flag'."
1325   (interactive (browse-url-interactive-arg "URL: "))
1326   (apply 'start-process (concat "gnome-moz-remote " url)
1327          nil
1328          browse-url-gnome-moz-program
1329          (append
1330           browse-url-gnome-moz-arguments
1331           (if (browse-url-maybe-new-window new-window)
1332             '("--newwin"))
1333           (list "--raise" url))))
1334
1335 ;; --- Mosaic ---
1336
1337 ;;;###autoload
1338 (defun browse-url-mosaic (url &optional new-window)
1339   "Ask the XMosaic WWW browser to load URL.
1340
1341 Default to the URL around or before point.  The strings in variable
1342 `browse-url-mosaic-arguments' are also passed to Mosaic and the
1343 program is invoked according to the variable
1344 `browse-url-mosaic-program'.
1345
1346 When called interactively, if variable `browse-url-new-window-flag' is
1347 non-nil, load the document in a new Mosaic window, otherwise use a
1348 random existing one.  A non-nil interactive prefix argument reverses
1349 the effect of `browse-url-new-window-flag'.
1350
1351 When called non-interactively, optional second argument NEW-WINDOW is
1352 used instead of `browse-url-new-window-flag'."
1353   (interactive (browse-url-interactive-arg "Mosaic URL: "))
1354   (let ((pidfile (expand-file-name browse-url-mosaic-pidfile))
1355         pid)
1356     (if (file-readable-p pidfile)
1357         (with-temp-buffer
1358           (insert-file-contents pidfile)
1359           (setq pid (read (current-buffer)))))
1360     (if (and (integerp pid) (zerop (signal-process pid 0))) ; Mosaic running
1361         (progn
1362           (with-temp-buffer
1363             (insert (if (browse-url-maybe-new-window new-window)
1364                         "newwin\n"
1365                       "goto\n")
1366                     url "\n")
1367             (if (file-exists-p (setq pidfile (format "/tmp/Mosaic.%d" pid)))
1368                 (delete-file pidfile))
1369             ;; http://debbugs.gnu.org/17428.  Use O_EXCL.
1370             (write-region nil nil pidfile nil 'silent nil 'excl))
1371           ;; Send signal SIGUSR to Mosaic
1372           (message "Signalling Mosaic...")
1373           (signal-process pid 'SIGUSR1)
1374           ;; Or you could try:
1375           ;; (call-process "kill" nil 0 nil "-USR1" (int-to-string pid))
1376           (message "Signalling Mosaic...done"))
1377       ;; Mosaic not running - start it
1378       (message "Starting Mosaic...")
1379       (apply 'start-process "xmosaic" nil browse-url-mosaic-program
1380              (append browse-url-mosaic-arguments (list url)))
1381       (message "Starting Mosaic...done"))))
1382
1383 ;; --- Grail ---
1384
1385 ;;;###autoload
1386 (defvar browse-url-grail
1387   (concat (or (getenv "GRAILDIR") "~/.grail") "/user/rcgrail.py")
1388   "Location of Grail remote control client script `rcgrail.py'.
1389 Typically found in $GRAILDIR/rcgrail.py, or ~/.grail/user/rcgrail.py.")
1390
1391 ;;;###autoload
1392 (defun browse-url-grail (url &optional new-window)
1393   "Ask the Grail WWW browser to load URL.
1394 Default to the URL around or before point.  Runs the program in the
1395 variable `browse-url-grail'."
1396   (interactive (browse-url-interactive-arg "Grail URL: "))
1397   (message "Sending URL to Grail...")
1398   (save-excursion
1399     (set-buffer (get-buffer-create " *Shell Command Output*"))
1400     (erase-buffer)
1401     ;; don't worry about this failing.
1402     (if (browse-url-maybe-new-window new-window)
1403         (call-process browse-url-grail nil 0 nil "-b" url)
1404       (call-process browse-url-grail nil 0 nil url))
1405     (message "Sending URL to Grail... done")))
1406
1407 ;; --- Mosaic using CCI ---
1408
1409 ;;;###autoload
1410 (defun browse-url-cci (url &optional new-window)
1411   "Ask the XMosaic WWW browser to load URL.
1412 Default to the URL around or before point.
1413
1414 This function only works for XMosaic version 2.5 or later.  You must
1415 select `CCI' from XMosaic's File menu, set the CCI Port Address to the
1416 value of variable `browse-url-CCI-port', and enable `Accept requests'.
1417
1418 When called interactively, if variable `browse-url-new-window-flag' is
1419 non-nil, load the document in a new browser window, otherwise use a
1420 random existing one.  A non-nil interactive prefix argument reverses
1421 the effect of `browse-url-new-window-flag'.
1422
1423 When called non-interactively, optional second argument NEW-WINDOW is
1424 used instead of `browse-url-new-window-flag'."
1425   (interactive (browse-url-interactive-arg "Mosaic URL: "))
1426   (open-network-stream "browse-url" " *browse-url*"
1427                        browse-url-CCI-host browse-url-CCI-port)
1428   ;; Todo: start browser if fails
1429   (process-send-string "browse-url"
1430                        (concat "get url (" url ") output "
1431                                (if (browse-url-maybe-new-window new-window)
1432                                    "new"
1433                                  "current")
1434                                "\r\n"))
1435   (process-send-string "browse-url" "disconnect\r\n")
1436   (delete-process "browse-url"))
1437
1438 ;; --- IXI Mosaic ---
1439
1440 ;;;###autoload
1441 (defun browse-url-iximosaic (url &optional new-window)
1442   ;; new-window ignored
1443   "Ask the IXIMosaic WWW browser to load URL.
1444 Default to the URL around or before point."
1445   (interactive (browse-url-interactive-arg "IXI Mosaic URL: "))
1446   (start-process "tellw3b" nil "tellw3b"
1447                  "-service WWW_BROWSER ixi_showurl " url))
1448
1449 ;; --- W3 ---
1450
1451 ;;;###autoload
1452 (defun browse-url-w3 (url &optional new-window)
1453   "Ask the w3 WWW browser to load URL.
1454 Default to the URL around or before point.
1455
1456 When called interactively, if variable `browse-url-new-window-flag' is
1457 non-nil, load the document in a new window.  A non-nil interactive
1458 prefix argument reverses the effect of `browse-url-new-window-flag'.
1459
1460 When called non-interactively, optional second argument NEW-WINDOW is
1461 used instead of `browse-url-new-window-flag'."
1462   (interactive (browse-url-interactive-arg "W3 URL: "))
1463   (require 'w3)                         ; w3-fetch-other-window not autoloaded
1464   (if (browse-url-maybe-new-window new-window)
1465       (w3-fetch-other-window url)
1466     (w3-fetch url)))
1467
1468 ;;;###autoload
1469 (defun browse-url-w3-gnudoit (url &optional new-window)
1470   ;; new-window ignored
1471   "Ask another Emacs running gnuserv to load the URL using the W3 browser.
1472 The `browse-url-gnudoit-program' program is used with options given by
1473 `browse-url-gnudoit-args'.  Default to the URL around or before point."
1474   (interactive (browse-url-interactive-arg "W3 URL: "))
1475     (apply 'start-process (concat "gnudoit:" url) nil
1476            browse-url-gnudoit-program
1477            (append browse-url-gnudoit-args
1478                    (list (concat "(w3-fetch \"" url "\")")
1479                          "(raise-frame)"))))
1480
1481 ;; --- emacs-w3m ---
1482
1483 ;;;###autoload
1484 (defun browse-url-w3m (url &optional new-window)
1485   "Ask the emacs-w3m WWW browser to load URL.
1486 Default to the URL around or before point.
1487
1488 When called interactively, if variable `browse-url-new-window-flag' is
1489 non-nil, load the document in a new window.  A non-nil interactive
1490 prefix argument reverses the effect of `browse-url-new-window-flag'.
1491
1492 When called non-interactively, optional second argument NEW-WINDOW is
1493 used instead of `browse-url-new-window-flag'."
1494   (interactive (browse-url-interactive-arg "W3M URL: "))
1495   (if (browse-url-maybe-new-window new-window)
1496       (progn
1497         (split-window) (other-window 1)))
1498   (w3m-goto-url-new-session url))
1499
1500 ;;;###autoload
1501 (defun browse-url-w3m-gnudoit (url &optional new-window)
1502   ;; new-window ignored
1503   "Ask the Emacs running gnuserv to load the URL using the emacs-w3m browser.
1504 The `browse-url-gnudoit-program' program is used with options given by
1505 `browse-url-gnudoit-args'.  Default to the URL around or before point."
1506   (interactive (browse-url-interactive-arg "W3M URL: "))
1507     (apply 'start-process (concat "gnudoit:" url) nil
1508            browse-url-gnudoit-program
1509            (append browse-url-gnudoit-args
1510                    (list (concat "(w3m-goto-url-new-session \"" url "\")")
1511                          "(raise-frame)"))))
1512
1513 ;; --- Lynx in an xterm ---
1514
1515 ;;;###autoload
1516 (defun browse-url-lynx-xterm (url &optional new-window)
1517   ;; new-window ignored
1518   "Ask the Lynx WWW browser to load URL.
1519 Default to the URL around or before point.  A new Lynx process is run
1520 in an Xterm window using the Xterm program named by `browse-url-xterm-program'
1521 with possible additional arguments `browse-url-xterm-args'."
1522   (interactive (browse-url-interactive-arg "Lynx URL: "))
1523   (apply #'start-process `(,(concat "lynx" url) nil ,browse-url-xterm-program
1524              ,@browse-url-xterm-args "-e" "lynx"
1525              ,url)))
1526
1527 ;; --- Lynx in an Emacs "term" window ---
1528
1529 ;;;###autoload
1530 (defun browse-url-lynx-emacs (url &optional new-buffer)
1531   "Ask the Lynx WWW browser to load URL.
1532 Default to the URL around or before point.  With a prefix argument, run
1533 a new Lynx process in a new buffer.
1534
1535 When called interactively, if variable `browse-url-new-window-flag' is
1536 non-nil, load the document in a new lynx in a new term window,
1537 otherwise use any existing one.  A non-nil interactive prefix argument
1538 reverses the effect of `browse-url-new-window-flag'.
1539
1540 When called non-interactively, optional second argument NEW-WINDOW is
1541 used instead of `browse-url-new-window-flag'."
1542   (interactive (browse-url-interactive-arg "Lynx URL: "))
1543   (let* ((system-uses-terminfo t)       ; Lynx uses terminfo
1544          ;; (term-term-name "vt100") ; ??
1545          (buf (get-buffer "*lynx*"))
1546          (proc (and buf (get-buffer-process buf)))
1547          (n browse-url-lynx-input-attempts))
1548     (if (and (browse-url-maybe-new-window new-buffer) buf)
1549         ;; Rename away the OLD buffer. This isn't very polite, but
1550         ;; term insists on working in a buffer named *lynx* and would
1551         ;; choke on *lynx*<1>
1552         (progn (set-buffer buf)
1553                (rename-uniquely)))
1554     (if (or (browse-url-maybe-new-window new-buffer)
1555             (not buf)
1556             (not proc)
1557             (not (memq (process-status proc) '(run stop))))
1558         ;; start a new lynx
1559         (progn
1560           (setq buf
1561                 (apply #'make-term
1562                        `("lynx" "lynx" nil ,@browse-url-lynx-emacs-args
1563                          ,url)))
1564           (switch-to-buffer buf)
1565           (term-char-mode)
1566           (set-process-sentinel
1567            (get-buffer-process buf)
1568            ;; Don't leave around a dead one (especially because of its
1569            ;; munged keymap.)
1570            (lambda (process event)
1571              (if (not (memq (process-status process) '(run stop)))
1572                  (let ((buf (process-buffer process)))
1573                    (if buf (kill-buffer buf)))))))
1574       ;; send the url to lynx in the old buffer
1575       (let ((win (get-buffer-window buf t)))
1576         (if win
1577             (select-window win)
1578           (switch-to-buffer buf)))
1579       (if (eq (following-char) ?_)
1580           (cond ((eq browse-url-lynx-input-field 'warn)
1581                  (error "Please move out of the input field first"))
1582                 ((eq browse-url-lynx-input-field 'avoid)
1583                  (while (and (eq (following-char) ?_) (> n 0))
1584                    (term-send-down) ; down arrow
1585                    (sit-for browse-url-lynx-input-delay))
1586                  (if (eq (following-char) ?_)
1587                      (error "Cannot move out of the input field, sorry")))))
1588       (term-send-string proc (concat "g" ; goto
1589                                      "\C-u" ; kill default url
1590                                      url
1591                                      "\r")))))
1592
1593 ;; --- MMM ---
1594
1595 ;;;###autoload
1596 (defun browse-url-mmm (url &optional new-window)
1597   "Ask the MMM WWW browser to load URL.
1598 Default to the URL around or before point."
1599   (interactive (browse-url-interactive-arg "MMM URL: "))
1600   (message "Sending URL to MMM...")
1601   (save-excursion
1602     (set-buffer (get-buffer-create " *Shell Command Output*"))
1603     (erase-buffer)
1604     ;; mmm_remote just SEGVs if the file isn't there...
1605     (if (or (file-exists-p (expand-file-name "~/.mmm_remote"))
1606             ;; location in v 0.4:
1607             (file-exists-p (expand-file-name "~/.mmm/remote")))
1608         (call-process "mmm_remote" nil 0 nil url)
1609       (call-process "mmm" nil 0 nil "-external" url))
1610     (message "Sending URL to MMM... done")))
1611
1612 ;; --- mailto ---
1613
1614 ;;;###autoload
1615 (defun browse-url-mail (url &optional new-window)
1616   "Open a new mail message buffer within Emacs.
1617 Default to using the mailto: URL around or before point as the
1618 recipient's address.  Supplying a non-nil interactive prefix argument
1619 will cause the mail to be composed in another window rather than the
1620 current one.
1621
1622 When called interactively, if variable `browse-url-new-window-flag' is
1623 non-nil use `compose-mail-other-window', otherwise `compose-mail'.  A
1624 non-nil interactive prefix argument reverses the effect of
1625 `browse-url-new-window-flag'.
1626
1627 When called non-interactively, optional second argument NEW-WINDOW is
1628 used instead of `browse-url-new-window-flag'."
1629   (interactive (browse-url-interactive-arg "Mailto URL: "))
1630   (save-excursion
1631     (let ((to (if (string-match "^mailto:" url)
1632                   (substring url 7)
1633                 url)))
1634       (if (browse-url-maybe-new-window new-window)
1635           (compose-mail-other-window to nil nil nil
1636                                      (list 'insert-buffer (current-buffer)))
1637         (compose-mail to nil nil nil nil
1638                       (list 'insert-buffer (current-buffer)))))))
1639
1640 ;; --- Random browser ---
1641
1642 ;;;###autoload
1643 (defun browse-url-generic (url &optional new-window)
1644   ;; new-window ignored
1645   "Ask the WWW browser defined by `browse-url-generic-program' to load URL.
1646 Default to the URL around or before point.  A fresh copy of the
1647 browser is started up in a new process with possible additional arguments
1648 `browse-url-generic-args'.  This is appropriate for browsers which
1649 don't offer a form of remote control."
1650   (interactive (browse-url-interactive-arg "URL: "))
1651   (if (not browse-url-generic-program)
1652     (error "No browser defined (`browse-url-generic-program')"))
1653   (apply 'start-process (concat browse-url-generic-program url) nil
1654          browse-url-generic-program
1655          (append browse-url-generic-args (list url))))
1656
1657 ;; --- KDE ---
1658
1659 ;;;###autoload
1660 (defun browse-url-kde (url &optional new-window)
1661   "Ask the KDE WWW browser to load URL.
1662 Default to the URL around or before point."
1663   (interactive (browse-url-interactive-arg "KDE URL: "))
1664   (message "Sending URL to KDE...")
1665   (apply #'start-process `(,(concat "KDE" url) nil ,browse-url-kde-program
1666                            ,@browse-url-kde-args ,url)))
1667
1668 (defalias 'browse-url-kfm 'browse-url-kde) ;; XEmacs backwards compatibility
1669
1670 ;; --- Opera ---
1671
1672 ;;;###autoload
1673 (defun browse-url-opera (url &optional new-window)
1674   "Ask the Opera WWW browser to load URL.
1675 Default to the URL around or before point.  The strings in variable
1676 `browse-url-opera-arguments' are also passed to Opera.
1677
1678 When called interactively, if variable `browse-url-new-window-flag' is
1679 non-nil, load the document in a new Opera window, otherwise use an
1680 existing one.  A non-nil interactive prefix argument reverses the
1681 effect of `browse-url-new-window-flag'.
1682
1683 When called non-interactively, optional second argument NEW-WINDOW is
1684 used instead of `browse-url-new-window-flag'."
1685   (interactive (browse-url-interactive-arg "URL: "))
1686   ;; URL encode any `confusing' characters in the URL.  This needs to
1687   ;; include at least commas; presumably also close parens.
1688   (while (string-match "[,)]" url)
1689     (setq url (replace-match
1690                (format "%%%x" (string-to-char (match-string 0 url))) t t url)))
1691   (let* ((process-environment (browse-url-process-environment))
1692          (process (apply 'start-process
1693                          (concat "opera " url) nil
1694                          browse-url-opera-program
1695                          (append
1696                           browse-url-opera-arguments
1697                           (list "-remote"
1698                                 (concat "openURL("
1699                                         url
1700                                         (if new-window ",new-window")
1701                                         ")"))))))
1702     (set-process-sentinel process
1703                           `(lambda (process change)
1704                              (browse-url-opera-sentinel process ,url)))))
1705
1706 (defun browse-url-opera-sentinel (process url)
1707   "Handle a change to the process communicating with Opera."
1708   (or (eq (process-exit-status process) 0)
1709       (let* ((process-environment (browse-url-process-environment)))
1710         ;; Opera is not running - start it
1711         (message "Starting Opera...")
1712         (apply 'start-process (concat "opera " url) nil
1713                browse-url-opera-program
1714                (append browse-url-opera-startup-arguments (list url))))))
1715
1716 (provide 'browse-url)
1717
1718 ;;; browse-url.el ends here