text: /* ***** BEGIN LICENSE BLOCK *****
   * Distributed under the BSD license:
   *
   * Copyright (c) 2010, Ajax.org B.V.
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions are met:
   *     * Redistributions of source code must retain the above copyright
   *       notice, this list of conditions and the following disclaimer.
   *     * Redistributions in binary form must reproduce the above copyright
   *       notice, this list of conditions and the following disclaimer in the
   *       documentation and/or other materials provided with the distribution.
   *     * Neither the name of Ajax.org B.V. nor the
   *       names of its contributors may be used to endorse or promote products
   *       derived from this software without specific prior written permission.
   *
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
   * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   *
   * ***** END LICENSE BLOCK ***** */
  
  
   /** H5C3 - Lets play nicely with others */
  if (typeof require === 'undefined')
  	if (typeof _require === 'function') 
  		require = _require;
  		
  if (typeof define === 'undefined')
  	if (typeof _define === 'function') 
  		define = _define;
  
  		
  define(function(require, exports, module) {
  	"use strict";
  
  	require("ace/lib/fixoldbrowsers");
  	var config = require("ace/config");
  	config.init();
  	var env = {};
  
  	var dom = require("ace/lib/dom");
  	var net = require("ace/lib/net");
  	var lang = require("ace/lib/lang");
  	var useragent = require("ace/lib/useragent");
  
  	var event = require("ace/lib/event");
  	var theme = require("ace/theme/textmate");
  	var EditSession = require("ace/edit_session").EditSession;
  	var UndoManager = require("ace/undomanager").UndoManager;
  
  	var HashHandler = require("ace/keyboard/hash_handler").HashHandler;
  
  	var Renderer = require("ace/virtual_renderer").VirtualRenderer;
  	var Editor = require("ace/editor").Editor;
  	var MultiSelect = require("ace/multi_select").MultiSelect;
  
  	var whitespace = require("ace/ext/whitespace");
  
  	var doclist = require("./doclist");
  	var modelist = require("ace/ext/modelist");
  	var layout = require("./layout");
  	var TokenTooltip = require("./token_tooltip").TokenTooltip;
  	var util = require("./util");
  	var saveOption = util.saveOption;
  	var fillDropdown = util.fillDropdown;
  	var bindCheckbox = util.bindCheckbox;
  	var bindDropdown = util.bindDropdown;
  
  	var ElasticTabstopsLite = require("ace/ext/elastic_tabstops_lite").ElasticTabstopsLite;
  
  	var IncrementalSearch = require("ace/incremental_search").IncrementalSearch;
  
  
  	var workerModule = require("ace/worker/worker_client");
  	if (location.href.indexOf("noworker") !== -1) {
  		workerModule.WorkerClient = workerModule.UIWorkerClient;
  	}
  
  	/*********** create editor ***************************/
  	var container = document.getElementById("editor-container");
  
  	// Splitting.
  	var Split = require("ace/split").Split;
  	var split = new Split(container, theme, 1);
  	env.editor = split.getEditor(0);
  	split.on("focus", function(editor) {
  		env.editor = editor;
  		updateUIEditorOptions();
  	});
  	env.split = split;
  	window.env = env;
  	window.ace = env.editor;
  	env.editor.setAnimatedScroll(true);
  
  	// add multiple cursor support to editor
  	require("ace/multi_select").MultiSelect(env.editor);
  
  	var consoleEl = dom.createElement("div");
  	container.parentNode.appendChild(consoleEl);
  	consoleEl.style.cssText = "position:fixed; bottom:1px; right:0;\
  	border:1px solid #baf; z-index:100";
  
  	var cmdLine = new layout.singleLineEditor(consoleEl);
  	cmdLine.editor = env.editor;
  	env.editor.cmdLine = cmdLine;
  
  	env.editor.showCommandLine = function(val) {
  		this.cmdLine.focus();
  		if (typeof val == "string")
  			this.cmdLine.setValue(val, 1);
  	};
  
  	/**
  	 * This demonstrates how you can define commands and bind shortcuts to them.
  	 */
  	env.editor.commands.addCommands([{
  		name: "gotoline",
  		bindKey: {win: "Ctrl-L", mac: "Command-L"},
  		exec: function(editor, line) {
  			if (typeof line == "object") {
  				var arg = this.name + " " + editor.getCursorPosition().row;
  				editor.cmdLine.setValue(arg, 1);
  				editor.cmdLine.focus();
  				return;
  			}
  			line = parseInt(line, 10);
  			if (!isNaN(line))
  				editor.gotoLine(line);
  		},
  		readOnly: true
  	}, {
  		name: "snippet",
  		bindKey: {win: "Alt-C", mac: "Command-Alt-C"},
  		exec: function(editor, needle) {
  			if (typeof needle == "object") {
  				editor.cmdLine.setValue("snippet ", 1);
  				editor.cmdLine.focus();
  				return;
  			}
  			var s = snippetManager.getSnippetByName(needle, editor);
  			if (s)
  				snippetManager.insertSnippet(editor, s.content);
  		},
  		readOnly: true
  	}, {
  		name: "focusCommandLine",
  		bindKey: "shift-esc|ctrl-`",
  		exec: function(editor, needle) { editor.cmdLine.focus(); },
  		readOnly: true
  	}, {
  		name: "nextFile",
  		bindKey: "Ctrl-tab",
  		exec: function(editor) { doclist.cycleOpen(editor, 1); },
  		readOnly: true
  	}, {
  		name: "previousFile",
  		bindKey: "Ctrl-shift-tab",
  		exec: function(editor) { doclist.cycleOpen(editor, -1); },
  		readOnly: true
  	}, {
  		name: "execute",
  		bindKey: "ctrl+enter",
  		exec: function(editor) {
  			try {
  				var r = window.eval(editor.getCopyText()||editor.getValue());
  			} catch(e) {
  				r = e;
  			}
  			editor.cmdLine.setValue(r + "")
  		},
  		readOnly: true
  	}, {
  		name: "showKeyboardShortcuts",
  		bindKey: {win: "Ctrl-Alt-h", mac: "Command-Alt-h"},
  		exec: function(editor) {
  			config.loadModule("ace/ext/keybinding_menu", function(module) {
  				module.init(editor);
  				editor.showKeyboardShortcuts()
  			})
  		}
  	}, {
  		name: "increaseFontSize",
  		bindKey: "Ctrl-+",
  		exec: function(editor) {
  			var size = parseInt(editor.getFontSize(), 10) || 12;
  			editor.setFontSize(size + 1);
  		}
  	}, {
  		name: "decreaseFontSize",
  		bindKey: "Ctrl+-",
  		exec: function(editor) {
  			var size = parseInt(editor.getFontSize(), 10) || 12;
  			editor.setFontSize(Math.max(size - 1 || 1));
  		}
  	}, {
  		name: "resetFontSize",
  		bindKey: "Ctrl+0",
  		exec: function(editor) {
  			editor.setFontSize(12);
  		}
  	}]);
  
  
  	env.editor.commands.addCommands(whitespace.commands);
  
  	cmdLine.commands.bindKeys({
  		"Shift-Return|Ctrl-Return|Alt-Return": function(cmdLine) { cmdLine.insert("\n"); },
  		"Esc|Shift-Esc": function(cmdLine){ cmdLine.editor.focus(); },
  		"Return": function(cmdLine){
  			var command = cmdLine.getValue().split(/\s+/);
  			var editor = cmdLine.editor;
  			editor.commands.exec(command[0], editor, command[1]);
  			editor.focus();
  		}
  	});
  
  	cmdLine.commands.removeCommands(["find", "gotoline", "findall", "replace", "replaceall"]);
  
  	var commands = env.editor.commands;
  	commands.addCommand({
  		name: "save",
  		bindKey: {win: "Ctrl-S", mac: "Command-S"},
  		exec: function(arg) {
  			var session = env.editor.session;
  			name = session.name.match(/[^\/]+$/)
  			localStorage.setItem(
  				"saved_file:" + name,
  				session.getValue()
  			);
  			env.editor.cmdLine.setValue("saved "+ name);
  		}
  	});
  
  	commands.addCommand({
  		name: "load",
  		bindKey: {win: "Ctrl-O", mac: "Command-O"},
  		exec: function(arg) {
  			var session = env.editor.session;
  			name = session.name.match(/[^\/]+$/)
  			var value = localStorage.getItem("saved_file:" + name);
  			if (typeof value == "string") {
  				session.setValue(value);
  				env.editor.cmdLine.setValue("loaded "+ name);
  			} else {
  				env.editor.cmdLine.setValue("no previuos value saved for "+ name);
  			}
  		}
  	});
  
  	var keybindings = {    
  		ace: null, // Null = use "default" keymapping
  		vim: require("ace/keyboard/vim").handler,
  		emacs: "ace/keyboard/emacs",
  		// This is a way to define simple keyboard remappings
  		custom: new HashHandler({
  			"gotoright":      "Tab",
  			"indent":         "]",
  			"outdent":        "[",
  			"gotolinestart":  "^",
  			"gotolineend":    "$"
  		})
  	};
  
  
  
  	/*********** manage layout ***************************/
  	var consoleHeight = 20;
  	function onResize() {
  		var left = env.split.$container.offsetLeft;
  		var width = document.documentElement.clientWidth - left;
  		container.style.width = width + "px";
  		container.style.height = document.documentElement.clientHeight - consoleHeight + "px";
  		env.split.resize();
  
  		consoleEl.style.width = width + "px";
  		cmdLine.resize();
  	}
  
  	window.onresize = onResize;
  	onResize();
  
  	/*********** options panel ***************************/
  	var docEl = document.getElementById("doc");
  	var modeEl = document.getElementById("mode");
  	var wrapModeEl = document.getElementById("soft_wrap");
  	var themeEl = document.getElementById("theme");
  	var foldingEl = document.getElementById("folding");
  	var selectStyleEl = document.getElementById("select_style");
  	var highlightActiveEl = document.getElementById("highlight_active");
  	var showHiddenEl = document.getElementById("show_hidden");
  	var showGutterEl = document.getElementById("show_gutter");
  	var showPrintMarginEl = document.getElementById("show_print_margin");
  	var highlightSelectedWordE = document.getElementById("highlight_selected_word");
  	var showHScrollEl = document.getElementById("show_hscroll");
  	var showVScrollEl = document.getElementById("show_vscroll");
  	var animateScrollEl = document.getElementById("animate_scroll");
  	var softTabEl = document.getElementById("soft_tab");
  	var behavioursEl = document.getElementById("enable_behaviours");
  
  	fillDropdown(docEl, doclist.all);
  
  	fillDropdown(modeEl, modelist.modes);
  	var modesByName = modelist.modesByName;
  	bindDropdown("mode", function(value) {
  		env.editor.session.setMode(modesByName[value].mode || modesByName.text.mode);
  		env.editor.session.modeName = value;
  	});
  
  	doclist.history = doclist.docs.map(function(doc) {
  		return doc.name;
  	});
  	doclist.history.index = 0;
  	doclist.cycleOpen = function(editor, dir) {
  		var h = this.history
  		h.index += dir;
  		if (h.index >= h.length) 
  			h.index = 0;
  		else if (h.index <= 0)
  			h.index = h.length - 1;
  		var s = h[h.index];
  		docEl.value = s;
  		docEl.onchange();
  		h.index
  	}
  	doclist.addToHistory = function(name) {
  		var h = this.history
  		var i = h.indexOf(name);
  		if (i != h.index) {
  			if (i != -1)
  				h.splice(i, 1);
  			h.index = h.push(name);
  		}
  	}
  
  	bindDropdown("doc", function(name) {
  		doclist.loadDoc(name, function(session) {
  			if (!session)
  				return;
  			doclist.addToHistory(session.name);
  			session = env.split.setSession(session);
  			whitespace.detectIndentation(session);
  			updateUIEditorOptions();
  			env.editor.focus();
  		});
  	});
  
  
  	function updateUIEditorOptions() {
  		var editor = env.editor;
  		var session = editor.session;
  
  		session.setFoldStyle(foldingEl.value);
  
  		saveOption(docEl, session.name);
  		saveOption(modeEl, session.modeName || "text");
  		saveOption(wrapModeEl, session.getUseWrapMode() ? session.getWrapLimitRange().min || "free" : "off");
  
  		saveOption(selectStyleEl, editor.getSelectionStyle() == "line");
  		saveOption(themeEl, editor.getTheme());
  		saveOption(highlightActiveEl, editor.getHighlightActiveLine());
  		saveOption(showHiddenEl, editor.getShowInvisibles());
  		saveOption(showGutterEl, editor.renderer.getShowGutter());
  		saveOption(showPrintMarginEl, editor.renderer.getShowPrintMargin());
  		saveOption(highlightSelectedWordE, editor.getHighlightSelectedWord());
  		saveOption(showHScrollEl, editor.renderer.getHScrollBarAlwaysVisible());
  		saveOption(animateScrollEl, editor.getAnimatedScroll());
  		saveOption(softTabEl, session.getUseSoftTabs());
  		saveOption(behavioursEl, editor.getBehavioursEnabled());
  	}
  
  	event.addListener(themeEl, "mouseover", function(e){
  		this.desiredValue = e.target.value;
  		if (!this.$timer)
  			this.$timer = setTimeout(this.updateTheme);
  	});
  
  	event.addListener(themeEl, "mouseout", function(e){
  		this.desiredValue = null;
  		if (!this.$timer)
  			this.$timer = setTimeout(this.updateTheme, 20);
  	});
  
  	themeEl.updateTheme = function(){
  		env.split.setTheme(themeEl.desiredValue || themeEl.selectedValue);
  		themeEl.$timer = null;
  	};
  
  	bindDropdown("theme", function(value) {
  		if (!value)
  			return;
  		env.editor.setTheme(value);
  		themeEl.selectedValue = value;
  	});
  
  	bindDropdown("keybinding", function(value) {
  		env.editor.setKeyboardHandler(keybindings[value]);
  	});
  
  	bindDropdown("fontsize", function(value) {
  		env.split.setFontSize(value);
  	});
  
  	bindDropdown("folding", function(value) {
  		env.editor.session.setFoldStyle(value);
  		env.editor.setShowFoldWidgets(value !== "manual");
  	});
  
  	bindDropdown("soft_wrap", function(value) {
  		var session = env.editor.session;
  		var renderer = env.editor.renderer;
  		switch (value) {
  			case "off":
  				session.setUseWrapMode(false);
  				renderer.setPrintMarginColumn(80);
  				break;
  			case "free":
  				session.setUseWrapMode(true);
  				session.setWrapLimitRange(null, null);
  				renderer.setPrintMarginColumn(80);
  				break;
  			default:
  				session.setUseWrapMode(true);
  				var col = parseInt(value, 10);
  				session.setWrapLimitRange(col, col);
  				renderer.setPrintMarginColumn(col);
  		}
  	});
  
  	bindCheckbox("select_style", function(checked) {
  		env.editor.setSelectionStyle(checked ? "line" : "text");
  	});
  
  	bindCheckbox("highlight_active", function(checked) {
  		env.editor.setHighlightActiveLine(checked);
  	});
  
  	bindCheckbox("show_hidden", function(checked) {
  		env.editor.setShowInvisibles(checked);
  	});
  
  	bindCheckbox("display_indent_guides", function(checked) {
  		env.editor.setDisplayIndentGuides(checked);
  	});
  
  	bindCheckbox("show_gutter", function(checked) {
  		env.editor.renderer.setShowGutter(checked);
  	});
  
  	bindCheckbox("show_print_margin", function(checked) {
  		env.editor.renderer.setShowPrintMargin(checked);
  	});
  
  	bindCheckbox("highlight_selected_word", function(checked) {
  		env.editor.setHighlightSelectedWord(checked);
  	});
  
  	bindCheckbox("show_hscroll", function(checked) {
  		env.editor.setOption("hScrollBarAlwaysVisible", checked);
  	});
  
  	bindCheckbox("show_vscroll", function(checked) {
  		env.editor.setOption("vScrollBarAlwaysVisible", checked);
  	});
  
  	bindCheckbox("animate_scroll", function(checked) {
  		env.editor.setAnimatedScroll(checked);
  	});
  
  	bindCheckbox("soft_tab", function(checked) {
  		env.editor.session.setUseSoftTabs(checked);
  	});
  
  	bindCheckbox("enable_behaviours", function(checked) {
  		env.editor.setBehavioursEnabled(checked);
  	});
  
  	bindCheckbox("fade_fold_widgets", function(checked) {
  		env.editor.setFadeFoldWidgets(checked);
  	});
  	bindCheckbox("read_only", function(checked) {
  		env.editor.setReadOnly(checked);
  	});
  	bindCheckbox("scrollPastEnd", function(checked) {
  		env.editor.setOption("scrollPastEnd", checked);
  	});
  
  	bindDropdown("split", function(value) {
  		var sp = env.split;
  		if (value == "none") {
  			sp.setSplits(1);
  		} else {
  			var newEditor = (sp.getSplits() == 1);
  			sp.setOrientation(value == "below" ? sp.BELOW : sp.BESIDE);        
  			sp.setSplits(2);
  
  			if (newEditor) {
  				var session = sp.getEditor(0).session;
  				var newSession = sp.setSession(session, 1);
  				newSession.name = session.name;
  			}
  		}
  	});
  
  
  	bindCheckbox("elastic_tabstops", function(checked) {
  		env.editor.setOption("useElasticTabstops", checked);
  	});
  
  	var iSearchCheckbox = bindCheckbox("isearch", function(checked) {
  		env.editor.setOption("useIncrementalSearch", checked);
  	});
  
  	env.editor.addEventListener('incrementalSearchSettingChanged', function(event) {
  		iSearchCheckbox.checked = event.isEnabled;
  	});
  
  
  	function synchroniseScrolling() {
  		var s1 = env.split.$editors[0].session;
  		var s2 = env.split.$editors[1].session;
  		s1.on('changeScrollTop', function(pos) {s2.setScrollTop(pos)});
  		s2.on('changeScrollTop', function(pos) {s1.setScrollTop(pos)});
  		s1.on('changeScrollLeft', function(pos) {s2.setScrollLeft(pos)});
  		s2.on('changeScrollLeft', function(pos) {s1.setScrollLeft(pos)});
  	}
  
  	bindCheckbox("highlight_token", function(checked) {
  		var editor = env.editor;
  		if (editor.tokenTooltip && !checked) {
  			editor.tokenTooltip.destroy();
  			delete editor.tokenTooltip;
  		} else if (checked) {
  			editor.tokenTooltip = new TokenTooltip(editor);
  		}
  	});
  
  	/************** dragover ***************************/
  	event.addListener(container, "dragover", function(e) {
  		var types = e.dataTransfer.types;
  		if (types && Array.prototype.indexOf.call(types, 'Files') !== -1)
  			return event.preventDefault(e);
  	});
  
  	event.addListener(container, "drop", function(e) {
  		var file;
  		try {
  			file = e.dataTransfer.files[0];
  			if (window.FileReader) {
  				var reader = new FileReader();
  				reader.onload = function() {
  					var mode = modelist.getModeForPath(file.name);
  
  					env.editor.session.doc.setValue(reader.result);
  					modeEl.value = mode.name;
  					env.editor.session.setMode(mode.mode);
  					env.editor.session.modeName = mode.name;
  				};
  				reader.readAsText(file);
  			}
  			return event.preventDefault(e);
  		} catch(err) {
  			return event.stopEvent(e);
  		}
  	});
  
  
  
  	var StatusBar = require("ace/ext/statusbar").StatusBar;
  	new StatusBar(env.editor, cmdLine.container);
  
  
  	var Emmet = require("ace/ext/emmet");
  	net.loadScript("http://nightwing.github.io/emmet-core/emmet.js", function() {
  		Emmet.setCore(window.emmet);
  		env.editor.setOption("enableEmmet", true);
  	});
  
  
  	// require("ace/placeholder").PlaceHolder;
  
  	var snippetManager = require("ace/snippets").snippetManager;
  
  	env.editSnippets = function() {
  		var sp = env.split;
  		if (sp.getSplits() == 2) {
  			sp.setSplits(1);
  			return;
  		}
  		sp.setSplits(1);
  		sp.setSplits(2);
  		sp.setOrientation(sp.BESIDE);
  		var editor = sp.$editors[1];
  		var id = sp.$editors[0].session.$mode.$id || "";
  		var m = snippetManager.files[id];
  		if (!doclist["snippets/" + id]) {
  			var text = m.snippetText;
  			var s = doclist.initDoc(text, "", {});
  			s.setMode("ace/mode/snippets");
  			doclist["snippets/" + id] = s
  		}
  		editor.on("blur", function() {
  			m.snippetText = editor.getValue();
  			snippetManager.unregister(m.snippets);
  			m.snippets = snippetManager.parseSnippetFile(m.snippetText);
  			snippetManager.register(m.snippets);
  		})
  		sp.$editors[0].once("changeMode", function() {
  			sp.setSplits(1);
  		})
  		editor.setSession(doclist["snippets/" + id], 1);
  		editor.focus();
  	}
  
  	require("ace/ext/language_tools");
  	env.editor.setOptions({
  		enableBasicAutocompletion: true,
  		enableSnippets: true
  	})
  
  });
  