2 * (C) Copyright 2004-2007 Shawn Betts
3 * (C) Copyright 2007-2008 John J. Foerch
4 * (C) Copyright 2007-2008 Jeremy Maitin-Shepard
6 * Use, modification, and distribution are subject to the terms specified in the
10 require("content-buffer.js");
12 define_hook("quit_hook");
17 var appStartup = Cc["@mozilla.org/toolkit/app-startup;1"]
18 .getService(Ci.nsIAppStartup);
19 appStartup.quit(appStartup.eAttemptQuit);
26 function show_conkeror_version (window)
28 window.minibuffer.message (conkeror.version);
30 interactive ("conkeror-version",
31 "Show version information for Conkeror.",
32 function (I) {show_conkeror_version(I.window);});
34 /* FIXME: maybe this should be supported for non-browser buffers */
35 function scroll_horiz_complete (buffer, n)
37 var w = buffer.focused_frame;
38 w.scrollTo (n > 0 ? w.scrollMaxX : 0, w.scrollY);
40 interactive("scroll-beginning-of-line",
41 "Scroll the current frame all the way to the left.",
42 function (I) {scroll_horiz_complete(I.buffer, -1);});
44 interactive("scroll-end-of-line",
45 "Scroll the current frame all the way to the right.",
46 function (I) {scroll_horiz_complete(I.buffer, 1);});
48 interactive("make-window",
51 make_window(buffer_creator(content_buffer,
53 $configuration = I.buffer.configuration));
56 function delete_window (window)
58 window.window.close();
60 interactive("delete-window",
61 "Delete the current window.",
62 function (I) {delete_window(I.window);});
64 interactive("jsconsole",
65 "Open the JavaScript console.",
67 open_in_browser(I.buffer,
68 I.browse_target("jsconsole"),
69 "chrome://global/content/console.xul");
71 default_browse_targets["jsconsole"] = "find-url-new-buffer";
74 * Given a callback func and an interactive context I, call func, passing either
75 * a focused field, or the minibuffer's input element if the minibuffer is
76 * active. Afterward, call `ensure_index_is_visible' on the field. See
77 * `paste_x_primary_selection' and `open_line' for examples.
79 function call_on_focused_field(I, func) {
80 var m = I.window.minibuffer;
81 var s = m.current_state;
82 if (m._input_mode_enabled) {
83 m._restore_normal_state();
84 var e = m.input_element;
85 } else var e = I.buffer.focused_element;
87 ensure_index_is_visible (I.window, e, e.selectionStart);
88 if (s && s.handle_input) s.handle_input(m);
92 * Replace the current region with modifier(selection). Deactivates region and
93 * sets point to the end of the inserted text, unless keep_point is true, in
94 * which case the point will be left at the beginning of the inserted text.
96 function modify_region(field, modifier, keep_point) {
98 modifier(field.value.substring(field.selectionStart, field.selectionEnd+1));
99 var point = field.selectionStart;
101 field.value.substr(0, field.selectionStart) + replacement +
102 field.value.substr(field.selectionEnd);
103 if (!keep_point) point += replacement.length;
104 field.setSelectionRange(point, point);
107 function paste_x_primary_selection (field) {
108 modify_region(field, function(str) read_from_x_primary_selection());
111 "paste-x-primary-selection",
112 "Insert the contents of the X primary selection into the selected field or " +
113 "minibuffer. Deactivates the region if it is active, and leaves the point " +
114 "after the inserted text.",
115 function (I) call_on_focused_field(I, paste_x_primary_selection)
118 function open_line(field) {
119 modify_region(field, function() "\n", true);
123 "If there is an active region, replace is with a newline, otherwise just " +
124 "insert a newline. In both cases leave point before the inserted newline.",
125 function (I) call_on_focused_field(I, open_line)
128 function meta_x (window, prefix, command, browser_object_class)
130 call_interactively({window: window,
131 prefix_argument: prefix,
132 _browser_object_class: browser_object_class}, command);
134 interactive("execute-extended-command",
135 "Execute a Conkeror command specified in the minibuffer.",
138 var boc = I._browser_object_class;
141 prompt += ' ['+boc+']';
142 if (prefix !== null && prefix !== undefined) {
143 if (typeof prefix == "object")
144 prompt += prefix[0] == 4 ? " C-u" : " "+prefix[0];
146 prompt += " "+prefix;
148 meta_x(I.window, I.P,
149 (yield I.minibuffer.read_command(
150 $prompt = "M-x" + prompt)),
154 /// built in commands
155 // see: http://www.xulplanet.com/tutorials/xultu/commandupdate.html
157 // Performs a command on a browser buffer content area
160 define_builtin_commands(
162 function (I, command) {
163 var buffer = I.buffer;
165 buffer.do_command(command);
167 /* Ignore exceptions */
171 I.buffer.mark_active = !I.buffer.mark_active;
173 function (I) I.buffer.mark_active,
177 define_builtin_commands(
179 function (I, command) {
180 var buffer = I.buffer;
182 buffer.do_command(command);
184 /* Ignore exceptions */
188 I.buffer.mark_active = !I.buffer.mark_active;
190 function (I) I.buffer.mark_active,
193 function get_link_text()
195 var e = document.commandDispatcher.focusedElement;
196 if (e && e.getAttribute("href")) {
197 return e.getAttribute("href");
204 function copy_email_address (loc)
206 // Copy the comma-separated list of email addresses only.
207 // There are other ways of embedding email addresses in a mailto:
208 // link, but such complex parsing is beyond us.
209 var qmark = loc.indexOf( "?" );
212 if ( qmark > 7 ) { // 7 == length of "mailto:"
213 addresses = loc.substring( 7, qmark );
215 addresses = loc.substr( 7 );
218 //XXX: the original code, which we got from firefox, unescapes the string
219 // using the current character set. To do this in conkeror, we
220 // *should* use an interactive method that gives us the character set,
221 // rather than fetching it by side-effect.
223 // // Let's try to unescape it using a character set
224 // // in case the address is not ASCII.
226 // var characterSet = this.target.ownerDocument.characterSet;
227 // const textToSubURI = Components.classes["@mozilla.org/intl/texttosuburi;1"]
228 // .getService(Components.interfaces.nsITextToSubURI);
229 // addresses = textToSubURI.unEscapeURIForUI(characterSet, addresses);
235 writeToClipboard(addresses);
236 message("Copied '" + addresses + "'");
238 interactive("copy-email-address", copy_email_address, ['focused_link_url']);
241 /* FIXME: fix this command */
243 interactive("source",
244 "Load a JavaScript file.",
245 function (fo) { load_rc (fo.path); }, [['f', function (a) { return "Source File: "; }, null, "source"]]);
247 function reinit (window, fn)
251 window.minibuffer.message ("Loaded: " + fn);
253 window.minibuffer.message ("Failed to load: "+fn);
257 interactive ("reinit",
258 "Reload the Conkeror rc file.",
260 reinit(I.window, get_pref("conkeror.rcfile"));
263 interactive("help-page",
264 "Open the Conkeror help page.",
266 open_in_browser(I.buffer, I.browse_target("find-url"),
267 "chrome://conkeror/content/help.html");
270 interactive("help-with-tutorial",
271 "Open the Conkeror tutorial.",
273 open_in_browser(I.buffer, I.browse_target("find-url"),
274 "chrome://conkeror/content/tutorial.html");
277 function univ_arg_to_number(prefix, default_value)
279 if (prefix == null) {
280 if (default_value == null)
283 return default_value;
285 if (typeof prefix == "object")
290 function eval_expression(window, s)
292 // eval in the global scope.
294 // In addition, the following variables are available:
296 var buffer = window.buffers.current;
297 var result = eval(s);
298 if (result !== undefined) {
299 window.minibuffer.message(String(result));
302 interactive("eval-expression",
303 "Evaluate JavaScript statements.",
307 (yield I.minibuffer.read($prompt = "Eval:",
308 $history = "eval-expression",
309 $completer = javascript_completer(I.buffer))));
313 function show_extension_manager () {
314 return conkeror.window_watcher.openWindow (
316 "chrome://mozapps/content/extensions/extensions.xul?type=extensions",
318 "resizable=yes,dialog=no",
321 interactive("extensions",
322 "Open the extensions manager in a new window.",
323 show_extension_manager);
325 function print_buffer(buffer)
327 buffer.top_frame.print();
329 interactive("print-buffer",
330 "Print the currently loaded page.",
331 function (I) {print_buffer(I.buffer);});
333 function view_partial_source (window, charset, selection) {
334 if (charset) { charset = "charset=" + charset; }
335 window.window.openDialog("chrome://global/content/viewPartialSource.xul",
336 "_blank", "scrollbars,resizable,chrome,dialog=no",
337 null, charset, selection, 'selection');
339 //interactive ('view-partial-source', view_partial_source, I.current_window, I.content_charset, I.content_selection);
342 function view_mathml_source (window, charset, target) {
343 if (charset) { charset = "charset=" + charset; }
344 window.window.openDialog("chrome://global/content/viewPartialSource.xul",
345 "_blank", "scrollbars,resizable,chrome,dialog=no",
346 null, charset, target, 'mathml');
350 function send_key_as_event (window, element, key) {
352 var event = window.document.createEvent ("KeyboardEvent");
358 key.modifiers & MOD_CTRL, // ctrl
359 key.modifiers & MOD_META, // alt
360 key.modifiers & MOD_SHIFT, // shift
361 key.modifiers & MOD_META, // meta
364 // bit of a hack here.. we have to fake a keydown event for conkeror
365 window.keyboard.last_key_down_event = copy_event (event);
367 return element.dispatchEvent (event);
369 return window.dispatchEvent (event);
376 send_key_as_event (I.window, I.buffer.focused_element, "return");
379 function ensure_content_focused(buffer) {
380 var foc = buffer.focused_frame_or_null;
382 buffer.top_frame.focus();
384 interactive("ensure-content-focused", "Ensure that the content document has focus.",
385 function (I) { ensure_content_focused(I.buffer); });
387 function network_set_online_status (status) {
389 io_service.manageOfflineStatus = false;
390 io_service.offline = status;
393 interactive("network-go-online", "Work online.",
394 function (I) {network_set_online_status (true);});
395 interactive("network-go-offline", "Work offline.",
396 function (I) {network_set_online_status (false);});