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)
130 call_interactively({window: window, prefix_argument: prefix}, command);
132 interactive("execute-extended-command",
133 "Execute a Conkeror command specified in the minibuffer.",
139 else if (typeof prefix == "object")
140 prompt = prefix[0] == 4 ? "C-u " : prefix[0] + " ";
142 prompt = prefix + " ";
143 meta_x(I.window, I.P,
144 (yield I.minibuffer.read_command(
145 $prompt = "M-x" + prompt)));
148 /// built in commands
149 // see: http://www.xulplanet.com/tutorials/xultu/commandupdate.html
151 // Performs a command on a browser buffer content area
154 define_builtin_commands(
156 function (I, command) {
157 var buffer = I.buffer;
159 buffer.do_command(command);
161 /* Ignore exceptions */
165 I.buffer.mark_active = !I.buffer.mark_active;
167 function (I) I.buffer.mark_active,
171 define_builtin_commands(
173 function (I, command) {
174 var buffer = I.buffer;
176 buffer.do_command(command);
178 /* Ignore exceptions */
182 I.buffer.mark_active = !I.buffer.mark_active;
184 function (I) I.buffer.mark_active,
187 function get_link_text()
189 var e = document.commandDispatcher.focusedElement;
190 if (e && e.getAttribute("href")) {
191 return e.getAttribute("href");
198 function copy_email_address (loc)
200 // Copy the comma-separated list of email addresses only.
201 // There are other ways of embedding email addresses in a mailto:
202 // link, but such complex parsing is beyond us.
203 var qmark = loc.indexOf( "?" );
206 if ( qmark > 7 ) { // 7 == length of "mailto:"
207 addresses = loc.substring( 7, qmark );
209 addresses = loc.substr( 7 );
212 //XXX: the original code, which we got from firefox, unescapes the string
213 // using the current character set. To do this in conkeror, we
214 // *should* use an interactive method that gives us the character set,
215 // rather than fetching it by side-effect.
217 // // Let's try to unescape it using a character set
218 // // in case the address is not ASCII.
220 // var characterSet = this.target.ownerDocument.characterSet;
221 // const textToSubURI = Components.classes["@mozilla.org/intl/texttosuburi;1"]
222 // .getService(Components.interfaces.nsITextToSubURI);
223 // addresses = textToSubURI.unEscapeURIForUI(characterSet, addresses);
229 writeToClipboard(addresses);
230 message("Copied '" + addresses + "'");
232 interactive("copy-email-address", copy_email_address, ['focused_link_url']);
235 /* FIXME: fix this command */
237 interactive("source",
238 "Load a JavaScript file.",
239 function (fo) { load_rc (fo.path); }, [['f', function (a) { return "Source File: "; }, null, "source"]]);
241 function reinit (window, fn)
245 window.minibuffer.message ("Loaded: " + fn);
247 window.minibuffer.message ("Failed to load: "+fn);
251 interactive ("reinit",
252 "Reload the Conkeror rc file.",
254 reinit(I.window, get_pref("conkeror.rcfile"));
257 interactive("help-page",
258 "Open the Conkeror help page.",
260 open_in_browser(I.buffer, I.browse_target("find-url"),
261 "chrome://conkeror/content/help.html");
264 interactive("help-with-tutorial",
265 "Open the Conkeror tutorial.",
267 open_in_browser(I.buffer, I.browse_target("find-url"),
268 "chrome://conkeror/content/tutorial.html");
271 function univ_arg_to_number(prefix, default_value)
273 if (prefix == null) {
274 if (default_value == null)
277 return default_value;
279 if (typeof prefix == "object")
284 function eval_expression(window, s)
286 // eval in the global scope.
288 // In addition, the following variables are available:
290 var buffer = window.buffers.current;
291 var result = eval(s);
292 if (result !== undefined) {
293 window.minibuffer.message(String(result));
296 interactive("eval-expression",
297 "Evaluate JavaScript statements.",
301 (yield I.minibuffer.read($prompt = "Eval:",
302 $history = "eval-expression",
303 $completer = javascript_completer(I.buffer))));
307 function show_extension_manager () {
308 return conkeror.window_watcher.openWindow (
310 "chrome://mozapps/content/extensions/extensions.xul?type=extensions",
312 "resizable=yes,dialog=no",
315 interactive("extensions",
316 "Open the extensions manager in a new window.",
317 show_extension_manager);
319 function print_buffer(buffer)
321 buffer.top_frame.print();
323 interactive("print-buffer",
324 "Print the currently loaded page.",
325 function (I) {print_buffer(I.buffer);});
327 function view_partial_source (window, charset, selection) {
328 if (charset) { charset = "charset=" + charset; }
329 window.window.openDialog("chrome://global/content/viewPartialSource.xul",
330 "_blank", "scrollbars,resizable,chrome,dialog=no",
331 null, charset, selection, 'selection');
333 //interactive ('view-partial-source', view_partial_source, I.current_window, I.content_charset, I.content_selection);
336 function view_mathml_source (window, charset, target) {
337 if (charset) { charset = "charset=" + charset; }
338 window.window.openDialog("chrome://global/content/viewPartialSource.xul",
339 "_blank", "scrollbars,resizable,chrome,dialog=no",
340 null, charset, target, 'mathml');
344 function send_key_as_event (window, element, key) {
346 var event = window.document.createEvent ("KeyboardEvent");
352 key.modifiers & MOD_CTRL, // ctrl
353 key.modifiers & MOD_META, // alt
354 key.modifiers & MOD_SHIFT, // shift
355 key.modifiers & MOD_META, // meta
358 // bit of a hack here.. we have to fake a keydown event for conkeror
359 window.keyboard.last_key_down_event = copy_event (event);
361 return element.dispatchEvent (event);
363 return window.dispatchEvent (event);
370 send_key_as_event (I.window, I.buffer.focused_element, "return");
373 function ensure_content_focused(buffer) {
374 var foc = buffer.focused_frame_or_null;
376 buffer.top_frame.focus();
378 interactive("ensure-content-focused", "Ensure that the content document has focus.",
379 function (I) { ensure_content_focused(I.buffer); });
381 function network_set_online_status (status) {
383 io_service.manageOfflineStatus = false;
384 io_service.offline = status;
387 interactive("network-go-online", "Work online.",
388 function (I) {network_set_online_status (true);});
389 interactive("network-go-offline", "Work offline.",
390 function (I) {network_set_online_status (false);});