Web Inspector: add Ace editor experiment
[WebKit-https.git] / Source / WebCore / inspector / front-end / ace / ace.js
1 /* ***** BEGIN LICENSE BLOCK *****
2  * Distributed under the BSD license:
3  *
4  * Copyright (c) 2010, Ajax.org B.V.
5  * All rights reserved.
6  * 
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *     * Redistributions of source code must retain the above copyright
10  *       notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above copyright
12  *       notice, this list of conditions and the following disclaimer in the
13  *       documentation and/or other materials provided with the distribution.
14  *     * Neither the name of Ajax.org B.V. nor the
15  *       names of its contributors may be used to endorse or promote products
16  *       derived from this software without specific prior written permission.
17  * 
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  * ***** END LICENSE BLOCK ***** */
30
31 (function() {
32
33 var ACE_NAMESPACE = "ace";
34
35 var global = (function() {
36     return this;
37 })();
38
39
40 if (!ACE_NAMESPACE && typeof requirejs !== "undefined")
41     return;
42
43
44 var _define = function(module, deps, payload) {
45     if (typeof module !== 'string') {
46         if (_define.original)
47             _define.original.apply(window, arguments);
48         else {
49             console.error('dropping module because define wasn\'t a string.');
50             console.trace();
51         }
52         return;
53     }
54
55     if (arguments.length == 2)
56         payload = deps;
57
58     if (!_define.modules)
59         _define.modules = {};
60
61     _define.modules[module] = payload;
62 };
63 var _require = function(parentId, module, callback) {
64     if (Object.prototype.toString.call(module) === "[object Array]") {
65         var params = [];
66         for (var i = 0, l = module.length; i < l; ++i) {
67             var dep = lookup(parentId, module[i]);
68             if (!dep && _require.original)
69                 return _require.original.apply(window, arguments);
70             params.push(dep);
71         }
72         if (callback) {
73             callback.apply(null, params);
74         }
75     }
76     else if (typeof module === 'string') {
77         var payload = lookup(parentId, module);
78         if (!payload && _require.original)
79             return _require.original.apply(window, arguments);
80
81         if (callback) {
82             callback();
83         }
84
85         return payload;
86     }
87     else {
88         if (_require.original)
89             return _require.original.apply(window, arguments);
90     }
91 };
92
93 var normalizeModule = function(parentId, moduleName) {
94     if (moduleName.indexOf("!") !== -1) {
95         var chunks = moduleName.split("!");
96         return normalizeModule(parentId, chunks[0]) + "!" + normalizeModule(parentId, chunks[1]);
97     }
98     if (moduleName.charAt(0) == ".") {
99         var base = parentId.split("/").slice(0, -1).join("/");
100         moduleName = base + "/" + moduleName;
101
102         while(moduleName.indexOf(".") !== -1 && previous != moduleName) {
103             var previous = moduleName;
104             moduleName = moduleName.replace(/\/\.\//, "/").replace(/[^\/]+\/\.\.\//, "");
105         }
106     }
107
108     return moduleName;
109 };
110 var lookup = function(parentId, moduleName) {
111
112     moduleName = normalizeModule(parentId, moduleName);
113
114     var module = _define.modules[moduleName];
115     if (!module) {
116         return null;
117     }
118
119     if (typeof module === 'function') {
120         var exports = {};
121         var mod = {
122             id: moduleName,
123             uri: '',
124             exports: exports,
125             packaged: true
126         };
127
128         var req = function(module, callback) {
129             return _require(moduleName, module, callback);
130         };
131
132         var returnValue = module(req, exports, mod);
133         exports = returnValue || mod.exports;
134         _define.modules[moduleName] = exports;
135         return exports;
136     }
137
138     return module;
139 };
140
141 function exportAce(ns) {
142     var require = function(module, callback) {
143         return _require("", module, callback);
144     };    
145
146     var root = global;
147     if (ns) {
148         if (!global[ns])
149             global[ns] = {};
150         root = global[ns];
151     }
152
153     if (!root.define || !root.define.packaged) {
154         _define.original = root.define;
155         root.define = _define;
156         root.define.packaged = true;
157     }
158
159     if (!root.require || !root.require.packaged) {
160         _require.original = root.require;
161         root.require = require;
162         root.require.packaged = true;
163     }
164 }
165
166 exportAce(ACE_NAMESPACE);
167
168 })();
169
170 ace.define('ace/ace', ['require', 'exports', 'module' , 'ace/lib/fixoldbrowsers', 'ace/lib/dom', 'ace/lib/event', 'ace/editor', 'ace/edit_session', 'ace/undomanager', 'ace/virtual_renderer', 'ace/multi_select', 'ace/worker/worker_client', 'ace/keyboard/hash_handler', 'ace/placeholder', 'ace/mode/folding/fold_mode', 'ace/config'], function(require, exports, module) {
171
172
173 require("./lib/fixoldbrowsers");
174
175 var dom = require("./lib/dom");
176 var event = require("./lib/event");
177
178 var Editor = require("./editor").Editor;
179 var EditSession = require("./edit_session").EditSession;
180 var UndoManager = require("./undomanager").UndoManager;
181 var Renderer = require("./virtual_renderer").VirtualRenderer;
182 var MultiSelect = require("./multi_select").MultiSelect;
183 require("./worker/worker_client");
184 require("./keyboard/hash_handler");
185 require("./placeholder");
186 require("./mode/folding/fold_mode");
187 exports.config = require("./config");
188 exports.require = require;
189 exports.edit = function(el) {
190     if (typeof(el) == "string") {
191         var _id = el;
192         var el = document.getElementById(_id);
193         if (!el)
194             throw "ace.edit can't find div #" + _id;
195     }
196
197     if (el.env && el.env.editor instanceof Editor)
198         return el.env.editor;
199
200     var doc = exports.createEditSession(dom.getInnerText(el));
201     el.innerHTML = '';
202
203     var editor = new Editor(new Renderer(el));
204     new MultiSelect(editor);
205     editor.setSession(doc);
206
207     var env = {
208         document: doc,
209         editor: editor,
210         onResize: editor.resize.bind(editor)
211     };
212     event.addListener(window, "resize", env.onResize);
213     el.env = editor.env = env;
214     return editor;
215 };
216 exports.createEditSession = function(text, mode) {
217     var doc = new EditSession(text, doc);
218     doc.setUndoManager(new UndoManager());
219     return doc;
220 }
221 exports.EditSession = EditSession;
222 exports.UndoManager = UndoManager;
223 });
224
225 ace.define('ace/lib/fixoldbrowsers', ['require', 'exports', 'module' , 'ace/lib/regexp', 'ace/lib/es5-shim'], function(require, exports, module) {
226
227
228 require("./regexp");
229 require("./es5-shim");
230
231 });
232  
233 ace.define('ace/lib/regexp', ['require', 'exports', 'module' ], function(require, exports, module) {
234
235     var real = {
236             exec: RegExp.prototype.exec,
237             test: RegExp.prototype.test,
238             match: String.prototype.match,
239             replace: String.prototype.replace,
240             split: String.prototype.split
241         },
242         compliantExecNpcg = real.exec.call(/()??/, "")[1] === undefined, // check `exec` handling of nonparticipating capturing groups
243         compliantLastIndexIncrement = function () {
244             var x = /^/g;
245             real.test.call(x, "");
246             return !x.lastIndex;
247         }();
248
249     if (compliantLastIndexIncrement && compliantExecNpcg)
250         return;
251     RegExp.prototype.exec = function (str) {
252         var match = real.exec.apply(this, arguments),
253             name, r2;
254         if ( typeof(str) == 'string' && match) {
255             if (!compliantExecNpcg && match.length > 1 && indexOf(match, "") > -1) {
256                 r2 = RegExp(this.source, real.replace.call(getNativeFlags(this), "g", ""));
257                 real.replace.call(str.slice(match.index), r2, function () {
258                     for (var i = 1; i < arguments.length - 2; i++) {
259                         if (arguments[i] === undefined)
260                             match[i] = undefined;
261                     }
262                 });
263             }
264             if (this._xregexp && this._xregexp.captureNames) {
265                 for (var i = 1; i < match.length; i++) {
266                     name = this._xregexp.captureNames[i - 1];
267                     if (name)
268                        match[name] = match[i];
269                 }
270             }
271             if (!compliantLastIndexIncrement && this.global && !match[0].length && (this.lastIndex > match.index))
272                 this.lastIndex--;
273         }
274         return match;
275     };
276     if (!compliantLastIndexIncrement) {
277         RegExp.prototype.test = function (str) {
278             var match = real.exec.call(this, str);
279             if (match && this.global && !match[0].length && (this.lastIndex > match.index))
280                 this.lastIndex--;
281             return !!match;
282         };
283     }
284
285     function getNativeFlags (regex) {
286         return (regex.global     ? "g" : "") +
287                (regex.ignoreCase ? "i" : "") +
288                (regex.multiline  ? "m" : "") +
289                (regex.extended   ? "x" : "") + // Proposed for ES4; included in AS3
290                (regex.sticky     ? "y" : "");
291     }
292
293     function indexOf (array, item, from) {
294         if (Array.prototype.indexOf) // Use the native array method if available
295             return array.indexOf(item, from);
296         for (var i = from || 0; i < array.length; i++) {
297             if (array[i] === item)
298                 return i;
299         }
300         return -1;
301     }
302
303 });
304
305 ace.define('ace/lib/es5-shim', ['require', 'exports', 'module' ], function(require, exports, module) {
306
307 function Empty() {}
308
309 if (!Function.prototype.bind) {
310     Function.prototype.bind = function bind(that) { // .length is 1
311         var target = this;
312         if (typeof target != "function") {
313             throw new TypeError("Function.prototype.bind called on incompatible " + target);
314         }
315         var args = slice.call(arguments, 1); // for normal call
316         var bound = function () {
317
318             if (this instanceof bound) {
319
320                 var result = target.apply(
321                     this,
322                     args.concat(slice.call(arguments))
323                 );
324                 if (Object(result) === result) {
325                     return result;
326                 }
327                 return this;
328
329             } else {
330                 return target.apply(
331                     that,
332                     args.concat(slice.call(arguments))
333                 );
334
335             }
336
337         };
338         if(target.prototype) {
339             Empty.prototype = target.prototype;
340             bound.prototype = new Empty();
341             Empty.prototype = null;
342         }
343         return bound;
344     };
345 }
346 var call = Function.prototype.call;
347 var prototypeOfArray = Array.prototype;
348 var prototypeOfObject = Object.prototype;
349 var slice = prototypeOfArray.slice;
350 var _toString = call.bind(prototypeOfObject.toString);
351 var owns = call.bind(prototypeOfObject.hasOwnProperty);
352 var defineGetter;
353 var defineSetter;
354 var lookupGetter;
355 var lookupSetter;
356 var supportsAccessors;
357 if ((supportsAccessors = owns(prototypeOfObject, "__defineGetter__"))) {
358     defineGetter = call.bind(prototypeOfObject.__defineGetter__);
359     defineSetter = call.bind(prototypeOfObject.__defineSetter__);
360     lookupGetter = call.bind(prototypeOfObject.__lookupGetter__);
361     lookupSetter = call.bind(prototypeOfObject.__lookupSetter__);
362 }
363 if ([1,2].splice(0).length != 2) {
364     if(function() { // test IE < 9 to splice bug - see issue #138
365         function makeArray(l) {
366             var a = new Array(l+2);
367             a[0] = a[1] = 0;
368             return a;
369         }
370         var array = [], lengthBefore;
371         
372         array.splice.apply(array, makeArray(20));
373         array.splice.apply(array, makeArray(26));
374
375         lengthBefore = array.length; //46
376         array.splice(5, 0, "XXX"); // add one element
377
378         lengthBefore + 1 == array.length
379
380         if (lengthBefore + 1 == array.length) {
381             return true;// has right splice implementation without bugs
382         }
383     }()) {//IE 6/7
384         var array_splice = Array.prototype.splice;
385         Array.prototype.splice = function(start, deleteCount) {
386             if (!arguments.length) {
387                 return [];
388             } else {
389                 return array_splice.apply(this, [
390                     start === void 0 ? 0 : start,
391                     deleteCount === void 0 ? (this.length - start) : deleteCount
392                 ].concat(slice.call(arguments, 2)))
393             }
394         };
395     } else {//IE8
396         Array.prototype.splice = function(pos, removeCount){
397             var length = this.length;
398             if (pos > 0) {
399                 if (pos > length)
400                     pos = length;
401             } else if (pos == void 0) {
402                 pos = 0;
403             } else if (pos < 0) {
404                 pos = Math.max(length + pos, 0);
405             }
406
407             if (!(pos+removeCount < length))
408                 removeCount = length - pos;
409
410             var removed = this.slice(pos, pos+removeCount);
411             var insert = slice.call(arguments, 2);
412             var add = insert.length;            
413             if (pos === length) {
414                 if (add) {
415                     this.push.apply(this, insert);
416                 }
417             } else {
418                 var remove = Math.min(removeCount, length - pos);
419                 var tailOldPos = pos + remove;
420                 var tailNewPos = tailOldPos + add - remove;
421                 var tailCount = length - tailOldPos;
422                 var lengthAfterRemove = length - remove;
423
424                 if (tailNewPos < tailOldPos) { // case A
425                     for (var i = 0; i < tailCount; ++i) {
426                         this[tailNewPos+i] = this[tailOldPos+i];
427                     }
428                 } else if (tailNewPos > tailOldPos) { // case B
429                     for (i = tailCount; i--; ) {
430                         this[tailNewPos+i] = this[tailOldPos+i];
431                     }
432                 } // else, add == remove (nothing to do)
433
434                 if (add && pos === lengthAfterRemove) {
435                     this.length = lengthAfterRemove; // truncate array
436                     this.push.apply(this, insert);
437                 } else {
438                     this.length = lengthAfterRemove + add; // reserves space
439                     for (i = 0; i < add; ++i) {
440                         this[pos+i] = insert[i];
441                     }
442                 }
443             }
444             return removed;
445         };
446     }
447 }
448 if (!Array.isArray) {
449     Array.isArray = function isArray(obj) {
450         return _toString(obj) == "[object Array]";
451     };
452 }
453 var boxedString = Object("a"),
454     splitString = boxedString[0] != "a" || !(0 in boxedString);
455
456 if (!Array.prototype.forEach) {
457     Array.prototype.forEach = function forEach(fun /*, thisp*/) {
458         var object = toObject(this),
459             self = splitString && _toString(this) == "[object String]" ?
460                 this.split("") :
461                 object,
462             thisp = arguments[1],
463             i = -1,
464             length = self.length >>> 0;
465         if (_toString(fun) != "[object Function]") {
466             throw new TypeError(); // TODO message
467         }
468
469         while (++i < length) {
470             if (i in self) {
471                 fun.call(thisp, self[i], i, object);
472             }
473         }
474     };
475 }
476 if (!Array.prototype.map) {
477     Array.prototype.map = function map(fun /*, thisp*/) {
478         var object = toObject(this),
479             self = splitString && _toString(this) == "[object String]" ?
480                 this.split("") :
481                 object,
482             length = self.length >>> 0,
483             result = Array(length),
484             thisp = arguments[1];
485         if (_toString(fun) != "[object Function]") {
486             throw new TypeError(fun + " is not a function");
487         }
488
489         for (var i = 0; i < length; i++) {
490             if (i in self)
491                 result[i] = fun.call(thisp, self[i], i, object);
492         }
493         return result;
494     };
495 }
496 if (!Array.prototype.filter) {
497     Array.prototype.filter = function filter(fun /*, thisp */) {
498         var object = toObject(this),
499             self = splitString && _toString(this) == "[object String]" ?
500                 this.split("") :
501                     object,
502             length = self.length >>> 0,
503             result = [],
504             value,
505             thisp = arguments[1];
506         if (_toString(fun) != "[object Function]") {
507             throw new TypeError(fun + " is not a function");
508         }
509
510         for (var i = 0; i < length; i++) {
511             if (i in self) {
512                 value = self[i];
513                 if (fun.call(thisp, value, i, object)) {
514                     result.push(value);
515                 }
516             }
517         }
518         return result;
519     };
520 }
521 if (!Array.prototype.every) {
522     Array.prototype.every = function every(fun /*, thisp */) {
523         var object = toObject(this),
524             self = splitString && _toString(this) == "[object String]" ?
525                 this.split("") :
526                 object,
527             length = self.length >>> 0,
528             thisp = arguments[1];
529         if (_toString(fun) != "[object Function]") {
530             throw new TypeError(fun + " is not a function");
531         }
532
533         for (var i = 0; i < length; i++) {
534             if (i in self && !fun.call(thisp, self[i], i, object)) {
535                 return false;
536             }
537         }
538         return true;
539     };
540 }
541 if (!Array.prototype.some) {
542     Array.prototype.some = function some(fun /*, thisp */) {
543         var object = toObject(this),
544             self = splitString && _toString(this) == "[object String]" ?
545                 this.split("") :
546                 object,
547             length = self.length >>> 0,
548             thisp = arguments[1];
549         if (_toString(fun) != "[object Function]") {
550             throw new TypeError(fun + " is not a function");
551         }
552
553         for (var i = 0; i < length; i++) {
554             if (i in self && fun.call(thisp, self[i], i, object)) {
555                 return true;
556             }
557         }
558         return false;
559     };
560 }
561 if (!Array.prototype.reduce) {
562     Array.prototype.reduce = function reduce(fun /*, initial*/) {
563         var object = toObject(this),
564             self = splitString && _toString(this) == "[object String]" ?
565                 this.split("") :
566                 object,
567             length = self.length >>> 0;
568         if (_toString(fun) != "[object Function]") {
569             throw new TypeError(fun + " is not a function");
570         }
571         if (!length && arguments.length == 1) {
572             throw new TypeError("reduce of empty array with no initial value");
573         }
574
575         var i = 0;
576         var result;
577         if (arguments.length >= 2) {
578             result = arguments[1];
579         } else {
580             do {
581                 if (i in self) {
582                     result = self[i++];
583                     break;
584                 }
585                 if (++i >= length) {
586                     throw new TypeError("reduce of empty array with no initial value");
587                 }
588             } while (true);
589         }
590
591         for (; i < length; i++) {
592             if (i in self) {
593                 result = fun.call(void 0, result, self[i], i, object);
594             }
595         }
596
597         return result;
598     };
599 }
600 if (!Array.prototype.reduceRight) {
601     Array.prototype.reduceRight = function reduceRight(fun /*, initial*/) {
602         var object = toObject(this),
603             self = splitString && _toString(this) == "[object String]" ?
604                 this.split("") :
605                 object,
606             length = self.length >>> 0;
607         if (_toString(fun) != "[object Function]") {
608             throw new TypeError(fun + " is not a function");
609         }
610         if (!length && arguments.length == 1) {
611             throw new TypeError("reduceRight of empty array with no initial value");
612         }
613
614         var result, i = length - 1;
615         if (arguments.length >= 2) {
616             result = arguments[1];
617         } else {
618             do {
619                 if (i in self) {
620                     result = self[i--];
621                     break;
622                 }
623                 if (--i < 0) {
624                     throw new TypeError("reduceRight of empty array with no initial value");
625                 }
626             } while (true);
627         }
628
629         do {
630             if (i in this) {
631                 result = fun.call(void 0, result, self[i], i, object);
632             }
633         } while (i--);
634
635         return result;
636     };
637 }
638 if (!Array.prototype.indexOf || ([0, 1].indexOf(1, 2) != -1)) {
639     Array.prototype.indexOf = function indexOf(sought /*, fromIndex */ ) {
640         var self = splitString && _toString(this) == "[object String]" ?
641                 this.split("") :
642                 toObject(this),
643             length = self.length >>> 0;
644
645         if (!length) {
646             return -1;
647         }
648
649         var i = 0;
650         if (arguments.length > 1) {
651             i = toInteger(arguments[1]);
652         }
653         i = i >= 0 ? i : Math.max(0, length + i);
654         for (; i < length; i++) {
655             if (i in self && self[i] === sought) {
656                 return i;
657             }
658         }
659         return -1;
660     };
661 }
662 if (!Array.prototype.lastIndexOf || ([0, 1].lastIndexOf(0, -3) != -1)) {
663     Array.prototype.lastIndexOf = function lastIndexOf(sought /*, fromIndex */) {
664         var self = splitString && _toString(this) == "[object String]" ?
665                 this.split("") :
666                 toObject(this),
667             length = self.length >>> 0;
668
669         if (!length) {
670             return -1;
671         }
672         var i = length - 1;
673         if (arguments.length > 1) {
674             i = Math.min(i, toInteger(arguments[1]));
675         }
676         i = i >= 0 ? i : length - Math.abs(i);
677         for (; i >= 0; i--) {
678             if (i in self && sought === self[i]) {
679                 return i;
680             }
681         }
682         return -1;
683     };
684 }
685 if (!Object.getPrototypeOf) {
686     Object.getPrototypeOf = function getPrototypeOf(object) {
687         return object.__proto__ || (
688             object.constructor ?
689             object.constructor.prototype :
690             prototypeOfObject
691         );
692     };
693 }
694 if (!Object.getOwnPropertyDescriptor) {
695     var ERR_NON_OBJECT = "Object.getOwnPropertyDescriptor called on a " +
696                          "non-object: ";
697     Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(object, property) {
698         if ((typeof object != "object" && typeof object != "function") || object === null)
699             throw new TypeError(ERR_NON_OBJECT + object);
700         if (!owns(object, property))
701             return;
702
703         var descriptor, getter, setter;
704         descriptor =  { enumerable: true, configurable: true };
705         if (supportsAccessors) {
706             var prototype = object.__proto__;
707             object.__proto__ = prototypeOfObject;
708
709             var getter = lookupGetter(object, property);
710             var setter = lookupSetter(object, property);
711             object.__proto__ = prototype;
712
713             if (getter || setter) {
714                 if (getter) descriptor.get = getter;
715                 if (setter) descriptor.set = setter;
716                 return descriptor;
717             }
718         }
719         descriptor.value = object[property];
720         return descriptor;
721     };
722 }
723 if (!Object.getOwnPropertyNames) {
724     Object.getOwnPropertyNames = function getOwnPropertyNames(object) {
725         return Object.keys(object);
726     };
727 }
728 if (!Object.create) {
729     var createEmpty;
730     if (Object.prototype.__proto__ === null) {
731         createEmpty = function () {
732             return { "__proto__": null };
733         };
734     } else {
735         createEmpty = function () {
736             var empty = {};
737             for (var i in empty)
738                 empty[i] = null;
739             empty.constructor =
740             empty.hasOwnProperty =
741             empty.propertyIsEnumerable =
742             empty.isPrototypeOf =
743             empty.toLocaleString =
744             empty.toString =
745             empty.valueOf =
746             empty.__proto__ = null;
747             return empty;
748         }
749     }
750
751     Object.create = function create(prototype, properties) {
752         var object;
753         if (prototype === null) {
754             object = createEmpty();
755         } else {
756             if (typeof prototype != "object")
757                 throw new TypeError("typeof prototype["+(typeof prototype)+"] != 'object'");
758             var Type = function () {};
759             Type.prototype = prototype;
760             object = new Type();
761             object.__proto__ = prototype;
762         }
763         if (properties !== void 0)
764             Object.defineProperties(object, properties);
765         return object;
766     };
767 }
768
769 function doesDefinePropertyWork(object) {
770     try {
771         Object.defineProperty(object, "sentinel", {});
772         return "sentinel" in object;
773     } catch (exception) {
774     }
775 }
776 if (Object.defineProperty) {
777     var definePropertyWorksOnObject = doesDefinePropertyWork({});
778     var definePropertyWorksOnDom = typeof document == "undefined" ||
779         doesDefinePropertyWork(document.createElement("div"));
780     if (!definePropertyWorksOnObject || !definePropertyWorksOnDom) {
781         var definePropertyFallback = Object.defineProperty;
782     }
783 }
784
785 if (!Object.defineProperty || definePropertyFallback) {
786     var ERR_NON_OBJECT_DESCRIPTOR = "Property description must be an object: ";
787     var ERR_NON_OBJECT_TARGET = "Object.defineProperty called on non-object: "
788     var ERR_ACCESSORS_NOT_SUPPORTED = "getters & setters can not be defined " +
789                                       "on this javascript engine";
790
791     Object.defineProperty = function defineProperty(object, property, descriptor) {
792         if ((typeof object != "object" && typeof object != "function") || object === null)
793             throw new TypeError(ERR_NON_OBJECT_TARGET + object);
794         if ((typeof descriptor != "object" && typeof descriptor != "function") || descriptor === null)
795             throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR + descriptor);
796         if (definePropertyFallback) {
797             try {
798                 return definePropertyFallback.call(Object, object, property, descriptor);
799             } catch (exception) {
800             }
801         }
802         if (owns(descriptor, "value")) {
803
804             if (supportsAccessors && (lookupGetter(object, property) ||
805                                       lookupSetter(object, property)))
806             {
807                 var prototype = object.__proto__;
808                 object.__proto__ = prototypeOfObject;
809                 delete object[property];
810                 object[property] = descriptor.value;
811                 object.__proto__ = prototype;
812             } else {
813                 object[property] = descriptor.value;
814             }
815         } else {
816             if (!supportsAccessors)
817                 throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);
818             if (owns(descriptor, "get"))
819                 defineGetter(object, property, descriptor.get);
820             if (owns(descriptor, "set"))
821                 defineSetter(object, property, descriptor.set);
822         }
823
824         return object;
825     };
826 }
827 if (!Object.defineProperties) {
828     Object.defineProperties = function defineProperties(object, properties) {
829         for (var property in properties) {
830             if (owns(properties, property))
831                 Object.defineProperty(object, property, properties[property]);
832         }
833         return object;
834     };
835 }
836 if (!Object.seal) {
837     Object.seal = function seal(object) {
838         return object;
839     };
840 }
841 if (!Object.freeze) {
842     Object.freeze = function freeze(object) {
843         return object;
844     };
845 }
846 try {
847     Object.freeze(function () {});
848 } catch (exception) {
849     Object.freeze = (function freeze(freezeObject) {
850         return function freeze(object) {
851             if (typeof object == "function") {
852                 return object;
853             } else {
854                 return freezeObject(object);
855             }
856         };
857     })(Object.freeze);
858 }
859 if (!Object.preventExtensions) {
860     Object.preventExtensions = function preventExtensions(object) {
861         return object;
862     };
863 }
864 if (!Object.isSealed) {
865     Object.isSealed = function isSealed(object) {
866         return false;
867     };
868 }
869 if (!Object.isFrozen) {
870     Object.isFrozen = function isFrozen(object) {
871         return false;
872     };
873 }
874 if (!Object.isExtensible) {
875     Object.isExtensible = function isExtensible(object) {
876         if (Object(object) === object) {
877             throw new TypeError(); // TODO message
878         }
879         var name = '';
880         while (owns(object, name)) {
881             name += '?';
882         }
883         object[name] = true;
884         var returnValue = owns(object, name);
885         delete object[name];
886         return returnValue;
887     };
888 }
889 if (!Object.keys) {
890     var hasDontEnumBug = true,
891         dontEnums = [
892             "toString",
893             "toLocaleString",
894             "valueOf",
895             "hasOwnProperty",
896             "isPrototypeOf",
897             "propertyIsEnumerable",
898             "constructor"
899         ],
900         dontEnumsLength = dontEnums.length;
901
902     for (var key in {"toString": null}) {
903         hasDontEnumBug = false;
904     }
905
906     Object.keys = function keys(object) {
907
908         if (
909             (typeof object != "object" && typeof object != "function") ||
910             object === null
911         ) {
912             throw new TypeError("Object.keys called on a non-object");
913         }
914
915         var keys = [];
916         for (var name in object) {
917             if (owns(object, name)) {
918                 keys.push(name);
919             }
920         }
921
922         if (hasDontEnumBug) {
923             for (var i = 0, ii = dontEnumsLength; i < ii; i++) {
924                 var dontEnum = dontEnums[i];
925                 if (owns(object, dontEnum)) {
926                     keys.push(dontEnum);
927                 }
928             }
929         }
930         return keys;
931     };
932
933 }
934 if (!Date.now) {
935     Date.now = function now() {
936         return new Date().getTime();
937     };
938 }
939 if("0".split(void 0, 0).length) {
940     var string_split = String.prototype.split;
941     String.prototype.split = function(separator, limit) {
942         if(separator === void 0 && limit === 0)return [];
943         return string_split.apply(this, arguments);
944     }
945 }
946 if("".substr && "0b".substr(-1) !== "b") {
947     var string_substr = String.prototype.substr;
948     String.prototype.substr = function(start, length) {
949         return string_substr.call(
950             this,
951             start < 0 ? (start = this.length + start) < 0 ? 0 : start : start,
952             length
953         );
954     }
955 }
956 var ws = "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003" +
957     "\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028" +
958     "\u2029\uFEFF";
959 if (!String.prototype.trim || ws.trim()) {
960     ws = "[" + ws + "]";
961     var trimBeginRegexp = new RegExp("^" + ws + ws + "*"),
962         trimEndRegexp = new RegExp(ws + ws + "*$");
963     String.prototype.trim = function trim() {
964         if (this === undefined || this === null) {
965             throw new TypeError("can't convert "+this+" to object");
966         }
967         return String(this)
968             .replace(trimBeginRegexp, "")
969             .replace(trimEndRegexp, "");
970     };
971 }
972
973 function toInteger(n) {
974     n = +n;
975     if (n !== n) { // isNaN
976         n = 0;
977     } else if (n !== 0 && n !== (1/0) && n !== -(1/0)) {
978         n = (n > 0 || -1) * Math.floor(Math.abs(n));
979     }
980     return n;
981 }
982
983 function isPrimitive(input) {
984     var type = typeof input;
985     return (
986         input === null ||
987         type === "undefined" ||
988         type === "boolean" ||
989         type === "number" ||
990         type === "string"
991     );
992 }
993
994 function toPrimitive(input) {
995     var val, valueOf, toString;
996     if (isPrimitive(input)) {
997         return input;
998     }
999     valueOf = input.valueOf;
1000     if (typeof valueOf === "function") {
1001         val = valueOf.call(input);
1002         if (isPrimitive(val)) {
1003             return val;
1004         }
1005     }
1006     toString = input.toString;
1007     if (typeof toString === "function") {
1008         val = toString.call(input);
1009         if (isPrimitive(val)) {
1010             return val;
1011         }
1012     }
1013     throw new TypeError();
1014 }
1015 var toObject = function (o) {
1016     if (o == null) { // this matches both null and undefined
1017         throw new TypeError("can't convert "+o+" to object");
1018     }
1019     return Object(o);
1020 };
1021
1022 });
1023
1024 ace.define('ace/lib/dom', ['require', 'exports', 'module' ], function(require, exports, module) {
1025
1026
1027 var XHTML_NS = "http://www.w3.org/1999/xhtml";
1028
1029 exports.createElement = function(tag, ns) {
1030     return document.createElementNS ?
1031            document.createElementNS(ns || XHTML_NS, tag) :
1032            document.createElement(tag);
1033 };
1034
1035 exports.setText = function(elem, text) {
1036     if (elem.innerText !== undefined) {
1037         elem.innerText = text;
1038     }
1039     if (elem.textContent !== undefined) {
1040         elem.textContent = text;
1041     }
1042 };
1043
1044 exports.hasCssClass = function(el, name) {
1045     var classes = el.className.split(/\s+/g);
1046     return classes.indexOf(name) !== -1;
1047 };
1048 exports.addCssClass = function(el, name) {
1049     if (!exports.hasCssClass(el, name)) {
1050         el.className += " " + name;
1051     }
1052 };
1053 exports.removeCssClass = function(el, name) {
1054     var classes = el.className.split(/\s+/g);
1055     while (true) {
1056         var index = classes.indexOf(name);
1057         if (index == -1) {
1058             break;
1059         }
1060         classes.splice(index, 1);
1061     }
1062     el.className = classes.join(" ");
1063 };
1064
1065 exports.toggleCssClass = function(el, name) {
1066     var classes = el.className.split(/\s+/g), add = true;
1067     while (true) {
1068         var index = classes.indexOf(name);
1069         if (index == -1) {
1070             break;
1071         }
1072         add = false;
1073         classes.splice(index, 1);
1074     }
1075     if(add)
1076         classes.push(name);
1077
1078     el.className = classes.join(" ");
1079     return add;
1080 };
1081 exports.setCssClass = function(node, className, include) {
1082     if (include) {
1083         exports.addCssClass(node, className);
1084     } else {
1085         exports.removeCssClass(node, className);
1086     }
1087 };
1088
1089 exports.hasCssString = function(id, doc) {
1090     var index = 0, sheets;
1091     doc = doc || document;
1092
1093     if (doc.createStyleSheet && (sheets = doc.styleSheets)) {
1094         while (index < sheets.length)
1095             if (sheets[index++].owningElement.id === id) return true;
1096     } else if ((sheets = doc.getElementsByTagName("style"))) {
1097         while (index < sheets.length)
1098             if (sheets[index++].id === id) return true;
1099     }
1100
1101     return false;
1102 };
1103
1104 exports.importCssString = function importCssString(cssText, id, doc) {
1105     doc = doc || document;
1106     if (id && exports.hasCssString(id, doc))
1107         return null;
1108     
1109     var style;
1110     
1111     if (doc.createStyleSheet) {
1112         style = doc.createStyleSheet();
1113         style.cssText = cssText;
1114         if (id)
1115             style.owningElement.id = id;
1116     } else {
1117         style = doc.createElementNS
1118             ? doc.createElementNS(XHTML_NS, "style")
1119             : doc.createElement("style");
1120
1121         style.appendChild(doc.createTextNode(cssText));
1122         if (id)
1123             style.id = id;
1124
1125         var head = doc.getElementsByTagName("head")[0] || doc.documentElement;
1126         head.appendChild(style);
1127     }
1128 };
1129
1130 exports.importCssStylsheet = function(uri, doc) {
1131     if (doc.createStyleSheet) {
1132         doc.createStyleSheet(uri);
1133     } else {
1134         var link = exports.createElement('link');
1135         link.rel = 'stylesheet';
1136         link.href = uri;
1137
1138         var head = doc.getElementsByTagName("head")[0] || doc.documentElement;
1139         head.appendChild(link);
1140     }
1141 };
1142
1143 exports.getInnerWidth = function(element) {
1144     return (
1145         parseInt(exports.computedStyle(element, "paddingLeft"), 10) +
1146         parseInt(exports.computedStyle(element, "paddingRight"), 10) + 
1147         element.clientWidth
1148     );
1149 };
1150
1151 exports.getInnerHeight = function(element) {
1152     return (
1153         parseInt(exports.computedStyle(element, "paddingTop"), 10) +
1154         parseInt(exports.computedStyle(element, "paddingBottom"), 10) +
1155         element.clientHeight
1156     );
1157 };
1158
1159 if (window.pageYOffset !== undefined) {
1160     exports.getPageScrollTop = function() {
1161         return window.pageYOffset;
1162     };
1163
1164     exports.getPageScrollLeft = function() {
1165         return window.pageXOffset;
1166     };
1167 }
1168 else {
1169     exports.getPageScrollTop = function() {
1170         return document.body.scrollTop;
1171     };
1172
1173     exports.getPageScrollLeft = function() {
1174         return document.body.scrollLeft;
1175     };
1176 }
1177
1178 if (window.getComputedStyle)
1179     exports.computedStyle = function(element, style) {
1180         if (style)
1181             return (window.getComputedStyle(element, "") || {})[style] || "";
1182         return window.getComputedStyle(element, "") || {};
1183     };
1184 else
1185     exports.computedStyle = function(element, style) {
1186         if (style)
1187             return element.currentStyle[style];
1188         return element.currentStyle;
1189     };
1190
1191 exports.scrollbarWidth = function(document) {
1192     var inner = exports.createElement("ace_inner");
1193     inner.style.width = "100%";
1194     inner.style.minWidth = "0px";
1195     inner.style.height = "200px";
1196     inner.style.display = "block";
1197
1198     var outer = exports.createElement("ace_outer");
1199     var style = outer.style;
1200
1201     style.position = "absolute";
1202     style.left = "-10000px";
1203     style.overflow = "hidden";
1204     style.width = "200px";
1205     style.minWidth = "0px";
1206     style.height = "150px";
1207     style.display = "block";
1208
1209     outer.appendChild(inner);
1210
1211     var body = document.documentElement;
1212     body.appendChild(outer);
1213
1214     var noScrollbar = inner.offsetWidth;
1215
1216     style.overflow = "scroll";
1217     var withScrollbar = inner.offsetWidth;
1218
1219     if (noScrollbar == withScrollbar) {
1220         withScrollbar = outer.clientWidth;
1221     }
1222
1223     body.removeChild(outer);
1224
1225     return noScrollbar-withScrollbar;
1226 };
1227 exports.setInnerHtml = function(el, innerHtml) {
1228     var element = el.cloneNode(false);//document.createElement("div");
1229     element.innerHTML = innerHtml;
1230     el.parentNode.replaceChild(element, el);
1231     return element;
1232 };
1233
1234 exports.setInnerText = function(el, innerText) {
1235     var document = el.ownerDocument;
1236     if (document.body && "textContent" in document.body)
1237         el.textContent = innerText;
1238     else
1239         el.innerText = innerText;
1240
1241 };
1242
1243 exports.getInnerText = function(el) {
1244     var document = el.ownerDocument;
1245     if (document.body && "textContent" in document.body)
1246         return el.textContent;
1247     else
1248          return el.innerText || el.textContent || "";
1249 };
1250
1251 exports.getParentWindow = function(document) {
1252     return document.defaultView || document.parentWindow;
1253 };
1254
1255 });
1256
1257 ace.define('ace/lib/event', ['require', 'exports', 'module' , 'ace/lib/keys', 'ace/lib/useragent', 'ace/lib/dom'], function(require, exports, module) {
1258
1259
1260 var keys = require("./keys");
1261 var useragent = require("./useragent");
1262 var dom = require("./dom");
1263
1264 exports.addListener = function(elem, type, callback) {
1265     if (elem.addEventListener) {
1266         return elem.addEventListener(type, callback, false);
1267     }
1268     if (elem.attachEvent) {
1269         var wrapper = function() {
1270             callback(window.event);
1271         };
1272         callback._wrapper = wrapper;
1273         elem.attachEvent("on" + type, wrapper);
1274     }
1275 };
1276
1277 exports.removeListener = function(elem, type, callback) {
1278     if (elem.removeEventListener) {
1279         return elem.removeEventListener(type, callback, false);
1280     }
1281     if (elem.detachEvent) {
1282         elem.detachEvent("on" + type, callback._wrapper || callback);
1283     }
1284 };
1285 exports.stopEvent = function(e) {
1286     exports.stopPropagation(e);
1287     exports.preventDefault(e);
1288     return false;
1289 };
1290
1291 exports.stopPropagation = function(e) {
1292     if (e.stopPropagation)
1293         e.stopPropagation();
1294     else
1295         e.cancelBubble = true;
1296 };
1297
1298 exports.preventDefault = function(e) {
1299     if (e.preventDefault)
1300         e.preventDefault();
1301     else
1302         e.returnValue = false;
1303 };
1304 exports.getButton = function(e) {
1305     if (e.type == "dblclick")
1306         return 0;
1307     if (e.type == "contextmenu" || (e.ctrlKey && useragent.isMac))
1308         return 2;
1309     if (e.preventDefault) {
1310         return e.button;
1311     }
1312     else {
1313         return {1:0, 2:2, 4:1}[e.button];
1314     }
1315 };
1316
1317 if (document.documentElement.setCapture) {
1318     exports.capture = function(el, eventHandler, releaseCaptureHandler) {
1319         var called = false;
1320         function onReleaseCapture(e) {
1321             eventHandler(e);
1322
1323             if (!called) {
1324                 called = true;
1325                 releaseCaptureHandler(e);
1326             }
1327
1328             exports.removeListener(el, "mousemove", eventHandler);
1329             exports.removeListener(el, "mouseup", onReleaseCapture);
1330             exports.removeListener(el, "losecapture", onReleaseCapture);
1331
1332             el.releaseCapture();
1333         }
1334
1335         exports.addListener(el, "mousemove", eventHandler);
1336         exports.addListener(el, "mouseup", onReleaseCapture);
1337         exports.addListener(el, "losecapture", onReleaseCapture);
1338         el.setCapture();
1339     };
1340 }
1341 else {
1342     exports.capture = function(el, eventHandler, releaseCaptureHandler) {
1343         function onMouseUp(e) {
1344             eventHandler && eventHandler(e);
1345             releaseCaptureHandler && releaseCaptureHandler(e);
1346
1347             document.removeEventListener("mousemove", eventHandler, true);
1348             document.removeEventListener("mouseup", onMouseUp, true);
1349
1350             e.stopPropagation();
1351         }
1352
1353         document.addEventListener("mousemove", eventHandler, true);
1354         document.addEventListener("mouseup", onMouseUp, true);
1355     };
1356 }
1357
1358 exports.addMouseWheelListener = function(el, callback) {
1359     var factor = 8;
1360     var listener = function(e) {
1361         if (e.wheelDelta !== undefined) {
1362             if (e.wheelDeltaX !== undefined) {
1363                 e.wheelX = -e.wheelDeltaX / factor;
1364                 e.wheelY = -e.wheelDeltaY / factor;
1365             } else {
1366                 e.wheelX = 0;
1367                 e.wheelY = -e.wheelDelta / factor;
1368             }
1369         }
1370         else {
1371             if (e.axis && e.axis == e.HORIZONTAL_AXIS) {
1372                 e.wheelX = (e.detail || 0) * 5;
1373                 e.wheelY = 0;
1374             } else {
1375                 e.wheelX = 0;
1376                 e.wheelY = (e.detail || 0) * 5;
1377             }
1378         }
1379         callback(e);
1380     };
1381     exports.addListener(el, "DOMMouseScroll", listener);
1382     exports.addListener(el, "mousewheel", listener);
1383 };
1384
1385 exports.addMultiMouseDownListener = function(el, timeouts, eventHandler, callbackName) {
1386     var clicks = 0;
1387     var startX, startY, timer;
1388     var eventNames = {
1389         2: "dblclick",
1390         3: "tripleclick",
1391         4: "quadclick"
1392     };
1393
1394     exports.addListener(el, "mousedown", function(e) {
1395         if (exports.getButton(e) != 0) {
1396             clicks = 0;
1397         } else {
1398             var isNewClick = Math.abs(e.clientX - startX) > 5 || Math.abs(e.clientY - startY) > 5;
1399
1400             if (!timer || isNewClick)
1401                 clicks = 0;
1402
1403             clicks += 1;
1404
1405             if (timer)
1406                 clearTimeout(timer)
1407             timer = setTimeout(function() {timer = null}, timeouts[clicks - 1] || 600);
1408         }
1409         if (clicks == 1) {
1410             startX = e.clientX;
1411             startY = e.clientY;
1412         }
1413
1414         eventHandler[callbackName]("mousedown", e);
1415
1416         if (clicks > 4)
1417             clicks = 0;
1418         else if (clicks > 1)
1419             return eventHandler[callbackName](eventNames[clicks], e);
1420     });
1421
1422     if (useragent.isOldIE) {
1423         exports.addListener(el, "dblclick", function(e) {
1424             clicks = 2;
1425             if (timer)
1426                 clearTimeout(timer);
1427             timer = setTimeout(function() {timer = null}, timeouts[clicks - 1] || 600);
1428             eventHandler[callbackName]("mousedown", e);
1429             eventHandler[callbackName](eventNames[clicks], e);
1430         });
1431     }
1432 };
1433
1434 function normalizeCommandKeys(callback, e, keyCode) {
1435     var hashId = 0;
1436     if ((useragent.isOpera && !("KeyboardEvent" in window)) && useragent.isMac) {
1437         hashId = 0 | (e.metaKey ? 1 : 0) | (e.altKey ? 2 : 0)
1438             | (e.shiftKey ? 4 : 0) | (e.ctrlKey ? 8 : 0);
1439     } else {
1440         hashId = 0 | (e.ctrlKey ? 1 : 0) | (e.altKey ? 2 : 0)
1441             | (e.shiftKey ? 4 : 0) | (e.metaKey ? 8 : 0);
1442     }
1443
1444     if (keyCode in keys.MODIFIER_KEYS) {
1445         switch (keys.MODIFIER_KEYS[keyCode]) {
1446             case "Alt":
1447                 hashId = 2;
1448                 break;
1449             case "Shift":
1450                 hashId = 4;
1451                 break;
1452             case "Ctrl":
1453                 hashId = 1;
1454                 break;
1455             default:
1456                 hashId = 8;
1457                 break;
1458         }
1459         keyCode = 0;
1460     }
1461
1462     if (hashId & 8 && (keyCode == 91 || keyCode == 93)) {
1463         keyCode = 0;
1464     }
1465     if (!hashId && !(keyCode in keys.FUNCTION_KEYS) && !(keyCode in keys.PRINTABLE_KEYS)) {
1466         return false;
1467     }
1468     return callback(e, hashId, keyCode);
1469 }
1470
1471 exports.addCommandKeyListener = function(el, callback) {
1472     var addListener = exports.addListener;
1473     if (useragent.isOldGecko || (useragent.isOpera && !("KeyboardEvent" in window))) {
1474         var lastKeyDownKeyCode = null;
1475         addListener(el, "keydown", function(e) {
1476             lastKeyDownKeyCode = e.keyCode;
1477         });
1478         addListener(el, "keypress", function(e) {
1479             return normalizeCommandKeys(callback, e, lastKeyDownKeyCode);
1480         });
1481     } else {
1482         var lastDown = null;
1483
1484         addListener(el, "keydown", function(e) {
1485             lastDown = e.keyIdentifier || e.keyCode;
1486             return normalizeCommandKeys(callback, e, e.keyCode);
1487         });
1488     }
1489 };
1490
1491 if (window.postMessage && !useragent.isOldIE) {
1492     var postMessageId = 1;
1493     exports.nextTick = function(callback, win) {
1494         win = win || window;
1495         var messageName = "zero-timeout-message-" + postMessageId;
1496         exports.addListener(win, "message", function listener(e) {
1497             if (e.data == messageName) {
1498                 exports.stopPropagation(e);
1499                 exports.removeListener(win, "message", listener);
1500                 callback();
1501             }
1502         });
1503         win.postMessage(messageName, "*");
1504     };
1505 }
1506
1507
1508 exports.nextFrame = window.requestAnimationFrame ||
1509     window.oRequestAnimationFrame ||
1510     window.msRequestAnimationFrame ||
1511     window.mozRequestAnimationFrame ||
1512     window.webkitRequestAnimationFrame;
1513
1514 if (exports.nextFrame)
1515     exports.nextFrame = exports.nextFrame.bind(window);
1516 else
1517     exports.nextFrame = function(callback) {
1518         setTimeout(callback, 17);
1519     };
1520 });
1521
1522 ace.define('ace/lib/keys', ['require', 'exports', 'module' , 'ace/lib/oop'], function(require, exports, module) {
1523
1524
1525 var oop = require("./oop");
1526 var Keys = (function() {
1527     var ret = {
1528         MODIFIER_KEYS: {
1529             16: 'Shift', 17: 'Ctrl', 18: 'Alt', 224: 'Meta'
1530         },
1531
1532         KEY_MODS: {
1533             "ctrl": 1, "alt": 2, "option" : 2,
1534             "shift": 4, "meta": 8, "command": 8
1535         },
1536
1537         FUNCTION_KEYS : {
1538             8  : "Backspace",
1539             9  : "Tab",
1540             13 : "Return",
1541             19 : "Pause",
1542             27 : "Esc",
1543             32 : "Space",
1544             33 : "PageUp",
1545             34 : "PageDown",
1546             35 : "End",
1547             36 : "Home",
1548             37 : "Left",
1549             38 : "Up",
1550             39 : "Right",
1551             40 : "Down",
1552             44 : "Print",
1553             45 : "Insert",
1554             46 : "Delete",
1555             96 : "Numpad0",
1556             97 : "Numpad1",
1557             98 : "Numpad2",
1558             99 : "Numpad3",
1559             100: "Numpad4",
1560             101: "Numpad5",
1561             102: "Numpad6",
1562             103: "Numpad7",
1563             104: "Numpad8",
1564             105: "Numpad9",
1565             112: "F1",
1566             113: "F2",
1567             114: "F3",
1568             115: "F4",
1569             116: "F5",
1570             117: "F6",
1571             118: "F7",
1572             119: "F8",
1573             120: "F9",
1574             121: "F10",
1575             122: "F11",
1576             123: "F12",
1577             144: "Numlock",
1578             145: "Scrolllock"
1579         },
1580
1581         PRINTABLE_KEYS: {
1582            32: ' ',  48: '0',  49: '1',  50: '2',  51: '3',  52: '4', 53:  '5',
1583            54: '6',  55: '7',  56: '8',  57: '9',  59: ';',  61: '=', 65:  'a',
1584            66: 'b',  67: 'c',  68: 'd',  69: 'e',  70: 'f',  71: 'g', 72:  'h',
1585            73: 'i',  74: 'j',  75: 'k',  76: 'l',  77: 'm',  78: 'n', 79:  'o',
1586            80: 'p',  81: 'q',  82: 'r',  83: 's',  84: 't',  85: 'u', 86:  'v',
1587            87: 'w',  88: 'x',  89: 'y',  90: 'z', 107: '+', 109: '-', 110: '.',
1588           188: ',', 190: '.', 191: '/', 192: '`', 219: '[', 220: '\\',
1589           221: ']', 222: '\''
1590         }
1591     };
1592     for (var i in ret.FUNCTION_KEYS) {
1593         var name = ret.FUNCTION_KEYS[i].toLowerCase();
1594         ret[name] = parseInt(i, 10);
1595     }
1596     oop.mixin(ret, ret.MODIFIER_KEYS);
1597     oop.mixin(ret, ret.PRINTABLE_KEYS);
1598     oop.mixin(ret, ret.FUNCTION_KEYS);
1599     ret.enter = ret["return"];
1600     ret.escape = ret.esc;
1601     ret.del = ret["delete"];
1602     ret[173] = '-';
1603
1604     return ret;
1605 })();
1606 oop.mixin(exports, Keys);
1607
1608 exports.keyCodeToString = function(keyCode) {
1609     return (Keys[keyCode] || String.fromCharCode(keyCode)).toLowerCase();
1610 }
1611
1612 });
1613
1614 ace.define('ace/lib/oop', ['require', 'exports', 'module' ], function(require, exports, module) {
1615
1616
1617 exports.inherits = (function() {
1618     var tempCtor = function() {};
1619     return function(ctor, superCtor) {
1620         tempCtor.prototype = superCtor.prototype;
1621         ctor.super_ = superCtor.prototype;
1622         ctor.prototype = new tempCtor();
1623         ctor.prototype.constructor = ctor;
1624     };
1625 }());
1626
1627 exports.mixin = function(obj, mixin) {
1628     for (var key in mixin) {
1629         obj[key] = mixin[key];
1630     }
1631 };
1632
1633 exports.implement = function(proto, mixin) {
1634     exports.mixin(proto, mixin);
1635 };
1636
1637 });
1638
1639 ace.define('ace/lib/useragent', ['require', 'exports', 'module' ], function(require, exports, module) {
1640 exports.OS = {
1641     LINUX: "LINUX",
1642     MAC: "MAC",
1643     WINDOWS: "WINDOWS"
1644 };
1645 exports.getOS = function() {
1646     if (exports.isMac) {
1647         return exports.OS.MAC;
1648     } else if (exports.isLinux) {
1649         return exports.OS.LINUX;
1650     } else {
1651         return exports.OS.WINDOWS;
1652     }
1653 };
1654 if (typeof navigator != "object")
1655     return;
1656
1657 var os = (navigator.platform.match(/mac|win|linux/i) || ["other"])[0].toLowerCase();
1658 var ua = navigator.userAgent;
1659 exports.isWin = (os == "win");
1660 exports.isMac = (os == "mac");
1661 exports.isLinux = (os == "linux");
1662 exports.isIE = 
1663     (navigator.appName == "Microsoft Internet Explorer" || navigator.appName.indexOf("MSAppHost") >= 0)
1664     && parseFloat(navigator.userAgent.match(/MSIE ([0-9]+[\.0-9]+)/)[1]);
1665     
1666 exports.isOldIE = exports.isIE && exports.isIE < 9;
1667 exports.isGecko = exports.isMozilla = window.controllers && window.navigator.product === "Gecko";
1668 exports.isOldGecko = exports.isGecko && parseInt((navigator.userAgent.match(/rv\:(\d+)/)||[])[1], 10) < 4;
1669 exports.isOpera = window.opera && Object.prototype.toString.call(window.opera) == "[object Opera]";
1670 exports.isWebKit = parseFloat(ua.split("WebKit/")[1]) || undefined;
1671
1672 exports.isChrome = parseFloat(ua.split(" Chrome/")[1]) || undefined;
1673
1674 exports.isAIR = ua.indexOf("AdobeAIR") >= 0;
1675
1676 exports.isIPad = ua.indexOf("iPad") >= 0;
1677
1678 exports.isTouchPad = ua.indexOf("TouchPad") >= 0;
1679
1680 });
1681
1682 ace.define('ace/editor', ['require', 'exports', 'module' , 'ace/lib/fixoldbrowsers', 'ace/lib/oop', 'ace/lib/lang', 'ace/lib/useragent', 'ace/keyboard/textinput', 'ace/mouse/mouse_handler', 'ace/mouse/fold_handler', 'ace/keyboard/keybinding', 'ace/edit_session', 'ace/search', 'ace/range', 'ace/lib/event_emitter', 'ace/commands/command_manager', 'ace/commands/default_commands', 'ace/config'], function(require, exports, module) {
1683
1684
1685 require("./lib/fixoldbrowsers");
1686
1687 var oop = require("./lib/oop");
1688 var lang = require("./lib/lang");
1689 var useragent = require("./lib/useragent");
1690 var TextInput = require("./keyboard/textinput").TextInput;
1691 var MouseHandler = require("./mouse/mouse_handler").MouseHandler;
1692 var FoldHandler = require("./mouse/fold_handler").FoldHandler;
1693 var KeyBinding = require("./keyboard/keybinding").KeyBinding;
1694 var EditSession = require("./edit_session").EditSession;
1695 var Search = require("./search").Search;
1696 var Range = require("./range").Range;
1697 var EventEmitter = require("./lib/event_emitter").EventEmitter;
1698 var CommandManager = require("./commands/command_manager").CommandManager;
1699 var defaultCommands = require("./commands/default_commands").commands;
1700 var config = require("./config");
1701 var Editor = function(renderer, session) {
1702     var container = renderer.getContainerElement();
1703     this.container = container;
1704     this.renderer = renderer;
1705
1706     this.commands = new CommandManager(useragent.isMac ? "mac" : "win", defaultCommands);
1707     this.textInput  = new TextInput(renderer.getTextAreaContainer(), this);
1708     this.renderer.textarea = this.textInput.getElement();
1709     this.keyBinding = new KeyBinding(this);
1710     this.$mouseHandler = new MouseHandler(this);
1711     new FoldHandler(this);
1712
1713     this.$blockScrolling = 0;
1714     this.$search = new Search().set({
1715         wrap: true
1716     });
1717
1718     this.setSession(session || new EditSession(""));
1719 };
1720
1721 (function(){
1722
1723     oop.implement(this, EventEmitter);
1724     this.setKeyboardHandler = function(keyboardHandler) {
1725         if (typeof keyboardHandler == "string" && keyboardHandler) {
1726             this.$keybindingId = keyboardHandler;
1727             var _self = this;
1728             config.loadModule(["keybinding", keyboardHandler], function(module) {
1729                 if (_self.$keybindingId == keyboardHandler)
1730                     _self.keyBinding.setKeyboardHandler(module && module.handler);
1731             });
1732         } else {
1733             delete this.$keybindingId;
1734             this.keyBinding.setKeyboardHandler(keyboardHandler);
1735         }
1736     };
1737     this.getKeyboardHandler = function() {
1738         return this.keyBinding.getKeyboardHandler();
1739     };
1740     this.setSession = function(session) {
1741         if (this.session == session)
1742             return;
1743
1744         if (this.session) {
1745             var oldSession = this.session;
1746             this.session.removeEventListener("change", this.$onDocumentChange);
1747             this.session.removeEventListener("changeMode", this.$onChangeMode);
1748             this.session.removeEventListener("tokenizerUpdate", this.$onTokenizerUpdate);
1749             this.session.removeEventListener("changeTabSize", this.$onChangeTabSize);
1750             this.session.removeEventListener("changeWrapLimit", this.$onChangeWrapLimit);
1751             this.session.removeEventListener("changeWrapMode", this.$onChangeWrapMode);
1752             this.session.removeEventListener("onChangeFold", this.$onChangeFold);
1753             this.session.removeEventListener("changeFrontMarker", this.$onChangeFrontMarker);
1754             this.session.removeEventListener("changeBackMarker", this.$onChangeBackMarker);
1755             this.session.removeEventListener("changeBreakpoint", this.$onChangeBreakpoint);
1756             this.session.removeEventListener("changeAnnotation", this.$onChangeAnnotation);
1757             this.session.removeEventListener("changeOverwrite", this.$onCursorChange);
1758             this.session.removeEventListener("changeScrollTop", this.$onScrollTopChange);
1759             this.session.removeEventListener("changeLeftTop", this.$onScrollLeftChange);
1760
1761             var selection = this.session.getSelection();
1762             selection.removeEventListener("changeCursor", this.$onCursorChange);
1763             selection.removeEventListener("changeSelection", this.$onSelectionChange);
1764         }
1765
1766         this.session = session;
1767
1768         this.$onDocumentChange = this.onDocumentChange.bind(this);
1769         session.addEventListener("change", this.$onDocumentChange);
1770         this.renderer.setSession(session);
1771
1772         this.$onChangeMode = this.onChangeMode.bind(this);
1773         session.addEventListener("changeMode", this.$onChangeMode);
1774
1775         this.$onTokenizerUpdate = this.onTokenizerUpdate.bind(this);
1776         session.addEventListener("tokenizerUpdate", this.$onTokenizerUpdate);
1777
1778         this.$onChangeTabSize = this.renderer.onChangeTabSize.bind(this.renderer);
1779         session.addEventListener("changeTabSize", this.$onChangeTabSize);
1780
1781         this.$onChangeWrapLimit = this.onChangeWrapLimit.bind(this);
1782         session.addEventListener("changeWrapLimit", this.$onChangeWrapLimit);
1783
1784         this.$onChangeWrapMode = this.onChangeWrapMode.bind(this);
1785         session.addEventListener("changeWrapMode", this.$onChangeWrapMode);
1786
1787         this.$onChangeFold = this.onChangeFold.bind(this);
1788         session.addEventListener("changeFold", this.$onChangeFold);
1789
1790         this.$onChangeFrontMarker = this.onChangeFrontMarker.bind(this);
1791         this.session.addEventListener("changeFrontMarker", this.$onChangeFrontMarker);
1792
1793         this.$onChangeBackMarker = this.onChangeBackMarker.bind(this);
1794         this.session.addEventListener("changeBackMarker", this.$onChangeBackMarker);
1795
1796         this.$onChangeBreakpoint = this.onChangeBreakpoint.bind(this);
1797         this.session.addEventListener("changeBreakpoint", this.$onChangeBreakpoint);
1798
1799         this.$onChangeAnnotation = this.onChangeAnnotation.bind(this);
1800         this.session.addEventListener("changeAnnotation", this.$onChangeAnnotation);
1801
1802         this.$onCursorChange = this.onCursorChange.bind(this);
1803         this.session.addEventListener("changeOverwrite", this.$onCursorChange);
1804
1805         this.$onScrollTopChange = this.onScrollTopChange.bind(this);
1806         this.session.addEventListener("changeScrollTop", this.$onScrollTopChange);
1807
1808         this.$onScrollLeftChange = this.onScrollLeftChange.bind(this);
1809         this.session.addEventListener("changeScrollLeft", this.$onScrollLeftChange);
1810
1811         this.selection = session.getSelection();
1812         this.selection.addEventListener("changeCursor", this.$onCursorChange);
1813
1814         this.$onSelectionChange = this.onSelectionChange.bind(this);
1815         this.selection.addEventListener("changeSelection", this.$onSelectionChange);
1816
1817         this.onChangeMode();
1818
1819         this.$blockScrolling += 1;
1820         this.onCursorChange();
1821         this.$blockScrolling -= 1;
1822
1823         this.onScrollTopChange();
1824         this.onScrollLeftChange();
1825         this.onSelectionChange();
1826         this.onChangeFrontMarker();
1827         this.onChangeBackMarker();
1828         this.onChangeBreakpoint();
1829         this.onChangeAnnotation();
1830         this.session.getUseWrapMode() && this.renderer.adjustWrapLimit();
1831         this.renderer.updateFull();
1832
1833         this._emit("changeSession", {
1834             session: session,
1835             oldSession: oldSession
1836         });
1837     };
1838     this.getSession = function() {
1839         return this.session;
1840     };
1841     this.setValue = function(val, cursorPos) {
1842         this.session.doc.setValue(val);
1843
1844         if (!cursorPos)
1845             this.selectAll();
1846         else if (cursorPos == 1)
1847             this.navigateFileEnd();
1848         else if (cursorPos == -1)
1849             this.navigateFileStart();
1850
1851         return val;
1852     };
1853     this.getValue = function() {
1854         return this.session.getValue();
1855     };
1856     this.getSelection = function() {
1857         return this.selection;
1858     };
1859     this.resize = function(force) {
1860         this.renderer.onResize(force);
1861     };
1862     this.setTheme = function(theme) {
1863         this.renderer.setTheme(theme);
1864     };
1865     this.getTheme = function() {
1866         return this.renderer.getTheme();
1867     };
1868     this.setStyle = function(style) {
1869         this.renderer.setStyle(style);
1870     };
1871     this.unsetStyle = function(style) {
1872         this.renderer.unsetStyle(style);
1873     };
1874     this.setFontSize = function(size) {
1875         if (typeof size == "number")
1876             size = size + "px";
1877         this.container.style.fontSize = size;
1878         this.renderer.updateFontSize();
1879     };
1880
1881     this.$highlightBrackets = function() {
1882         if (this.session.$bracketHighlight) {
1883             this.session.removeMarker(this.session.$bracketHighlight);
1884             this.session.$bracketHighlight = null;
1885         }
1886
1887         if (this.$highlightPending) {
1888             return;
1889         }
1890         var self = this;
1891         this.$highlightPending = true;
1892         setTimeout(function() {
1893             self.$highlightPending = false;
1894
1895             var pos = self.session.findMatchingBracket(self.getCursorPosition());
1896             if (pos) {
1897                 var range = new Range(pos.row, pos.column, pos.row, pos.column+1);
1898                 self.session.$bracketHighlight = self.session.addMarker(range, "ace_bracket", "text");
1899             }
1900         }, 50);
1901     };
1902     this.focus = function() {
1903         var _self = this;
1904         setTimeout(function() {
1905             _self.textInput.focus();
1906         });
1907         this.textInput.focus();
1908     };
1909     this.isFocused = function() {
1910         return this.textInput.isFocused();
1911     };
1912     this.blur = function() {
1913         this.textInput.blur();
1914     };
1915     this.onFocus = function() {
1916         if (this.$isFocused)
1917             return;
1918         this.$isFocused = true;
1919         this.renderer.showCursor();
1920         this.renderer.visualizeFocus();
1921         this._emit("focus");
1922     };
1923     this.onBlur = function() {
1924         if (!this.$isFocused)
1925             return;
1926         this.$isFocused = false;
1927         this.renderer.hideCursor();
1928         this.renderer.visualizeBlur();
1929         this._emit("blur");
1930     };
1931
1932     this.$cursorChange = function() {
1933         this.renderer.updateCursor();
1934     };
1935     this.onDocumentChange = function(e) {
1936         var delta = e.data;
1937         var range = delta.range;
1938         var lastRow;
1939
1940         if (range.start.row == range.end.row && delta.action != "insertLines" && delta.action != "removeLines")
1941             lastRow = range.end.row;
1942         else
1943             lastRow = Infinity;
1944         this.renderer.updateLines(range.start.row, lastRow);
1945
1946         this._emit("change", e);
1947         this.$cursorChange();
1948     };
1949
1950     this.onTokenizerUpdate = function(e) {
1951         var rows = e.data;
1952         this.renderer.updateLines(rows.first, rows.last);
1953     };
1954
1955
1956     this.onScrollTopChange = function() {
1957         this.renderer.scrollToY(this.session.getScrollTop());
1958     };
1959     
1960     this.onScrollLeftChange = function() {
1961         this.renderer.scrollToX(this.session.getScrollLeft());
1962     };
1963     this.onCursorChange = function() {
1964         this.$cursorChange();
1965
1966         if (!this.$blockScrolling) {
1967             this.renderer.scrollCursorIntoView();
1968         }
1969
1970         this.$highlightBrackets();
1971         this.$updateHighlightActiveLine();
1972         this._emit("changeSelection");
1973     };
1974
1975     this.$updateHighlightActiveLine = function() {
1976         var session = this.getSession();
1977
1978         var highlight;
1979         if (this.$highlightActiveLine) {
1980             if ((this.$selectionStyle != "line" || !this.selection.isMultiLine()))
1981                 highlight = this.getCursorPosition();
1982         }
1983
1984         if (session.$highlightLineMarker && !highlight) {
1985             session.removeMarker(session.$highlightLineMarker.id);
1986             session.$highlightLineMarker = null;
1987         } else if (!session.$highlightLineMarker && highlight) {
1988             session.$highlightLineMarker = session.highlightLines(highlight.row, highlight.row, "ace_active-line");
1989         } else if (highlight) {
1990             session.$highlightLineMarker.start.row = highlight.row;
1991             session.$highlightLineMarker.end.row = highlight.row;
1992             session._emit("changeBackMarker");
1993         }
1994     };
1995
1996     this.onSelectionChange = function(e) {
1997         var session = this.session;
1998
1999         if (session.$selectionMarker) {
2000             session.removeMarker(session.$selectionMarker);
2001         }
2002         session.$selectionMarker = null;
2003
2004         if (!this.selection.isEmpty()) {
2005             var range = this.selection.getRange();
2006             var style = this.getSelectionStyle();
2007             session.$selectionMarker = session.addMarker(range, "ace_selection", style);
2008         } else {
2009             this.$updateHighlightActiveLine();
2010         }
2011
2012         var re = this.$highlightSelectedWord && this.$getSelectionHighLightRegexp()
2013         this.session.highlight(re);
2014         
2015         this._emit("changeSelection");
2016     };
2017
2018     this.$getSelectionHighLightRegexp = function() {
2019         var session = this.session;
2020
2021         var selection = this.getSelectionRange();
2022         if (selection.isEmpty() || selection.isMultiLine())
2023             return;
2024
2025         var startOuter = selection.start.column - 1;
2026         var endOuter = selection.end.column + 1;
2027         var line = session.getLine(selection.start.row);
2028         var lineCols = line.length;
2029         var needle = line.substring(Math.max(startOuter, 0),
2030                                     Math.min(endOuter, lineCols));
2031         if ((startOuter >= 0 && /^[\w\d]/.test(needle)) ||
2032             (endOuter <= lineCols && /[\w\d]$/.test(needle)))
2033             return;
2034
2035         needle = line.substring(selection.start.column, selection.end.column);
2036         if (!/^[\w\d]+$/.test(needle))
2037             return;
2038
2039         var re = this.$search.$assembleRegExp({
2040             wholeWord: true,
2041             caseSensitive: true,
2042             needle: needle
2043         });
2044
2045         return re;
2046     };
2047
2048
2049     this.onChangeFrontMarker = function() {
2050         this.renderer.updateFrontMarkers();
2051     };
2052
2053     this.onChangeBackMarker = function() {
2054         this.renderer.updateBackMarkers();
2055     };
2056
2057
2058     this.onChangeBreakpoint = function() {
2059         this.renderer.updateBreakpoints();
2060     };
2061
2062     this.onChangeAnnotation = function() {
2063         this.renderer.setAnnotations(this.session.getAnnotations());
2064     };
2065
2066
2067     this.onChangeMode = function() {
2068         this.renderer.updateText();
2069     };
2070
2071
2072     this.onChangeWrapLimit = function() {
2073         this.renderer.updateFull();
2074     };
2075
2076     this.onChangeWrapMode = function() {
2077         this.renderer.onResize(true);
2078     };
2079
2080
2081     this.onChangeFold = function() {
2082         this.$updateHighlightActiveLine();
2083         this.renderer.updateFull();
2084     };
2085
2086     this.getCopyText = function() {
2087         var text = "";
2088         if (!this.selection.isEmpty())
2089             text = this.session.getTextRange(this.getSelectionRange());
2090
2091         this._emit("copy", text);
2092         return text;
2093     };
2094     this.onCopy = function() {
2095         this.commands.exec("copy", this);
2096     };
2097     this.onCut = function() {
2098         this.commands.exec("cut", this);
2099     };
2100     this.onPaste = function(text) {
2101         if (this.$readOnly) 
2102             return;
2103         this._emit("paste", text);
2104         this.insert(text);
2105     };
2106
2107
2108     this.execCommand = function(command, args) {
2109         this.commands.exec(command, this, args);
2110     };
2111     this.insert = function(text) {
2112         var session = this.session;
2113         var mode = session.getMode();
2114         var cursor = this.getCursorPosition();
2115
2116         if (this.getBehavioursEnabled()) {
2117             var transform = mode.transformAction(session.getState(cursor.row), 'insertion', this, session, text);
2118             if (transform)
2119                 text = transform.text;
2120         }
2121
2122         text = text.replace("\t", this.session.getTabString());
2123         if (!this.selection.isEmpty()) {
2124             cursor = this.session.remove(this.getSelectionRange());
2125             this.clearSelection();
2126         }
2127         else if (this.session.getOverwrite()) {
2128             var range = new Range.fromPoints(cursor, cursor);
2129             range.end.column += text.length;
2130             this.session.remove(range);
2131         }
2132
2133         this.clearSelection();
2134
2135         var start = cursor.column;
2136         var lineState = session.getState(cursor.row);
2137         var line = session.getLine(cursor.row);
2138         var shouldOutdent = mode.checkOutdent(lineState, line, text);
2139         var end = session.insert(cursor, text);
2140
2141         if (transform && transform.selection) {
2142             if (transform.selection.length == 2) { // Transform relative to the current column
2143                 this.selection.setSelectionRange(
2144                     new Range(cursor.row, start + transform.selection[0],
2145                               cursor.row, start + transform.selection[1]));
2146             } else { // Transform relative to the current row.
2147                 this.selection.setSelectionRange(
2148                     new Range(cursor.row + transform.selection[0],
2149                               transform.selection[1],
2150                               cursor.row + transform.selection[2],
2151                               transform.selection[3]));
2152             }
2153         }
2154         if (session.getDocument().isNewLine(text)) {
2155             var lineIndent = mode.getNextLineIndent(lineState, line.slice(0, cursor.column), session.getTabString());
2156
2157             this.moveCursorTo(cursor.row+1, 0);
2158
2159             var size = session.getTabSize();
2160             var minIndent = Number.MAX_VALUE;
2161
2162             for (var row = cursor.row + 1; row <= end.row; ++row) {
2163                 var indent = 0;
2164
2165                 line = session.getLine(row);
2166                 for (var i = 0; i < line.length; ++i)
2167                     if (line.charAt(i) == '\t')
2168                         indent += size;
2169                     else if (line.charAt(i) == ' ')
2170                         indent += 1;
2171                     else
2172                         break;
2173                 if (/[^\s]/.test(line))
2174                     minIndent = Math.min(indent, minIndent);
2175             }
2176
2177             for (var row = cursor.row + 1; row <= end.row; ++row) {
2178                 var outdent = minIndent;
2179
2180                 line = session.getLine(row);
2181                 for (var i = 0; i < line.length && outdent > 0; ++i)
2182                     if (line.charAt(i) == '\t')
2183                         outdent -= size;
2184                     else if (line.charAt(i) == ' ')
2185                         outdent -= 1;
2186                 session.remove(new Range(row, 0, row, i));
2187             }
2188             session.indentRows(cursor.row + 1, end.row, lineIndent);
2189         }
2190         if (shouldOutdent)
2191             mode.autoOutdent(lineState, session, cursor.row);
2192     };
2193
2194     this.onTextInput = function(text) {
2195         this.keyBinding.onTextInput(text);
2196     };
2197
2198     this.onCommandKey = function(e, hashId, keyCode) {
2199         this.keyBinding.onCommandKey(e, hashId, keyCode);
2200     };
2201     this.setOverwrite = function(overwrite) {
2202         this.session.setOverwrite(overwrite);
2203     };
2204     this.getOverwrite = function() {
2205         return this.session.getOverwrite();
2206     };
2207     this.toggleOverwrite = function() {
2208         this.session.toggleOverwrite();
2209     };
2210     this.setScrollSpeed = function(speed) {
2211         this.$mouseHandler.setScrollSpeed(speed);
2212     };
2213     this.getScrollSpeed = function() {
2214         return this.$mouseHandler.getScrollSpeed();
2215     };
2216     this.setDragDelay = function(dragDelay) {
2217         this.$mouseHandler.setDragDelay(dragDelay);
2218     };
2219     this.getDragDelay = function() {
2220         return this.$mouseHandler.getDragDelay();
2221     };
2222
2223     this.$selectionStyle = "line";
2224     this.setSelectionStyle = function(style) {
2225         if (this.$selectionStyle == style) return;
2226
2227         this.$selectionStyle = style;
2228         this.onSelectionChange();
2229         this._emit("changeSelectionStyle", {data: style});
2230     };
2231     this.getSelectionStyle = function() {
2232         return this.$selectionStyle;
2233     };
2234
2235     this.$highlightActiveLine = true;
2236     this.setHighlightActiveLine = function(shouldHighlight) {
2237         if (this.$highlightActiveLine == shouldHighlight)
2238             return;
2239
2240         this.$highlightActiveLine = shouldHighlight;
2241         this.$updateHighlightActiveLine();
2242     };
2243     this.getHighlightActiveLine = function() {
2244         return this.$highlightActiveLine;
2245     };
2246
2247     this.$highlightGutterLine = true;
2248     this.setHighlightGutterLine = function(shouldHighlight) {
2249         if (this.$highlightGutterLine == shouldHighlight)
2250             return;
2251
2252         this.renderer.setHighlightGutterLine(shouldHighlight);
2253         this.$highlightGutterLine = shouldHighlight;
2254     };
2255
2256     this.getHighlightGutterLine = function() {
2257         return this.$highlightGutterLine;
2258     };
2259
2260     this.$highlightSelectedWord = true;
2261     this.setHighlightSelectedWord = function(shouldHighlight) {
2262         if (this.$highlightSelectedWord == shouldHighlight)
2263             return;
2264
2265         this.$highlightSelectedWord = shouldHighlight;
2266         this.$onSelectionChange();
2267     };
2268     this.getHighlightSelectedWord = function() {
2269         return this.$highlightSelectedWord;
2270     };
2271
2272     this.setAnimatedScroll = function(shouldAnimate){
2273         this.renderer.setAnimatedScroll(shouldAnimate);
2274     };
2275
2276     this.getAnimatedScroll = function(){
2277         return this.renderer.getAnimatedScroll();
2278     };
2279     this.setShowInvisibles = function(showInvisibles) {
2280         this.renderer.setShowInvisibles(showInvisibles);
2281     };
2282     this.getShowInvisibles = function() {
2283         return this.renderer.getShowInvisibles();
2284     };
2285
2286     this.setDisplayIndentGuides = function(display) {
2287         this.renderer.setDisplayIndentGuides(display);
2288     };
2289
2290     this.getDisplayIndentGuides = function() {
2291         return this.renderer.getDisplayIndentGuides();
2292     };
2293     this.setShowPrintMargin = function(showPrintMargin) {
2294         this.renderer.setShowPrintMargin(showPrintMargin);
2295     };
2296     this.getShowPrintMargin = function() {
2297         return this.renderer.getShowPrintMargin();
2298     };
2299     this.setPrintMarginColumn = function(showPrintMargin) {
2300         this.renderer.setPrintMarginColumn(showPrintMargin);
2301     };
2302     this.getPrintMarginColumn = function() {
2303         return this.renderer.getPrintMarginColumn();
2304     };
2305
2306     this.$readOnly = false;
2307     this.setReadOnly = function(readOnly) {
2308         this.$readOnly = readOnly;
2309         this.textInput.setReadOnly(readOnly);
2310         this.renderer.$cursorLayer.setBlinking(!readOnly);
2311     };
2312     this.getReadOnly = function() {
2313         return this.$readOnly;
2314     };
2315
2316     this.$modeBehaviours = true;
2317     this.setBehavioursEnabled = function (enabled) {
2318         this.$modeBehaviours = enabled;
2319     };
2320     this.getBehavioursEnabled = function () {
2321         return this.$modeBehaviours;
2322     };
2323
2324     this.$modeWrapBehaviours = true;
2325     this.setWrapBehavioursEnabled = function (enabled) {
2326         this.$modeWrapBehaviours = enabled;
2327     };
2328     this.getWrapBehavioursEnabled = function () {
2329         return this.$modeWrapBehaviours;
2330     };
2331     this.setShowFoldWidgets = function(show) {
2332         var gutter = this.renderer.$gutterLayer;
2333         if (gutter.getShowFoldWidgets() == show)
2334             return;
2335
2336         this.renderer.$gutterLayer.setShowFoldWidgets(show);
2337         this.$showFoldWidgets = show;
2338         this.renderer.updateFull();
2339     };
2340     this.getShowFoldWidgets = function() {
2341         return this.renderer.$gutterLayer.getShowFoldWidgets();
2342     };
2343
2344     this.setFadeFoldWidgets = function(show) {
2345         this.renderer.setFadeFoldWidgets(show);
2346     };
2347
2348     this.getFadeFoldWidgets = function() {
2349         return this.renderer.getFadeFoldWidgets();
2350     };
2351     this.remove = function(dir) {
2352         if (this.selection.isEmpty()){
2353             if (dir == "left")
2354                 this.selection.selectLeft();
2355             else
2356                 this.selection.selectRight();
2357         }
2358
2359         var range = this.getSelectionRange();
2360         if (this.getBehavioursEnabled()) {
2361             var session = this.session;
2362             var state = session.getState(range.start.row);
2363             var new_range = session.getMode().transformAction(state, 'deletion', this, session, range);
2364             if (new_range)
2365                 range = new_range;
2366         }
2367
2368         this.session.remove(range);
2369         this.clearSelection();
2370     };
2371     this.removeWordRight = function() {
2372         if (this.selection.isEmpty())
2373             this.selection.selectWordRight();
2374
2375         this.session.remove(this.getSelectionRange());
2376         this.clearSelection();
2377     };
2378     this.removeWordLeft = function() {
2379         if (this.selection.isEmpty())
2380             this.selection.selectWordLeft();
2381
2382         this.session.remove(this.getSelectionRange());
2383         this.clearSelection();
2384     };
2385     this.removeToLineStart = function() {
2386         if (this.selection.isEmpty())
2387             this.selection.selectLineStart();
2388
2389         this.session.remove(this.getSelectionRange());
2390         this.clearSelection();
2391     };
2392     this.removeToLineEnd = function() {
2393         if (this.selection.isEmpty())
2394             this.selection.selectLineEnd();
2395
2396         var range = this.getSelectionRange();
2397         if (range.start.column == range.end.column && range.start.row == range.end.row) {
2398             range.end.column = 0;
2399             range.end.row++;
2400         }
2401
2402         this.session.remove(range);
2403         this.clearSelection();
2404     };
2405     this.splitLine = function() {
2406         if (!this.selection.isEmpty()) {
2407             this.session.remove(this.getSelectionRange());
2408             this.clearSelection();
2409         }
2410
2411         var cursor = this.getCursorPosition();
2412         this.insert("\n");
2413         this.moveCursorToPosition(cursor);
2414     };
2415     this.transposeLetters = function() {
2416         if (!this.selection.isEmpty()) {
2417             return;
2418         }
2419
2420         var cursor = this.getCursorPosition();
2421         var column = cursor.column;
2422         if (column === 0)
2423             return;
2424
2425         var line = this.session.getLine(cursor.row);
2426         var swap, range;
2427         if (column < line.length) {
2428             swap = line.charAt(column) + line.charAt(column-1);
2429             range = new Range(cursor.row, column-1, cursor.row, column+1);
2430         }
2431         else {
2432             swap = line.charAt(column-1) + line.charAt(column-2);
2433             range = new Range(cursor.row, column-2, cursor.row, column);
2434         }
2435         this.session.replace(range, swap);
2436     };
2437     this.toLowerCase = function() {
2438         var originalRange = this.getSelectionRange();
2439         if (this.selection.isEmpty()) {
2440             this.selection.selectWord();
2441         }
2442
2443         var range = this.getSelectionRange();
2444         var text = this.session.getTextRange(range);
2445         this.session.replace(range, text.toLowerCase());
2446         this.selection.setSelectionRange(originalRange);
2447     };
2448     this.toUpperCase = function() {
2449         var originalRange = this.getSelectionRange();
2450         if (this.selection.isEmpty()) {
2451             this.selection.selectWord();
2452         }
2453
2454         var range = this.getSelectionRange();
2455         var text = this.session.getTextRange(range);
2456         this.session.replace(range, text.toUpperCase());
2457         this.selection.setSelectionRange(originalRange);
2458     };
2459     this.indent = function() {
2460         var session = this.session;
2461         var range = this.getSelectionRange();
2462
2463         if (range.start.row < range.end.row || range.start.column < range.end.column) {
2464             var rows = this.$getSelectedRows();
2465             session.indentRows(rows.first, rows.last, "\t");
2466         } else {
2467             var indentString;
2468
2469             if (this.session.getUseSoftTabs()) {
2470                 var size        = session.getTabSize(),
2471                     position    = this.getCursorPosition(),
2472                     column      = session.documentToScreenColumn(position.row, position.column),
2473                     count       = (size - column % size);
2474
2475                 indentString = lang.stringRepeat(" ", count);
2476             } else
2477                 indentString = "\t";
2478             return this.insert(indentString);
2479         }
2480     };
2481     this.blockIndent = function() {
2482         var rows = this.$getSelectedRows();
2483         this.session.indentRows(rows.first, rows.last, "\t");
2484     };
2485     this.blockOutdent = function() {
2486         var selection = this.session.getSelection();
2487         this.session.outdentRows(selection.getRange());
2488     };
2489     this.sortLines = function() {
2490         var rows = this.$getSelectedRows();
2491         var session = this.session;
2492
2493         var lines = [];
2494         for (i = rows.first; i <= rows.last; i++)
2495             lines.push(session.getLine(i));
2496
2497         lines.sort(function(a, b) {
2498             if (a.toLowerCase() < b.toLowerCase()) return -1;
2499             if (a.toLowerCase() > b.toLowerCase()) return 1;
2500             return 0;
2501         });
2502
2503         var deleteRange = new Range(0, 0, 0, 0);
2504         for (var i = rows.first; i <= rows.last; i++) {
2505             var line = session.getLine(i);
2506             deleteRange.start.row = i;
2507             deleteRange.end.row = i;
2508             deleteRange.end.column = line.length;
2509             session.replace(deleteRange, lines[i-rows.first]);
2510         }
2511     };
2512     this.toggleCommentLines = function() {
2513         var state = this.session.getState(this.getCursorPosition().row);
2514         var rows = this.$getSelectedRows();
2515         this.session.getMode().toggleCommentLines(state, this.session, rows.first, rows.last);
2516     };
2517     this.getNumberAt = function( row, column ) {
2518         var _numberRx = /[\-]?[0-9]+(?:\.[0-9]+)?/g
2519         _numberRx.lastIndex = 0
2520
2521         var s = this.session.getLine(row)
2522         while(_numberRx.lastIndex < column - 1 ){
2523             var m = _numberRx.exec(s)
2524             if(m.index <= column && m.index+m[0].length >= column){
2525                 var number = {
2526                     value: m[0],
2527                     start: m.index,
2528                     end: m.index+m[0].length
2529
2530                 }
2531                 return number
2532             }
2533         }
2534         return null;
2535     };
2536     this.modifyNumber = function(amount) {
2537         var row = this.selection.getCursor().row;
2538         var column = this.selection.getCursor().column;
2539         var charRange = new Range(row, column-1, row, column);
2540
2541         var c = this.session.getTextRange(charRange);
2542         if (!isNaN(parseFloat(c)) && isFinite(c)) {
2543             var nr = this.getNumberAt(row, column);
2544             if (nr) {
2545                 var fp = nr.value.indexOf(".") >= 0 ? nr.start + nr.value.indexOf(".") + 1 : nr.end;
2546                 var decimals = nr.start + nr.value.length - fp;
2547
2548                 var t = parseFloat(nr.value);
2549                 t *= Math.pow(10, decimals);
2550                 
2551
2552                 if(fp !== nr.end && column < fp){
2553                     amount *= Math.pow(10, nr.end - column - 1);
2554                 } else {
2555                     amount *= Math.pow(10, nr.end - column);
2556                 }
2557                 
2558                 t += amount;
2559                 t /= Math.pow(10, decimals);
2560                 var nnr = t.toFixed(decimals);
2561                 var replaceRange = new Range(row, nr.start, row, nr.end);
2562                 this.session.replace(replaceRange, nnr);
2563                 this.moveCursorTo(row, Math.max(nr.start +1, column + nnr.length - nr.value.length));
2564
2565             }
2566         }
2567     };
2568     this.removeLines = function() {
2569         var rows = this.$getSelectedRows();
2570         var range;
2571         if (rows.first === 0 || rows.last+1 < this.session.getLength())
2572             range = new Range(rows.first, 0, rows.last+1, 0);
2573         else
2574             range = new Range(
2575                 rows.first-1, this.session.getLine(rows.first-1).length,
2576                 rows.last, this.session.getLine(rows.last).length
2577             );
2578         this.session.remove(range);
2579         this.clearSelection();
2580     };
2581
2582     this.duplicateSelection = function() {
2583         var sel = this.selection;
2584         var doc = this.session;
2585         var range = sel.getRange();
2586         if (range.isEmpty()) {
2587             var row = range.start.row;
2588             doc.duplicateLines(row, row);
2589         } else {
2590             var reverse = sel.isBackwards()
2591             var point = sel.isBackwards() ? range.start : range.end;
2592             var endPoint = doc.insert(point, doc.getTextRange(range), false);
2593             range.start = point;
2594             range.end = endPoint;
2595             
2596             sel.setSelectionRange(range, reverse)
2597         }
2598     };
2599     this.moveLinesDown = function() {
2600         this.$moveLines(function(firstRow, lastRow) {
2601             return this.session.moveLinesDown(firstRow, lastRow);
2602         });
2603     };
2604     this.moveLinesUp = function() {
2605         this.$moveLines(function(firstRow, lastRow) {
2606             return this.session.moveLinesUp(firstRow, lastRow);
2607         });
2608     };
2609     this.moveText = function(range, toPosition) {
2610         if (this.$readOnly)
2611             return null;
2612
2613         return this.session.moveText(range, toPosition);
2614     };
2615     this.copyLinesUp = function() {
2616         this.$moveLines(function(firstRow, lastRow) {
2617             this.session.duplicateLines(firstRow, lastRow);
2618             return 0;
2619         });
2620     };
2621     this.copyLinesDown = function() {
2622         this.$moveLines(function(firstRow, lastRow) {
2623             return this.session.duplicateLines(firstRow, lastRow);
2624         });
2625     };
2626     this.$moveLines = function(mover) {
2627         var rows = this.$getSelectedRows();
2628         var selection = this.selection;
2629         if (!selection.isMultiLine()) {
2630             var range = selection.getRange();
2631             var reverse = selection.isBackwards();
2632         }
2633
2634         var linesMoved = mover.call(this, rows.first, rows.last);
2635
2636         if (range) {
2637             range.start.row += linesMoved;
2638             range.end.row += linesMoved;
2639             selection.setSelectionRange(range, reverse);
2640         }
2641         else {
2642             selection.setSelectionAnchor(rows.last+linesMoved+1, 0);
2643             selection.$moveSelection(function() {
2644                 selection.moveCursorTo(rows.first+linesMoved, 0);
2645             });
2646         }
2647     };
2648     this.$getSelectedRows = function() {
2649         var range = this.getSelectionRange().collapseRows();
2650
2651         return {
2652             first: range.start.row,
2653             last: range.end.row
2654         };
2655     };
2656
2657     this.onCompositionStart = function(text) {
2658         this.renderer.showComposition(this.getCursorPosition());
2659     };
2660
2661     this.onCompositionUpdate = function(text) {
2662         this.renderer.setCompositionText(text);
2663     };
2664
2665     this.onCompositionEnd = function() {
2666         this.renderer.hideComposition();
2667     };
2668     this.getFirstVisibleRow = function() {
2669         return this.renderer.getFirstVisibleRow();
2670     };
2671     this.getLastVisibleRow = function() {
2672         return this.renderer.getLastVisibleRow();
2673     };
2674     this.isRowVisible = function(row) {
2675         return (row >= this.getFirstVisibleRow() && row <= this.getLastVisibleRow());
2676     };
2677     this.isRowFullyVisible = function(row) {
2678         return (row >= this.renderer.getFirstFullyVisibleRow() && row <= this.renderer.getLastFullyVisibleRow());
2679     };
2680     this.$getVisibleRowCount = function() {
2681         return this.renderer.getScrollBottomRow() - this.renderer.getScrollTopRow() + 1;
2682     };
2683
2684     this.$moveByPage = function(dir, select) {
2685         var renderer = this.renderer;
2686         var config = this.renderer.layerConfig;
2687         var rows = dir * Math.floor(config.height / config.lineHeight);
2688
2689         this.$blockScrolling++;
2690         if (select == true) {
2691             this.selection.$moveSelection(function(){
2692                 this.moveCursorBy(rows, 0);
2693             });
2694         } else if (select == false) {
2695             this.selection.moveCursorBy(rows, 0);
2696             this.selection.clearSelection();
2697         }
2698         this.$blockScrolling--;
2699
2700         var scrollTop = renderer.scrollTop;
2701
2702         renderer.scrollBy(0, rows * config.lineHeight);
2703         if (select != null)
2704             renderer.scrollCursorIntoView(null, 0.5);
2705
2706         renderer.animateScrolling(scrollTop);
2707     };
2708     this.selectPageDown = function() {
2709         this.$moveByPage(1, true);
2710     };
2711     this.selectPageUp = function() {
2712         this.$moveByPage(-1, true);
2713     };
2714     this.gotoPageDown = function() {
2715        this.$moveByPage(1, false);
2716     };
2717     this.gotoPageUp = function() {
2718         this.$moveByPage(-1, false);
2719     };
2720     this.scrollPageDown = function() {
2721         this.$moveByPage(1);
2722     };
2723     this.scrollPageUp = function() {
2724         this.$moveByPage(-1);
2725     };
2726     this.scrollToRow = function(row) {
2727         this.renderer.scrollToRow(row);
2728     };
2729     this.scrollToLine = function(line, center, animate, callback) {
2730         this.renderer.scrollToLine(line, center, animate, callback);
2731     };
2732     this.centerSelection = function() {
2733         var range = this.getSelectionRange();
2734         var pos = {
2735             row: Math.floor(range.start.row + (range.end.row - range.start.row) / 2),
2736             column: Math.floor(range.start.column + (range.end.column - range.start.column) / 2)
2737         }
2738         this.renderer.alignCursor(pos, 0.5);
2739     };
2740     this.getCursorPosition = function() {
2741         return this.selection.getCursor();
2742     };
2743     this.getCursorPositionScreen = function() {
2744         return this.session.documentToScreenPosition(this.getCursorPosition());
2745     };
2746     this.getSelectionRange = function() {
2747         return this.selection.getRange();
2748     };
2749     this.selectAll = function() {
2750         this.$blockScrolling += 1;
2751         this.selection.selectAll();
2752         this.$blockScrolling -= 1;
2753     };
2754     this.clearSelection = function() {
2755         this.selection.clearSelection();
2756     };
2757     this.moveCursorTo = function(row, column) {
2758         this.selection.moveCursorTo(row, column);
2759     };
2760     this.moveCursorToPosition = function(pos) {
2761         this.selection.moveCursorToPosition(pos);
2762     };
2763     this.jumpToMatching = function(select) {
2764         var cursor = this.getCursorPosition();
2765
2766         var range = this.session.getBracketRange(cursor);
2767         if (!range) {
2768             range = this.find({
2769                 needle: /[{}()\[\]]/g,
2770                 preventScroll:true,
2771                 start: {row: cursor.row, column: cursor.column - 1}
2772             });
2773             if (!range)
2774                 return;
2775             var pos = range.start;
2776             if (pos.row == cursor.row && Math.abs(pos.column - cursor.column) < 2)
2777                 range = this.session.getBracketRange(pos);
2778         }
2779         
2780         pos = range && range.cursor || pos;
2781         if (pos) {
2782             if (select) {
2783                 if (range && range.isEqual(this.getSelectionRange()))
2784                     this.clearSelection();
2785                 else
2786                     this.selection.selectTo(pos.row, pos.column);
2787             } else {
2788                 this.clearSelection();
2789                 this.moveCursorTo(pos.row, pos.column);
2790             }
2791         }
2792     };
2793     this.gotoLine = function(lineNumber, column, animate) {
2794         this.selection.clearSelection();
2795         this.session.unfold({row: lineNumber - 1, column: column || 0});
2796
2797         this.$blockScrolling += 1;
2798         this.moveCursorTo(lineNumber - 1, column || 0);
2799         this.$blockScrolling -= 1;
2800
2801         if (!this.isRowFullyVisible(lineNumber - 1))
2802             this.scrollToLine(lineNumber - 1, true, animate);
2803     };
2804     this.navigateTo = function(row, column) {
2805         this.clearSelection();
2806         this.moveCursorTo(row, column);
2807     };
2808     this.navigateUp = function(times) {
2809         this.selection.clearSelection();
2810         times = times || 1;
2811         this.selection.moveCursorBy(-times, 0);
2812     };
2813     this.navigateDown = function(times) {
2814         this.selection.clearSelection();
2815         times = times || 1;
2816         this.selection.moveCursorBy(times, 0);
2817     };
2818     this.navigateLeft = function(times) {
2819         if (!this.selection.isEmpty()) {
2820             var selectionStart = this.getSelectionRange().start;
2821             this.moveCursorToPosition(selectionStart);
2822         }
2823         else {
2824             times = times || 1;
2825             while (times--) {
2826                 this.selection.moveCursorLeft();
2827             }
2828         }
2829         this.clearSelection();
2830     };
2831     this.navigateRight = function(times) {
2832         if (!this.selection.isEmpty()) {
2833             var selectionEnd = this.getSelectionRange().end;
2834             this.moveCursorToPosition(selectionEnd);
2835         }
2836         else {
2837             times = times || 1;
2838             while (times--) {
2839                 this.selection.moveCursorRight();
2840             }
2841         }
2842         this.clearSelection();
2843     };
2844     this.navigateLineStart = function() {
2845         this.selection.moveCursorLineStart();
2846         this.clearSelection();
2847     };
2848     this.navigateLineEnd = function() {
2849         this.selection.moveCursorLineEnd();
2850         this.clearSelection();
2851     };
2852     this.navigateFileEnd = function() {
2853         var scrollTop = this.renderer.scrollTop;
2854         this.selection.moveCursorFileEnd();
2855         this.clearSelection();
2856         this.renderer.animateScrolling(scrollTop);
2857     };
2858     this.navigateFileStart = function() {
2859         var scrollTop = this.renderer.scrollTop;
2860         this.selection.moveCursorFileStart();
2861         this.clearSelection();
2862         this.renderer.animateScrolling(scrollTop);
2863     };
2864     this.navigateWordRight = function() {
2865         this.selection.moveCursorWordRight();
2866         this.clearSelection();
2867     };
2868     this.navigateWordLeft = function() {
2869         this.selection.moveCursorWordLeft();
2870         this.clearSelection();
2871     };
2872     this.replace = function(replacement, options) {
2873         if (options)
2874             this.$search.set(options);
2875
2876         var range = this.$search.find(this.session);
2877         var replaced = 0;
2878         if (!range)
2879             return replaced;
2880
2881         if (this.$tryReplace(range, replacement)) {
2882             replaced = 1;
2883         }
2884         if (range !== null) {
2885             this.selection.setSelectionRange(range);
2886             this.renderer.scrollSelectionIntoView(range.start, range.end);
2887         }
2888
2889         return replaced;
2890     };
2891     this.replaceAll = function(replacement, options) {
2892         if (options) {
2893             this.$search.set(options);
2894         }
2895
2896         var ranges = this.$search.findAll(this.session);
2897         var replaced = 0;
2898         if (!ranges.length)
2899             return replaced;
2900
2901         this.$blockScrolling += 1;
2902
2903         var selection = this.getSelectionRange();
2904         this.clearSelection();
2905         this.selection.moveCursorTo(0, 0);
2906
2907         for (var i = ranges.length - 1; i >= 0; --i) {
2908             if(this.$tryReplace(ranges[i], replacement)) {
2909                 replaced++;
2910             }
2911         }
2912
2913         this.selection.setSelectionRange(selection);
2914         this.$blockScrolling -= 1;
2915
2916         return replaced;
2917     };
2918
2919     this.$tryReplace = function(range, replacement) {
2920         var input = this.session.getTextRange(range);
2921         replacement = this.$search.replace(input, replacement);
2922         if (replacement !== null) {
2923             range.end = this.session.replace(range, replacement);
2924             return range;
2925         } else {
2926             return null;
2927         }
2928     };
2929     this.getLastSearchOptions = function() {
2930         return this.$search.getOptions();
2931     };
2932     this.find = function(needle, options, animate) {
2933         if (!options)
2934             options = {};
2935
2936         if (typeof needle == "string" || needle instanceof RegExp)
2937             options.needle = needle;
2938         else if (typeof needle == "object")
2939             oop.mixin(options, needle);
2940
2941         var range = this.selection.getRange();
2942         if (options.needle == null) {
2943             needle = this.session.getTextRange(range)
2944                 || this.$search.$options.needle;
2945             if (!needle) {
2946                 range = this.session.getWordRange(range.start.row, range.start.column);
2947                 needle = this.session.getTextRange(range);
2948             }
2949             this.$search.set({needle: needle});
2950         }
2951
2952         this.$search.set(options);
2953         if (!options.start)
2954             this.$search.set({start: range});
2955
2956         var newRange = this.$search.find(this.session);
2957         if (options.preventScroll)
2958             return newRange;
2959         if (newRange) {
2960             this.revealRange(newRange, animate);
2961             return newRange;
2962         }
2963         if (options.backwards)
2964             range.start = range.end;
2965         else
2966             range.end = range.start;
2967         this.selection.setRange(range);
2968     };
2969     this.findNext = function(options, animate) {
2970         this.find({skipCurrent: true, backwards: false}, options, animate);
2971     };
2972     this.findPrevious = function(options, animate) {
2973         this.find(options, {skipCurrent: true, backwards: true}, animate);
2974     };
2975
2976     this.revealRange = function(range, animate) {
2977         this.$blockScrolling += 1;
2978         this.session.unfold(range);
2979         this.selection.setSelectionRange(range);
2980         this.$blockScrolling -= 1;
2981
2982         var scrollTop = this.renderer.scrollTop;
2983         this.renderer.scrollSelectionIntoView(range.start, range.end, 0.5);
2984         if (animate != false)
2985             this.renderer.animateScrolling(scrollTop);
2986     };
2987     this.undo = function() {
2988         this.$blockScrolling++;
2989         this.session.getUndoManager().undo();
2990         this.$blockScrolling--;
2991         this.renderer.scrollCursorIntoView(null, 0.5);
2992     };
2993     this.redo = function() {
2994         this.$blockScrolling++;
2995         this.session.getUndoManager().redo();
2996         this.$blockScrolling--;
2997         this.renderer.scrollCursorIntoView(null, 0.5);
2998     };
2999     this.destroy = function() {
3000         this.renderer.destroy();
3001     };
3002
3003 }).call(Editor.prototype);
3004
3005
3006 exports.Editor = Editor;
3007 });
3008
3009 ace.define('ace/lib/lang', ['require', 'exports', 'module' ], function(require, exports, module) {
3010
3011
3012 exports.stringReverse = function(string) {
3013     return string.split("").reverse().join("");
3014 };
3015
3016 exports.stringRepeat = function (string, count) {
3017     var result = '';
3018     while (count > 0) {
3019         if (count & 1)
3020             result += string;
3021
3022         if (count >>= 1)
3023             string += string;
3024     }
3025     return result;
3026 };
3027
3028 var trimBeginRegexp = /^\s\s*/;
3029 var trimEndRegexp = /\s\s*$/;
3030
3031 exports.stringTrimLeft = function (string) {
3032     return string.replace(trimBeginRegexp, '');
3033 };
3034
3035 exports.stringTrimRight = function (string) {
3036     return string.replace(trimEndRegexp, '');
3037 };
3038
3039 exports.copyObject = function(obj) {
3040     var copy = {};
3041     for (var key in obj) {
3042         copy[key] = obj[key];
3043     }
3044     return copy;
3045 };
3046
3047 exports.copyArray = function(array){
3048     var copy = [];
3049     for (var i=0, l=array.length; i<l; i++) {
3050         if (array[i] && typeof array[i] == "object")
3051             copy[i] = this.copyObject( array[i] );
3052         else 
3053             copy[i] = array[i];
3054     }
3055     return copy;
3056 };
3057
3058 exports.deepCopy = function (obj) {
3059     if (typeof obj != "object") {
3060         return obj;
3061     }
3062     
3063     var copy = obj.constructor();
3064     for (var key in obj) {
3065         if (typeof obj[key] == "object") {
3066             copy[key] = this.deepCopy(obj[key]);
3067         } else {
3068             copy[key] = obj[key];
3069         }
3070     }
3071     return copy;
3072 };
3073
3074 exports.arrayToMap = function(arr) {
3075     var map = {};
3076     for (var i=0; i<arr.length; i++) {
3077         map[arr[i]] = 1;
3078     }
3079     return map;
3080
3081 };
3082
3083 exports.createMap = function(props) {
3084     var map = Object.create(null);
3085     for (var i in props) {
3086         map[i] = props[i];
3087     }
3088     return map;
3089 };
3090 exports.arrayRemove = function(array, value) {
3091   for (var i = 0; i <= array.length; i++) {
3092     if (value === array[i]) {
3093       array.splice(i, 1);
3094     }
3095   }
3096 };
3097
3098 exports.escapeRegExp = function(str) {
3099     return str.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1');
3100 };
3101
3102 exports.escapeHTML = function(str) {
3103     return str.replace(/&/g, "&#38;").replace(/"/g, "&#34;").replace(/'/g, "&#39;").replace(/</g, "&#60;");
3104 };
3105
3106 exports.getMatchOffsets = function(string, regExp) {
3107     var matches = [];
3108
3109     string.replace(regExp, function(str) {
3110         matches.push({
3111             offset: arguments[arguments.length-2],
3112             length: str.length
3113         });
3114     });
3115
3116     return matches;
3117 };
3118 exports.deferredCall = function(fcn) {
3119
3120     var timer = null;
3121     var callback = function() {
3122         timer = null;
3123         fcn();
3124     };
3125
3126     var deferred = function(timeout) {
3127         deferred.cancel();
3128         timer = setTimeout(callback, timeout || 0);
3129         return deferred;
3130     };
3131
3132     deferred.schedule = deferred;
3133
3134     deferred.call = function() {
3135         this.cancel();
3136         fcn();
3137         return deferred;
3138     };
3139
3140     deferred.cancel = function() {
3141         clearTimeout(timer);
3142         timer = null;
3143         return deferred;
3144     };
3145
3146     return deferred;
3147 };
3148
3149
3150 exports.delayedCall = function(fcn, defaultTimeout) {
3151     var timer = null;
3152     var callback = function() {
3153         timer = null;
3154         fcn();
3155     };
3156
3157     var _self = function(timeout) {
3158         timer && clearTimeout(timer);
3159         timer = setTimeout(callback, timeout || defaultTimeout);
3160     };
3161
3162     _self.delay = _self;
3163     _self.schedule = function(timeout) {
3164         if (timer == null)
3165             timer = setTimeout(callback, timeout || 0);
3166     };
3167
3168     _self.call = function() {
3169         this.cancel();
3170         fcn();
3171     };
3172
3173     _self.cancel = function() {
3174         timer && clearTimeout(timer);
3175         timer = null;
3176     };
3177
3178     _self.isPending = function() {
3179         return timer;
3180     };
3181
3182     return _self;
3183 };
3184 });
3185
3186 ace.define('ace/keyboard/textinput', ['require', 'exports', 'module' , 'ace/lib/event', 'ace/lib/useragent', 'ace/lib/dom', 'ace/lib/lang'], function(require, exports, module) {
3187
3188
3189 var event = require("../lib/event");
3190 var useragent = require("../lib/useragent");
3191 var dom = require("../lib/dom");
3192 var lang = require("../lib/lang");
3193 var BROKEN_SETDATA = useragent.isChrome < 18;
3194
3195 var TextInput = function(parentNode, host) {
3196     var text = dom.createElement("textarea");
3197     text.className = "ace_text-input";
3198     if (useragent.isTouchPad)
3199         text.setAttribute("x-palm-disable-auto-cap", true);
3200
3201     text.wrap = "off";
3202     text.autocorrect = "off";
3203     text.autocapitalize = "off";
3204     text.spellcheck = false;
3205
3206     text.style.bottom = "2000em";
3207     parentNode.insertBefore(text, parentNode.firstChild);
3208
3209     var PLACEHOLDER = "\x01\x01";
3210
3211     var cut = false;
3212     var copied = false;
3213     var pasted = false;
3214     var inCompostion = false;
3215     var tempStyle = '';
3216     var isSelectionEmpty = true;
3217     try { var isFocused = document.activeElement === text; } catch(e) {}
3218     
3219     event.addListener(text, "blur", function() {
3220         host.onBlur();
3221         isFocused = false;
3222     });
3223     event.addListener(text, "focus", function() {
3224         isFocused = true;
3225         host.onFocus();
3226         resetSelection();
3227     });
3228     this.focus = function() { text.focus(); };
3229     this.blur = function() { text.blur(); };
3230     this.isFocused = function() {
3231         return isFocused;
3232     };
3233     var syncSelection = lang.delayedCall(function() {
3234         isFocused && resetSelection(isSelectionEmpty);
3235     });
3236     var syncValue = lang.delayedCall(function() {
3237          if (!inCompostion) {
3238             text.value = PLACEHOLDER;
3239             isFocused && resetSelection();
3240          }
3241     });
3242
3243     function resetSelection(isEmpty) {
3244         if (inCompostion)
3245             return;
3246         var selectionStart = isEmpty ? 2 : 1;
3247         var selectionEnd = 2;
3248         try {
3249             text.setSelectionRange(selectionStart, selectionEnd);
3250         } catch(e){}
3251     }
3252
3253     function resetValue() {
3254         if (inCompostion)
3255             return;
3256         text.value = PLACEHOLDER;
3257         if (useragent.isWebKit)
3258             syncValue.schedule();
3259     }
3260
3261     useragent.isWebKit || host.addEventListener('changeSelection', function() {
3262         if (host.selection.isEmpty() != isSelectionEmpty) {
3263             isSelectionEmpty = !isSelectionEmpty;
3264             syncSelection.schedule();
3265         }
3266     });
3267
3268     resetValue();
3269     if (isFocused)
3270         host.onFocus();
3271
3272
3273     var isAllSelected = function(text) {
3274         return text.selectionStart === 0 && text.selectionEnd === text.value.length;
3275     };
3276     if (!text.setSelectionRange && text.createTextRange) {
3277         text.setSelectionRange = function(selectionStart, selectionEnd) {
3278             var range = this.createTextRange();
3279             range.collapse(true);
3280             range.moveStart('character', selectionStart);
3281             range.moveEnd('character', selectionEnd);
3282             range.select();
3283         };
3284         isAllSelected = function(text) {
3285             try {
3286                 var range = text.ownerDocument.selection.createRange();
3287             }catch(e) {}
3288             if (!range || range.parentElement() != text) return false;
3289                 return range.text == text.value;
3290         }
3291     }
3292     if (useragent.isOldIE) {
3293         var inPropertyChange = false;
3294         var onPropertyChange = function(e){
3295             if (inPropertyChange)
3296                 return;
3297             var data = text.value;
3298             if (inCompostion || !data || data == PLACEHOLDER)
3299                 return;
3300             if (e && data == PLACEHOLDER[0])
3301                 return syncProperty.schedule();
3302
3303             sendText(data);
3304             inPropertyChange = true;
3305             resetValue();
3306             inPropertyChange = false;
3307         };
3308         var syncProperty = lang.delayedCall(onPropertyChange);
3309         event.addListener(text, "propertychange", onPropertyChange);
3310
3311         var keytable = { 13:1, 27:1 };
3312         event.addListener(text, "keyup", function (e) {
3313             if (inCompostion && (!text.value || keytable[e.keyCode]))
3314                 setTimeout(onCompositionEnd, 0);
3315             if ((text.value.charCodeAt(0)||0) < 129) {
3316                 return;
3317             }
3318             inCompostion ? onCompositionUpdate() : onCompositionStart();
3319         });
3320     }
3321
3322     var onSelect = function(e) {
3323         if (cut) {
3324             cut = false;
3325             return;
3326         }
3327         if (copied) {
3328             copied = false;
3329             return;
3330         }
3331         if (isAllSelected(text)) {
3332             host.selectAll();
3333             resetSelection();
3334         }
3335     };
3336
3337