PageSourceSearch

https://onenak.onenakconsulting.com/web/static/lib/ace/ace.js

js onenakconsulting.com collected 2026-10-06 09:28:30 UTC 690,191 bytes, 20,654 lines download raw bytes

vendor: 6,274 bytes, lines 1-186
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/**
32 * Define a module along with a payload
33 * @param module a name for the payload
34 * @param payload a function to call with (require, exports, module) params
35 */
36
37(function() {
38
39var ACE_NAMESPACE = "";
40
41var global = (function() { return this; })();
42if (!global && typeof window != "undefined") global = window; // strict mode
43
44
45if (!ACE_NAMESPACE && typeof requirejs !== "undefined")
46    return;
47
48
49var define = function(module, deps, payload) {
50    if (typeof module !== "string") {
51        if (define.original)
52            define.original.apply(this, arguments);
53        else {
54            console.error("dropping module because define wasn\'t a string.");
55            console.trace();
56        }
57        return;
58    }
59    if (arguments.length == 2)
60        payload = deps;
61    if (!define.modules[module]) {
62        define.payloads[module] = payload;
63        define.modules[module] = null;
64    }
65};
66
67define.modules = {};
68define.payloads = {};
69
70/**
71 * Get at functionality define()ed using the function above
72 */
73var _require = function(parentId, module, callback) {
74    if (typeof module === "string") {
75        var payload = lookup(parentId, module);
76        if (payload != undefined) {
77            callback && callback();
78            return payload;
79        }
80    } else if (Object.prototype.toString.call(module) === "[object Array]") {
81        var params = [];
82        for (var i = 0, l = module.length; i < l; ++i) {
83            var dep = lookup(parentId, module[i]);
84            if (dep == undefined && require.original)
85                return;
86            params.push(dep);
87        }
88        return callback && callback.apply(null, params) || true;
89    }
90};
91
92var require = function(module, callback) {
93    var packagedModule = _require("", module, callback);
94    if (packagedModule == undefined && require.original)
95        return require.original.apply(this, arguments);
96    return packagedModule;
97};
98
99var normalizeModule = function(parentId, moduleName) {
100    // normalize plugin requires
101    if (moduleName.indexOf("!") !== -1) {
102        var chunks = moduleName.split("!");
103        return normalizeModule(parentId, chunks[0]) + "!" + normalizeModule(parentId, chunks[1]);
104    }
105    // normalize relative requires
106    if (moduleName.charAt(0) == ".") {
107        var base = parentId.split("/").slice(0, -1).join("/");
108        moduleName = base + "/" + moduleName;
109
110        while(moduleName.indexOf(".") !== -1 && previous != moduleName) {
111            var previous = moduleName;
112            moduleName = moduleName.replace(/\/\.\//, "/").replace(/[^\/]+\/\.\.\//, "");
113        }
114    }
115    return moduleName;
116};
117
118/**
119 * Internal function to lookup moduleNames and resolve them by calling the
120 * definition function if needed.
121 */
122var lookup = function(parentId, moduleName) {
123    moduleName = normalizeModule(parentId, moduleName);
124
125    var module = define.modules[moduleName];
126    if (!module) {
127        module = define.payloads[moduleName];
128        if (typeof module === 'function') {
129            var exports = {};
130            var mod = {
131                id: moduleName,
132                uri: '',
133                exports: exports,
134                packaged: true
135            };
136
137            var req = function(module, callback) {
138                return _require(moduleName, module, callback);
139            };
140
141            var returnValue = module(req, exports, mod);
142            exports = returnValue || mod.exports;
143            define.modules[moduleName] = exports;
144            delete define.payloads[moduleName];
145        }
146        module = define.modules[moduleName] = exports || module;
147    }
148    return module;
149};
150
151function exportAce(ns) {
152    var root = global;
153    if (ns) {
154        if (!global[ns])
155            global[ns] = {};
156        root = global[ns];
157    }
158
159    if (!root.define || !root.define.packaged) {
160        define.original = root.define;
161        root.define = define;
162        root.define.packaged = true;
163    }
164
165    if (!root.require || !root.require.packaged) {
166        require.original = root.require;
167        root.require = require;
168        root.require.packaged = true;
169    }
170}
171
172exportAce(ACE_NAMESPACE);
173
174})();
175
176define("ace/lib/regexp",["require","exports","module"], function(require, exports, module) {
177"use strict";
178
179    var real = {
180            exec: RegExp.prototype.exec,
181            test: RegExp.prototype.test,
182            match: String.prototype.match,
183            replace: String.prototype.replace,
184            split: String.prototype.split
185        },
186        compliantExecNpcg = real.exec.call(/()??/, "")[1] === undefined, // check `exec` handling of nonp
186articipating capturing groups
187        compliantLastIndexIncrement = function () {
188            var x = /^/g;
189            real.test.call(x, "");
190            return !x.lastIndex;
191        }();
192
193    if (compliantLastIndexIncrement && compliantExecNpcg)
194        return;
195    RegExp.prototype.exec = function (str) {
196        var match = real.exec.apply(this, arguments),
197            name, r2;
198        if ( typeof(str) == 'string' && match) {
199            if (!compliantExecNpcg && match.length > 1 && indexOf(match, "") > -1) {
200                r2 = RegExp(this.source, real.replace.call(getNativeFlags(this), "g", ""));
201                real.replace.call(str.slice(match.index), r2, function () {
202                    for (var i = 1; i < arguments.length - 2; i++) {
203                        if (arguments[i] === undefined)
204                            match[i] = undefined;
205                    }
206                });
207            }
208            if (this._xregexp && this._xregexp.captureNames) {
209                for (var i = 1; i < match.length; i++) {
210                    name = this._xregexp.captureNames[i - 1];
211                    if (name)
212                       match[name] = match[i];
213                }
214            }
215            if (!compliantLastIndexIncrement && this.global && !match[0].length && (this.lastIndex > match.index))
216                this.lastIndex--;
217        }
218        return match;
219    };
220    if (!compliantLastIndexIncrement) {
221        RegExp.prototype.test = function (str) {
222            var match = real.exec.call(this, str);
223            if (match && this.global && !match[0].length && (this.lastIndex > match.index))
224                this.lastIndex--;
225            return !!match;
226        };
227    }
228
229    function getNativeFlags (regex) {
230        return (regex.global     ? "g" : "") +
231               (regex.ignoreCase ? "i" : "") +
232               (regex.multiline  ? "m" : "") +
233               (regex.extended   ? "x" : "") + // Proposed for ES4; included in AS3
234               (regex.sticky     ? "y" : "");
235    }
236
237    function indexOf (array, item, from) {
238        if (Array.prototype.indexOf) // Use the native array method if available
239            return array.indexOf(item, from);
240        for (var i = from || 0; i < array.length; i++) {
241            if (array[i] === item)
242                return i;
243        }
244        return -1;
245    }
246
247});
248
249define("ace/lib/es5-shim",["require","exports","module"], function(require, exports, module) {
250
251function Empty() {}
252
253if (!Function.prototype.bind) {
254    Function.prototype.bind = function bind(that) { // .length is 1
255        var target = this;
256        if (typeof target != "function") {
257            throw new TypeError("Function.prototype.bind called on incompatible " + target);
258        }
259        var args = slice.call(arguments, 1); // for normal call
260        var bound = function () {
261
262            if (this instanceof bound) {
263
264                var result = target.apply(
265                    this,
266                    args.concat(slice.call(arguments))
267                );
268                if (Object(result) === result) {
269                    return result;
270                }
271                return this;
272
273            } else {
274                return target.apply(
275                    that,
276                    args.concat(slice.call(arguments))
277                );
278
279            }
280
281        };
282        if(target.prototype) {
283            Empty.prototype = target.prototype;
284            bound.prototype = new Empty();
285            Empty.prototype = null;
286        }
287        return bound;
288    };
289}
290var call = Function.prototype.call;
291var prototypeOfArray = Array.prototype;
292var prototypeOfObject = Object.prototype;
293var slice = prototypeOfArray.slice;
294var _toString = call.bind(prototypeOfObject.toString);
295var owns = call.bind(prototypeOfObject.hasOwnProperty);
296var defineGetter;
297var defineSetter;
298var lookupGetter;
299var lookupSetter;
300var supportsAccessors;
301if ((supportsAccessors = owns(prototypeOfObject, "__defineGetter__"))) {
302    defineGetter = call.bind(prototypeOfObject.__defineGetter__);
303    defineSetter = call.bind(prototypeOfObject.__defineSetter__);
304    lookupGetter = call.bind(prototypeOfObject.__lookupGetter__);
305    lookupSetter = call.bind(prototypeOfObject.__lookupSetter__);
306}
307if ([1,2].splice(0).length != 2) {
308    if(function() { // test IE < 9 to splice bug - see issue #138
309        function makeArray(l) {
310            var a = new Array(l+2);
311            a[0] = a[1] = 0;
312            return a;
313        }
314        var array = [], lengthBefore;
315        
316        array.splice.apply(array, makeArray(20));
317        array.splice.apply(array, makeArray(26));
318
319        lengthBefore = array.length; //46
320        array.splice(5, 0, "XXX"); // add one element
321
322        lengthBefore + 1 == array.length
323
324        if (lengthBefore + 1 == array.length) {
325            return true;// has right splice implementation without bugs
326        }
327    }()) {//IE 6/7
328        var array_splice = Array.prototype.splice;
329        Array.prototype.splice = function(start, deleteCount) {
330            if (!arguments.length) {
331                return [];
332            } else {
333                return array_splice.apply(this, [
334                    start === void 0 ? 0 : start,
335                    deleteCount === void 0 ? (this.length - start) : deleteCount
336                ].concat(slice.call(arguments, 2)))
337            }
338        };
339    } else {//IE8
340        Array.prototype.splice = function(pos, removeCount){
341            var length = this.length;
342            if (pos > 0) {
343                if (pos > length)
344                    pos = length;
345            } else if (pos == void 0) {
346                pos = 0;
347            } else if (pos < 0) {
348                pos = Math.max(length + pos, 0);
349            }
350
351            if (!(pos+removeCount < length))
352                removeCount = length - pos;
353
354            var removed = this.slice(pos, pos+removeCount);
355            var insert = slice.call(arguments, 2);
356            var add = insert.length;            
357            if (pos === length) {
358                if (add) {
359                    this.push.apply(this, insert);
360                }
361            } else {
362                var remove = Math.min(removeCount, length - pos);
363                var tailOldPos = pos + remove;
364                var tailNewPos = tailOldPos + add - remove;
365                var tailCount = length - tailOldPos;
366                var lengthAfterRemove = length - remove;
367
368                if (tailNewPos < tailOldPos) { // case A
369                    for (var i = 0; i < tailCount; ++i) {
370                        this[tailNewPos+i] = this[tailOldPos+i];
371                    }
372                } else if (tailNewPos > tailOldPos) { // case B
373                    for (i = tailCount; i--; ) {
374                        this[tailNewPos+i] = this[tailOldPos+i];
375                    }
376                } // else, add == remove (nothing to do)
377
378                if (add && pos === lengthAfterRemove) {
379                    this.length = lengthAfterRemove; // truncate array
380                    this.push.apply(this, insert);
381                } else {
382                    this.length = lengthAfterRemove + add; // reserves space
383                    for (i = 0; i < add; ++i) {
384                        this[pos+i] = insert[i];
385                    }
386                }
387            }
388            return removed;
389        };
390    }
391}
392if (!Array.isArray) {
393    Array.isArray = function isArray(obj) {
394        return _toString(obj) == "[object Array]";
395    };
396}
397var boxedString = Object("a"),
398    splitString = boxedString[0] != "a" || !(0 in boxedString);
399
400if (!Array.prototype.forEach) {
401    Array.prototype.forEach = function forEach(fun /*, thisp*/) {
402        var object = toObject(this),
403            self = splitString && _toString(this) == "[object String]" ?
404                this.split("") :
405                object,
406            thisp = arguments[1],
407            i = -1,
408            length = self.length >>> 0;
409        if (_toString(fun) != "[object Function]") {
410            throw new TypeError(); // TODO message
411        }
412
413        while (++i < length) {
414            if (i in self) {
415                fun.call(thisp, self[i], i, object);
416            }
417        }
418    };
419}
420if (!Array.prototype.map) {
421    Array.prototype.map = function map(fun /*, thisp*/) {
422        var object = toObject(this),
423            self = splitString && _toString(this) == "[object String]" ?
424                this.split("") :
425                object,
426            length = self.length >>> 0,
427            result = Array(length),
428            thisp = arguments[1];
429        if (_toString(fun) != "[object Function]") {
430            throw new TypeError(fun + " is not a function");
431        }
432
433        for (var i = 0; i < length; i++) {
434            if (i in self)
435                result[i] = fun.call(thisp, self[i], i, object);
436        }
437        return result;
438    };
439}
440if (!Array.prototype.filter) {
441    Array.prototype.filter = function filter(fun /*, thisp */) {
442        var object = toObject(this),
443            self = splitString && _toString(this) == "[object String]" ?
444                this.split("") :
445                    object,
446            length = self.length >>> 0,
447            result = [],
448            value,
449            thisp = arguments[1];
450        if (_toString(fun) != "[object Function]") {
451            throw new TypeError(fun + " is not a function");
452        }
453
454        for (var i = 0; i < length; i++) {
455            if (i in self) {
456                value = self[i];
457                if (fun.call(thisp, value, i, object)) {
458                    result.push(value);
459                }
460            }
461        }
462        return result;
463    };
464}
465if (!Array.prototype.every) {
466    Array.prototype.every = function every(fun /*, thisp */) {
467        var object = toObject(this),
468            self = splitString && _toString(this) == "[object String]" ?
469                this.split("") :
470                object,
471            length = self.length >>> 0,
472            thisp = arguments[1];
473        if (_toString(fun) != "[object Function]") {
474            throw new TypeError(fun + " is not a function");
475        }
476
477        for (var i = 0; i < length; i++) {
478            if (i in self && !fun.call(thisp, self[i], i, object)) {
479                return false;
480            }
481        }
482        return true;
483    };
484}
485if (!Array.prototype.some) {
486    Array.prototype.some = function some(fun /*, thisp */) {
487        var object = toObject(this),
488            self = splitString && _toString(this) == "[object String]" ?
489                this.split("") :
490                object,
491            length = self.length >>> 0,
492            thisp = arguments[1];
493        if (_toString(fun) != "[object Function]") {
494            throw new TypeError(fun + " is not a function");
495        }
496
497        for (var i = 0; i < length; i++) {
498            if (i in self && fun.call(thisp, self[i], i, object)) {
499                return true;
500            }
501        }
502        return false;
503    };
504}
505if (!Array.prototype.reduce) {
506    Array.prototype.reduce = function reduce(fun /*, initial*/) {
507        var object = toObject(this),
508            self = splitString && _toString(this) == "[object String]" ?
509                this.split("") :
510                object,
511            length = self.length >>> 0;
512        if (_toString(fun) != "[object Function]") {
513            throw new TypeError(fun + " is not a function");
514        }
515        if (!length && arguments.length == 1) {
516            throw new TypeError("reduce of empty array with no initial value");
517        }
518
519        var i = 0;
520        var result;
521        if (arguments.length >= 2) {
522            result = arguments[1];
523        } else {
524            do {
525                if (i in self) {
526                    result = self[i++];
527                    break;
528                }
529                if (++i >= length) {
530                    throw new TypeError("reduce of empty array with no initial value");
531                }
532            } while (true);
533        }
534
535        for (; i < length; i++) {
536            if (i in self) {
537                result = fun.call(void 0, result, self[i], i, object);
538            }
539        }
540
541        return result;
542    };
543}
544if (!Array.prototype.reduceRight) {
545    Array.prototype.reduceRight = function reduceRight(fun /*, initial*/) {
546        var object = toObject(this),
547            self = splitString && _toString(this) == "[object String]" ?
548                this.split("") :
549                object,
550            length = self.length >>> 0;
551        if (_toString(fun) != "[object Function]") {
552            throw new TypeError(fun + " is not a function");
553        }
554        if (!length && arguments.length == 1) {
555            throw new TypeError("reduceRight of empty array with no initial value");
556        }
557
558        var result, i = length - 1;
559        if (arguments.length >= 2) {
560            result = arguments[1];
561        } else {
562            do {
563                if (i in self) {
564                    result = self[i--];
565                    break;
566                }
567                if (--i < 0) {
568                    throw new TypeError("reduceRight of empty array with no initial value");
569                }
570            } while (true);
571        }
572
573        do {
574            if (i in this) {
575                result = fun.call(void 0, result, self[i], i, object);
576            }
577        } while (i--);
578
579        return result;
580    };
581}
582if (!Array.prototype.indexOf || ([0, 1].indexOf(1, 2) != -1)) {
583    Array.prototype.indexOf = function indexOf(sought /*, fromIndex */ ) {
584        var self = splitString && _toString(this) == "[object String]" ?
585                this.split("") :
586                toObject(this),
587            length = self.length >>> 0;
588
589        if (!length) {
590            return -1;
591        }
592
593        var i = 0;
594        if (arguments.length > 1) {
595            i = toInteger(arguments[1]);
596        }
597        i = i >= 0 ? i : Math.max(0, length + i);
598        for (; i < length; i++) {
599            if (i in self && self[i] === sought) {
600                return i;
601            }
602        }
603        return -1;
604    };
605}
606if (!Array.prototype.lastIndexOf || ([0, 1].lastIndexOf(0, -3) != -1)) {
607    Array.prototype.lastIndexOf = function lastIndexOf(sought /*, fromIndex */) {
608        var self = splitString && _toString(this) == "[object String]" ?
609                this.split("") :
610                toObject(this),
611            length = self.length >>> 0;
612
613        if (!length) {
614            return -1;
615        }
616        var i = length - 1;
617        if (arguments.length > 1) {
618            i = Math.min(i, toInteger(arguments[1]));
619        }
620        i = i >= 0 ? i : length - Math.abs(i);
621        for (; i >= 0; i--) {
622            if (i in self && sought === self[i]) {
623                return i;
624            }
625        }
626        return -1;
627    };
628}
629if (!Object.getPrototypeOf) {
630    Object.getPrototypeOf = function getPrototypeOf(object) {
631        return object.__proto__ || (
632            object.constructor ?
633            object.constructor.prototype :
634            prototypeOfObject
635        );
636    };
637}
638if (!Object.getOwnPropertyDescriptor) {
639    var ERR_NON_OBJECT = "Object.getOwnPropertyDescriptor called on a " +
640                         "non-object: ";
641    Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(object, property) {
642        if ((typeof object != "object" && typeof object != "function") || object === null)
643            throw new TypeError(ERR_NON_OBJECT + object);
644        if (!owns(object, property))
645            return;
646
647        var descriptor, getter, setter;
648        descriptor =  { enumerable: true, configurable: true };
649        if (supportsAccessors) {
650            var prototype = object.__proto__;
651            object.__proto__ = prototypeOfObject;
652
653            var getter = lookupGetter(object, property);
654            var setter = lookupSetter(object, property);
655            object.__proto__ = prototype;
656
657            if (getter || setter) {
658                if (getter) descriptor.get = getter;
659                if (setter) descriptor.set = setter;
660                return descriptor;
661            }
662        }
663        descriptor.value = object[property];
664        return descriptor;
665    };
666}
667if (!Object.getOwnPropertyNames) {
668    Object.getOwnPropertyNames = function getOwnPropertyNames(object) {
669        return Object.keys(object);
670    };
671}
672if (!Object.create) {
673    var createEmpty;
674    if (Object.prototype.__proto__ === null) {
675        createEmpty = function () {
676            return { "__proto__": null };
677        };
678    } else {
679        createEmpty = function () {
680            var empty = {};
681            for (var i in empty)
682                empty[i] = null;
683            empty.constructor =
684            empty.hasOwnProperty =
685            empty.propertyIsEnumerable =
686            empty.isPrototypeOf =
687            empty.toLocaleString =
688            empty.toString =
689            empty.valueOf =
690            empty.__proto__ = null;
691            return empty;
692        }
693    }
694
695    Object.create = function create(prototype, properties) {
696        var object;
697        if (prototype === null) {
698            object = createEmpty();
699        } else {
700            if (typeof prototype != "object")
701                throw new TypeError("typeof prototype["+(typeof prototype)+"] != 'object'");
702            var Type = function () {};
703            Type.prototype = prototype;
704            object = new Type();
705            object.__proto__ = prototype;
706        }
707        if (properties !== void 0)
708            Object.defineProperties(object, properties);
709        return object;
710    };
711}
712
713function doesDefinePropertyWork(object) {
714    try {
715        Object.defineProperty(object, "sentinel", {});
716        return "sentinel" in object;
717    } catch (exception) {
718    }
719}
720if (Object.defineProperty) {
721    var definePropertyWorksOnObject = doesDefinePropertyWork({});
722    var definePropertyWorksOnDom = typeof document == "undefined" ||
723        doesDefinePropertyWork(document.createElement("div"));
724    if (!definePropertyWorksOnObject || !definePropertyWorksOnDom) {
725        var definePropertyFallback = Object.defineProperty;
726    }
727}
728
729if (!Object.defineProperty || definePropertyFallback) {
730    var ERR_NON_OBJECT_DESCRIPTOR = "Property description must be an object: ";
731    var ERR_NON_OBJECT_TARGET = "Object.defineProperty called on non-object: "
732    var ERR_ACCESSORS_NOT_SUPPORTED = "getters & setters can not be defined " +
733                                      "on this javascript engine";
734
735    Object.defineProperty = function defineProperty(object, property, descriptor) {
736        if ((typeof object != "object" && typeof object != "function") || object === null)
737            throw new TypeError(ERR_NON_OBJECT_TARGET + object);
738        if ((typeof descriptor != "object" && typeof descriptor != "function") || descriptor === null)
739            throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR + descriptor);
740        if (definePropertyFallback) {
741            try {
742                return definePropertyFallback.call(Object, object, property, descriptor);
743            } catch (exception) {
744            }
745        }
746        if (owns(descriptor, "value")) {
747
748            if (supportsAccessors && (lookupGetter(object, property) ||
749                                      lookupSetter(object, property)))
750            {
751                var prototype = object.__proto__;
752                object.__proto__ = prototypeOfObject;
753                delete object[property];
754                object[property] = descriptor.value;
755                object.__proto__ = prototype;
756            } else {
757                object[property] = descriptor.value;
758            }
759        } else {
760            if (!supportsAccessors)
761                throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);
762            if (owns(descriptor, "get"))
763                defineGetter(object, property, descriptor.get);
764            if (owns(descriptor, "set"))
765                defineSetter(object, property, descriptor.set);
766        }
767
768        return object;
769    };
770}
771if (!Object.defineProperties) {
772    Object.defineProperties = function defineProperties(object, properties) {
773        for (var property in properties) {
774            if (owns(properties, property))
775                Object.defineProperty(object, property, properties[property]);
776        }
777        return object;
778    };
779}
780if (!Object.seal) {
781    Object.seal = function seal(object) {
782        return object;
783    };
784}
785if (!Object.freeze) {
786    Object.freeze = function freeze(object) {
787        return object;
788    };
789}
790try {
791    Object.freeze(function () {});
792} catch (exception) {
793    Object.freeze = (function freeze(freezeObject) {
794        return function freeze(object) {
795            if (typeof object == "function") {
796                return object;
797            } else {
798                return freezeObject(object);
799            }
800        };
801    })(Object.freeze);
802}
803if (!Object.preventExtensions) {
804    Object.preventExtensions = function preventExtensions(object) {
805        return object;
806    };
807}
808if (!Object.isSealed) {
809    Object.isSealed = function isSealed(object) {
810        return false;
811    };
812}
813if (!Object.isFrozen) {
814    Object.isFrozen = function isFrozen(object) {
815        return false;
816    };
817}
818if (!Object.isExtensible) {
819    Object.isExtensible = function isExtensible(object) {
820        if (Object(object) === object) {
821            throw new TypeError(); // TODO message
822        }
823        var name = '';
824        while (owns(object, name)) {
825            name += '?';
826        }
827        object[name] = true;
828        var returnValue = owns(object, name);
829        delete object[name];
830        return returnValue;
831    };
832}
833if (!Object.keys) {
834    var hasDontEnumBug = true,
835        dontEnums = [
836            "toString",
837            "toLocaleString",
838            "valueOf",
839            "hasOwnProperty",
840            "isPrototypeOf",
841            "propertyIsEnumerable",
842            "constructor"
843        ],
844        dontEnumsLength = dontEnums.length;
845
846    for (var key in {"toString": null}) {
847        hasDontEnumBug = false;
848    }
849
850    Object.keys = function keys(object) {
851
852        if (
853            (typeof object != "object" && typeof object != "function") ||
854            object === null
855        ) {
856            throw new TypeError("Object.keys called on a non-object");
857        }
858
859        var keys = [];
860        for (var name in object) {
861            if (owns(object, name)) {
862                keys.push(name);
863            }
864        }
865
866        if (hasDontEnumBug) {
867            for (var i = 0, ii = dontEnumsLength; i < ii; i++) {
868                var dontEnum = dontEnums[i];
869                if (owns(object, dontEnum)) {
870                    keys.push(dontEnum);
871                }
872            }
873        }
874        return keys;
875    };
876
877}
878if (!Date.now) {
879    Date.now = function now() {
880        return new Date().getTime();
881    };
882}
883var ws = "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003" +
884    "\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028" +
885    "\u2029\uFEFF";
886if (!String.prototype.trim || ws.trim()) {
887    ws = "[" + ws + "]";
888    var trimBeginRegexp = new RegExp("^" + ws + ws + "*"),
889        trimEndRegexp = new RegExp(ws + ws + "*$");
890    String.prototype.trim = function trim() {
891        return String(this).replace(trimBeginRegexp, "").replace(trimEndRegexp, "");
892    };
893}
894
895function toInteger(n) {
896    n = +n;
897    if (n !== n) { // isNaN
898        n = 0;
899    } else if (n !== 0 && n !== (1/0) && n !== -(1/0)) {
900        n = (n > 0 || -1) * Math.floor(Math.abs(n));
901    }
902    return n;
903}
904
905function isPrimitive(input) {
906    var type = typeof input;
907    return (
908        input === null ||
909        type === "undefined" ||
910        type === "boolean" ||
911        type === "number" ||
912        type === "string"
913    );
914}
915
916function toPrimitive(input) {
917    var val, valueOf, toString;
918    if (isPrimitive(input)) {
919        return input;
920    }
921    valueOf = input.valueOf;
922    if (typeof valueOf === "function") {
923        val = valueOf.call(input);
924        if (isPrimitive(val)) {
925            return val;
926        }
927    }
928    toString = input.toString;
929    if (typeof toString === "function") {
930        val = toString.call(input);
931        if (isPrimitive(val)) {
932            return val;
933        }
934    }
935    throw new TypeError();
936}
937var toObject = function (o) {
938    if (o == null) { // this matches both null and undefined
939        throw new TypeError("can't convert "+o+" to object");
940    }
941    return Object(o);
942};
943
944});
945
946define("ace/lib/fixoldbrowsers",["require","exports","module","ace/lib/regexp","ace/lib/es5-shim"], function(require, exports, module) {
947"use strict";
948
949require("./regexp");
950require("./es5-shim");
951
952});
953
954define("ace/lib/dom",["require","exports","module"], function(require, exports, module) {
955"use strict";
956
957var XHTML_NS = "http://www.w3.org/1999/xhtml";
958
959exports.buildDom = function buildDom(arr, parent, refs) {
960    if (typeof arr == "string" && arr) {
961        var txt = document.createTextNode(arr);
962        if (parent)
963            parent.appendChild(txt);
964        return txt;
965    }
966    
967    if (!Array.isArray(arr))
968        return arr;
969    if (typeof arr[0] != "string" || !arr[0]) {
970        var els = [];
971        for (var i = 0; i < arr.length; i++) {
972            var ch = buildDom(arr[i], parent, refs);
973            ch && els.push(ch);
974        }
975        return els;
976    }
977    
978    var el = document.createElement(arr[0]);
979    var options = arr[1];
980    var childIndex = 1;
981    if (options && typeof options == "object" && !Array.isArray(options))
982        childIndex = 2;
983    for (var i = childIndex; i < arr.length; i++)
984        buildDom(arr[i], el, refs);
985    if (childIndex == 2) {
986        Object.keys(options).forEach(function(n) {
987            var val = options[n];
988            if (n === "class") {
989                el.className = Array.isArray(val) ? val.join(" ") : val;
990            } else if (typeof val == "function" || n == "value") {
991                el[n] = val;
992            } else if (n === "ref") {
993                if (refs) refs[val] = el;
994            } else if (val != null) {
995                el.setAttribute(n, val);
996            }
997        });
998    }
999    if (parent)
1000        parent.appendChild(el);
1001    return el;
1002};
1003
1004exports.getDocumentHead = function(doc) {
1005    if (!doc)
1006        doc = document;
1007    return doc.head || doc.getElementsByTagName("head")[0] || doc.documentElement;
1008};
1009
1010exports.createElement = function(tag, ns) {
1011    return document.createElementNS ?
1012           document.createElementNS(ns || XHTML_NS, tag) :
1013           document.createElement(tag);
1014};
1015
1016exports.hasCssClass = function(el, name) {
1017    var classes = (el.className + "").split(/\s+/g);
1018    return classes.indexOf(name) !== -1;
1019};
1020exports.addCssClass = function(el, name) {
1021    if (!exports.hasCssClass(el, name)) {
1022        el.className += " " + name;
1023    }
1024};
1025exports.removeCssClass = function(el, name) {
1026    var classes = el.className.split(/\s+/g);
1027    while (true) {
1028        var index = classes.indexOf(name);
1029        if (index == -1) {
1030            break;
1031        }
1032        classes.splice(index, 1);
1033    }
1034    el.className = classes.join(" ");
1035};
1036
1037exports.toggleCssClass = function(el, name) {
1038    var classes = el.className.split(/\s+/g), add = true;
1039    while (true) {
1040        var index = classes.indexOf(name);
1041        if (index == -1) {
1042            break;
1043        }
1044        add = false;
1045        classes.splice(index, 1);
1046    }
1047    if (add)
1048        classes.push(name);
1049
1050    el.className = classes.join(" ");
1051    return add;
1052};
1053exports.setCssClass = function(node, className, include) {
1054    if (include) {
1055        exports.addCssClass(node, className);
1056    } else {
1057        exports.removeCssClass(node, className);
1058    }
1059};
1060
1061exports.hasCssString = function(id, doc) {
1062    var index = 0, sheets;
1063    doc = doc || document;
1064
1065    if (doc.createStyleSheet && (sheets = doc.styleSheets)) {
1066        while (index < sheets.length)
1067            if (sheets[index++].owningElement.id === id) return true;
1068    } else if ((sheets = doc.getElementsByTagName("style"))) {
1069        while (index < sheets.length)
1070            if (sheets[index++].id === id) return true;
1071    }
1072
1073    return false;
1074};
1075
1076exports.importCssString = function importCssString(cssText, id, doc) {
1077    doc = doc || document;
1078    if (id && exports.hasCssString(id, doc))
1079        return null;
1080    
1081    var style;
1082    
1083    if (id)
1084        cssText += "\n/*# sourceURL=ace/css/" + id + " */";
1085    
1086    if (doc.createStyleSheet) {
1087        style = doc.createStyleSheet();
1088        style.cssText = cssText;
1089        if (id)
1090            style.owningElement.id = id;
1091    } else {
1092        style = exports.createElement("style");
1093        style.appendChild(doc.createTextNode(cssText));
1094        if (id)
1095            style.id = id;
1096
1097        exports.getDocumentHead(doc).appendChild(style);
1098    }
1099};
1100
1101exports.importCssStylsheet = function(uri, doc) {
1102    if (doc.createStyleSheet) {
1103        doc.createStyleSheet(uri);
1104    } else {
1105        var link = exports.createElement('link');
1106        link.rel = 'stylesheet';
1107        link.href = uri;
1108
1109        exports.getDocumentHead(doc).appendChild(link);
1110    }
1111};
1112
1113exports.getInnerWidth = function(element) {
1114    return (
1115        parseInt(exports.computedStyle(element, "paddingLeft"), 10) +
1116        parseInt(exports.computedStyle(element, "paddingRight"), 10) + 
1117        element.clientWidth
1118    );
1119};
1120
1121exports.getInnerHeight = function(element) {
1122    return (
1123        parseInt(exports.computedStyle(element, "paddingTop"), 10) +
1124        parseInt(exports.computedStyle(element, "paddingBottom"), 10) +
1125        element.clientHeight
1126    );
1127};
1128
1129exports.scrollbarWidth = function(document) {
1130    var inner = exports.createElement("ace_inner");
1131    inner.style.width = "100%";
1132    inner.style.minWidth = "0px";
1133    inner.style.height = "200px";
1134    inner.style.display = "block";
1135
1136    var outer = exports.createElement("ace_outer");
1137    var style = outer.style;
1138
1139    style.position = "absolute";
1140    style.left = "-10000px";
1141    style.overflow = "hidden";
1142    style.width = "200px";
1143    style.minWidth = "0px";
1144    style.height = "150px";
1145    style.display = "block";
1146
1147    outer.appendChild(inner);
1148
1149    var body = document.documentElement;
1150    body.appendChild(outer);
1151
1152    var noScrollbar = inner.offsetWidth;
1153
1154    style.overflow = "scroll";
1155    var withScrollbar = inner.offsetWidth;
1156
1157    if (noScrollbar == withScrollbar) {
1158        withScrollbar = outer.clientWidth;
1159    }
1160
1161    body.removeChild(outer);
1162
1163    return noScrollbar-withScrollbar;
1164};
1165
1166if (typeof document == "undefined") {
1167    exports.importCssString = function() {};
1168    return;
1169}
1170
1171if (window.pageYOffset !== undefined) {
1172    exports.getPageScrollTop = function() {
1173        return window.pageYOffset;
1174    };
1175
1176    exports.getPageScrollLeft = function() {
1177        return window.pageXOffset;
1178    };
1179}
1180else {
1181    exports.getPageScrollTop = function() {
1182        return document.body.scrollTop;
1183    };
1184
1185    exports.getPageScrollLeft = function() {
1186        return document.body.scrollLeft;
1187    };
1188}
1189
1190if (window.getComputedStyle)
1191    exports.computedStyle = function(element, style) {
1192        if (style)
1193            return (window.getComputedStyle(element, "") || {})[style] || "";
1194        return window.getComputedStyle(element, "") || {};
1195    };
1196else
1197    exports.computedStyle = function(element, style) {
1198        if (style)
1199            return element.currentStyle[style];
1200        return element.currentStyle;
1201    };
1202exports.setInnerHtml = function(el, innerHtml) {
1203    var element = el.cloneNode(false);//document.createElement("div");
1204    element.innerHTML = innerHtml;
1205    el.parentNode.replaceChild(element, el);
1206    return element;
1207};
1208
1209if ("textContent" in document.documentElement) {
1210    exports.setInnerText = function(el, innerText) {
1211        el.textContent = innerText;
1212    };
1213
1214    exports.getInnerText = function(el) {
1215        return el.textContent;
1216    };
1217}
1218else {
1219    exports.setInnerText = function(el, innerText) {
1220        el.innerText = innerText;
1221    };
1222
1223    exports.getInnerText = function(el) {
1224        return el.innerText;
1225    };
1226}
1227
1228exports.getParentWindow = function(document) {
1229    return document.defaultView || document.parentWindow;
1230};
1231
1232});
1233
1234define("ace/lib/oop",["require","exports","module"], function(require, exports, module) {
1235"use strict";
1236
1237exports.inherits = function(ctor, superCtor) {
1238    ctor.super_ = superCtor;
1239    ctor.prototype = Object.create(superCtor.prototype, {
1240        constructor: {
1241            value: ctor,
1242            enumerable: false,
1243            writable: true,
1244            configurable: true
1245        }
1246    });
1247};
1248
1249exports.mixin = function(obj, mixin) {
1250    for (var key in mixin) {
1251        obj[key] = mixin[key];
1252    }
1253    return obj;
1254};
1255
1256exports.implement = function(proto, mixin) {
1257    exports.mixin(proto, mixin);
1258};
1259
1260});
1261
1262define("ace/lib/keys",["require","exports","module","ace/lib/fixoldbrowsers","ace/lib/oop"], function(require, exports, module) {
1263"use strict";
1264
1265require("./fixoldbrowsers");
1266
1267var oop = require("./oop");
1268var Keys = (function() {
1269    var ret = {
1270        MODIFIER_KEYS: {
1271            16: 'Shift', 17: 'Ctrl', 18: 'Alt', 224: 'Meta'
1272        },
1273
1274        KEY_MODS: {
1275            "ctrl": 1, "alt": 2, "option" : 2, "shift": 4,
1276            "super": 8, "meta": 8, "command": 8, "cmd": 8
1277        },
1278
1279        FUNCTION_KEYS : {
1280            8  : "Backspace",
1281            9  : "Tab",
1282            13 : "Return",
1283            19 : "Pause",
1284            27 : "Esc",
1285            32 : "Space",
1286            33 : "PageUp",
1287            34 : "PageDown",
1288            35 : "End",
1289            36 : "Home",
1290            37 : "Left",
1291            38 : "Up",
1292            39 : "Right",
1293            40 : "Down",
1294            44 : "Print",
1295            45 : "Insert",
1296            46 : "Delete",
1297            96 : "Numpad0",
1298            97 : "Numpad1",
1299            98 : "Numpad2",
1300            99 : "Numpad3",
1301            100: "Numpad4",
1302            101: "Numpad5",
1303            102: "Numpad6",
1304            103: "Numpad7",
1305            104: "Numpad8",
1306            105: "Numpad9",
1307            '-13': "NumpadEnter",
1308            112: "F1",
1309            113: "F2",
1310            114: "F3",
1311            115: "F4",
1312            116: "F5",
1313            117: "F6",
1314            118: "F7",
1315            119: "F8",
1316            120: "F9",
1317            121: "F10",
1318            122: "F11",
1319            123: "F12",
1320            144: "Numlock",
1321            145: "Scrolllock"
1322        },
1323
1324        PRINTABLE_KEYS: {
1325           32: ' ',  48: '0',  49: '1',  50: '2',  51: '3',  52: '4', 53:  '5',
1326           54: '6',  55: '7',  56: '8',  57: '9',  59: ';',  61: '=', 65:  'a',
1327           66: 'b',  67: 'c',  68: 'd',  69: 'e',  70: 'f',  71: 'g', 72:  'h',
1328           73: 'i',  74: 'j',  75: 'k',  76: 'l',  77: 'm',  78: 'n', 79:  'o',
1329           80: 'p',  81: 'q',  82: 'r',  83: 's',  84: 't',  85: 'u', 86:  'v',
1330           87: 'w',  88: 'x',  89: 'y',  90: 'z', 107: '+', 109: '-', 110: '.',
1331          186: ';', 187: '=', 188: ',', 189: '-', 190: '.', 191: '/', 192: '`',
1332          219: '[', 220: '\\',221: ']', 222: "'", 111: '/', 106: '*'
1333        }
1334    };
1335    var name, i;
1336    for (i in ret.FUNCTION_KEYS) {
1337        name = ret.FUNCTION_KEYS[i].toLowerCase();
1338        ret[name] = parseInt(i, 10);
1339    }
1340    for (i in ret.PRINTABLE_KEYS) {
1341        name = ret.PRINTABLE_KEYS[i].toLowerCase();
1342        ret[name] = parseInt(i, 10);
1343    }
1344    oop.mixin(ret, ret.MODIFIER_KEYS);
1345    oop.mixin(ret, ret.PRINTABLE_KEYS);
1346    oop.mixin(ret, ret.FUNCTION_KEYS);
1347    ret.enter = ret["return"];
1348    ret.escape = ret.esc;
1349    ret.del = ret["delete"];
1350    ret[173] = '-';
1351    
1352    (function() {
1353        var mods = ["cmd", "ctrl", "alt", "shift"];
1354        for (var i = Math.pow(2, mods.length); i--;) {            
1355            ret.KEY_MODS[i] = mods.filter(function(x) {
1356                return i & ret.KEY_MODS[x];
1357            }).join("-") + "-";
1358        }
1359    })();
1360
1361    ret.KEY_MODS[0] = "";
1362    ret.KEY_MODS[-1] = "input-";
1363
1364    return ret;
1365})();
1366oop.mixin(exports, Keys);
1367
1368exports.keyCodeToString = function(keyCode) {
1369    var keyString = Keys[keyCode];
1370    if (typeof keyString != "string")
1371        keyString = String.fromCharCode(keyCode);
1372    return keyString.toLowerCase();
1373};
1374
1375});
1376
1377define("ace/lib/useragent",["require","exports","module"], function(require, exports, module) {
1378"use strict";
1379exports.OS = {
1380    LINUX: "LINUX",
1381    MAC: "MAC",
1382    WINDOWS: "WINDOWS"
1383};
1384exports.getOS = function() {
1385    if (exports.isMac) {
1386        return exports.OS.MAC;
1387    } else if (exports.isLinux) {
1388        return exports.OS.LINUX;
1389    } else {
1390        return exports.OS.WINDOWS;
1391    }
1392};
1393if (typeof navigator != "object")
1394    return;
1395
1396var os = (navigator.platform.match(/mac|win|linux/i) || ["other"])[0].toLowerCase();
1397var ua = navigator.userAgent;
1398exports.isWin = (os == "win");
1399exports.isMac = (os == "mac");
1400exports.isLinux = (os == "linux");
1401exports.isIE = 
1402    (navigator.appName == "Microsoft Internet Explorer" || navigator.appName.indexOf("MSAppHost") >= 0)
1403    ? parseFloat((ua.match(/(?:MSIE |Trident\/[0-9]+[\.0-9]+;.*rv:)([0-9]+[\.0-9]+)/)||[])[1])
1404    : parseFloat((ua.match(/(?:Trident\/[0-9]+[\.0-9]+;.*rv:)([0-9]+[\.0-9]+)/)||[])[1]); // for ie
1405    
1406exports.isOldIE = exports.isIE && exports.isIE < 9;
1407exports.isGecko = exports.isMozilla = ua.match(/ Gecko\/\d+/);
1408exports.isOpera = window.opera && Object.prototype.toString.call(window.opera) == "[object Opera]";
1409exports.isWebKit = parseFloat(ua.split("WebKit/")[1]) || undefined;
1410
1411exports.isChrome = parseFloat(ua.split(" Chrome/")[1]) || undefined;
1412
1413exports.isAIR = ua.indexOf("AdobeAIR") >= 0;
1414
1415exports.isIPad = ua.indexOf("iPad") >= 0;
1416
1417exports.isChromeOS = ua.indexOf(" CrOS ") >= 0;
1418
1419exports.isIOS = /iPad|iPhone|iPod/.test(ua) && !window.MSStream;
1420
1421if (exports.isIOS) exports.isMac = true;
1422
1423});
1424
1425define("ace/lib/event",["require","exports","module","ace/lib/keys","ace/lib/useragent"], function(require, exports, module) {
1426"use strict";
1427
1428var keys = require("./keys");
1429var useragent = require("./useragent");
1430
1431var pressedKeys = null;
1432var ts = 0;
1433
1434exports.addListener = function(elem, type, callback) {
1435    if (elem.addEventListener) {
1436        return elem.addEventListener(type, callback, false);
1437    }
1438    if (elem.attachEvent) {
1439        var wrapper = function() {
1440            callback.call(elem, window.event);
1441        };
1442        callback._wrapper = wrapper;
1443        elem.attachEvent("on" + type, wrapper);
1444    }
1445};
1446
1447exports.removeListener = function(elem, type, callback) {
1448    if (elem.removeEventListener) {
1449        return elem.removeEventListener(type, callback, false);
1450    }
1451    if (elem.detachEvent) {
1452        elem.detachEvent("on" + type, callback._wrapper || callback);
1453    }
1454};
1455exports.stopEvent = function(e) {
1456    exports.stopPropagation(e);
1457    exports.preventDefault(e);
1458    return false;
1459};
1460
1461exports.stopPropagation = function(e) {
1462    if (e.stopPropagation)
1463        e.stopPropagation();
1464    else
1465        e.cancelBubble = true;
1466};
1467
1468exports.preventDefault = function(e) {
1469    if (e.preventDefault)
1470        e.preventDefault();
1471    else
1472        e.returnValue = false;
1473};
1474exports.getButton = function(e) {
1475    if (e.type == "dblclick")
1476        return 0;
1477    if (e.type == "contextmenu" || (useragent.isMac && (e.ctrlKey && !e.altKey && !e.shiftKey)))
1478        return 2;
1479    if (e.preventDefault) {
1480        return e.button;
1481    }
1482    else {
1483        return {1:0, 2:2, 4:1}[e.button];
1484    }
1485};
1486
1487exports.capture = function(el, eventHandler, releaseCaptureHandler) {
1488    function onMouseUp(e) {
1489        eventHandler && eventHandler(e);
1490        releaseCaptureHandler && releaseCaptureHandler(e);
1491
1492        exports.removeListener(document, "mousemove", eventHandler, true);
1493        exports.removeListener(document, "mouseup", onMouseUp, true);
1494        exports.removeListener(document, "dragstart", onMouseUp, true);
1495    }
1496
1497    exports.addListener(document, "mousemove", eventHandler, true);
1498    exports.addListener(document, "mouseup", onMouseUp, true);
1499    exports.addListener(document, "dragstart", onMouseUp, true);
1500    
1501    return onMouseUp;
1502};
1503
1504exports.addTouchMoveListener = function (el, callback) {
1505    var startx, starty;
1506    exports.addListener(el, "touchstart", function (e) {
1507        var touches = e.touches;
1508        var touchObj = touches[0];
1509        startx = touchObj.clientX;
1510        starty = touchObj.clientY;
1511    });
1512    exports.addListener(el, "touchmove", function (e) {
1513        var touches = e.touches;
1514        if (touches.length > 1) return;
1515        
1516        var touchObj = touches[0];
1517
1518        e.wheelX = startx - touchObj.clientX;
1519        e.wheelY = starty - touchObj.clientY;
1520
1521        startx = touchObj.clientX;
1522        starty = touchObj.clientY;
1523
1524        callback(e);
1525    });
1526};
1527
1528exports.addMouseWheelListener = function(el, callback) {
1529    if ("onmousewheel" in el) {
1530        exports.addListener(el, "mousewheel", function(e) {
1531            var factor = 8;
1532            if (e.wheelDeltaX !== undefined) {
1533                e.wheelX = -e.wheelDeltaX / factor;
1534                e.wheelY = -e.wheelDeltaY / factor;
1535            } else {
1536                e.wheelX = 0;
1537                e.wheelY = -e.wheelDelta / factor;
1538            }
1539            callback(e);
1540        });
1541    } else if ("onwheel" in el) {
1542        exports.addListener(el, "wheel",  function(e) {
1543            var factor = 0.35;
1544            switch (e.deltaMode) {
1545                case e.DOM_DELTA_PIXEL:
1546                    e.wheelX = e.deltaX * factor || 0;
1547                    e.wheelY = e.deltaY * factor || 0;
1548                    break;
1549                case e.DOM_DELTA_LINE:
1550                case e.DOM_DELTA_PAGE:
1551                    e.wheelX = (e.deltaX || 0) * 5;
1552                    e.wheelY = (e.deltaY || 0) * 5;
1553                    break;
1554            }
1555            
1556            callback(e);
1557        });
1558    } else {
1559        exports.addListener(el, "DOMMouseScroll", function(e) {
1560            if (e.axis && e.axis == e.HORIZONTAL_AXIS) {
1561                e.wheelX = (e.detail || 0) * 5;
1562                e.wheelY = 0;
1563            } else {
1564                e.wheelX = 0;
1565                e.wheelY = (e.detail || 0) * 5;
1566            }
1567            callback(e);
1568        });
1569    }
1570};
1571
1572exports.addMultiMouseDownListener = function(elements, timeouts, eventHandler, callbackName) {
1573    var clicks = 0;
1574    var startX, startY, timer; 
1575    var eventNames = {
1576        2: "dblclick",
1577        3: "tripleclick",
1578        4: "quadclick"
1579    };
1580
1581    function onMousedown(e) {
1582        if (exports.getButton(e) !== 0) {
1583            clicks = 0;
1584        } else if (e.detail > 1) {
1585            clicks++;
1586            if (clicks > 4)
1587                clicks = 1;
1588        } else {
1589            clicks = 1;
1590        }
1591        if (useragent.isIE) {
1592            var isNewClick = Math.abs(e.clientX - startX) > 5 || Math.abs(e.clientY - startY) > 5;
1593            if (!timer || isNewClick)
1594                clicks = 1;
1595            if (timer)
1596                clearTimeout(timer);
1597            timer = setTimeout(function() {timer = null;}, timeouts[clicks - 1] || 600);
1598
1599            if (clicks == 1) {
1600                startX = e.clientX;
1601                startY = e.clientY;
1602            }
1603        }
1604        
1605        e._clicks = clicks;
1606
1607        eventHandler[callbackName]("mousedown", e);
1608
1609        if (clicks > 4)
1610            clicks = 0;
1611        else if (clicks > 1)
1612            return eventHandler[callbackName](eventNames[clicks], e);
1613    }
1614    function onDblclick(e) {
1615        clicks = 2;
1616        if (timer)
1617            clearTimeout(timer);
1618        timer = setTimeout(function() {timer = null;}, timeouts[clicks - 1] || 600);
1619        eventHandler[callbackName]("mousedown", e);
1620        eventHandler[callbackName](eventNames[clicks], e);
1621    }
1622    if (!Array.isArray(elements))
1623        elements = [elements];
1624    elements.forEach(function(el) {
1625        exports.addListener(el, "mousedown", onMousedown);
1626        if (useragent.isOldIE)
1627            exports.addListener(el, "dblclick", onDblclick);
1628    });
1629};
1630
1631var getModifierHash = useragent.isMac && useragent.isOpera && !("KeyboardEvent" in window)
1632    ? function(e) {
1633        return 0 | (e.metaKey ? 1 : 0) | (e.altKey ? 2 : 0) | (e.shiftKey ? 4 : 0) | (e.ctrlKey ? 8 : 0);
1634    }
1635    : function(e) {
1636        return 0 | (e.ctrlKey ? 1 : 0) | (e.altKey ? 2 : 0) | (e.shiftKey ? 4 : 0) | (e.metaKey ? 8 : 0);
1637    };
1638
1639exports.getModifierString = function(e) {
1640    return keys.KEY_MODS[getModifierHash(e)];
1641};
1642
1643function normalizeCommandKeys(callback, e, keyCode) {
1644    var hashId = getModifierHash(e);
1645
1646    if (!useragent.isMac && pressedKeys) {
1647        if (e.getModifierState && (e.getModifierState("OS") || e.getModifierState("Win")))
1648            hashId |= 8;
1649        if (pressedKeys.altGr) {
1650            if ((3 & hashId) != 3)
1651                pressedKeys.altGr = 0;
1652            else
1653                return;
1654        }
1655        if (keyCode === 18 || keyCode === 17) {
1656            var location = "location" in e ? e.location : e.keyLocation;
1657            if (keyCode === 17 && location === 1) {
1658                if (pressedKeys[keyCode] == 1)
1659                    ts = e.timeStamp;
1660            } else if (keyCode === 18 && hashId === 3 && location === 2) {
1661                var dt = e.timeStamp - ts;
1662                if (dt < 50)
1663                    pressedKeys.altGr = true;
1664            }
1665        }
1666    }
1667    
1668    if (keyCode in keys.MODIFIER_KEYS) {
1669        keyCode = -1;
1670    }
1671    if (hashId & 8 && (keyCode >= 91 && keyCode <= 93)) {
1672        keyCode = -1;
1673    }
1674    
1675    if (!hashId && keyCode === 13) {
1676        var location = "location" in e ? e.location : e.keyLocation;
1677        if (location === 3) {
1678            callback(e, hashId, -keyCode);
1679            if (e.defaultPrevented)
1680                return;
1681        }
1682    }
1683    
1684    if (useragent.isChromeOS && hashId & 8) {
1685        callback(e, hashId, keyCode);
1686        if (e.defaultPrevented)
1687            return;
1688        else
1689            hashId &= ~8;
1690    }
1691    if (!hashId && !(keyCode in keys.FUNCTION_KEYS) && !(keyCode in keys.PRINTABLE_KEYS)) {
1692        return false;
1693    }
1694    
1695    return callback(e, hashId, keyCode);
1696}
1697
1698
1699exports.addCommandKeyListener = function(el, callback) {
1700    var addListener = exports.addListener;
1701    if (useragent.isOldGecko || (useragent.isOpera && !("KeyboardEvent" in window))) {
1702        var lastKeyDownKeyCode = null;
1703        addListener(el, "keydown", function(e) {
1704            lastKeyDownKeyCode = e.keyCode;
1705        });
1706        addListener(el, "keypress", function(e) {
1707            return normalizeCommandKeys(callback, e, lastKeyDownKeyCode);
1708        });
1709    } else {
1710        var lastDefaultPrevented = null;
1711
1712        addListener(el, "keydown", function(e) {
1713            pressedKeys[e.keyCode] = (pressedKeys[e.keyCode] || 0) + 1;
1714            var result = normalizeCommandKeys(callback, e, e.keyCode);
1715            lastDefaultPrevented = e.defaultPrevented;
1716            return result;
1717        });
1718
1719        addListener(el, "keypress", function(e) {
1720            if (lastDefaultPrevented && (e.ctrlKey || e.altKey || e.shiftKey || e.metaKey)) {
1721                exports.stopEvent(e);
1722                lastDefaultPrevented = null;
1723            }
1724        });
1725
1726        addListener(el, "keyup", function(e) {
1727            pressedKeys[e.keyCode] = null;
1728        });
1729
1730        if (!pressedKeys) {
1731            resetPressedKeys();
1732            addListener(window, "focus", resetPressedKeys);
1733        }
1734    }
1735};
1736function resetPressedKeys() {
1737    pressedKeys = Object.create(null);
1738}
1739
1740if (typeof window == "object" && window.postMessage && !useragent.isOldIE) {
1741    var postMessageId = 1;
1742    exports.nextTick = function(callback, win) {
1743        win = win || window;
1744        var messageName = "zero-timeout-message-" + postMessageId;
1745        exports.addListener(win, "message", function listener(e) {
1746            if (e.data == messageName) {
1747                exports.stopPropagation(e);
1748                exports.removeListener(win, "message", listener);
1749                callback();
1750            }
1751        });
1752        win.postMessage(messageName, "*");
1753    };
1754}
1755
1756
1757exports.nextFrame = typeof window == "object" && (window.requestAnimationFrame
1758    || window.mozRequestAnimationFrame
1759    || window.webkitRequestAnimationFrame
1760    || window.msRequestAnimationFrame
1761    || window.oRequestAnimationFrame);
1762
1763if (exports.nextFrame)
1764    exports.nextFrame = exports.nextFrame.bind(window);
1765else
1766    exports.nextFrame = function(callback) {
1767        setTimeout(callback, 17);
1768    };
1769});
1770
1771define("ace/range",["require","exports","module"], function(require, exports, module) {
1772"use strict";
1773var comparePoints = function(p1, p2) {
1774    return p1.row - p2.row || p1.column - p2.column;
1775};
1776var Range = function(startRow, startColumn, endRow, endColumn) {
1777    this.start = {
1778        row: startRow,
1779        column: startColumn
1780    };
1781
1782    this.end = {
1783        row: endRow,
1784        column: endColumn
1785    };
1786};
1787
1788(function() {
1789    this.isEqual = function(range) {
1790        return this.start.row === range.start.row &&
1791            this.end.row === range.end.row &&
1792            this.start.column === range.start.column &&
1793            this.end.column === range.end.column;
1794    };
1795    this.toString = function() {
1796        return ("Range: [" + this.start.row + "/" + this.start.column +
1797            "] -> [" + this.end.row + "/" + this.end.column + "]");
1798    };
1799
1800    this.contains = function(row, column) {
1801        return this.compare(row, column) == 0;
1802    };
1803    this.compareRange = function(range) {
1804        var cmp,
1805            end = range.end,
1806            start = range.start;
1807
1808        cmp = this.compare(end.row, end.column);
1809        if (cmp == 1) {
1810            cmp = this.compare(start.row, start.column);
1811            if (cmp == 1) {
1812                return 2;
1813            } else if (cmp == 0) {
1814                return 1;
1815            } else {
1816                return 0;
1817            }
1818        } else if (cmp == -1) {
1819            return -2;
1820        } else {
1821            cmp = this.compare(start.row, start.column);
1822            if (cmp == -1) {
1823                return -1;
1824            } else if (cmp == 1) {
1825                return 42;
1826            } else {
1827                return 0;
1828            }
1829        }
1830    };
1831    this.comparePoint = function(p) {
1832        return this.compare(p.row, p.column);
1833    };
1834    this.containsRange = function(range) {
1835        return this.comparePoint(range.start) == 0 && this.comparePoint(range.end) == 0;
1836    };
1837    this.intersects = function(range) {
1838        var cmp = this.compareRange(range);
1839        return (cmp == -1 || cmp == 0 || cmp == 1);
1840    };
1841    this.isEnd = function(row, column) {
vendor: 10,257 bytes, lines 1842-2228
1842        return this.end.row == row && this.end.column == column;
1843    };
1844    this.isStart = function(row, column) {
1845        return this.start.row == row && this.start.column == column;
1846    };
1847    this.setStart = function(row, column) {
1848        if (typeof row == "object") {
1849            this.start.column = row.column;
1850            this.start.row = row.row;
1851        } else {
1852            this.start.row = row;
1853            this.start.column = column;
1854        }
1855    };
1856    this.setEnd = function(row, column) {
1857        if (typeof row == "object") {
1858            this.end.column = row.column;
1859            this.end.row = row.row;
1860        } else {
1861            this.end.row = row;
1862            this.end.column = column;
1863        }
1864    };
1865    this.inside = function(row, column) {
1866        if (this.compare(row, column) == 0) {
1867            if (this.isEnd(row, column) || this.isStart(row, column)) {
1868                return false;
1869            } else {
1870                return true;
1871            }
1872        }
1873        return false;
1874    };
1875    this.insideStart = function(row, column) {
1876        if (this.compare(row, column) == 0) {
1877            if (this.isEnd(row, column)) {
1878                return false;
1879            } else {
1880                return true;
1881            }
1882        }
1883        return false;
1884    };
1885    this.insideEnd = function(row, column) {
1886        if (this.compare(row, column) == 0) {
1887            if (this.isStart(row, column)) {
1888                return false;
1889            } else {
1890                return true;
1891            }
1892        }
1893        return false;
1894    };
1895    this.compare = function(row, column) {
1896        if (!this.isMultiLine()) {
1897            if (row === this.start.row) {
1898                return column < this.start.column ? -1 : (column > this.end.column ? 1 : 0);
1899            }
1900        }
1901
1902        if (row < this.start.row)
1903            return -1;
1904
1905        if (row > this.end.row)
1906            return 1;
1907
1908        if (this.start.row === row)
1909            return column >= this.start.column ? 0 : -1;
1910
1911        if (this.end.row === row)
1912            return column <= this.end.column ? 0 : 1;
1913
1914        return 0;
1915    };
1916    this.compareStart = function(row, column) {
1917        if (this.start.row == row && this.start.column == column) {
1918            return -1;
1919        } else {
1920            return this.compare(row, column);
1921        }
1922    };
1923    this.compareEnd = function(row, column) {
1924        if (this.end.row == row && this.end.column == column) {
1925            return 1;
1926        } else {
1927            return this.compare(row, column);
1928        }
1929    };
1930    this.compareInside = function(row, column) {
1931        if (this.end.row == row && this.end.column == column) {
1932            return 1;
1933        } else if (this.start.row == row && this.start.column == column) {
1934            return -1;
1935        } else {
1936            return this.compare(row, column);
1937        }
1938    };
1939    this.clipRows = function(firstRow, lastRow) {
1940        if (this.end.row > lastRow)
1941            var end = {row: lastRow + 1, column: 0};
1942        else if (this.end.row < firstRow)
1943            var end = {row: firstRow, column: 0};
1944
1945        if (this.start.row > lastRow)
1946            var start = {row: lastRow + 1, column: 0};
1947        else if (this.start.row < firstRow)
1948            var start = {row: firstRow, column: 0};
1949
1950        return Range.fromPoints(start || this.start, end || this.end);
1951    };
1952    this.extend = function(row, column) {
1953        var cmp = this.compare(row, column);
1954
1955        if (cmp == 0)
1956            return this;
1957        else if (cmp == -1)
1958            var start = {row: row, column: column};
1959        else
1960            var end = {row: row, column: column};
1961
1962        return Range.fromPoints(start || this.start, end || this.end);
1963    };
1964
1965    this.isEmpty = function() {
1966        return (this.start.row === this.end.row && this.start.column === this.end.column);
1967    };
1968    this.isMultiLine = function() {
1969        return (this.start.row !== this.end.row);
1970    };
1971    this.clone = function() {
1972        return Range.fromPoints(this.start, this.end);
1973    };
1974    this.collapseRows = function() {
1975        if (this.end.column == 0)
1976            return new Range(this.start.row, 0, Math.max(this.start.row, this.end.row-1), 0);
1977        else
1978            return new Range(this.start.row, 0, this.end.row, 0);
1979    };
1980    this.toScreenRange = function(session) {
1981        var screenPosStart = session.documentToScreenPosition(this.start);
1982        var screenPosEnd = session.documentToScreenPosition(this.end);
1983
1984        return new Range(
1985            screenPosStart.row, screenPosStart.column,
1986            screenPosEnd.row, screenPosEnd.column
1987        );
1988    };
1989    this.moveBy = function(row, column) {
1990        this.start.row += row;
1991        this.start.column += column;
1992        this.end.row += row;
1993        this.end.column += column;
1994    };
1995
1996}).call(Range.prototype);
1997Range.fromPoints = function(start, end) {
1998    return new Range(start.row, start.column, end.row, end.column);
1999};
2000Range.comparePoints = comparePoints;
2001
2002Range.comparePoints = function(p1, p2) {
2003    return p1.row - p2.row || p1.column - p2.column;
2004};
2005
2006
2007exports.Range = Range;
2008});
2009
2010define("ace/lib/lang",["require","exports","module"], function(require, exports, module) {
2011"use strict";
2012
2013exports.last = function(a) {
2014    return a[a.length - 1];
2015};
2016
2017exports.stringReverse = function(string) {
2018    return string.split("").reverse().join("");
2019};
2020
2021exports.stringRepeat = function (string, count) {
2022    var result = '';
2023    while (count > 0) {
2024        if (count & 1)
2025            result += string;
2026
2027        if (count >>= 1)
2028            string += string;
2029    }
2030    return result;
2031};
2032
2033var trimBeginRegexp = /^\s\s*/;
2034var trimEndRegexp = /\s\s*$/;
2035
2036exports.stringTrimLeft = function (string) {
2037    return string.replace(trimBeginRegexp, '');
2038};
2039
2040exports.stringTrimRight = function (string) {
2041    return string.replace(trimEndRegexp, '');
2042};
2043
2044exports.copyObject = function(obj) {
2045    var copy = {};
2046    for (var key in obj) {
2047        copy[key] = obj[key];
2048    }
2049    return copy;
2050};
2051
2052exports.copyArray = function(array){
2053    var copy = [];
2054    for (var i=0, l=array.length; i<l; i++) {
2055        if (array[i] && typeof array[i] == "object")
2056            copy[i] = this.copyObject(array[i]);
2057        else 
2058            copy[i] = array[i];
2059    }
2060    return copy;
2061};
2062
2063exports.deepCopy = function deepCopy(obj) {
2064    if (typeof obj !== "object" || !obj)
2065        return obj;
2066    var copy;
2067    if (Array.isArray(obj)) {
2068        copy = [];
2069        for (var key = 0; key < obj.length; key++) {
2070            copy[key] = deepCopy(obj[key]);
2071        }
2072        return copy;
2073    }
2074    if (Object.prototype.toString.call(obj) !== "[object Object]")
2075        return obj;
2076    
2077    copy = {};
2078    for (var key in obj)
2079        copy[key] = deepCopy(obj[key]);
2080    return copy;
2081};
2082
2083exports.arrayToMap = function(arr) {
2084    var map = {};
2085    for (var i=0; i<arr.length; i++) {
2086        map[arr[i]] = 1;
2087    }
2088    return map;
2089
2090};
2091
2092exports.createMap = function(props) {
2093    var map = Object.create(null);
2094    for (var i in props) {
2095        map[i] = props[i];
2096    }
2097    return map;
2098};
2099exports.arrayRemove = function(array, value) {
2100  for (var i = 0; i <= array.length; i++) {
2101    if (value === array[i]) {
2102      array.splice(i, 1);
2103    }
2104  }
2105};
2106
2107exports.escapeRegExp = function(str) {
2108    return str.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1');
2109};
2110
2111exports.escapeHTML = function(str) {
2112    return str.replace(/&/g, "&#38;").replace(/"/g, "&#34;").replace(/'/g, "&#39;").replace(/</g, "&#60;");
2113};
2114
2115exports.getMatchOffsets = function(string, regExp) {
2116    var matches = [];
2117
2118    string.replace(regExp, function(str) {
2119        matches.push({
2120            offset: arguments[arguments.length-2],
2121            length: str.length
2122        });
2123    });
2124
2125    return matches;
2126};
2127exports.deferredCall = function(fcn) {
2128    var timer = null;
2129    var callback = function() {
2130        timer = null;
2131        fcn();
2132    };
2133
2134    var deferred = function(timeout) {
2135        deferred.cancel();
2136        timer = setTimeout(callback, timeout || 0);
2137        return deferred;
2138    };
2139
2140    deferred.schedule = deferred;
2141
2142    deferred.call = function() {
2143        this.cancel();
2144        fcn();
2145        return deferred;
2146    };
2147
2148    deferred.cancel = function() {
2149        clearTimeout(timer);
2150        timer = null;
2151        return deferred;
2152    };
2153    
2154    deferred.isPending = function() {
2155        return timer;
2156    };
2157
2158    return deferred;
2159};
2160
2161
2162exports.delayedCall = function(fcn, defaultTimeout) {
2163    var timer = null;
2164    var callback = function() {
2165        timer = null;
2166        fcn();
2167    };
2168
2169    var _self = function(timeout) {
2170        if (timer == null)
2171            timer = setTimeout(callback, timeout || defaultTimeout);
2172    };
2173
2174    _self.delay = function(timeout) {
2175        timer && clearTimeout(timer);
2176        timer = setTimeout(callback, timeout || defaultTimeout);
2177    };
2178    _self.schedule = _self;
2179
2180    _self.call = function() {
2181        this.cancel();
2182        fcn();
2183    };
2184
2185    _self.cancel = function() {
2186        timer && clearTimeout(timer);
2187        timer = null;
2188    };
2189
2190    _self.isPending = function() {
2191        return timer;
2192    };
2193
2194    return _self;
2195};
2196});
2197
2198define("ace/keyboard/textinput_ios",["require","exports","module","ace/lib/event","ace/lib/useragent","ace/lib/dom","ace/lib/lang","ace/lib/keys"], function(require, exports, module) {
2199"use strict";
2200
2201var event = require("../lib/event");
2202var useragent = require("../lib/useragent");
2203var dom = require("../lib/dom");
2204var lang = require("../lib/lang");
2205var KEYS = require("../lib/keys");
2206var MODS = KEYS.KEY_MODS;
2207var BROKEN_SETDATA = useragent.isChrome < 18;
2208var USE_IE_MIME_TYPE =  useragent.isIE;
2209
2210var TextInput = function(parentNode, host) {
2211    var self = this;
2212    var text = dom.createElement("textarea");
2213    text.className = useragent.isIOS ? "ace_text-input ace_text-input-ios" : "ace_text-input";
2214
2215    if (useragent.isTouchPad)
2216        text.setAttribute("x-palm-disable-auto-cap", true);
2217
2218    text.setAttribute("wrap", "off");
2219    text.setAttribute("autocorrect", "off");
2220    text.setAttribute("autocapitalize", "off");
2221    text.setAttribute("spellcheck", false);
2222
2223    text.style.opacity = "0";
2224    parentNode.insertBefore(text, parentNode.firstChild);
2225
2226    var PLACEHOLDER = "\n aaaa a\n";
2227
2228    var copied = false;
2229    var cut = false;
2230    var pasted = false;
2231    var inComposition = false;
2232    var tempStyle = '';
2233    var isSelectionEmpty = true;
2234    try { var isFocused = document.activeElement === text; } catch(e) {}
2235    
2236    event.addListener(text, "blur", function(e) {
2237        host.onBlur(e);
2238        isFocused = false;
2239    });
2240    event.addListener(text, "focus", function(e) {
2241        isFocused = true;
2242        host.onFocus(e);
2243        resetSelection();
2244    });
2245    this.focus = function() {
2246        if (tempStyle) return text.focus();
2247        text.style.position = "fixed";
2248        text.focus();
2249    };
2250    this.blur = function() {
2251        text.blur();
2252    };
2253    this.isFocused = function() {
2254        return isFocused;
2255    };
2256    var syncSelection = lang.delayedCall(function() {
2257        isFocused && resetSelection(isSelectionEmpty);
2258    });
2259    var syncValue = lang.delayedCall(function() {
2260         if (!inComposition) {
2261            text.value = PLACEHOLDER;
2262            isFocused && resetSelection();
2263         }
2264    });
2265
2266    function resetSelection(isEmpty) {
2267        if (inComposition)
2268            return;
2269        inComposition = true;
2270        
2271        if (inputHandler) {
2272            selectionStart = 0;
2273            selectionEnd = isEmpty ? 0 : text.value.length - 1;
2274        } else {
2275            var selectionStart = 4;
2276            var selectionEnd = 5;
2277        }
2278        try {
2279            text.setSelectionRange(selectionStart, selectionEnd);
2280        } catch(e) {}
2281        
2282        inComposition = false;
2283    }
2284
2285    function resetValue() {
2286        if (inComposition)
2287            return;
2288        text.value = PLACEHOLDER;
2289        if (useragent.isWebKit)
2290            syncValue.schedule();
2291    }
2292
2293    useragent.isWebKit || host.addEventListener('changeSelection', function() {
2294        if (host.selection.isEmpty() != isSelectionEmpty) {
2295            isSelectionEmpty = !isSelectionEmpty;
2296            syncSelection.schedule();
2297        }
2298    });
2299
2300    resetValue();
2301    if (isFocused)
2302        host.onFocus();
2303
2304
2305    var isAllSelected = function(text) {
2306        return text.selectionStart === 0 && text.selectionEnd === text.value.length;
2307    };
2308
2309    var onSelect = function(e) {
2310        if (isAllSelected(text)) {
2311            host.selectAll();
2312            resetSelection();
2313        } else if (inputHandler) {
2314            resetSelection(host.selection.isEmpty());
2315        }
2316    };
2317
2318    var inputHandler = null;
2319    this.setInputHandler = function(cb) {inputHandler = cb;};
2320    this.getInputHandler = function() {return inputHandler;};
2321    var afterContextMenu = false;
2322    
2323    var sendText = function(data) {
2324        if (text.selectionStart === 4 && text.selectionEnd === 5) {
2325          return;
2326        }
2327        if (inputHandler) {
2328            data = inputHandler(data);
2329            inputHandler = null;
2330        }
2331        if (pasted) {
2332            resetSelection();
2333            if (data)
2334                host.onPaste(data);
2335            pasted = false;
2336        } else if (data == PLACEHOLDER.substr(0) && text.selectionStart === 4) {
2337            if (afterContextMenu)
2338                host.execCommand("del", {source: "ace"});
2339            else // some versions of android do not fire keydown when pressing backspace
2340                host.execCommand("backspace", {source: "ace"});
2341        } else if (!copied) {
2342            if (data.substring(0, 9) == PLACEHOLDER && data.length > PLACEHOLDER.length)
2343                data = data.substr(9);
2344            else if (data.substr(0, 4) == PLACEHOLDER.substr(0, 4))
2345                data = data.substr(4, data.length - PLACEHOLDER.length + 1);
2346            else if (data.charAt(data.length - 1) == PLACEHOLDER.charAt(0))
2347                data = data.slice(0, -1);
2348            if (data == PLACEHOLDER.charAt(0)) {
2349            } else if (data.charAt(data.length - 1) == PLACEHOLDER.charAt(0))
2350                data = data.slice(0, -1);
2351            
2352            if (data)
2353                host.onTextInput(data);
2354        }
2355        if (copied) {
2356          copied = false;
2357        }
2358        if (afterContextMenu)
2359            afterContextMenu = false;
2360    };
2361    var onInput = function(e) {
2362        if (inComposition)
2363            return;
2364        var data = text.value;
2365        sendText(data);
2366        resetValue();
2367    };
2368    
2369    var handleClipboardData = function(e, data, forceIEMime) {
2370        var clipboardData = e.clipboardData || window.clipboardData;
2371        if (!clipboardData || BROKEN_SETDATA)
2372            return;
2373        var mime = USE_IE_MIME_TYPE || forceIEMime ? "Text" : "text/plain";
2374        try {
2375            if (data) {
2376                return clipboardData.setData(mime, data) !== false;
2377            } else {
2378                return clipboardData.getData(mime);
2379            }
2380        } catch(e) {
2381            if (!forceIEMime)
2382                return handleClipboardData(e, data, true);
2383        }
2384    };
2385
2386    var doCopy = function(e, isCut) {
2387        var data = host.getCopyText();
2388        if (!data)
2389            return event.preventDefault(e);
2390
2391        if (handleClipboardData(e, data)) {
2392            if (useragent.isIOS) {
2393                cut = isCut;
2394                text.value = "\n aa" + data + "a a\n";
2395                text.setSelectionRange(4, 4 + data.length);
2396                copied = {
2397                    value: data
2398                };
2399            }
2400            isCut ? host.onCut() : host.onCopy();
2401            if (!useragent.isIOS) event.preventDefault(e);
2402        } else {
2403            copied = true;
2404            text.value = data;
2405            text.select();
2406            setTimeout(function(){
2407                copied = false;
2408                resetValue();
2409                resetSelection();
2410                isCut ? host.onCut() : host.onCopy();
2411            });
2412        }
2413    };
2414    
2415    var onCut = function(e) {
2416        doCopy(e, true);
2417    };
2418    
2419    var onCopy = function(e) {
2420        doCopy(e, false);
2421    };
2422    
2423    var onPaste = function(e) {
2424        var data = handleClipboardData(e);
2425        if (typeof data == "string") {
2426            if (data)
2427                host.onPaste(data, e);
2428            if (useragent.isIE)
2429                setTimeout(resetSelection);
2430            event.preventDefault(e);
2431        }
2432        else {
2433            text.value = "";
2434            pasted = true;
2435        }
2436    };
2437
2438    event.addCommandKeyListener(text, host.onCommandKey.bind(host));
2439
2440    event.addListener(text, "select", onSelect);
2441
2442    event.addListener(text, "input", onInput);
2443
2444    event.addListener(text, "cut", onCut);
2445    event.addListener(text, "copy", onCopy);
2446    event.addListener(text, "paste", onPaste);
2447    var onCompositionStart = function(e) {
2448        if (inComposition || !host.onCompositionStart || host.$readOnly) 
2449            return;
2450        inComposition = {};
2451        inComposition.canUndo = host.session.$undoManager;
2452        host.onCompositionStart();
2453        setTimeout(onCompositionUpdate, 0);
2454        host.on("mousedown", onCompositionEnd);
2455        if (inComposition.canUndo && !host.selection.isEmpty()) {
2456            host.insert("");
2457            host.session.markUndoGroup();
2458            host.selection.clearSelection();
2459        }
2460        host.session.markUndoGroup();
2461    };
2462
2463    var onCompositionUpdate = function() {
2464        if (!inComposition || !host.onCompositionUpdate || host.$readOnly)
2465            return;
2466        var val = text.value.replace(/\x01/g, "");
2467        if (inComposition.lastValue === val) return;
2468        
2469        host.onCompositionUpdate(val);
2470        if (inComposition.lastValue)
2471            host.undo();
2472        if (inComposition.canUndo)
2473            inComposition.lastValue = val;
2474        if (inComposition.lastValue) {
2475            var r = host.selection.getRange();
2476            host.insert(inComposition.lastValue);
2477            host.session.markUndoGroup();
2478            inComposition.range = host.selection.getRange();
2479            host.selection.setRange(r);
2480            host.selection.clearSelection();
2481        }
2482    };
2483
2484    var onCompositionEnd = function(e) {
2485        if (!host.onCompositionEnd || host.$readOnly) return;
2486        var c = inComposition;
2487        inComposition = false;
2488        var timer = setTimeout(function() {
2489            timer = null;
2490            var str = text.value.replace(/\x01/g, "");
2491            if (inComposition)
2492                return;
2493            else if (str == c.lastValue)
2494                resetValue();
2495            else if (!c.lastValue && str) {
2496                resetValue();
2497                sendText(str);
2498            }
2499        });
2500        inputHandler = function compositionInputHandler(str) {
2501            if (timer)
2502                clearTimeout(timer);
2503            str = str.replace(/\x01/g, "");
2504            if (str == c.lastValue)
2505                return "";
2506            if (c.lastValue && timer)
2507                host.undo();
2508            return str;
2509        };
2510        host.onCompositionEnd();
2511        host.removeListener("mousedown", onCompositionEnd);
2512        if (e.type == "compositionend" && c.range) {
2513            host.selection.setRange(c.range);
2514        }
2515        var needsOnInput =
2516            (!!useragent.isChrome && useragent.isChrome >= 53) ||
2517            (!!useragent.isWebKit && useragent.isWebKit >= 603);
2518
2519        if (needsOnInput) {
2520          onInput();
2521        }
2522    };
2523    
2524    
2525
2526    var syncComposition = lang.delayedCall(onCompositionUpdate, 50);
2527
2528    event.addListener(text, "compositionstart", onCompositionStart);
2529    event.addListener(text, "compositionupdate", function(){syncComposition.schedule();});
2530    event.addListener(text, "keyup", function(){syncComposition.schedule();});
2531    event.addListener(text, "keydown", function(){syncComposition.schedule();});
2532    event.addListener(text, "compositionend", onCompositionEnd);
2533
2534    this.getElement = function() {
2535        return text;
2536    };
2537
2538    this.setReadOnly = function(readOnly) {
2539       text.readOnly = readOnly;
2540    };
2541
2542    this.onContextMenu = function(e) {
2543        afterContextMenu = true;
2544        resetSelection(host.selection.isEmpty());
2545        host._emit("nativecontextmenu", {target: host, domEvent: e});
2546        this.moveToMouse(e, true);
2547    };
2548    
2549    this.moveToMouse = function(e, bringToFront) {
2550        if (!tempStyle)
2551            tempStyle = text.style.cssText;
2552        text.style.cssText = (bringToFront ? "z-index:100000;" : "")
2553            + "height:" + text.style.height + ";"
2554            + (useragent.isIE ? "opacity:0.1;" : "");
2555
2556        var rect = host.container.getBoundingClientRect();
2557        var style = dom.computedStyle(host.container);
2558        var top = rect.top + (parseInt(style.borderTopWidth) || 0);
2559        var left = rect.left + (parseInt(rect.borderLeftWidth) || 0);
2560        var maxTop = rect.bottom - top - text.clientHeight -2;
2561        var move = function(e) {
2562            text.style.left = e.clientX - left - 2 + "px";
2563            text.style.top = Math.min(e.clientY - top - 2, maxTop) + "px";
2564        }; 
2565        move(e);
2566
2567        if (e.type != "mousedown")
2568            return;
2569
2570        if (host.renderer.$keepTextAreaAtCursor)
2571            host.renderer.$keepTextAreaAtCursor = null;
2572
2573        clearTimeout(closeTimeout);
2574        if (useragent.isWin)
2575            event.capture(host.container, move, onContextMenuClose);
2576    };
2577
2578    this.onContextMenuClose = onContextMenuClose;
2579    var closeTimeout;
2580    function onContextMenuClose() {
2581        clearTimeout(closeTimeout);
2582        closeTimeout = setTimeout(function () {
2583            if (tempStyle) {
2584                text.style.cssText = tempStyle;
2585                tempStyle = '';
2586            }
2587            if (host.renderer.$keepTextAreaAtCursor == null) {
2588                host.renderer.$keepTextAreaAtCursor = true;
2589                host.renderer.$moveTextAreaToCursor();
2590            }
2591        }, 0);
2592    }
2593
2594    var onContextMenu = function(e) {
2595        host.textInput.onContextMenu(e);
2596        onContextMenuClose();
2597    };
2598    event.addListener(text, "mouseup", onContextMenu);
2599    event.addListener(text, "mousedown", function(e) {
2600        e.preventDefault();
2601        onContextMenuClose();
2602    });
2603    event.addListener(host.renderer.scroller, "contextmenu", onContextMenu);
2604    event.addListener(text, "contextmenu", onContextMenu);
2605    
2606    if (useragent.isIOS) {
2607        var typingResetTimeout = null;
2608        var typing = false;
2609
2610        parentNode.addEventListener("keydown", function (e) {
2611            if (typingResetTimeout) clearTimeout(typingResetTimeout);
2612            typing = true;
2613        });
2614
2615        parentNode.addEventListener("keyup", function (e) {
2616            typingResetTimeout = setTimeout(function () {
2617                typing = false;
2618            }, 100);
2619        });
2620        var detectArrowKeys = function(e) {
2621            if (document.activeElement !== text) return;
2622            if (typing) return;
2623          
2624            if (cut) {
2625                return setTimeout(function () {
2626                    cut = false;
2627                }, 100);
2628            }
2629            var selectionStart = text.selectionStart;
2630            var selectionEnd = text.selectionEnd;
2631            text.setSelectionRange(4, 5);
2632            if (selectionStart == selectionEnd) {
2633                switch (selectionStart) {
2634                    case 0: host.onCommandKey(null, 0, KEYS.up); break;
2635                    case 1: host.onCommandKey(null, 0, KEYS.home); break;
2636                    case 2: host.onCommandKey(null, MODS.option, KEYS.left); break;
2637                    case 4: host.onCommandKey(null, 0, KEYS.left); break;
2638                    case 5: host.onCommandKey(null, 0, KEYS.right); break;
2639                    case 7: host.onCommandKey(null, MODS.option, KEYS.right); break;
2640                    case 8: host.onCommandKey(null, 0, KEYS.end); break;
2641                    case 9: host.onCommandKey(null, 0, KEYS.down); break;
2642                }
2643            } else {
2644                switch (selectionEnd) {
2645                    case 6: host.onCommandKey(null, MODS.shift, KEYS.right); break;
2646                    case 7: host.onCommandKey(null, MODS.shift | MODS.option, KEYS.right); break;
2647                    case 8: host.onCommandKey(null, MODS.shift, KEYS.end); break;
2648                    case 9: host.onCommandKey(null, MODS.shift, KEYS.down); break;
2649                }
2650                switch (selectionStart) {
2651                    case 0: host.onCommandKey(null, MODS.shift, KEYS.up); break;
2652                    case 1: host.onCommandKey(null, MODS.shift, KEYS.home); break;
2653                    case 2: host.onCommandKey(null, MODS.shift | MODS.option, KEYS.left); break;
2654                    case 3: host.onCommandKey(null, MODS.shift, KEYS.left); break;
2655                }
2656            }
2657        };
2658        document.addEventListener("selectionchange", detectArrowKeys);
2659        host.on("destroy", function() {
2660            document.removeEventListener("selectionchange", detectArrowKeys);
2661        });
2662    }
2663};
2664
2665exports.TextInput = TextInput;
2666});
2667
2668define("ace/keyboard/textinput",["require","exports","module","ace/lib/event","ace/lib/useragent","ace/lib/dom","ace/lib/lang","ace/keyboard/textinput_ios"], function(require, exports, module) {
2669"use strict";
2670
2671var event = require("../lib/event");
2672var useragent = require("../lib/useragent");
2673var dom = require("../lib/dom");
2674var lang = require("../lib/lang");
2675var BROKEN_SETDATA = useragent.isChrome < 18;
2676var USE_IE_MIME_TYPE =  useragent.isIE;
2677var HAS_FOCUS_ARGS = useragent.isChrome > 63;
2678
2679var TextInputIOS = require("./textinput_ios").TextInput;
2680var TextInput = function(parentNode, host) {
2681    if (useragent.isIOS)
2682        return TextInputIOS.call(this, parentNode, host);
2683    
2684    var text = dom.createElement("textarea");
2685    text.className = "ace_text-input";
2686
2687    text.setAttribute("wrap", "off");
2688    text.setAttribute("autocorrect", "off");
2689    text.setAttribute("autocapitalize", "off");
2690    text.setAttribute("spellcheck", false);
2691
2692    text.style.opacity = "0";
2693    parentNode.insertBefore(text, parentNode.firstChild);
2694    var PLACEHOLDER = useragent.isIE ? "\x01\x01" : "\u2028\u2028";
2695    var PLACEHOLDER_RE = useragent.isIE ? /\x01/g : /\u2028/g;
2696
2697    var copied = false;
2698    var pasted = false;
2699    var inComposition = false;
2700    var tempStyle = '';
2701    var isSelectionEmpty = true;
2702    var copyWithEmptySelection = false;
2703
2704    var commandMode = false;
2705    try { var isFocused = document.activeElement === text; } catch(e) {}
2706    
2707    event.addListener(text, "blur", function(e) {
2708        host.onBlur(e);
2709        isFocused = false;
2710    });
2711    event.addListener(text, "focus", function(e) {
2712        isFocused = true;
2713        host.onFocus(e);
2714        resetSelection();
2715    });
2716    this.$focusScroll = false;
2717    this.focus = function() {
2718        if (tempStyle || HAS_FOCUS_ARGS || this.$focusScroll == "browser")
2719            return text.focus({ preventScroll: true });
2720        var top = text.style.top;
2721        text.style.position = "fixed";
2722        text.style.top = "0px";
2723        var isTransformed = text.getBoundingClientRect().top != 0;
2724        var ancestors = [];
2725        if (isTransformed) {
2726            var t = text.parentElement;
2727            while (t) {
2728                ancestors.push(t);
2729                t.setAttribute("ace_nocontext", true);
2730                t = t.parentElement;
2731            }
2732        }
2733        text.focus({ preventScroll: true });
2734        if (isTransformed) {
2735            ancestors.forEach(function(p) {
2736                p.removeAttribute("ace_nocontext");
2737            });
2738        }
2739        setTimeout(function() {
2740            text.style.position = "";
2741            if (text.style.top == "0px")
2742                text.style.top = top;
2743        }, 0);
2744    };
2745    this.blur = function() {
2746        text.blur();
2747    };
2748    this.isFocused = function() {
2749        return isFocused;
2750    };
2751    var syncSelection = lang.delayedCall(function() {
2752        isFocused && resetSelection(isSelectionEmpty);
2753    });
2754    var syncValue = lang.delayedCall(function() {
2755         if (!inComposition) {
2756            text.value = PLACEHOLDER;
2757            isFocused && resetSelection();
2758         }
2759    });
2760
2761    function resetSelection(isEmpty) {
2762        isEmpty = copyWithEmptySelection ? false : isEmpty;
2763        if (inComposition)
2764            return;
2765        inComposition = true;
2766        
2767        if (inputHandler) {
2768            var selectionStart = 0;
2769            var selectionEnd = isEmpty ? 0 : text.value.length - 1;
2770        } else {
2771            var selectionStart = isEmpty ? 2 : 1;
2772            var selectionEnd = 2;
2773        }
2774        try {
2775            text.setSelectionRange(selectionStart, selectionEnd);
2776        } catch(e){}
2777        
2778        inComposition = false;
2779    }
2780
2781    function resetValue() {
2782        if (inComposition)
2783            return;
2784        text.value = PLACEHOLDER;
2785        if (useragent.isWebKit)
2786            syncValue.schedule();
2787    }
2788
2789    useragent.isWebKit || host.addEventListener('changeSelection', function() {
2790        if (host.selection.isEmpty() != isSelectionEmpty) {
2791            isSelectionEmpty = !isSelectionEmpty;
2792            syncSelection.schedule();
2793        }
2794    });
2795
2796    resetValue();
2797    if (isFocused)
2798        host.onFocus();
2799
2800
2801    var isAllSelected = function(text) {
2802        return text.selectionStart === 0 && text.selectionEnd === text.value.length;
2803    };
2804
2805    var onSelect = function(e) {
2806        if (copied) {
2807            copied = false;
2808        } else if (isAllSelected(text)) {
2809            host.selectAll();
2810            resetSelection();
2811        } else if (inputHandler) {
2812            resetSelection(host.selection.isEmpty());
2813        }
2814    };
2815
2816    var inputHandler = null;
2817    this.setInputHandler = function(cb) {inputHandler = cb;};
2818    this.getInputHandler = function() {return inputHandler;};
2819    var afterContextMenu = false;
2820    
2821    var sendText = function(data) {
2822        if (inputHandler) {
2823            data = inputHandler(data);
2824            inputHandler = null;
2825        }
2826        if (pasted) {
2827            resetSelection();
2828            if (data)
2829                host.onPaste(data);
2830            pasted = false;
2831        } else if (data == PLACEHOLDER.charAt(0)) {
2832            if (afterContextMenu)
2833                host.execCommand("del", {source: "ace"});
2834            else // some versions of android do not fire keydown when pressing backspace
2835                host.execCommand("backspace", {source: "ace"});
2836        } else {
2837            if (data.substring(0, 2) == PLACEHOLDER)
2838                data = data.substr(2);
2839            else if (data.charAt(0) == PLACEHOLDER.charAt(0))
2840                data = data.substr(1);
2841            else if (data.charAt(data.length - 1) == PLACEHOLDER.charAt(0))
2842                data = data.slice(0, -1);
2843            if (data.charAt(data.length - 1) == PLACEHOLDER.charAt(0))
2844                data = data.slice(0, -1);
2845            
2846            if (data)
2847                host.onTextInput(data);
2848        }
2849        if (afterContextMenu)
2850            afterContextMenu = false;
2851    };
2852    var onInput = function(e) {
2853        if (inComposition)
2854            return;
2855        var data = text.value;
2856        sendText(data);
2857        resetValue();
2858    };
2859    
2860    var handleClipboardData = function(e, data, forceIEMime) {
2861        var clipboardData = e.clipboardData || window.clipboardData;
2862        if (!clipboardData || BROKEN_SETDATA)
2863            return;
2864        var mime = USE_IE_MIME_TYPE || forceIEMime ? "Text" : "text/plain";
2865        try {
2866            if (data) {
2867                return clipboardData.setData(mime, data) !== false;
2868            } else {
2869                return clipboardData.getData(mime);
2870            }
2871        } catch(e) {
2872            if (!forceIEMime)
2873                return handleClipboardData(e, data, true);
2874        }
2875    };
2876
2877    var doCopy = function(e, isCut) {
2878        var data = host.getCopyText();
2879        if (!data)
2880            return event.preventDefault(e);
2881
2882        if (handleClipboardData(e, data)) {
2883            isCut ? host.onCut() : host.onCopy();
2884            event.preventDefault(e);
2885        } else {
2886            copied = true;
2887            text.value = data;
2888            text.select();
2889            setTimeout(function(){
2890                copied = false;
2891                resetValue();
2892                resetSelection();
2893                isCut ? host.onCut() : host.onCopy();
2894            });
2895        }
2896    };
2897    
2898    var onCut = function(e) {
2899        doCopy(e, true);
2900    };
2901    
2902    var onCopy = function(e) {
2903        doCopy(e, false);
2904    };
2905    
2906    var onPaste = function(e) {
2907        var data = handleClipboardData(e);
2908        if (typeof data == "string") {
2909            if (data)
2910                host.onPaste(data, e);
2911            if (useragent.isIE)
2912                setTimeout(resetSelection);
2913            event.preventDefault(e);
2914        }
2915        else {
2916            text.value = "";
2917            pasted = true;
2918        }
2919    };
2920
2921    event.addCommandKeyListener(text, host.onCommandKey.bind(host));
2922
2923    event.addListener(text, "select", onSelect);
2924
2925    event.addListener(text, "input", onInput);
2926
2927    event.addListener(text, "cut", onCut);
2928    event.addListener(text, "copy", onCopy);
2929    event.addListener(text, "paste", onPaste);
2930    if (!('oncut' in text) || !('oncopy' in text) || !('onpaste' in text)) {
2931        event.addListener(parentNode, "keydown", function(e) {
2932            if ((useragent.isMac && !e.metaKey) || !e.ctrlKey)
2933                return;
2934
2935            switch (e.keyCode) {
2936                case 67:
2937                    onCopy(e);
2938                    break;
2939                case 86:
2940                    onPaste(e);
2941                    break;
2942                case 88:
2943                    onCut(e);
2944                    break;
2945            }
2946        });
2947    }
2948    var onCompositionStart = function(e) {
2949        if (inComposition || !host.onCompositionStart || host.$readOnly) 
2950            return;
2951        inComposition = {};
2952        inComposition.canUndo = host.session.$undoManager;
2953        host.onCompositionStart();
2954        setTimeout(onCompositionUpdate, 0);
2955        host.on("mousedown", onCompositionEnd);
2956        if (inComposition.canUndo && !host.selection.isEmpty()) {
2957            host.insert("");
2958            host.session.markUndoGroup();
2959            host.selection.clearSelection();
2960        }
2961        host.session.markUndoGroup();
2962    };
2963
2964    var onCompositionUpdate = function() {
2965        if (!inComposition || !host.onCompositionUpdate || host.$readOnly)
2966            return;
2967        var val = text.value.replace(PLACEHOLDER_RE, "");
2968        if (inComposition.lastValue === val) return;
2969        
2970        host.onCompositionUpdate(val);
2971        if (inComposition.lastValue)
2972            host.undo();
2973        if (inComposition.canUndo)
2974            inComposition.lastValue = val;
2975        if (inComposition.lastValue) {
2976            var r = host.selection.getRange();
2977            host.insert(inComposition.lastValue);
2978            host.session.markUndoGroup();
2979            inComposition.range = host.selection.getRange();
2980            host.selection.setRange(r);
2981            host.selection.clearSelection();
2982        }
2983    };
2984
2985    var onCompositionEnd = function(e) {
2986        if (!host.onCompositionEnd || host.$readOnly) return;
2987        var c = inComposition;
2988        inComposition = false;
2989        var timer = setTimeout(function() {
2990            timer = null;
2991            var str = text.value.replace(PLACEHOLDER_RE, "");
2992            if (inComposition)
2993                return;
2994            else if (str == c.lastValue)
2995                resetValue();
2996            else if (!c.lastValue && str) {
2997                resetValue();
2998                sendText(str);
2999            }
3000        });
3001        inputHandler = function compositionInputHandler(str) {
3002            if (timer)
3003                clearTimeout(timer);
3004            str = str.replace(PLACEHOLDER_RE, "");
3005            if (str == c.lastValue)
3006                return "";
3007            if (c.lastValue && timer)
3008                host.undo();
3009            return str;
3010        };
3011        host.onCompositionEnd();
3012        host.removeListener("mousedown", onCompositionEnd);
3013        if (e.type == "compositionend" && c.range) {
3014            host.selection.setRange(c.range);
3015        }
3016        var needsOnInput = useragent.isIE ||
3017            (useragent.isChrome && useragent.isChrome >= 53) ||
3018            (useragent.isWebKit && useragent.isWebKit >= 603);
3019
3020        if (needsOnInput) {
3021          onInput();
3022        }
3023    };
3024    
3025    
3026
3027    var syncComposition = lang.delayedCall(onCompositionUpdate, 50);
3028
3029    event.addListener(text, "compositionstart", onCompositionStart);
3030    event.addListener(text, "compositionupdate", function(){syncComposition.schedule();});
3031    event.addListener(text, "keyup", function(){syncComposition.schedule();});
3032    event.addListener(text, "keydown", function(){syncComposition.schedule();});
3033    event.addListener(text, "compositionend", onCompositionEnd);
3034
3035    this.getElement = function() {
3036        return text;
3037    };
3038
3039    this.setCommandMode = function(value) {
3040       commandMode = value;
3041       text.readOnly = false;
3042    };
3043    
3044    this.setReadOnly = function(readOnly) {
3045        if (!commandMode)
3046            text.readOnly = readOnly;
3047    };
3048
3049    this.setCopyWithEmptySelection = function(value) {
3050        copyWithEmptySelection = value;
3051    };
3052
3053    this.onContextMenu = function(e) {
3054        afterContextMenu = true;
3055        resetSelection(host.selection.isEmpty());
3056        host._emit("nativecontextmenu", {target: host, domEvent: e});
3057        this.moveToMouse(e, true);
3058    };
3059    
3060    this.moveToMouse = function(e, bringToFront) {
3061        if (!tempStyle)
3062            tempStyle = text.style.cssText;
3063        text.style.cssText = (bringToFront ? "z-index:100000;" : "")
3064            + "height:" + text.style.height + ";"
3065            + (useragent.isIE ? "opacity:0.1;" : "");
3066
3067        var rect = host.container.getBoundingClientRect();
3068        var style = dom.computedStyle(host.container);
3069        var top = rect.top + (parseInt(style.borderTopWidth) || 0);
3070        var left = rect.left + (parseInt(rect.borderLeftWidth) || 0);
3071        var maxTop = rect.bottom - top - text.clientHeight -2;
3072        var move = function(e) {
3073            text.style.left = e.clientX - left - 2 + "px";
3074            text.style.top = Math.min(e.clientY - top - 2, maxTop) + "px";
3075        }; 
3076        move(e);
3077
3078        if (e.type != "mousedown")
3079            return;
3080
3081        if (host.renderer.$keepTextAreaAtCursor)
3082            host.renderer.$keepTextAreaAtCursor = null;
3083
3084        clearTimeout(closeTimeout);
3085        if (useragent.isWin)
3086            event.capture(host.container, move, onContextMenuClose);
3087    };
3088
3089    this.onContextMenuClose = onContextMenuClose;
3090    var closeTimeout;
3091    function onContextMenuClose() {
3092        clearTimeout(closeTimeout);
3093        closeTimeout = setTimeout(function () {
3094            if (tempStyle) {
3095                text.style.cssText = tempStyle;
3096                tempStyle = '';
3097            }
3098            if (host.renderer.$keepTextAreaAtCursor == null) {
3099                host.renderer.$keepTextAreaAtCursor = true;
3100                host.renderer.$moveTextAreaToCursor();
3101            }
3102        }, 0);
3103    }
3104
3105    var onContextMenu = function(e) {
3106        host.textInput.onContextMenu(e);
3107        onContextMenuClose();
3108    };
3109    event.addListener(text, "mouseup", onContextMenu);
3110    event.addListener(text, "mousedown", function(e) {
3111        e.preventDefault();
3112        onContextMenuClose();
3113    });
3114    event.addListener(host.renderer.scroller, "contextmenu", onContextMenu);
3115    event.addListener(text, "contextmenu", onContextMenu);
3116};
3117
3118exports.TextInput = TextInput;
3119});
3120
3121define("ace/mouse/default_handlers",["require","exports","module","ace/lib/dom","ace/lib/event","ace/lib/useragent"], function(require, exports, module) {
3122"use strict";
3123
3124var dom = require("../lib/dom");
3125var event = require("../lib/event");
3126var useragent = require("../lib/useragent");
3127
3128var DRAG_OFFSET = 0; // pixels
3129var SCROLL_COOLDOWN_T = 250; // milliseconds
3130
3131function DefaultHandlers(mouseHandler) {
3132    mouseHandler.$clickSelection = null;
3133
3134    var editor = mouseHandler.editor;
3135    editor.setDefaultHandler("mousedown", this.onMouseDown.bind(mouseHandler));
3136    editor.setDefaultHandler("dblclick", this.onDoubleClick.bind(mouseHandler));
3137    editor.setDefaultHandler("tripleclick", this.onTripleClick.bind(mouseHandler));
3138    editor.setDefaultHandler("quadclick", this.onQuadClick.bind(mouseHandler));
3139    editor.setDefaultHandler("mousewheel", this.onMouseWheel.bind(mouseHandler));
3140    editor.setDefaultHandler("touchmove", this.onTouchMove.bind(mouseHandler));
3141
3142    var exports = ["select", "startSelect", "selectEnd", "selectAllEnd", "selectByWordsEnd",
3143        "selectByLinesEnd", "dragWait", "dragWaitEnd", "focusWait"];
3144
vendor: 9,277 bytes, lines 3145-3408
3145    exports.forEach(function(x) {
3146        mouseHandler[x] = this[x];
3147    }, this);
3148
3149    mouseHandler.selectByLines = this.extendSelectionBy.bind(mouseHandler, "getLineRange");
3150    mouseHandler.selectByWords = this.extendSelectionBy.bind(mouseHandler, "getWordRange");
3151}
3152
3153(function() {
3154
3155    this.onMouseDown = function(ev) {
3156        var inSelection = ev.inSelection();
3157        var pos = ev.getDocumentPosition();
3158        this.mousedownEvent = ev;
3159        var editor = this.editor;
3160
3161        var button = ev.getButton();
3162        if (button !== 0) {
3163            var selectionRange = editor.getSelectionRange();
3164            var selectionEmpty = selectionRange.isEmpty();
3165            if (selectionEmpty || button == 1)
3166                editor.selection.moveToPosition(pos);
3167            if (button == 2) {
3168                editor.textInput.onContextMenu(ev.domEvent);
3169                if (!useragent.isMozilla)
3170                    ev.preventDefault();
3171            }
3172            return;
3173        }
3174
3175        this.mousedownEvent.time = Date.now();
3176        if (inSelection && !editor.isFocused()) {
3177            editor.focus();
3178            if (this.$focusTimeout && !this.$clickSelection && !editor.inMultiSelectMode) {
3179                this.setState("focusWait");
3180                this.captureMouse(ev);
3181                return;
3182            }
3183        }
3184
3185        this.captureMouse(ev);
3186        this.startSelect(pos, ev.domEvent._clicks > 1);
3187        return ev.preventDefault();
3188    };
3189
3190    this.startSelect = function(pos, waitForClickSelection) {
3191        pos = pos || this.editor.renderer.screenToTextCoordinates(this.x, this.y);
3192        var editor = this.editor;
3193        if (this.mousedownEvent.getShiftKey())
3194            editor.selection.selectToPosition(pos);
3195        else if (!waitForClickSelection)
3196            editor.selection.moveToPosition(pos);
3197        if (!waitForClickSelection)
3198            this.select();
3199        if (editor.renderer.scroller.setCapture) {
3200            editor.renderer.scroller.setCapture();
3201        }
3202        editor.setStyle("ace_selecting");
3203        this.setState("select");
3204    };
3205
3206    this.select = function() {
3207        var anchor, editor = this.editor;
3208        var cursor = editor.renderer.screenToTextCoordinates(this.x, this.y);
3209        if (this.$clickSelection) {
3210            var cmp = this.$clickSelection.comparePoint(cursor);
3211
3212            if (cmp == -1) {
3213                anchor = this.$clickSelection.end;
3214            } else if (cmp == 1) {
3215                anchor = this.$clickSelection.start;
3216            } else {
3217                var orientedRange = calcRangeOrientation(this.$clickSelection, cursor);
3218                cursor = orientedRange.cursor;
3219                anchor = orientedRange.anchor;
3220            }
3221            editor.selection.setSelectionAnchor(anchor.row, anchor.column);
3222        }
3223        editor.selection.selectToPosition(cursor);
3224        editor.renderer.scrollCursorIntoView();
3225    };
3226
3227    this.extendSelectionBy = function(unitName) {
3228        var anchor, editor = this.editor;
3229        var cursor = editor.renderer.screenToTextCoordinates(this.x, this.y);
3230        var range = editor.selection[unitName](cursor.row, cursor.column);
3231        if (this.$clickSelection) {
3232            var cmpStart = this.$clickSelection.comparePoint(range.start);
3233            var cmpEnd = this.$clickSelection.comparePoint(range.end);
3234
3235            if (cmpStart == -1 && cmpEnd <= 0) {
3236                anchor = this.$clickSelection.end;
3237                if (range.end.row != cursor.row || range.end.column != cursor.column)
3238                    cursor = range.start;
3239            } else if (cmpEnd == 1 && cmpStart >= 0) {
3240                anchor = this.$clickSelection.start;
3241                if (range.start.row != cursor.row || range.start.column != cursor.column)
3242                    cursor = range.end;
3243            } else if (cmpStart == -1 && cmpEnd == 1) {
3244                cursor = range.end;
3245                anchor = range.start;
3246            } else {
3247                var orientedRange = calcRangeOrientation(this.$clickSelection, cursor);
3248                cursor = orientedRange.cursor;
3249                anchor = orientedRange.anchor;
3250            }
3251            editor.selection.setSelectionAnchor(anchor.row, anchor.column);
3252        }
3253        editor.selection.selectToPosition(cursor);
3254        editor.renderer.scrollCursorIntoView();
3255    };
3256
3257    this.selectEnd =
3258    this.selectAllEnd =
3259    this.selectByWordsEnd =
3260    this.selectByLinesEnd = function() {
3261        this.$clickSelection = null;
3262        this.editor.unsetStyle("ace_selecting");
3263        if (this.editor.renderer.scroller.releaseCapture) {
3264            this.editor.renderer.scroller.releaseCapture();
3265        }
3266    };
3267
3268    this.focusWait = function() {
3269        var distance = calcDistance(this.mousedownEvent.x, this.mousedownEvent.y, this.x, this.y);
3270        var time = Date.now();
3271
3272        if (distance > DRAG_OFFSET || time - this.mousedownEvent.time > this.$focusTimeout)
3273            this.startSelect(this.mousedownEvent.getDocumentPosition());
3274    };
3275
3276    this.onDoubleClick = function(ev) {
3277        var pos = ev.getDocumentPosition();
3278        var editor = this.editor;
3279        var session = editor.session;
3280
3281        var range = session.getBracketRange(pos);
3282        if (range) {
3283            if (range.isEmpty()) {
3284                range.start.column--;
3285                range.end.column++;
3286            }
3287            this.setState("select");
3288        } else {
3289            range = editor.selection.getWordRange(pos.row, pos.column);
3290            this.setState("selectByWords");
3291        }
3292        this.$clickSelection = range;
3293        this.select();
3294    };
3295
3296    this.onTripleClick = function(ev) {
3297        var pos = ev.getDocumentPosition();
3298        var editor = this.editor;
3299
3300        this.setState("selectByLines");
3301        var range = editor.getSelectionRange();
3302        if (range.isMultiLine() && range.contains(pos.row, pos.column)) {
3303            this.$clickSelection = editor.selection.getLineRange(range.start.row);
3304            this.$clickSelection.end = editor.selection.getLineRange(range.end.row).end;
3305        } else {
3306            this.$clickSelection = editor.selection.getLineRange(pos.row);
3307        }
3308        this.select();
3309    };
3310
3311    this.onQuadClick = function(ev) {
3312        var editor = this.editor;
3313
3314        editor.selectAll();
3315        this.$clickSelection = editor.getSelectionRange();
3316        this.setState("selectAll");
3317    };
3318
3319    this.onMouseWheel = function(ev) {
3320        if (ev.getAccelKey())
3321            return;
3322        if (ev.getShiftKey() && ev.wheelY && !ev.wheelX) {
3323            ev.wheelX = ev.wheelY;
3324            ev.wheelY = 0;
3325        }
3326        
3327        var editor = this.editor;
3328        
3329        if (!this.$lastScroll)
3330            this.$lastScroll = { t: 0, vx: 0, vy: 0, allowed: 0 };
3331        
3332        var prevScroll = this.$lastScroll;
3333        var t = ev.domEvent.timeStamp;
3334        var dt = t - prevScroll.t;
3335        var vx = dt ? ev.wheelX / dt : prevScroll.vx;
3336        var vy = dt ? ev.wheelY / dt : prevScroll.vy;
3337        if (dt < SCROLL_COOLDOWN_T) {
3338            vx = (vx + prevScroll.vx) / 2;
3339            vy = (vy + prevScroll.vy) / 2;
3340        }
3341        
3342        var direction = Math.abs(vx / vy);
3343        
3344        var canScroll = false;
3345        if (direction >= 1 && editor.renderer.isScrollableBy(ev.wheelX * ev.speed, 0))
3346            canScroll = true;
3347        if (direction <= 1 && editor.renderer.isScrollableBy(0, ev.wheelY * ev.speed))
3348            canScroll = true;
3349            
3350        if (canScroll) {
3351            prevScroll.allowed = t;
3352        } else if (t - prevScroll.allowed < SCROLL_COOLDOWN_T) {
3353            var isSlower = Math.abs(vx) <= 1.1 * Math.abs(prevScroll.vx)
3354                && Math.abs(vy) <= 1.1 * Math.abs(prevScroll.vy);
3355            if (isSlower) {
3356                canScroll = true;
3357                prevScroll.allowed = t;
3358            }
3359            else {
3360                prevScroll.allowed = 0;
3361            }
3362        }
3363        
3364        prevScroll.t = t;
3365        prevScroll.vx = vx;
3366        prevScroll.vy = vy;
3367
3368        if (canScroll) {
3369            editor.renderer.scrollBy(ev.wheelX * ev.speed, ev.wheelY * ev.speed);
3370            return ev.stop();
3371        }
3372    };
3373    
3374    this.onTouchMove = function(ev) {
3375        this.editor._emit("mousewheel", ev);
3376    };
3377
3378}).call(DefaultHandlers.prototype);
3379
3380exports.DefaultHandlers = DefaultHandlers;
3381
3382function calcDistance(ax, ay, bx, by) {
3383    return Math.sqrt(Math.pow(bx - ax, 2) + Math.pow(by - ay, 2));
3384}
3385
3386function calcRangeOrientation(range, cursor) {
3387    if (range.start.row == range.end.row)
3388        var cmp = 2 * cursor.column - range.start.column - range.end.column;
3389    else if (range.start.row == range.end.row - 1 && !range.start.column && !range.end.column)
3390        var cmp = cursor.column - 4;
3391    else
3392        var cmp = 2 * cursor.row - range.start.row - range.end.row;
3393
3394    if (cmp < 0)
3395        return {cursor: range.start, anchor: range.end};
3396    else
3397        return {cursor: range.end, anchor: range.start};
3398}
3399
3400});
3401
3402define("ace/tooltip",["require","exports","module","ace/lib/oop","ace/lib/dom"], function(require, exports, module) {
3403"use strict";
3404
3405var oop = require("./lib/oop");
3406var dom = require("./lib/dom");
3407function Tooltip (parentNode) {
3408    this.isOpen = false;
3409    this.$element = null;
3410    this.$parentNode = parentNode;
3411}
3412
3413(function() {
3414    this.$init = function() {
3415        this.$element = dom.createElement("div");
3416        this.$element.className = "ace_tooltip";
3417        this.$element.style.display = "none";
3418        this.$parentNode.appendChild(this.$element);
3419        return this.$element;
3420    };
3421    this.getElement = function() {
3422        return this.$element || this.$init();
3423    };
3424    this.setText = function(text) {
3425        dom.setInnerText(this.getElement(), text);
3426    };
3427    this.setHtml = function(html) {
3428        this.getElement().innerHTML = html;
3429    };
3430    this.setPosition = function(x, y) {
3431        this.getElement().style.left = x + "px";
3432        this.getElement().style.top = y + "px";
3433    };
3434    this.setClassName = function(className) {
3435        dom.addCssClass(this.getElement(), className);
3436    };
3437    this.show = function(text, x, y) {
3438        if (text != null)
3439            this.setText(text);
3440        if (x != null && y != null)
3441            this.setPosition(x, y);
3442        if (!this.isOpen) {
3443            this.getElement().style.display = "block";
3444            this.isOpen = true;
3445        }
3446    };
3447
3448    this.hide = function() {
3449        if (this.isOpen) {
3450            this.getElement().style.display = "none";
3451            this.isOpen = false;
3452        }
3453    };
3454    this.getHeight = function() {
3455        return this.getElement().offsetHeight;
3456    };
3457    this.getWidth = function() {
3458        return this.getElement().offsetWidth;
3459    };
3460    
3461    this.destroy = function() {
3462        this.isOpen = false;
3463        if (this.$element && this.$element.parentNode) {
3464            this.$element.parentNode.removeChild(this.$element);
3465        }
3466    };
3467
3468}).call(Tooltip.prototype);
3469
3470exports.Tooltip = Tooltip;
3471});
3472
3473define("ace/mouse/default_gutter_handler",["require","exports","module","ace/lib/dom","ace/lib/oop","ace/lib/event","ace/tooltip"], function(require, exports, module) {
3474"use strict";
3475var dom = require("../lib/dom");
3476var oop = require("../lib/oop");
3477var event = require("../lib/event");
3478var Tooltip = require("../tooltip").Tooltip;
3479
3480function GutterHandler(mouseHandler) {
3481    var editor = mouseHandler.editor;
3482    var gutter = editor.renderer.$gutterLayer;
3483    var tooltip = new GutterTooltip(editor.container);
3484
3485    mouseHandler.editor.setDefaultHandler("guttermousedown", function(e) {
3486        if (!editor.isFocused() || e.getButton() != 0)
3487            return;
3488        var gutterRegion = gutter.getRegion(e);
3489
3490        if (gutterRegion == "foldWidgets")
3491            return;
3492
3493        var row = e.getDocumentPosition().row;
3494        var selection = editor.session.selection;
3495
3496        if (e.getShiftKey())
3497            selection.selectTo(row, 0);
3498        else {
3499            if (e.domEvent.detail == 2) {
3500                editor.selectAll();
3501                return e.preventDefault();
3502            }
3503            mouseHandler.$clickSelection = editor.selection.getLineRange(row);
3504        }
3505        mouseHandler.setState("selectByLines");
3506        mouseHandler.captureMouse(e);
3507        return e.preventDefault();
3508    });
3509
3510
3511    var tooltipTimeout, mouseEvent, tooltipAnnotation;
3512
3513    function showTooltip() {
3514        var row = mouseEvent.getDocumentPosition().row;
3515        var annotation = gutter.$annotations[row];
3516        if (!annotation)
3517            return hideTooltip();
3518
3519        var maxRow = editor.session.getLength();
3520        if (row == maxRow) {
3521            var screenRow = editor.renderer.pixelToScreenCoordinates(0, mouseEvent.y).row;
3522            var pos = mouseEvent.$pos;
3523            if (screenRow > editor.session.documentToScreenRow(pos.row, pos.column))
3524                return hideTooltip();
3525        }
3526
3527        if (tooltipAnnotation == annotation)
3528            return;
3529        tooltipAnnotation = annotation.text.join("<br/>");
3530
3531        tooltip.setHtml(tooltipAnnotation);
3532        tooltip.show();
3533        editor._signal("showGutterTooltip", tooltip);
3534        editor.on("mousewheel", hideTooltip);
3535
3536        if (mouseHandler.$tooltipFollowsMouse) {
3537            moveTooltip(mouseEvent);
3538        } else {
3539            var gutterElement = mouseEvent.domEvent.target;
3540            var rect = gutterElement.getBoundingClientRect();
3541            var style = tooltip.getElement().style;
3542            style.left = rect.right + "px";
3543            style.top = rect.bottom + "px";
3544        }
3545    }
3546
3547    function hideTooltip() {
3548        if (tooltipTimeout)
3549            tooltipTimeout = clearTimeout(tooltipTimeout);
3550        if (tooltipAnnotation) {
3551            tooltip.hide();
3552            tooltipAnnotation = null;
3553            editor._signal("hideGutterTooltip", tooltip);
3554            editor.removeEventListener("mousewheel", hideTooltip);
3555        }
3556    }
3557
3558    function moveTooltip(e) {
3559        tooltip.setPosition(e.x, e.y);
3560    }
3561
3562    mouseHandler.editor.setDefaultHandler("guttermousemove", function(e) {
3563        var target = e.domEvent.target || e.domEvent.srcElement;
3564        if (dom.hasCssClass(target, "ace_fold-widget"))
3565            return hideTooltip();
3566
3567        if (tooltipAnnotation && mouseHandler.$tooltipFollowsMouse)
3568            moveTooltip(e);
3569
3570        mouseEvent = e;
3571        if (tooltipTimeout)
3572            return;
3573        tooltipTimeout = setTimeout(function() {
3574            tooltipTimeout = null;
3575            if (mouseEvent && !mouseHandler.isMousePressed)
3576                showTooltip();
3577            else
3578                hideTooltip();
3579        }, 50);
3580    });
3581
3582    event.addListener(editor.renderer.$gutter, "mouseout", function(e) {
3583        mouseEvent = null;
3584        if (!tooltipAnnotation || tooltipTimeout)
3585            return;
3586
3587        tooltipTimeout = setTimeout(function() {
3588            tooltipTimeout = null;
3589            hideTooltip();
3590        }, 50);
3591    });
3592    
3593    editor.on("changeSession", hideTooltip);
3594}
3595
3596function GutterTooltip(parentNode) {
3597    Tooltip.call(this, parentNode);
3598}
3599
3600oop.inherits(GutterTooltip, Tooltip);
3601
3602(function(){
3603    this.setPosition = function(x, y) {
3604        var windowWidth = window.innerWidth || document.documentElement.clientWidth;
3605        var windowHeight = window.innerHeight || document.documentElement.clientHeight;
3606        var width = this.getWidth();
3607        var height = this.getHeight();
3608        x += 15;
3609        y += 15;
3610        if (x + width > windowWidth) {
3611            x -= (x + width) - windowWidth;
3612        }
3613        if (y + height > windowHeight) {
3614            y -= 20 + height;
3615        }
3616        Tooltip.prototype.setPosition.call(this, x, y);
3617    };
3618
3619}).call(GutterTooltip.prototype);
3620
3621
3622
3623exports.GutterHandler = GutterHandler;
3624
3625});
3626
3627define("ace/mouse/mouse_event",["require","exports","module","ace/lib/event","ace/lib/useragent"], function(require, exports, module) {
3628"use strict";
3629
3630var event = require("../lib/event");
3631var useragent = require("../lib/useragent");
3632var MouseEvent = exports.MouseEvent = function(domEvent, editor) {
3633    this.domEvent = domEvent;
3634    this.editor = editor;
3635    
3636    this.x = this.clientX = domEvent.clientX;
3637    this.y = this.clientY = domEvent.clientY;
3638
3639    this.$pos = null;
3640    this.$inSelection = null;
3641    
3642    this.propagationStopped = false;
3643    this.defaultPrevented = false;
3644};
3645
3646(function() {  
3647    
3648    this.stopPropagation = function() {
3649        event.stopPropagation(this.domEvent);
3650        this.propagationStopped = true;
3651    };
3652    
3653    this.preventDefault = function() {
3654        event.preventDefault(this.domEvent);
3655        this.defaultPrevented = true;
3656    };
3657    
3658    this.stop = function() {
3659        this.stopPropagation();
3660        this.preventDefault();
3661    };
3662    this.getDocumentPosition = function() {
3663        if (this.$pos)
3664            return this.$pos;
3665        
3666        this.$pos = this.editor.renderer.screenToTextCoordinates(this.clientX, this.clientY);
3667        return this.$pos;
3668    };
3669    this.inSelection = function() {
3670        if (this.$inSelection !== null)
3671            return this.$inSelection;
3672            
3673        var editor = this.editor;
3674        
3675
3676        var selectionRange = editor.getSelectionRange();
3677        if (selectionRange.isEmpty())
3678            this.$inSelection = false;
3679        else {
3680            var pos = this.getDocumentPosition();
3681            this.$inSelection = selectionRange.contains(pos.row, pos.column);
3682        }
3683
3684        return this.$inSelection;
3685    };
3686    this.getButton = function() {
3687        return event.getButton(this.domEvent);
3688    };
3689    this.getShiftKey = function() {
3690        return this.domEvent.shiftKey;
3691    };
3692    
3693    this.getAccelKey = useragent.isMac
3694        ? function() { return this.domEvent.metaKey; }
3695        : function() { return this.domEvent.ctrlKey; };
3696    
3697}).call(MouseEvent.prototype);
3698
3699});
3700
3701define("ace/mouse/dragdrop_handler",["require","exports","module","ace/lib/dom","ace/lib/event","ace/lib/useragent"], function(require, exports, module) {
3702"use strict";
3703
3704var dom = require("../lib/dom");
3705var event = require("../lib/event");
3706var useragent = require("../lib/useragent");
3707
3708var AUTOSCROLL_DELAY = 200;
3709var SCROLL_CURSOR_DELAY = 200;
3710var SCROLL_CURSOR_HYSTERESIS = 5;
3711
3712function DragdropHandler(mouseHandler) {
3713
3714    var editor = mouseHandler.editor;
3715
3716    var blankImage = dom.createElement("img");
3717    blankImage.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";
3718    if (useragent.isOpera)
3719        blankImage.style.cssText = "width:1px;height:1px;position:fixed;top:0;left:0;z-index:2147483647;opacity:0;";
3720
3721    var exports = ["dragWait", "dragWaitEnd", "startDrag", "dragReadyEnd", "onMouseDrag"];
3722
3723     exports.forEach(function(x) {
3724         mouseHandler[x] = this[x];
3725    }, this);
3726    editor.addEventListener("mousedown", this.onMouseDown.bind(mouseHandler));
3727
3728
3729    var mouseTarget = editor.container;
3730    var dragSelectionMarker, x, y;
3731    var timerId, range;
3732    var dragCursor, counter = 0;
3733    var dragOperation;
3734    var isInternal;
3735    var autoScrollStartTime;
3736    var cursorMovedTime;
3737    var cursorPointOnCaretMoved;
3738
3739    this.onDragStart = function(e) {
3740        if (this.cancelDrag || !mouseTarget.draggable) {
3741            var self = this;
3742            setTimeout(function(){
3743                self.startSelect();
3744                self.captureMouse(e);
3745            }, 0);
3746            return e.preventDefault();
3747        }
3748        range = editor.getSelectionRange();
3749
3750        var dataTransfer = e.dataTransfer;
3751        dataTransfer.effectAllowed = editor.getReadOnly() ? "copy" : "copyMove";
3752        if (useragent.isOpera) {
3753            editor.container.appendChild(blankImage);
3754            blankImage.scrollTop = 0;
3755        }
3756        dataTransfer.setDragImage && dataTransfer.setDragImage(blankImage, 0, 0);
3757        if (useragent.isOpera) {
3758            editor.container.removeChild(blankImage);
3759        }
3760        dataTransfer.clearData();
3761        dataTransfer.setData("Text", editor.session.getTextRange());
3762
3763        isInternal = true;
3764        this.setState("drag");
3765    };
3766
3767    this.onDragEnd = function(e) {
3768        mouseTarget.draggable = false;
3769        isInternal = false;
3770        this.setState(null);
3771        if (!editor.getReadOnly()) {
3772            var dropEffect = e.dataTransfer.dropEffect;
3773            if (!dragOperation && dropEffect == "move")
3774                editor.session.remove(editor.getSelectionRange());
3775            editor.renderer.$cursorLayer.setBlinking(true);
3776        }
3777        this.editor.unsetStyle("ace_dragging");
3778        this.editor.renderer.setCursorStyle("");
3779    };
3780
3781    this.onDragEnter = function(e) {
3782        if (editor.getReadOnly() || !canAccept(e.dataTransfer))
3783            return;
3784        x = e.clientX;
3785        y = e.clientY;
3786        if (!dragSelectionMarker)
3787            addDragMarker();
3788        counter++;
3789        e.dataTransfer.dropEffect = dragOperation = getDropEffect(e);
3790        return event.preventDefault(e);
3791    };
3792
3793    this.onDragOver = function(e) {
3794        if (editor.getReadOnly() || !canAccept(e.dataTransfer))
3795            return;
3796        x = e.clientX;
3797        y = e.clientY;
3798        if (!dragSelectionMarker) {
3799            addDragMarker();
3800            counter++;
3801        }
3802        if (onMouseMoveTimer !== null)
3803            onMouseMoveTimer = null;
3804
3805        e.dataTransfer.dropEffect = dragOperation = getDropEffect(e);
3806        return event.preventDefault(e);
3807    };
3808
3809    this.onDragLeave = function(e) {
3810        counter--;
3811        if (counter <= 0 && dragSelectionMarker) {
3812            clearDragMarker();
3813            dragOperation = null;
3814            return event.preventDefault(e);
3815        }
3816    };
3817
3818    this.onDrop = function(e) {
3819        if (!dragCursor)
3820            return;
3821        var dataTransfer = e.dataTransfer;
3822        if (isInternal) {
3823            switch (dragOperation) {
3824                case "move":
vendor: 15,026 bytes, lines 3825-4265
3825                    if (range.contains(dragCursor.row, dragCursor.column)) {
3826                        range = {
3827                            start: dragCursor,
3828                            end: dragCursor
3829                        };
3830                    } else {
3831                        range = editor.moveText(range, dragCursor);
3832                    }
3833                    break;
3834                case "copy":
3835                    range = editor.moveText(range, dragCursor, true);
3836                    break;
3837            }
3838        } else {
3839            var dropData = dataTransfer.getData('Text');
3840            range = {
3841                start: dragCursor,
3842                end: editor.session.insert(dragCursor, dropData)
3843            };
3844            editor.focus();
3845            dragOperation = null;
3846        }
3847        clearDragMarker();
3848        return event.preventDefault(e);
3849    };
3850
3851    event.addListener(mouseTarget, "dragstart", this.onDragStart.bind(mouseHandler));
3852    event.addListener(mouseTarget, "dragend", this.onDragEnd.bind(mouseHandler));
3853    event.addListener(mouseTarget, "dragenter", this.onDragEnter.bind(mouseHandler));
3854    event.addListener(mouseTarget, "dragover", this.onDragOver.bind(mouseHandler));
3855    event.addListener(mouseTarget, "dragleave", this.onDragLeave.bind(mouseHandler));
3856    event.addListener(mouseTarget, "drop", this.onDrop.bind(mouseHandler));
3857
3858    function scrollCursorIntoView(cursor, prevCursor) {
3859        var now = Date.now();
3860        var vMovement = !prevCursor || cursor.row != prevCursor.row;
3861        var hMovement = !prevCursor || cursor.column != prevCursor.column;
3862        if (!cursorMovedTime || vMovement || hMovement) {
3863            editor.moveCursorToPosition(cursor);
3864            cursorMovedTime = now;
3865            cursorPointOnCaretMoved = {x: x, y: y};
3866        } else {
3867            var distance = calcDistance(cursorPointOnCaretMoved.x, cursorPointOnCaretMoved.y, x, y);
3868            if (distance > SCROLL_CURSOR_HYSTERESIS) {
3869                cursorMovedTime = null;
3870            } else if (now - cursorMovedTime >= SCROLL_CURSOR_DELAY) {
3871                editor.renderer.scrollCursorIntoView();
3872                cursorMovedTime = null;
3873            }
3874        }
3875    }
3876
3877    function autoScroll(cursor, prevCursor) {
3878        var now = Date.now();
3879        var lineHeight = editor.renderer.layerConfig.lineHeight;
3880        var characterWidth = editor.renderer.layerConfig.characterWidth;
3881        var editorRect = editor.renderer.scroller.getBoundingClientRect();
3882        var offsets = {
3883           x: {
3884               left: x - editorRect.left,
3885               right: editorRect.right - x
3886           },
3887           y: {
3888               top: y - editorRect.top,
3889               bottom: editorRect.bottom - y
3890           }
3891        };
3892        var nearestXOffset = Math.min(offsets.x.left, offsets.x.right);
3893        var nearestYOffset = Math.min(offsets.y.top, offsets.y.bottom);
3894        var scrollCursor = {row: cursor.row, column: cursor.column};
3895        if (nearestXOffset / characterWidth <= 2) {
3896            scrollCursor.column += (offsets.x.left < offsets.x.right ? -3 : +2);
3897        }
3898        if (nearestYOffset / lineHeight <= 1) {
3899            scrollCursor.row += (offsets.y.top < offsets.y.bottom ? -1 : +1);
3900        }
3901        var vScroll = cursor.row != scrollCursor.row;
3902        var hScroll = cursor.column != scrollCursor.column;
3903        var vMovement = !prevCursor || cursor.row != prevCursor.row;
3904        if (vScroll || (hScroll && !vMovement)) {
3905            if (!autoScrollStartTime)
3906                autoScrollStartTime = now;
3907            else if (now - autoScrollStartTime >= AUTOSCROLL_DELAY)
3908                editor.renderer.scrollCursorIntoView(scrollCursor);
3909        } else {
3910            autoScrollStartTime = null;
3911        }
3912    }
3913
3914    function onDragInterval() {
3915        var prevCursor = dragCursor;
3916        dragCursor = editor.renderer.screenToTextCoordinates(x, y);
3917        scrollCursorIntoView(dragCursor, prevCursor);
3918        autoScroll(dragCursor, prevCursor);
3919    }
3920
3921    function addDragMarker() {
3922        range = editor.selection.toOrientedRange();
3923        dragSelectionMarker = editor.session.addMarker(range, "ace_selection", editor.getSelectionStyle());
3924        editor.clearSelection();
3925        if (editor.isFocused())
3926            editor.renderer.$cursorLayer.setBlinking(false);
3927        clearInterval(timerId);
3928        onDragInterval();
3929        timerId = setInterval(onDragInterval, 20);
3930        counter = 0;
3931        event.addListener(document, "mousemove", onMouseMove);
3932    }
3933
3934    function clearDragMarker() {
3935        clearInterval(timerId);
3936        editor.session.removeMarker(dragSelectionMarker);
3937        dragSelectionMarker = null;
3938        editor.selection.fromOrientedRange(range);
3939        if (editor.isFocused() && !isInternal)
3940            editor.renderer.$cursorLayer.setBlinking(!editor.getReadOnly());
3941        range = null;
3942        dragCursor = null;
3943        counter = 0;
3944        autoScrollStartTime = null;
3945        cursorMovedTime = null;
3946        event.removeListener(document, "mousemove", onMouseMove);
3947    }
3948    var onMouseMoveTimer = null;
3949    function onMouseMove() {
3950        if (onMouseMoveTimer == null) {
3951            onMouseMoveTimer = setTimeout(function() {
3952                if (onMouseMoveTimer != null && dragSelectionMarker)
3953                    clearDragMarker();
3954            }, 20);
3955        }
3956    }
3957
3958    function canAccept(dataTransfer) {
3959        var types = dataTransfer.types;
3960        return !types || Array.prototype.some.call(types, function(type) {
3961            return type == 'text/plain' || type == 'Text';
3962        });
3963    }
3964
3965    function getDropEffect(e) {
3966        var copyAllowed = ['copy', 'copymove', 'all', 'uninitialized'];
3967        var moveAllowed = ['move', 'copymove', 'linkmove', 'all', 'uninitialized'];
3968
3969        var copyModifierState = useragent.isMac ? e.altKey : e.ctrlKey;
3970        var effectAllowed = "uninitialized";
3971        try {
3972            effectAllowed = e.dataTransfer.effectAllowed.toLowerCase();
3973        } catch (e) {}
3974        var dropEffect = "none";
3975
3976        if (copyModifierState && copyAllowed.indexOf(effectAllowed) >= 0)
3977            dropEffect = "copy";
3978        else if (moveAllowed.indexOf(effectAllowed) >= 0)
3979            dropEffect = "move";
3980        else if (copyAllowed.indexOf(effectAllowed) >= 0)
3981            dropEffect = "copy";
3982
3983        return dropEffect;
3984    }
3985}
3986
3987(function() {
3988
3989    this.dragWait = function() {
3990        var interval = Date.now() - this.mousedownEvent.time;
3991        if (interval > this.editor.getDragDelay())
3992            this.startDrag();
3993    };
3994
3995    this.dragWaitEnd = function() {
3996        var target = this.editor.container;
3997        target.draggable = false;
3998        this.startSelect(this.mousedownEvent.getDocumentPosition());
3999        this.selectEnd();
4000    };
4001
4002    this.dragReadyEnd = function(e) {
4003        this.editor.renderer.$cursorLayer.setBlinking(!this.editor.getReadOnly());
4004        this.editor.unsetStyle("ace_dragging");
4005        this.editor.renderer.setCursorStyle("");
4006        this.dragWaitEnd();
4007    };
4008
4009    this.startDrag = function(){
4010        this.cancelDrag = false;
4011        var editor = this.editor;
4012        var target = editor.container;
4013        target.draggable = true;
4014        editor.renderer.$cursorLayer.setBlinking(false);
4015        editor.setStyle("ace_dragging");
4016        var cursorStyle = useragent.isWin ? "default" : "move";
4017        editor.renderer.setCursorStyle(cursorStyle);
4018        this.setState("dragReady");
4019    };
4020
4021    this.onMouseDrag = function(e) {
4022        var target = this.editor.container;
4023        if (useragent.isIE && this.state == "dragReady") {
4024            var distance = calcDistance(this.mousedownEvent.x, this.mousedownEvent.y, this.x, this.y);
4025            if (distance > 3)
4026                target.dragDrop();
4027        }
4028        if (this.state === "dragWait") {
4029            var distance = calcDistance(this.mousedownEvent.x, this.mousedownEvent.y, this.x, this.y);
4030            if (distance > 0) {
4031                target.draggable = false;
4032                this.startSelect(this.mousedownEvent.getDocumentPosition());
4033            }
4034        }
4035    };
4036
4037    this.onMouseDown = function(e) {
4038        if (!this.$dragEnabled)
4039            return;
4040        this.mousedownEvent = e;
4041        var editor = this.editor;
4042
4043        var inSelection = e.inSelection();
4044        var button = e.getButton();
4045        var clickCount = e.domEvent.detail || 1;
4046        if (clickCount === 1 && button === 0 && inSelection) {
4047            if (e.editor.inMultiSelectMode && (e.getAccelKey() || e.getShiftKey()))
4048                return;
4049            this.mousedownEvent.time = Date.now();
4050            var eventTarget = e.domEvent.target || e.domEvent.srcElement;
4051            if ("unselectable" in eventTarget)
4052                eventTarget.unselectable = "on";
4053            if (editor.getDragDelay()) {
4054                if (useragent.isWebKit) {
4055                    this.cancelDrag = true;
4056                    var mouseTarget = editor.container;
4057                    mouseTarget.draggable = true;
4058                }
4059                this.setState("dragWait");
4060            } else {
4061                this.startDrag();
4062            }
4063            this.captureMouse(e, this.onMouseDrag.bind(this));
4064            e.defaultPrevented = true;
4065        }
4066    };
4067
4068}).call(DragdropHandler.prototype);
4069
4070
4071function calcDistance(ax, ay, bx, by) {
4072    return Math.sqrt(Math.pow(bx - ax, 2) + Math.pow(by - ay, 2));
4073}
4074
4075exports.DragdropHandler = DragdropHandler;
4076
4077});
4078
4079define("ace/lib/net",["require","exports","module","ace/lib/dom"], function(require, exports, module) {
4080"use strict";
4081var dom = require("./dom");
4082
4083exports.get = function (url, callback) {
4084    var xhr = new XMLHttpRequest();
4085    xhr.open('GET', url, true);
4086    xhr.onreadystatechange = function () {
4087        if (xhr.readyState === 4) {
4088            callback(xhr.responseText);
4089        }
4090    };
4091    xhr.send(null);
4092};
4093
4094exports.loadScript = function(path, callback) {
4095    var head = dom.getDocumentHead();
4096    var s = document.createElement('script');
4097
4098    s.src = path;
4099    head.appendChild(s);
4100
4101    s.onload = s.onreadystatechange = function(_, isAbort) {
4102        if (isAbort || !s.readyState || s.readyState == "loaded" || s.readyState == "complete") {
4103            s = s.onload = s.onreadystatechange = null;
4104            if (!isAbort)
4105                callback();
4106        }
4107    };
4108};
4109exports.qualifyURL = function(url) {
4110    var a = document.createElement('a');
4111    a.href = url;
4112    return a.href;
4113};
4114
4115});
4116
4117define("ace/lib/event_emitter",["require","exports","module"], function(require, exports, module) {
4118"use strict";
4119
4120var EventEmitter = {};
4121var stopPropagation = function() { this.propagationStopped = true; };
4122var preventDefault = function() { this.defaultPrevented = true; };
4123
4124EventEmitter._emit =
4125EventEmitter._dispatchEvent = function(eventName, e) {
4126    this._eventRegistry || (this._eventRegistry = {});
4127    this._defaultHandlers || (this._defaultHandlers = {});
4128
4129    var listeners = this._eventRegistry[eventName] || [];
4130    var defaultHandler = this._defaultHandlers[eventName];
4131    if (!listeners.length && !defaultHandler)
4132        return;
4133
4134    if (typeof e != "object" || !e)
4135        e = {};
4136
4137    if (!e.type)
4138        e.type = eventName;
4139    if (!e.stopPropagation)
4140        e.stopPropagation = stopPropagation;
4141    if (!e.preventDefault)
4142        e.preventDefault = preventDefault;
4143
4144    listeners = listeners.slice();
4145    for (var i=0; i<listeners.length; i++) {
4146        listeners[i](e, this);
4147        if (e.propagationStopped)
4148            break;
4149    }
4150    
4151    if (defaultHandler && !e.defaultPrevented)
4152        return defaultHandler(e, this);
4153};
4154
4155
4156EventEmitter._signal = function(eventName, e) {
4157    var listeners = (this._eventRegistry || {})[eventName];
4158    if (!listeners)
4159        return;
4160    listeners = listeners.slice();
4161    for (var i=0; i<listeners.length; i++)
4162        listeners[i](e, this);
4163};
4164
4165EventEmitter.once = function(eventName, callback) {
4166    var _self = this;
4167    callback && this.addEventListener(eventName, function newCallback() {
4168        _self.removeEventListener(eventName, newCallback);
4169        callback.apply(null, arguments);
4170    });
4171};
4172
4173
4174EventEmitter.setDefaultHandler = function(eventName, callback) {
4175    var handlers = this._defaultHandlers;
4176    if (!handlers)
4177        handlers = this._defaultHandlers = {_disabled_: {}};
4178    
4179    if (handlers[eventName]) {
4180        var old = handlers[eventName];
4181        var disabled = handlers._disabled_[eventName];
4182        if (!disabled)
4183            handlers._disabled_[eventName] = disabled = [];
4184        disabled.push(old);
4185        var i = disabled.indexOf(callback);
4186        if (i != -1) 
4187            disabled.splice(i, 1);
4188    }
4189    handlers[eventName] = callback;
4190};
4191EventEmitter.removeDefaultHandler = function(eventName, callback) {
4192    var handlers = this._defaultHandlers;
4193    if (!handlers)
4194        return;
4195    var disabled = handlers._disabled_[eventName];
4196    
4197    if (handlers[eventName] == callback) {
4198        var old = handlers[eventName];
4199        if (disabled)
4200            this.setDefaultHandler(eventName, disabled.pop());
4201    } else if (disabled) {
4202        var i = disabled.indexOf(callback);
4203        if (i != -1)
4204            disabled.splice(i, 1);
4205    }
4206};
4207
4208EventEmitter.on =
4209EventEmitter.addEventListener = function(eventName, callback, capturing) {
4210    this._eventRegistry = this._eventRegistry || {};
4211
4212    var listeners = this._eventRegistry[eventName];
4213    if (!listeners)
4214        listeners = this._eventRegistry[eventName] = [];
4215
4216    if (listeners.indexOf(callback) == -1)
4217        listeners[capturing ? "unshift" : "push"](callback);
4218    return callback;
4219};
4220
4221EventEmitter.off =
4222EventEmitter.removeListener =
4223EventEmitter.removeEventListener = function(eventName, callback) {
4224    this._eventRegistry = this._eventRegistry || {};
4225
4226    var listeners = this._eventRegistry[eventName];
4227    if (!listeners)
4228        return;
4229
4230    var index = listeners.indexOf(callback);
4231    if (index !== -1)
4232        listeners.splice(index, 1);
4233};
4234
4235EventEmitter.removeAllListeners = function(eventName) {
4236    if (this._eventRegistry) this._eventRegistry[eventName] = [];
4237};
4238
4239exports.EventEmitter = EventEmitter;
4240
4241});
4242
4243define("ace/lib/app_config",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"], function(require, exports, module) {
4244"no use strict";
4245
4246var oop = require("./oop");
4247var EventEmitter = require("./event_emitter").EventEmitter;
4248
4249var optionsProvider = {
4250    setOptions: function(optList) {
4251        Object.keys(optList).forEach(function(key) {
4252            this.setOption(key, optList[key]);
4253        }, this);
4254    },
4255    getOptions: function(optionNames) {
4256        var result = {};
4257        if (!optionNames) {
4258            var options = this.$options;
4259            optionNames = Object.keys(options).filter(function(key) {
4260                return !options[key].hidden;
4261            });
4262        } else if (!Array.isArray(optionNames)) {
4263            result = optionNames;
4264            optionNames = Object.keys(result);
4265        }
4266        optionNames.forEach(function(key) {
4267            result[key] = this.getOption(key);
4268        }, this);
4269        return result;
4270    },
4271    setOption: function(name, value) {
4272        if (this["$" + name] === value)
4273            return;
4274        var opt = this.$options[name];
4275        if (!opt) {
4276            return warn('misspelled option "' + name + '"');
4277        }
4278        if (opt.forwardTo)
4279            return this[opt.forwardTo] && this[opt.forwardTo].setOption(name, value);
4280
4281        if (!opt.handlesSet)
4282            this["$" + name] = value;
4283        if (opt && opt.set)
4284            opt.set.call(this, value);
4285    },
4286    getOption: function(name) {
4287        var opt = this.$options[name];
4288        if (!opt) {
4289            return warn('misspelled option "' + name + '"');
4290        }
4291        if (opt.forwardTo)
4292            return this[opt.forwardTo] && this[opt.forwardTo].getOption(name);
4293        return opt && opt.get ? opt.get.call(this) : this["$" + name];
4294    }
4295};
4296
4297function warn(message) {
4298    if (typeof console != "undefined" && console.warn)
4299        console.warn.apply(console, arguments);
4300}
4301
4302function reportError(msg, data) {
4303    var e = new Error(msg);
4304    e.data = data;
4305    if (typeof console == "object" && console.error)
4306        console.error(e);
4307    setTimeout(function() { throw e; });
4308}
4309
4310var AppConfig = function() {
4311    this.$defaultOptions = {};
4312};
4313
4314(function() {
4315    oop.implement(this, EventEmitter);
4316    this.defineOptions = function(obj, path, options) {
4317        if (!obj.$options)
4318            this.$defaultOptions[path] = obj.$options = {};
4319
4320        Object.keys(options).forEach(function(key) {
4321            var opt = options[key];
4322            if (typeof opt == "string")
4323                opt = {forwardTo: opt};
4324
4325            opt.name || (opt.name = key);
4326            obj.$options[opt.name] = opt;
4327            if ("initialValue" in opt)
4328                obj["$" + opt.name] = opt.initialValue;
4329        });
4330        oop.implement(obj, optionsProvider);
4331
4332        return this;
4333    };
4334
4335    this.resetOptions = function(obj) {
4336        Object.keys(obj.$options).forEach(function(key) {
4337            var opt = obj.$options[key];
4338            if ("value" in opt)
4339                obj.setOption(key, opt.value);
4340        });
4341    };
4342
4343    this.setDefaultValue = function(path, name, value) {
4344        var opts = this.$defaultOptions[path] || (this.$defaultOptions[path] = {});
4345        if (opts[name]) {
4346            if (opts.forwardTo)
4347                this.setDefaultValue(opts.forwardTo, name, value);
4348            else
4349                opts[name].value = value;
4350        }
4351    };
4352
4353    this.setDefaultValues = function(path, optionHash) {
4354        Object.keys(optionHash).forEach(function(key) {
4355            this.setDefaultValue(path, key, optionHash[key]);
4356        }, this);
4357    };
4358    
4359    this.warn = warn;
4360    this.reportError = reportError;
4361    
4362}).call(AppConfig.prototype);
4363
4364exports.AppConfig = AppConfig;
4365
4366});
4367
4368define("ace/config",["require","exports","module","ace/lib/lang","ace/lib/oop","ace/lib/net","ace/lib/app_config"], function(require, exports, module) {
4369"no use strict";
4370
4371var lang = require("./lib/lang");
4372var oop = require("./lib/oop");
4373var net = require("./lib/net");
4374var AppConfig = require("./lib/app_config").AppConfig;
4375
4376module.exports = exports = new AppConfig();
4377
4378var global = (function() {
4379    return this || typeof window != "undefined" && window;
4380})();
4381
4382var options = {
4383    packaged: false,
4384    workerPath: null,
4385    modePath: null,
4386    themePath: null,
4387    basePath: "",
4388    suffix: ".js",
4389    $moduleUrls: {}
4390};
4391
4392exports.get = function(key) {
4393    if (!options.hasOwnProperty(key))
4394        throw new Error("Unknown config key: " + key);
4395
4396    return options[key];
4397};
4398
4399exports.set = function(key, value) {
4400    if (!options.hasOwnProperty(key))
4401        throw new Error("Unknown config key: " + key);
4402
4403    options[key] = value;
4404};
4405
4406exports.all = function() {
4407    return lang.copyObject(options);
4408};
4409exports.moduleUrl = function(name, component) {
4410    if (options.$moduleUrls[name])
4411        return options.$moduleUrls[name];
4412
4413    var parts = name.split("/");
4414    component = component || parts[parts.length - 2] || "";
4415    var sep = component == "snippets" ? "/" : "-";
4416    var base = parts[parts.length - 1];
4417    if (component == "worker" && sep == "-") {
4418        var re = new RegExp("^" + component + "[\\-_]|[\\-_]" + component + "$", "g");
4419        base = base.replace(re, "");
4420    }
4421
4422    if ((!base || base == component) && parts.length > 1)
4423        base = parts[parts.length - 2];
4424    var path = options[component + "Path"];
4425    if (path == null) {
4426        path = options.basePath;
4427    } else if (sep == "/") {
4428        component = sep = "";
4429    }
4430    if (path && path.slice(-1) != "/")
4431        path += "/";
4432    return path + component + sep + base + this.get("suffix");
4433};
4434
4435exports.setModuleUrl = function(name, subst) {
4436    return options.$moduleUrls[name] = subst;
4437};
4438
4439exports.$loading = {};
4440exports.loadModule = function(moduleName, onLoad) {
4441    var module, moduleType;
4442    if (Array.isArray(moduleName)) {
4443        moduleType = moduleName[0];
4444        moduleName = moduleName[1];
4445    }
4446
4447    try {
4448        module = require(moduleName);
4449    } catch (e) {}
4450    if (module && !exports.$loading[moduleName])
4451        return onLoad && onLoad(module);
4452
4453    if (!exports.$loading[moduleName])
4454        exports.$loading[moduleName] = [];
4455
4456    exports.$loading[moduleName].push(onLoad);
4457
4458    if (exports.$loading[moduleName].length > 1)
4459        return;
4460
4461    var afterLoad = function() {
4462        require([moduleName], function(module) {
4463            exports._emit("load.module", {name: moduleName, module: module});
4464            var listeners = exports.$loading[moduleName];
4465            exports.$loading[moduleName] = null;
4466            listeners.forEach(function(onLoad) {
4467                onLoad && onLoad(module);
4468            });
4469        });
4470    };
4471
4472    if (!exports.get("packaged"))
4473        return afterLoad();
4474    net.loadScript(exports.moduleUrl(moduleName, moduleType), afterLoad);
4475};
4476init(true);function init(packaged) {
4477
4478    if (!global || !global.document)
4479        return;
4480    
4481    options.packaged = packaged || require.packaged || module.packaged || (global.define && define.packaged);
4482
4483    var scriptOptions = {};
4484    var scriptUrl = "";
4485    var currentScript = (document.currentScript || document._currentScript ); // native or polyfill
4486    var currentDocument = currentScript && currentScript.ownerDocument || document;
4487    
4488    var scripts = currentDocument.getElementsByTagName("script");
4489    for (var i=0; i<scripts.length; i++) {
4490        var script = scripts[i];
4491
4492        var src = script.src || script.getAttribute("src");
4493        if (!src)
4494            continue;
4495
4496        var attributes = script.attributes;
4497        for (var j=0, l=attributes.length; j < l; j++) {
4498            var attr = attributes[j];
4499            if (attr.name.indexOf("data-ace-") === 0) {
4500                scriptOptions[deHyphenate(attr.name.replace(/^data-ace-/, ""))] = attr.value;
4501            }
4502        }
4503
4504        var m = src.match(/^(.*)\/ace(\-\w+)?\.js(\?|$)/);
4505        if (m)
4506            scriptUrl = m[1];
4507    }
4508
4509    if (scriptUrl) {
4510        scriptOptions.base = scriptOptions.base || scriptUrl;
4511        scriptOptions.packaged = true;
4512    }
4513
4514    scriptOptions.basePath = scriptOptions.base;
4515    scriptOptions.workerPath = scriptOptions.workerPath || scriptOptions.base;
4516    scriptOptions.modePath = scriptOptions.modePath || scriptOptions.base;
4517    scriptOptions.themePath = scriptOptions.themePath || scriptOptions.base;
4518    delete scriptOptions.base;
4519
4520    for (var key in scriptOptions)
4521        if (typeof scriptOptions[key] !== "undefined")
4522            exports.set(key, scriptOptions[key]);
4523}
4524
4525exports.init = init;
4526
4527function deHyphenate(str) {
4528    return str.replace(/-(.)/g, function(m, m1) { return m1.toUpperCase(); });
4529}
4530
4531});
4532
4533define("ace/mouse/mouse_handler",["require","exports","module","ace/lib/event","ace/lib/useragent","ace/mouse/default_handlers","ace/mouse/default_gutter_handler","ace/mouse/mouse_event","ace/mouse/dragdrop_handler","ace/config"], function(require, exports, module) {
4534"use strict";
4535
4536var event = require("../lib/event");
4537var useragent = require("../lib/useragent");
4538var DefaultHandlers = require("./default_handlers").DefaultHandlers;
4539var DefaultGutterHandler = require("./default_gutter_handler").GutterHandler;
4540var MouseEvent = require("./mouse_event").MouseEvent;
4541var DragdropHandler = require("./dragdrop_handler").DragdropHandler;
4542var config = require("../config");
4543
4544var MouseHandler = function(editor) {
4545    var _self = this;
4546    this.editor = editor;
4547
4548    new DefaultHandlers(this);
4549    new DefaultGutterHandler(this);
4550    new DragdropHandler(this);
4551
4552    var focusEditor = function(e) {
4553        var windowBlurred = !document.hasFocus || !document.hasFocus()
4554            || !editor.isFocused() && document.activeElement == (editor.textInput && editor.textInput.getElement());
4555        if (windowBlurred)
4556            window.focus();
4557        editor.focus();
4558    };
4559
4560    var mouseTarget = editor.renderer.getMouseEventTarget();
4561    event.addListener(mouseTarget, "click", this.onMouseEvent.bind(this, "click"));
4562    event.addListener(mouseTarget, "mousemove", this.onMouseMove.bind(this, "mousemove"));
4563    event.addMultiMouseDownListener([
4564        mouseTarget,
4565        editor.renderer.scrollBarV && editor.renderer.scrollBarV.inner,
4566        editor.renderer.scrollBarH && editor.renderer.scrollBarH.inner,
4567        editor.textInput && editor.textInput.getElement()
4568    ].filter(Boolean), [400, 300, 250], this, "onMouseEvent");
4569    event.addMouseWheelListener(editor.container, this.onMouseWheel.bind(this, "mousewheel"));
4570    event.addTouchMoveListener(editor.container, this.onTouchMove.bind(this, "touchmove"));
4571
4572    var gutterEl = editor.renderer.$gutter;
4573    event.addListener(gutterEl, "mousedown", this.onMouseEvent.bind(this, "guttermousedown"));
4574    event.addListener(gutterEl, "click", this.onMouseEvent.bind(this, "gutterclick"));
4575    event.addListener(gutterEl, "dblclick", this.onMouseEvent.bind(this, "gutterdblclick"));
4576    event.addListener(gutterEl, "mousemove", this.onMouseEvent.bind(this, "guttermousemove"));
4577
4578    event.addListener(mouseTarget, "mousedown", focusEditor);
4579    event.addListener(gutterEl, "mousedown", focusEditor);
4580    if (useragent.isIE && editor.renderer.scrollBarV) {
4581        event.addListener(editor.renderer.scrollBarV.element, "mousedown", focusEditor);
4582        event.addListener(editor.renderer.scrollBarH.element, "mousedown", focusEditor);
4583    }
4584
4585    editor.on("mousemove", function(e){
4586        if (_self.state || _self.$dragDelay || !_self.$dragEnabled)
4587            return;
4588
4589        var character = editor.renderer.screenToTextCoordinates(e.x, e.y);
4590        var range = editor.session.selection.getRange();
4591        var renderer = editor.renderer;
4592
4593        if (!range.isEmpty() && range.insideStart(character.row, character.column)) {
4594            renderer.setCursorStyle("default");
4595        } else {
4596            renderer.setCursorStyle("");
4597        }
4598    });
4599};
4600
4601(function() {
4602    this.onMouseEvent = function(name, e) {
4603        this.editor._emit(name, new MouseEvent(e, this.editor));
4604    };
4605
4606    this.onMouseMove = function(name, e) {
4607        var listeners = this.editor._eventRegistry && this.editor._eventRegistry.mousemove;
4608        if (!listeners || !listeners.length)
4609            return;
4610
4611        this.editor._emit(name, new MouseEvent(e, this.editor));
4612    };
4613
4614    this.onMouseWheel = function(name, e) {
4615        var mouseEvent = new MouseEvent(e, this.editor);
4616        mouseEvent.speed = this.$scrollSpeed * 2;
4617        mouseEvent.wheelX = e.wheelX;
4618        mouseEvent.wheelY = e.wheelY;
4619
4620        this.editor._emit(name, mouseEvent);
4621    };
4622    
4623    this.onTouchMove = function (name, e) {
4624        var mouseEvent = new MouseEvent(e, this.editor);
4625        mouseEvent.speed = 1;//this.$scrollSpeed * 2;
4626        mouseEvent.wheelX = e.wheelX;
4627        mouseEvent.wheelY = e.wheelY;
4628        this.editor._emit(name, mouseEvent);
4629    };
4630
4631    this.setState = function(state) {
4632        this.state = state;
4633    };
4634
4635    this.captureMouse = function(ev, mouseMoveHandler) {
4636        this.x = ev.x;
4637        this.y = ev.y;
4638
4639        this.isMousePressed = true;
4640        var editor = this.editor;
4641        var renderer = this.editor.renderer;
4642        if (renderer.$keepTextAreaAtCursor)
4643            renderer.$keepTextAreaAtCursor = null;
4644
4645        var self = this;
4646        var onMouseMove = function(e) {
4647            if (!e) return;
4648            if (useragent.isWebKit && !e.which && self.releaseMouse)
4649                return self.releaseMouse();
4650
4651            self.x = e.clientX;
4652            self.y = e.clientY;
4653            mouseMoveHandler && mouseMoveHandler(e);
4654            self.mouseEvent = new MouseEvent(e, self.editor);
4655            self.$mouseMoved = true;
4656        };
4657
4658        var onCaptureEnd = function(e) {
4659            editor.off("beforeEndOperation", onOperationEnd);
4660            clearInterval(timerId);
4661            onCaptureInterval();
4662            self[self.state + "End"] && self[self.state + "End"](e);
4663            self.state = "";
4664            if (renderer.$keepTextAreaAtCursor == null) {
4665                renderer.$keepTextAreaAtCursor = true;
4666                renderer.$moveTextAreaToCursor();
4667            }
4668            self.isMousePressed = false;
4669            self.$onCaptureMouseMove = self.releaseMouse = null;
4670            e && self.onMouseEvent("mouseup", e);
4671        };
4672
4673        var onCaptureInterval = function() {
4674            self[self.state] && self[self.state]();
4675            self.$mouseMoved = false;
4676        };
4677
4678        if (useragent.isOldIE && ev.domEvent.type == "dblclick") {
4679            return setTimeout(function() {onCaptureEnd(ev);});
4680        }
4681
4682        var onOperationEnd = function(e) {
4683            if (editor.curOp.command.name && editor.curOp.selectionChanged) {
vendor: 14,105 bytes, lines 4684-5204
4684                self[self.state + "End"] && self[self.state + "End"]();
4685                self.state = "";
4686                self.releaseMouse();
4687            }
4688        };
4689
4690        editor.on("beforeEndOperation", onOperationEnd);
4691
4692        self.$onCaptureMouseMove = onMouseMove;
4693        self.releaseMouse = event.capture(this.editor.container, onMouseMove, onCaptureEnd);
4694        var timerId = setInterval(onCaptureInterval, 20);
4695    };
4696    this.releaseMouse = null;
4697    this.cancelContextMenu = function() {
4698        var stop = function(e) {
4699            if (e && e.domEvent && e.domEvent.type != "contextmenu")
4700                return;
4701            this.editor.off("nativecontextmenu", stop);
4702            if (e && e.domEvent)
4703                event.stopEvent(e.domEvent);
4704        }.bind(this);
4705        setTimeout(stop, 10);
4706        this.editor.on("nativecontextmenu", stop);
4707    };
4708}).call(MouseHandler.prototype);
4709
4710config.defineOptions(MouseHandler.prototype, "mouseHandler", {
4711    scrollSpeed: {initialValue: 2},
4712    dragDelay: {initialValue: (useragent.isMac ? 150 : 0)},
4713    dragEnabled: {initialValue: true},
4714    focusTimeout: {initialValue: 0},
4715    tooltipFollowsMouse: {initialValue: true}
4716});
4717
4718
4719exports.MouseHandler = MouseHandler;
4720});
4721
4722define("ace/mouse/fold_handler",["require","exports","module","ace/lib/dom"], function(require, exports, module) {
4723"use strict";
4724var dom = require("../lib/dom");
4725
4726function FoldHandler(editor) {
4727
4728    editor.on("click", function(e) {
4729        var position = e.getDocumentPosition();
4730        var session = editor.session;
4731        var fold = session.getFoldAt(position.row, position.column, 1);
4732        if (fold) {
4733            if (e.getAccelKey())
4734                session.removeFold(fold);
4735            else
4736                session.expandFold(fold);
4737
4738            e.stop();
4739        }
4740        
4741        var target = e.domEvent && e.domEvent.target;
4742        if (target && dom.hasCssClass(target, "ace_inline_button")) {
4743            if (dom.hasCssClass(target, "ace_toggle_wrap")) {
4744                session.setOption("wrap", true);
4745                editor.renderer.scrollCursorIntoView();
4746            }
4747        }
4748    });
4749
4750    editor.on("gutterclick", function(e) {
4751        var gutterRegion = editor.renderer.$gutterLayer.getRegion(e);
4752
4753        if (gutterRegion == "foldWidgets") {
4754            var row = e.getDocumentPosition().row;
4755            var session = editor.session;
4756            if (session.foldWidgets && session.foldWidgets[row])
4757                editor.session.onFoldWidgetClick(row, e);
4758            if (!editor.isFocused())
4759                editor.focus();
4760            e.stop();
4761        }
4762    });
4763
4764    editor.on("gutterdblclick", function(e) {
4765        var gutterRegion = editor.renderer.$gutterLayer.getRegion(e);
4766
4767        if (gutterRegion == "foldWidgets") {
4768            var row = e.getDocumentPosition().row;
4769            var session = editor.session;
4770            var data = session.getParentFoldRangeData(row, true);
4771            var range = data.range || data.firstRange;
4772
4773            if (range) {
4774                row = range.start.row;
4775                var fold = session.getFoldAt(row, session.getLine(row).length, 1);
4776
4777                if (fold) {
4778                    session.removeFold(fold);
4779                } else {
4780                    session.addFold("...", range);
4781                    editor.renderer.scrollCursorIntoView({row: range.start.row, column: 0});
4782                }
4783            }
4784            e.stop();
4785        }
4786    });
4787}
4788
4789exports.FoldHandler = FoldHandler;
4790
4791});
4792
4793define("ace/keyboard/keybinding",["require","exports","module","ace/lib/keys","ace/lib/event"], function(require, exports, module) {
4794"use strict";
4795
4796var keyUtil  = require("../lib/keys");
4797var event = require("../lib/event");
4798
4799var KeyBinding = function(editor) {
4800    this.$editor = editor;
4801    this.$data = {editor: editor};
4802    this.$handlers = [];
4803    this.setDefaultHandler(editor.commands);
4804};
4805
4806(function() {
4807    this.setDefaultHandler = function(kb) {
4808        this.removeKeyboardHandler(this.$defaultHandler);
4809        this.$defaultHandler = kb;
4810        this.addKeyboardHandler(kb, 0);
4811    };
4812
4813    this.setKeyboardHandler = function(kb) {
4814        var h = this.$handlers;
4815        if (h[h.length - 1] == kb)
4816            return;
4817
4818        while (h[h.length - 1] && h[h.length - 1] != this.$defaultHandler)
4819            this.removeKeyboardHandler(h[h.length - 1]);
4820
4821        this.addKeyboardHandler(kb, 1);
4822    };
4823
4824    this.addKeyboardHandler = function(kb, pos) {
4825        if (!kb)
4826            return;
4827        if (typeof kb == "function" && !kb.handleKeyboard)
4828            kb.handleKeyboard = kb;
4829        var i = this.$handlers.indexOf(kb);
4830        if (i != -1)
4831            this.$handlers.splice(i, 1);
4832
4833        if (pos == undefined)
4834            this.$handlers.push(kb);
4835        else
4836            this.$handlers.splice(pos, 0, kb);
4837
4838        if (i == -1 && kb.attach)
4839            kb.attach(this.$editor);
4840    };
4841
4842    this.removeKeyboardHandler = function(kb) {
4843        var i = this.$handlers.indexOf(kb);
4844        if (i == -1)
4845            return false;
4846        this.$handlers.splice(i, 1);
4847        kb.detach && kb.detach(this.$editor);
4848        return true;
4849    };
4850
4851    this.getKeyboardHandler = function() {
4852        return this.$handlers[this.$handlers.length - 1];
4853    };
4854    
4855    this.getStatusText = function() {
4856        var data = this.$data;
4857        var editor = data.editor;
4858        return this.$handlers.map(function(h) {
4859            return h.getStatusText && h.getStatusText(editor, data) || "";
4860        }).filter(Boolean).join(" ");
4861    };
4862
4863    this.$callKeyboardHandlers = function(hashId, keyString, keyCode, e) {
4864        var toExecute;
4865        var success = false;
4866        var commands = this.$editor.commands;
4867
4868        for (var i = this.$handlers.length; i--;) {
4869            toExecute = this.$handlers[i].handleKeyboard(
4870                this.$data, hashId, keyString, keyCode, e
4871            );
4872            if (!toExecute || !toExecute.command)
4873                continue;
4874            if (toExecute.command == "null") {
4875                success = true;
4876            } else {
4877                success = commands.exec(toExecute.command, this.$editor, toExecute.args, e);
4878            }
4879            if (success && e && hashId != -1 && 
4880                toExecute.passEvent != true && toExecute.command.passEvent != true
4881            ) {
4882                event.stopEvent(e);
4883            }
4884            if (success)
4885                break;
4886        }
4887        
4888        if (!success && hashId == -1) {
4889            toExecute = {command: "insertstring"};
4890            success = commands.exec("insertstring", this.$editor, keyString);
4891        }
4892        
4893        if (success && this.$editor._signal)
4894            this.$editor._signal("keyboardActivity", toExecute);
4895        
4896        return success;
4897    };
4898
4899    this.onCommandKey = function(e, hashId, keyCode) {
4900        var keyString = keyUtil.keyCodeToString(keyCode);
4901        this.$callKeyboardHandlers(hashId, keyString, keyCode, e);
4902    };
4903
4904    this.onTextInput = function(text) {
4905        this.$callKeyboardHandlers(-1, text);
4906    };
4907
4908}).call(KeyBinding.prototype);
4909
4910exports.KeyBinding = KeyBinding;
4911});
4912
4913define("ace/lib/bidiutil",["require","exports","module"], function(require, exports, module) {
4914"use strict";
4915
4916var ArabicAlefBetIntervalsBegine = ['\u0621', '\u0641'];
4917var ArabicAlefBetIntervalsEnd = ['\u063A', '\u064a'];
4918var dir = 0, hiLevel = 0;
4919var lastArabic = false, hasUBAT_AL = false,  hasUBAT_B = false,  hasUBAT_S = false, hasBlockSep = false, hasSegSep = false;
4920
4921var impTab_LTR = [	[	0,		3,		0,		1,		0,		0,		0	],	[	0,		3,		0,		1,		2,		2,		0	],	[	0,		3,		0,		0x11,		2,		0,		1	],	[	0,		3,		5,		5,		4,		1,		0	],	[	0,		3,		0x15,		0x15,		4,		0,		1	],	[	0,		3,		5,		5,		4,		2,		0	]
4922];
4923
4924var impTab_RTL = [	[	2,		0,		1,		1,		0,		1,		0	],	[	2,		0,		1,		1,		0,		2,		0	],	[	2,		0,		2,		1,		3,		2,		0	],	[	2,		0,		2,		0x21,		3,		1,		1	]
4925];
4926
4927var LTR = 0, RTL = 1;
4928
4929var L = 0;
4930var R = 1;
4931var EN = 2;
4932var AN = 3;
4933var ON = 4;
4934var B = 5;
4935var S = 6;
4936var AL = 7;
4937var WS = 8;
4938var CS = 9;
4939var ES = 10;
4940var ET = 11;
4941var NSM = 12;
4942var LRE = 13;
4943var RLE = 14;
4944var PDF = 15;
4945var LRO = 16;
4946var RLO = 17;
4947var BN = 18;
4948
4949var UnicodeTBL00 = [
4950BN,BN,BN,BN,BN,BN,BN,BN,BN,S,B,S,WS,B,BN,BN,
4951BN,BN,BN,BN,BN,BN,BN,BN,BN,BN,BN,BN,B,B,B,S,
4952WS,ON,ON,ET,ET,ET,ON,ON,ON,ON,ON,ES,CS,ES,CS,CS,
4953EN,EN,EN,EN,EN,EN,EN,EN,EN,EN,CS,ON,ON,ON,ON,ON,
4954ON,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,
4955L,L,L,L,L,L,L,L,L,L,L,ON,ON,ON,ON,ON,
4956ON,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,
4957L,L,L,L,L,L,L,L,L,L,L,ON,ON,ON,ON,BN,
4958BN,BN,BN,BN,BN,B,BN,BN,BN,BN,BN,BN,BN,BN,BN,BN,
4959BN,BN,BN,BN,BN,BN,BN,BN,BN,BN,BN,BN,BN,BN,BN,BN,
4960CS,ON,ET,ET,ET,ET,ON,ON,ON,ON,L,ON,ON,BN,ON,ON,
4961ET,ET,EN,EN,ON,L,ON,ON,ON,EN,L,ON,ON,ON,ON,ON
4962];
4963
4964var UnicodeTBL20 = [
4965WS,WS,WS,WS,WS,WS,WS,WS,WS,WS,WS,BN,BN,BN,L,R	,
4966ON,ON,ON,ON,ON,ON,ON,ON,ON,ON,ON,ON,ON,ON,ON,ON,
4967ON,ON,ON,ON,ON,ON,ON,ON,WS,B,LRE,RLE,PDF,LRO,RLO,CS,
4968ET,ET,ET,ET,ET,ON,ON,ON,ON,ON,ON,ON,ON,ON,ON,ON,
4969ON,ON,ON,ON,CS,ON,ON,ON,ON,ON,ON,ON,ON,ON,ON,ON,
4970ON,ON,ON,ON,ON,ON,ON,ON,ON,ON,ON,ON,ON,ON,ON,WS
4971];
4972
4973function _computeLevels(chars, levels, len, charTypes) {
4974	var impTab = dir ? impTab_RTL : impTab_LTR
4975		, prevState = null, newClass = null, newLevel = null, newState = 0
4976		, action = null, cond = null, condPos = -1, i = null, ix = null, classes = [];
4977
4978	if (!charTypes) {
4979		for (i = 0, charTypes = []; i < len; i++) {
4980			charTypes[i] = _getCharacterType(chars[i]);
4981		}
4982	}
4983	hiLevel = dir;
4984	lastArabic = false;
4985	hasUBAT_AL = false;
4986	hasUBAT_B = false;
4987	hasUBAT_S = false;
4988	for (ix = 0; ix < len; ix++){
4989		prevState = newState;
4990		classes[ix] = newClass = _getCharClass(chars, charTypes, classes, ix);
4991		newState = impTab[prevState][newClass];
4992		action = newState & 0xF0;
4993		newState &= 0x0F;
4994		levels[ix] = newLevel = impTab[newState][5];
4995		if (action > 0){
4996			if (action == 0x10){
4997				for(i = condPos; i < ix; i++){
4998					levels[i] = 1;
4999				}
5000				condPos = -1;
5001			} else {
5002				condPos = -1;
5003			}
5004		}
5005		cond = impTab[newState][6];
5006		if (cond){
5007			if(condPos == -1){
5008				condPos = ix;
5009			}
5010		}else{
5011			if (condPos > -1){
5012				for(i = condPos; i < ix; i++){
5013					levels[i] = newLevel;
5014				}
5015				condPos = -1;
5016			}
5017		}
5018		if (charTypes[ix] == B){
5019			levels[ix] = 0;
5020		}
5021		hiLevel |= newLevel;
5022	}
5023	if (hasUBAT_S){
5024		for(i = 0; i < len; i++){
5025			if(charTypes[i] == S){
5026				levels[i] = dir;
5027				for(var j = i - 1; j >= 0; j--){
5028					if(charTypes[j] == WS){
5029						levels[j] = dir;
5030					}else{
5031						break;
5032					}
5033				}
5034			}
5035		}
5036	}
5037}
5038
5039function _invertLevel(lev, levels, _array) {
5040	if (hiLevel < lev){
5041		return;
5042	}
5043	if (lev == 1 && dir == RTL && !hasUBAT_B){
5044		_array.reverse();
5045		return;
5046	}
5047	var len = _array.length, start = 0, end, lo, hi, tmp;
5048	while(start < len){
5049		if (levels[start] >= lev){
5050			end = start + 1;
5051		while(end < len && levels[end] >= lev){
5052			end++;
5053		}
5054		for(lo = start, hi = end - 1 ; lo < hi; lo++, hi--){
5055			tmp = _array[lo];
5056			_array[lo] = _array[hi];
5057			_array[hi] = tmp;
5058		}
5059		start = end;
5060	}
5061	start++;
5062	}
5063}
5064
5065function _getCharClass(chars, types, classes, ix) {			
5066	var cType = types[ix], wType, nType, len, i;
5067	switch(cType){
5068		case L:
5069		case R:
5070			lastArabic = false;
5071		case ON:
5072		case AN:
5073			return cType;
5074		case EN:
5075			return lastArabic ? AN : EN;
5076		case AL:
5077			lastArabic = true;
5078			hasUBAT_AL = true;
5079			return R;
5080		case WS:
5081			return ON;
5082		case CS:
5083			if (ix < 1 || (ix + 1) >= types.length ||
5084				((wType = classes[ix - 1]) != EN && wType != AN) ||
5085				((nType = types[ix + 1]) != EN && nType != AN)){
5086				return ON;
5087			}
5088			if (lastArabic){nType = AN;}
5089			return nType == wType ? nType : ON;
5090		case ES:
5091			wType = ix > 0 ? classes[ix - 1] : B;
5092			if (wType == EN && (ix + 1) < types.length && types[ix + 1] == EN){
5093				return EN;
5094			}
5095			return ON;
5096		case ET:
5097			if (ix > 0 && classes[ix - 1] == EN){
5098				return EN;
5099			}
5100			if (lastArabic){
5101				return ON;
5102			}
5103			i = ix + 1;
5104			len = types.length;
5105			while (i < len && types[i] == ET){
5106				i++;
5107			}
5108			if (i < len && types[i] == EN){
5109				return EN;
5110			}
5111			return ON;
5112		case NSM:
5113			len = types.length;
5114			i = ix + 1;
5115			while (i < len && types[i] == NSM){
5116				i++;
5117			}
5118			if (i < len){
5119				var c = chars[ix], rtlCandidate = (c >= 0x0591 && c <= 0x08FF) || c == 0xFB1E;
5120				
5121				wType = types[i];
5122				if (rtlCandidate && (wType == R || wType == AL)){
5123					return R;
5124				}
5125			}
5126
5127			if (ix < 1 || (wType = types[ix - 1]) == B){
5128				return ON;
5129			}
5130			return classes[ix - 1];
5131		case B:
5132			lastArabic = false;
5133			hasUBAT_B = true;
5134			return dir;
5135		case S:
5136			hasUBAT_S = true;
5137			return ON;
5138		case LRE:
5139		case RLE:
5140		case LRO:
5141		case RLO:
5142		case PDF:
5143			lastArabic = false;
5144		case BN:
5145			return ON;
5146	}
5147}
5148
5149function _getCharacterType( ch ) {		
5150	var uc = ch.charCodeAt(0), hi = uc >> 8;
5151	
5152	if (hi == 0) {		
5153		return ((uc > 0x00BF) ? L : UnicodeTBL00[uc]);
5154	} else if (hi == 5) {
5155		return (/[\u0591-\u05f4]/.test(ch) ? R : L);
5156	} else if (hi == 6) {
5157		if (/[\u0610-\u061a\u064b-\u065f\u06d6-\u06e4\u06e7-\u06ed]/.test(ch))
5158			return NSM;
5159		else if (/[\u0660-\u0669\u066b-\u066c]/.test(ch))
5160			return AN;
5161		else if (uc == 0x066A)
5162			return ET;
5163		else if (/[\u06f0-\u06f9]/.test(ch))
5164			return EN;			
5165		else
5166			return AL;
5167	} else if (hi == 0x20 && uc <= 0x205F) {
5168		return UnicodeTBL20[uc & 0xFF];
5169	} else if (hi == 0xFE) {
5170		return (uc >= 0xFE70 ? AL : ON);
5171	}		
5172	return ON;	
5173}
5174
5175function _isArabicDiacritics( ch ) {
5176	return (ch >= '\u064b' && ch <= '\u0655');
5177}
5178exports.L = L;
5179exports.R = R;
5180exports.EN = EN;
5181exports.ON_R = 3;
5182exports.AN = 4;
5183exports.R_H = 5;
5184exports.B = 6;
5185
5186exports.DOT = "\xB7";
5187exports.doBidiReorder = function(text, textCharTypes, isRtl) {
5188	if (text.length < 2)
5189		return {};
5190		
5191	var chars = text.split(""), logicalFromVisual = new Array(chars.length),
5192		bidiLevels = new Array(chars.length), levels = []; 
5193
5194	dir = isRtl ? RTL : LTR;
5195
5196	_computeLevels(chars, levels, chars.length, textCharTypes);
5197
5198	for (var i = 0; i < logicalFromVisual.length; logicalFromVisual[i] = i, i++);
5199
5200	_invertLevel(2, levels, logicalFromVisual);
5201	_invertLevel(1, levels, logicalFromVisual);
5202
5203	for (var i = 0; i < logicalFromVisual.length - 1; i++) { //fix levels to reflect character width
5204		if (textCharTypes[i] === AN) {
5205			levels[i] = exports.AN;
5206		} else if (levels[i] === R && ((textCharTypes[i] > AL && textCharTypes[i] < LRE) 
5207			|| textCharTypes[i] === ON || textCharTypes[i] === BN)) {
5208			levels[i] = exports.ON_R;
5209		} else if ((i > 0 && chars[i - 1] === '\u0644') && /\u0622|\u0623|\u0625|\u0627/.test(chars[i])) {
5210			levels[i - 1] = levels[i] = exports.R_H;
5211			i++;
5212		}
5213	}
5214	if (chars[chars.length - 1] === exports.DOT)
5215		levels[chars.length - 1] = exports.B;
5216				
5217	for (var i = 0; i < logicalFromVisual.length; i++) {
5218		bidiLevels[i] = levels[logicalFromVisual[i]];
5219	}
5220
5221	return {'logicalFromVisual': logicalFromVisual, 'bidiLevels': bidiLevels};
5222};
5223exports.hasBidiCharacters = function(text, textCharTypes){
5224	var ret = false;
5225	for (var i = 0; i < text.length; i++){
5226		textCharTypes[i] = _getCharacterType(text.charAt(i));
5227		if (!ret && (textCharTypes[i] == R || textCharTypes[i] == AL))
5228			ret = true;
5229	}
5230	return ret;
5231};	
5232exports.getVisualFromLogicalIdx = function(logIdx, rowMap) {
5233	for (var i = 0; i < rowMap.logicalFromVisual.length; i++) {
5234		if (rowMap.logicalFromVisual[i] == logIdx)
5235			return i;
5236	}
5237	return 0;
5238};
5239
5240});
5241
5242define("ace/bidihandler",["require","exports","module","ace/lib/bidiutil","ace/lib/lang","ace/lib/useragent"], function(require, exports, module) {
5243"use strict";
5244
5245var bidiUtil = require("./lib/bidiutil");
5246var lang = require("./lib/lang");
5247var useragent = require("./lib/useragent");
5248var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/;
5249var BidiHandler = function(session) {
5250    this.session = session;
5251    this.bidiMap = {};
5252    this.currentRow = null;
5253    this.bidiUtil = bidiUtil;
5254    this.charWidths = [];
5255    this.EOL = "\xAC";
5256    this.showInvisibles = true;
5257    this.isRtlDir = false;
5258    this.line = "";
5259    this.wrapIndent = 0;
5260    this.isLastRow = false;
5261    this.EOF = "\xB6";
5262    this.seenBidi = false;
5263};
5264
5265(function() {
5266    this.isBidiRow = function(screenRow, docRow, splitIndex) {
5267        if (!this.seenBidi)
5268            return false;
5269        if (screenRow !== this.currentRow) {
5270            this.currentRow = screenRow;
5271            this.updateRowLine(docRow, splitIndex);
5272            this.updateBidiMap();
5273        }
5274        return this.bidiMap.bidiLevels;
5275    };
5276
5277    this.onChange = function(delta) {
5278        if (!this.seenBidi) {
5279            if (delta.action == "insert" && bidiRE.test(delta.lines.join("\n"))) {
5280                this.seenBidi = true;
5281                this.currentRow = null;
5282            }
5283        } 
5284        else {
5285            this.currentRow = null;
5286        }
5287    };
5288
5289    this.getDocumentRow = function() {
5290        var docRow = 0;
5291        var rowCache = this.session.$screenRowCache;
5292        if (rowCache.length) {
5293            var index = this.session.$getRowCacheIndex(rowCache, this.currentRow);
5294            if (index >= 0)
5295                docRow = this.session.$docRowCache[index];
5296        }
5297
5298        return docRow;
5299    };
5300
5301    this.getSplitIndex = function() {
5302        var splitIndex = 0;
5303        var rowCache = this.session.$screenRowCache;
5304        if (rowCache.length) {
5305            var currentIndex, prevIndex = this.session.$getRowCacheIndex(rowCache, this.currentRow);
5306            while (this.currentRow - splitIndex > 0) {
5307                currentIndex = this.session.$getRowCacheIndex(rowCache, this.currentRow - splitIndex - 1);
5308                if (currentIndex !== prevIndex)
5309                    break;
5310
5311                prevIndex = currentIndex;
5312                splitIndex++;
5313            }
5314        }
5315
5316        return splitIndex;
5317    };
5318
5319    this.updateRowLine = function(docRow, splitIndex) {
5320        if (docRow === undefined)
5321            docRow = this.getDocumentRow();
5322            
5323        this.wrapIndent = 0;
5324        this.isLastRow = (docRow === this.session.getLength() - 1);
5325        this.line = this.session.getLine(docRow);
5326        if (this.session.$useWrapMode) {
5327            var splits = this.session.$wrapData[docRow];
5328            if (splits) {
5329                if (splitIndex === undefined)
5330                    splitIndex = this.getSplitIndex();
5331
5332                if(splitIndex > 0 && splits.length) {
5333                    this.wrapIndent = splits.indent;
5334                    this.line = (splitIndex < splits.length) ?
5335                        this.line.substring(splits[splitIndex - 1], splits[splits.length - 1]) :
5336                            this.line.substring(splits[splits.length - 1]);
5337                } else {
5338                    this.line = this.line.substring(0, splits[splitIndex]);
5339                }
5340            }
5341        }
5342        var session = this.session, shift = 0, size;
5343        this.line = this.line.replace(/\t|[\u1100-\u2029, \u202F-\uFFE6]/g, function(ch, i){
5344            if (ch === '\t' || session.isFullWidth(ch.charCodeAt(0))) {
5345                size = (ch === '\t') ? session.getScreenTabSize(i + shift) : 2;
5346                shift += size - 1;
5347                return lang.stringRepeat(bidiUtil.DOT, size);
5348            }
5349            return ch;
5350        });
5351    };
5352    
5353    this.updateBidiMap = function() {
5354        var textCharTypes = [], endOfLine = this.isLastRow ? this.EOF : this.EOL;
5355        var line = this.line + (this.showInvisibles ? endOfLine : bidiUtil.DOT);
5356        if (bidiUtil.hasBidiCharacters(line, textCharTypes)) {
5357            this.bidiMap = bidiUtil.doBidiReorder(line, textCharTypes, this.isRtlDir);
5358        } else {
5359            this.bidiMap = {};
5360        }
5361    };
5362    this.markAsDirty = function() {
5363        this.currentRow = null;
5364    };
5365    this.updateCharacterWidths = function(fontMetrics) {
5366        if (!this.seenBidi)
5367            return;
5368        if (this.characterWidth === fontMetrics.$characterSize.width)
5369            return;
5370
5371        var characterWidth = this.characterWidth = fontMetrics.$characterSize.width;
5372        var bidiCharWidth = fontMetrics.$measureCharWidth("\u05d4");
5373
5374        this.charWidths[bidiUtil.L] = this.charWidths[bidiUtil.EN] = this.charWidths[bidiUtil.ON_R] = characterWidth;
5375        this.charWidths[bidiUtil.R] = this.charWidths[bidiUtil.AN] = bidiCharWidth;
5376        this.charWidths[bidiUtil.R_H] = useragent.isChrome ? bidiCharWidth : bidiCharWidth * 0.45;
5377        this.charWidths[bidiUtil.B] = 0;
5378
5379        this.currentRow = null;
5380    };
5381
5382    this.getShowInvisibles = function() {
5383        return this.showInvisibles;
5384    };
5385
5386    this.setShowInvisibles = function(showInvisibles) {
5387        this.showInvisibles = showInvisibles;
5388        this.currentRow = null;
5389    };
5390
5391    this.setEolChar = function(eolChar) {
5392        this.EOL = eolChar; 
5393    };
5394
5395    this.setTextDir = function(isRtlDir) {
5396        this.isRtlDir = isRtlDir; 
5397    };
5398    this.getPosLeft = function(col) {
5399        col -= this.wrapIndent;
5400        var visualIdx = bidiUtil.getVisualFromLogicalIdx(col > 0 ? col - 1 : 0, this.bidiMap),
5401            levels = this.bidiMap.bidiLevels, left = 0;
5402
5403        if (col === 0 && levels[visualIdx] % 2 !== 0)
5404            visualIdx++;
5405
5406        for (var i = 0; i < visualIdx; i++) {
5407            left += this.charWidths[levels[i]];
5408        }
5409
5410        if (col !== 0 && levels[visualIdx] % 2 === 0)
5411            left += this.charWidths[levels[visualIdx]];
5412
5413        if (this.wrapIndent)
5414            left += this.wrapIndent * this.charWidths[bidiUtil.L];
5415
5416        return left;
5417    };
5418    this.getSelections = function(startCol, endCol) {
5419        var map = this.bidiMap, levels = map.bidiLevels, level, offset = this.wrapIndent * this.charWidths[bidiUtil.L], selections = [],
5420            selColMin = Math.min(startCol, endCol) - this.wrapIndent, selColMax = Math.max(startCol, endCol) - this.wrapIndent,
5421                isSelected = false, isSelectedPrev = false, selectionStart = 0;
5422
5423        for (var logIdx, visIdx = 0; visIdx < levels.length; visIdx++) {
5424            logIdx = map.logicalFromVisual[visIdx];
5425            level = levels[visIdx];
5426            isSelected = (logIdx >= selColMin) && (logIdx < selColMax);
5427            if (isSelected && !isSelectedPrev) {
5428                selectionStart = offset;
5429            } else if (!isSelected && isSelectedPrev) {
5430                selections.push({left: selectionStart, width: offset - selectionStart});
5431            }
5432            offset += this.charWidths[level];
5433            isSelectedPrev = isSelected;
5434        }
5435
5436        if (isSelected && (visIdx === levels.length)) {
5437            selections.push({left: selectionStart, width: offset - selectionStart});
5438        }
5439
5440        return selections;
5441    };
5442    this.offsetToCol = function(posX) {
5443        var logicalIdx = 0, posX = Math.max(posX, 0),
5444            offset = 0, visualIdx = 0, levels = this.bidiMap.bidiLevels,
5445                charWidth = this.charWidths[levels[visualIdx]];
5446
5447        if (this.wrapIndent) {
5448            posX -= this.wrapIndent * this.charWidths[bidiUtil.L];
5449        }
5450    
5451        while(posX > offset + charWidth/2) {
5452            offset += charWidth;
5453            if(visualIdx === levels.length - 1) {
5454                charWidth = 0;
5455                break;
5456            }
5457            charWidth = this.charWidths[levels[++visualIdx]];
5458        }
5459    
5460        if (visualIdx > 0 && (levels[visualIdx - 1] % 2 !== 0) && (levels[visualIdx] % 2 === 0)){
5461            if(posX < offset)
5462                visualIdx--;
5463            logicalIdx = this.bidiMap.logicalFromVisual[visualIdx];
5464
5465        } else if (visualIdx > 0 && (levels[visualIdx - 1] % 2 === 0) && (levels[visualIdx] % 2 !== 0)){
5466            logicalIdx = 1 + ((posX > offset) ? this.bidiMap.logicalFromVisual[visualIdx]
5467                    : this.bidiMap.logicalFromVisual[visualIdx - 1]);
5468
5469        } else if ((this.isRtlDir && visualIdx === levels.length - 1 && charWidth === 0 && (levels[visualIdx - 1] % 2 === 0))
5470                || (!this.isRtlDir && visualIdx === 0 && (levels[visualIdx] % 2 !== 0))){
5471            logicalIdx = 1 + this.bidiMap.logicalFromVisual[visualIdx];
5472        } else {
5473            if (visualIdx > 0 && (levels[visualIdx - 1] % 2 !== 0) && charWidth !== 0)
5474                visualIdx--;
5475            logicalIdx = this.bidiMap.logicalFromVisual[visualIdx];
5476        }
5477
5478        return (logicalIdx + this.wrapIndent);
5479    };
5480
5481}).call(BidiHandler.prototype);
5482
5483exports.BidiHandler = BidiHandler;
5484});
5485
5486define("ace/selection",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/lib/event_emitter","ace/range"], function(require, exports, module) {
5487"use strict";
5488
5489var oop = require("./lib/oop");
5490var lang = require("./lib/lang");
5491var EventEmitter = require("./lib/event_emitter").EventEmitter;
5492var Range = require("./range").Range;
5493var Selection = function(session) {
5494    this.session = session;
5495    this.doc = session.getDocument();
5496
5497    this.clearSelection();
5498    this.cursor = this.lead = this.doc.createAnchor(0, 0);
5499    this.anchor = this.doc.createAnchor(0, 0);
5500    this.$silent = false;
5501
5502    var self = this;
5503    this.cursor.on("change", function(e) {
5504        self.$cursorChanged = true;
5505        if (!self.$silent)
5506            self._emit("changeCursor");
5507        if (!self.$isEmpty && !self.$silent)
5508            self._emit("changeSelection");
5509        if (!self.$keepDesiredColumnOnChange && e.old.column != e.value.column)
5510            self.$desiredColumn = null;
5511    });
5512
5513    this.anchor.on("change", function() {
5514        self.$anchorChanged = true;
5515        if (!self.$isEmpty && !self.$silent)
5516            self._emit("changeSelection");
5517    });
5518};
5519
5520(function() {
5521
5522    oop.implement(this, EventEmitter);
5523    this.isEmpty = function() {
5524        return this.$isEmpty || (
5525            this.anchor.row == this.lead.row &&
5526            this.anchor.column == this.lead.column
5527        );
5528    };
5529    this.isMultiLine = function() {
5530        return !this.$isEmpty && this.anchor.row != this.cursor.row;
5531    };
5532    this.getCursor = function() {
5533        return this.lead.getPosition();
5534    };
5535    this.setSelectionAnchor = function(row, column) {
5536        this.$isEmpty = false;
5537        this.anchor.setPosition(row, column);
5538    };
5539    this.getAnchor = 
5540    this.getSelectionAnchor = function() {
5541        if (this.$isEmpty)
5542            return this.getSelectionLead();
5543        
5544        return this.anchor.getPosition();
5545    };
5546    this.getSelectionLead = function() {
5547        return this.lead.getPosition();
5548    };
5549    this.isBackwards = function() {
5550        var anchor = this.anchor;
5551        var lead = this.lead;
5552        return (anchor.row > lead.row || (anchor.row == lead.row && anchor.column > lead.column));
5553    };
5554    this.getRange = function() {
5555        var anchor = this.anchor;
5556        var lead = this.lead;
5557
5558        if (this.$isEmpty)
5559            return Range.fromPoints(lead, lead);
5560
5561        return this.isBackwards()
5562            ? Range.fromPoints(lead, anchor)
5563            : Range.fromPoints(anchor, lead);
5564    };
5565    this.clearSelection = function() {
5566        if (!this.$isEmpty) {
5567            this.$isEmpty = true;
5568            this._emit("changeSelection");
5569        }
5570    };
5571    this.selectAll = function() {
5572        this.$setSelection(0, 0, Number.MAX_VALUE, Number.MAX_VALUE);
5573    };
5574    this.setRange =
5575    this.setSelectionRange = function(range, reverse) {
5576        var start = reverse ? range.end : range.start;
5577        var end = reverse ? range.start : range.end;
5578        this.$setSelection(start.row, start.column, end.row, end.column);
5579    };
5580
5581    this.$setSelection = function(anchorRow, anchorColumn, cursorRow, cursorColumn) {
5582        var wasEmpty = this.$isEmpty;
5583        this.$silent = true;
5584        this.$cursorChanged = this.$anchorChanged = false;
5585        this.anchor.setPosition(anchorRow, anchorColumn);
5586        this.cursor.setPosition(cursorRow, cursorColumn);
5587        this.$isEmpty = !Range.comparePoints(this.anchor, this.cursor);
5588        this.$silent = false;
5589        if (this.$cursorChanged)
5590            this._emit("changeCursor");
5591        if (this.$cursorChanged || this.$anchorChanged)
5592            this._emit("changeSelection");
5593    };
5594
5595    this.$moveSelection = function(mover) {
5596        var lead = this.lead;
5597        if (this.$isEmpty)
5598            this.setSelectionAnchor(lead.row, lead.column);
5599
5600        mover.call(this);
5601    };
5602    this.selectTo = function(row, column) {
5603        this.$moveSelection(function() {
5604            this.moveCursorTo(row, column);
5605        });
5606    };
5607    this.selectToPosition = function(pos) {
5608        this.$moveSelection(function() {
5609            this.moveCursorToPosition(pos);
5610        });
5611    };
5612    this.moveTo = function(row, column) {
5613        this.clearSelection();
5614        this.moveCursorTo(row, column);
5615    };
5616    this.moveToPosition = function(pos) {
5617        this.clearSelection();
5618        this.moveCursorToPosition(pos);
5619    };
5620    this.selectUp = function() {
5621        this.$moveSelection(this.moveCursorUp);
5622    };
5623    this.selectDown = function() {
5624        this.$moveSelection(this.moveCursorDown);
5625    };
5626    this.selectRight = function() {
5627        this.$moveSelection(this.moveCursorRight);
5628    };
5629    this.selectLeft = function() {
5630        this.$moveSelection(this.moveCursorLeft);
5631    };
5632    this.selectLineStart = function() {
5633        this.$moveSelection(this.moveCursorLineStart);
5634    };
5635    this.selectLineEnd = function() {
5636        this.$moveSelection(this.moveCursorLineEnd);
5637    };
5638    this.selectFileEnd = function() {
5639        this.$moveSelection(this.moveCursorFileEnd);
5640    };
5641    this.selectFileStart = function() {
5642        this.$moveSelection(this.moveCursorFileStart);
5643    };
5644    this.selectWordRight = function() {
5645        this.$moveSelection(this.moveCursorWordRight);
5646    };
5647    this.selectWordLeft = function() {
5648        this.$moveSelection(this.moveCursorWordLeft);
5649    };
5650    this.getWordRange = function(row, column) {
5651        if (typeof column == "undefined") {
5652            var cursor = row || this.lead;
5653            row = cursor.row;
5654            column = cursor.column;
5655        }
5656        return this.session.getWordRange(row, column);
5657    };
5658    this.selectWord = function() {
5659        this.setSelectionRange(this.getWordRange());
5660    };
5661    this.selectAWord = function() {
5662        var cursor = this.getCursor();
5663        var range = this.session.getAWordRange(cursor.row, cursor.column);
5664        this.setSelectionRange(range);
5665    };
5666
5667    this.getLineRange = function(row, excludeLastChar) {
5668        var rowStart = typeof row == "number" ? row : this.lead.row;
5669        var rowEnd;
5670
5671        var foldLine = this.session.getFoldLine(rowStart);
5672        if (foldLine) {
5673            rowStart = foldLine.start.row;
5674            rowEnd = foldLine.end.row;
5675        } else {
5676            rowEnd = rowStart;
5677        }
5678        if (excludeLastChar === true)
5679            return new Range(rowStart, 0, rowEnd, this.session.getLine(rowEnd).length);
5680        else
5681            return new Range(rowStart, 0, rowEnd + 1, 0);
5682    };
5683    this.selectLine = function() {
5684        this.setSelectionRange(this.getLineRange());
5685    };
5686    this.moveCursorUp = function() {
5687        this.moveCursorBy(-1, 0);
5688    };
5689    this.moveCursorDown = function() {
5690        this.moveCursorBy(1, 0);
5691    };
5692    this.wouldMoveIntoSoftTab = function(cursor, tabSize, direction) {
5693        var start = cursor.column;
5694        var end = cursor.column + tabSize;
5695
5696        if (direction < 0) {
5697            start = cursor.column - tabSize;
5698            end = cursor.column;
5699        }
5700        return this.session.isTabStop(cursor) && this.doc.getLine(cursor.row).slice(start, end).split(" ").length-1 == tabSize;
5701    };
5702    this.moveCursorLeft = function() {
5703        var cursor = this.lead.getPosition(),
5704            fold;
5705
5706        if (fold = this.session.getFoldAt(cursor.row, cursor.column, -1)) {
5707            this.moveCursorTo(fold.start.row, fold.start.column);
5708        } else if (cursor.column === 0) {
5709            if (cursor.row > 0) {
5710                this.moveCursorTo(cursor.row - 1, this.doc.getLine(cursor.row - 1).length);
5711            }
5712        }
5713        else {
5714            var tabSize = this.session.getTabSize();
5715            if (this.wouldMoveIntoSoftTab(cursor, tabSize, -1) && !this.session.getNavigateWithinSoftTabs()) {
5716                this.moveCursorBy(0, -tabSize);
5717            } else {
5718                this.moveCursorBy(0, -1);
5719            }
5720        }
5721    };
5722    this.moveCursorRight = function() {
5723        var cursor = this.lead.getPosition(),
5724            fold;
5725        if (fold = this.session.getFoldAt(cursor.row, cursor.column, 1
vendor: 80,312 bytes, lines 5725-7908
5725)) {
5726            this.moveCursorTo(fold.end.row, fold.end.column);
5727        }
5728        else if (this.lead.column == this.doc.getLine(this.lead.row).length) {
5729            if (this.lead.row < this.doc.getLength() - 1) {
5730                this.moveCursorTo(this.lead.row + 1, 0);
5731            }
5732        }
5733        else {
5734            var tabSize = this.session.getTabSize();
5735            var cursor = this.lead;
5736            if (this.wouldMoveIntoSoftTab(cursor, tabSize, 1) && !this.session.getNavigateWithinSoftTabs()) {
5737                this.moveCursorBy(0, tabSize);
5738            } else {
5739                this.moveCursorBy(0, 1);
5740            }
5741        }
5742    };
5743    this.moveCursorLineStart = function() {
5744        var row = this.lead.row;
5745        var column = this.lead.column;
5746        var screenRow = this.session.documentToScreenRow(row, column);
5747        var firstColumnPosition = this.session.screenToDocumentPosition(screenRow, 0);
5748        var beforeCursor = this.session.getDisplayLine(
5749            row, null, firstColumnPosition.row,
5750            firstColumnPosition.column
5751        );
5752
5753        var leadingSpace = beforeCursor.match(/^\s*/);
5754        if (leadingSpace[0].length != column && !this.session.$useEmacsStyleLineStart)
5755            firstColumnPosition.column += leadingSpace[0].length;
5756        this.moveCursorToPosition(firstColumnPosition);
5757    };
5758    this.moveCursorLineEnd = function() {
5759        var lead = this.lead;
5760        var lineEnd = this.session.getDocumentLastRowColumnPosition(lead.row, lead.column);
5761        if (this.lead.column == lineEnd.column) {
5762            var line = this.session.getLine(lineEnd.row);
5763            if (lineEnd.column == line.length) {
5764                var textEnd = line.search(/\s+$/);
5765                if (textEnd > 0)
5766                    lineEnd.column = textEnd;
5767            }
5768        }
5769
5770        this.moveCursorTo(lineEnd.row, lineEnd.column);
5771    };
5772    this.moveCursorFileEnd = function() {
5773        var row = this.doc.getLength() - 1;
5774        var column = this.doc.getLine(row).length;
5775        this.moveCursorTo(row, column);
5776    };
5777    this.moveCursorFileStart = function() {
5778        this.moveCursorTo(0, 0);
5779    };
5780    this.moveCursorLongWordRight = function() {
5781        var row = this.lead.row;
5782        var column = this.lead.column;
5783        var line = this.doc.getLine(row);
5784        var rightOfCursor = line.substring(column);
5785
5786        this.session.nonTokenRe.lastIndex = 0;
5787        this.session.tokenRe.lastIndex = 0;
5788        var fold = this.session.getFoldAt(row, column, 1);
5789        if (fold) {
5790            this.moveCursorTo(fold.end.row, fold.end.column);
5791            return;
5792        }
5793        if (this.session.nonTokenRe.exec(rightOfCursor)) {
5794            column += this.session.nonTokenRe.lastIndex;
5795            this.session.nonTokenRe.lastIndex = 0;
5796            rightOfCursor = line.substring(column);
5797        }
5798        if (column >= line.length) {
5799            this.moveCursorTo(row, line.length);
5800            this.moveCursorRight();
5801            if (row < this.doc.getLength() - 1)
5802                this.moveCursorWordRight();
5803            return;
5804        }
5805        if (this.session.tokenRe.exec(rightOfCursor)) {
5806            column += this.session.tokenRe.lastIndex;
5807            this.session.tokenRe.lastIndex = 0;
5808        }
5809
5810        this.moveCursorTo(row, column);
5811    };
5812    this.moveCursorLongWordLeft = function() {
5813        var row = this.lead.row;
5814        var column = this.lead.column;
5815        var fold;
5816        if (fold = this.session.getFoldAt(row, column, -1)) {
5817            this.moveCursorTo(fold.start.row, fold.start.column);
5818            return;
5819        }
5820
5821        var str = this.session.getFoldStringAt(row, column, -1);
5822        if (str == null) {
5823            str = this.doc.getLine(row).substring(0, column);
5824        }
5825
5826        var leftOfCursor = lang.stringReverse(str);
5827        this.session.nonTokenRe.lastIndex = 0;
5828        this.session.tokenRe.lastIndex = 0;
5829        if (this.session.nonTokenRe.exec(leftOfCursor)) {
5830            column -= this.session.nonTokenRe.lastIndex;
5831            leftOfCursor = leftOfCursor.slice(this.session.nonTokenRe.lastIndex);
5832            this.session.nonTokenRe.lastIndex = 0;
5833        }
5834        if (column <= 0) {
5835            this.moveCursorTo(row, 0);
5836            this.moveCursorLeft();
5837            if (row > 0)
5838                this.moveCursorWordLeft();
5839            return;
5840        }
5841        if (this.session.tokenRe.exec(leftOfCursor)) {
5842            column -= this.session.tokenRe.lastIndex;
5843            this.session.tokenRe.lastIndex = 0;
5844        }
5845
5846        this.moveCursorTo(row, column);
5847    };
5848
5849    this.$shortWordEndIndex = function(rightOfCursor) {
5850        var index = 0, ch;
5851        var whitespaceRe = /\s/;
5852        var tokenRe = this.session.tokenRe;
5853
5854        tokenRe.lastIndex = 0;
5855        if (this.session.tokenRe.exec(rightOfCursor)) {
5856            index = this.session.tokenRe.lastIndex;
5857        } else {
5858            while ((ch = rightOfCursor[index]) && whitespaceRe.test(ch))
5859                index ++;
5860
5861            if (index < 1) {
5862                tokenRe.lastIndex = 0;
5863                 while ((ch = rightOfCursor[index]) && !tokenRe.test(ch)) {
5864                    tokenRe.lastIndex = 0;
5865                    index ++;
5866                    if (whitespaceRe.test(ch)) {
5867                        if (index > 2) {
5868                            index--;
5869                            break;
5870                        } else {
5871                            while ((ch = rightOfCursor[index]) && whitespaceRe.test(ch))
5872                                index ++;
5873                            if (index > 2)
5874                                break;
5875                        }
5876                    }
5877                }
5878            }
5879        }
5880        tokenRe.lastIndex = 0;
5881
5882        return index;
5883    };
5884
5885    this.moveCursorShortWordRight = function() {
5886        var row = this.lead.row;
5887        var column = this.lead.column;
5888        var line = this.doc.getLine(row);
5889        var rightOfCursor = line.substring(column);
5890
5891        var fold = this.session.getFoldAt(row, column, 1);
5892        if (fold)
5893            return this.moveCursorTo(fold.end.row, fold.end.column);
5894
5895        if (column == line.length) {
5896            var l = this.doc.getLength();
5897            do {
5898                row++;
5899                rightOfCursor = this.doc.getLine(row);
5900            } while (row < l && /^\s*$/.test(rightOfCursor));
5901
5902            if (!/^\s+/.test(rightOfCursor))
5903                rightOfCursor = "";
5904            column = 0;
5905        }
5906
5907        var index = this.$shortWordEndIndex(rightOfCursor);
5908
5909        this.moveCursorTo(row, column + index);
5910    };
5911
5912    this.moveCursorShortWordLeft = function() {
5913        var row = this.lead.row;
5914        var column = this.lead.column;
5915
5916        var fold;
5917        if (fold = this.session.getFoldAt(row, column, -1))
5918            return this.moveCursorTo(fold.start.row, fold.start.column);
5919
5920        var line = this.session.getLine(row).substring(0, column);
5921        if (column === 0) {
5922            do {
5923                row--;
5924                line = this.doc.getLine(row);
5925            } while (row > 0 && /^\s*$/.test(line));
5926
5927            column = line.length;
5928            if (!/\s+$/.test(line))
5929                line = "";
5930        }
5931
5932        var leftOfCursor = lang.stringReverse(line);
5933        var index = this.$shortWordEndIndex(leftOfCursor);
5934
5935        return this.moveCursorTo(row, column - index);
5936    };
5937
5938    this.moveCursorWordRight = function() {
5939        if (this.session.$selectLongWords)
5940            this.moveCursorLongWordRight();
5941        else
5942            this.moveCursorShortWordRight();
5943    };
5944
5945    this.moveCursorWordLeft = function() {
5946        if (this.session.$selectLongWords)
5947            this.moveCursorLongWordLeft();
5948        else
5949            this.moveCursorShortWordLeft();
5950    };
5951    this.moveCursorBy = function(rows, chars) {
5952        var screenPos = this.session.documentToScreenPosition(
5953            this.lead.row,
5954            this.lead.column
5955        );
5956
5957        var offsetX;
5958
5959        if (chars === 0) {
5960            if (rows !== 0) {
5961                if (this.session.$bidiHandler.isBidiRow(screenPos.row, this.lead.row)) {
5962                    offsetX = this.session.$bidiHandler.getPosLeft(screenPos.column);
5963                    screenPos.column = Math.round(offsetX / this.session.$bidiHandler.charWidths[0]);
5964                } else {
5965                    offsetX = screenPos.column * this.session.$bidiHandler.charWidths[0];
5966                }
5967            }
5968
5969            if (this.$desiredColumn)
5970                screenPos.column = this.$desiredColumn;
5971            else
5972                this.$desiredColumn = screenPos.column;
5973        }
5974
5975        var docPos = this.session.screenToDocumentPosition(screenPos.row + rows, screenPos.column, offsetX);
5976        
5977        if (rows !== 0 && chars === 0 && docPos.row === this.lead.row && docPos.column === this.lead.column) {
5978            if (this.session.lineWidgets && this.session.lineWidgets[docPos.row]) {
5979                if (docPos.row > 0 || rows > 0)
5980                    docPos.row++;
5981            }
5982        }
5983        this.moveCursorTo(docPos.row, docPos.column + chars, chars === 0);
5984    };
5985    this.moveCursorToPosition = function(position) {
5986        this.moveCursorTo(position.row, position.column);
5987    };
5988    this.moveCursorTo = function(row, column, keepDesiredColumn) {
5989        var fold = this.session.getFoldAt(row, column, 1);
5990        if (fold) {
5991            row = fold.start.row;
5992            column = fold.start.column;
5993        }
5994
5995        this.$keepDesiredColumnOnChange = true;
5996        var line = this.session.getLine(row);
5997        if (/[\uDC00-\uDFFF]/.test(line.charAt(column)) && line.charAt(column - 1)) {
5998            if (this.lead.row == row && this.lead.column == column + 1)
5999                column = column - 1;
6000            else
6001                column = column + 1;
6002        }
6003        this.lead.setPosition(row, column);
6004        this.$keepDesiredColumnOnChange = false;
6005
6006        if (!keepDesiredColumn)
6007            this.$desiredColumn = null;
6008    };
6009    this.moveCursorToScreen = function(row, column, keepDesiredColumn) {
6010        var pos = this.session.screenToDocumentPosition(row, column);
6011        this.moveCursorTo(pos.row, pos.column, keepDesiredColumn);
6012    };
6013    this.detach = function() {
6014        this.lead.detach();
6015        this.anchor.detach();
6016        this.session = this.doc = null;
6017    };
6018
6019    this.fromOrientedRange = function(range) {
6020        this.setSelectionRange(range, range.cursor == range.start);
6021        this.$desiredColumn = range.desiredColumn || this.$desiredColumn;
6022    };
6023
6024    this.toOrientedRange = function(range) {
6025        var r = this.getRange();
6026        if (range) {
6027            range.start.column = r.start.column;
6028            range.start.row = r.start.row;
6029            range.end.column = r.end.column;
6030            range.end.row = r.end.row;
6031        } else {
6032            range = r;
6033        }
6034
6035        range.cursor = this.isBackwards() ? range.start : range.end;
6036        range.desiredColumn = this.$desiredColumn;
6037        return range;
6038    };
6039    this.getRangeOfMovements = function(func) {
6040        var start = this.getCursor();
6041        try {
6042            func(this);
6043            var end = this.getCursor();
6044            return Range.fromPoints(start, end);
6045        } catch(e) {
6046            return Range.fromPoints(start, start);
6047        } finally {
6048            this.moveCursorToPosition(start);
6049        }
6050    };
6051
6052    this.toJSON = function() {
6053        if (this.rangeCount) {
6054            var data = this.ranges.map(function(r) {
6055                var r1 = r.clone();
6056                r1.isBackwards = r.cursor == r.start;
6057                return r1;
6058            });
6059        } else {
6060            var data = this.getRange();
6061            data.isBackwards = this.isBackwards();
6062        }
6063        return data;
6064    };
6065
6066    this.fromJSON = function(data) {
6067        if (data.start == undefined) {
6068            if (this.rangeList) {
6069                this.toSingleRange(data[0]);
6070                for (var i = data.length; i--; ) {
6071                    var r = Range.fromPoints(data[i].start, data[i].end);
6072                    if (data[i].isBackwards)
6073                        r.cursor = r.start;
6074                    this.addRange(r, true);
6075                }
6076                return;
6077            } else {
6078                data = data[0];
6079            }
6080        }
6081        if (this.rangeList)
6082            this.toSingleRange(data);
6083        this.setSelectionRange(data, data.isBackwards);
6084    };
6085
6086    this.isEqual = function(data) {
6087        if ((data.length || this.rangeCount) && data.length != this.rangeCount)
6088            return false;
6089        if (!data.length || !this.ranges)
6090            return this.getRange().isEqual(data);
6091
6092        for (var i = this.ranges.length; i--; ) {
6093            if (!this.ranges[i].isEqual(data[i]))
6094                return false;
6095        }
6096        return true;
6097    };
6098
6099}).call(Selection.prototype);
6100
6101exports.Selection = Selection;
6102});
6103
6104define("ace/tokenizer",["require","exports","module","ace/config"], function(require, exports, module) {
6105"use strict";
6106
6107var config = require("./config");
6108var MAX_TOKEN_COUNT = 2000;
6109var Tokenizer = function(rules) {
6110    this.states = rules;
6111
6112    this.regExps = {};
6113    this.matchMappings = {};
6114    for (var key in this.states) {
6115        var state = this.states[key];
6116        var ruleRegExps = [];
6117        var matchTotal = 0;
6118        var mapping = this.matchMappings[key] = {defaultToken: "text"};
6119        var flag = "g";
6120
6121        var splitterRurles = [];
6122        for (var i = 0; i < state.length; i++) {
6123            var rule = state[i];
6124            if (rule.defaultToken)
6125                mapping.defaultToken = rule.defaultToken;
6126            if (rule.caseInsensitive)
6127                flag = "gi";
6128            if (rule.regex == null)
6129                continue;
6130
6131            if (rule.regex instanceof RegExp)
6132                rule.regex = rule.regex.toString().slice(1, -1);
6133            var adjustedregex = rule.regex;
6134            var matchcount = new RegExp("(?:(" + adjustedregex + ")|(.))").exec("a").length - 2;
6135            if (Array.isArray(rule.token)) {
6136                if (rule.token.length == 1 || matchcount == 1) {
6137                    rule.token = rule.token[0];
6138                } else if (matchcount - 1 != rule.token.length) {
6139                    this.reportError("number of classes and regexp groups doesn't match", { 
6140                        rule: rule,
6141                        groupCount: matchcount - 1
6142                    });
6143                    rule.token = rule.token[0];
6144                } else {
6145                    rule.tokenArray = rule.token;
6146                    rule.token = null;
6147                    rule.onMatch = this.$arrayTokens;
6148                }
6149            } else if (typeof rule.token == "function" && !rule.onMatch) {
6150                if (matchcount > 1)
6151                    rule.onMatch = this.$applyToken;
6152                else
6153                    rule.onMatch = rule.token;
6154            }
6155
6156            if (matchcount > 1) {
6157                if (/\\\d/.test(rule.regex)) {
6158                    adjustedregex = rule.regex.replace(/\\([0-9]+)/g, function(match, digit) {
6159                        return "\\" + (parseInt(digit, 10) + matchTotal + 1);
6160                    });
6161                } else {
6162                    matchcount = 1;
6163                    adjustedregex = this.removeCapturingGroups(rule.regex);
6164                }
6165                if (!rule.splitRegex && typeof rule.token != "string")
6166                    splitterRurles.push(rule); // flag will be known only at the very end
6167            }
6168
6169            mapping[matchTotal] = i;
6170            matchTotal += matchcount;
6171
6172            ruleRegExps.push(adjustedregex);
6173            if (!rule.onMatch)
6174                rule.onMatch = null;
6175        }
6176        
6177        if (!ruleRegExps.length) {
6178            mapping[0] = 0;
6179            ruleRegExps.push("$");
6180        }
6181        
6182        splitterRurles.forEach(function(rule) {
6183            rule.splitRegex = this.createSplitterRegexp(rule.regex, flag);
6184        }, this);
6185
6186        this.regExps[key] = new RegExp("(" + ruleRegExps.join(")|(") + ")|($)", flag);
6187    }
6188};
6189
6190(function() {
6191    this.$setMaxTokenCount = function(m) {
6192        MAX_TOKEN_COUNT = m | 0;
6193    };
6194    
6195    this.$applyToken = function(str) {
6196        var values = this.splitRegex.exec(str).slice(1);
6197        var types = this.token.apply(this, values);
6198        if (typeof types === "string")
6199            return [{type: types, value: str}];
6200
6201        var tokens = [];
6202        for (var i = 0, l = types.length; i < l; i++) {
6203            if (values[i])
6204                tokens[tokens.length] = {
6205                    type: types[i],
6206                    value: values[i]
6207                };
6208        }
6209        return tokens;
6210    };
6211
6212    this.$arrayTokens = function(str) {
6213        if (!str)
6214            return [];
6215        var values = this.splitRegex.exec(str);
6216        if (!values)
6217            return "text";
6218        var tokens = [];
6219        var types = this.tokenArray;
6220        for (var i = 0, l = types.length; i < l; i++) {
6221            if (values[i + 1])
6222                tokens[tokens.length] = {
6223                    type: types[i],
6224                    value: values[i + 1]
6225                };
6226        }
6227        return tokens;
6228    };
6229
6230    this.removeCapturingGroups = function(src) {
6231        var r = src.replace(
6232            /\[(?:\\.|[^\]])*?\]|\\.|\(\?[:=!]|(\()/g,
6233            function(x, y) {return y ? "(?:" : x;}
6234        );
6235        return r;
6236    };
6237
6238    this.createSplitterRegexp = function(src, flag) {
6239        if (src.indexOf("(?=") != -1) {
6240            var stack = 0;
6241            var inChClass = false;
6242            var lastCapture = {};
6243            src.replace(/(\\.)|(\((?:\?[=!])?)|(\))|([\[\]])/g, function(
6244                m, esc, parenOpen, parenClose, square, index
6245            ) {
6246                if (inChClass) {
6247                    inChClass = square != "]";
6248                } else if (square) {
6249                    inChClass = true;
6250                } else if (parenClose) {
6251                    if (stack == lastCapture.stack) {
6252                        lastCapture.end = index+1;
6253                        lastCapture.stack = -1;
6254                    }
6255                    stack--;
6256                } else if (parenOpen) {
6257                    stack++;
6258                    if (parenOpen.length != 1) {
6259                        lastCapture.stack = stack;
6260                        lastCapture.start = index;
6261                    }
6262                }
6263                return m;
6264            });
6265
6266            if (lastCapture.end != null && /^\)*$/.test(src.substr(lastCapture.end)))
6267                src = src.substring(0, lastCapture.start) + src.substr(lastCapture.end);
6268        }
6269        if (src.charAt(0) != "^") src = "^" + src;
6270        if (src.charAt(src.length - 1) != "$") src += "$";
6271        
6272        return new RegExp(src, (flag||"").replace("g", ""));
6273    };
6274    this.getLineTokens = function(line, startState) {
6275        if (startState && typeof startState != "string") {
6276            var stack = startState.slice(0);
6277            startState = stack[0];
6278            if (startState === "#tmp") {
6279                stack.shift();
6280                startState = stack.shift();
6281            }
6282        } else
6283            var stack = [];
6284
6285        var currentState = startState || "start";
6286        var state = this.states[currentState];
6287        if (!state) {
6288            currentState = "start";
6289            state = this.states[currentState];
6290        }
6291        var mapping = this.matchMappings[currentState];
6292        var re = this.regExps[currentState];
6293        re.lastIndex = 0;
6294
6295        var match, tokens = [];
6296        var lastIndex = 0;
6297        var matchAttempts = 0;
6298
6299        var token = {type: null, value: ""};
6300
6301        while (match = re.exec(line)) {
6302            var type = mapping.defaultToken;
6303            var rule = null;
6304            var value = match[0];
6305            var index = re.lastIndex;
6306
6307            if (index - value.length > lastIndex) {
6308                var skipped = line.substring(lastIndex, index - value.length);
6309                if (token.type == type) {
6310                    token.value += skipped;
6311                } else {
6312                    if (token.type)
6313                        tokens.push(token);
6314                    token = {type: type, value: skipped};
6315                }
6316            }
6317
6318            for (var i = 0; i < match.length-2; i++) {
6319                if (match[i + 1] === undefined)
6320                    continue;
6321
6322                rule = state[mapping[i]];
6323
6324                if (rule.onMatch)
6325                    type = rule.onMatch(value, currentState, stack, line);
6326                else
6327                    type = rule.token;
6328
6329                if (rule.next) {
6330                    if (typeof rule.next == "string") {
6331                        currentState = rule.next;
6332                    } else {
6333                        currentState = rule.next(currentState, stack);
6334                    }
6335                    
6336                    state = this.states[currentState];
6337                    if (!state) {
6338                        this.reportError("state doesn't exist", currentState);
6339                        currentState = "start";
6340                        state = this.states[currentState];
6341                    }
6342                    mapping = this.matchMappings[currentState];
6343                    lastIndex = index;
6344                    re = this.regExps[currentState];
6345                    re.lastIndex = index;
6346                }
6347                if (rule.consumeLineEnd)
6348                    lastIndex = index;
6349                break;
6350            }
6351
6352            if (value) {
6353                if (typeof type === "string") {
6354                    if ((!rule || rule.merge !== false) && token.type === type) {
6355                        token.value += value;
6356                    } else {
6357                        if (token.type)
6358                            tokens.push(token);
6359                        token = {type: type, value: value};
6360                    }
6361                } else if (type) {
6362                    if (token.type)
6363                        tokens.push(token);
6364                    token = {type: null, value: ""};
6365                    for (var i = 0; i < type.length; i++)
6366                        tokens.push(type[i]);
6367                }
6368            }
6369
6370            if (lastIndex == line.length)
6371                break;
6372
6373            lastIndex = index;
6374
6375            if (matchAttempts++ > MAX_TOKEN_COUNT) {
6376                if (matchAttempts > 2 * line.length) {
6377                    this.reportError("infinite loop with in ace tokenizer", {
6378                        startState: startState,
6379                        line: line
6380                    });
6381                }
6382                while (lastIndex < line.length) {
6383                    if (token.type)
6384                        tokens.push(token);
6385                    token = {
6386                        value: line.substring(lastIndex, lastIndex += 2000),
6387                        type: "overflow"
6388                    };
6389                }
6390                currentState = "start";
6391                stack = [];
6392                break;
6393            }
6394        }
6395
6396        if (token.type)
6397            tokens.push(token);
6398        
6399        if (stack.length > 1) {
6400            if (stack[0] !== currentState)
6401                stack.unshift("#tmp", currentState);
6402        }
6403        return {
6404            tokens : tokens,
6405            state : stack.length ? stack : currentState
6406        };
6407    };
6408    
6409    this.reportError = config.reportError;
6410    
6411}).call(Tokenizer.prototype);
6412
6413exports.Tokenizer = Tokenizer;
6414});
6415
6416define("ace/mode/text_highlight_rules",["require","exports","module","ace/lib/lang"], function(require, exports, module) {
6417"use strict";
6418
6419var lang = require("../lib/lang");
6420
6421var TextHighlightRules = function() {
6422
6423    this.$rules = {
6424        "start" : [{
6425            token : "empty_line",
6426            regex : '^$'
6427        }, {
6428            defaultToken : "text"
6429        }]
6430    };
6431};
6432
6433(function() {
6434
6435    this.addRules = function(rules, prefix) {
6436        if (!prefix) {
6437            for (var key in rules)
6438                this.$rules[key] = rules[key];
6439            return;
6440        }
6441        for (var key in rules) {
6442            var state = rules[key];
6443            for (var i = 0; i < state.length; i++) {
6444                var rule = state[i];
6445                if (rule.next || rule.onMatch) {
6446                    if (typeof rule.next == "string") {
6447                        if (rule.next.indexOf(prefix) !== 0)
6448                            rule.next = prefix + rule.next;
6449                    }
6450                    if (rule.nextState && rule.nextState.indexOf(prefix) !== 0)
6451                        rule.nextState = prefix + rule.nextState;
6452                }
6453            }
6454            this.$rules[prefix + key] = state;
6455        }
6456    };
6457
6458    this.getRules = function() {
6459        return this.$rules;
6460    };
6461
6462    this.embedRules = function (HighlightRules, prefix, escapeRules, states, append) {
6463        var embedRules = typeof HighlightRules == "function"
6464            ? new HighlightRules().getRules()
6465            : HighlightRules;
6466        if (states) {
6467            for (var i = 0; i < states.length; i++)
6468                states[i] = prefix + states[i];
6469        } else {
6470            states = [];
6471            for (var key in embedRules)
6472                states.push(prefix + key);
6473        }
6474
6475        this.addRules(embedRules, prefix);
6476
6477        if (escapeRules) {
6478            var addRules = Array.prototype[append ? "push" : "unshift"];
6479            for (var i = 0; i < states.length; i++)
6480                addRules.apply(this.$rules[states[i]], lang.deepCopy(escapeRules));
6481        }
6482
6483        if (!this.$embeds)
6484            this.$embeds = [];
6485        this.$embeds.push(prefix);
6486    };
6487
6488    this.getEmbeds = function() {
6489        return this.$embeds;
6490    };
6491
6492    var pushState = function(currentState, stack) {
6493        if (currentState != "start" || stack.length)
6494            stack.unshift(this.nextState, currentState);
6495        return this.nextState;
6496    };
6497    var popState = function(currentState, stack) {
6498        stack.shift();
6499        return stack.shift() || "start";
6500    };
6501
6502    this.normalizeRules = function() {
6503        var id = 0;
6504        var rules = this.$rules;
6505        function processState(key) {
6506            var state = rules[key];
6507            state.processed = true;
6508            for (var i = 0; i < state.length; i++) {
6509                var rule = state[i];
6510                var toInsert = null;
6511                if (Array.isArray(rule)) {
6512                    toInsert = rule;
6513                    rule = {};
6514                }
6515                if (!rule.regex && rule.start) {
6516                    rule.regex = rule.start;
6517                    if (!rule.next)
6518                        rule.next = [];
6519                    rule.next.push({
6520                        defaultToken: rule.token
6521                    }, {
6522                        token: rule.token + ".end",
6523                        regex: rule.end || rule.start,
6524                        next: "pop"
6525                    });
6526                    rule.token = rule.token + ".start";
6527                    rule.push = true;
6528                }
6529                var next = rule.next || rule.push;
6530                if (next && Array.isArray(next)) {
6531                    var stateName = rule.stateName;
6532                    if (!stateName)  {
6533                        stateName = rule.token;
6534                        if (typeof stateName != "string")
6535                            stateName = stateName[0] || "";
6536                        if (rules[stateName])
6537                            stateName += id++;
6538                    }
6539                    rules[stateName] = next;
6540                    rule.next = stateName;
6541                    processState(stateName);
6542                } else if (next == "pop") {
6543                    rule.next = popState;
6544                }
6545
6546                if (rule.push) {
6547                    rule.nextState = rule.next || rule.push;
6548                    rule.next = pushState;
6549                    delete rule.push;
6550                }
6551
6552                if (rule.rules) {
6553                    for (var r in rule.rules) {
6554                        if (rules[r]) {
6555                            if (rules[r].push)
6556                                rules[r].push.apply(rules[r], rule.rules[r]);
6557                        } else {
6558                            rules[r] = rule.rules[r];
6559                        }
6560                    }
6561                }
6562                var includeName = typeof rule == "string" ? rule : rule.include;
6563                if (includeName) {
6564                    if (Array.isArray(includeName))
6565                        toInsert = includeName.map(function(x) { return rules[x]; });
6566                    else
6567                        toInsert = rules[includeName];
6568                }
6569
6570                if (toInsert) {
6571                    var args = [i, 1].concat(toInsert);
6572                    if (rule.noEscape)
6573                        args = args.filter(function(x) {return !x.next;});
6574                    state.splice.apply(state, args);
6575                    i--;
6576                }
6577                
6578                if (rule.keywordMap) {
6579                    rule.token = this.createKeywordMapper(
6580                        rule.keywordMap, rule.defaultToken || "text", rule.caseInsensitive
6581                    );
6582                    delete rule.defaultToken;
6583                }
6584            }
6585        }
6586        Object.keys(rules).forEach(processState, this);
6587    };
6588
6589    this.createKeywordMapper = function(map, defaultToken, ignoreCase, splitChar) {
6590        var keywords = Object.create(null);
6591        Object.keys(map).forEach(function(className) {
6592            var a = map[className];
6593            if (ignoreCase)
6594                a = a.toLowerCase();
6595            var list = a.split(splitChar || "|");
6596            for (var i = list.length; i--; )
6597                keywords[list[i]] = className;
6598        });
6599        if (Object.getPrototypeOf(keywords)) {
6600            keywords.__proto__ = null;
6601        }
6602        this.$keywordList = Object.keys(keywords);
6603        map = null;
6604        return ignoreCase
6605            ? function(value) {return keywords[value.toLowerCase()] || defaultToken; }
6606            : function(value) {return keywords[value] || defaultToken; };
6607    };
6608
6609    this.getKeywords = function() {
6610        return this.$keywords;
6611    };
6612
6613}).call(TextHighlightRules.prototype);
6614
6615exports.TextHighlightRules = TextHighlightRules;
6616});
6617
6618define("ace/mode/behaviour",["require","exports","module"], function(require, exports, module) {
6619"use strict";
6620
6621var Behaviour = function() {
6622   this.$behaviours = {};
6623};
6624
6625(function () {
6626
6627    this.add = function (name, action, callback) {
6628        switch (undefined) {
6629          case this.$behaviours:
6630              this.$behaviours = {};
6631          case this.$behaviours[name]:
6632              this.$behaviours[name] = {};
6633        }
6634        this.$behaviours[name][action] = callback;
6635    };
6636    
6637    this.addBehaviours = function (behaviours) {
6638        for (var key in behaviours) {
6639            for (var action in behaviours[key]) {
6640                this.add(key, action, behaviours[key][action]);
6641            }
6642        }
6643    };
6644    
6645    this.remove = function (name) {
6646        if (this.$behaviours && this.$behaviours[name]) {
6647            delete this.$behaviours[name];
6648        }
6649    };
6650    
6651    this.inherit = function (mode, filter) {
6652        if (typeof mode === "function") {
6653            var behaviours = new mode().getBehaviours(filter);
6654        } else {
6655            var behaviours = mode.getBehaviours(filter);
6656        }
6657        this.addBehaviours(behaviours);
6658    };
6659    
6660    this.getBehaviours = function (filter) {
6661        if (!filter) {
6662            return this.$behaviours;
6663        } else {
6664            var ret = {};
6665            for (var i = 0; i < filter.length; i++) {
6666                if (this.$behaviours[filter[i]]) {
6667                    ret[filter[i]] = this.$behaviours[filter[i]];
6668                }
6669            }
6670            return ret;
6671        }
6672    };
6673
6674}).call(Behaviour.prototype);
6675
6676exports.Behaviour = Behaviour;
6677});
6678
6679define("ace/token_iterator",["require","exports","module","ace/range"], function(require, exports, module) {
6680"use strict";
6681
6682var Range = require("./range").Range;
6683var TokenIterator = function(session, initialRow, initialColumn) {
6684    this.$session = session;
6685    this.$row = initialRow;
6686    this.$rowTokens = session.getTokens(initialRow);
6687
6688    var token = session.getTokenAt(initialRow, initialColumn);
6689    this.$tokenIndex = token ? token.index : -1;
6690};
6691
6692(function() { 
6693    this.stepBackward = function() {
6694        this.$tokenIndex -= 1;
6695        
6696        while (this.$tokenIndex < 0) {
6697            this.$row -= 1;
6698            if (this.$row < 0) {
6699                this.$row = 0;
6700                return null;
6701            }
6702                
6703            this.$rowTokens = this.$session.getTokens(this.$row);
6704            this.$tokenIndex = this.$rowTokens.length - 1;
6705        }
6706            
6707        return this.$rowTokens[this.$tokenIndex];
6708    };   
6709    this.stepForward = function() {
6710        this.$tokenIndex += 1;
6711        var rowCount;
6712        while (this.$tokenIndex >= this.$rowTokens.length) {
6713            this.$row += 1;
6714            if (!rowCount)
6715                rowCount = this.$session.getLength();
6716            if (this.$row >= rowCount) {
6717                this.$row = rowCount - 1;
6718                return null;
6719            }
6720
6721            this.$rowTokens = this.$session.getTokens(this.$row);
6722            this.$tokenIndex = 0;
6723        }
6724            
6725        return this.$rowTokens[this.$tokenIndex];
6726    };      
6727    this.getCurrentToken = function () {
6728        return this.$rowTokens[this.$tokenIndex];
6729    };      
6730    this.getCurrentTokenRow = function () {
6731        return this.$row;
6732    };     
6733    this.getCurrentTokenColumn = function() {
6734        var rowTokens = this.$rowTokens;
6735        var tokenIndex = this.$tokenIndex;
6736        var column = rowTokens[tokenIndex].start;
6737        if (column !== undefined)
6738            return column;
6739            
6740        column = 0;
6741        while (tokenIndex > 0) {
6742            tokenIndex -= 1;
6743            column += rowTokens[tokenIndex].value.length;
6744        }
6745        
6746        return column;  
6747    };
6748    this.getCurrentTokenPosition = function() {
6749        return {row: this.$row, column: this.getCurrentTokenColumn()};
6750    };
6751    this.getCurrentTokenRange = function() {
6752        var token = this.$rowTokens[this.$tokenIndex];
6753        var column = this.getCurrentTokenColumn();
6754        return new Range(this.$row, column, this.$row, column + token.value.length);
6755    };
6756    
6757}).call(TokenIterator.prototype);
6758
6759exports.TokenIterator = TokenIterator;
6760});
6761
6762define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"], function(require, exports, module) {
6763"use strict";
6764
6765var oop = require("../../lib/oop");
6766var Behaviour = require("../behaviour").Behaviour;
6767var TokenIterator = require("../../token_iterator").TokenIterator;
6768var lang = require("../../lib/lang");
6769
6770var SAFE_INSERT_IN_TOKENS =
6771    ["text", "paren.rparen", "punctuation.operator"];
6772var SAFE_INSERT_BEFORE_TOKENS =
6773    ["text", "paren.rparen", "punctuation.operator", "comment"];
6774
6775var context;
6776var contextCache = {};
6777var defaultQuotes = {'"' : '"', "'" : "'"};
6778
6779var initContext = function(editor) {
6780    var id = -1;
6781    if (editor.multiSelect) {
6782        id = editor.selection.index;
6783        if (contextCache.rangeCount != editor.multiSelect.rangeCount)
6784            contextCache = {rangeCount: editor.multiSelect.rangeCount};
6785    }
6786    if (contextCache[id])
6787        return context = contextCache[id];
6788    context = contextCache[id] = {
6789        autoInsertedBrackets: 0,
6790        autoInsertedRow: -1,
6791        autoInsertedLineEnd: "",
6792        maybeInsertedBrackets: 0,
6793        maybeInsertedRow: -1,
6794        maybeInsertedLineStart: "",
6795        maybeInsertedLineEnd: ""
6796    };
6797};
6798
6799var getWrapped = function(selection, selected, opening, closing) {
6800    var rowDiff = selection.end.row - selection.start.row;
6801    return {
6802        text: opening + selected + closing,
6803        selection: [
6804                0,
6805                selection.start.column + 1,
6806                rowDiff,
6807                selection.end.column + (rowDiff ? 0 : 1)
6808            ]
6809    };
6810};
6811
6812var CstyleBehaviour = function(options) {
6813    this.add("braces", "insertion", function(state, action, editor, session, text) {
6814        var cursor = editor.getCursorPosition();
6815        var line = session.doc.getLine(cursor.row);
6816        if (text == '{') {
6817            initContext(editor);
6818            var selection = editor.getSelectionRange();
6819            var selected = session.doc.getTextRange(selection);
6820            if (selected !== "" && selected !== "{" && editor.getWrapBehavioursEnabled()) {
6821                return getWrapped(selection, selected, '{', '}');
6822            } else if (CstyleBehaviour.isSaneInsertion(editor, session)) {
6823                if (/[\]\}\)]/.test(line[cursor.column]) || editor.inMultiSelectMode || options && options.braces) {
6824                    CstyleBehaviour.recordAutoInsert(editor, session, "}");
6825                    return {
6826                        text: '{}',
6827                        selection: [1, 1]
6828                    };
6829                } else {
6830                    CstyleBehaviour.recordMaybeInsert(editor, session, "{");
6831                    return {
6832                        text: '{',
6833                        selection: [1, 1]
6834                    };
6835                }
6836            }
6837        } else if (text == '}') {
6838            initContext(editor);
6839            var rightChar = line.substring(cursor.column, cursor.column + 1);
6840            if (rightChar == '}') {
6841                var matching = session.$findOpeningBracket('}', {column: cursor.column + 1, row: cursor.row});
6842                if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) {
6843                    CstyleBehaviour.popAutoInsertedClosing();
6844                    return {
6845                        text: '',
6846                        selection: [1, 1]
6847                    };
6848                }
6849            }
6850        } else if (text == "\n" || text == "\r\n") {
6851            initContext(editor);
6852            var closing = "";
6853            if (CstyleBehaviour.isMaybeInsertedClosing(cursor, line)) {
6854                closing = lang.stringRepeat("}", context.maybeInsertedBrackets);
6855                CstyleBehaviour.clearMaybeInsertedClosing();
6856            }
6857            var rightChar = line.substring(cursor.column, cursor.column + 1);
6858            if (rightChar === '}') {
6859                var openBracePos = session.findMatchingBracket({row: cursor.row, column: cursor.column+1}, '}');
6860                if (!openBracePos)
6861                     return null;
6862                var next_indent = this.$getIndent(session.getLine(openBracePos.row));
6863            } else if (closing) {
6864                var next_indent = this.$getIndent(line);
6865            } else {
6866                CstyleBehaviour.clearMaybeInsertedClosing();
6867                return;
6868            }
6869            var indent = next_indent + session.getTabString();
6870
6871            return {
6872                text: '\n' + indent + '\n' + next_indent + closing,
6873                selection: [1, indent.length, 1, indent.length]
6874            };
6875        } else {
6876            CstyleBehaviour.clearMaybeInsertedClosing();
6877        }
6878    });
6879
6880    this.add("braces", "deletion", function(state, action, editor, session, range) {
6881        var selected = session.doc.getTextRange(range);
6882        if (!range.isMultiLine() && selected == '{') {
6883            initContext(editor);
6884            var line = session.doc.getLine(range.start.row);
6885            var rightChar = line.substring(range.end.column, range.end.column + 1);
6886            if (rightChar == '}') {
6887                range.end.column++;
6888                return range;
6889            } else {
6890                context.maybeInsertedBrackets--;
6891            }
6892        }
6893    });
6894
6895    this.add("parens", "insertion", function(state, action, editor, session, text) {
6896        if (text == '(') {
6897            initContext(editor);
6898            var selection = editor.getSelectionRange();
6899            var selected = session.doc.getTextRange(selection);
6900            if (selected !== "" && editor.getWrapBehavioursEnabled()) {
6901                return getWrapped(selection, selected, '(', ')');
6902            } else if (CstyleBehaviour.isSaneInsertion(editor, session)) {
6903                CstyleBehaviour.recordAutoInsert(editor, session, ")");
6904                return {
6905                    text: '()',
6906                    selection: [1, 1]
6907                };
6908            }
6909        } else if (text == ')') {
6910            initContext(editor);
6911            var cursor = editor.getCursorPosition();
6912            var line = session.doc.getLine(cursor.row);
6913            var rightChar = line.substring(cursor.column, cursor.column + 1);
6914            if (rightChar == ')') {
6915                var matching = session.$findOpeningBracket(')', {column: cursor.column + 1, row: cursor.row});
6916                if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) {
6917                    CstyleBehaviour.popAutoInsertedClosing();
6918                    return {
6919                        text: '',
6920                        selection: [1, 1]
6921                    };
6922                }
6923            }
6924        }
6925    });
6926
6927    this.add("parens", "deletion", function(state, action, editor, session, range) {
6928        var selected = session.doc.getTextRange(range);
6929        if (!range.isMultiLine() && selected == '(') {
6930            initContext(editor);
6931            var line = session.doc.getLine(range.start.row);
6932            var rightChar = line.substring(range.start.column + 1, range.start.column + 2);
6933            if (rightChar == ')') {
6934                range.end.column++;
6935                return range;
6936            }
6937        }
6938    });
6939
6940    this.add("brackets", "insertion", function(state, action, editor, session, text) {
6941        if (text == '[') {
6942            initContext(editor);
6943            var selection = editor.getSelectionRange();
6944            var selected = session.doc.getTextRange(selection);
6945            if (selected !== "" && editor.getWrapBehavioursEnabled()) {
6946                return getWrapped(selection, selected, '[', ']');
6947            } else if (CstyleBehaviour.isSaneInsertion(editor, session)) {
6948                CstyleBehaviour.recordAutoInsert(editor, session, "]");
6949                return {
6950                    text: '[]',
6951                    selection: [1, 1]
6952                };
6953            }
6954        } else if (text == ']') {
6955            initContext(editor);
6956            var cursor = editor.getCursorPosition();
6957            var line = session.doc.getLine(cursor.row);
6958            var rightChar = line.substring(cursor.column, cursor.column + 1);
6959            if (rightChar == ']') {
6960                var matching = session.$findOpeningBracket(']', {column: cursor.column + 1, row: cursor.row});
6961                if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) {
6962                    CstyleBehaviour.popAutoInsertedClosing();
6963                    return {
6964                        text: '',
6965                        selection: [1, 1]
6966                    };
6967                }
6968            }
6969        }
6970    });
6971
6972    this.add("brackets", "deletion", function(state, action, editor, session, range) {
6973        var selected = session.doc.getTextRange(range);
6974        if (!range.isMultiLine() && selected == '[') {
6975            initContext(editor);
6976            var line = session.doc.getLine(range.start.row);
6977            var rightChar = line.substring(range.start.column + 1, range.start.column + 2);
6978            if (rightChar == ']') {
6979                range.end.column++;
6980                return range;
6981            }
6982        }
6983    });
6984
6985    this.add("string_dquotes", "insertion", function(state, action, editor, session, text) {
6986        var quotes = session.$mode.$quotes || defaultQuotes;
6987        if (text.length == 1 && quotes[text]) {
6988            if (this.lineCommentStart && this.lineCommentStart.indexOf(text) != -1) 
6989                return;
6990            initContext(editor);
6991            var quote = text;
6992            var selection = editor.getSelectionRange();
6993            var selected = session.doc.getTextRange(selection);
6994            if (selected !== "" && (selected.length != 1 || !quotes[selected]) && editor.getWrapBehavioursEnabled()) {
6995                return getWrapped(selection, selected, quote, quote);
6996            } else if (!selected) {
6997                var cursor = editor.getCursorPosition();
6998                var line = session.doc.getLine(cursor.row);
6999                var leftChar = line.substring(cursor.column-1, cursor.column);
7000                var rightChar = line.substring(cursor.column, cursor.column + 1);
7001                
7002                var token = session.getTokenAt(cursor.row, cursor.column);
7003                var rightToken = session.getTokenAt(cursor.row, cursor.column + 1);
7004                if (leftChar == "\\" && token && /escape/.test(token.type))
7005                    return null;
7006                
7007                var stringBefore = token && /string|escape/.test(token.type);
7008                var stringAfter = !rightToken || /string|escape/.test(rightToken.type);
7009                
7010                var pair;
7011                if (rightChar == quote) {
7012                    pair = stringBefore !== stringAfter;
7013                    if (pair && /string\.end/.test(rightToken.type))
7014                        pair = false;
7015                } else {
7016                    if (stringBefore && !stringAfter)
7017                        return null; // wrap string with different quote
7018                    if (stringBefore && stringAfter)
7019                        return null; // do not pair quotes inside strings
7020                    var wordRe = session.$mode.tokenRe;
7021                    wordRe.lastIndex = 0;
7022                    var isWordBefore = wordRe.test(leftChar);
7023                    wordRe.lastIndex = 0;
7024                    var isWordAfter = wordRe.test(leftChar);
7025                    if (isWordBefore || isWordAfter)
7026                        return null; // before or after alphanumeric
7027                    if (rightChar && !/[\s;,.})\]\\]/.test(rightChar))
7028                        return null; // there is rightChar and it isn't closing
7029                    pair = true;
7030                }
7031                return {
7032                    text: pair ? quote + quote : "",
7033                    selection: [1,1]
7034                };
7035            }
7036        }
7037    });
7038
7039    this.add("string_dquotes", "deletion", function(state, action, editor, session, range) {
7040        var selected = session.doc.getTextRange(range);
7041        if (!range.isMultiLine() && (selected == '"' || selected == "'")) {
7042            initContext(editor);
7043            var line = session.doc.getLine(range.start.row);
7044            var rightChar = line.substring(range.start.column + 1, range.start.column + 2);
7045            if (rightChar == selected) {
7046                range.end.column++;
7047                return range;
7048            }
7049        }
7050    });
7051
7052};
7053
7054    
7055CstyleBehaviour.isSaneInsertion = function(editor, session) {
7056    var cursor = editor.getCursorPosition();
7057    var iterator = new TokenIterator(session, cursor.row, cursor.column);
7058    if (!this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS)) {
7059        var iterator2 = new TokenIterator(session, cursor.row, cursor.column + 1);
7060        if (!this.$matchTokenType(iterator2.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS))
7061            return false;
7062    }
7063    iterator.stepForward();
7064    return iterator.getCurrentTokenRow() !== cursor.row ||
7065        this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_BEFORE_TOKENS);
7066};
7067
7068CstyleBehaviour.$matchTokenType = function(token, types) {
7069    return types.indexOf(token.type || token) > -1;
7070};
7071
7072CstyleBehaviour.recordAutoInsert = function(editor, session, bracket) {
7073    var cursor = editor.getCursorPosition();
7074    var line = session.doc.getLine(cursor.row);
7075    if (!this.isAutoInsertedClosing(cursor, line, context.autoInsertedLineEnd[0]))
7076        context.autoInsertedBrackets = 0;
7077    context.autoInsertedRow = cursor.row;
7078    context.autoInsertedLineEnd = bracket + line.substr(cursor.column);
7079    context.autoInsertedBrackets++;
7080};
7081
7082CstyleBehaviour.recordMaybeInsert = function(editor, session, bracket) {
7083    var cursor = editor.getCursorPosition();
7084    var line = session.doc.getLine(cursor.row);
7085    if (!this.isMaybeInsertedClosing(cursor, line))
7086        context.maybeInsertedBrackets = 0;
7087    context.maybeInsertedRow = cursor.row;
7088    context.maybeInsertedLineStart = line.substr(0, cursor.column) + bracket;
7089    context.maybeInsertedLineEnd = line.substr(cursor.column);
7090    context.maybeInsertedBrackets++;
7091};
7092
7093CstyleBehaviour.isAutoInsertedClosing = function(cursor, line, bracket) {
7094    return context.autoInsertedBrackets > 0 &&
7095        cursor.row === context.autoInsertedRow &&
7096        bracket === context.autoInsertedLineEnd[0] &&
7097        line.substr(cursor.column) === context.autoInsertedLineEnd;
7098};
7099
7100CstyleBehaviour.isMaybeInsertedClosing = function(cursor, line) {
7101    return context.maybeInsertedBrackets > 0 &&
7102        cursor.row === context.maybeInsertedRow &&
7103        line.substr(cursor.column) === context.maybeInsertedLineEnd &&
7104        line.substr(0, cursor.column) == context.maybeInsertedLineStart;
7105};
7106
7107CstyleBehaviour.popAutoInsertedClosing = function() {
7108    context.autoInsertedLineEnd = context.autoInsertedLineEnd.substr(1);
7109    context.autoInsertedBrackets--;
7110};
7111
7112CstyleBehaviour.clearMaybeInsertedClosing = function() {
7113    if (context) {
7114        context.maybeInsertedBrackets = 0;
7115        context.maybeInsertedRow = -1;
7116    }
7117};
7118
7119
7120
7121oop.inherits(CstyleBehaviour, Behaviour);
7122
7123exports.CstyleBehaviour = CstyleBehaviour;
7124});
7125
7126define("ace/unicode",["require","exports","module"], function(require, exports, module) {
7127"use strict";
7128var wordChars = [48,9,8,25,5,0,2,25,48,0,11,0,5,0,6,22,2,30,2,457,5,11,15,4,8,0,2,0,18,116,2,1,3,3,9,0,2,2,2,0,2,19,2,82,2,138,2,4,3,155,12,37,3,0,8,38,10,44,2,0,2,1,2,1,2,0,9,26,6,2,30,10,7,61,2,9,5,101,2,7,3,9,2,18,3,0,17,58,3,100,15,53,5,0,6,45,211,57,3,18,2,5,3,11,3,9,2,1,7,6,2,2,2,7,3,1,3,21,2,6,2,0,4,3,3,8,3,1,3,3,9,0,5,1,2,4,3,11,16,2,2,5,5,1,3,21,2,6,2,1,2,1,2,1,3,0,2,4,5,1,3,2,4,0,8,3,2,0,8,15,12,2,2,8,2,2,2,21,2,6,2,1,2,4,3,9,2,2,2,2,3,0,16,3,3,9,18,2,2,7,3,1,3,21,2,6,2,1,2,4,3,8,3,1,3,2,9,1,5,1,2,4,3,9,2,0,17,1,2,5,4,2,2,3,4,1,2,0,2,1,4,1,4,2,4,11,5,4,4,2,2,3,3,0,7,0,15,9,18,2,2,7,2,2,2,22,2,9,2,4,4,7,2,2,2,3,8,1,2,1,7,3,3,9,19,1,2,7,2,2,2,22,2,9,2,4,3,8,2,2,2,3,8,1,8,0,2,3,3,9,19,1,2,7,2,2,2,22,2,15,4,7,2,2,2,3,10,0,9,3,3,9,11,5,3,1,2,17,4,23,2,8,2,0,3,6,4,0,5,5,2,0,2,7,19,1,14,57,6,14,2,9,40,1,2,0,3,1,2,0,3,0,7,3,2,6,2,2,2,0,2,0,3,1,2,12,2,2,3,4,2,0,2,5,3,9,3,1,35,0,24,1,7,9,12,0,2,0,2,0,5,9,2,35,5,19,2,5,5,7,2,35,10,0,58,73,7,77,3,37,11,42,2,0,4,328,2,3,3,6,2,0,2,3,3,40,2,3,3,32,2,3,3,6,2,0,2,3,3,14,2,56,2,3,3,66,5,0,33,15,17,84,13,619,3,16,2,25,6,74,22,12,2,6,12,20,12,19,13,12,2,2,2,1,13,51,3,29,4,0,5,1,3,9,34,2,3,9,7,87,9,42,6,69,11,28,4,11,5,11,11,39,3,4,12,43,5,25,7,10,38,27,5,62,2,28,3,10,7,9,14,0,89,75,5,9,18,8,13,42,4,11,71,55,9,9,4,48,83,2,2,30,14,230,23,280,3,5,3,37,3,5,3,7,2,0,2,0,2,0,2,30,3,52,2,6,2,0,4,2,2,6,4,3,3,5,5,12,6,2,2,6,67,1,20,0,29,0,14,0,17,4,60,12,5,0,4,11,18,0,5,0,3,9,2,0,4,4,7,0,2,0,2,0,2,3,2,10,3,3,6,4,5,0,53,1,2684,46,2,46,2,132,7,6,15,37,11,53,10,0,17,22,10,6,2,6,2,6,2,6,2,6,2,6,2,6,2,6,2,31,48,0,470,1,36,5,2,4,6,1,5,85,3,1,3,2,2,89,2,3,6,40,4,93,18,23,57,15,513,6581,75,20939,53,1164,68,45,3,268,4,27,21,31,3,13,13,1,2,24,9,69,11,1,38,8,3,102,3,1,111,44,25,51,13,68,12,9,7,23,4,0,5,45,3,35,13,28,4,64,15,10,39,54,10,13,3,9,7,22,4,1,5,66,25,2,227,42,2,1,3,9,7,11171,13,22,5,48,8453,301,3,61,3,105,39,6,13,4,6,11,2,12,2,4,2,0,2,1,2,1,2,107,34,362,19,63,3,53,41,11,5,15,17,6,13,1,25,2,33,4,2,134,20,9,8,25,5,0,2,25,12,88,4,5,3,5,3,5,3,2];
7129
7130var code = 0;
7131var str = [];
7132for (var i = 0; i < wordChars.length; i += 2) {
7133    str.push(code += wordChars[i]);
7134    if (wordChars[i + 1])
7135        str.push(45, code += wordChars[i + 1]);
7136}
7137
7138exports.wordChars = String.fromCharCode.apply(null, str);
7139
7140});
7141
7142define("ace/mode/text",["require","exports","module","ace/tokenizer","ace/mode/text_highlight_rules","ace/mode/behaviour/cstyle","ace/unicode","ace/lib/lang","ace/token_iterator","ace/range"], function(require, exports, module) {
7143"use strict";
7144
7145var Tokenizer = require("../tokenizer").Tokenizer;
7146var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
7147var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour;
7148var unicode = require("../unicode");
7149var lang = require("../lib/lang");
7150var TokenIterator = require("../token_iterator").TokenIterator;
7151var Range = require("../range").Range;
7152
7153var Mode = function() {
7154    this.HighlightRules = TextHighlightRules;
7155};
7156
7157(function() {
7158    this.$defaultBehaviour = new CstyleBehaviour();
7159
7160    this.tokenRe = new RegExp("^[" + unicode.wordChars + "\\$_]+", "g");
7161
7162    this.nonTokenRe = new RegExp("^(?:[^" + unicode.wordChars + "\\$_]|\\s])+", "g");
7163
7164    this.getTokenizer = function() {
7165        if (!this.$tokenizer) {
7166            this.$highlightRules = this.$highlightRules || new this.HighlightRules(this.$highlightRuleConfig);
7167            this.$tokenizer = new Tokenizer(this.$highlightRules.getRules());
7168        }
7169        return this.$tokenizer;
7170    };
7171
7172    this.lineCommentStart = "";
7173    this.blockComment = "";
7174
7175    this.toggleCommentLines = function(state, session, startRow, endRow) {
7176        var doc = session.doc;
7177
7178        var ignoreBlankLines = true;
7179        var shouldRemove = true;
7180        var minIndent = Infinity;
7181        var tabSize = session.getTabSize();
7182        var insertAtTabStop = false;
7183
7184        if (!this.lineCommentStart) {
7185            if (!this.blockComment)
7186                return false;
7187            var lineCommentStart = this.blockComment.start;
7188            var lineCommentEnd = this.blockComment.end;
7189            var regexpStart = new RegExp("^(\\s*)(?:" + lang.escapeRegExp(lineCommentStart) + ")");
7190            var regexpEnd = new RegExp("(?:" + lang.escapeRegExp(lineCommentEnd) + ")\\s*$");
7191
7192            var comment = function(line, i) {
7193                if (testRemove(line, i))
7194                    return;
7195                if (!ignoreBlankLines || /\S/.test(line)) {
7196                    doc.insertInLine({row: i, column: line.length}, lineCommentEnd);
7197                    doc.insertInLine({row: i, column: minIndent}, lineCommentStart);
7198                }
7199            };
7200
7201            var uncomment = function(line, i) {
7202                var m;
7203                if (m = line.match(regexpEnd))
7204                    doc.removeInLine(i, line.length - m[0].length, line.length);
7205                if (m = line.match(regexpStart))
7206                    doc.removeInLine(i, m[1].length, m[0].length);
7207            };
7208
7209            var testRemove = function(line, row) {
7210                if (regexpStart.test(line))
7211                    return true;
7212                var tokens = session.getTokens(row);
7213                for (var i = 0; i < tokens.length; i++) {
7214                    if (tokens[i].type === "comment")
7215                        return true;
7216                }
7217            };
7218        } else {
7219            if (Array.isArray(this.lineCommentStart)) {
7220                var regexpStart = this.lineCommentStart.map(lang.escapeRegExp).join("|");
7221                var lineCommentStart = this.lineCommentStart[0];
7222            } else {
7223                var regexpStart = lang.escapeRegExp(this.lineCommentStart);
7224                var lineCommentStart = this.lineCommentStart;
7225            }
7226            regexpStart = new RegExp("^(\\s*)(?:" + regexpStart + ") ?");
7227            
7228            insertAtTabStop = session.getUseSoftTabs();
7229
7230            var uncomment = function(line, i) {
7231                var m = line.match(regexpStart);
7232                if (!m) return;
7233                var start = m[1].length, end = m[0].length;
7234                if (!shouldInsertSpace(line, start, end) && m[0][end - 1] == " ")
7235                    end--;
7236                doc.removeInLine(i, start, end);
7237            };
7238            var commentWithSpace = lineCommentStart + " ";
7239            var comment = function(line, i) {
7240                if (!ignoreBlankLines || /\S/.test(line)) {
7241                    if (shouldInsertSpace(line, minIndent, minIndent))
7242                        doc.insertInLine({row: i, column: minIndent}, commentWithSpace);
7243                    else
7244                        doc.insertInLine({row: i, column: minIndent}, lineCommentStart);
7245                }
7246            };
7247            var testRemove = function(line, i) {
7248                return regexpStart.test(line);
7249            };
7250            
7251            var shouldInsertSpace = function(line, before, after) {
7252                var spaces = 0;
7253                while (before-- && line.charAt(before) == " ")
7254                    spaces++;
7255                if (spaces % tabSize != 0)
7256                    return false;
7257                var spaces = 0;
7258                while (line.charAt(after++) == " ")
7259                    spaces++;
7260                if (tabSize > 2)
7261                    return spaces % tabSize != tabSize - 1;
7262                else
7263                    return spaces % tabSize == 0;
7264            };
7265        }
7266
7267        function iter(fun) {
7268            for (var i = startRow; i <= endRow; i++)
7269                fun(doc.getLine(i), i);
7270        }
7271
7272
7273        var minEmptyLength = Infinity;
7274        iter(function(line, i) {
7275            var indent = line.search(/\S/);
7276            if (indent !== -1) {
7277                if (indent < minIndent)
7278                    minIndent = indent;
7279                if (shouldRemove && !testRemove(line, i))
7280                    shouldRemove = false;
7281            } else if (minEmptyLength > line.length) {
7282                minEmptyLength = line.length;
7283            }
7284        });
7285
7286        if (minIndent == Infinity) {
7287            minIndent = minEmptyLength;
7288            ignoreBlankLines = false;
7289            shouldRemove = false;
7290        }
7291
7292        if (insertAtTabStop && minIndent % tabSize != 0)
7293            minIndent = Math.floor(minIndent / tabSize) * tabSize;
7294
7295        iter(shouldRemove ? uncomment : comment);
7296    };
7297
7298    this.toggleBlockComment = function(state, session, range, cursor) {
7299        var comment = this.blockComment;
7300        if (!comment)
7301            return;
7302        if (!comment.start && comment[0])
7303            comment = comment[0];
7304
7305        var iterator = new TokenIterator(session, cursor.row, cursor.column);
7306        var token = iterator.getCurrentToken();
7307
7308        var sel = session.selection;
7309        var initialRange = session.selection.toOrientedRange();
7310        var startRow, colDiff;
7311
7312        if (token && /comment/.test(token.type)) {
7313            var startRange, endRange;
7314            while (token && /comment/.test(token.type)) {
7315                var i = token.value.indexOf(comment.start);
7316                if (i != -1) {
7317                    var row = iterator.getCurrentTokenRow();
7318                    var column = iterator.getCurrentTokenColumn() + i;
7319                    startRange = new Range(row, column, row, column + comment.start.length);
7320                    break;
7321                }
7322                token = iterator.stepBackward();
7323            }
7324
7325            var iterator = new TokenIterator(session, cursor.row, cursor.column);
7326            var token = iterator.getCurrentToken();
7327            while (token && /comment/.test(token.type)) {
7328                var i = token.value.indexOf(comment.end);
7329                if (i != -1) {
7330                    var row = iterator.getCurrentTokenRow();
7331                    var column = iterator.getCurrentTokenColumn() + i;
7332                    endRange = new Range(row, column, row, column + comment.end.length);
7333                    break;
7334                }
7335                token = iterator.stepForward();
7336            }
7337            if (endRange)
7338                session.remove(endRange);
7339            if (startRange) {
7340                session.remove(startRange);
7341                startRow = startRange.start.row;
7342                colDiff = -comment.start.length;
7343            }
7344        } else {
7345            colDiff = comment.start.length;
7346            startRow = range.start.row;
7347            session.insert(range.end, comment.end);
7348            session.insert(range.start, comment.start);
7349        }
7350        if (initialRange.start.row == startRow)
7351            initialRange.start.column += colDiff;
7352        if (initialRange.end.row == startRow)
7353            initialRange.end.column += colDiff;
7354        session.selection.fromOrientedRange(initialRange);
7355    };
7356
7357    this.getNextLineIndent = function(state, line, tab) {
7358        return this.$getIndent(line);
7359    };
7360
7361    this.checkOutdent = function(state, line, input) {
7362        return false;
7363    };
7364
7365    this.autoOutdent = function(state, doc, row) {
7366    };
7367
7368    this.$getIndent = function(line) {
7369        return line.match(/^\s*/)[0];
7370    };
7371
7372    this.createWorker = function(session) {
7373        return null;
7374    };
7375
7376    this.createModeDelegates = function (mapping) {
7377        this.$embeds = [];
7378        this.$modes = {};
7379        for (var i in mapping) {
7380            if (mapping[i]) {
7381                this.$embeds.push(i);
7382                this.$modes[i] = new mapping[i]();
7383            }
7384        }
7385
7386        var delegations = ["toggleBlockComment", "toggleCommentLines", "getNextLineIndent", 
7387            "checkOutdent", "autoOutdent", "transformAction", "getCompletions"];
7388
7389        for (var i = 0; i < delegations.length; i++) {
7390            (function(scope) {
7391              var functionName = delegations[i];
7392              var defaultHandler = scope[functionName];
7393              scope[delegations[i]] = function() {
7394                  return this.$delegator(functionName, arguments, defaultHandler);
7395              };
7396            }(this));
7397        }
7398    };
7399
7400    this.$delegator = function(method, args, defaultHandler) {
7401        var state = args[0];
7402        if (typeof state != "string")
7403            state = state[0];
7404        for (var i = 0; i < this.$embeds.length; i++) {
7405            if (!this.$modes[this.$embeds[i]]) continue;
7406
7407            var split = state.split(this.$embeds[i]);
7408            if (!split[0] && split[1]) {
7409                args[0] = split[1];
7410                var mode = this.$modes[this.$embeds[i]];
7411                return mode[method].apply(mode, args);
7412            }
7413        }
7414        var ret = defaultHandler.apply(this, args);
7415        return defaultHandler ? ret : undefined;
7416    };
7417
7418    this.transformAction = function(state, action, editor, session, param) {
7419        if (this.$behaviour) {
7420            var behaviours = this.$behaviour.getBehaviours();
7421            for (var key in behaviours) {
7422                if (behaviours[key][action]) {
7423                    var ret = behaviours[key][action].apply(this, arguments);
7424                    if (ret) {
7425                        return ret;
7426                    }
7427                }
7428            }
7429        }
7430    };
7431    
7432    this.getKeywords = function(append) {
7433        if (!this.completionKeywords) {
7434            var rules = this.$tokenizer.rules;
7435            var completionKeywords = [];
7436            for (var rule in rules) {
7437                var ruleItr = rules[rule];
7438                for (var r = 0, l = ruleItr.length; r < l; r++) {
7439                    if (typeof ruleItr[r].token === "string") {
7440                        if (/keyword|support|storage/.test(ruleItr[r].token))
7441                            completionKeywords.push(ruleItr[r].regex);
7442                    }
7443                    else if (typeof ruleItr[r].token === "object") {
7444                        for (var a = 0, aLength = ruleItr[r].token.length; a < aLength; a++) {    
7445                            if (/keyword|support|storage/.test(ruleItr[r].token[a])) {
7446                                var rule = ruleItr[r].regex.match(/\(.+?\)/g)[a];
7447                                completionKeywords.push(rule.substr(1, rule.length - 2));
7448                            }
7449                        }
7450                    }
7451                }
7452            }
7453            this.completionKeywords = completionKeywords;
7454        }
7455        if (!append)
7456            return this.$keywordList;
7457        return completionKeywords.concat(this.$keywordList || []);
7458    };
7459    
7460    this.$createKeywordList = function() {
7461        if (!this.$highlightRules)
7462            this.getTokenizer();
7463        return this.$keywordList = this.$highlightRules.$keywordList || [];
7464    };
7465
7466    this.getCompletions = function(state, session, pos, prefix) {
7467        var keywords = this.$keywordList || this.$createKeywordList();
7468        return keywords.map(function(word) {
7469            return {
7470                name: word,
7471                value: word,
7472                score: 0,
7473                meta: "keyword"
7474            };
7475        });
7476    };
7477
7478    this.$id = "ace/mode/text";
7479}).call(Mode.prototype);
7480
7481exports.Mode = Mode;
7482});
7483
7484define("ace/apply_delta",["require","exports","module"], function(require, exports, module) {
7485"use strict";
7486
7487function throwDeltaError(delta, errorText){
7488    console.log("Invalid Delta:", delta);
7489    throw "Invalid Delta: " + errorText;
7490}
7491
7492function positionInDocument(docLines, position) {
7493    return position.row    >= 0 && position.row    <  docLines.length &&
7494           position.column >= 0 && position.column <= docLines[position.row].length;
7495}
7496
7497function validateDelta(docLines, delta) {
7498    if (delta.action != "insert" && delta.action != "remove")
7499        throwDeltaError(delta, "delta.action must be 'insert' or 'remove'");
7500    if (!(delta.lines instanceof Array))
7501        throwDeltaError(delta, "delta.lines must be an Array");
7502    if (!delta.start || !delta.end)
7503       throwDeltaError(delta, "delta.start/end must be an present");
7504    var start = delta.start;
7505    if (!positionInDocument(docLines, delta.start))
7506        throwDeltaError(delta, "delta.start must be contained in document");
7507    var end = delta.end;
7508    if (delta.action == "remove" && !positionInDocument(docLines, end))
7509        throwDeltaError(delta, "delta.end must contained in document for 'remove' actions");
7510    var numRangeRows = end.row - start.row;
7511    var numRangeLastLineChars = (end.column - (numRangeRows == 0 ? start.column : 0));
7512    if (numRangeRows != delta.lines.length - 1 || delta.lines[numRangeRows].length != numRangeLastLineChars)
7513        throwDeltaError(delta, "delta.range must match delta lines");
7514}
7515
7516exports.applyDelta = function(docLines, delta, doNotValidate) {
7517    
7518    var row = delta.start.row;
7519    var startColumn = delta.start.column;
7520    var line = docLines[row] || "";
7521    switch (delta.action) {
7522        case "insert":
7523            var lines = delta.lines;
7524            if (lines.length === 1) {
7525                docLines[row] = line.substring(0, startColumn) + delta.lines[0] + line.substring(startColumn);
7526            } else {
7527                var args = [row, 1].concat(delta.lines);
7528                docLines.splice.apply(docLines, args);
7529                docLines[row] = line.substring(0, startColumn) + docLines[row];
7530                docLines[row + delta.lines.length - 1] += line.substring(startColumn);
7531            }
7532            break;
7533        case "remove":
7534            var endColumn = delta.end.column;
7535            var endRow = delta.end.row;
7536            if (row === endRow) {
7537                docLines[row] = line.substring(0, startColumn) + line.substring(endColumn);
7538            } else {
7539                docLines.splice(
7540                    row, endRow - row + 1,
7541                    line.substring(0, startColumn) + docLines[endRow].substring(endColumn)
7542                );
7543            }
7544            break;
7545    }
7546};
7547});
7548
7549define("ace/anchor",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"], function(require, exports, module) {
7550"use strict";
7551
7552var oop = require("./lib/oop");
7553var EventEmitter = require("./lib/event_emitter").EventEmitter;
7554
7555var Anchor = exports.Anchor = function(doc, row, column) {
7556    this.$onChange = this.onChange.bind(this);
7557    this.attach(doc);
7558    
7559    if (typeof column == "undefined")
7560        this.setPosition(row.row, row.column);
7561    else
7562        this.setPosition(row, column);
7563};
7564
7565(function() {
7566
7567    oop.implement(this, EventEmitter);
7568    this.getPosition = function() {
7569        return this.$clipPositionToDocument(this.row, this.column);
7570    };
7571    this.getDocument = function() {
7572        return this.document;
7573    };
7574    this.$insertRight = false;
7575    this.onChange = function(delta) {
7576        if (delta.start.row == delta.end.row && delta.start.row != this.row)
7577            return;
7578
7579        if (delta.start.row > this.row)
7580            return;
7581            
7582        var point = $getTransformedPoint(delta, {row: this.row, column: this.column}, this.$insertRight);
7583        this.setPosition(point.row, point.column, true);
7584    };
7585    
7586    function $pointsInOrder(point1, point2, equalPointsInOrder) {
7587        var bColIsAfter = equalPointsInOrder ? point1.column <= point2.column : point1.column < point2.column;
7588        return (point1.row < point2.row) || (point1.row == point2.row && bColIsAfter);
7589    }
7590            
7591    function $getTransformedPoint(delta, point, moveIfEqual) {
7592        var deltaIsInsert = delta.action == "insert";
7593        var deltaRowShift = (deltaIsInsert ? 1 : -1) * (delta.end.row    - delta.start.row);
7594        var deltaColShift = (deltaIsInsert ? 1 : -1) * (delta.end.column - delta.start.column);
7595        var deltaStart = delta.start;
7596        var deltaEnd = deltaIsInsert ? deltaStart : delta.end; // Collapse insert range.
7597        if ($pointsInOrder(point, deltaStart, moveIfEqual)) {
7598            return {
7599                row: point.row,
7600                column: point.column
7601            };
7602        }
7603        if ($pointsInOrder(deltaEnd, point, !moveIfEqual)) {
7604            return {
7605                row: point.row + deltaRowShift,
7606                column: point.column + (point.row == deltaEnd.row ? deltaColShift : 0)
7607            };
7608        }
7609        
7610        return {
7611            row: deltaStart.row,
7612            column: deltaStart.column
7613        };
7614    }
7615    this.setPosition = function(row, column, noClip) {
7616        var pos;
7617        if (noClip) {
7618            pos = {
7619                row: row,
7620                column: column
7621            };
7622        } else {
7623            pos = this.$clipPositionToDocument(row, column);
7624        }
7625
7626        if (this.row == pos.row && this.column == pos.column)
7627            return;
7628
7629        var old = {
7630            row: this.row,
7631            column: this.column
7632        };
7633
7634        this.row = pos.row;
7635        this.column = pos.column;
7636        this._signal("change", {
7637            old: old,
7638            value: pos
7639        });
7640    };
7641    this.detach = function() {
7642        this.document.removeEventListener("change", this.$onChange);
7643    };
7644    this.attach = function(doc) {
7645        this.document = doc || this.document;
7646        this.document.on("change", this.$onChange);
7647    };
7648    this.$clipPositionToDocument = function(row, column) {
7649        var pos = {};
7650
7651        if (row >= this.document.getLength()) {
7652            pos.row = Math.max(0, this.document.getLength() - 1);
7653            pos.column = this.document.getLine(pos.row).length;
7654        }
7655        else if (row < 0) {
7656            pos.row = 0;
7657            pos.column = 0;
7658        }
7659        else {
7660            pos.row = row;
7661            pos.column = Math.min(this.document.getLine(pos.row).length, Math.max(0, column));
7662        }
7663
7664        if (column < 0)
7665            pos.column = 0;
7666
7667        return pos;
7668    };
7669
7670}).call(Anchor.prototype);
7671
7672});
7673
7674define("ace/document",["require","exports","module","ace/lib/oop","ace/apply_delta","ace/lib/event_emitter","ace/range","ace/anchor"], function(require, exports, module) {
7675"use strict";
7676
7677var oop = require("./lib/oop");
7678var applyDelta = require("./apply_delta").applyDelta;
7679var EventEmitter = require("./lib/event_emitter").EventEmitter;
7680var Range = require("./range").Range;
7681var Anchor = require("./anchor").Anchor;
7682
7683var Document = function(textOrLines) {
7684    this.$lines = [""];
7685    if (textOrLines.length === 0) {
7686        this.$lines = [""];
7687    } else if (Array.isArray(textOrLines)) {
7688        this.insertMergedLines({row: 0, column: 0}, textOrLines);
7689    } else {
7690        this.insert({row: 0, column:0}, textOrLines);
7691    }
7692};
7693
7694(function() {
7695
7696    oop.implement(this, EventEmitter);
7697    this.setValue = function(text) {
7698        var len = this.getLength() - 1;
7699        this.remove(new Range(0, 0, len, this.getLine(len).length));
7700        this.insert({row: 0, column: 0}, text);
7701    };
7702    this.getValue = function() {
7703        return this.getAllLines().join(this.getNewLineCharacter());
7704    };
7705    this.createAnchor = function(row, column) {
7706        return new Anchor(this, row, column);
7707    };
7708    if ("aaa".split(/a/).length === 0) {
7709        this.$split = function(text) {
7710            return text.replace(/\r\n|\r/g, "\n").split("\n");
7711        };
7712    } else {
7713        this.$split = function(text) {
7714            return text.split(/\r\n|\r|\n/);
7715        };
7716    }
7717
7718
7719    this.$detectNewLine = function(text) {
7720        var match = text.match(/^.*?(\r\n|\r|\n)/m);
7721        this.$autoNewLine = match ? match[1] : "\n";
7722        this._signal("changeNewLineMode");
7723    };
7724    this.getNewLineCharacter = function() {
7725        switch (this.$newLineMode) {
7726          case "windows":
7727            return "\r\n";
7728          case "unix":
7729            return "\n";
7730          default:
7731            return this.$autoNewLine || "\n";
7732        }
7733    };
7734
7735    this.$autoNewLine = "";
7736    this.$newLineMode = "auto";
7737    this.setNewLineMode = function(newLineMode) {
7738        if (this.$newLineMode === newLineMode)
7739            return;
7740
7741        this.$newLineMode = newLineMode;
7742        this._signal("changeNewLineMode");
7743    };
7744    this.getNewLineMode = function() {
7745        return this.$newLineMode;
7746    };
7747    this.isNewLine = function(text) {
7748        return (text == "\r\n" || text == "\r" || text == "\n");
7749    };
7750    this.getLine = function(row) {
7751        return this.$lines[row] || "";
7752    };
7753    this.getLines = function(firstRow, lastRow) {
7754        return this.$lines.slice(firstRow, lastRow + 1);
7755    };
7756    this.getAllLines = function() {
7757        return this.getLines(0, this.getLength());
7758    };
7759    this.getLength = function() {
7760        return this.$lines.length;
7761    };
7762    this.getTextRange = function(range) {
7763        return this.getLinesForRange(range).join(this.getNewLineCharacter());
7764    };
7765    this.getLinesForRange = function(range) {
7766        var lines;
7767        if (range.start.row === range.end.row) {
7768            lines = [this.getLine(range.start.row).substring(range.start.column, range.end.column)];
7769        } else {
7770            lines = this.getLines(range.start.row, range.end.row);
7771            lines[0] = (lines[0] || "").substring(range.start.column);
7772            var l = lines.length - 1;
7773            if (range.end.row - range.start.row == l)
7774                lines[l] = lines[l].substring(0, range.end.column);
7775        }
7776        return lines;
7777    };
7778    this.insertLines = function(row, lines) {
7779        console.warn("Use of document.insertLines is deprecated. Use the insertFullLines method instead.");
7780        return this.insertFullLines(row, lines);
7781    };
7782    this.removeLines = function(firstRow, lastRow) {
7783        console.warn("Use of document.removeLines is deprecated. Use the removeFullLines method instead.");
7784        return this.removeFullLines(firstRow, lastRow);
7785    };
7786    this.insertNewLine = function(position) {
7787        console.warn("Use of document.insertNewLine is deprecated. Use insertMergedLines(position, ['', '']) instead.");
7788        return this.insertMergedLines(position, ["", ""]);
7789    };
7790    this.insert = function(position, text) {
7791        if (this.getLength() <= 1)
7792            this.$detectNewLine(text);
7793        
7794        return this.insertMergedLines(position, this.$split(text));
7795    };
7796    this.insertInLine = function(position, text) {
7797        var start = this.clippedPos(position.row, position.column);
7798        var end = this.pos(position.row, position.column + text.length);
7799        
7800        this.applyDelta({
7801            start: start,
7802            end: end,
7803            action: "insert",
7804            lines: [text]
7805        }, true);
7806        
7807        return this.clonePos(end);
7808    };
7809    
7810    this.clippedPos = function(row, column) {
7811        var length = this.getLength();
7812        if (row === undefined) {
7813            row = length;
7814        } else if (row < 0) {
7815            row = 0;
7816        } else if (row >= length) {
7817            row = length - 1;
7818            column = undefined;
7819        }
7820        var line = this.getLine(row);
7821        if (column == undefined)
7822            column = line.length;
7823        column = Math.min(Math.max(column, 0), line.length);
7824        return {row: row, column: column};
7825    };
7826    
7827    this.clonePos = function(pos) {
7828        return {row: pos.row, column: pos.column};
7829    };
7830    
7831    this.pos = function(row, column) {
7832        return {row: row, column: column};
7833    };
7834    
7835    this.$clipPosition = function(position) {
7836        var length = this.getLength();
7837        if (position.row >= length) {
7838            position.row = Math.max(0, length - 1);
7839            position.column = this.getLine(length - 1).length;
7840        } else {
7841            position.row = Math.max(0, position.row);
7842            position.column = Math.min(Math.max(position.column, 0), this.getLine(position.row).length);
7843        }
7844        return position;
7845    };
7846    this.insertFullLines = function(row, lines) {
7847        row = Math.min(Math.max(row, 0), this.getLength());
7848        var column = 0;
7849        if (row < this.getLength()) {
7850            lines = lines.concat([""]);
7851            column = 0;
7852        } else {
7853            lines = [""].concat(lines);
7854            row--;
7855            column = this.$lines[row].length;
7856        }
7857        this.insertMergedLines({row: row, column: column}, lines);
7858    };    
7859    this.insertMergedLines = function(position, lines) {
7860        var start = this.clippedPos(position.row, position.column);
7861        var end = {
7862            row: start.row + lines.length - 1,
7863            column: (lines.length == 1 ? start.column : 0) + lines[lines.length - 1].length
7864        };
7865        
7866        this.applyDelta({
7867            start: start,
7868            end: end,
7869            action: "insert",
7870            lines: lines
7871        });
7872        
7873        return this.clonePos(end);
7874    };
7875    this.remove = function(range) {
7876        var start = this.clippedPos(range.start.row, range.start.column);
7877        var end = this.clippedPos(range.end.row, range.end.column);
7878        this.applyDelta({
7879            start: start,
7880            end: end,
7881            action: "remove",
7882            lines: this.getLinesForRange({start: start, end: end})
7883        });
7884        return this.clonePos(start);
7885    };
7886    this.removeInLine = function(row, startColumn, endColumn) {
7887        var start = this.clippedPos(row, startColumn);
7888        var end = this.clippedPos(row, endColumn);
7889        
7890        this.applyDelta({
7891            start: start,
7892            end: end,
7893            action: "remove",
7894            lines: this.getLinesForRange({start: start, end: end})
7895        }, true);
7896        
7897        return this.clonePos(start);
7898    };
7899    this.removeFullLines = function(firstRow, lastRow) {
7900        firstRow = Math.min(Math.max(0, firstRow), this.getLength() - 1);
7901        lastRow  = Math.min(Math.max(0, lastRow ), this.getLength() - 1);
7902        var deleteFirstNewLine = lastRow == this.getLength() - 1 && firstRow > 0;
7903        var deleteLastNewLine  = lastRow  < this.getLength() - 1;
7904        var startRow = ( deleteFirstNewLine ? firstRow - 1                  : firstRow                    );
7905        var startCol = ( deleteFirstNewLine ? this.getLine(startRow).length : 0                           );
7906        var endRow   = ( deleteLastNewLine  ? lastRow + 1                   : lastRow                     );
7907        var endCol   = ( deleteLastNewLine  ? 0                             : this.getLine(endRow).length ); 
7908        var range = new Range(startRow, startCol, endRow, endCol);
7909        var deletedLines = this.$lines.slice(firstRow, lastRow + 1);
7910        
7911        this.applyDelta({
7912            start: range.start,
7913            end: range.end,
7914            action: "remove",
7915            lines: this.getLinesForRange(range)
7916        });
7917        return deletedLines;
7918    };
7919    this.removeNewLine = function(row) {
7920        if (row < this.getLength() - 1 && row >= 0) {
7921            this.applyDelta({
7922                start: this.pos(row, this.getLine(row).length),
7923                end: this.pos(row + 1, 0),
7924                action: "remove",
7925                lines: ["", ""]
7926            });
7927        }
7928    };
7929    this.replace = function(range, text) {
7930        if (!(range instanceof Range))
7931            range = Range.fromPoints(range.start, range.end);
7932        if (text.length === 0 && range.isEmpty())
7933            return range.start;
7934        if (text == this.getTextRange(range))
7935            return range.end;
7936
7937        this.remove(range);
7938        var end;
7939        if (text) {
7940            end = this.insert(range.start, text);
7941        }
7942        else {
7943            end = range.start;
7944        }
7945        
7946        return end;
7947    };
7948    this.applyDeltas = function(deltas) {
7949        for (var i=0; i<deltas.length; i++) {
7950            this.applyDelta(deltas[i]);
7951        }
7952    };
7953    this.revertDeltas = function(deltas) {
7954        for (var i=deltas.length-1; i>=0; i--) {
7955            this.revertDelta(deltas[i]);
7956        }
7957    };
7958    this.applyDelta = function(delta, doNotValidate) {
7959        var isInsert = delta.action == "insert";
7960        if (isInsert ? delta.lines.length <= 1 && !delta.lines[0]
7961            : !Range.comparePoints(delta.start, delta.end)) {
7962            return;
7963        }
7964        
7965        if (isInsert && delta.lines.length > 20000)
7966            this.$splitAndapplyLargeDelta(delta, 20000);
7967        applyDelta(this.$lines, delta, doNotValidate);
7968        this._signal("change", delta);
7969    };
7970    
7971    this.$splitAndapplyLargeDelta = function(delta, MAX) {
7972        var lines = delta.lines;
7973        var l = lines.length;
7974        var row = delta.start.row; 
7975        var column = delta.start.column;
7976        var from = 0, to = 0;
7977        do {
7978            from = to;
7979            to += MAX - 1;
7980            var chunk = lines.slice(from, to);
7981            if (to > l) {
7982                delta.lines = chunk;
7983                delta.start.row = row + from;
7984                delta.start.column = column;
7985                break;
7986            }
7987            chunk.push("");
7988            this.applyDelta({
7989                start: this.pos(row + from, column),
7990                end: this.pos(row + to, column = 0),
7991                action: delta.action,
7992                lines: chunk
7993            }, true);
7994        } while(true);
7995    };
7996    this.revertDelta = function(delta) {
7997        this.applyDelta({
7998            start: this.clonePos(delta.start),
7999            end: this.clonePos(delta.end),
8000            action: (delta.action == "insert" ? "remove" : "insert"),
8001            lines: delta.lines.slice()
8002        });
8003    };
8004    this.indexToPosition = function(index, startRow) {
8005        var lines = this.$lines || this.getAllLines();
8006        var newlineLength = this.getNewLineCharacter().length;
8007        for (var i = startRow || 0, l = lines.length; i < l; i++) {
8008            index -= lines[i].length + newlineLength;
8009            if (index < 0)
8010                return {row: i, column: index + lines[i].length + newlineLength};
8011        }
8012        return {row: l-1, column: lines[l-1].length};
8013    };
8014    this.positionToIndex = function(pos, startRow) {
8015        var lines = this.$lines || this.getAllLines();
8016        var newlineLength = this.getNewLineCharacter().length;
8017        var index = 0;
8018        var row = Math.min(pos.row, lines.length);
8019        for (var i = startRow || 0; i < row; ++i)
8020            index += lines[i].length + newlineLength;
8021
8022        return index + pos.column;
8023    };
8024
8025}).call(Document.prototype);
8026
8027exports.Document = Document;
8028});
8029
8030define("ace/background_tokenizer",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"], function(require, exports, module) {
8031"use strict";
8032
8033var oop = require("./lib/oop");
8034var EventEmitter = require("./lib/event_emitter").EventEmitter;
8035
8036var BackgroundTokenizer = function(tokenizer, editor) {
8037    this.running = false;
8038    this.lines = [];
8039    this.states = [];
8040    this.currentLine = 0;
8041    this.tokenizer = tokenizer;
8042
8043    var self = this;
8044
8045    this.$worker = function() {
8046        if (!self.running) { return; }
8047
8048        var workerStart = new Date();
8049        var currentLine = self.currentLine;
8050        var endLine = -1;
8051        var doc = self.doc;
8052
8053        var startLine = currentLine;
8054        while (self.lines[currentLine])
8055            currentLine++;
8056        
8057        var len = doc.getLength();
8058        var processedLines = 0;
8059        self.running = false;
8060        while (currentLine < len) {
8061            self.$tokenizeRow(currentLine);
8062            endLine = currentLine;
8063            do {
8064                currentLine++;
8065            } while (self.lines[currentLine]);
8066            processedLines ++;
8067            if ((processedLines % 5 === 0) && (new Date() - workerStart) > 20) {                
8068                self.running = setTimeout(self.$worker, 20);
8069                break;
8070            }
8071        }
8072        self.currentLine = currentLine;
8073        
8074        if (endLine == -1)
8075            endLine = currentLine;
8076        
8077        if (startLine <= endLine)
8078            self.fireUpdateEvent(startLine, endLine);
8079    };
8080};
8081
8082(function(){
8083
8084    oop.implement(this, EventEmitter);
8085    this.setTokenizer = function(tokenizer) {
8086        this.tokenizer = tokenizer;
8087        this.lines = [];
8088        this.states = [];
8089
8090        this.start(0);
8091    };
8092    this.setDocument = function(doc) {
8093        this.doc = doc;
8094        this.lines = [];
8095        this.states = [];
8096
8097        this.stop();
8098    };
8099    this.fireUpdateEvent = function(firstRow, lastRow) {
8100        var data = {
8101            first: firstRow,
8102            last: lastRow
8103        };
8104        this._signal("update", {data: data});
8105    };
8106    this.start = function(startRow) {
8107        this.currentLine = Math.min(startRow || 0, this.currentLine, this.doc.getLength());
8108        this.lines.splice(this.currentLine, this.lines.length);
8109        this.states.splice(this.currentLine, this.states.length);
8110
8111        this.stop();
8112        this.running = setTimeout(this.$worker, 700);
8113    };
8114    
8115    this.scheduleStart = function() {
8116        if (!this.running)
8117            this.running = setTimeout(this.$worker, 700);
8118    };
8119
8120    this.$updateOnChange = function(delta) {
8121        var startRow = delta.start.row;
8122        var len = delta.end.row - startRow;
8123
8124        if (len === 0) {
8125            this.lines[startRow] = null;
8126        } else if (delta.action == "remove") {
8127            this.lines.splice(startRow, len + 1, null);
8128            this.states.splice(startRow, len + 1, null);
8129        } else {
8130            var args = Array(len + 1);
8131            args.unshift(startRow, 1);
8132            this.lines.splice.apply(this.lines, args);
8133            this.states.splice.apply(this.states, args);
8134        }
8135
8136        this.currentLine = Math.min(startRow, this.currentLine, this.doc.getLength());
8137
8138        this.stop();
8139    };
8140    this.stop = function() {
8141        if (this.running)
8142            clearTimeout(this.running);
8143        this.running = false;
8144    };
8145    this.getTokens = function(row) {
8146        return this.lines[row] || this.$tokenizeRow(row);
8147    };
8148    this.getState = function(row) {
8149        if (this.currentLine == row)
8150            this.$tokenizeRow(row);
8151        return this.states[row] || "start";
8152    };
8153
8154    this.$tokenizeRow = function(row) {
8155        var line = this.doc.getLine(row);
8156        var state = this.states[row - 1];
8157
8158        var data = this.tokenizer.getLineTokens(line, state, row);
8159
8160        if (this.states[row] + "" !== data.state + "") {
8161            this.states[row] = data.state;
8162            this.lines[row + 1] = null;
8163            if (this.currentLine > row + 1)
8164                this.currentLine = row + 1;
8165        } else if (this.currentLine == row) {
8166            this.currentLine = row + 1;
8167        }
8168
8169        return this.lines[row] = data.tokens;
8170    };
8171
8172}).call(BackgroundTokenizer.prototype);
8173
8174exports.BackgroundTokenizer = BackgroundTokenizer;
8175});
8176
8177define("ace/search_highlight",["require","exports","module","ace/lib/lang","ace/lib/oop","ace/range"], function(require, exports, module) {
8178"use strict";
8179
8180var lang = require("./lib/lang");
8181var oop = require("./lib/oop");
8182var Range = require("./range").Range;
8183
8184var SearchHighlight = function(regExp, clazz, type) {
8185    this.setRegexp(regExp);
8186    this.clazz = clazz;
8187    this.type = type || "text";
8188};
8189
8190(function() {
8191    this.MAX_RANGES = 500;
8192    
8193    this.setRegexp = function(regExp) {
8194        if (this.regExp+"" == regExp+"")
8195            return;
8196        this.regExp = regExp;
8197        this.cache = [];
8198    };
8199
8200    this.update = function(html, markerLayer, session, config) {
8201        if (!this.regExp)
8202            return;
8203        var start = config.firstRow, end = config.lastRow;
8204
8205        for (var i = start; i <= end; i++) {
8206            var ranges = this.cache[i];
8207            if (ranges == null) {
8208                ranges = lang.getMatchOffsets(session.getLine(i), this.regExp);
8209                if (ranges.length > this.MAX_RANGES)
8210                    ranges = ranges.slice(0, this.MAX_RANGES);
8211                ranges = ranges.map(function(match) {
8212                    return new Range(i, match.offset, i, match.offset + match.length);
8213                });
8214                this.cache[i] = ranges.length ? ranges : "";
8215            }
8216
8217            for (var j = ranges.length; j --; ) {
8218                markerLayer.drawSingleLineMarker(
8219                    html, ranges[j].toScreenRange(session), this.clazz, config);
8220            }
8221        }
8222    };
8223
8224}).call(SearchHighlight.prototype);
8225
8226exports.SearchHighlight = SearchHighlight;
8227});
8228
8229define("ace/edit_session/fold_line",["require","exports","module","ace/range"], function(require, exports, module) {
8230"use strict";
8231
8232var Range = require("../range").Range;
8233function FoldLine(foldData, folds) {
8234    this.foldData = foldData;
8235    if (Array.isArray(folds)) {
8236        this.folds = folds;
8237    } else {
8238        folds = this.folds = [ folds ];
8239    }
8240
8241    var last = folds[folds.length - 1];
8242    this.range = new Range(folds[0].start.row, folds[0].start.column,
8243                           last.end.row, last.end.column);
8244    this.start = this.range.start;
8245    this.end   = this.range.end;
8246
8247    this.folds.forEach(function(fold) {
8248        fold.setFoldLine(this);
8249    }, this);
8250}
8251
8252(function() {
8253    this.shiftRow = function(shift) {
8254        this.start.row += shift;
8255        this.end.row += shift;
8256        this.folds.forEach(function(fold) {
8257            fold.start.row += shift;
8258            fold.end.row += shift;
8259        });
8260    };
8261
8262    this.addFold = function(fold) {
8263        if (fold.sameRow) {
8264            if (fold.start.row < this.startRow || fold.endRow > this.endRow) {
8265                throw new Error("Can't add a fold to this FoldLine as it has no connection");
8266            }
8267            this.folds.push(fold);
8268            this.folds.sort(function(a, b) {
8269                return -a.range.compareEnd(b.start.row, b.start.column);
8270            });
8271            if (this.range.compareEnd(fold.start.row, fold.start.column) > 0) {
vendor: 10,538 bytes, lines 8272-8626
8272                this.end.row = fold.end.row;
8273                this.end.column =  fold.end.column;
8274            } else if (this.range.compareStart(fold.end.row, fold.end.column) < 0) {
8275                this.start.row = fold.start.row;
8276                this.start.column = fold.start.column;
8277            }
8278        } else if (fold.start.row == this.end.row) {
8279            this.folds.push(fold);
8280            this.end.row = fold.end.row;
8281            this.end.column = fold.end.column;
8282        } else if (fold.end.row == this.start.row) {
8283            this.folds.unshift(fold);
8284            this.start.row = fold.start.row;
8285            this.start.column = fold.start.column;
8286        } else {
8287            throw new Error("Trying to add fold to FoldRow that doesn't have a matching row");
8288        }
8289        fold.foldLine = this;
8290    };
8291
8292    this.containsRow = function(row) {
8293        return row >= this.start.row && row <= this.end.row;
8294    };
8295
8296    this.walk = function(callback, endRow, endColumn) {
8297        var lastEnd = 0,
8298            folds = this.folds,
8299            fold,
8300            cmp, stop, isNewRow = true;
8301
8302        if (endRow == null) {
8303            endRow = this.end.row;
8304            endColumn = this.end.column;
8305        }
8306
8307        for (var i = 0; i < folds.length; i++) {
8308            fold = folds[i];
8309
8310            cmp = fold.range.compareStart(endRow, endColumn);
8311            if (cmp == -1) {
8312                callback(null, endRow, endColumn, lastEnd, isNewRow);
8313                return;
8314            }
8315
8316            stop = callback(null, fold.start.row, fold.start.column, lastEnd, isNewRow);
8317            stop = !stop && callback(fold.placeholder, fold.start.row, fold.start.column, lastEnd);
8318            if (stop || cmp === 0) {
8319                return;
8320            }
8321            isNewRow = !fold.sameRow;
8322            lastEnd = fold.end.column;
8323        }
8324        callback(null, endRow, endColumn, lastEnd, isNewRow);
8325    };
8326
8327    this.getNextFoldTo = function(row, column) {
8328        var fold, cmp;
8329        for (var i = 0; i < this.folds.length; i++) {
8330            fold = this.folds[i];
8331            cmp = fold.range.compareEnd(row, column);
8332            if (cmp == -1) {
8333                return {
8334                    fold: fold,
8335                    kind: "after"
8336                };
8337            } else if (cmp === 0) {
8338                return {
8339                    fold: fold,
8340                    kind: "inside"
8341                };
8342            }
8343        }
8344        return null;
8345    };
8346
8347    this.addRemoveChars = function(row, column, len) {
8348        var ret = this.getNextFoldTo(row, column),
8349            fold, folds;
8350        if (ret) {
8351            fold = ret.fold;
8352            if (ret.kind == "inside"
8353                && fold.start.column != column
8354                && fold.start.row != row)
8355            {
8356                window.console && window.console.log(row, column, fold);
8357            } else if (fold.start.row == row) {
8358                folds = this.folds;
8359                var i = folds.indexOf(fold);
8360                if (i === 0) {
8361                    this.start.column += len;
8362                }
8363                for (i; i < folds.length; i++) {
8364                    fold = folds[i];
8365                    fold.start.column += len;
8366                    if (!fold.sameRow) {
8367                        return;
8368                    }
8369                    fold.end.column += len;
8370                }
8371                this.end.column += len;
8372            }
8373        }
8374    };
8375
8376    this.split = function(row, column) {
8377        var pos = this.getNextFoldTo(row, column);
8378        
8379        if (!pos || pos.kind == "inside")
8380            return null;
8381            
8382        var fold = pos.fold;
8383        var folds = this.folds;
8384        var foldData = this.foldData;
8385        
8386        var i = folds.indexOf(fold);
8387        var foldBefore = folds[i - 1];
8388        this.end.row = foldBefore.end.row;
8389        this.end.column = foldBefore.end.column;
8390        folds = folds.splice(i, folds.length - i);
8391
8392        var newFoldLine = new FoldLine(foldData, folds);
8393        foldData.splice(foldData.indexOf(this) + 1, 0, newFoldLine);
8394        return newFoldLine;
8395    };
8396
8397    this.merge = function(foldLineNext) {
8398        var folds = foldLineNext.folds;
8399        for (var i = 0; i < folds.length; i++) {
8400            this.addFold(folds[i]);
8401        }
8402        var foldData = this.foldData;
8403        foldData.splice(foldData.indexOf(foldLineNext), 1);
8404    };
8405
8406    this.toString = function() {
8407        var ret = [this.range.toString() + ": [" ];
8408
8409        this.folds.forEach(function(fold) {
8410            ret.push("  " + fold.toString());
8411        });
8412        ret.push("]");
8413        return ret.join("\n");
8414    };
8415
8416    this.idxToPosition = function(idx) {
8417        var lastFoldEndColumn = 0;
8418
8419        for (var i = 0; i < this.folds.length; i++) {
8420            var fold = this.folds[i];
8421
8422            idx -= fold.start.column - lastFoldEndColumn;
8423            if (idx < 0) {
8424                return {
8425                    row: fold.start.row,
8426                    column: fold.start.column + idx
8427                };
8428            }
8429
8430            idx -= fold.placeholder.length;
8431            if (idx < 0) {
8432                return fold.start;
8433            }
8434
8435            lastFoldEndColumn = fold.end.column;
8436        }
8437
8438        return {
8439            row: this.end.row,
8440            column: this.end.column + idx
8441        };
8442    };
8443}).call(FoldLine.prototype);
8444
8445exports.FoldLine = FoldLine;
8446});
8447
8448define("ace/range_list",["require","exports","module","ace/range"], function(require, exports, module) {
8449"use strict";
8450var Range = require("./range").Range;
8451var comparePoints = Range.comparePoints;
8452
8453var RangeList = function() {
8454    this.ranges = [];
8455};
8456
8457(function() {
8458    this.comparePoints = comparePoints;
8459
8460    this.pointIndex = function(pos, excludeEdges, startIndex) {
8461        var list = this.ranges;
8462
8463        for (var i = startIndex || 0; i < list.length; i++) {
8464            var range = list[i];
8465            var cmpEnd = comparePoints(pos, range.end);
8466            if (cmpEnd > 0)
8467                continue;
8468            var cmpStart = comparePoints(pos, range.start);
8469            if (cmpEnd === 0)
8470                return excludeEdges && cmpStart !== 0 ? -i-2 : i;
8471            if (cmpStart > 0 || (cmpStart === 0 && !excludeEdges))
8472                return i;
8473
8474            return -i-1;
8475        }
8476        return -i - 1;
8477    };
8478
8479    this.add = function(range) {
8480        var excludeEdges = !range.isEmpty();
8481        var startIndex = this.pointIndex(range.start, excludeEdges);
8482        if (startIndex < 0)
8483            startIndex = -startIndex - 1;
8484
8485        var endIndex = this.pointIndex(range.end, excludeEdges, startIndex);
8486
8487        if (endIndex < 0)
8488            endIndex = -endIndex - 1;
8489        else
8490            endIndex++;
8491        return this.ranges.splice(startIndex, endIndex - startIndex, range);
8492    };
8493
8494    this.addList = function(list) {
8495        var removed = [];
8496        for (var i = list.length; i--; ) {
8497            removed.push.apply(removed, this.add(list[i]));
8498        }
8499        return removed;
8500    };
8501
8502    this.substractPoint = function(pos) {
8503        var i = this.pointIndex(pos);
8504
8505        if (i >= 0)
8506            return this.ranges.splice(i, 1);
8507    };
8508    this.merge = function() {
8509        var removed = [];
8510        var list = this.ranges;
8511        
8512        list = list.sort(function(a, b) {
8513            return comparePoints(a.start, b.start);
8514        });
8515        
8516        var next = list[0], range;
8517        for (var i = 1; i < list.length; i++) {
8518            range = next;
8519            next = list[i];
8520            var cmp = comparePoints(range.end, next.start);
8521            if (cmp < 0)
8522                continue;
8523
8524            if (cmp == 0 && !range.isEmpty() && !next.isEmpty())
8525                continue;
8526
8527            if (comparePoints(range.end, next.end) < 0) {
8528                range.end.row = next.end.row;
8529                range.end.column = next.end.column;
8530            }
8531
8532            list.splice(i, 1);
8533            removed.push(next);
8534            next = range;
8535            i--;
8536        }
8537        
8538        this.ranges = list;
8539
8540        return removed;
8541    };
8542
8543    this.contains = function(row, column) {
8544        return this.pointIndex({row: row, column: column}) >= 0;
8545    };
8546
8547    this.containsPoint = function(pos) {
8548        return this.pointIndex(pos) >= 0;
8549    };
8550
8551    this.rangeAtPoint = function(pos) {
8552        var i = this.pointIndex(pos);
8553        if (i >= 0)
8554            return this.ranges[i];
8555    };
8556
8557
8558    this.clipRows = function(startRow, endRow) {
8559        var list = this.ranges;
8560        if (list[0].start.row > endRow || list[list.length - 1].start.row < startRow)
8561            return [];
8562
8563        var startIndex = this.pointIndex({row: startRow, column: 0});
8564        if (startIndex < 0)
8565            startIndex = -startIndex - 1;
8566        var endIndex = this.pointIndex({row: endRow, column: 0}, startIndex);
8567        if (endIndex < 0)
8568            endIndex = -endIndex - 1;
8569
8570        var clipped = [];
8571        for (var i = startIndex; i < endIndex; i++) {
8572            clipped.push(list[i]);
8573        }
8574        return clipped;
8575    };
8576
8577    this.removeAll = function() {
8578        return this.ranges.splice(0, this.ranges.length);
8579    };
8580
8581    this.attach = function(session) {
8582        if (this.session)
8583            this.detach();
8584
8585        this.session = session;
8586        this.onChange = this.$onChange.bind(this);
8587
8588        this.session.on('change', this.onChange);
8589    };
8590
8591    this.detach = function() {
8592        if (!this.session)
8593            return;
8594        this.session.removeListener('change', this.onChange);
8595        this.session = null;
8596    };
8597
8598    this.$onChange = function(delta) {
8599        if (delta.action == "insert"){
8600            var start = delta.start;
8601            var end = delta.end;
8602        } else {
8603            var end = delta.start;
8604            var start = delta.end;
8605        }
8606        var startRow = start.row;
8607        var endRow = end.row;
8608        var lineDif = endRow - startRow;
8609
8610        var colDiff = -start.column + end.column;
8611        var ranges = this.ranges;
8612
8613        for (var i = 0, n = ranges.length; i < n; i++) {
8614            var r = ranges[i];
8615            if (r.end.row < startRow)
8616                continue;
8617            if (r.start.row > startRow)
8618                break;
8619
8620            if (r.start.row == startRow && r.start.column >= start.column ) {
8621                if (r.start.column == start.column && this.$insertRight) {
8622                } else {
8623                    r.start.column += colDiff;
8624                    r.start.row += lineDif;
8625                }
8626            }
8627            if (r.end.row == startRow && r.end.column >= start.column) {
8628                if (r.end.column == start.column && this.$insertRight) {
8629                    continue;
8630                }
8631                if (r.end.column == start.column && colDiff > 0 && i < n - 1) {                
8632                    if (r.end.column > r.start.column && r.end.column == ranges[i+1].start.column)
8633                        r.end.column -= colDiff;
8634                }
8635                r.end.column += colDiff;
8636                r.end.row += lineDif;
8637            }
8638        }
8639
8640        if (lineDif != 0 && i < n) {
8641            for (; i < n; i++) {
8642                var r = ranges[i];
8643                r.start.row += lineDif;
8644                r.end.row += lineDif;
8645            }
8646        }
8647    };
8648
8649}).call(RangeList.prototype);
8650
8651exports.RangeList = RangeList;
8652});
8653
8654define("ace/edit_session/fold",["require","exports","module","ace/range","ace/range_list","ace/lib/oop"], function(require, exports, module) {
8655"use strict";
8656
8657var Range = require("../range").Range;
8658var RangeList = require("../range_list").RangeList;
8659var oop = require("../lib/oop");
8660var Fold = exports.Fold = function(range, placeholder) {
8661    this.foldLine = null;
8662    this.placeholder = placeholder;
8663    this.range = range;
8664    this.start = range.start;
8665    this.end = range.end;
8666
8667    this.sameRow = range.start.row == range.end.row;
8668    this.subFolds = this.ranges = [];
8669};
8670
8671oop.inherits(Fold, RangeList);
8672
8673(function() {
8674
8675    this.toString = function() {
8676        return '"' + this.placeholder + '" ' + this.range.toString();
8677    };
8678
8679    this.setFoldLine = function(foldLine) {
8680        this.foldLine = foldLine;
8681        this.subFolds.forEach(function(fold) {
8682            fold.setFoldLine(foldLine);
8683        });
8684    };
8685
8686    this.clone = function() {
8687        var range = this.range.clone();
8688        var fold = new Fold(range, this.placeholder);
8689        this.subFolds.forEach(function(subFold) {
8690            fold.subFolds.push(subFold.clone());
8691        });
8692        fold.collapseChildren = this.collapseChildren;
8693        return fold;
8694    };
8695
8696    this.addSubFold = function(fold) {
8697        if (this.range.isEqual(fold))
8698            return;
8699
8700        if (!this.range.containsRange(fold))
8701            throw new Error("A fold can't intersect already existing fold" + fold.range + this.range);
8702        consumeRange(fold, this.start);
8703
8704        var row = fold.start.row, column = fold.start.column;
8705        for (var i = 0, cmp = -1; i < this.subFolds.length; i++) {
8706            cmp = this.subFolds[i].range.compare(row, column);
8707            if (cmp != 1)
8708                break;
8709        }
8710        var afterStart = this.subFolds[i];
8711
8712        if (cmp == 0)
8713            return afterStart.addSubFold(fold);
8714        var row = fold.range.end.row, column = fold.range.end.column;
8715        for (var j = i, cmp = -1; j < this.subFolds.length; j++) {
8716            cmp = this.subFolds[j].range.compare(row, column);
8717            if (cmp != 1)
8718                break;
8719        }
8720        var afterEnd = this.subFolds[j];
8721
8722        if (cmp == 0)
8723            throw new Error("A fold can't intersect already existing fold" + fold.range + this.range);
8724
8725        var consumedFolds = this.subFolds.splice(i, j - i, fold);
8726        fold.setFoldLine(this.foldLine);
8727
8728        return fold;
8729    };
8730    
8731    this.restoreRange = function(range) {
8732        return restoreRange(range, this.start);
8733    };
8734
8735}).call(Fold.prototype);
8736
8737function consumePoint(point, anchor) {
8738    point.row -= anchor.row;
8739    if (point.row == 0)
8740        point.column -= anchor.column;
8741}
8742function consumeRange(range, anchor) {
8743    consumePoint(range.start, anchor);
8744    consumePoint(range.end, anchor);
8745}
8746function restorePoint(point, anchor) {
8747    if (point.row == 0)
8748        point.column += anchor.column;
8749    point.row += anchor.row;
8750}
8751function restoreRange(range, anchor) {
8752    restorePoint(range.start, anchor);
8753    restorePoint(range.end, anchor);
8754}
8755
8756});
8757
8758define("ace/edit_session/folding",["require","exports","module","ace/range","ace/edit_session/fold_line","ace/edit_session/fold","ace/token_iterator"], function(require, exports, module) {
8759"use strict";
8760
8761var Range = require("../range").Range;
8762var FoldLine = require("./fold_line").FoldLine;
8763var Fold = require("./fold").Fold;
8764var TokenIterator = require("../token_iterator").TokenIterator;
8765
8766function Folding() {
8767    this.getFoldAt = function(row, column, side) {
8768        var foldLine = this.getFoldLine(row);
8769        if (!foldLine)
8770            return null;
8771
8772        var folds = foldLine.folds;
8773        for (var i = 0; i < folds.length; i++) {
8774            var fold = folds[i];
8775            if (fold.range.contains(row, column)) {
8776                if (side == 1 && fold.range.isEnd(row, column)) {
8777                    continue;
8778                } else if (side == -1 && fold.range.isStart(row, column)) {
8779                    continue;
8780                }
8781                return fold;
8782            }
8783        }
8784    };
8785    this.getFoldsInRange = function(range) {
8786        var start = range.start;
8787        var end = range.end;
8788        var foldLines = this.$foldData;
8789        var foundFolds = [];
8790
8791        start.column += 1;
8792        end.column -= 1;
8793
8794        for (var i = 0; i < foldLines.length; i++) {
8795            var cmp = foldLines[i].range.compareRange(range);
8796            if (cmp == 2) {
8797                continue;
8798            }
8799            else if (cmp == -2) {
8800                break;
8801            }
8802
8803            var folds = foldLines[i].folds;
8804            for (var j = 0; j < folds.length; j++) {
8805                var fold = folds[j];
8806                cmp = fold.range.compareRange(range);
8807                if (cmp == -2) {
8808                    break;
8809                } else if (cmp == 2) {
8810                    continue;
8811                } else
8812                if (cmp == 42) {
8813                    break;
8814                }
8815                foundFolds.push(fold);
8816            }
8817        }
8818        start.column -= 1;
8819        end.column += 1;
8820
8821        return foundFolds;
8822    };
8823
8824    this.getFoldsInRangeList = function(ranges) {
8825        if (Array.isArray(ranges)) {
8826            var folds = [];
vendor: 13,940 bytes, lines 8827-9248
8827            ranges.forEach(function(range) {
8828                folds = folds.concat(this.getFoldsInRange(range));
8829            }, this);
8830        } else {
8831            var folds = this.getFoldsInRange(ranges);
8832        }
8833        return folds;
8834    };
8835    this.getAllFolds = function() {
8836        var folds = [];
8837        var foldLines = this.$foldData;
8838        
8839        for (var i = 0; i < foldLines.length; i++)
8840            for (var j = 0; j < foldLines[i].folds.length; j++)
8841                folds.push(foldLines[i].folds[j]);
8842
8843        return folds;
8844    };
8845    this.getFoldStringAt = function(row, column, trim, foldLine) {
8846        foldLine = foldLine || this.getFoldLine(row);
8847        if (!foldLine)
8848            return null;
8849
8850        var lastFold = {
8851            end: { column: 0 }
8852        };
8853        var str, fold;
8854        for (var i = 0; i < foldLine.folds.length; i++) {
8855            fold = foldLine.folds[i];
8856            var cmp = fold.range.compareEnd(row, column);
8857            if (cmp == -1) {
8858                str = this
8859                    .getLine(fold.start.row)
8860                    .substring(lastFold.end.column, fold.start.column);
8861                break;
8862            }
8863            else if (cmp === 0) {
8864                return null;
8865            }
8866            lastFold = fold;
8867        }
8868        if (!str)
8869            str = this.getLine(fold.start.row).substring(lastFold.end.column);
8870
8871        if (trim == -1)
8872            return str.substring(0, column - lastFold.end.column);
8873        else if (trim == 1)
8874            return str.substring(column - lastFold.end.column);
8875        else
8876            return str;
8877    };
8878
8879    this.getFoldLine = function(docRow, startFoldLine) {
8880        var foldData = this.$foldData;
8881        var i = 0;
8882        if (startFoldLine)
8883            i = foldData.indexOf(startFoldLine);
8884        if (i == -1)
8885            i = 0;
8886        for (i; i < foldData.length; i++) {
8887            var foldLine = foldData[i];
8888            if (foldLine.start.row <= docRow && foldLine.end.row >= docRow) {
8889                return foldLine;
8890            } else if (foldLine.end.row > docRow) {
8891                return null;
8892            }
8893        }
8894        return null;
8895    };
8896    this.getNextFoldLine = function(docRow, startFoldLine) {
8897        var foldData = this.$foldData;
8898        var i = 0;
8899        if (startFoldLine)
8900            i = foldData.indexOf(startFoldLine);
8901        if (i == -1)
8902            i = 0;
8903        for (i; i < foldData.length; i++) {
8904            var foldLine = foldData[i];
8905            if (foldLine.end.row >= docRow) {
8906                return foldLine;
8907            }
8908        }
8909        return null;
8910    };
8911
8912    this.getFoldedRowCount = function(first, last) {
8913        var foldData = this.$foldData, rowCount = last-first+1;
8914        for (var i = 0; i < foldData.length; i++) {
8915            var foldLine = foldData[i],
8916                end = foldLine.end.row,
8917                start = foldLine.start.row;
8918            if (end >= last) {
8919                if (start < last) {
8920                    if (start >= first)
8921                        rowCount -= last-start;
8922                    else
8923                        rowCount = 0; // in one fold
8924                }
8925                break;
8926            } else if (end >= first){
8927                if (start >= first) // fold inside range
8928                    rowCount -=  end-start;
8929                else
8930                    rowCount -=  end-first+1;
8931            }
8932        }
8933        return rowCount;
8934    };
8935
8936    this.$addFoldLine = function(foldLine) {
8937        this.$foldData.push(foldLine);
8938        this.$foldData.sort(function(a, b) {
8939            return a.start.row - b.start.row;
8940        });
8941        return foldLine;
8942    };
8943    this.addFold = function(placeholder, range) {
8944        var foldData = this.$foldData;
8945        var added = false;
8946        var fold;
8947        
8948        if (placeholder instanceof Fold)
8949            fold = placeholder;
8950        else {
8951            fold = new Fold(range, placeholder);
8952            fold.collapseChildren = range.collapseChildren;
8953        }
8954        this.$clipRangeToDocument(fold.range);
8955
8956        var startRow = fold.start.row;
8957        var startColumn = fold.start.column;
8958        var endRow = fold.end.row;
8959        var endColumn = fold.end.column;
8960        if (!(startRow < endRow || 
8961            startRow == endRow && startColumn <= endColumn - 2))
8962            throw new Error("The range has to be at least 2 characters width");
8963
8964        var startFold = this.getFoldAt(startRow, startColumn, 1);
8965        var endFold = this.getFoldAt(endRow, endColumn, -1);
8966        if (startFold && endFold == startFold)
8967            return startFold.addSubFold(fold);
8968
8969        if (startFold && !startFold.range.isStart(startRow, startColumn))
8970            this.removeFold(startFold);
8971        
8972        if (endFold && !endFold.range.isEnd(endRow, endColumn))
8973            this.removeFold(endFold);
8974        var folds = this.getFoldsInRange(fold.range);
8975        if (folds.length > 0) {
8976            this.removeFolds(folds);
8977            folds.forEach(function(subFold) {
8978                fold.addSubFold(subFold);
8979            });
8980        }
8981
8982        for (var i = 0; i < foldData.length; i++) {
8983            var foldLine = foldData[i];
8984            if (endRow == foldLine.start.row) {
8985                foldLine.addFold(fold);
8986                added = true;
8987                break;
8988            } else if (startRow == foldLine.end.row) {
8989                foldLine.addFold(fold);
8990                added = true;
8991                if (!fold.sameRow) {
8992                    var foldLineNext = foldData[i + 1];
8993                    if (foldLineNext && foldLineNext.start.row == endRow) {
8994                        foldLine.merge(foldLineNext);
8995                        break;
8996                    }
8997                }
8998                break;
8999            } else if (endRow <= foldLine.start.row) {
9000                break;
9001            }
9002        }
9003
9004        if (!added)
9005            foldLine = this.$addFoldLine(new FoldLine(this.$foldData, fold));
9006
9007        if (this.$useWrapMode)
9008            this.$updateWrapData(foldLine.start.row, foldLine.start.row);
9009        else
9010            this.$updateRowLengthCache(foldLine.start.row, foldLine.start.row);
9011        this.$modified = true;
9012        this._signal("changeFold", { data: fold, action: "add" });
9013
9014        return fold;
9015    };
9016
9017    this.addFolds = function(folds) {
9018        folds.forEach(function(fold) {
9019            this.addFold(fold);
9020        }, this);
9021    };
9022
9023    this.removeFold = function(fold) {
9024        var foldLine = fold.foldLine;
9025        var startRow = foldLine.start.row;
9026        var endRow = foldLine.end.row;
9027
9028        var foldLines = this.$foldData;
9029        var folds = foldLine.folds;
9030        if (folds.length == 1) {
9031            foldLines.splice(foldLines.indexOf(foldLine), 1);
9032        } else
9033        if (foldLine.range.isEnd(fold.end.row, fold.end.column)) {
9034            folds.pop();
9035            foldLine.end.row = folds[folds.length - 1].end.row;
9036            foldLine.end.column = folds[folds.length - 1].end.column;
9037        } else
9038        if (foldLine.range.isStart(fold.start.row, fold.start.column)) {
9039            folds.shift();
9040            foldLine.start.row = folds[0].start.row;
9041            foldLine.start.column = folds[0].start.column;
9042        } else
9043        if (fold.sameRow) {
9044            folds.splice(folds.indexOf(fold), 1);
9045        } else
9046        {
9047            var newFoldLine = foldLine.split(fold.start.row, fold.start.column);
9048            folds = newFoldLine.folds;
9049            folds.shift();
9050            newFoldLine.start.row = folds[0].start.row;
9051            newFoldLine.start.column = folds[0].start.column;
9052        }
9053
9054        if (!this.$updating) {
9055            if (this.$useWrapMode)
9056                this.$updateWrapData(startRow, endRow);
9057            else
9058                this.$updateRowLengthCache(startRow, endRow);
9059        }
9060        this.$modified = true;
9061        this._signal("changeFold", { data: fold, action: "remove" });
9062    };
9063
9064    this.removeFolds = function(folds) {
9065        var cloneFolds = [];
9066        for (var i = 0; i < folds.length; i++) {
9067            cloneFolds.push(folds[i]);
9068        }
9069
9070        cloneFolds.forEach(function(fold) {
9071            this.removeFold(fold);
9072        }, this);
9073        this.$modified = true;
9074    };
9075
9076    this.expandFold = function(fold) {
9077        this.removeFold(fold);
9078        fold.subFolds.forEach(function(subFold) {
9079            fold.restoreRange(subFold);
9080            this.addFold(subFold);
9081        }, this);
9082        if (fold.collapseChildren > 0) {
9083            this.foldAll(fold.start.row+1, fold.end.row, fold.collapseChildren-1);
9084        }
9085        fold.subFolds = [];
9086    };
9087
9088    this.expandFolds = function(folds) {
9089        folds.forEach(function(fold) {
9090            this.expandFold(fold);
9091        }, this);
9092    };
9093
9094    this.unfold = function(location, expandInner) {
9095        var range, folds;
9096        if (location == null) {
9097            range = new Range(0, 0, this.getLength(), 0);
9098            expandInner = true;
9099        } else if (typeof location == "number")
9100            range = new Range(location, 0, location, this.getLine(location).length);
9101        else if ("row" in location)
9102            range = Range.fromPoints(location, location);
9103        else
9104            range = location;
9105        
9106        folds = this.getFoldsInRangeList(range);
9107        if (expandInner) {
9108            this.removeFolds(folds);
9109        } else {
9110            var subFolds = folds;
9111            while (subFolds.length) {
9112                this.expandFolds(subFolds);
9113                subFolds = this.getFoldsInRangeList(range);
9114            }
9115        }
9116        if (folds.length)
9117            return folds;
9118    };
9119    this.isRowFolded = function(docRow, startFoldRow) {
9120        return !!this.getFoldLine(docRow, startFoldRow);
9121    };
9122
9123    this.getRowFoldEnd = function(docRow, startFoldRow) {
9124        var foldLine = this.getFoldLine(docRow, startFoldRow);
9125        return foldLine ? foldLine.end.row : docRow;
9126    };
9127
9128    this.getRowFoldStart = function(docRow, startFoldRow) {
9129        var foldLine = this.getFoldLine(docRow, startFoldRow);
9130        return foldLine ? foldLine.start.row : docRow;
9131    };
9132
9133    this.getFoldDisplayLine = function(foldLine, endRow, endColumn, startRow, startColumn) {
9134        if (startRow == null)
9135            startRow = foldLine.start.row;
9136        if (startColumn == null)
9137            startColumn = 0;
9138        if (endRow == null)
9139            endRow = foldLine.end.row;
9140        if (endColumn == null)
9141            endColumn = this.getLine(endRow).length;
9142        var doc = this.doc;
9143        var textLine = "";
9144
9145        foldLine.walk(function(placeholder, row, column, lastColumn) {
9146            if (row < startRow)
9147                return;
9148            if (row == startRow) {
9149                if (column < startColumn)
9150                    return;
9151                lastColumn = Math.max(startColumn, lastColumn);
9152            }
9153
9154            if (placeholder != null) {
9155                textLine += placeholder;
9156            } else {
9157                textLine += doc.getLine(row).substring(lastColumn, column);
9158            }
9159        }, endRow, endColumn);
9160        return textLine;
9161    };
9162
9163    this.getDisplayLine = function(row, endColumn, startRow, startColumn) {
9164        var foldLine = this.getFoldLine(row);
9165
9166        if (!foldLine) {
9167            var line;
9168            line = this.doc.getLine(row);
9169            return line.substring(startColumn || 0, endColumn || line.length);
9170        } else {
9171            return this.getFoldDisplayLine(
9172                foldLine, row, endColumn, startRow, startColumn);
9173        }
9174    };
9175
9176    this.$cloneFoldData = function() {
9177        var fd = [];
9178        fd = this.$foldData.map(function(foldLine) {
9179            var folds = foldLine.folds.map(function(fold) {
9180                return fold.clone();
9181            });
9182            return new FoldLine(fd, folds);
9183        });
9184
9185        return fd;
9186    };
9187
9188    this.toggleFold = function(tryToUnfold) {
9189        var selection = this.selection;
9190        var range = selection.getRange();
9191        var fold;
9192        var bracketPos;
9193
9194        if (range.isEmpty()) {
9195            var cursor = range.start;
9196            fold = this.getFoldAt(cursor.row, cursor.column);
9197
9198            if (fold) {
9199                this.expandFold(fold);
9200                return;
9201            } else if (bracketPos = this.findMatchingBracket(cursor)) {
9202                if (range.comparePoint(bracketPos) == 1) {
9203                    range.end = bracketPos;
9204                } else {
9205                    range.start = bracketPos;
9206                    range.start.column++;
9207                    range.end.column--;
9208                }
9209            } else if (bracketPos = this.findMatchingBracket({row: cursor.row, column: cursor.column + 1})) {
9210                if (range.comparePoint(bracketPos) == 1)
9211                    range.end = bracketPos;
9212                else
9213                    range.start = bracketPos;
9214
9215                range.start.column++;
9216            } else {
9217                range = this.getCommentFoldRange(cursor.row, cursor.column) || range;
9218            }
9219        } else {
9220            var folds = this.getFoldsInRange(range);
9221            if (tryToUnfold && folds.length) {
9222                this.expandFolds(folds);
9223                return;
9224            } else if (folds.length == 1 ) {
9225                fold = folds[0];
9226            }
9227        }
9228
9229        if (!fold)
9230            fold = this.getFoldAt(range.start.row, range.start.column);
9231
9232        if (fold && fold.range.toString() == range.toString()) {
9233            this.expandFold(fold);
9234            return;
9235        }
9236
9237        var placeholder = "...";
9238        if (!range.isMultiLine()) {
9239            placeholder = this.getTextRange(range);
9240            if (placeholder.length < 4)
9241                return;
9242            placeholder = placeholder.trim().substring(0, 2) + "..";
9243        }
9244
9245        this.addFold(placeholder, range);
9246    };
9247
9248    this.getCommentFoldRange = function(row, column, dir) {
9249        var iterator = new TokenIterator(this, row, column);
9250        var token = iterator.getCurrentToken();
9251        var type = token.type;
9252        if (token && /^comment|string/.test(type)) {
9253            type = type.match(/comment|string/)[0];
9254            if (type == "comment")
9255                type += "|doc-start";
9256            var re = new RegExp(type);
9257            var range = new Range();
9258            if (dir != 1) {
9259                do {
9260                    token = iterator.stepBackward();
9261                } while (token && re.test(token.type));
9262                iterator.stepForward();
9263            }
9264            
9265            range.start.row = iterator.getCurrentTokenRow();
9266            range.start.column = iterator.getCurrentTokenColumn() + 2;
9267
9268            iterator = new TokenIterator(this, row, column);
9269            
9270            if (dir != -1) {
9271                var lastRow = -1;
9272                do {
9273                    token = iterator.stepForward();
9274                    if (lastRow == -1) {
9275                        var state = this.getState(iterator.$row);
9276                        if (!re.test(state))
9277                            lastRow = iterator.$row;
9278                    } else if (iterator.$row > lastRow) {
9279                        break;
9280                    }
9281                } while (token && re.test(token.type));
9282                token = iterator.stepBackward();
9283            } else
9284                token = iterator.getCurrentToken();
9285
9286            range.end.row = iterator.getCurrentTokenRow();
9287            range.end.column = iterator.getCurrentTokenColumn() + token.value.length - 2;
9288            return range;
9289        }
9290    };
9291
9292    this.foldAll = function(startRow, endRow, depth) {
9293        if (depth == undefined)
9294            depth = 100000; // JSON.stringify doesn't hanle Infinity
9295        var foldWidgets = this.foldWidgets;
9296        if (!foldWidgets)
9297            return; // mode doesn't support folding
9298        endRow = endRow || this.getLength();
9299        startRow = startRow || 0;
9300        for (var row = startRow; row < endRow; row++) {
9301            if (foldWidgets[row] == null)
9302                foldWidgets[row] = this.getFoldWidget(row);
9303            if (foldWidgets[row] != "start")
9304                continue;
9305
9306            var range = this.getFoldWidgetRange(row);
9307            if (range && range.isMultiLine()
9308                && range.end.row <= endRow
9309                && range.start.row >= startRow
9310            ) {
9311                row = range.end.row;
9312                try {
9313                    var fold = this.addFold("...", range);
9314                    if (fold)
9315                        fold.collapseChildren = depth;
9316                } catch(e) {}
9317            }
9318        }
9319    };
9320    this.$foldStyles = {
9321        "manual": 1,
9322        "markbegin": 1,
9323        "markbeginend": 1
9324    };
9325    this.$foldStyle = "markbegin";
9326    this.setFoldStyle = function(style) {
9327        if (!this.$foldStyles[style])
9328            throw new Error("invalid fold style: " + style + "[" + Object.keys(this.$foldStyles).join(", ") + "]");
9329        
9330        if (this.$foldStyle == style)
9331            return;
9332
9333        this.$foldStyle = style;
9334        
9335        if (style == "manual")
9336            this.unfold();
9337        var mode = this.$foldMode;
9338        this.$setFolding(null);
9339        this.$setFolding(mode);
9340    };
9341
9342    this.$setFolding = function(foldMode) {
9343        if (this.$foldMode == foldMode)
9344            return;
9345            
9346        this.$foldMode = foldMode;
9347        
9348        this.off('change', this.$updateFoldWidgets);
9349        this.off('tokenizerUpdate', this.$tokenizerUpdateFoldWidgets);
9350        this._signal("changeAnnotation");
9351        
9352        if (!foldMode || this.$foldStyle == "manual") {
9353            this.foldWidgets = null;
9354            return;
9355        }
9356        
9357        this.foldWidgets = [];
9358        this.getFoldWidget = foldMode.getFoldWidget.bind(foldMode, this, this.$foldStyle);
9359        this.getFoldWidgetRange = foldMode.getFoldWidgetRange.bind(foldMode, this, this.$foldStyle);
9360        
9361        this.$updateFoldWidgets = this.updateFoldWidgets.bind(this);
9362        this.$tokenizerUpdateFoldWidgets = this.tokenizerUpdateFoldWidgets.bind(this);
9363        this.on('change', this.$updateFoldWidgets);
9364        this.on('tokenizerUpdate', this.$tokenizerUpdateFoldWidgets);
9365    };
9366
9367    this.getParentFoldRangeData = function (row, ignoreCurrent) {
9368        var fw = this.foldWidgets;
9369        if (!fw || (ignoreCurrent && fw[row]))
9370            return {};
9371
9372        var i = row - 1, firstRange;
9373        while (i >= 0) {
9374            var c = fw[i];
9375            if (c == null)
9376                c = fw[i] = this.getFoldWidget(i);
9377
9378            if (c == "start") {
9379                var range = this.getFoldWidgetRange(i);
9380                if (!firstRange)
9381                    firstRange = range;
9382                if (range && range.end.row >= row)
9383                    break;
9384            }
9385            i--;
9386        }
9387
9388        return {
9389            range: i !== -1 && range,
9390            firstRange: firstRange
9391        };
9392    };
9393
9394    this.onFoldWidgetClick = function(row, e) {
9395        e = e.domEvent;
9396        var options = {
vendor: 9,695 bytes, lines 9397-9699
9397            children: e.shiftKey,
9398            all: e.ctrlKey || e.metaKey,
9399            siblings: e.altKey
9400        };
9401        
9402        var range = this.$toggleFoldWidget(row, options);
9403        if (!range) {
9404            var el = (e.target || e.srcElement);
9405            if (el && /ace_fold-widget/.test(el.className))
9406                el.className += " ace_invalid";
9407        }
9408    };
9409    
9410    this.$toggleFoldWidget = function(row, options) {
9411        if (!this.getFoldWidget)
9412            return;
9413        var type = this.getFoldWidget(row);
9414        var line = this.getLine(row);
9415
9416        var dir = type === "end" ? -1 : 1;
9417        var fold = this.getFoldAt(row, dir === -1 ? 0 : line.length, dir);
9418
9419        if (fold) {
9420            if (options.children || options.all)
9421                this.removeFold(fold);
9422            else
9423                this.expandFold(fold);
9424            return fold;
9425        }
9426
9427        var range = this.getFoldWidgetRange(row, true);
9428        if (range && !range.isMultiLine()) {
9429            fold = this.getFoldAt(range.start.row, range.start.column, 1);
9430            if (fold && range.isEqual(fold.range)) {
9431                this.removeFold(fold);
9432                return fold;
9433            }
9434        }
9435        
9436        if (options.siblings) {
9437            var data = this.getParentFoldRangeData(row);
9438            if (data.range) {
9439                var startRow = data.range.start.row + 1;
9440                var endRow = data.range.end.row;
9441            }
9442            this.foldAll(startRow, endRow, options.all ? 10000 : 0);
9443        } else if (options.children) {
9444            endRow = range ? range.end.row : this.getLength();
9445            this.foldAll(row + 1, endRow, options.all ? 10000 : 0);
9446        } else if (range) {
9447            if (options.all) 
9448                range.collapseChildren = 10000;
9449            this.addFold("...", range);
9450        }
9451        
9452        return range;
9453    };
9454    
9455    
9456    
9457    this.toggleFoldWidget = function(toggleParent) {
9458        var row = this.selection.getCursor().row;
9459        row = this.getRowFoldStart(row);
9460        var range = this.$toggleFoldWidget(row, {});
9461        
9462        if (range)
9463            return;
9464        var data = this.getParentFoldRangeData(row, true);
9465        range = data.range || data.firstRange;
9466        
9467        if (range) {
9468            row = range.start.row;
9469            var fold = this.getFoldAt(row, this.getLine(row).length, 1);
9470
9471            if (fold) {
9472                this.removeFold(fold);
9473            } else {
9474                this.addFold("...", range);
9475            }
9476        }
9477    };
9478
9479    this.updateFoldWidgets = function(delta) {
9480        var firstRow = delta.start.row;
9481        var len = delta.end.row - firstRow;
9482
9483        if (len === 0) {
9484            this.foldWidgets[firstRow] = null;
9485        } else if (delta.action == 'remove') {
9486            this.foldWidgets.splice(firstRow, len + 1, null);
9487        } else {
9488            var args = Array(len + 1);
9489            args.unshift(firstRow, 1);
9490            this.foldWidgets.splice.apply(this.foldWidgets, args);
9491        }
9492    };
9493    this.tokenizerUpdateFoldWidgets = function(e) {
9494        var rows = e.data;
9495        if (rows.first != rows.last) {
9496            if (this.foldWidgets.length > rows.first)
9497                this.foldWidgets.splice(rows.first, this.foldWidgets.length);
9498        }
9499    };
9500}
9501
9502exports.Folding = Folding;
9503
9504});
9505
9506define("ace/edit_session/bracket_match",["require","exports","module","ace/token_iterator","ace/range"], function(require, exports, module) {
9507"use strict";
9508
9509var TokenIterator = require("../token_iterator").TokenIterator;
9510var Range = require("../range").Range;
9511
9512
9513function BracketMatch() {
9514
9515    this.findMatchingBracket = function(position, chr) {
9516        if (position.column == 0) return null;
9517
9518        var charBeforeCursor = chr || this.getLine(position.row).charAt(position.column-1);
9519        if (charBeforeCursor == "") return null;
9520
9521        var match = charBeforeCursor.match(/([\(\[\{])|([\)\]\}])/);
9522        if (!match)
9523            return null;
9524
9525        if (match[1])
9526            return this.$findClosingBracket(match[1], position);
9527        else
9528            return this.$findOpeningBracket(match[2], position);
9529    };
9530    
9531    this.getBracketRange = function(pos) {
9532        var line = this.getLine(pos.row);
9533        var before = true, range;
9534
9535        var chr = line.charAt(pos.column-1);
9536        var match = chr && chr.match(/([\(\[\{])|([\)\]\}])/);
9537        if (!match) {
9538            chr = line.charAt(pos.column);
9539            pos = {row: pos.row, column: pos.column + 1};
9540            match = chr && chr.match(/([\(\[\{])|([\)\]\}])/);
9541            before = false;
9542        }
9543        if (!match)
9544            return null;
9545
9546        if (match[1]) {
9547            var bracketPos = this.$findClosingBracket(match[1], pos);
9548            if (!bracketPos)
9549                return null;
9550            range = Range.fromPoints(pos, bracketPos);
9551            if (!before) {
9552                range.end.column++;
9553                range.start.column--;
9554            }
9555            range.cursor = range.end;
9556        } else {
9557            var bracketPos = this.$findOpeningBracket(match[2], pos);
9558            if (!bracketPos)
9559                return null;
9560            range = Range.fromPoints(bracketPos, pos);
9561            if (!before) {
9562                range.start.column++;
9563                range.end.column--;
9564            }
9565            range.cursor = range.start;
9566        }
9567        
9568        return range;
9569    };
9570
9571    this.$brackets = {
9572        ")": "(",
9573        "(": ")",
9574        "]": "[",
9575        "[": "]",
9576        "{": "}",
9577        "}": "{"
9578    };
9579
9580    this.$findOpeningBracket = function(bracket, position, typeRe) {
9581        var openBracket = this.$brackets[bracket];
9582        var depth = 1;
9583
9584        var iterator = new TokenIterator(this, position.row, position.column);
9585        var token = iterator.getCurrentToken();
9586        if (!token)
9587            token = iterator.stepForward();
9588        if (!token)
9589            return;
9590        
9591         if (!typeRe){
9592            typeRe = new RegExp(
9593                "(\\.?" +
9594                token.type.replace(".", "\\.").replace("rparen", ".paren")
9595                    .replace(/\b(?:end)\b/, "(?:start|begin|end)")
9596                + ")+"
9597            );
9598        }
9599        var valueIndex = position.column - iterator.getCurrentTokenColumn() - 2;
9600        var value = token.value;
9601        
9602        while (true) {
9603        
9604            while (valueIndex >= 0) {
9605                var chr = value.charAt(valueIndex);
9606                if (chr == openBracket) {
9607                    depth -= 1;
9608                    if (depth == 0) {
9609                        return {row: iterator.getCurrentTokenRow(),
9610                            column: valueIndex + iterator.getCurrentTokenColumn()};
9611                    }
9612                }
9613                else if (chr == bracket) {
9614                    depth += 1;
9615                }
9616                valueIndex -= 1;
9617            }
9618            do {
9619                token = iterator.stepBackward();
9620            } while (token && !typeRe.test(token.type));
9621
9622            if (token == null)
9623                break;
9624                
9625            value = token.value;
9626            valueIndex = value.length - 1;
9627        }
9628        
9629        return null;
9630    };
9631
9632    this.$findClosingBracket = function(bracket, position, typeRe) {
9633        var closingBracket = this.$brackets[bracket];
9634        var depth = 1;
9635
9636        var iterator = new TokenIterator(this, position.row, position.column);
9637        var token = iterator.getCurrentToken();
9638        if (!token)
9639            token = iterator.stepForward();
9640        if (!token)
9641            return;
9642
9643        if (!typeRe){
9644            typeRe = new RegExp(
9645                "(\\.?" +
9646                token.type.replace(".", "\\.").replace("lparen", ".paren")
9647                    .replace(/\b(?:start|begin)\b/, "(?:start|begin|end)")
9648                + ")+"
9649            );
9650        }
9651        var valueIndex = position.column - iterator.getCurrentTokenColumn();
9652
9653        while (true) {
9654
9655            var value = token.value;
9656            var valueLength = value.length;
9657            while (valueIndex < valueLength) {
9658                var chr = value.charAt(valueIndex);
9659                if (chr == closingBracket) {
9660                    depth -= 1;
9661                    if (depth == 0) {
9662                        return {row: iterator.getCurrentTokenRow(),
9663                            column: valueIndex + iterator.getCurrentTokenColumn()};
9664                    }
9665                }
9666                else if (chr == bracket) {
9667                    depth += 1;
9668                }
9669                valueIndex += 1;
9670            }
9671            do {
9672                token = iterator.stepForward();
9673            } while (token && !typeRe.test(token.type));
9674
9675            if (token == null)
9676                break;
9677
9678            valueIndex = 0;
9679        }
9680        
9681        return null;
9682    };
9683}
9684exports.BracketMatch = BracketMatch;
9685
9686});
9687
9688define("ace/edit_session",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/bidihandler","ace/config","ace/lib/event_emitter","ace/selection","ace/mode/text","ace/range","ace/document","ace/background_tokenizer","ace/search_highlight","ace/edit_session/folding","ace/edit_session/bracket_match"], function(require, exports, module) {
9689"use strict";
9690
9691var oop = require("./lib/oop");
9692var lang = require("./lib/lang");
9693var BidiHandler = require("./bidihandler").BidiHandler;
9694var config = require("./config");
9695var EventEmitter = require("./lib/event_emitter").EventEmitter;
9696var Selection = require("./selection").Selection;
9697var TextMode = require("./mode/text").Mode;
9698var Range = require("./range").Range;
9699var Document = require("./document").Document;
9700var BackgroundTokenizer = require("./background_tokenizer").BackgroundTokenizer;
9701var SearchHighlight = require("./search_highlight").SearchHighlight;
9702
9703var EditSession = function(text, mode) {
9704    this.$breakpoints = [];
9705    this.$decorations = [];
9706    this.$frontMarkers = {};
9707    this.$backMarkers = {};
9708    this.$markerId = 1;
9709    this.$undoSelect = true;
9710
9711    this.$foldData = [];
9712    this.id = "session" + (++EditSession.$uid);
9713    this.$foldData.toString = function() {
9714        return this.join("\n");
9715    };
9716    this.on("changeFold", this.onChangeFold.bind(this));
9717    this.$onChange = this.onChange.bind(this);
9718
9719    if (typeof text != "object" || !text.getLine)
9720        text = new Document(text);
9721
9722    this.$bidiHandler = new BidiHandler(this);
9723    this.setDocument(text);
9724    this.selection = new Selection(this);
9725
9726    config.resetOptions(this);
9727    this.setMode(mode);
9728    config._signal("session", this);
9729};
9730
9731
9732EditSession.$uid = 0;
9733
9734(function() {
9735
9736    oop.implement(this, EventEmitter);
9737    this.setDocument = function(doc) {
9738        if (this.doc)
9739            this.doc.removeListener("change", this.$onChange);
9740
9741        this.doc = doc;
9742        doc.on("change", this.$onChange);
9743
9744        if (this.bgTokenizer)
9745            this.bgTokenizer.setDocument(this.getDocument());
9746
9747        this.resetCaches();
9748    };
9749    this.getDocument = function() {
9750        return this.doc;
9751    };
9752    this.$resetRowCache = function(docRow) {
9753        if (!docRow) {
9754            this.$docRowCache = [];
9755            this.$screenRowCache = [];
9756            return;
9757        }
9758        var l = this.$docRowCache.length;
9759        var i = this.$getRowCacheIndex(this.$docRowCache, docRow) + 1;
9760        if (l > i) {
9761            this.$docRowCache.splice(i, l);
9762            this.$screenRowCache.splice(i, l);
9763        }
9764    };
9765
9766    this.$getRowCacheIndex = function(cacheArray, val) {
9767        var low = 0;
9768        var hi = cacheArray.length - 1;
9769
9770        while (low <= hi) {
9771            var mid = (low + hi) >> 1;
9772            var c = cacheArray[mid];
9773
9774            if (val > c)
9775                low = mid + 1;
9776            else if (val < c)
9777                hi = mid - 1;
9778            else
9779                return mid;
9780        }
9781
9782        return low -1;
9783    };
9784
9785    this.resetCaches = function() {
9786        this.$modified = true;
9787        this.$wrapData = [];
9788        this.$rowLengthCache = [];
9789        this.$resetRowCache(0);
9790        if (this.bgTokenizer)
9791            this.bgTokenizer.start(0);
9792    };
9793
9794    this.onChangeFold = function(e) {
9795        var fold = e.data;
9796        this.$resetRowCache(fold.start.row);
9797    };
9798
9799    this.onChange = function(delta) {
9800        this.$modified = true;
9801        this.$bidiHandler.onChange(delta);
9802        this.$resetRowCache(delta.start.row);
9803
9804        var removedFolds = this.$updateInternalDataOnChange(delta);
9805        if (!this.$fromUndo && this.$undoManager) {
9806            if (removedFolds && removedFolds.length) {
9807                this.$undoManager.add({
9808                    action: "removeFolds",
9809                    folds:  removedFolds
9810                }, this.mergeUndoDeltas);
9811                this.mergeUndoDeltas = true;
9812            }
9813            this.$undoManager.add(delta, this.mergeUndoDeltas);
9814            this.mergeUndoDeltas = true;
9815            
9816            this.$informUndoManager.schedule();
9817        }
9818
9819        this.bgTokenizer && this.bgTokenizer.$updateOnChange(delta);
9820        this._signal("change", delta);
9821    };
9822    this.setValue = function(text) {
9823        this.doc.setValue(text);
9824        this.selection.moveTo(0, 0);
9825
9826        this.$resetRowCache(0);
9827        this.setUndoManager(this.$undoManager);
9828        this.getUndoManager().reset();
9829    };
9830    this.getValue =
9831    this.toString = function() {
9832        return this.doc.getValue();
9833    };
9834    this.getSelection = function() {
9835        return this.selection;
9836    };
9837    this.getState = function(row) {
9838        return this.bgTokenizer.getState(row);
9839    };
9840    this.getTokens = function(row) {
9841        return this.bgTokenizer.getTokens(row);
9842    };
9843    this.getTokenAt = function(row, column) {
9844        var tokens = this.bgTokenizer.getTokens(row);
9845        var token, c = 0;
9846        if (column == null) {
9847            var i = tokens.length - 1;
9848            c = this.getLine(row).length;
9849        } else {
9850            for (var i = 0; i < tokens.length; i++) {
9851                c += tokens[i].value.length;
9852                if (c >= column)
9853                    break;
9854            }
9855        }
9856        token = tokens[i];
9857        if (!token)
9858            return null;
9859        token.index = i;
9860        token.start = c - token.value.length;
9861        return token;
9862    };
9863    this.setUndoManager = function(undoManager) {
9864        this.$undoManager = undoManager;
9865        
9866        if (this.$informUndoManager)
9867            this.$informUndoManager.cancel();
9868        
9869        if (undoManager) {
9870            var self = this;
9871            undoManager.addSession(this);
9872            this.$syncInformUndoManager = function() {
9873                self.$informUndoManager.cancel();
9874                self.mergeUndoDeltas = false;
9875            };
9876            this.$informUndoManager = lang.delayedCall(this.$syncInformUndoManager);
9877        } else {
9878            this.$syncInformUndoManager = function() {};
9879        }
9880    };
9881    this.markUndoGroup = function() {
9882        if (this.$syncInformUndoManager)
9883            this.$syncInformUndoManager();
9884    };
9885    
9886    this.$defaultUndoManager = {
9887        undo: function() {},
9888        redo: function() {},
9889        reset: function() {},
9890        add: function() {},
9891        addSelection: function() {},
9892        startNewGroup: function() {},
9893        addSession: function() {}
9894    };
9895    this.getUndoManager = function() {
9896        return this.$undoManager || this.$defaultUndoManager;
9897    };
9898    this.getTabString = function() {
9899        if (this.getUseSoftTabs()) {
9900            return lang.stringRepeat(" ", this.getTabSize());
9901        } else {
9902            return "\t";
9903        }
9904    };
9905    this.setUseSoftTabs = function(val) {
vendor: 45,684 bytes, lines 9906-11248
9906        this.setOption("useSoftTabs", val);
9907    };
9908    this.getUseSoftTabs = function() {
9909        return this.$useSoftTabs && !this.$mode.$indentWithTabs;
9910    };
9911    this.setTabSize = function(tabSize) {
9912        this.setOption("tabSize", tabSize);
9913    };
9914    this.getTabSize = function() {
9915        return this.$tabSize;
9916    };
9917    this.isTabStop = function(position) {
9918        return this.$useSoftTabs && (position.column % this.$tabSize === 0);
9919    };
9920    this.setNavigateWithinSoftTabs = function (navigateWithinSoftTabs) {
9921        this.setOption("navigateWithinSoftTabs", navigateWithinSoftTabs);
9922    };
9923    this.getNavigateWithinSoftTabs = function() {
9924        return this.$navigateWithinSoftTabs;
9925    };
9926
9927    this.$overwrite = false;
9928    this.setOverwrite = function(overwrite) {
9929        this.setOption("overwrite", overwrite);
9930    };
9931    this.getOverwrite = function() {
9932        return this.$overwrite;
9933    };
9934    this.toggleOverwrite = function() {
9935        this.setOverwrite(!this.$overwrite);
9936    };
9937    this.addGutterDecoration = function(row, className) {
9938        if (!this.$decorations[row])
9939            this.$decorations[row] = "";
9940        this.$decorations[row] += " " + className;
9941        this._signal("changeBreakpoint", {});
9942    };
9943    this.removeGutterDecoration = function(row, className) {
9944        this.$decorations[row] = (this.$decorations[row] || "").replace(" " + className, "");
9945        this._signal("changeBreakpoint", {});
9946    };
9947    this.getBreakpoints = function() {
9948        return this.$breakpoints;
9949    };
9950    this.setBreakpoints = function(rows) {
9951        this.$breakpoints = [];
9952        for (var i=0; i<rows.length; i++) {
9953            this.$breakpoints[rows[i]] = "ace_breakpoint";
9954        }
9955        this._signal("changeBreakpoint", {});
9956    };
9957    this.clearBreakpoints = function() {
9958        this.$breakpoints = [];
9959        this._signal("changeBreakpoint", {});
9960    };
9961    this.setBreakpoint = function(row, className) {
9962        if (className === undefined)
9963            className = "ace_breakpoint";
9964        if (className)
9965            this.$breakpoints[row] = className;
9966        else
9967            delete this.$breakpoints[row];
9968        this._signal("changeBreakpoint", {});
9969    };
9970    this.clearBreakpoint = function(row) {
9971        delete this.$breakpoints[row];
9972        this._signal("changeBreakpoint", {});
9973    };
9974    this.addMarker = function(range, clazz, type, inFront) {
9975        var id = this.$markerId++;
9976
9977        var marker = {
9978            range : range,
9979            type : type || "line",
9980            renderer: typeof type == "function" ? type : null,
9981            clazz : clazz,
9982            inFront: !!inFront,
9983            id: id
9984        };
9985
9986        if (inFront) {
9987            this.$frontMarkers[id] = marker;
9988            this._signal("changeFrontMarker");
9989        } else {
9990            this.$backMarkers[id] = marker;
9991            this._signal("changeBackMarker");
9992        }
9993
9994        return id;
9995    };
9996    this.addDynamicMarker = function(marker, inFront) {
9997        if (!marker.update)
9998            return;
9999        var id = this.$markerId++;
10000        marker.id = id;
10001        marker.inFront = !!inFront;
10002
10003        if (inFront) {
10004            this.$frontMarkers[id] = marker;
10005            this._signal("changeFrontMarker");
10006        } else {
10007            this.$backMarkers[id] = marker;
10008            this._signal("changeBackMarker");
10009        }
10010
10011        return marker;
10012    };
10013    this.removeMarker = function(markerId) {
10014        var marker = this.$frontMarkers[markerId] || this.$backMarkers[markerId];
10015        if (!marker)
10016            return;
10017
10018        var markers = marker.inFront ? this.$frontMarkers : this.$backMarkers;
10019        delete (markers[markerId]);
10020        this._signal(marker.inFront ? "changeFrontMarker" : "changeBackMarker");
10021    };
10022    this.getMarkers = function(inFront) {
10023        return inFront ? this.$frontMarkers : this.$backMarkers;
10024    };
10025
10026    this.highlight = function(re) {
10027        if (!this.$searchHighlight) {
10028            var highlight = new SearchHighlight(null, "ace_selected-word", "text");
10029            this.$searchHighlight = this.addDynamicMarker(highlight);
10030        }
10031        this.$searchHighlight.setRegexp(re);
10032    };
10033    this.highlightLines = function(startRow, endRow, clazz, inFront) {
10034        if (typeof endRow != "number") {
10035            clazz = endRow;
10036            endRow = startRow;
10037        }
10038        if (!clazz)
10039            clazz = "ace_step";
10040
10041        var range = new Range(startRow, 0, endRow, Infinity);
10042        range.id = this.addMarker(range, clazz, "fullLine", inFront);
10043        return range;
10044    };
10045    this.setAnnotations = function(annotations) {
10046        this.$annotations = annotations;
10047        this._signal("changeAnnotation", {});
10048    };
10049    this.getAnnotations = function() {
10050        return this.$annotations || [];
10051    };
10052    this.clearAnnotations = function() {
10053        this.setAnnotations([]);
10054    };
10055    this.$detectNewLine = function(text) {
10056        var match = text.match(/^.*?(\r?\n)/m);
10057        if (match) {
10058            this.$autoNewLine = match[1];
10059        } else {
10060            this.$autoNewLine = "\n";
10061        }
10062    };
10063    this.getWordRange = function(row, column) {
10064        var line = this.getLine(row);
10065
10066        var inToken = false;
10067        if (column > 0)
10068            inToken = !!line.charAt(column - 1).match(this.tokenRe);
10069
10070        if (!inToken)
10071            inToken = !!line.charAt(column).match(this.tokenRe);
10072
10073        if (inToken)
10074            var re = this.tokenRe;
10075        else if (/^\s+$/.test(line.slice(column-1, column+1)))
10076            var re = /\s/;
10077        else
10078            var re = this.nonTokenRe;
10079
10080        var start = column;
10081        if (start > 0) {
10082            do {
10083                start--;
10084            }
10085            while (start >= 0 && line.charAt(start).match(re));
10086            start++;
10087        }
10088
10089        var end = column;
10090        while (end < line.length && line.charAt(end).match(re)) {
10091            end++;
10092        }
10093
10094        return new Range(row, start, row, end);
10095    };
10096    this.getAWordRange = function(row, column) {
10097        var wordRange = this.getWordRange(row, column);
10098        var line = this.getLine(wordRange.end.row);
10099
10100        while (line.charAt(wordRange.end.column).match(/[ \t]/)) {
10101            wordRange.end.column += 1;
10102        }
10103        return wordRange;
10104    };
10105    this.setNewLineMode = function(newLineMode) {
10106        this.doc.setNewLineMode(newLineMode);
10107    };
10108    this.getNewLineMode = function() {
10109        return this.doc.getNewLineMode();
10110    };
10111    this.setUseWorker = function(useWorker) { this.setOption("useWorker", useWorker); };
10112    this.getUseWorker = function() { return this.$useWorker; };
10113    this.onReloadTokenizer = function(e) {
10114        var rows = e.data;
10115        this.bgTokenizer.start(rows.first);
10116        this._signal("tokenizerUpdate", e);
10117    };
10118
10119    this.$modes = {};
10120    this.$mode = null;
10121    this.$modeId = null;
10122    this.setMode = function(mode, cb) {
10123        if (mode && typeof mode === "object") {
10124            if (mode.getTokenizer)
10125                return this.$onChangeMode(mode);
10126            var options = mode;
10127            var path = options.path;
10128        } else {
10129            path = mode || "ace/mode/text";
10130        }
10131        if (!this.$modes["ace/mode/text"])
10132            this.$modes["ace/mode/text"] = new TextMode();
10133
10134        if (this.$modes[path] && !options) {
10135            this.$onChangeMode(this.$modes[path]);
10136            cb && cb();
10137            return;
10138        }
10139        this.$modeId = path;
10140        config.loadModule(["mode", path], function(m) {
10141            if (this.$modeId !== path)
10142                return cb && cb();
10143            if (this.$modes[path] && !options) {
10144                this.$onChangeMode(this.$modes[path]);
10145            } else if (m && m.Mode) {
10146                m = new m.Mode(options);
10147                if (!options) {
10148                    this.$modes[path] = m;
10149                    m.$id = path;
10150                }
10151                this.$onChangeMode(m);
10152            }
10153            cb && cb();
10154        }.bind(this));
10155        if (!this.$mode)
10156            this.$onChangeMode(this.$modes["ace/mode/text"], true);
10157    };
10158
10159    this.$onChangeMode = function(mode, $isPlaceholder) {
10160        if (!$isPlaceholder)
10161            this.$modeId = mode.$id;
10162        if (this.$mode === mode) 
10163            return;
10164
10165        this.$mode = mode;
10166
10167        this.$stopWorker();
10168
10169        if (this.$useWorker)
10170            this.$startWorker();
10171
10172        var tokenizer = mode.getTokenizer();
10173
10174        if(tokenizer.addEventListener !== undefined) {
10175            var onReloadTokenizer = this.onReloadTokenizer.bind(this);
10176            tokenizer.addEventListener("update", onReloadTokenizer);
10177        }
10178
10179        if (!this.bgTokenizer) {
10180            this.bgTokenizer = new BackgroundTokenizer(tokenizer);
10181            var _self = this;
10182            this.bgTokenizer.addEventListener("update", function(e) {
10183                _self._signal("tokenizerUpdate", e);
10184            });
10185        } else {
10186            this.bgTokenizer.setTokenizer(tokenizer);
10187        }
10188
10189        this.bgTokenizer.setDocument(this.getDocument());
10190
10191        this.tokenRe = mode.tokenRe;
10192        this.nonTokenRe = mode.nonTokenRe;
10193
10194        
10195        if (!$isPlaceholder) {
10196            if (mode.attachToSession)
10197                mode.attachToSession(this);
10198            this.$options.wrapMethod.set.call(this, this.$wrapMethod);
10199            this.$setFolding(mode.foldingRules);
10200            this.bgTokenizer.start(0);
10201            this._emit("changeMode");
10202        }
10203    };
10204
10205    this.$stopWorker = function() {
10206        if (this.$worker) {
10207            this.$worker.terminate();
10208            this.$worker = null;
10209        }
10210    };
10211
10212    this.$startWorker = function() {
10213        try {
10214            this.$worker = this.$mode.createWorker(this);
10215        } catch (e) {
10216            config.warn("Could not load worker", e);
10217            this.$worker = null;
10218        }
10219    };
10220    this.getMode = function() {
10221        return this.$mode;
10222    };
10223
10224    this.$scrollTop = 0;
10225    this.setScrollTop = function(scrollTop) {
10226        if (this.$scrollTop === scrollTop || isNaN(scrollTop))
10227            return;
10228
10229        this.$scrollTop = scrollTop;
10230        this._signal("changeScrollTop", scrollTop);
10231    };
10232    this.getScrollTop = function() {
10233        return this.$scrollTop;
10234    };
10235
10236    this.$scrollLeft = 0;
10237    this.setScrollLeft = function(scrollLeft) {
10238        if (this.$scrollLeft === scrollLeft || isNaN(scrollLeft))
10239            return;
10240
10241        this.$scrollLeft = scrollLeft;
10242        this._signal("changeScrollLeft", scrollLeft);
10243    };
10244    this.getScrollLeft = function() {
10245        return this.$scrollLeft;
10246    };
10247    this.getScreenWidth = function() {
10248        this.$computeWidth();
10249        if (this.lineWidgets) 
10250            return Math.max(this.getLineWidgetMaxWidth(), this.screenWidth);
10251        return this.screenWidth;
10252    };
10253    
10254    this.getLineWidgetMaxWidth = function() {
10255        if (this.lineWidgetsWidth != null) return this.lineWidgetsWidth;
10256        var width = 0;
10257        this.lineWidgets.forEach(function(w) {
10258            if (w && w.screenWidth > width)
10259                width = w.screenWidth;
10260        });
10261        return this.lineWidgetWidth = width;
10262    };
10263
10264    this.$computeWidth = function(force) {
10265        if (this.$modified || force) {
10266            this.$modified = false;
10267
10268            if (this.$useWrapMode)
10269                return this.screenWidth = this.$wrapLimit;
10270
10271            var lines = this.doc.getAllLines();
10272            var cache = this.$rowLengthCache;
10273            var longestScreenLine = 0;
10274            var foldIndex = 0;
10275            var foldLine = this.$foldData[foldIndex];
10276            var foldStart = foldLine ? foldLine.start.row : Infinity;
10277            var len = lines.length;
10278
10279            for (var i = 0; i < len; i++) {
10280                if (i > foldStart) {
10281                    i = foldLine.end.row + 1;
10282                    if (i >= len)
10283                        break;
10284                    foldLine = this.$foldData[foldIndex++];
10285                    foldStart = foldLine ? foldLine.start.row : Infinity;
10286                }
10287
10288                if (cache[i] == null)
10289                    cache[i] = this.$getStringScreenWidth(lines[i])[0];
10290
10291                if (cache[i] > longestScreenLine)
10292                    longestScreenLine = cache[i];
10293            }
10294            this.screenWidth = longestScreenLine;
10295        }
10296    };
10297    this.getLine = function(row) {
10298        return this.doc.getLine(row);
10299    };
10300    this.getLines = function(firstRow, lastRow) {
10301        return this.doc.getLines(firstRow, lastRow);
10302    };
10303    this.getLength = function() {
10304        return this.doc.getLength();
10305    };
10306    this.getTextRange = function(range) {
10307        return this.doc.getTextRange(range || this.selection.getRange());
10308    };
10309    this.insert = function(position, text) {
10310        return this.doc.insert(position, text);
10311    };
10312    this.remove = function(range) {
10313        return this.doc.remove(range);
10314    };
10315    this.removeFullLines = function(firstRow, lastRow){
10316        return this.doc.removeFullLines(firstRow, lastRow);
10317    };
10318    this.undoChanges = function(deltas, dontSelect) {
10319        if (!deltas.length)
10320            return;
10321
10322        this.$fromUndo = true;
10323        for (var i = deltas.length - 1; i != -1; i--) {
10324            var delta = deltas[i];
10325            if (delta.action == "insert" || delta.action == "remove") {
10326                this.doc.revertDelta(delta);
10327            } else if (delta.folds) {
10328                this.addFolds(delta.folds);
10329            }
10330        }
10331        if (!dontSelect && this.$undoSelect) {
10332            if (deltas.selectionBefore)
10333                this.selection.fromJSON(deltas.selectionBefore);
10334            else
10335                this.selection.setRange(this.$getUndoSelection(deltas, true));
10336        }
10337        this.$fromUndo = false;
10338    };
10339    this.redoChanges = function(deltas, dontSelect) {
10340        if (!deltas.length)
10341            return;
10342
10343        this.$fromUndo = true;
10344        for (var i = 0; i < deltas.length; i++) {
10345            var delta = deltas[i];
10346            if (delta.action == "insert" || delta.action == "remove") {
10347                this.doc.applyDelta(delta);
10348            }
10349        }
10350
10351        if (!dontSelect && this.$undoSelect) {
10352            if (deltas.selectionAfter)
10353                this.selection.fromJSON(deltas.selectionAfter);
10354            else
10355                this.selection.setRange(this.$getUndoSelection(deltas, false));
10356        }
10357        this.$fromUndo = false;
10358    };
10359    this.setUndoSelect = function(enable) {
10360        this.$undoSelect = enable;
10361    };
10362
10363    this.$getUndoSelection = function(deltas, isUndo) {
10364        function isInsert(delta) {
10365            return isUndo ? delta.action !== "insert" : delta.action === "insert";
10366        }
10367
10368        var range, point;
10369        var lastDeltaIsInsert;
10370
10371        for (var i = 0; i < deltas.length; i++) {
10372            var delta = deltas[i];
10373            if (!delta.start) continue; // skip folds
10374            if (!range) {
10375                if (isInsert(delta)) {
10376                    range = Range.fromPoints(delta.start, delta.end);
10377                    lastDeltaIsInsert = true;
10378                } else {
10379                    range = Range.fromPoints(delta.start, delta.start);
10380                    lastDeltaIsInsert = false;
10381                }
10382                continue;
10383            }
10384            
10385            if (isInsert(delta)) {
10386                point = delta.start;
10387                if (range.compare(point.row, point.column) == -1) {
10388                    range.setStart(point);
10389                }
10390                point = delta.end;
10391                if (range.compare(point.row, point.column) == 1) {
10392                    range.setEnd(point);
10393                }
10394                lastDeltaIsInsert = true;
10395            } else {
10396                point = delta.start;
10397                if (range.compare(point.row, point.column) == -1) {
10398                    range = Range.fromPoints(delta.start, delta.start);
10399                }
10400                lastDeltaIsInsert = false;
10401            }
10402        }
10403        return range;
10404    };
10405    this.replace = function(range, text) {
10406        return this.doc.replace(range, text);
10407    };
10408    this.moveText = function(fromRange, toPosition, copy) {
10409        var text = this.getTextRange(fromRange);
10410        var folds = this.getFoldsInRange(fromRange);
10411
10412        var toRange = Range.fromPoints(toPosition, toPosition);
10413        if (!copy) {
10414            this.remove(fromRange);
10415            var rowDiff = fromRange.start.row - fromRange.end.row;
10416            var collDiff = rowDiff ? -fromRange.end.column : fromRange.start.column - fromRange.end.column;
10417            if (collDiff) {
10418                if (toRange.start.row == fromRange.end.row && toRange.start.column > fromRange.end.column)
10419                    toRange.start.column += collDiff;
10420                if (toRange.end.row == fromRange.end.row && toRange.end.column > fromRange.end.column)
10421                    toRange.end.column += collDiff;
10422            }
10423            if (rowDiff && toRange.start.row >= fromRange.end.row) {
10424                toRange.start.row += rowDiff;
10425                toRange.end.row += rowDiff;
10426            }
10427        }
10428
10429        toRange.end = this.insert(toRange.start, text);
10430        if (folds.length) {
10431            var oldStart = fromRange.start;
10432            var newStart = toRange.start;
10433            var rowDiff = newStart.row - oldStart.row;
10434            var collDiff = newStart.column - oldStart.column;
10435            this.addFolds(folds.map(function(x) {
10436                x = x.clone();
10437                if (x.start.row == oldStart.row)
10438                    x.start.column += collDiff;
10439                if (x.end.row == oldStart.row)
10440                    x.end.column += collDiff;
10441                x.start.row += rowDiff;
10442                x.end.row += rowDiff;
10443                return x;
10444            }));
10445        }
10446
10447        return toRange;
10448    };
10449    this.indentRows = function(startRow, endRow, indentString) {
10450        indentString = indentString.replace(/\t/g, this.getTabString());
10451        for (var row=startRow; row<=endRow; row++)
10452            this.doc.insertInLine({row: row, column: 0}, indentString);
10453    };
10454    this.outdentRows = function (range) {
10455        var rowRange = range.collapseRows();
10456        var deleteRange = new Range(0, 0, 0, 0);
10457        var size = this.getTabSize();
10458
10459        for (var i = rowRange.start.row; i <= rowRange.end.row; ++i) {
10460            var line = this.getLine(i);
10461
10462            deleteRange.start.row = i;
10463            deleteRange.end.row = i;
10464            for (var j = 0; j < size; ++j)
10465                if (line.charAt(j) != ' ')
10466                    break;
10467            if (j < size && line.charAt(j) == '\t') {
10468                deleteRange.start.column = j;
10469                deleteRange.end.column = j + 1;
10470            } else {
10471                deleteRange.start.column = 0;
10472                deleteRange.end.column = j;
10473            }
10474            this.remove(deleteRange);
10475        }
10476    };
10477
10478    this.$moveLines = function(firstRow, lastRow, dir) {
10479        firstRow = this.getRowFoldStart(firstRow);
10480        lastRow = this.getRowFoldEnd(lastRow);
10481        if (dir < 0) {
10482            var row = this.getRowFoldStart(firstRow + dir);
10483            if (row < 0) return 0;
10484            var diff = row-firstRow;
10485        } else if (dir > 0) {
10486            var row = this.getRowFoldEnd(lastRow + dir);
10487            if (row > this.doc.getLength()-1) return 0;
10488            var diff = row-lastRow;
10489        } else {
10490            firstRow = this.$clipRowToDocument(firstRow);
10491            lastRow = this.$clipRowToDocument(lastRow);
10492            var diff = lastRow - firstRow + 1;
10493        }
10494
10495        var range = new Range(firstRow, 0, lastRow, Number.MAX_VALUE);
10496        var folds = this.getFoldsInRange(range).map(function(x){
10497            x = x.clone();
10498            x.start.row += diff;
10499            x.end.row += diff;
10500            return x;
10501        });
10502        
10503        var lines = dir == 0
10504            ? this.doc.getLines(firstRow, lastRow)
10505            : this.doc.removeFullLines(firstRow, lastRow);
10506        this.doc.insertFullLines(firstRow+diff, lines);
10507        folds.length && this.addFolds(folds);
10508        return diff;
10509    };
10510    this.moveLinesUp = function(firstRow, lastRow) {
10511        return this.$moveLines(firstRow, lastRow, -1);
10512    };
10513    this.moveLinesDown = function(firstRow, lastRow) {
10514        return this.$moveLines(firstRow, lastRow, 1);
10515    };
10516    this.duplicateLines = function(firstRow, lastRow) {
10517        return this.$moveLines(firstRow, lastRow, 0);
10518    };
10519
10520
10521    this.$clipRowToDocument = function(row) {
10522        return Math.max(0, Math.min(row, this.doc.getLength()-1));
10523    };
10524
10525    this.$clipColumnToRow = function(row, column) {
10526        if (column < 0)
10527            return 0;
10528        return Math.min(this.doc.getLine(row).length, column);
10529    };
10530
10531
10532    this.$clipPositionToDocument = function(row, column) {
10533        column = Math.max(0, column);
10534
10535        if (row < 0) {
10536            row = 0;
10537            column = 0;
10538        } else {
10539            var len = this.doc.getLength();
10540            if (row >= len) {
10541                row = len - 1;
10542                column = this.doc.getLine(len-1).length;
10543            } else {
10544                column = Math.min(this.doc.getLine(row).length, column);
10545            }
10546        }
10547
10548        return {
10549            row: row,
10550            column: column
10551        };
10552    };
10553
10554    this.$clipRangeToDocument = function(range) {
10555        if (range.start.row < 0) {
10556            range.start.row = 0;
10557            range.start.column = 0;
10558        } else {
10559            range.start.column = this.$clipColumnToRow(
10560                range.start.row,
10561                range.start.column
10562            );
10563        }
10564
10565        var len = this.doc.getLength() - 1;
10566        if (range.end.row > len) {
10567            range.end.row = len;
10568            range.end.column = this.doc.getLine(len).length;
10569        } else {
10570            range.end.column = this.$clipColumnToRow(
10571                range.end.row,
10572                range.end.column
10573            );
10574        }
10575        return range;
10576    };
10577    this.$wrapLimit = 80;
10578    this.$useWrapMode = false;
10579    this.$wrapLimitRange = {
10580        min : null,
10581        max : null
10582    };
10583    this.setUseWrapMode = function(useWrapMode) {
10584        if (useWrapMode != this.$useWrapMode) {
10585            this.$useWrapMode = useWrapMode;
10586            this.$modified = true;
10587            this.$resetRowCache(0);
10588            if (useWrapMode) {
10589                var len = this.getLength();
10590                this.$wrapData = Array(len);
10591                this.$updateWrapData(0, len - 1);
10592            }
10593
10594            this._signal("changeWrapMode");
10595        }
10596    };
10597    this.getUseWrapMode = function() {
10598        return this.$useWrapMode;
10599    };
10600    this.setWrapLimitRange = function(min, max) {
10601        if (this.$wrapLimitRange.min !== min || this.$wrapLimitRange.max !== max) {
10602            this.$wrapLimitRange = { min: min, max: max };
10603            this.$modified = true;
10604            this.$bidiHandler.markAsDirty();
10605            if (this.$useWrapMode)
10606                this._signal("changeWrapMode");
10607        }
10608    };
10609    this.adjustWrapLimit = function(desiredLimit, $printMargin) {
10610        var limits = this.$wrapLimitRange;
10611        if (limits.max < 0)
10612            limits = {min: $printMargin, max: $printMargin};
10613        var wrapLimit = this.$constrainWrapLimit(desiredLimit, limits.min, limits.max);
10614        if (wrapLimit != this.$wrapLimit && wrapLimit > 1) {
10615            this.$wrapLimit = wrapLimit;
10616            this.$modified = true;
10617            if (this.$useWrapMode) {
10618                this.$updateWrapData(0, this.getLength() - 1);
10619                this.$resetRowCache(0);
10620                this._signal("changeWrapLimit");
10621            }
10622            return true;
10623        }
10624        return false;
10625    };
10626
10627    this.$constrainWrapLimit = function(wrapLimit, min, max) {
10628        if (min)
10629            wrapLimit = Math.max(min, wrapLimit);
10630
10631        if (max)
10632            wrapLimit = Math.min(max, wrapLimit);
10633
10634        return wrapLimit;
10635    };
10636    this.getWrapLimit = function() {
10637        return this.$wrapLimit;
10638    };
10639    this.setWrapLimit = function (limit) {
10640        this.setWrapLimitRange(limit, limit);
10641    };
10642    this.getWrapLimitRange = function() {
10643        return {
10644            min : this.$wrapLimitRange.min,
10645            max : this.$wrapLimitRange.max
10646        };
10647    };
10648
10649    this.$updateInternalDataOnChange = function(delta) {
10650        var useWrapMode = this.$useWrapMode;
10651        var action = delta.action;
10652        var start = delta.start;
10653        var end = delta.end;
10654        var firstRow = start.row;
10655        var lastRow = end.row;
10656        var len = lastRow - firstRow;
10657        var removedFolds = null;
10658        
10659        this.$updating = true;
10660        if (len != 0) {
10661            if (action === "remove") {
10662                this[useWrapMode ? "$wrapData" : "$rowLengthCache"].splice(firstRow, len);
10663
10664                var foldLines = this.$foldData;
10665                removedFolds = this.getFoldsInRange(delta);
10666                this.removeFolds(removedFolds);
10667
10668                var foldLine = this.getFoldLine(end.row);
10669                var idx = 0;
10670                if (foldLine) {
10671                    foldLine.addRemoveChars(end.row, end.column, start.column - end.column);
10672                    foldLine.shiftRow(-len);
10673
10674                    var foldLineBefore = this.getFoldLine(firstRow);
10675                    if (foldLineBefore && foldLineBefore !== foldLine) {
10676                        foldLineBefore.merge(foldLine);
10677                        foldLine = foldLineBefore;
10678                    }
10679                    idx = foldLines.indexOf(foldLine) + 1;
10680                }
10681
10682                for (idx; idx < foldLines.length; idx++) {
10683                    var foldLine = foldLines[idx];
10684                    if (foldLine.start.row >= end.row) {
10685                        foldLine.shiftRow(-len);
10686                    }
10687                }
10688
10689                lastRow = firstRow;
10690            } else {
10691                var args = Array(len);
10692                args.unshift(firstRow, 0);
10693                var arr = useWrapMode ? this.$wrapData : this.$rowLengthCache;
10694                arr.splice.apply(arr, args);
10695                var foldLines = this.$foldData;
10696                var foldLine = this.getFoldLine(firstRow);
10697                var idx = 0;
10698                if (foldLine) {
10699                    var cmp = foldLine.range.compareInside(start.row, start.column);
10700                    if (cmp == 0) {
10701                        foldLine = foldLine.split(start.row, start.column);
10702                        if (foldLine) {
10703                            foldLine.shiftRow(len);
10704                            foldLine.addRemoveChars(lastRow, 0, end.column - start.column);
10705                        }
10706                    } else
10707                    if (cmp == -1) {
10708                        foldLine.addRemoveChars(firstRow, 0, end.column - start.column);
10709                        foldLine.shiftRow(len);
10710                    }
10711                    idx = foldLines.indexOf(foldLine) + 1;
10712                }
10713
10714                for (idx; idx < foldLines.length; idx++) {
10715                    var foldLine = foldLines[idx];
10716                    if (foldLine.start.row >= firstRow) {
10717                        foldLine.shiftRow(len);
10718                    }
10719                }
10720            }
10721        } else {
10722            len = Math.abs(delta.start.column - delta.end.column);
10723            if (action === "remove") {
10724                removedFolds = this.getFoldsInRange(delta);
10725                this.removeFolds(removedFolds);
10726
10727                len = -len;
10728            }
10729            var foldLine = this.getFoldLine(firstRow);
10730            if (foldLine) {
10731                foldLine.addRemoveChars(firstRow, start.column, len);
10732            }
10733        }
10734
10735        if (useWrapMode && this.$wrapData.length != this.doc.getLength()) {
10736            console.error("doc.getLength() and $wrapData.length have to be the same!");
10737        }
10738        this.$updating = false;
10739
10740        if (useWrapMode)
10741            this.$updateWrapData(firstRow, lastRow);
10742        else
10743            this.$updateRowLengthCache(firstRow, lastRow);
10744
10745        return removedFolds;
10746    };
10747
10748    this.$updateRowLengthCache = function(firstRow, lastRow, b) {
10749        this.$rowLengthCache[firstRow] = null;
10750        this.$rowLengthCache[lastRow] = null;
10751    };
10752
10753    this.$updateWrapData = function(firstRow, lastRow) {
10754        var lines = this.doc.getAllLines();
10755        var tabSize = this.getTabSize();
10756        var wrapData = this.$wrapData;
10757        var wrapLimit = this.$wrapLimit;
10758        var tokens;
10759        var foldLine;
10760
10761        var row = firstRow;
10762        lastRow = Math.min(lastRow, lines.length - 1);
10763        while (row <= lastRow) {
10764            foldLine = this.getFoldLine(row, foldLine);
10765            if (!foldLine) {
10766                tokens = this.$getDisplayTokens(lines[row]);
10767                wrapData[row] = this.$computeWrapSplits(tokens, wrapLimit, tabSize);
10768                row ++;
10769            } else {
10770                tokens = [];
10771                foldLine.walk(function(placeholder, row, column, lastColumn) {
10772                        var walkTokens;
10773                        if (placeholder != null) {
10774                            walkTokens = this.$getDisplayTokens(
10775                                            placeholder, tokens.length);
10776                            walkTokens[0] = PLACEHOLDER_START;
10777                            for (var i = 1; i < walkTokens.length; i++) {
10778                                walkTokens[i] = PLACEHOLDER_BODY;
10779                            }
10780                        } else {
10781                            walkTokens = this.$getDisplayTokens(
10782                                lines[row].substring(lastColumn, column),
10783                                tokens.length);
10784                        }
10785                        tokens = tokens.concat(walkTokens);
10786                    }.bind(this),
10787                    foldLine.end.row,
10788                    lines[foldLine.end.row].length + 1
10789                );
10790
10791                wrapData[foldLine.start.row] = this.$computeWrapSplits(tokens, wrapLimit, tabSize);
10792                row = foldLine.end.row + 1;
10793            }
10794        }
10795    };
10796    var CHAR = 1,
10797        CHAR_EXT = 2,
10798        PLACEHOLDER_START = 3,
10799        PLACEHOLDER_BODY =  4,
10800        PUNCTUATION = 9,
10801        SPACE = 10,
10802        TAB = 11,
10803        TAB_SPACE = 12;
10804
10805
10806    this.$computeWrapSplits = function(tokens, wrapLimit, tabSize) {
10807        if (tokens.length == 0) {
10808            return [];
10809        }
10810
10811        var splits = [];
10812        var displayLength = tokens.length;
10813        var lastSplit = 0, lastDocSplit = 0;
10814
10815        var isCode = this.$wrapAsCode;
10816
10817        var indentedSoftWrap = this.$indentedSoftWrap;
10818        var maxIndent = wrapLimit <= Math.max(2 * tabSize, 8)
10819            || indentedSoftWrap === false ? 0 : Math.floor(wrapLimit / 2);
10820
10821        function getWrapIndent() {
10822            var indentation = 0;
10823            if (maxIndent === 0)
10824                return indentation;
10825            if (indentedSoftWrap) {
10826                for (var i = 0; i < tokens.length; i++) {
10827                    var token = tokens[i];
10828                    if (token == SPACE)
10829                        indentation += 1;
10830                    else if (token == TAB)
10831                        indentation += tabSize;
10832                    else if (token == TAB_SPACE)
10833                        continue;
10834                    else
10835                        break;
10836                }
10837            }
10838            if (isCode && indentedSoftWrap !== false)
10839                indentation += tabSize;
10840            return Math.min(indentation, maxIndent);
10841        }
10842        function addSplit(screenPos) {
10843            var displayed = tokens.slice(lastSplit, screenPos);
10844            var len = displayed.length;
10845            displayed.join("")
10846                .replace(/12/g, function() {
10847                    len -= 1;
10848                })
10849                .replace(/2/g, function() {
10850                    len -= 1;
10851                });
10852
10853            if (!splits.length) {
10854                indent = getWrapIndent();
10855                splits.indent = indent;
10856            }
10857            lastDocSplit += len;
10858            splits.push(lastDocSplit);
10859            lastSplit = screenPos;
10860        }
10861        var indent = 0;
10862        while (displayLength - lastSplit > wrapLimit - indent) {
10863            var split = lastSplit + wrapLimit - indent;
10864            if (tokens[split - 1] >= SPACE && tokens[split] >= SPACE) {
10865                addSplit(split);
10866                continue;
10867            }
10868            if (tokens[split] == PLACEHOLDER_START || tokens[split] == PLACEHOLDER_BODY) {
10869                for (split; split != lastSplit - 1; split--) {
10870                    if (tokens[split] == PLACEHOLDER_START) {
10871                        break;
10872                    }
10873                }
10874                if (split > lastSplit) {
10875                    addSplit(split);
10876                    continue;
10877                }
10878                split = lastSplit + wrapLimit;
10879                for (split; split < tokens.length; split++) {
10880                    if (tokens[split] != PLACEHOLDER_BODY) {
10881                        break;
10882                    }
10883                }
10884                if (split == tokens.length) {
10885                    break;  // Breaks the while-loop.
10886                }
10887                addSplit(split);
10888                continue;
10889            }
10890            var minSplit = Math.max(split - (wrapLimit -(wrapLimit>>2)), lastSplit - 1);
10891            while (split > minSplit && tokens[split] < PLACEHOLDER_START) {
10892                split --;
10893            }
10894            if (isCode) {
10895                while (split > minSplit && tokens[split] < PLACEHOLDER_START) {
10896                    split --;
10897                }
10898                while (split > minSplit && tokens[split] == PUNCTUATION) {
10899                    split --;
10900                }
10901            } else {
10902                while (split > minSplit && tokens[split] < SPACE) {
10903                    split --;
10904                }
10905            }
10906            if (split > minSplit) {
10907                addSplit(++split);
10908                continue;
10909            }
10910            split = lastSplit + wrapLimit;
10911            if (tokens[split] == CHAR_EXT)
10912                split--;
10913            addSplit(split - indent);
10914        }
10915        return splits;
10916    };
10917    this.$getDisplayTokens = function(str, offset) {
10918        var arr = [];
10919        var tabSize;
10920        offset = offset || 0;
10921
10922        for (var i = 0; i < str.length; i++) {
10923            var c = str.charCodeAt(i);
10924            if (c == 9) {
10925                tabSize = this.getScreenTabSize(arr.length + offset);
10926                arr.push(TAB);
10927                for (var n = 1; n < tabSize; n++) {
10928                    arr.push(TAB_SPACE);
10929                }
10930            }
10931            else if (c == 32) {
10932                arr.push(SPACE);
10933            } else if((c > 39 && c < 48) || (c > 57 && c < 64)) {
10934                arr.push(PUNCTUATION);
10935            }
10936            else if (c >= 0x1100 && isFullWidth(c)) {
10937                arr.push(CHAR, CHAR_EXT);
10938            } else {
10939                arr.push(CHAR);
10940            }
10941        }
10942        return arr;
10943    };
10944    this.$getStringScreenWidth = function(str, maxScreenColumn, screenColumn) {
10945        if (maxScreenColumn == 0)
10946            return [0, 0];
10947        if (maxScreenColumn == null)
10948            maxScreenColumn = Infinity;
10949        screenColumn = screenColumn || 0;
10950
10951        var c, column;
10952        for (column = 0; column < str.length; column++) {
10953            c = str.charCodeAt(column);
10954            if (c == 9) {
10955                screenColumn += this.getScreenTabSize(screenColumn);
10956            }
10957            else if (c >= 0x1100 && isFullWidth(c)) {
10958                screenColumn += 2;
10959            } else {
10960                screenColumn += 1;
10961            }
10962            if (screenColumn > maxScreenColumn) {
10963                break;
10964            }
10965        }
10966
10967        return [screenColumn, column];
10968    };
10969
10970    this.lineWidgets = null;
10971    this.getRowLength = function(row) {
10972        if (this.lineWidgets)
10973            var h = this.lineWidgets[row] && this.lineWidgets[row].rowCount || 0;
10974        else 
10975            h = 0;
10976        if (!this.$useWrapMode || !this.$wrapData[row]) {
10977            return 1 + h;
10978        } else {
10979            return this.$wrapData[row].length + 1 + h;
10980        }
10981    };
10982    this.getRowLineCount = function(row) {
10983        if (!this.$useWrapMode || !this.$wrapData[row]) {
10984            return 1;
10985        } else {
10986            return this.$wrapData[row].length + 1;
10987        }
10988    };
10989
10990    this.getRowWrapIndent = function(screenRow) {
10991        if (this.$useWrapMode) {
10992            var pos = this.screenToDocumentPosition(screenRow, Number.MAX_VALUE);
10993            var splits = this.$wrapData[pos.row];
10994            return splits.length && splits[0] < pos.column ? splits.indent : 0;
10995        } else {
10996            return 0;
10997        }
10998    };
10999    this.getScreenLastRowColumn = function(screenRow) {
11000        var pos = this.screenToDocumentPosition(screenRow, Number.MAX_VALUE);
11001        return this.documentToScreenColumn(pos.row, pos.column);
11002    };
11003    this.getDocumentLastRowColumn = function(docRow, docColumn) {
11004        var screenRow = this.documentToScreenRow(docRow, docColumn);
11005        return this.getScreenLastRowColumn(screenRow);
11006    };
11007    this.getDocumentLastRowColumnPosition = function(docRow, docColumn) {
11008        var screenRow = this.documentToScreenRow(docRow, docColumn);
11009        return this.screenToDocumentPosition(screenRow, Number.MAX_VALUE / 10);
11010    };
11011    this.getRowSplitData = function(row) {
11012        if (!this.$useWrapMode) {
11013            return undefined;
11014        } else {
11015            return this.$wrapData[row];
11016        }
11017    };
11018    this.getScreenTabSize = function(screenColumn) {
11019        return this.$tabSize - screenColumn % this.$tabSize;
11020    };
11021
11022
11023    this.screenToDocumentRow = function(screenRow, screenColumn) {
11024        return this.screenToDocumentPosition(screenRow, screenColumn).row;
11025    };
11026
11027
11028    this.screenToDocumentColumn = function(screenRow, screenColumn) {
11029        return this.screenToDocumentPosition(screenRow, screenColumn).column;
11030    };
11031    this.screenToDocumentPosition = function(screenRow, screenColumn, offsetX) {
11032        if (screenRow < 0)
11033            return {row: 0, column: 0};
11034
11035        var line;
11036        var docRow = 0;
11037        var docColumn = 0;
11038        var column;
11039        var row = 0;
11040        var rowLength = 0;
11041
11042        var rowCache = this.$screenRowCache;
11043        var i = this.$getRowCacheIndex(rowCache, screenRow);
11044        var l = rowCache.length;
11045        if (l && i >= 0) {
11046            var row = rowCache[i];
11047            var docRow = this.$docRowCache[i];
11048            var doCache = screenRow > rowCache[l - 1];
11049        } else {
11050            var doCache = !l;
11051        }
11052
11053        var maxRow = this.getLength() - 1;
11054        var foldLine = this.getNextFoldLine(docRow);
11055        var foldStart = foldLine ? foldLine.start.row : Infinity;
11056
11057        while (row <= screenRow) {
11058            rowLength = this.getRowLength(docRow);
11059            if (row + rowLength > screenRow || docRow >= maxRow) {
11060                break;
11061            } else {
11062                row += rowLength;
11063                docRow++;
11064                if (docRow > foldStart) {
11065                    docRow = foldLine.end.row+1;
11066                    foldLine = this.getNextFoldLine(docRow, foldLine);
11067                    foldStart = foldLine ? foldLine.start.row : Infinity;
11068                }
11069            }
11070
11071            if (doCache) {
11072                this.$docRowCache.push(docRow);
11073                this.$screenRowCache.push(row);
11074            }
11075        }
11076
11077        if (foldLine && foldLine.start.row <= docRow) {
11078            line = this.getFoldDisplayLine(foldLine);
11079            docRow = foldLine.start.row;
11080        } else if (row + rowLength <= screenRow || docRow > maxRow) {
11081            return {
11082                row: maxRow,
11083                column: this.getLine(maxRow).length
11084            };
11085        } else {
11086            line = this.getLine(docRow);
11087            foldLine = null;
11088        }
11089        var wrapIndent = 0, splitIndex = Math.floor(screenRow - row);
11090        if (this.$useWrapMode) {
11091            var splits = this.$wrapData[docRow];
11092            if (splits) {
11093                column = splits[splitIndex];
11094                if(splitIndex > 0 && splits.length) {
11095                    wrapIndent = splits.indent;
11096                    docColumn = splits[splitIndex - 1] || splits[splits.length - 1];
11097                    line = line.substring(docColumn);
11098                }
11099            }
11100        }
11101
11102        if (offsetX !== undefined && this.$bidiHandler.isBidiRow(row + splitIndex, docRow, splitIndex))
11103            screenColumn = this.$bidiHandler.offsetToCol(offsetX);
11104
11105        docColumn += this.$getStringScreenWidth(line, screenColumn - wrapIndent)[1];
11106        if (this.$useWrapMode && docColumn >= column)
11107            docColumn = column - 1;
11108
11109        if (foldLine)
11110            return foldLine.idxToPosition(docColumn);
11111
11112        return {row: docRow, column: docColumn};
11113    };
11114    this.documentToScreenPosition = function(docRow, docColumn) {
11115        if (typeof docColumn === "undefined")
11116            var pos = this.$clipPositionToDocument(docRow.row, docRow.column);
11117        else
11118            pos = this.$clipPositionToDocument(docRow, docColumn);
11119
11120        docRow = pos.row;
11121        docColumn = pos.column;
11122
11123        var screenRow = 0;
11124        var foldStartRow = null;
11125        var fold = null;
11126        fold = this.getFoldAt(docRow, docColumn, 1);
11127        if (fold) {
11128            docRow = fold.start.row;
11129            docColumn = fold.start.column;
11130        }
11131
11132        var rowEnd, row = 0;
11133
11134
11135        var rowCache = this.$docRowCache;
11136        var i = this.$getRowCacheIndex(rowCache, docRow);
11137        var l = rowCache.length;
11138        if (l && i >= 0) {
11139            var row = rowCache[i];
11140            var screenRow = this.$screenRowCache[i];
11141            var doCache = docRow > rowCache[l - 1];
11142        } else {
11143            var doCache = !l;
11144        }
11145
11146        var foldLine = this.getNextFoldLine(row);
11147        var foldStart = foldLine ?foldLine.start.row :Infinity;
11148
11149        while (row < docRow) {
11150            if (row >= foldStart) {
11151                rowEnd = foldLine.end.row + 1;
11152                if (rowEnd > docRow)
11153                    break;
11154                foldLine = this.getNextFoldLine(rowEnd, foldLine);
11155                foldStart = foldLine ?foldLine.start.row :Infinity;
11156            }
11157            else {
11158                rowEnd = row + 1;
11159            }
11160
11161            screenRow += this.getRowLength(row);
11162            row = rowEnd;
11163
11164            if (doCache) {
11165                this.$docRowCache.push(row);
11166                this.$screenRowCache.push(screenRow);
11167            }
11168        }
11169        var textLine = "";
11170        if (foldLine && row >= foldStart) {
11171            textLine = this.getFoldDisplayLine(foldLine, docRow, docColumn);
11172            foldStartRow = foldLine.start.row;
11173        } else {
11174            textLine = this.getLine(docRow).substring(0, docColumn);
11175            foldStartRow = docRow;
11176        }
11177        var wrapIndent = 0;
11178        if (this.$useWrapMode) {
11179            var wrapRow = this.$wrapData[foldStartRow];
11180            if (wrapRow) {
11181                var screenRowOffset = 0;
11182                while (textLine.length >= wrapRow[screenRowOffset]) {
11183                    screenRow ++;
11184                    screenRowOffset++;
11185                }
11186                textLine = textLine.substring(
11187                    wrapRow[screenRowOffset - 1] || 0, textLine.length
11188                );
11189                wrapIndent = screenRowOffset > 0 ? wrapRow.indent : 0;
11190            }
11191        }
11192
11193        return {
11194            row: screenRow,
11195            column: wrapIndent + this.$getStringScreenWidth(textLine)[0]
11196        };
11197    };
11198    this.documentToScreenColumn = function(row, docColumn) {
11199        return this.documentToScreenPosition(row, docColumn).column;
11200    };
11201    this.documentToScreenRow = function(docRow, docColumn) {
11202        return this.documentToScreenPosition(docRow, docColumn).row;
11203    };
11204    this.getScreenLength = function() {
11205        var screenRows = 0;
11206        var fold = null;
11207        if (!this.$useWrapMode) {
11208            screenRows = this.getLength();
11209            var foldData = this.$foldData;
11210            for (var i = 0; i < foldData.length; i++) {
11211                fold = foldData[i];
11212                screenRows -= fold.end.row - fold.start.row;
11213            }
11214        } else {
11215            var lastRow = this.$wrapData.length;
11216            var row = 0, i = 0;
11217            var fold = this.$foldData[i++];
11218            var foldStart = fold ? fold.start.row :Infinity;
11219
11220            while (row < lastRow) {
11221                var splits = this.$wrapData[row];
11222                screenRows += splits ? splits.length + 1 : 1;
11223                row ++;
11224                if (row > foldStart) {
11225                    row = fold.end.row+1;
11226                    fold = this.$foldData[i++];
11227                    foldStart = fold ?fold.start.row :Infinity;
11228                }
11229            }
11230        }
11231        if (this.lineWidgets)
11232            screenRows += this.$getWidgetScreenLength();
11233
11234        return screenRows;
11235    };
11236    this.$setFontMetrics = function(fm) {
11237        if (!this.$enableVarChar) return;
11238        this.$getStringScreenWidth = function(str, maxScreenColumn, screenColumn) {
11239            if (maxScreenColumn === 0)
11240                return [0, 0];
11241            if (!maxScreenColumn)
11242                maxScreenColumn = Infinity;
11243            screenColumn = screenColumn || 0;
11244            
11245            var c, column;
11246            for (column = 0; column < str.length; column++) {
11247                c = str.charAt(column);
11248                if (c === "\t") {
11249                    screenColumn += this.getScreenTabSize(screenColumn);
11250                } else {
11251                    screenColumn += fm.getCharacterWidth(c);
11252                }
11253                if (screenColumn > maxScreenColumn) {
11254                    break;
11255                }
11256            }
11257            
11258            return [screenColumn, column];
11259        };
11260    };
11261    
11262    this.destroy = function() {
11263        if (this.bgTokenizer) {
11264            this.bgTokenizer.setDocument(null);
11265            this.bgTokenizer = null;
11266        }
11267        this.$stopWorker();
11268    };
11269
11270    this.isFullWidth = isFullWidth;
11271    function isFullWidth(c) {
11272        if (c < 0x1100)
11273            return false;
11274        return c >= 0x1100 && c <= 0x115F ||
11275               c >= 0x11A3 && c <= 0x11A7 ||
11276               c >= 0x11FA && c <= 0x11FF ||
11277               c >= 0x2329 && c <= 0x232A ||
11278               c >= 0x2E80 && c <= 0x2E99 ||
11279               c >= 0x2E9B && c <= 0x2EF3 ||
11280               c >= 0x2F00 && c <= 0x2FD5 ||
11281               c >= 0x2FF0 && c <= 0x2FFB ||
11282               c >= 0x3000 && c <= 0x303E ||
11283               c >= 0x3041 && c <= 0x3096 ||
11284               c >= 0x3099 && c <= 0x30FF ||
11285               c >= 0x3105 && c <= 0x312D ||
11286               c >= 0x3131 && c <= 0x318E ||
11287               c >= 0x3190 && c <= 0x31BA ||
11288               c >= 0x31C0 && c <= 0x31E3 ||
11289               c >= 0x31F0 && c <= 0x321E ||
11290               c >= 0x3220 && c <= 0x3247 ||
11291               c >= 0x3250 && c <= 0x32FE ||
11292               c >= 0x3300 && c <= 0x4DBF ||
11293               c >= 0x4E00 && c <= 0xA48C ||
11294               c >= 0xA490 && c <= 0xA4C6 ||
11295               c >= 0xA960 && c <= 0xA97C ||
11296               c >= 0xAC00 && c <= 0xD7A3 ||
11297               c >= 0xD7B0 && c <= 0xD7C6 ||
11298               c >= 0xD7CB && c <= 0xD7FB ||
11299               c >= 0xF900 && c <= 0xFAFF ||
11300               c >= 0xFE10 && c <= 0xFE19 ||
11301               c >= 0xFE30 && c <= 0xFE52 ||
11302               c >= 0xFE54 && c <= 0xFE66 ||
11303               c >= 0xFE68 && c <= 0xFE6B ||
11304               c >= 0xFF01 && c <= 0xFF60 ||
11305               c >= 0xFFE0 && c <= 0xFFE6;
11306    }
11307
11308}).call(EditSession.prototype);
11309
11310require("./edit_session/folding").Folding.call(EditSession.prototype);
11311require("./edit_session/bracket_match").BracketMatch.call(EditSession.prototype);
11312
11313
11314config.defineOptions(EditSession.prototype, "session", {
11315    wrap: {
11316        set: function(value) {
11317            if (!value || value == "off")
11318                value = false;
11319            else if (value == "free")
11320                value = true;
11321            else if (value == "printMargin")
11322                value = -1;
11323            else if (typeof value == "string")
11324                value = parseInt(value, 10) || false;
11325
11326            if (this.$wrap == value)
11327                return;
11328            this.$wrap = value;
11329            if (!value) {
11330                this.setUseWrapMode(false);
11331            } else {
11332                var col = typeof value == "number" ? value : null;
11333                this.setWrapLimitRange(col, col);
11334                this.setUseWrapMode(true);
11335            }
11336        },
11337        get: function() {
11338            if (this.getUseWrapMode()) {
11339                if (this.$wrap == -1)
11340                    return "printMargin";
11341                if (!this.getWrapLimitRange().min)
11342                    return "free";
11343                return this.$wrap;
11344            }
11345            return "off";
11346        },
11347        handlesSet: true
11348    },    
11349    wrapMethod: {
11350        set: function(val) {
11351            val = val == "auto"
11352                ? this.$mode.type != "text"
11353                : val != "text";
11354            if (val != this.$wrapAsCode) {
11355                this.$wrapAsCode = val;
11356                if (this.$useWrapMode) {
11357                    this.$modified = true;
11358                    this.$resetRowCache(0);
11359                    this.$updateWrapData(0, this.getLength() - 1);
11360                }
11361            }
11362        },
11363        initialValue: "auto"
11364    },
11365    indentedSoftWrap: { initialValue: true },
11366    firstLineNumber: {
11367        set: function() {this._signal("changeBreakpoint");},
11368        initialValue: 1
11369    },
11370    useWorker: {
11371        set: function(useWorker) {
11372            this.$useWorker = useWorker;
11373
11374            this.$stopWorker();
11375            if (useWorker)
11376                this.$startWorker();
11377        },
11378        initialValue: true
11379    },
11380    useSoftTabs: {initialValue: true},
11381    tabSize: {
11382        set: function(tabSize) {
11383            if (isNaN(tabSize) || this.$tabSize === tabSize) return;
11384
11385            this.$modified = true;
11386            this.$rowLengthCache = [];
11387            this.$tabSize = tabSize;
11388            this._signal("changeTabSize");
11389        },
11390        initialValue: 4,
11391        handlesSet: true
11392    },
11393    navigateWithinSoftTabs: {initialValue: false},
11394    foldStyle: {
11395        set: function(val) {this.setFoldStyle(val);},
11396        handlesSet: true
11397    },
11398    overwrite: {
11399        set: function(val) {this._signal("changeOverwrite");},
11400        initialValue: false
11401    },
11402    newLineMode: {
11403        set: function(val) {this.doc.setNewLineMode(val);},
11404        get: function() {return this.doc.getNewLineMode();},
11405        handlesSet: true
11406    },
11407    mode: {
11408        set: function(val) { this.setMode(val); },
11409        get: function() { return this.$modeId; }
11410    }
11411});
11412
11413exports.EditSession = EditSession;
11414});
11415
11416define("ace/search",["require","exports","module","ace/lib/lang","ace/lib/oop","ace/range"], function(require, exports, module) {
11417"use strict";
11418
11419var lang = require("./lib/lang");
11420var oop = require("./lib/oop");
11421var Range = require("./range").Range;
11422
11423var Search = function() {
11424    this.$options = {};
11425};
11426
11427(function() {
11428    this.set = function(options) {
11429        oop.mixin(this.$options, options);
11430        return this;
11431    };
11432    this.getOptions = function() {
11433        return lang.copyObject(this.$options);
11434    };
11435    this.setOptions = function(options) {
11436        this.$options = options;
11437    };
11438    this.find = function(session) {
11439        var options = this.$options;
11440        var iterator = this.$matchIterator(session, options);
11441        if (!iterator)
11442            return false;
11443
11444        var firstRange = null;
11445        iterator.forEach(function(sr, sc, er, ec) {
11446            firstRange = new Range(sr, sc, er, ec);
11447            if (sc == ec && options.start && options.start.start
11448                && options.skipCurrent != false && firstRange.isEqual(options.start)
11449            ) {
11450                firstRange = null;
11451                return false;
11452            }
11453            
11454            return true;
11455        });
11456
11457        return firstRange;
11458    };
11459    this.findAll = function(session) {
11460        var options = this.$options;
11461        if (!options.needle)
11462            return [];
11463        this.$assembleRegExp(options);
11464
11465        var range = options.range;
11466        var lines = range
11467            ? session.getLines(range.start.row, range.end.row)
11468            : session.doc.getAllLines();
11469
11470        var ranges = [];
11471        var re = options.re;
11472        if (options.$isMultiLine) {
11473            var len = re.length;
11474            var maxRow = lines.length - len;
11475            var prevRange;
11476            outer: for (var row = re.offset || 0; row <= maxRow; row++) {
11477                for (var j = 0; j < len; j++)
11478                    if (lines[row + j].search(re[j]) == -1)
11479                        continue outer;
11480                
11481                var startLine = lines[row];
11482                var line = lines[row + len - 1];
11483                var startIndex = startLine.length - startLine.match(re[0])[0].length;
11484                var endIndex = line.match(re[len - 1])[0].length;
11485                
11486                if (prevRange && prevRange.end.row === row &&
11487                    prevRange.end.column > startIndex
11488                ) {
11489                    continue;
11490                }
11491                ranges.push(prevRange = new Range(
11492                    row, startIndex, row + len - 1, endIndex
11493                ));
11494                if (len > 2)
11495                    row = row + len - 2;
11496            }
11497        } else {
11498            for (var i = 0; i < lines.length; i++) {
11499                var matches = lang.getMatchOffsets(lines[i], re);
11500                for (var j = 0; j < matches.length; j++) {
11501                    var match = matches[j];
11502                    ranges.push(new Range(i, match.offset, i, match.offset + match.length));
11503                }
11504            }
11505        }
11506
11507        if (range) {
11508            var startColumn = range.start.column;
11509            var endColumn = range.start.column;
11510            var i = 0, j = ranges.length - 1;
11511            while (i < j && ranges[i].start.column < startColumn && ranges[i].start.row == range.start.row)
11512                i++;
11513
11514            while (i < j && ranges[j].end.column > endColumn && ranges[j].end.row == range.end.row)
11515                j--;
11516            
11517            ranges = ranges.slice(i, j + 1);
11518            for (i = 0, j = ranges.length; i < j; i++) {
11519                ranges[i].start.row += range.start.row;
11520                ranges[i].end.row += range.start.row;
11521            }
11522        }
11523
11524        return ranges;
11525    };
11526    this.replace = function(input, replacement) {
11527        var options = this.$options;
11528
11529        var re = this.$assembleRegExp(options);
11530        if (options.$isMultiLine)
11531            return replacement;
11532
11533        if (!re)
11534            return;
11535
11536        var match = re.exec(input);
11537        if (!match || match[0].length != input.length)
11538            return null;
11539        
11540        replacement = input.replace(re, replacement);
11541        if (options.preserveCase) {
11542            replacement = replacement.split("");
11543            for (var i = Math.min(input.length, input.length); i--; ) {
11544                var ch = input[i];
11545                if (ch && ch.toLowerCase() != ch)
11546                    replacement[i] = replacement[i].toUpperCase();
11547                else
11548                    replacement[i] = replacement[i].toLowerCase();
11549            }
11550            replacement = replacement.join("");
11551        }
11552        
11553        return replacement;
11554    };
11555
11556    this.$assembleRegExp = function(options, $disableFakeMultiline) {
11557        if (options.needle instanceof RegExp)
11558            return options.re = options.needle;
11559
11560        var needle = options.needle;
11561
11562        if (!options.needle)
11563            return options.re = false;
vendor: 4,618 bytes, lines 11564-11683
11564
11565        if (!options.regExp)
11566            needle = lang.escapeRegExp(needle);
11567
11568        if (options.wholeWord)
11569            needle = addWordBoundary(needle, options);
11570
11571        var modifier = options.caseSensitive ? "gm" : "gmi";
11572
11573        options.$isMultiLine = !$disableFakeMultiline && /[\n\r]/.test(needle);
11574        if (options.$isMultiLine)
11575            return options.re = this.$assembleMultilineRegExp(needle, modifier);
11576
11577        try {
11578            var re = new RegExp(needle, modifier);
11579        } catch(e) {
11580            re = false;
11581        }
11582        return options.re = re;
11583    };
11584
11585    this.$assembleMultilineRegExp = function(needle, modifier) {
11586        var parts = needle.replace(/\r\n|\r|\n/g, "$\n^").split("\n");
11587        var re = [];
11588        for (var i = 0; i < parts.length; i++) try {
11589            re.push(new RegExp(parts[i], modifier));
11590        } catch(e) {
11591            return false;
11592        }
11593        return re;
11594    };
11595
11596    this.$matchIterator = function(session, options) {
11597        var re = this.$assembleRegExp(options);
11598        if (!re)
11599            return false;
11600        var backwards = options.backwards == true;
11601        var skipCurrent = options.skipCurrent != false;
11602
11603        var range = options.range;
11604        var start = options.start;
11605        if (!start)
11606            start = range ? range[backwards ? "end" : "start"] : session.selection.getRange();
11607         
11608        if (start.start)
11609            start = start[skipCurrent != backwards ? "end" : "start"];
11610
11611        var firstRow = range ? range.start.row : 0;
11612        var lastRow = range ? range.end.row : session.getLength() - 1;
11613        
11614        if (backwards) {
11615            var forEach = function(callback) {
11616                var row = start.row;
11617                if (forEachInLine(row, start.column, callback))
11618                    return;
11619                for (row--; row >= firstRow; row--)
11620                    if (forEachInLine(row, Number.MAX_VALUE, callback))
11621                        return;
11622                if (options.wrap == false)
11623                    return;
11624                for (row = lastRow, firstRow = start.row; row >= firstRow; row--)
11625                    if (forEachInLine(row, Number.MAX_VALUE, callback))
11626                        return;
11627            };
11628        }
11629        else {
11630            var forEach = function(callback) {
11631                var row = start.row;
11632                if (forEachInLine(row, start.column, callback))
11633                    return;
11634                for (row = row + 1; row <= lastRow; row++)
11635                    if (forEachInLine(row, 0, callback))
11636                        return;
11637                if (options.wrap == false)
11638                    return;
11639                for (row = firstRow, lastRow = start.row; row <= lastRow; row++)
11640                    if (forEachInLine(row, 0, callback))
11641                        return;
11642            };
11643        }
11644        
11645        if (options.$isMultiLine) {
11646            var len = re.length;
11647            var forEachInLine = function(row, offset, callback) {
11648                var startRow = backwards ? row - len + 1 : row;
11649                if (startRow < 0) return;
11650                var line = session.getLine(startRow);
11651                var startIndex = line.search(re[0]);
11652                if (!backwards && startIndex < offset || startIndex === -1) return;
11653                for (var i = 1; i < len; i++) {
11654                    line = session.getLine(startRow + i);
11655                    if (line.search(re[i]) == -1)
11656                        return;
11657                }
11658                var endIndex = line.match(re[len - 1])[0].length;
11659                if (backwards && endIndex > offset) return;
11660                if (callback(startRow, startIndex, startRow + len - 1, endIndex))
11661                    return true;
11662            };
11663        }
11664        else if (backwards) {
11665            var forEachInLine = function(row, endIndex, callback) {
11666                var line = session.getLine(row);
11667                var matches = [];
11668                var m, last = 0;
11669                re.lastIndex = 0;
11670                while((m = re.exec(line))) {
11671                    var length = m[0].length;
11672                    last = m.index;
11673                    if (!length) {
11674                        if (last >= line.length) break;
11675                        re.lastIndex = last += 1;
11676                    }
11677                    if (m.index + length > endIndex)
11678                        break;
11679                    matches.push(m.index, length);
11680                }
11681                for (var i = matches.length - 1; i >= 0; i -= 2) {
11682                    var column = matches[i - 1];
11683                    var length = matches[i];
11684                    if (callback(row, column, row, column + length))
11685                        return true;
11686                }
11687            };
11688        }
11689        else {
11690            var forEachInLine = function(row, startIndex, callback) {
11691                var line = session.getLine(row);
11692                var last;
11693                var m;
11694                re.lastIndex = startIndex;
11695                while((m = re.exec(line))) {
11696                    var length = m[0].length;
11697                    last = m.index;
11698                    if (callback(row, last, row,last + length))
11699                        return true;
11700                    if (!length) {
11701                        re.lastIndex = last += 1;
11702                        if (last >= line.length) return false;
11703                    }
11704                }
11705            };
11706        }
11707        return {forEach: forEach};
11708    };
11709
11710}).call(Search.prototype);
11711
11712function addWordBoundary(needle, options) {
11713    function wordBoundary(c) {
11714        if (/\w/.test(c) || options.regExp) return "\\b";
11715        return "";
11716    }
11717    return wordBoundary(needle[0]) + needle
11718        + wordBoundary(needle[needle.length - 1]);
11719}
11720
11721exports.Search = Search;
11722});
11723
11724define("ace/keyboard/hash_handler",["require","exports","module","ace/lib/keys","ace/lib/useragent"], function(require, exports, module) {
11725"use strict";
11726
11727var keyUtil = require("../lib/keys");
11728var useragent = require("../lib/useragent");
11729var KEY_MODS = keyUtil.KEY_MODS;
11730
11731function HashHandler(config, platform) {
11732    this.platform = platform || (useragent.isMac ? "mac" : "win");
11733    this.commands = {};
11734    this.commandKeyBinding = {};
11735    this.addCommands(config);
11736    this.$singleCommand = true;
11737}
11738
11739function MultiHashHandler(config, platform) {
11740    HashHandler.call(this, config, platform);
11741    this.$singleCommand = false;
11742}
11743
11744MultiHashHandler.prototype = HashHandler.prototype;
11745
11746(function() {
11747    
11748
11749    this.addCommand = function(command) {
11750        if (this.commands[command.name])
11751            this.removeCommand(command);
11752
11753        this.commands[command.name] = command;
11754
11755        if (command.bindKey)
11756            this._buildKeyHash(command);
11757    };
11758
11759    this.removeCommand = function(command, keepCommand) {
11760        var name = command && (typeof command === 'string' ? command : command.name);
11761        command = this.commands[name];
11762        if (!keepCommand)
11763            delete this.commands[name];
11764        var ckb = this.commandKeyBinding;
11765        for (var keyId in ckb) {
11766            var cmdGroup = ckb[keyId];
11767            if (cmdGroup == command) {
11768                delete ckb[keyId];
11769            } else if (Array.isArray(cmdGroup)) {
11770                var i = cmdGroup.indexOf(command);
11771                if (i != -1) {
11772                    cmdGroup.splice(i, 1);
11773                    if (cmdGroup.length == 1)
11774                        ckb[keyId] = cmdGroup[0];
11775                }
11776            }
11777        }
11778    };
11779
11780    this.bindKey = function(key, command, position) {
11781        if (typeof key == "object" && key) {
11782            if (position == undefined)
11783                position = key.position;
11784            key = key[this.platform];
11785        }
11786        if (!key)
11787            return;
11788        if (typeof command == "function")
11789            return this.addCommand({exec: command, bindKey: key, name: command.name || key});
11790        
11791        key.split("|").forEach(function(keyPart) {
11792            var chain = "";
11793            if (keyPart.indexOf(" ") != -1) {
11794                var parts = keyPart.split(/\s+/);
11795                keyPart = parts.pop();
11796                parts.forEach(function(keyPart) {
11797                    var binding = this.parseKeys(keyPart);
11798                    var id = KEY_MODS[binding.hashId] + binding.key;
11799                    chain += (chain ? " " : "") + id;
11800                    this._addCommandToBinding(chain, "chainKeys");
11801                }, this);
11802                chain += " ";
11803            }
11804            var binding = this.parseKeys(keyPart);
11805            var id = KEY_MODS[binding.hashId] + binding.key;
11806            this._addCommandToBinding(chain + id, command, position);
11807        }, this);
11808    };
11809    
11810    function getPosition(command) {
11811        return typeof command == "object" && command.bindKey
11812            && command.bindKey.position 
11813            || (command.isDefault ? -100 : 0);
11814    }
11815    this._addCommandToBinding = function(keyId, command, position) {
11816        var ckb = this.commandKeyBinding, i;
11817        if (!command) {
11818            delete ckb[keyId];
11819        } else if (!ckb[keyId] || this.$singleCommand) {
11820            ckb[keyId] = command;
11821        } else {
11822            if (!Array.isArray(ckb[keyId])) {
11823                ckb[keyId] = [ckb[keyId]];
11824            }
vendor: 29,707 bytes, lines 11824-12741
11824 else if ((i = ckb[keyId].indexOf(command)) != -1) {
11825                ckb[keyId].splice(i, 1);
11826            }
11827            
11828            if (typeof position != "number") {
11829                position = getPosition(command);
11830            }
11831
11832            var commands = ckb[keyId];
11833            for (i = 0; i < commands.length; i++) {
11834                var other = commands[i];
11835                var otherPos = getPosition(other);
11836                if (otherPos > position)
11837                    break;
11838            }
11839            commands.splice(i, 0, command);
11840        }
11841    };
11842
11843    this.addCommands = function(commands) {
11844        commands && Object.keys(commands).forEach(function(name) {
11845            var command = commands[name];
11846            if (!command)
11847                return;
11848            
11849            if (typeof command === "string")
11850                return this.bindKey(command, name);
11851
11852            if (typeof command === "function")
11853                command = { exec: command };
11854
11855            if (typeof command !== "object")
11856                return;
11857
11858            if (!command.name)
11859                command.name = name;
11860
11861            this.addCommand(command);
11862        }, this);
11863    };
11864
11865    this.removeCommands = function(commands) {
11866        Object.keys(commands).forEach(function(name) {
11867            this.removeCommand(commands[name]);
11868        }, this);
11869    };
11870
11871    this.bindKeys = function(keyList) {
11872        Object.keys(keyList).forEach(function(key) {
11873            this.bindKey(key, keyList[key]);
11874        }, this);
11875    };
11876
11877    this._buildKeyHash = function(command) {
11878        this.bindKey(command.bindKey, command);
11879    };
11880    this.parseKeys = function(keys) {
11881        var parts = keys.toLowerCase().split(/[\-\+]([\-\+])?/).filter(function(x){return x;});
11882        var key = parts.pop();
11883
11884        var keyCode = keyUtil[key];
11885        if (keyUtil.FUNCTION_KEYS[keyCode])
11886            key = keyUtil.FUNCTION_KEYS[keyCode].toLowerCase();
11887        else if (!parts.length)
11888            return {key: key, hashId: -1};
11889        else if (parts.length == 1 && parts[0] == "shift")
11890            return {key: key.toUpperCase(), hashId: -1};
11891
11892        var hashId = 0;
11893        for (var i = parts.length; i--;) {
11894            var modifier = keyUtil.KEY_MODS[parts[i]];
11895            if (modifier == null) {
11896                if (typeof console != "undefined")
11897                    console.error("invalid modifier " + parts[i] + " in " + keys);
11898                return false;
11899            }
11900            hashId |= modifier;
11901        }
11902        return {key: key, hashId: hashId};
11903    };
11904
11905    this.findKeyCommand = function findKeyCommand(hashId, keyString) {
11906        var key = KEY_MODS[hashId] + keyString;
11907        return this.commandKeyBinding[key];
11908    };
11909
11910    this.handleKeyboard = function(data, hashId, keyString, keyCode) {
11911        if (keyCode < 0) return;
11912        var key = KEY_MODS[hashId] + keyString;
11913        var command = this.commandKeyBinding[key];
11914        if (data.$keyChain) {
11915            data.$keyChain += " " + key;
11916            command = this.commandKeyBinding[data.$keyChain] || command;
11917        }
11918        
11919        if (command) {
11920            if (command == "chainKeys" || command[command.length - 1] == "chainKeys") {
11921                data.$keyChain = data.$keyChain || key;
11922                return {command: "null"};
11923            }
11924        }
11925        
11926        if (data.$keyChain) {
11927            if ((!hashId || hashId == 4) && keyString.length == 1)
11928                data.$keyChain = data.$keyChain.slice(0, -key.length - 1); // wait for input
11929            else if (hashId == -1 || keyCode > 0)
11930                data.$keyChain = ""; // reset keyChain
11931        }
11932        return {command: command};
11933    };
11934    
11935    this.getStatusText = function(editor, data) {
11936        return data.$keyChain || "";
11937    };
11938
11939}).call(HashHandler.prototype);
11940
11941exports.HashHandler = HashHandler;
11942exports.MultiHashHandler = MultiHashHandler;
11943});
11944
11945define("ace/commands/command_manager",["require","exports","module","ace/lib/oop","ace/keyboard/hash_handler","ace/lib/event_emitter"], function(require, exports, module) {
11946"use strict";
11947
11948var oop = require("../lib/oop");
11949var MultiHashHandler = require("../keyboard/hash_handler").MultiHashHandler;
11950var EventEmitter = require("../lib/event_emitter").EventEmitter;
11951
11952var CommandManager = function(platform, commands) {
11953    MultiHashHandler.call(this, commands, platform);
11954    this.byName = this.commands;
11955    this.setDefaultHandler("exec", function(e) {
11956        return e.command.exec(e.editor, e.args || {});
11957    });
11958};
11959
11960oop.inherits(CommandManager, MultiHashHandler);
11961
11962(function() {
11963
11964    oop.implement(this, EventEmitter);
11965
11966    this.exec = function(command, editor, args) {
11967        if (Array.isArray(command)) {
11968            for (var i = command.length; i--; ) {
11969                if (this.exec(command[i], editor, args)) return true;
11970            }
11971            return false;
11972        }
11973
11974        if (typeof command === "string")
11975            command = this.commands[command];
11976
11977        if (!command)
11978            return false;
11979
11980        if (editor && editor.$readOnly && !command.readOnly)
11981            return false;
11982
11983        if (command.isAvailable && !command.isAvailable(editor))
11984            return false;
11985
11986        var e = {editor: editor, command: command, args: args};
11987        e.returnValue = this._emit("exec", e);
11988        this._signal("afterExec", e);
11989
11990        return e.returnValue === false ? false : true;
11991    };
11992
11993    this.toggleRecording = function(editor) {
11994        if (this.$inReplay)
11995            return;
11996
11997        editor && editor._emit("changeStatus");
11998        if (this.recording) {
11999            this.macro.pop();
12000            this.removeEventListener("exec", this.$addCommandToMacro);
12001
12002            if (!this.macro.length)
12003                this.macro = this.oldMacro;
12004
12005            return this.recording = false;
12006        }
12007        if (!this.$addCommandToMacro) {
12008            this.$addCommandToMacro = function(e) {
12009                this.macro.push([e.command, e.args]);
12010            }.bind(this);
12011        }
12012
12013        this.oldMacro = this.macro;
12014        this.macro = [];
12015        this.on("exec", this.$addCommandToMacro);
12016        return this.recording = true;
12017    };
12018
12019    this.replay = function(editor) {
12020        if (this.$inReplay || !this.macro)
12021            return;
12022
12023        if (this.recording)
12024            return this.toggleRecording(editor);
12025
12026        try {
12027            this.$inReplay = true;
12028            this.macro.forEach(function(x) {
12029                if (typeof x == "string")
12030                    this.exec(x, editor);
12031                else
12032                    this.exec(x[0], editor, x[1]);
12033            }, this);
12034        } finally {
12035            this.$inReplay = false;
12036        }
12037    };
12038
12039    this.trimMacro = function(m) {
12040        return m.map(function(x){
12041            if (typeof x[0] != "string")
12042                x[0] = x[0].name;
12043            if (!x[1])
12044                x = x[0];
12045            return x;
12046        });
12047    };
12048
12049}).call(CommandManager.prototype);
12050
12051exports.CommandManager = CommandManager;
12052
12053});
12054
12055define("ace/commands/default_commands",["require","exports","module","ace/lib/lang","ace/config","ace/range"], function(require, exports, module) {
12056"use strict";
12057
12058var lang = require("../lib/lang");
12059var config = require("../config");
12060var Range = require("../range").Range;
12061
12062function bindKey(win, mac) {
12063    return {win: win, mac: mac};
12064}
12065exports.commands = [{
12066    name: "showSettingsMenu",
12067    bindKey: bindKey("Ctrl-,", "Command-,"),
12068    exec: function(editor) {
12069        config.loadModule("ace/ext/settings_menu", function(module) {
12070            module.init(editor);
12071            editor.showSettingsMenu();
12072        });
12073    },
12074    readOnly: true
12075}, {
12076    name: "goToNextError",
12077    bindKey: bindKey("Alt-E", "F4"),
12078    exec: function(editor) {
12079        config.loadModule("./ext/error_marker", function(module) {
12080            module.showErrorMarker(editor, 1);
12081        });
12082    },
12083    scrollIntoView: "animate",
12084    readOnly: true
12085}, {
12086    name: "goToPreviousError",
12087    bindKey: bindKey("Alt-Shift-E", "Shift-F4"),
12088    exec: function(editor) {
12089        config.loadModule("./ext/error_marker", function(module) {
12090            module.showErrorMarker(editor, -1);
12091        });
12092    },
12093    scrollIntoView: "animate",
12094    readOnly: true
12095}, {
12096    name: "selectall",
12097    bindKey: bindKey("Ctrl-A", "Command-A"),
12098    exec: function(editor) { editor.selectAll(); },
12099    readOnly: true
12100}, {
12101    name: "centerselection",
12102    bindKey: bindKey(null, "Ctrl-L"),
12103    exec: function(editor) { editor.centerSelection(); },
12104    readOnly: true
12105}, {
12106    name: "gotoline",
12107    bindKey: bindKey("Ctrl-L", "Command-L"),
12108    exec: function(editor, line) {
12109        if (typeof line !== "number")
12110            line = parseInt(prompt("Enter line number:"), 10);
12111        if (!isNaN(line)) {
12112            editor.gotoLine(line);
12113        }
12114    },
12115    readOnly: true
12116}, {
12117    name: "fold",
12118    bindKey: bindKey("Alt-L|Ctrl-F1", "Command-Alt-L|Command-F1"),
12119    exec: function(editor) { editor.session.toggleFold(false); },
12120    multiSelectAction: "forEach",
12121    scrollIntoView: "center",
12122    readOnly: true
12123}, {
12124    name: "unfold",
12125    bindKey: bindKey("Alt-Shift-L|Ctrl-Shift-F1", "Command-Alt-Shift-L|Command-Shift-F1"),
12126    exec: function(editor) { editor.session.toggleFold(true); },
12127    multiSelectAction: "forEach",
12128    scrollIntoView: "center",
12129    readOnly: true
12130}, {
12131    name: "toggleFoldWidget",
12132    bindKey: bindKey("F2", "F2"),
12133    exec: function(editor) { editor.session.toggleFoldWidget(); },
12134    multiSelectAction: "forEach",
12135    scrollIntoView: "center",
12136    readOnly: true
12137}, {
12138    name: "toggleParentFoldWidget",
12139    bindKey: bindKey("Alt-F2", "Alt-F2"),
12140    exec: function(editor) { editor.session.toggleFoldWidget(true); },
12141    multiSelectAction: "forEach",
12142    scrollIntoView: "center",
12143    readOnly: true
12144}, {
12145    name: "foldall",
12146    bindKey: bindKey(null, "Ctrl-Command-Option-0"),
12147    exec: function(editor) { editor.session.foldAll(); },
12148    scrollIntoView: "center",
12149    readOnly: true
12150}, {
12151    name: "foldOther",
12152    bindKey: bindKey("Alt-0", "Command-Option-0"),
12153    exec: function(editor) { 
12154        editor.session.foldAll();
12155        editor.session.unfold(editor.selection.getAllRanges());
12156    },
12157    scrollIntoView: "center",
12158    readOnly: true
12159}, {
12160    name: "unfoldall",
12161    bindKey: bindKey("Alt-Shift-0", "Command-Option-Shift-0"),
12162    exec: function(editor) { editor.session.unfold(); },
12163    scrollIntoView: "center",
12164    readOnly: true
12165}, {
12166    name: "findnext",
12167    bindKey: bindKey("Ctrl-K", "Command-G"),
12168    exec: function(editor) { editor.findNext(); },
12169    multiSelectAction: "forEach",
12170    scrollIntoView: "center",
12171    readOnly: true
12172}, {
12173    name: "findprevious",
12174    bindKey: bindKey("Ctrl-Shift-K", "Command-Shift-G"),
12175    exec: function(editor) { editor.findPrevious(); },
12176    multiSelectAction: "forEach",
12177    scrollIntoView: "center",
12178    readOnly: true
12179}, {
12180    name: "selectOrFindNext",
12181    bindKey: bindKey("Alt-K", "Ctrl-G"),
12182    exec: function(editor) {
12183        if (editor.selection.isEmpty())
12184            editor.selection.selectWord();
12185        else
12186            editor.findNext(); 
12187    },
12188    readOnly: true
12189}, {
12190    name: "selectOrFindPrevious",
12191    bindKey: bindKey("Alt-Shift-K", "Ctrl-Shift-G"),
12192    exec: function(editor) { 
12193        if (editor.selection.isEmpty())
12194            editor.selection.selectWord();
12195        else
12196            editor.findPrevious();
12197    },
12198    readOnly: true
12199}, {
12200    name: "find",
12201    bindKey: bindKey("Ctrl-F", "Command-F"),
12202    exec: function(editor) {
12203        config.loadModule("ace/ext/searchbox", function(e) {e.Search(editor);});
12204    },
12205    readOnly: true
12206}, {
12207    name: "overwrite",
12208    bindKey: "Insert",
12209    exec: function(editor) { editor.toggleOverwrite(); },
12210    readOnly: true
12211}, {
12212    name: "selecttostart",
12213    bindKey: bindKey("Ctrl-Shift-Home", "Command-Shift-Home|Command-Shift-Up"),
12214    exec: function(editor) { editor.getSelection().selectFileStart(); },
12215    multiSelectAction: "forEach",
12216    readOnly: true,
12217    scrollIntoView: "animate",
12218    aceCommandGroup: "fileJump"
12219}, {
12220    name: "gotostart",
12221    bindKey: bindKey("Ctrl-Home", "Command-Home|Command-Up"),
12222    exec: function(editor) { editor.navigateFileStart(); },
12223    multiSelectAction: "forEach",
12224    readOnly: true,
12225    scrollIntoView: "animate",
12226    aceCommandGroup: "fileJump"
12227}, {
12228    name: "selectup",
12229    bindKey: bindKey("Shift-Up", "Shift-Up|Ctrl-Shift-P"),
12230    exec: function(editor) { editor.getSelection().selectUp(); },
12231    multiSelectAction: "forEach",
12232    scrollIntoView: "cursor",
12233    readOnly: true
12234}, {
12235    name: "golineup",
12236    bindKey: bindKey("Up", "Up|Ctrl-P"),
12237    exec: function(editor, args) { editor.navigateUp(args.times); },
12238    multiSelectAction: "forEach",
12239    scrollIntoView: "cursor",
12240    readOnly: true
12241}, {
12242    name: "selecttoend",
12243    bindKey: bindKey("Ctrl-Shift-End", "Command-Shift-End|Command-Shift-Down"),
12244    exec: function(editor) { editor.getSelection().selectFileEnd(); },
12245    multiSelectAction: "forEach",
12246    readOnly: true,
12247    scrollIntoView: "animate",
12248    aceCommandGroup: "fileJump"
12249}, {
12250    name: "gotoend",
12251    bindKey: bindKey("Ctrl-End", "Command-End|Command-Down"),
12252    exec: function(editor) { editor.navigateFileEnd(); },
12253    multiSelectAction: "forEach",
12254    readOnly: true,
12255    scrollIntoView: "animate",
12256    aceCommandGroup: "fileJump"
12257}, {
12258    name: "selectdown",
12259    bindKey: bindKey("Shift-Down", "Shift-Down|Ctrl-Shift-N"),
12260    exec: function(editor) { editor.getSelection().selectDown(); },
12261    multiSelectAction: "forEach",
12262    scrollIntoView: "cursor",
12263    readOnly: true
12264}, {
12265    name: "golinedown",
12266    bindKey: bindKey("Down", "Down|Ctrl-N"),
12267    exec: function(editor, args) { editor.navigateDown(args.times); },
12268    multiSelectAction: "forEach",
12269    scrollIntoView: "cursor",
12270    readOnly: true
12271}, {
12272    name: "selectwordleft",
12273    bindKey: bindKey("Ctrl-Shift-Left", "Option-Shift-Left"),
12274    exec: function(editor) { editor.getSelection().selectWordLeft(); },
12275    multiSelectAction: "forEach",
12276    scrollIntoView: "cursor",
12277    readOnly: true
12278}, {
12279    name: "gotowordleft",
12280    bindKey: bindKey("Ctrl-Left", "Option-Left"),
12281    exec: function(editor) { editor.navigateWordLeft(); },
12282    multiSelectAction: "forEach",
12283    scrollIntoView: "cursor",
12284    readOnly: true
12285}, {
12286    name: "selecttolinestart",
12287    bindKey: bindKey("Alt-Shift-Left", "Command-Shift-Left|Ctrl-Shift-A"),
12288    exec: function(editor) { editor.getSelection().selectLineStart(); },
12289    multiSelectAction: "forEach",
12290    scrollIntoView: "cursor",
12291    readOnly: true
12292}, {
12293    name: "gotolinestart",
12294    bindKey: bindKey("Alt-Left|Home", "Command-Left|Home|Ctrl-A"),
12295    exec: function(editor) { editor.navigateLineStart(); },
12296    multiSelectAction: "forEach",
12297    scrollIntoView: "cursor",
12298    readOnly: true
12299}, {
12300    name: "selectleft",
12301    bindKey: bindKey("Shift-Left", "Shift-Left|Ctrl-Shift-B"),
12302    exec: function(editor) { editor.getSelection().selectLeft(); },
12303    multiSelectAction: "forEach",
12304    scrollIntoView: "cursor",
12305    readOnly: true
12306}, {
12307    name: "gotoleft",
12308    bindKey: bindKey("Left", "Left|Ctrl-B"),
12309    exec: function(editor, args) { editor.navigateLeft(args.times); },
12310    multiSelectAction: "forEach",
12311    scrollIntoView: "cursor",
12312    readOnly: true
12313}, {
12314    name: "selectwordright",
12315    bindKey: bindKey("Ctrl-Shift-Right", "Option-Shift-Right"),
12316    exec: function(editor) { editor.getSelection().selectWordRight(); },
12317    multiSelectAction: "forEach",
12318    scrollIntoView: "cursor",
12319    readOnly: true
12320}, {
12321    name: "gotowordright",
12322    bindKey: bindKey("Ctrl-Right", "Option-Right"),
12323    exec: function(editor) { editor.navigateWordRight(); },
12324    multiSelectAction: "forEach",
12325    scrollIntoView: "cursor",
12326    readOnly: true
12327}, {
12328    name: "selecttolineend",
12329    bindKey: bindKey("Alt-Shift-Right", "Command-Shift-Right|Shift-End|Ctrl-Shift-E"),
12330    exec: function(editor) { editor.getSelection().selectLineEnd(); },
12331    multiSelectAction: "forEach",
12332    scrollIntoView: "cursor",
12333    readOnly: true
12334}, {
12335    name: "gotolineend",
12336    bindKey: bindKey("Alt-Right|End", "Command-Right|End|Ctrl-E"),
12337    exec: function(editor) { editor.navigateLineEnd(); },
12338    multiSelectAction: "forEach",
12339    scrollIntoView: "cursor",
12340    readOnly: true
12341}, {
12342    name: "selectright",
12343    bindKey: bindKey("Shift-Right", "Shift-Right"),
12344    exec: function(editor) { editor.getSelection().selectRight(); },
12345    multiSelectAction: "forEach",
12346    scrollIntoView: "cursor",
12347    readOnly: true
12348}, {
12349    name: "gotoright",
12350    bindKey: bindKey("Right", "Right|Ctrl-F"),
12351    exec: function(editor, args) { editor.navigateRight(args.times); },
12352    multiSelectAction: "forEach",
12353    scrollIntoView: "cursor",
12354    readOnly: true
12355}, {
12356    name: "selectpagedown",
12357    bindKey: "Shift-PageDown",
12358    exec: function(editor) { editor.selectPageDown(); },
12359    readOnly: true
12360}, {
12361    name: "pagedown",
12362    bindKey: bindKey(null, "Option-PageDown"),
12363    exec: function(editor) { editor.scrollPageDown(); },
12364    readOnly: true
12365}, {
12366    name: "gotopagedown",
12367    bindKey: bindKey("PageDown", "PageDown|Ctrl-V"),
12368    exec: function(editor) { editor.gotoPageDown(); },
12369    readOnly: true
12370}, {
12371    name: "selectpageup",
12372    bindKey: "Shift-PageUp",
12373    exec: function(editor) { editor.selectPageUp(); },
12374    readOnly: true
12375}, {
12376    name: "pageup",
12377    bindKey: bindKey(null, "Option-PageUp"),
12378    exec: function(editor) { editor.scrollPageUp(); },
12379    readOnly: true
12380}, {
12381    name: "gotopageup",
12382    bindKey: "PageUp",
12383    exec: function(editor) { editor.gotoPageUp(); },
12384    readOnly: true
12385}, {
12386    name: "scrollup",
12387    bindKey: bindKey("Ctrl-Up", null),
12388    exec: function(e) { e.renderer.scrollBy(0, -2 * e.renderer.layerConfig.lineHeight); },
12389    readOnly: true
12390}, {
12391    name: "scrolldown",
12392    bindKey: bindKey("Ctrl-Down", null),
12393    exec: function(e) { e.renderer.scrollBy(0, 2 * e.renderer.layerConfig.lineHeight); },
12394    readOnly: true
12395}, {
12396    name: "selectlinestart",
12397    bindKey: "Shift-Home",
12398    exec: function(editor) { editor.getSelection().selectLineStart(); },
12399    multiSelectAction: "forEach",
12400    scrollIntoView: "cursor",
12401    readOnly: true
12402}, {
12403    name: "selectlineend",
12404    bindKey: "Shift-End",
12405    exec: function(editor) { editor.getSelection().selectLineEnd(); },
12406    multiSelectAction: "forEach",
12407    scrollIntoView: "cursor",
12408    readOnly: true
12409}, {
12410    name: "togglerecording",
12411    bindKey: bindKey("Ctrl-Alt-E", "Command-Option-E"),
12412    exec: function(editor) { editor.commands.toggleRecording(editor); },
12413    readOnly: true
12414}, {
12415    name: "replaymacro",
12416    bindKey: bindKey("Ctrl-Shift-E", "Command-Shift-E"),
12417    exec: function(editor) { editor.commands.replay(editor); },
12418    readOnly: true
12419}, {
12420    name: "jumptomatching",
12421    bindKey: bindKey("Ctrl-P", "Ctrl-P"),
12422    exec: function(editor) { editor.jumpToMatching(); },
12423    multiSelectAction: "forEach",
12424    scrollIntoView: "animate",
12425    readOnly: true
12426}, {
12427    name: "selecttomatching",
12428    bindKey: bindKey("Ctrl-Shift-P", "Ctrl-Shift-P"),
12429    exec: function(editor) { editor.jumpToMatching(true); },
12430    multiSelectAction: "forEach",
12431    scrollIntoView: "animate",
12432    readOnly: true
12433}, {
12434    name: "expandToMatching",
12435    bindKey: bindKey("Ctrl-Shift-M", "Ctrl-Shift-M"),
12436    exec: function(editor) { editor.jumpToMatching(true, true); },
12437    multiSelectAction: "forEach",
12438    scrollIntoView: "animate",
12439    readOnly: true
12440}, {
12441    name: "passKeysToBrowser",
12442    bindKey: bindKey(null, null),
12443    exec: function() {},
12444    passEvent: true,
12445    readOnly: true
12446}, {
12447    name: "copy",
12448    exec: function(editor) {
12449    },
12450    readOnly: true
12451},
12452{
12453    name: "cut",
12454    exec: function(editor) {
12455        var cutLine = editor.$copyWithEmptySelection && editor.selection.isEmpty();
12456        var range = cutLine ? editor.selection.getLineRange() : editor.selection.getRange();
12457        editor._emit("cut", range);
12458
12459        if (!range.isEmpty())
12460            editor.session.remove(range);
12461        editor.clearSelection();
12462    },
12463    scrollIntoView: "cursor",
12464    multiSelectAction: "forEach"
12465}, {
12466    name: "paste",
12467    exec: function(editor, args) {
12468        editor.$handlePaste(args);
12469    },
12470    scrollIntoView: "cursor"
12471}, {
12472    name: "removeline",
12473    bindKey: bindKey("Ctrl-D", "Command-D"),
12474    exec: function(editor) { editor.removeLines(); },
12475    scrollIntoView: "cursor",
12476    multiSelectAction: "forEachLine"
12477}, {
12478    name: "duplicateSelection",
12479    bindKey: bindKey("Ctrl-Shift-D", "Command-Shift-D"),
12480    exec: function(editor) { editor.duplicateSelection(); },
12481    scrollIntoView: "cursor",
12482    multiSelectAction: "forEach"
12483}, {
12484    name: "sortlines",
12485    bindKey: bindKey("Ctrl-Alt-S", "Command-Alt-S"),
12486    exec: function(editor) { editor.sortLines(); },
12487    scrollIntoView: "selection",
12488    multiSelectAction: "forEachLine"
12489}, {
12490    name: "togglecomment",
12491    bindKey: bindKey("Ctrl-/", "Command-/"),
12492    exec: function(editor) { editor.toggleCommentLines(); },
12493    multiSelectAction: "forEachLine",
12494    scrollIntoView: "selectionPart"
12495}, {
12496    name: "toggleBlockComment",
12497    bindKey: bindKey("Ctrl-Shift-/", "Command-Shift-/"),
12498    exec: function(editor) { editor.toggleBlockComment(); },
12499    multiSelectAction: "forEach",
12500    scrollIntoView: "selectionPart"
12501}, {
12502    name: "modifyNumberUp",
12503    bindKey: bindKey("Ctrl-Shift-Up", "Alt-Shift-Up"),
12504    exec: function(editor) { editor.modifyNumber(1); },
12505    scrollIntoView: "cursor",
12506    multiSelectAction: "forEach"
12507}, {
12508    name: "modifyNumberDown",
12509    bindKey: bindKey("Ctrl-Shift-Down", "Alt-Shift-Down"),
12510    exec: function(editor) { editor.modifyNumber(-1); },
12511    scrollIntoView: "cursor",
12512    multiSelectAction: "forEach"
12513}, {
12514    name: "replace",
12515    bindKey: bindKey("Ctrl-H", "Command-Option-F"),
12516    exec: function(editor) {
12517        config.loadModule("ace/ext/searchbox", function(e) {e.Search(editor, true);});
12518    }
12519}, {
12520    name: "undo",
12521    bindKey: bindKey("Ctrl-Z", "Command-Z"),
12522    exec: function(editor) { editor.undo(); }
12523}, {
12524    name: "redo",
12525    bindKey: bindKey("Ctrl-Shift-Z|Ctrl-Y", "Command-Shift-Z|Command-Y"),
12526    exec: function(editor) { editor.redo(); }
12527}, {
12528    name: "copylinesup",
12529    bindKey: bindKey("Alt-Shift-Up", "Command-Option-Up"),
12530    exec: function(editor) { editor.copyLinesUp(); },
12531    scrollIntoView: "cursor"
12532}, {
12533    name: "movelinesup",
12534    bindKey: bindKey("Alt-Up", "Option-Up"),
12535    exec: function(editor) { editor.moveLinesUp(); },
12536    scrollIntoView: "cursor"
12537}, {
12538    name: "copylinesdown",
12539    bindKey: bindKey("Alt-Shift-Down", "Command-Option-Down"),
12540    exec: function(editor) { editor.copyLinesDown(); },
12541    scrollIntoView: "cursor"
12542}, {
12543    name: "movelinesdown",
12544    bindKey: bindKey("Alt-Down", "Option-Down"),
12545    exec: function(editor) { editor.moveLinesDown(); },
12546    scrollIntoView: "cursor"
12547}, {
12548    name: "del",
12549    bindKey: bindKey("Delete", "Delete|Ctrl-D|Shift-Delete"),
12550    exec: function(editor) { editor.remove("right"); },
12551    multiSelectAction: "forEach",
12552    scrollIntoView: "cursor"
12553}, {
12554    name: "backspace",
12555    bindKey: bindKey(
12556        "Shift-Backspace|Backspace",
12557        "Ctrl-Backspace|Shift-Backspace|Backspace|Ctrl-H"
12558    ),
12559    exec: function(editor) { editor.remove("left"); },
12560    multiSelectAction: "forEach",
12561    scrollIntoView: "cursor"
12562}, {
12563    name: "cut_or_delete",
12564    bindKey: bindKey("Shift-Delete", null),
12565    exec: function(editor) { 
12566        if (editor.selection.isEmpty()) {
12567            editor.remove("left");
12568        } else {
12569            return false;
12570        }
12571    },
12572    multiSelectAction: "forEach",
12573    scrollIntoView: "cursor"
12574}, {
12575    name: "removetolinestart",
12576    bindKey: bindKey("Alt-Backspace", "Command-Backspace"),
12577    exec: function(editor) { editor.removeToLineStart(); },
12578    multiSelectAction: "forEach",
12579    scrollIntoView: "cursor"
12580}, {
12581    name: "removetolineend",
12582    bindKey: bindKey("Alt-Delete", "Ctrl-K|Command-Delete"),
12583    exec: function(editor) { editor.removeToLineEnd(); },
12584    multiSelectAction: "forEach",
12585    scrollIntoView: "cursor"
12586}, {
12587    name: "removetolinestarthard",
12588    bindKey: bindKey("Ctrl-Shift-Backspace", null),
12589    exec: function(editor) {
12590        var range = editor.selection.getRange();
12591        range.start.column = 0;
12592        editor.session.remove(range);
12593    },
12594    multiSelectAction: "forEach",
12595    scrollIntoView: "cursor"
12596}, {
12597    name: "removetolineendhard",
12598    bindKey: bindKey("Ctrl-Shift-Delete", null),
12599    exec: function(editor) {
12600        var range = editor.selection.getRange();
12601        range.end.column = Number.MAX_VALUE;
12602        editor.session.remove(range);
12603    },
12604    multiSelectAction: "forEach",
12605    scrollIntoView: "cursor"
12606}, {
12607    name: "removewordleft",
12608    bindKey: bindKey("Ctrl-Backspace", "Alt-Backspace|Ctrl-Alt-Backspace"),
12609    exec: function(editor) { editor.removeWordLeft(); },
12610    multiSelectAction: "forEach",
12611    scrollIntoView: "cursor"
12612}, {
12613    name: "removewordright",
12614    bindKey: bindKey("Ctrl-Delete", "Alt-Delete"),
12615    exec: function(editor) { editor.removeWordRight(); },
12616    multiSelectAction: "forEach",
12617    scrollIntoView: "cursor"
12618}, {
12619    name: "outdent",
12620    bindKey: bindKey("Shift-Tab", "Shift-Tab"),
12621    exec: function(editor) { editor.blockOutdent(); },
12622    multiSelectAction: "forEach",
12623    scrollIntoView: "selectionPart"
12624}, {
12625    name: "indent",
12626    bindKey: bindKey("Tab", "Tab"),
12627    exec: function(editor) { editor.indent(); },
12628    multiSelectAction: "forEach",
12629    scrollIntoView: "selectionPart"
12630}, {
12631    name: "blockoutdent",
12632    bindKey: bindKey("Ctrl-[", "Ctrl-["),
12633    exec: function(editor) { editor.blockOutdent(); },
12634    multiSelectAction: "forEachLine",
12635    scrollIntoView: "selectionPart"
12636}, {
12637    name: "blockindent",
12638    bindKey: bindKey("Ctrl-]", "Ctrl-]"),
12639    exec: function(editor) { editor.blockIndent(); },
12640    multiSelectAction: "forEachLine",
12641    scrollIntoView: "selectionPart"
12642}, {
12643    name: "insertstring",
12644    exec: function(editor, str) { editor.insert(str); },
12645    multiSelectAction: "forEach",
12646    scrollIntoView: "cursor"
12647}, {
12648    name: "inserttext",
12649    exec: function(editor, args) {
12650        editor.insert(lang.stringRepeat(args.text  || "", args.times || 1));
12651    },
12652    multiSelectAction: "forEach",
12653    scrollIntoView: "cursor"
12654}, {
12655    name: "splitline",
12656    bindKey: bindKey(null, "Ctrl-O"),
12657    exec: function(editor) { editor.splitLine(); },
12658    multiSelectAction: "forEach",
12659    scrollIntoView: "cursor"
12660}, {
12661    name: "transposeletters",
12662    bindKey: bindKey("Alt-Shift-X", "Ctrl-T"),
12663    exec: function(editor) { editor.transposeLetters(); },
12664    multiSelectAction: function(editor) {editor.transposeSelections(1); },
12665    scrollIntoView: "cursor"
12666}, {
12667    name: "touppercase",
12668    bindKey: bindKey("Ctrl-U", "Ctrl-U"),
12669    exec: function(editor) { editor.toUpperCase(); },
12670    multiSelectAction: "forEach",
12671    scrollIntoView: "cursor"
12672}, {
12673    name: "tolowercase",
12674    bindKey: bindKey("Ctrl-Shift-U", "Ctrl-Shift-U"),
12675    exec: function(editor) { editor.toLowerCase(); },
12676    multiSelectAction: "forEach",
12677    scrollIntoView: "cursor"
12678}, {
12679    name: "expandtoline",
12680    bindKey: bindKey("Ctrl-Shift-L", "Command-Shift-L"),
12681    exec: function(editor) {
12682        var range = editor.selection.getRange();
12683
12684        range.start.column = range.end.column = 0;
12685        range.end.row++;
12686        editor.selection.setRange(range, false);
12687    },
12688    multiSelectAction: "forEach",
12689    scrollIntoView: "cursor",
12690    readOnly: true
12691}, {
12692    name: "joinlines",
12693    bindKey: bindKey(null, null),
12694    exec: function(editor) {
12695        var isBackwards = editor.selection.isBackwards();
12696        var selectionStart = isBackwards ? editor.selection.getSelectionLead() : editor.selection.getSelectionAnchor();
12697        var selectionEnd = isBackwards ? editor.selection.getSelectionAnchor() : editor.selection.getSelectionLead();
12698        var firstLineEndCol = editor.session.doc.getLine(selectionStart.row).length;
12699        var selectedText = editor.session.doc.getTextRange(editor.selection.getRange());
12700        var selectedCount = selectedText.replace(/\n\s*/, " ").length;
12701        var insertLine = editor.session.doc.getLine(selectionStart.row);
12702
12703        for (var i = selectionStart.row + 1; i <= selectionEnd.row + 1; i++) {
12704            var curLine = lang.stringTrimLeft(lang.stringTrimRight(editor.session.doc.getLine(i)));
12705            if (curLine.length !== 0) {
12706                curLine = " " + curLine;
12707            }
12708            insertLine += curLine;
12709        }
12710
12711        if (selectionEnd.row + 1 < (editor.session.doc.getLength() - 1)) {
12712            insertLine += editor.session.doc.getNewLineCharacter();
12713        }
12714
12715        editor.clearSelection();
12716        editor.session.doc.replace(new Range(selectionStart.row, 0, selectionEnd.row + 2, 0), insertLine);
12717
12718        if (selectedCount > 0) {
12719            editor.selection.moveCursorTo(selectionStart.row, selectionStart.column);
12720            editor.selection.selectTo(selectionStart.row, selectionStart.column + selectedCount);
12721        } else {
12722            firstLineEndCol = editor.session.doc.getLine(selectionStart.row).length > firstLineEndCol ? (firstLineEndCol + 1) : firstLineEndCol;
12723            editor.selection.moveCursorTo(selectionStart.row, firstLineEndCol);
12724        }
12725    },
12726    multiSelectAction: "forEach",
12727    readOnly: true
12728}, {
12729    name: "invertSelection",
12730    bindKey: bindKey(null, null),
12731    exec: function(editor) {
12732        var endRow = editor.session.doc.getLength() - 1;
12733        var endCol = editor.session.doc.getLine(endRow).length;
12734        var ranges = editor.selection.rangeList.ranges;
12735        var newRanges = [];
12736        if (ranges.length < 1) {
12737            ranges = [editor.selection.getRange()];
12738        }
12739
12740        for (var i = 0; i < ranges.length; i++) {
12741            if (i == (ranges.length - 1)) {
12742                if (!(ranges[i].end.row === endRow && ranges[i].end.column === endCol)) {
12743                    newRanges.push(new Range(ranges[i].end.row, ranges[i].end.column, endRow, endCol));
12744                }
12745            }
12746
12747            if (i === 0) {
12748                if (!(ranges[i].start.row === 0 && ranges[i].start.column === 0)) {
12749                    newRanges.push(new Range(0, 0, ranges[i].start.row, ranges[i].start.column));
12750                }
12751            } else {
12752                newRanges.push(new Range(ranges[i-1].end.row, ranges[i-1].end.column, ranges[i].start.row, ranges[i].start.column));
12753            }
12754        }
12755
12756        editor.exitMultiSelectMode();
12757        editor.clearSelection();
12758
12759        for(var i = 0; i < newRanges.length; i++) {
12760            editor.selection.addRange(newRanges[i], false);
12761        }
12762    },
12763    readOnly: true,
12764    scrollIntoView: "none"
12765}];
12766
12767});
12768
12769define("ace/clipboard",["require","exports","module"], function(require, exports, module) {
12770"use strict";
12771
12772module.exports = { lineMode: false };
12773
12774});
12775
12776define("ace/editor",["require","exports","module","ace/lib/fixoldbrowsers","ace/lib/oop","ace/lib/dom","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","ace/token_iterator","ace/clipboard"], function(require, exports, module) {
12777"use strict";
12778
12779require("./lib/fixoldbrowsers");
12780
12781var oop = require("./lib/oop");
12782var dom = require("./lib/dom");
12783var lang = require("./lib/lang");
12784var useragent = require("./lib/useragent");
12785var TextInput = require("./keyboard/textinput").TextInput;
12786var MouseHandler = require("./mouse/mouse_handler").MouseHandler;
12787var FoldHandler = require("./mouse/fold_handler").FoldHandler;
12788var KeyBinding = require("./keyboard/keybinding").KeyBinding;
12789var EditSession = require("./edit_session").EditSession;
12790var Search = require("./search").Search;
12791var Range = require("./range").Range;
12792var EventEmitter = require("./lib/event_emitter").EventEmitter;
12793var CommandManager = require("./commands/command_manager").CommandManager;
12794var defaultCommands = require("./commands/default_commands").commands;
12795var config = require("./config");
12796var TokenIterator = require("./token_iterator").TokenIterator;
12797
12798var clipboard = require("./clipboard");
12799var Editor = function(renderer, session, options) {
12800    var container = renderer.getContainerElement();
12801    this.container = container;
12802    this.renderer = renderer;
12803    this.id = "editor" + (++Editor.$uid);
12804
12805    this.commands = new CommandManager(useragent.isMac ? "mac" : "win", defaultCommands);
12806    if (typeof document == "object") {
12807        this.textInput = new TextInput(renderer.getTextAreaContainer(), this);
12808        this.renderer.textarea = this.textInput.getElement();
12809        this.$mouseHandler = new MouseHandler(this);
12810        new FoldHandler(this);
12811    }
12812
12813    this.keyBinding = new KeyBinding(this);
12814
12815    this.$search = new Search().set({
12816        wrap: true
12817    });
12818
12819    this.$historyTracker = this.$historyTracker.bind(this);
12820    this.commands.on("exec", this.$historyTracker);
12821
12822    this.$initOperationListeners();
12823    
12824    this._$emitInputEvent = lang.delayedCall(function() {
12825        this._signal("input", {});
12826        if (this.session && this.session.bgTokenizer)
12827            this.session.bgTokenizer.scheduleStart();
12828    }.bind(this));
12829    
12830    this.on("change", function(_, _self) {
12831        _self._$emitInputEvent.schedule(31);
12832    });
12833
12834    this.setSession(session || options && options.session || new EditSession(""));
12835    config.resetOptions(this);
12836    if (options)
12837        this.setOptions(options);
12838    config._signal("editor", this);
12839};
12840
12841Editor.$uid = 0;
12842
12843(function(){
12844
12845    oop.implement(this, EventEmitter);
12846
12847    this.$initOperationListeners = function() {
12848        this.commands.on("exec", this.startOperation.bind(this), true);
12849        this.commands.on("afterExec", this.endOperation.bind(this), true);
12850
12851        this.$opResetTimer = lang.delayedCall(this.endOperation.bind(this));
12852        this.on("change", function() {
12853            if (!this.curOp) {
12854                this.startOperation();
12855                this.curOp.selectionBefore = this.$lastSel;
12856            }
12857            this.curOp.docChanged = true;
12858        }.bind(this), true);
12859        
12860        this.on("changeSelection", function() {
12861            if (!this.curOp) {
12862                this.startOperation();
12863                this.curOp.selectionBefore = this.$lastSel;
12864            }
12865            this.curOp.selectionChanged = true;
12866        }.bind(this), true);
12867    };
12868
12869    this.curOp = null;
12870    this.prevOp = {};
12871    this.startOperation = function(commadEvent) {
12872        if (this.curOp) {
12873            if (!commadEvent || this.curOp.command)
12874                return;
12875            this.prevOp = this.curOp;
12876        }
12877        if (!commadEvent) {
12878            this.previousCommand = null;
12879            commadEvent = {};
12880        }
12881
12882        this.$opResetTimer.schedule();
12883        this.curOp = this.session.curOp = {
12884            command: commadEvent.command || {},
12885            args: commadEvent.args,
12886            scrollTop: this.renderer.scrollTop
12887        };
12888        this.curOp.selectionBefore = this.selection.toJSON();
12889    };
12890
12891    this.endOperation = function(e) {
12892        if (this.curOp) {
12893            if (e && e.returnValue === false)
12894                return (this.curOp = null);
12895            this._signal("beforeEndOperation");
12896            var command = this.curOp.command;
12897            var scrollIntoView = command && command.scrollIntoView;
12898            if (scrollIntoView) {
12899                switch (scrollIntoView) {
12900                    case "center-animate":
12901                        scrollIntoView = "animate";
12902                    case "center":
12903                        this.renderer.scrollCursorIntoView(null, 0.5);
12904                        break;
12905                    case "animate":
12906                    case "cursor":
12907                        this.renderer.scrollCursorIntoView();
12908                        break;
12909                    case "selectionPart":
12910                        var range = this.selection.getRange();
12911                        var config = this.renderer.layerConfig;
12912                        if (range.start.row >= config.lastRow || range.end.row <= config.firstRow) {
12913                            this.renderer.scrollSelectionIntoView(this.selection.anchor, this.selection.lead);
12914                        }
12915                        break;
12916                    default:
12917                        break;
12918                }
12919                if (scrollIntoView == "animate")
12920                    this.renderer.animateScrolling(this.curOp.scrollTop);
12921            }
12922            var sel = this.selection.toJSON();
12923            this.curOp.selectionAfter = sel;
12924            this.$lastSel = this.selection.toJSON();
12925            this.session.getUndoManager().addSelection(sel);
12926            this.prevOp = this.curOp;
12927            this.curOp = null;
12928        }
12929    };
12930    this.$mergeableCommands = ["backspace", "del", "insertstring"];
12931    this.$historyTracker = function(e) {
12932        if (!this.$mergeUndoDeltas)
12933            return;
12934
12935        var prev = this.prevOp;
12936        var mergeableCommands = this.$mergeableCommands;
12937        var shouldMerge = prev.command && (e.command.name == prev.command.name);
12938        if (e.command.name == "insertstring") {
12939            var text = e.args;
12940            if (this.mergeNextCommand === undefined)
12941                this.mergeNextCommand = true;
12942
12943            shouldMerge = shouldMerge
12944                && this.mergeNextCommand // previous command allows to coalesce with
12945                && (!/\s/.test(text) || /\s/.test(prev.args)); // previous insertion was of same type
12946
12947            this.mergeNextCommand = true;
12948        } else {
12949            shouldMerge = shouldMerge
12950                && mergeableCommands.indexOf(e.command.name) !== -1; // the command is mergeable
12951        }
12952
12953        if (
12954            this.$mergeUndoDeltas != "always"
12955            && Date.now() - this.sequenceStartTime > 2000
12956        ) {
12957            shouldMerge = false; // the sequence is too long
12958        }
12959
12960        if (shouldMerge)
12961            this.session.mergeUndoDeltas = true;
12962        else if (mergeableCommands.indexOf(e.command.name) !== -1)
12963            this.sequenceStartTime = Date.now();
12964    };
12965    this.setKeyboardHandler = function(keyboardHandler, cb) {
12966        if (keyboardHandler && typeof keyboardHandler === "string" && keyboardHandler != "ace") {
12967            this.$keybindingId = keyboardHandler;
12968            var _self = this;
12969            config.loadModule(["keybinding", keyboardHandler], function(module) {
12970                if (_self.$keybindingId == keyboardHandler)
12971                    _self.keyBinding.setKeyboardHandler(module && module.handler);
12972                cb && cb();
12973            });
12974        } else {
12975            this.$keybindingId = null;
12976            this.keyBinding.setKeyboardHandler(keyboardHandler);
12977            cb && cb();
12978        }
12979    };
12980    this.getKeyboardHandler = function() {
12981        return this.keyBinding.getKeyboardHandler();
12982    };
12983    this.setSession = function(session) {
12984        if (this.session == session)
12985            return;
12986        if (this.curOp) this.endOperation();
12987        this.curOp = {};
12988
12989        var oldSession = this.session;
12990        if (oldSession) {
12991            this.session.off("change", this.$onDocumentChange);
12992            this.session.off("changeMode", this.$onChangeMode);
12993            this.session.off("tokenizerUpdate", this.$onTokenizerUpdate);
12994            this.session.off("changeTabSize", this.$onChangeTabSize);
12995            this.session.off("changeWrapLimit", this.$onChangeWrapLimit);
12996            this.session.off("changeWrapMode", this.$onChangeWrapMode);
12997            this.session.off("changeFold", this.$onChangeFold);
12998            this.session.off("changeFrontMarker", this.$onChangeFrontMarker);
12999            this.session.off("changeBackMarker", this.$onChangeBackMarker);
13000            this.session.off("changeBreakpoint", this.$onChangeBreakpoint);
13001            this.session.off("changeAnnotation", this.$onChangeAnnotation);
13002            this.session.off("changeOverwrite", this.$onCursorChange);
13003            this.session.off("changeScrollTop", this.$onScrollTopChange);
13004            this.session.off("changeScrollLeft", this.$onScrollLeftChange);
13005
13006            var selection = this.session.getSelection();
13007            selection.off("changeCursor", this.$onCursorChange);
13008            selection.off("changeSelection", this.$onSelectionChange);
13009        }
13010
13011        this.session = session;
13012        if (session) {
13013            this.$onDocumentChange = this.onDocumentChange.bind(this);
13014            session.on("change", this.$onDocumentChange);
13015            this.renderer.setSession(session);
13016    
13017            this.$onChangeMode = this.onChangeMode.bind(this);
13018            session.on("changeMode", this.$onChangeMode);
13019    
13020            this.$onTokenizerUpdate = this.onTokenizerUpdate.bind(this);
13021            session.on("tokenizerUpdate", this.$onTokenizerUpdate);
13022    
13023            this.$onChangeTabSize = this.renderer.onChangeTabSize.bind(this.renderer);
13024            session.on("changeTabSize", this.$onChangeTabSize);
13025    
13026            this.$onChangeWrapLimit = this.onChangeWrapLimit.bind(this);
13027            session.on("changeWrapLimit", this.$onChangeWrapLimit);
13028    
13029            this.$onChangeWrapMode = this.onChangeWrapMode.bind(this);
13030            session.on("changeWrapMode", this.$onChangeWrapMode);
13031    
13032            this.$onChangeFold = this.onChangeFold.bind(this);
13033            session.on("changeFold", this.$onChangeFold);
13034    
13035            this.$onChangeFrontMarker = this.onChangeFrontMarker.bind(this);
13036            this.session.on("changeFrontMarker", this.$onChangeFrontMarker);
13037    
13038            this.$onChangeBackMarker = this.onChangeBackMarker.bind(this);
13039            this.session.on("changeBackMarker", this.$onChangeBackMarker);
13040    
13041            this.$onChangeBreakpoint = this.onChangeBreakpoint.bind(this);
13042            this.session.on("changeBreakpoint", this.$onChangeBreakpoint);
13043    
13044            this.$onChangeAnnotation = this.onChangeAnnotation.bind(this);
13045            this.session.on("changeAnnotation", this.$onChangeAnnotation);
13046    
13047            this.$onCursorChange = this.onCursorChange.bind(this);
13048            this.session.on("changeOverwrite", this.$onCursorChange);
13049    
13050            this.$onScrollTopChange = this.onScrollTopChange.bind(this);
13051            this.session.on("changeScrollTop", this.$onScrollTopChange);
13052    
13053            this.$onScrollLeftChange = this.onScrollLeftChange.bind(this);
13054            this.session.on("changeScrollLeft", this.$onScrollLeftChange);
13055    
13056            this.selection = session.getSelection();
13057            this.selection.on("changeCursor", this.$onCursorChange);
13058    
13059            this.$onSelectionChange = this.onSelectionChange.bind(this);
13060            this.selection.on("changeSelection", this.$onSelectionChange);
13061    
13062            this.onChangeMode();
13063    
13064            this.onCursorChange();
13065    
13066            this.onScrollTopChange();
13067            this.onScrollLeftChange();
13068            this.onSelectionChange();
13069            this.onChangeFrontMarker();
13070            this.onChangeBackMarker();
13071            this.onChangeBreakpoint();
13072            this.onChangeAnnotation();
13073            this.session.getUseWrapMode() && this.renderer.adjustWrapLimit();
13074            this.renderer.updateFull();
13075        } else {
13076            this.selection = null;
13077            this.renderer.setSession(session);
13078        }
13079
13080        this._signal("changeSession", {
13081            session: session,
13082            oldSession: oldSession
13083        });
13084        
13085        this.curOp = null;
13086        
13087        oldSession && oldSession._signal("changeEditor", {oldEditor: this});
13088        session && session._signal("changeEditor", {editor: this});
13089        
13090        if (session && session.bgTokenizer)
13091            session.bgTokenizer.scheduleStart();
13092    };
13093    this.getSession = function() {
13094        return this.session;
13095    };
13096    this.setValue = function(val, cursorPos) {
13097        this.session.doc.setValue(val);
13098
13099        if (!cursorPos)
13100            this.selectAll();
13101        else if (cursorPos == 1)
13102            this.navigateFileEnd();
13103        else if (cursorPos == -1)
13104            this.navigateFileStart();
13105
13106        return val;
13107    };
13108    this.getValue = function() {
13109        return this.session.getValue();
13110    };
13111    this.getSelection = function() {
13112        return this.selection;
13113    };
13114    this.resize = function(force) {
13115        this.renderer.onResize(force);
13116    };
13117    this.setTheme = function(theme, cb) {
13118        this.renderer.setTheme(theme, cb);
13119    };
13120    this.getTheme = function() {
13121        return this.renderer.getTheme();
13122    };
13123    this.setStyle = function(style) {
13124        this.renderer.setStyle(style);
13125    };
13126    this.unsetStyle = function(style) {
13127        this.renderer.unsetStyle(style);
13128    };
13129    this.getFontSize = function () {
13130        return this.getOption("fontSize") ||
13131           dom.computedStyle(this.container, "fontSize");
13132    };
13133    this.setFontSize = function(size) {
13134        this.setOption("fontSize", size);
13135    };
13136
13137    this.$highlightBrackets = function() {
13138        if (this.session.$bracketHighlight) {
13139            this.session.removeMarker(this.session.$bracketHighlight);
13140            this.session.$bracketHighlight = null;
13141        }
13142
13143        if (this.$highlightPending) {
13144            return;
13145        }
13146        var self = this;
13147        this.$highlightPending = true;
13148        setTimeout(function() {
13149            self.$highlightPending = false;
13150            var session = self.session;
13151            if (!session || !session.bgTokenizer) return;
13152            var pos = session.findMatchingBracket(self.getCursorPosition());
13153            if (pos) {
13154                var range = new Range(pos.row, pos.column, pos.row, pos.column + 1);
13155            } else if (session.$mode.getMatching) {
13156                var range = session.$mode.getMatching(self.session);
13157            }
13158            if (range)
13159                session.$bracketHighlight = session.addMarker(range, "ace_bracket", "text");
13160        }, 50);
13161    };
13162    this.$highlightTags = function() {
13163        if (this.$highlightTagPending)
13164            return;
13165        var self = this;
13166        this.$highlightTagPending = true;
13167        setTimeout(function() {
13168            self.$highlightTagPending = false;
13169            
13170            var session = self.session;
13171            if (!session || !session.bgTokenizer) return;
13172            
13173            var pos = self.getCursorPosition();
13174            var iterator = new TokenIterator(self.session, pos.row, pos.column);
13175            var token = iterator.getCurrentToken();
13176            
13177            if (!token || !/\b(?:tag-open|tag-name)/.test(token.type)) {
13178                session.removeMarker(session.$tagHighlight);
13179                session.$tagHighlight = null;
13180                return;
13181            }
13182            
13183            if (token.type.indexOf("tag-open") != -1) {
13184                token = iterator.stepForward();
13185                if (!token)
13186                    return;
13187            }
13188            
13189            var tag = token.value;
13190            var depth = 0;
13191            var prevToken = iterator.stepBackward();
13192            
13193            if (prevToken.value == '<'){
13194                do {
13195                    prevToken = token;
13196                    token = iterator.stepForward();
13197                    
13198                    if (token && token.value === tag && token.type.indexOf('tag-name') !== -1) {
13199                        if (prevToken.value === '<'){
13200                            depth++;
13201                        } else if (prevToken.value === '</'){
13202                            depth--;
13203                        }
13204                    }
13205                    
13206                } while (token && depth >= 0);
13207            } else {
13208                do {
13209                    token = prevToken;
13210                    prevToken = iterator.stepBackward();
13211                    
13212                    if (token && token.value === tag && token.type.indexOf('tag-name') !== -1) {
13213                        if (prevToken.value === '<') {
13214                            depth++;
13215                        } else if (prevToken.value === '</') {
13216                            depth--;
13217                        }
13218                    }
13219                } while (prevToken && depth <= 0);
13220                iterator.stepForward();
13221            }
13222            
13223            if (!token) {
13224                session.removeMarker(session.$tagHighlight);
13225                session.$tagHighlight = null;
13226                return;
13227            }
13228            
13229            var row = iterator.getCurrentTokenRow();
13230            var column = iterator.getCurrentTokenColumn();
13231            var range = new Range(row, column, row, column+token.value.length);
13232            var sbm = session.$backMarkers[session.$tagHighlight];
13233            if (session.$tagHighlight && sbm != undefined && range.compareRange(sbm.range) !== 0) {
13234                session.removeMarker(session.$tagHighlight);
13235                session.$tagHighlight = null;
13236            }
13237            
13238            if (!session.$tagHighlight)
13239                session.$tagHighlight = session.addMarker(range, "ace_bracket", "text");
13240        }, 50);
13241    };
13242    this.focus = function() {
13243        var _self = this;
13244        setTimeout(function() {
13245            if (!_self.isFocused())
13246                _self.textInput.focus();
13247        });
13248        this.textInput.focus();
13249    };
13250    this.isFocused = function() {
13251        return this.textInput.isFocused();
13252    };
13253    this.blur = function() {
13254        this.textInput.blur();
13255    };
13256    this.onFocus = function(e) {
13257        if (this.$isFocused)
13258            return;
13259        this.$isFocused = true;
13260        this.renderer.showCursor();
13261        this.renderer.visualizeFocus();
13262        this._emit("focus", e);
13263    };
13264    this.onBlur = function(e) {
13265        if (!this.$isFocused)
13266            return;
13267        this.$isFocused = false;
13268        this.renderer.hideCursor();
13269        this.renderer.visualizeBlur();
13270        this._emit("blur", e);
13271    };
13272
13273    this.$cursorChange = function() {
13274        this.renderer.updateCursor();
13275    };
13276    this.onDocumentChange = function(delta) {
13277        var wrap = this.session.$useWrapMode;
13278        var lastRow = (delta.start.row == delta.end.row ? delta.end.row : Infinity);
13279        this.renderer.updateLines(delta.start.row, lastRow, wrap);
13280
13281        this._signal("change", delta);
13282        this.$cursorChange();
13283        this.$updateHighlightActiveLine();
13284    };
13285
13286    this.onTokenizerUpdate = function(e) {
13287        var rows = e.data;
13288        this.renderer.updateLines(rows.first, rows.last);
13289    };
13290
13291
13292    this.onScrollTopChange = function() {
13293        this.renderer.scrollToY(this.session.getScrollTop());
13294    };
13295
13296    this.onScrollLeftChange = function() {
13297        this.renderer.scrollToX(this.session.getScrollLeft());
13298    };
13299    this.onCursorChange = function() {
13300        this.$cursorChange();
13301
13302        this.$highlightBrackets();
13303        this.$highlightTags();
13304        this.$updateHighlightActiveLine();
13305        this._signal("changeSelection");
13306    };
13307
13308    this.$updateHighlightActiveLine = function() {
13309        var session = this.getSession();
13310
13311        var highlight;
13312        if (this.$highlightActiveLine) {
13313            if (this.$selectionStyle != "line" || !this.selection.isMultiLine())
13314                highlight = this.getCursorPosition();
13315            if (this.renderer.theme && this.renderer.theme.$selectionColorConflict && !this.selection.isEmpty())
13316                highlight = false;
13317            if (this.renderer.$maxLines && this.session.getLength() === 1 && !(this.renderer.$minLines > 1))
13318                highlight = false;
13319        }
13320
13321        if (session.$highlightLineMarker && !highlight) {
13322            session.removeMarker(session.$highlightLineMarker.id);
13323            session.$highlightLineMarker = null;
13324        } else if (!session.$highlightLineMarker && highlight) {
13325            var range = new Range(highlight.row, highlight.column, highlight.row, Infinity);
13326            range.id = session.addMarker(range, "ace_active-line", "screenLine");
13327            session.$highlightLineMarker = range;
13328        } else if (highlight) {
13329            session.$highlightLineMarker.start.row = highlight.row;
13330            session.$highlightLineMarker.end.row = highlight.row;
13331            session.$highlightLineMarker.start.column = highlight.column;
13332            session._signal("changeBackMarker");
13333        }
13334    };
13335
13336    this.onSelectionChange = function(e) {
13337        var session = this.session;
13338
13339        if (session.$selectionMarker) {
13340            session.removeMarker(session.$selectionMarker);
13341        }
13342        session.$selectionMarker = null;
13343
13344        if (!this.selection.isEmpty()) {
13345            var range = this.selection.getRange();
13346            var style = this.getSelectionStyle();
13347            session.$selectionMarker = session.addMarker(range, "ace_selection", style);
13348        } else {
13349            this.$updateHighlightActiveLine();
13350        }
13351
13352        var re = this.$highlightSelectedWord && this.$getSelectionHighLightRegexp();
13353        this.session.highlight(re);
13354
13355        this._signal("changeSelection");
13356    };
13357
13358    this.$getSelectionHighLightRegexp = function() {
13359        var session = this.session;
13360
13361        var selection = this.getSelectionRange();
13362        if (selection.isEmpty() || selection.isMultiLine())
13363            return;
13364
13365        var startColumn = selection.start.column;
13366        var endColumn = selection.end.column;
13367        var line = session.getLine(selection.start.row);
13368        
13369        var needle = line.substring(startColumn, endColumn);
13370        if (needle.length > 5000 || !/[\w\d]/.test(needle))
13371            return;
13372
13373        var re = this.$search.$assembleRegExp({
13374            wholeWord: true,
13375            caseSensitive: true,
13376            needle: needle
13377        });
13378        
13379        var wordWithBoundary = line.substring(startColumn - 1, endColumn + 1);
13380        if (!re.test(wordWithBoundary))
13381            return;
13382        
13383        return re;
13384    };
13385
13386
13387    this.onChangeFrontMarker = function() {
13388        this.renderer.updateFrontMarkers();
13389    };
13390
13391    this.onChangeBackMarker = function() {
13392        this.renderer.updateBackMarkers();
13393    };
13394
13395
13396    this.onChangeBreakpoint = function() {
13397        this.renderer.updateBreakpoints();
13398    };
13399
13400    this.onChangeAnnotation = function() {
13401        this.renderer.setAnnotations(this.session.getAnnotations());
13402    };
13403
13404
13405    this.onChangeMode = function(e) {
13406        this.renderer.updateText();
13407        this._emit("changeMode", e);
13408    };
13409
13410
13411    this.onChangeWrapLimit = function() {
13412        this.renderer.updateFull();
13413    };
13414
13415    this.onChangeWrapMode = function() {
13416        this.renderer.onResize(true);
13417    };
13418
13419
13420    this.onChangeFold = function() {
13421        this.$updateHighlightActiveLine();
13422        this.renderer.updateFull();
13423    };
13424    this.getSelectedText = function() {
13425        return this.session.getTextRange(this.getSelectionRange());
13426    };
13427    this.getCopyText = function() {
13428        var text = this.getSelectedText();
13429        var nl = this.session.doc.getNewLineCharacter();
13430        var copyLine= false;
13431        if (!text && this.$copyWithEmptySelection) {
13432            copyLine = true;
13433            var ranges = this.selection.getAllRanges();
13434            for (var i = 0; i < ranges.length; i++) {
13435                var range = ranges[i];
13436                if (i && ranges[i - 1].start.row == range.start.row)
13437                    continue;
13438                text += this.session.getLine(range.start.row) + nl;
13439            }
13440        }
13441        var e = {text: text};
13442        this._signal("copy", e);
13443        clipboard.lineMode = copyLine ? e.text : "";
13444        return e.text;
13445    };
13446    this.onCopy = function() {
13447        this.commands.exec("copy", this);
13448    };
13449    this.onCut = function() {
13450        this.commands.exec("cut", this);
13451    };
13452    this.onPaste = function(text, event) {
13453        var e = {text: text, event: event};
13454        this.commands.exec("paste", this, e);
13455    };
13456    
13457    this.$handlePaste = function(e) {
13458        if (typeof e == "string") 
13459            e = {text: e};
13460        this._signal("paste", e);
13461        var text = e.text;
13462
13463        var lineMode = text == clipboard.lineMode;
13464        var session = this.session;
13465        if (!this.inMultiSelectMode || this.inVirtualSelectionMode) {
13466            if (lineMode)
13467                session.insert({ row: this.selection.lead.row, column: 0 }, text);
13468            else
13469                this.insert(text);
13470        } else if (lineMode) {
13471            this.selection.rangeList.ranges.forEach(function(range) {
13472                session.insert({ row: range.start.row, column: 0 }, text);
13473            });
13474        } else {
13475            var lines = text.split(/\r\n|\r|\n/);
13476            var ranges = this.selection.rangeList.ranges;
13477    
13478            if (lines.length > ranges.length || lines.length < 2 || !lines[1])
13479                return this.commands.exec("insertstring", this, text);
13480    
13481            for (var i = ranges.length; i--;) {
13482                var range = ranges[i];
13483                if (!range.isEmpty())
13484                    session.remove(range);
13485    
13486                session.insert(range.start, lines[i]);
13487            }
13488        }
13489    };
13490
13491    this.execCommand = function(command, args) {
13492        return this.commands.exec(command, this, args);
13493    };
13494    this.insert = function(text, pasted) {
13495        var session = this.session;
13496        var mode = session.getMode();
13497        var cursor = this.getCursorPosition();
13498
13499        if (this.getBehavioursEnabled() && !pasted) {
13500            var transform = mode.transformAction(session.getState(cursor.row), 'insertion', this, session, text);
13501            if (transform) {
13502                if (text !== transform.text) {
13503                    if (!this.inVirtualSelectionMode) {
13504                        this.session.mergeUndoDeltas = false;
vendor: 25,790 bytes, lines 13505-14238
13505                        this.mergeNextCommand = false;
13506                    }
13507                }
13508                text = transform.text;
13509
13510            }
13511        }
13512        
13513        if (text == "\t")
13514            text = this.session.getTabString();
13515        if (!this.selection.isEmpty()) {
13516            var range = this.getSelectionRange();
13517            cursor = this.session.remove(range);
13518            this.clearSelection();
13519        }
13520        else if (this.session.getOverwrite() && text.indexOf("\n") == -1) {
13521            var range = new Range.fromPoints(cursor, cursor);
13522            range.end.column += text.length;
13523            this.session.remove(range);
13524        }
13525
13526        if (text == "\n" || text == "\r\n") {
13527            var line = session.getLine(cursor.row);
13528            if (cursor.column > line.search(/\S|$/)) {
13529                var d = line.substr(cursor.column).search(/\S|$/);
13530                session.doc.removeInLine(cursor.row, cursor.column, cursor.column + d);
13531            }
13532        }
13533        this.clearSelection();
13534
13535        var start = cursor.column;
13536        var lineState = session.getState(cursor.row);
13537        var line = session.getLine(cursor.row);
13538        var shouldOutdent = mode.checkOutdent(lineState, line, text);
13539        var end = session.insert(cursor, text);
13540
13541        if (transform && transform.selection) {
13542            if (transform.selection.length == 2) { // Transform relative to the current column
13543                this.selection.setSelectionRange(
13544                    new Range(cursor.row, start + transform.selection[0],
13545                              cursor.row, start + transform.selection[1]));
13546            } else { // Transform relative to the current row.
13547                this.selection.setSelectionRange(
13548                    new Range(cursor.row + transform.selection[0],
13549                              transform.selection[1],
13550                              cursor.row + transform.selection[2],
13551                              transform.selection[3]));
13552            }
13553        }
13554
13555        if (session.getDocument().isNewLine(text)) {
13556            var lineIndent = mode.getNextLineIndent(lineState, line.slice(0, cursor.column), session.getTabString());
13557
13558            session.insert({row: cursor.row+1, column: 0}, lineIndent);
13559        }
13560        if (shouldOutdent)
13561            mode.autoOutdent(lineState, session, cursor.row);
13562    };
13563
13564    this.onTextInput = function(text) {
13565        this.keyBinding.onTextInput(text);
13566    };
13567
13568    this.onCommandKey = function(e, hashId, keyCode) {
13569        this.keyBinding.onCommandKey(e, hashId, keyCode);
13570    };
13571    this.setOverwrite = function(overwrite) {
13572        this.session.setOverwrite(overwrite);
13573    };
13574    this.getOverwrite = function() {
13575        return this.session.getOverwrite();
13576    };
13577    this.toggleOverwrite = function() {
13578        this.session.toggleOverwrite();
13579    };
13580    this.setScrollSpeed = function(speed) {
13581        this.setOption("scrollSpeed", speed);
13582    };
13583    this.getScrollSpeed = function() {
13584        return this.getOption("scrollSpeed");
13585    };
13586    this.setDragDelay = function(dragDelay) {
13587        this.setOption("dragDelay", dragDelay);
13588    };
13589    this.getDragDelay = function() {
13590        return this.getOption("dragDelay");
13591    };
13592    this.setSelectionStyle = function(val) {
13593        this.setOption("selectionStyle", val);
13594    };
13595    this.getSelectionStyle = function() {
13596        return this.getOption("selectionStyle");
13597    };
13598    this.setHighlightActiveLine = function(shouldHighlight) {
13599        this.setOption("highlightActiveLine", shouldHighlight);
13600    };
13601    this.getHighlightActiveLine = function() {
13602        return this.getOption("highlightActiveLine");
13603    };
13604    this.setHighlightGutterLine = function(shouldHighlight) {
13605        this.setOption("highlightGutterLine", shouldHighlight);
13606    };
13607
13608    this.getHighlightGutterLine = function() {
13609        return this.getOption("highlightGutterLine");
13610    };
13611    this.setHighlightSelectedWord = function(shouldHighlight) {
13612        this.setOption("highlightSelectedWord", shouldHighlight);
13613    };
13614    this.getHighlightSelectedWord = function() {
13615        return this.$highlightSelectedWord;
13616    };
13617
13618    this.setAnimatedScroll = function(shouldAnimate){
13619        this.renderer.setAnimatedScroll(shouldAnimate);
13620    };
13621
13622    this.getAnimatedScroll = function(){
13623        return this.renderer.getAnimatedScroll();
13624    };
13625    this.setShowInvisibles = function(showInvisibles) {
13626        this.renderer.setShowInvisibles(showInvisibles);
13627    };
13628    this.getShowInvisibles = function() {
13629        return this.renderer.getShowInvisibles();
13630    };
13631
13632    this.setDisplayIndentGuides = function(display) {
13633        this.renderer.setDisplayIndentGuides(display);
13634    };
13635
13636    this.getDisplayIndentGuides = function() {
13637        return this.renderer.getDisplayIndentGuides();
13638    };
13639    this.setShowPrintMargin = function(showPrintMargin) {
13640        this.renderer.setShowPrintMargin(showPrintMargin);
13641    };
13642    this.getShowPrintMargin = function() {
13643        return this.renderer.getShowPrintMargin();
13644    };
13645    this.setPrintMarginColumn = function(showPrintMargin) {
13646        this.renderer.setPrintMarginColumn(showPrintMargin);
13647    };
13648    this.getPrintMarginColumn = function() {
13649        return this.renderer.getPrintMarginColumn();
13650    };
13651    this.setReadOnly = function(readOnly) {
13652        this.setOption("readOnly", readOnly);
13653    };
13654    this.getReadOnly = function() {
13655        return this.getOption("readOnly");
13656    };
13657    this.setBehavioursEnabled = function (enabled) {
13658        this.setOption("behavioursEnabled", enabled);
13659    };
13660    this.getBehavioursEnabled = function () {
13661        return this.getOption("behavioursEnabled");
13662    };
13663    this.setWrapBehavioursEnabled = function (enabled) {
13664        this.setOption("wrapBehavioursEnabled", enabled);
13665    };
13666    this.getWrapBehavioursEnabled = function () {
13667        return this.getOption("wrapBehavioursEnabled");
13668    };
13669    this.setShowFoldWidgets = function(show) {
13670        this.setOption("showFoldWidgets", show);
13671
13672    };
13673    this.getShowFoldWidgets = function() {
13674        return this.getOption("showFoldWidgets");
13675    };
13676
13677    this.setFadeFoldWidgets = function(fade) {
13678        this.setOption("fadeFoldWidgets", fade);
13679    };
13680
13681    this.getFadeFoldWidgets = function() {
13682        return this.getOption("fadeFoldWidgets");
13683    };
13684    this.remove = function(dir) {
13685        if (this.selection.isEmpty()){
13686            if (dir == "left")
13687                this.selection.selectLeft();
13688            else
13689                this.selection.selectRight();
13690        }
13691
13692        var range = this.getSelectionRange();
13693        if (this.getBehavioursEnabled()) {
13694            var session = this.session;
13695            var state = session.getState(range.start.row);
13696            var new_range = session.getMode().transformAction(state, 'deletion', this, session, range);
13697
13698            if (range.end.column === 0) {
13699                var text = session.getTextRange(range);
13700                if (text[text.length - 1] == "\n") {
13701                    var line = session.getLine(range.end.row);
13702                    if (/^\s+$/.test(line)) {
13703                        range.end.column = line.length;
13704                    }
13705                }
13706            }
13707            if (new_range)
13708                range = new_range;
13709        }
13710
13711        this.session.remove(range);
13712        this.clearSelection();
13713    };
13714    this.removeWordRight = function() {
13715        if (this.selection.isEmpty())
13716            this.selection.selectWordRight();
13717
13718        this.session.remove(this.getSelectionRange());
13719        this.clearSelection();
13720    };
13721    this.removeWordLeft = function() {
13722        if (this.selection.isEmpty())
13723            this.selection.selectWordLeft();
13724
13725        this.session.remove(this.getSelectionRange());
13726        this.clearSelection();
13727    };
13728    this.removeToLineStart = function() {
13729        if (this.selection.isEmpty())
13730            this.selection.selectLineStart();
13731
13732        this.session.remove(this.getSelectionRange());
13733        this.clearSelection();
13734    };
13735    this.removeToLineEnd = function() {
13736        if (this.selection.isEmpty())
13737            this.selection.selectLineEnd();
13738
13739        var range = this.getSelectionRange();
13740        if (range.start.column == range.end.column && range.start.row == range.end.row) {
13741            range.end.column = 0;
13742            range.end.row++;
13743        }
13744
13745        this.session.remove(range);
13746        this.clearSelection();
13747    };
13748    this.splitLine = function() {
13749        if (!this.selection.isEmpty()) {
13750            this.session.remove(this.getSelectionRange());
13751            this.clearSelection();
13752        }
13753
13754        var cursor = this.getCursorPosition();
13755        this.insert("\n");
13756        this.moveCursorToPosition(cursor);
13757    };
13758    this.transposeLetters = function() {
13759        if (!this.selection.isEmpty()) {
13760            return;
13761        }
13762
13763        var cursor = this.getCursorPosition();
13764        var column = cursor.column;
13765        if (column === 0)
13766            return;
13767
13768        var line = this.session.getLine(cursor.row);
13769        var swap, range;
13770        if (column < line.length) {
13771            swap = line.charAt(column) + line.charAt(column-1);
13772            range = new Range(cursor.row, column-1, cursor.row, column+1);
13773        }
13774        else {
13775            swap = line.charAt(column-1) + line.charAt(column-2);
13776            range = new Range(cursor.row, column-2, cursor.row, column);
13777        }
13778        this.session.replace(range, swap);
13779        this.session.selection.moveToPosition(range.end);
13780    };
13781    this.toLowerCase = function() {
13782        var originalRange = this.getSelectionRange();
13783        if (this.selection.isEmpty()) {
13784            this.selection.selectWord();
13785        }
13786
13787        var range = this.getSelectionRange();
13788        var text = this.session.getTextRange(range);
13789        this.session.replace(range, text.toLowerCase());
13790        this.selection.setSelectionRange(originalRange);
13791    };
13792    this.toUpperCase = function() {
13793        var originalRange = this.getSelectionRange();
13794        if (this.selection.isEmpty()) {
13795            this.selection.selectWord();
13796        }
13797
13798        var range = this.getSelectionRange();
13799        var text = this.session.getTextRange(range);
13800        this.session.replace(range, text.toUpperCase());
13801        this.selection.setSelectionRange(originalRange);
13802    };
13803    this.indent = function() {
13804        var session = this.session;
13805        var range = this.getSelectionRange();
13806
13807        if (range.start.row < range.end.row) {
13808            var rows = this.$getSelectedRows();
13809            session.indentRows(rows.first, rows.last, "\t");
13810            return;
13811        } else if (range.start.column < range.end.column) {
13812            var text = session.getTextRange(range);
13813            if (!/^\s+$/.test(text)) {
13814                var rows = this.$getSelectedRows();
13815                session.indentRows(rows.first, rows.last, "\t");
13816                return;
13817            }
13818        }
13819        
13820        var line = session.getLine(range.start.row);
13821        var position = range.start;
13822        var size = session.getTabSize();
13823        var column = session.documentToScreenColumn(position.row, position.column);
13824
13825        if (this.session.getUseSoftTabs()) {
13826            var count = (size - column % size);
13827            var indentString = lang.stringRepeat(" ", count);
13828        } else {
13829            var count = column % size;
13830            while (line[range.start.column - 1] == " " && count) {
13831                range.start.column--;
13832                count--;
13833            }
13834            this.selection.setSelectionRange(range);
13835            indentString = "\t";
13836        }
13837        return this.insert(indentString);
13838    };
13839    this.blockIndent = function() {
13840        var rows = this.$getSelectedRows();
13841        this.session.indentRows(rows.first, rows.last, "\t");
13842    };
13843    this.blockOutdent = function() {
13844        var selection = this.session.getSelection();
13845        this.session.outdentRows(selection.getRange());
13846    };
13847    this.sortLines = function() {
13848        var rows = this.$getSelectedRows();
13849        var session = this.session;
13850
13851        var lines = [];
13852        for (var i = rows.first; i <= rows.last; i++)
13853            lines.push(session.getLine(i));
13854
13855        lines.sort(function(a, b) {
13856            if (a.toLowerCase() < b.toLowerCase()) return -1;
13857            if (a.toLowerCase() > b.toLowerCase()) return 1;
13858            return 0;
13859        });
13860
13861        var deleteRange = new Range(0, 0, 0, 0);
13862        for (var i = rows.first; i <= rows.last; i++) {
13863            var line = session.getLine(i);
13864            deleteRange.start.row = i;
13865            deleteRange.end.row = i;
13866            deleteRange.end.column = line.length;
13867            session.replace(deleteRange, lines[i-rows.first]);
13868        }
13869    };
13870    this.toggleCommentLines = function() {
13871        var state = this.session.getState(this.getCursorPosition().row);
13872        var rows = this.$getSelectedRows();
13873        this.session.getMode().toggleCommentLines(state, this.session, rows.first, rows.last);
13874    };
13875
13876    this.toggleBlockComment = function() {
13877        var cursor = this.getCursorPosition();
13878        var state = this.session.getState(cursor.row);
13879        var range = this.getSelectionRange();
13880        this.session.getMode().toggleBlockComment(state, this.session, range, cursor);
13881    };
13882    this.getNumberAt = function(row, column) {
13883        var _numberRx = /[\-]?[0-9]+(?:\.[0-9]+)?/g;
13884        _numberRx.lastIndex = 0;
13885
13886        var s = this.session.getLine(row);
13887        while (_numberRx.lastIndex < column) {
13888            var m = _numberRx.exec(s);
13889            if(m.index <= column && m.index+m[0].length >= column){
13890                var number = {
13891                    value: m[0],
13892                    start: m.index,
13893                    end: m.index+m[0].length
13894                };
13895                return number;
13896            }
13897        }
13898        return null;
13899    };
13900    this.modifyNumber = function(amount) {
13901        var row = this.selection.getCursor().row;
13902        var column = this.selection.getCursor().column;
13903        var charRange = new Range(row, column-1, row, column);
13904
13905        var c = this.session.getTextRange(charRange);
13906        if (!isNaN(parseFloat(c)) && isFinite(c)) {
13907            var nr = this.getNumberAt(row, column);
13908            if (nr) {
13909                var fp = nr.value.indexOf(".") >= 0 ? nr.start + nr.value.indexOf(".") + 1 : nr.end;
13910                var decimals = nr.start + nr.value.length - fp;
13911
13912                var t = parseFloat(nr.value);
13913                t *= Math.pow(10, decimals);
13914
13915
13916                if(fp !== nr.end && column < fp){
13917                    amount *= Math.pow(10, nr.end - column - 1);
13918                } else {
13919                    amount *= Math.pow(10, nr.end - column);
13920                }
13921
13922                t += amount;
13923                t /= Math.pow(10, decimals);
13924                var nnr = t.toFixed(decimals);
13925                var replaceRange = new Range(row, nr.start, row, nr.end);
13926                this.session.replace(replaceRange, nnr);
13927                this.moveCursorTo(row, Math.max(nr.start +1, column + nnr.length - nr.value.length));
13928
13929            }
13930        }
13931    };
13932    this.removeLines = function() {
13933        var rows = this.$getSelectedRows();
13934        this.session.removeFullLines(rows.first, rows.last);
13935        this.clearSelection();
13936    };
13937
13938    this.duplicateSelection = function() {
13939        var sel = this.selection;
13940        var doc = this.session;
13941        var range = sel.getRange();
13942        var reverse = sel.isBackwards();
13943        if (range.isEmpty()) {
13944            var row = range.start.row;
13945            doc.duplicateLines(row, row);
13946        } else {
13947            var point = reverse ? range.start : range.end;
13948            var endPoint = doc.insert(point, doc.getTextRange(range), false);
13949            range.start = point;
13950            range.end = endPoint;
13951
13952            sel.setSelectionRange(range, reverse);
13953        }
13954    };
13955    this.moveLinesDown = function() {
13956        this.$moveLines(1, false);
13957    };
13958    this.moveLinesUp = function() {
13959        this.$moveLines(-1, false);
13960    };
13961    this.moveText = function(range, toPosition, copy) {
13962        return this.session.moveText(range, toPosition, copy);
13963    };
13964    this.copyLinesUp = function() {
13965        this.$moveLines(-1, true);
13966    };
13967    this.copyLinesDown = function() {
13968        this.$moveLines(1, true);
13969    };
13970    this.$moveLines = function(dir, copy) {
13971        var rows, moved;
13972        var selection = this.selection;
13973        if (!selection.inMultiSelectMode || this.inVirtualSelectionMode) {
13974            var range = selection.toOrientedRange();
13975            rows = this.$getSelectedRows(range);
13976            moved = this.session.$moveLines(rows.first, rows.last, copy ? 0 : dir);
13977            if (copy && dir == -1) moved = 0;
13978            range.moveBy(moved, 0);
13979            selection.fromOrientedRange(range);
13980        } else {
13981            var ranges = selection.rangeList.ranges;
13982            selection.rangeList.detach(this.session);
13983            this.inVirtualSelectionMode = true;
13984            
13985            var diff = 0;
13986            var totalDiff = 0;
13987            var l = ranges.length;
13988            for (var i = 0; i < l; i++) {
13989                var rangeIndex = i;
13990                ranges[i].moveBy(diff, 0);
13991                rows = this.$getSelectedRows(ranges[i]);
13992                var first = rows.first;
13993                var last = rows.last;
13994                while (++i < l) {
13995                    if (totalDiff) ranges[i].moveBy(totalDiff, 0);
13996                    var subRows = this.$getSelectedRows(ranges[i]);
13997                    if (copy && subRows.first != last)
13998                        break;
13999                    else if (!copy && subRows.first > last + 1)
14000                        break;
14001                    last = subRows.last;
14002                }
14003                i--;
14004                diff = this.session.$moveLines(first, last, copy ? 0 : dir);
14005                if (copy && dir == -1) rangeIndex = i + 1;
14006                while (rangeIndex <= i) {
14007                    ranges[rangeIndex].moveBy(diff, 0);
14008                    rangeIndex++;
14009                }
14010                if (!copy) diff = 0;
14011                totalDiff += diff;
14012            }
14013            
14014            selection.fromOrientedRange(selection.ranges[0]);
14015            selection.rangeList.attach(this.session);
14016            this.inVirtualSelectionMode = false;
14017        }
14018    };
14019    this.$getSelectedRows = function(range) {
14020        range = (range || this.getSelectionRange()).collapseRows();
14021
14022        return {
14023            first: this.session.getRowFoldStart(range.start.row),
14024            last: this.session.getRowFoldEnd(range.end.row)
14025        };
14026    };
14027
14028    this.onCompositionStart = function(text) {
14029        this.renderer.showComposition(this.getCursorPosition());
14030    };
14031
14032    this.onCompositionUpdate = function(text) {
14033        this.renderer.setCompositionText(text);
14034    };
14035
14036    this.onCompositionEnd = function() {
14037        this.renderer.hideComposition();
14038    };
14039    this.getFirstVisibleRow = function() {
14040        return this.renderer.getFirstVisibleRow();
14041    };
14042    this.getLastVisibleRow = function() {
14043        return this.renderer.getLastVisibleRow();
14044    };
14045    this.isRowVisible = function(row) {
14046        return (row >= this.getFirstVisibleRow() && row <= this.getLastVisibleRow());
14047    };
14048    this.isRowFullyVisible = function(row) {
14049        return (row >= this.renderer.getFirstFullyVisibleRow() && row <= this.renderer.getLastFullyVisibleRow());
14050    };
14051    this.$getVisibleRowCount = function() {
14052        return this.renderer.getScrollBottomRow() - this.renderer.getScrollTopRow() + 1;
14053    };
14054
14055    this.$moveByPage = function(dir, select) {
14056        var renderer = this.renderer;
14057        var config = this.renderer.layerConfig;
14058        var rows = dir * Math.floor(config.height / config.lineHeight);
14059
14060        if (select === true) {
14061            this.selection.$moveSelection(function(){
14062                this.moveCursorBy(rows, 0);
14063            });
14064        } else if (select === false) {
14065            this.selection.moveCursorBy(rows, 0);
14066            this.selection.clearSelection();
14067        }
14068
14069        var scrollTop = renderer.scrollTop;
14070
14071        renderer.scrollBy(0, rows * config.lineHeight);
14072        if (select != null)
14073            renderer.scrollCursorIntoView(null, 0.5);
14074
14075        renderer.animateScrolling(scrollTop);
14076    };
14077    this.selectPageDown = function() {
14078        this.$moveByPage(1, true);
14079    };
14080    this.selectPageUp = function() {
14081        this.$moveByPage(-1, true);
14082    };
14083    this.gotoPageDown = function() {
14084       this.$moveByPage(1, false);
14085    };
14086    this.gotoPageUp = function() {
14087        this.$moveByPage(-1, false);
14088    };
14089    this.scrollPageDown = function() {
14090        this.$moveByPage(1);
14091    };
14092    this.scrollPageUp = function() {
14093        this.$moveByPage(-1);
14094    };
14095    this.scrollToRow = function(row) {
14096        this.renderer.scrollToRow(row);
14097    };
14098    this.scrollToLine = function(line, center, animate, callback) {
14099        this.renderer.scrollToLine(line, center, animate, callback);
14100    };
14101    this.centerSelection = function() {
14102        var range = this.getSelectionRange();
14103        var pos = {
14104            row: Math.floor(range.start.row + (range.end.row - range.start.row) / 2),
14105            column: Math.floor(range.start.column + (range.end.column - range.start.column) / 2)
14106        };
14107        this.renderer.alignCursor(pos, 0.5);
14108    };
14109    this.getCursorPosition = function() {
14110        return this.selection.getCursor();
14111    };
14112    this.getCursorPositionScreen = function() {
14113        return this.session.documentToScreenPosition(this.getCursorPosition());
14114    };
14115    this.getSelectionRange = function() {
14116        return this.selection.getRange();
14117    };
14118    this.selectAll = function() {
14119        this.selection.selectAll();
14120    };
14121    this.clearSelection = function() {
14122        this.selection.clearSelection();
14123    };
14124    this.moveCursorTo = function(row, column) {
14125        this.selection.moveCursorTo(row, column);
14126    };
14127    this.moveCursorToPosition = function(pos) {
14128        this.selection.moveCursorToPosition(pos);
14129    };
14130    this.jumpToMatching = function(select, expand) {
14131        var cursor = this.getCursorPosition();
14132        var iterator = new TokenIterator(this.session, cursor.row, cursor.column);
14133        var prevToken = iterator.getCurrentToken();
14134        var token = prevToken || iterator.stepForward();
14135
14136        if (!token) return;
14137        var matchType;
14138        var found = false;
14139        var depth = {};
14140        var i = cursor.column - token.start;
14141        var bracketType;
14142        var brackets = {
14143            ")": "(",
14144            "(": "(",
14145            "]": "[",
14146            "[": "[",
14147            "{": "{",
14148            "}": "{"
14149        };
14150        
14151        do {
14152            if (token.value.match(/[{}()\[\]]/g)) {
14153                for (; i < token.value.length && !found; i++) {
14154                    if (!brackets[token.value[i]]) {
14155                        continue;
14156                    }
14157
14158                    bracketType = brackets[token.value[i]] + '.' + token.type.replace("rparen", "lparen");
14159
14160                    if (isNaN(depth[bracketType])) {
14161                        depth[bracketType] = 0;
14162                    }
14163
14164                    switch (token.value[i]) {
14165                        case '(':
14166                        case '[':
14167                        case '{':
14168                            depth[bracketType]++;
14169                            break;
14170                        case ')':
14171                        case ']':
14172                        case '}':
14173                            depth[bracketType]--;
14174
14175                            if (depth[bracketType] === -1) {
14176                                matchType = 'bracket';
14177                                found = true;
14178                            }
14179                        break;
14180                    }
14181                }
14182            }
14183            else if (token.type.indexOf('tag-name') !== -1) {
14184                if (isNaN(depth[token.value])) {
14185                    depth[token.value] = 0;
14186                }
14187                
14188                if (prevToken.value === '<') {
14189                    depth[token.value]++;
14190                }
14191                else if (prevToken.value === '</') {
14192                    depth[token.value]--;
14193                }
14194                
14195                if (depth[token.value] === -1) {
14196                    matchType = 'tag';
14197                    found = true;
14198                }
14199            }
14200
14201            if (!found) {
14202                prevToken = token;
14203                token = iterator.stepForward();
14204                i = 0;
14205            }
14206        } while (token && !found);
14207        if (!matchType)
14208            return;
14209
14210        var range, pos;
14211        if (matchType === 'bracket') {
14212            range = this.session.getBracketRange(cursor);
14213            if (!range) {
14214                range = new Range(
14215                    iterator.getCurrentTokenRow(),
14216                    iterator.getCurrentTokenColumn() + i - 1,
14217                    iterator.getCurrentTokenRow(),
14218                    iterator.getCurrentTokenColumn() + i - 1
14219                );
14220                pos = range.start;
14221                if (expand || pos.row === cursor.row && Math.abs(pos.column - cursor.column) < 2)
14222                    range = this.session.getBracketRange(pos);
14223            }
14224        }
14225        else if (matchType === 'tag') {
14226            if (token && token.type.indexOf('tag-name') !== -1) 
14227                var tag = token.value;
14228            else
14229                return;
14230
14231            range = new Range(
14232                iterator.getCurrentTokenRow(),
14233                iterator.getCurrentTokenColumn() - 2,
14234                iterator.getCurrentTokenRow(),
14235                iterator.getCurrentTokenColumn() - 2
14236            );
14237            if (range.compare(cursor.row, cursor.column) === 0) {
14238                found = false;
14239                do {
14240                    token = prevToken;
14241                    prevToken = iterator.stepBackward();
14242                    
14243                    if (prevToken) {
14244                        if (prevToken.type.indexOf('tag-close') !== -1) {
14245                            range.setEnd(iterator.getCurrentTokenRow(), iterator.getCurrentTokenColumn() + 1);
14246                        }
14247
14248                        if (token.value === tag && token.type.indexOf('tag-name') !== -1) {
14249                            if (prevToken.value === '<') {
14250                                depth[tag]++;
14251                            }
14252                            else if (prevToken.value === '</') {
14253                                depth[tag]--;
14254                            }
14255                            
14256                            if (depth[tag] === 0)
14257                                found = true;
14258                        }
14259                    }
14260                } while (prevToken && !found);
14261            }
14262            if (token && token.type.indexOf('tag-name')) {
14263                pos = range.start;
14264                if (pos.row == cursor.row && Math.abs(pos.column - cursor.column) < 2)
14265                    pos = range.end;
14266            }
14267        }
14268
14269        pos = range && range.cursor || pos;
14270        if (pos) {
14271            if (select) {
14272                if (range && expand) {
14273                    this.selection.setRange(range);
14274                } else if (range && range.isEqual(this.getSelectionRange())) {
14275                    this.clearSelection();
14276                } else {
14277                    this.selection.selectTo(pos.row, pos.column);
14278                }
14279            } else {
14280                this.selection.moveTo(pos.row, pos.column);
14281            }
14282        }
14283    };
14284    this.gotoLine = function(lineNumber, column, animate) {
14285        this.selection.clearSelection();
14286        this.session.unfold({row: lineNumber - 1, column: column || 0});
14287        this.exitMultiSelectMode && this.exitMultiSelectMode();
14288        this.moveCursorTo(lineNumber - 1, column || 0);
14289
14290        if (!this.isRowFullyVisible(lineNumber - 1))
14291            this.scrollToLine(lineNumber - 1, true, animate);
14292    };
14293    this.navigateTo = function(row, column) {
14294        this.selection.moveTo(row, column);
14295    };
14296    this.navigateUp = function(times) {
14297        if (this.selection.isMultiLine() && !this.selection.isBackwards()) {
14298            var selectionStart = this.selection.anchor.getPosition();
14299            return this.moveCursorToPosition(selectionStart);
14300        }
14301        this.selection.clearSelection();
14302        this.selection.moveCursorBy(-times || -1, 0);
14303    };
14304    this.navigateDown = function(times) {
14305        if (this.selection.isMultiLine() && this.selection.isBackwards()) {
14306            var selectionEnd = this.selection.anchor.getPosition();
14307            return this.moveCursorToPosition(selectionEnd);
14308        }
14309        this.selection.clearSelection();
14310        this.selection.moveCursorBy(times || 1, 0);
14311    };
14312    this.navigateLeft = function(times) {
14313        if (!this.selection.isEmpty()) {
14314            var selectionStart = this.getSelectionRange().start;
14315            this.moveCursorToPosition(selectionStart);
14316        }
14317        else {
14318            times = times || 1;
14319            while (times--) {
14320                this.selection.moveCursorLeft();
14321            }
14322        }
14323        this.clearSelection();
14324    };
14325    this.navigateRight = function(times) {
14326        if (!this.selection.isEmpty()) {
14327            var selectionEnd = this.getSelectionRange().end;
14328            this.moveCursorToPosition(selectionEnd);
14329        }
14330        else {
14331            times = times || 1;
14332            while (times--) {
14333                this.selection.moveCursorRight();
14334            }
14335        }
14336        this.clearSelection();
14337    };
14338    this.navigateLineStart = function() {
14339        this.selection.moveCursorLineStart();
14340        this.clearSelection();
14341    };
14342    this.navigateLineEnd = function() {
14343        this.selection.moveCursorLineEnd();
14344        this.clearSelection();
14345    };
14346    this.navigateFileEnd = function() {
14347        this.selection.moveCursorFileEnd();
14348        this.clearSelection();
14349    };
14350    this.navigateFileStart = function() {
14351        this.selection.moveCursorFileStart();
14352        this.clearSelection();
14353    };
14354    this.navigateWordRight = function() {
14355        this.selection.moveCursorWordRight();
14356        this.clearSelection();
14357    };
14358    this.navigateWordLeft = function() {
14359        this.selection.moveCursorWordLeft();
14360        this.clearSelection();
14361    };
14362    this.replace = function(replacement, options) {
14363        if (options)
14364            this.$search.set(options);
14365
14366        var range = this.$search.find(this.session);
14367        var replaced = 0;
14368        if (!range)
14369            return replaced;
14370
14371        if (this.$tryReplace(range, replacement)) {
14372            replaced = 1;
14373        }
14374
14375        this.selection.setSelectionRange(range);
14376        this.renderer.scrollSelectionIntoView(range.start, range.end);
14377
14378        return replaced;
14379    };
14380    this.replaceAll = function(replacement, options) {
14381        if (options) {
14382            this.$search.set(options);
14383        }
14384
14385        var ranges = this.$search.findAll(this.session);
14386        var replaced = 0;
14387        if (!ranges.length)
14388            return replaced;
14389
vendor: 20,283 bytes, lines 14390-15060
14390        var selection = this.getSelectionRange();
14391        this.selection.moveTo(0, 0);
14392
14393        for (var i = ranges.length - 1; i >= 0; --i) {
14394            if(this.$tryReplace(ranges[i], replacement)) {
14395                replaced++;
14396            }
14397        }
14398
14399        this.selection.setSelectionRange(selection);
14400
14401        return replaced;
14402    };
14403
14404    this.$tryReplace = function(range, replacement) {
14405        var input = this.session.getTextRange(range);
14406        replacement = this.$search.replace(input, replacement);
14407        if (replacement !== null) {
14408            range.end = this.session.replace(range, replacement);
14409            return range;
14410        } else {
14411            return null;
14412        }
14413    };
14414    this.getLastSearchOptions = function() {
14415        return this.$search.getOptions();
14416    };
14417    this.find = function(needle, options, animate) {
14418        if (!options)
14419            options = {};
14420
14421        if (typeof needle == "string" || needle instanceof RegExp)
14422            options.needle = needle;
14423        else if (typeof needle == "object")
14424            oop.mixin(options, needle);
14425
14426        var range = this.selection.getRange();
14427        if (options.needle == null) {
14428            needle = this.session.getTextRange(range)
14429                || this.$search.$options.needle;
14430            if (!needle) {
14431                range = this.session.getWordRange(range.start.row, range.start.column);
14432                needle = this.session.getTextRange(range);
14433            }
14434            this.$search.set({needle: needle});
14435        }
14436
14437        this.$search.set(options);
14438        if (!options.start)
14439            this.$search.set({start: range});
14440
14441        var newRange = this.$search.find(this.session);
14442        if (options.preventScroll)
14443            return newRange;
14444        if (newRange) {
14445            this.revealRange(newRange, animate);
14446            return newRange;
14447        }
14448        if (options.backwards)
14449            range.start = range.end;
14450        else
14451            range.end = range.start;
14452        this.selection.setRange(range);
14453    };
14454    this.findNext = function(options, animate) {
14455        this.find({skipCurrent: true, backwards: false}, options, animate);
14456    };
14457    this.findPrevious = function(options, animate) {
14458        this.find(options, {skipCurrent: true, backwards: true}, animate);
14459    };
14460
14461    this.revealRange = function(range, animate) {
14462        this.session.unfold(range);
14463        this.selection.setSelectionRange(range);
14464
14465        var scrollTop = this.renderer.scrollTop;
14466        this.renderer.scrollSelectionIntoView(range.start, range.end, 0.5);
14467        if (animate !== false)
14468            this.renderer.animateScrolling(scrollTop);
14469    };
14470    this.undo = function() {
14471        this.session.getUndoManager().undo(this.session);
14472        this.renderer.scrollCursorIntoView(null, 0.5);
14473    };
14474    this.redo = function() {
14475        this.session.getUndoManager().redo(this.session);
14476        this.renderer.scrollCursorIntoView(null, 0.5);
14477    };
14478    this.destroy = function() {
14479        this.renderer.destroy();
14480        this._signal("destroy", this);
14481        if (this.session) {
14482            this.session.destroy();
14483        }
14484    };
14485    this.setAutoScrollEditorIntoView = function(enable) {
14486        if (!enable)
14487            return;
14488        var rect;
14489        var self = this;
14490        var shouldScroll = false;
14491        if (!this.$scrollAnchor)
14492            this.$scrollAnchor = document.createElement("div");
14493        var scrollAnchor = this.$scrollAnchor;
14494        scrollAnchor.style.cssText = "position:absolute";
14495        this.container.insertBefore(scrollAnchor, this.container.firstChild);
14496        var onChangeSelection = this.on("changeSelection", function() {
14497            shouldScroll = true;
14498        });
14499        var onBeforeRender = this.renderer.on("beforeRender", function() {
14500            if (shouldScroll)
14501                rect = self.renderer.container.getBoundingClientRect();
14502        });
14503        var onAfterRender = this.renderer.on("afterRender", function() {
14504            if (shouldScroll && rect && (self.isFocused()
14505                || self.searchBox && self.searchBox.isFocused())
14506            ) {
14507                var renderer = self.renderer;
14508                var pos = renderer.$cursorLayer.$pixelPos;
14509                var config = renderer.layerConfig;
14510                var top = pos.top - config.offset;
14511                if (pos.top >= 0 && top + rect.top < 0) {
14512                    shouldScroll = true;
14513                } else if (pos.top < config.height &&
14514                    pos.top + rect.top + config.lineHeight > window.innerHeight) {
14515                    shouldScroll = false;
14516                } else {
14517                    shouldScroll = null;
14518                }
14519                if (shouldScroll != null) {
14520                    scrollAnchor.style.top = top + "px";
14521                    scrollAnchor.style.left = pos.left + "px";
14522                    scrollAnchor.style.height = config.lineHeight + "px";
14523                    scrollAnchor.scrollIntoView(shouldScroll);
14524                }
14525                shouldScroll = rect = null;
14526            }
14527        });
14528        this.setAutoScrollEditorIntoView = function(enable) {
14529            if (enable)
14530                return;
14531            delete this.setAutoScrollEditorIntoView;
14532            this.off("changeSelection", onChangeSelection);
14533            this.renderer.off("afterRender", onAfterRender);
14534            this.renderer.off("beforeRender", onBeforeRender);
14535        };
14536    };
14537
14538
14539    this.$resetCursorStyle = function() {
14540        var style = this.$cursorStyle || "ace";
14541        var cursorLayer = this.renderer.$cursorLayer;
14542        if (!cursorLayer)
14543            return;
14544        cursorLayer.setSmoothBlinking(/smooth/.test(style));
14545        cursorLayer.isBlinking = !this.$readOnly && style != "wide";
14546        dom.setCssClass(cursorLayer.element, "ace_slim-cursors", /slim/.test(style));
14547    };
14548
14549}).call(Editor.prototype);
14550
14551
14552
14553config.defineOptions(Editor.prototype, "editor", {
14554    selectionStyle: {
14555        set: function(style) {
14556            this.onSelectionChange();
14557            this._signal("changeSelectionStyle", {data: style});
14558        },
14559        initialValue: "line"
14560    },
14561    highlightActiveLine: {
14562        set: function() {this.$updateHighlightActiveLine();},
14563        initialValue: true
14564    },
14565    highlightSelectedWord: {
14566        set: function(shouldHighlight) {this.$onSelectionChange();},
14567        initialValue: true
14568    },
14569    readOnly: {
14570        set: function(readOnly) {
14571            this.textInput.setReadOnly(readOnly);
14572            this.$resetCursorStyle(); 
14573        },
14574        initialValue: false
14575    },
14576    copyWithEmptySelection: {
14577        set: function(value) {
14578            this.textInput.setCopyWithEmptySelection(value);
14579        },
14580        initialValue: false
14581    },
14582    cursorStyle: {
14583        set: function(val) { this.$resetCursorStyle(); },
14584        values: ["ace", "slim", "smooth", "wide"],
14585        initialValue: "ace"
14586    },
14587    mergeUndoDeltas: {
14588        values: [false, true, "always"],
14589        initialValue: true
14590    },
14591    behavioursEnabled: {initialValue: true},
14592    wrapBehavioursEnabled: {initialValue: true},
14593    autoScrollEditorIntoView: {
14594        set: function(val) {this.setAutoScrollEditorIntoView(val);}
14595    },
14596    keyboardHandler: {
14597        set: function(val) { this.setKeyboardHandler(val); },
14598        get: function() { return this.$keybindingId; },
14599        handlesSet: true
14600    },
14601    value: {
14602        set: function(val) { this.session.setValue(val); },
14603        get: function() { return this.getValue(); },
14604        handlesSet: true,
14605        hidden: true
14606    },
14607    session: {
14608        set: function(val) { this.setSession(val); },
14609        get: function() { return this.session; },
14610        handlesSet: true,
14611        hidden: true
14612    },
14613
14614    hScrollBarAlwaysVisible: "renderer",
14615    vScrollBarAlwaysVisible: "renderer",
14616    highlightGutterLine: "renderer",
14617    animatedScroll: "renderer",
14618    showInvisibles: "renderer",
14619    showPrintMargin: "renderer",
14620    printMarginColumn: "renderer",
14621    printMargin: "renderer",
14622    fadeFoldWidgets: "renderer",
14623    showFoldWidgets: "renderer",
14624    showLineNumbers: "renderer",
14625    showGutter: "renderer",
14626    displayIndentGuides: "renderer",
14627    fontSize: "renderer",
14628    fontFamily: "renderer",
14629    maxLines: "renderer",
14630    minLines: "renderer",
14631    scrollPastEnd: "renderer",
14632    fixedWidthGutter: "renderer",
14633    theme: "renderer",
14634
14635    scrollSpeed: "$mouseHandler",
14636    dragDelay: "$mouseHandler",
14637    dragEnabled: "$mouseHandler",
14638    focusTimeout: "$mouseHandler",
14639    tooltipFollowsMouse: "$mouseHandler",
14640
14641    firstLineNumber: "session",
14642    overwrite: "session",
14643    newLineMode: "session",
14644    useWorker: "session",
14645    useSoftTabs: "session",
14646    navigateWithinSoftTabs: "session",
14647    tabSize: "session",
14648    wrap: "session",
14649    indentedSoftWrap: "session",
14650    foldStyle: "session",
14651    mode: "session"
14652});
14653
14654exports.Editor = Editor;
14655});
14656
14657define("ace/undomanager",["require","exports","module","ace/range"], function(require, exports, module) {
14658"use strict";
14659var UndoManager = function() {
14660    this.$maxRev = 0;
14661    this.$fromUndo = false;
14662    this.reset();
14663};
14664
14665(function() {
14666    
14667    this.addSession = function(session) {
14668        this.$session = session;
14669    };
14670    this.add = function(delta, allowMerge, session) {
14671        if (this.$fromUndo) return;
14672        if (delta == this.$lastDelta) return;
14673        if (allowMerge === false || !this.lastDeltas) {
14674            this.lastDeltas = [];
14675            this.$undoStack.push(this.lastDeltas);
14676            delta.id = this.$rev = ++this.$maxRev;
14677        }
14678        if (delta.action == "remove" || delta.action == "insert")
14679            this.$lastDelta = delta;
14680        this.lastDeltas.push(delta);
14681    };
14682    
14683    this.addSelection = function(selection, rev) {
14684        this.selections.push({
14685            value: selection,
14686            rev: rev || this.$rev
14687        });
14688    };
14689    
14690    this.startNewGroup = function() {
14691        this.lastDeltas = null;
14692        return this.$rev;
14693    };
14694    
14695    this.markIgnored = function(from, to) {
14696        if (to == null) to = this.$rev + 1;
14697        var stack = this.$undoStack;
14698        for (var i = stack.length; i--;) {
14699            var delta = stack[i][0];
14700            if (delta.id <= from)
14701                break;
14702            if (delta.id < to)
14703                delta.ignore = true;
14704        }
14705        this.lastDeltas = null;
14706    };
14707    
14708    this.getSelection = function(rev, after) {
14709        var stack = this.selections;
14710        for (var i = stack.length; i--;) {
14711            var selection = stack[i];
14712            if (selection.rev < rev) {
14713                if (after)
14714                    selection = stack[i + 1];
14715                return selection;
14716            }
14717        }
14718    };
14719    
14720    this.getRevision = function() {
14721        return this.$rev;
14722    };
14723    
14724    this.getDeltas = function(from, to) {
14725        if (to == null) to = this.$rev + 1;
14726        var stack = this.$undoStack;
14727        var end = null, start = 0;
14728        for (var i = stack.length; i--;) {
14729            var delta = stack[i][0];
14730            if (delta.id < to && !end)
14731                end = i+1;
14732            if (delta.id <= from) {
14733                start = i + 1;
14734                break;
14735            }
14736        }
14737        return stack.slice(start, end);
14738    };
14739    
14740    this.getChangedRanges = function(from, to) {
14741        if (to == null) to = this.$rev + 1;
14742        
14743    };
14744    
14745    this.getChangedLines = function(from, to) {
14746        if (to == null) to = this.$rev + 1;
14747        
14748    };
14749    this.undo = function(session, dontSelect) {
14750        this.lastDeltas = null;
14751        var stack = this.$undoStack;
14752        
14753        if (!rearrangeUndoStack(stack, stack.length))
14754            return;
14755        
14756        if (!session)
14757            session = this.$session;
14758        
14759        if (this.$redoStackBaseRev !== this.$rev && this.$redoStack.length)
14760            this.$redoStack = [];
14761        
14762        this.$fromUndo = true;
14763        
14764        var deltaSet = stack.pop();
14765        var undoSelectionRange = null;
14766        if (deltaSet && deltaSet.length) {
14767            undoSelectionRange = session.undoChanges(deltaSet, dontSelect);
14768            this.$redoStack.push(deltaSet);
14769            this.$syncRev();
14770        }
14771        
14772        this.$fromUndo = false;
14773
14774        return undoSelectionRange;
14775    };
14776    this.redo = function(session, dontSelect) {
14777        this.lastDeltas = null;
14778        
14779        if (!session)
14780            session = this.$session;
14781        
14782        this.$fromUndo = true;
14783        if (this.$redoStackBaseRev != this.$rev) {
14784            var diff = this.getDeltas(this.$redoStackBaseRev, this.$rev + 1);
14785            rebaseRedoStack(this.$redoStack, diff);
14786            this.$redoStackBaseRev = this.$rev;
14787            this.$redoStack.forEach(function(x) {
14788                x[0].id = ++this.$maxRev;
14789            }, this);
14790        }
14791        var deltaSet = this.$redoStack.pop();
14792        var redoSelectionRange = null;
14793        
14794        if (deltaSet) {
14795            redoSelectionRange = session.redoChanges(deltaSet, dontSelect);
14796            this.$undoStack.push(deltaSet);
14797            this.$syncRev();
14798        }
14799        this.$fromUndo = false;
14800        
14801        return redoSelectionRange;
14802    };
14803    
14804    this.$syncRev = function() {
14805        var stack = this.$undoStack;
14806        var nextDelta = stack[stack.length - 1];
14807        var id = nextDelta && nextDelta[0].id || 0;
14808        this.$redoStackBaseRev = id;
14809        this.$rev = id;
14810    };
14811    this.reset = function() {
14812        this.lastDeltas = null;
14813        this.$lastDelta = null;
14814        this.$undoStack = [];
14815        this.$redoStack = [];
14816        this.$rev = 0;
14817        this.mark = 0;
14818        this.$redoStackBaseRev = this.$rev;
14819        this.selections = [];
14820    };
14821    this.canUndo = function() {
14822        return this.$undoStack.length > 0;
14823    };
14824    this.canRedo = function() {
14825        return this.$redoStack.length > 0;
14826    };
14827    this.bookmark = function(rev) {
14828        if (rev == undefined)
14829            rev = this.$rev;
14830        this.mark = rev;
14831    };
14832    this.isAtBookmark = function() {
14833        return this.$rev === this.mark;
14834    };
14835    
14836    this.toJSON = function() {
14837        
14838    };
14839    
14840    this.fromJSON = function() {
14841        
14842    };
14843    
14844    this.hasUndo = this.canUndo;
14845    this.hasRedo = this.canRedo;
14846    this.isClean = this.isAtBookmark;
14847    this.markClean = this.bookmark;
14848    
14849}).call(UndoManager.prototype);
14850
14851function rearrangeUndoStack(stack, pos) {
14852    for (var i = pos; i--; ) {
14853        var deltaSet = stack[i];
14854        if (deltaSet && !deltaSet[0].ignore) {
14855            while(i < pos - 1) {
14856                var swapped = swapGroups(stack[i], stack[i + 1]);
14857                stack[i] = swapped[0];
14858                stack[i + 1] = swapped[1];
14859                i++;
14860            }
14861            return true;
14862        }
14863    }
14864}
14865
14866var Range = require("./range").Range;
14867var cmp = Range.comparePoints;
14868var comparePoints = Range.comparePoints;
14869
14870function $updateMarkers(delta) {
14871    var isInsert = delta.action == "insert";
14872    var start = delta.start;
14873    var end = delta.end;
14874    var rowShift = (end.row - start.row) * (isInsert ? 1 : -1);
14875    var colShift = (end.column - start.column) * (isInsert ? 1 : -1);
14876    if (isInsert) end = start;
14877
14878    for (var i in this.marks) {
14879        var point = this.marks[i];
14880        var cmp = comparePoints(point, start);
14881        if (cmp < 0) {
14882            continue; // delta starts after the range
14883        }
14884        if (cmp === 0) {
14885            if (isInsert) {
14886                if (point.bias == 1) {
14887                    cmp = 1;
14888                }
14889                else {
14890                    point.bias == -1;
14891                    continue;
14892                }
14893            }
14894        }
14895        var cmp2 = isInsert ? cmp : comparePoints(point, end);
14896        if (cmp2 > 0) {
14897            point.row += rowShift;
14898            point.column += point.row == end.row ? colShift : 0;
14899            continue;
14900        }
14901        if (!isInsert && cmp2 <= 0) {
14902            point.row = start.row;
14903            point.column = start.column;
14904            if (cmp2 === 0)
14905                point.bias = 1;
14906        }
14907    }
14908}
14909
14910
14911
14912function clonePos(pos) {
14913    return {row: pos.row,column: pos.column};
14914}
14915function cloneDelta(d) {
14916    return {
14917        start: clonePos(d.start),
14918        end: clonePos(d.end),
14919        action: d.action,
14920        lines: d.lines.slice()
14921    };
14922}
14923function stringifyDelta(d) {
14924    d = d || this;
14925    if (Array.isArray(d)) {
14926        return d.map(stringifyDelta).join("\n");
14927    }
14928    var type = "";
14929    if (d.action) {
14930        type = d.action == "insert" ? "+" : "-";
14931        type += "[" + d.lines + "]";
14932    } else if (d.value) {
14933        if (Array.isArray(d.value)) {
14934            type = d.value.map(stringifyRange).join("\n");
14935        } else {
14936            type = stringifyRange(d.value);
14937        }
14938    }
14939    if (d.start) {
14940        type += stringifyRange(d);
14941    }
14942    if (d.id || d.rev) {
14943        type += "\t(" + (d.id || d.rev) + ")";
14944    }
14945    return type;
14946}
14947function stringifyRange(r) {
14948    return r.start.row + ":" + r.start.column 
14949        + "=>" + r.end.row + ":" + r.end.column;
14950}
14951
14952function swap(d1, d2) {
14953    var i1 = d1.action == "insert";
14954    var i2 = d2.action == "insert";
14955    
14956    if (i1 && i2) {
14957        if (cmp(d2.start, d1.end) >= 0) {
14958            shift(d2, d1, -1);
14959        } else if (cmp(d2.start, d1.start) <= 0) {
14960            shift(d1, d2, +1);
14961        } else {
14962            return null;
14963        }
14964    } else if (i1 && !i2) {
14965        if (cmp(d2.start, d1.end) >= 0) {
14966            shift(d2, d1, -1);
14967        } else if (cmp(d2.end, d1.start) <= 0) {
14968            shift(d1, d2, -1);
14969        } else {
14970            return null;
14971        }
14972    } else if (!i1 && i2) {
14973        if (cmp(d2.start, d1.start) >= 0) {
14974            shift(d2, d1, +1);
14975        } else if (cmp(d2.start, d1.start) <= 0) {
14976            shift(d1, d2, +1);
14977        } else {
14978            return null;
14979        }
14980    } else if (!i1 && !i2) {
14981        if (cmp(d2.start, d1.start) >= 0) {
14982            shift(d2, d1, +1);
14983        } else if (cmp(d2.end, d1.start) <= 0) {
14984            shift(d1, d2, -1);
14985        } else {
14986            return null;
14987        }
14988    }
14989    return [d2, d1];
14990}
14991function swapGroups(ds1, ds2) {
14992    for (var i = ds1.length; i--; ) {
14993        for (var j = 0; j < ds2.length; j++) {
14994            if (!swap(ds1[i], ds2[j])) {
14995                while (i < ds1.length) {
14996                    while (j--) {
14997                        swap(ds2[j], ds1[i]);
14998                    }
14999                    j = ds2.length;
15000                    i++;
15001                }                
15002                return [ds1, ds2];
15003            }
15004        }
15005    }
15006    ds1.selectionBefore = ds2.selectionBefore = 
15007    ds1.selectionAfter = ds2.selectionAfter = null;
15008    return [ds2, ds1];
15009}
15010function xform(d1, c1) {
15011    var i1 = d1.action == "insert";
15012    var i2 = c1.action == "insert";
15013    
15014    if (i1 && i2) {
15015        if (cmp(d1.start, c1.start) < 0) {
15016            shift(c1, d1, 1);
15017        } else {
15018            shift(d1, c1, 1);
15019        }
15020    } else if (i1 && !i2) {
15021        if (cmp(d1.start, c1.end) >= 0) {
15022            shift(d1, c1, -1);
15023        } else if (cmp(d1.start, c1.start) <= 0) {
15024            shift(c1, d1, +1);
15025        } else {
15026            shift(d1, Range.fromPoints(c1.start, d1.start), -1);
15027            shift(c1, d1, +1);
15028        }
15029    } else if (!i1 && i2) {
15030        if (cmp(c1.start, d1.end) >= 0) {
15031            shift(c1, d1, -1);
15032        } else if (cmp(c1.start, d1.start) <= 0) {
15033            shift(d1, c1, +1);
15034        } else {
15035            shift(c1, Range.fromPoints(d1.start, c1.start), -1);
15036            shift(d1, c1, +1);
15037        }
15038    } else if (!i1 && !i2) {
15039        if (cmp(c1.start, d1.end) >= 0) {
15040            shift(c1, d1, -1);
15041        } else if (cmp(c1.end, d1.start) <= 0) {
15042            shift(d1, c1, -1);
15043        } else {
15044            var before, after;
15045            if (cmp(d1.start, c1.start) < 0) {
15046                before = d1;
15047                d1 = splitDelta(d1, c1.start);
15048            }
15049            if (cmp(d1.end, c1.end) > 0) {
15050                after = splitDelta(d1, c1.end);
15051            }
15052
15053            shiftPos(c1.end, d1.start, d1.end, -1);
15054            if (after && !before) {
15055                d1.lines = after.lines;
15056                d1.start = after.start;
15057                d1.end = after.end;
15058                after = d1;
15059            }
15060
15061            return [c1, before, after].filter(Boolean);
15062        }
15063    }
15064    return [c1, d1];
15065}
15066    
15067function shift(d1, d2, dir) {
15068    shiftPos(d1.start, d2.start, d2.end, dir);
15069    shiftPos(d1.end, d2.start, d2.end, dir);
15070}
15071function shiftPos(pos, start, end, dir) {
15072    if (pos.row == (dir == 1 ? start : end).row) {
15073        pos.column += dir * (end.column - start.column);
15074    }
15075    pos.row += dir * (end.row - start.row);
15076}
15077function splitDelta(c, pos) {
15078    var lines = c.lines;
15079    var end = c.end;
15080    c.end = clonePos(pos);    
15081    var rowsBefore = c.end.row - c.start.row;
15082    var otherLines = lines.splice(rowsBefore, lines.length);
15083    
15084    var col = rowsBefore ? pos.column : pos.column - c.start.column;
15085    lines.push(otherLines[0].substring(0, col));
15086    otherLines[0] = otherLines[0].substr(col)   ; 
15087    var rest = {
15088        start: clonePos(pos),
15089        end: end,
15090        lines: otherLines,
15091        action: c.action
15092    };
15093    return rest;
15094}
15095
15096function moveDeltasByOne(redoStack, d) {
15097    d = cloneDelta(d);
15098    for (var j = redoStack.length; j--;) {
15099        var deltaSet = redoStack[j];
15100        for (var i = deltaSet.length; i--> 0;) {
15101            var x = deltaSet[i];
15102            var xformed = xform(x, d);
15103            d = xformed[0];
15104            if (xformed.length != 2) {
15105                if (xformed[2]) {
15106                    redoStack.splice(i + 1, 1, xformed[1], xformed[2]);
15107                    i++;
15108                } else if (!xformed[1]) {
15109                    redoStack.splice(i, 1);
15110                    i--;
15111                }
15112            }
15113        }
15114    }
15115    return redoStack;
15116}
15117function rebaseRedoStack(redoStack, deltaSets) {
15118    for (var i = 0; i < deltaSets.length; i++) {
15119        var deltas = deltaSets[i];
15120        for (var j = 0; j < deltas.length; j++) {
15121            moveDeltasByOne(redoStack, deltas[j]);
15122        }
15123    }
15124}
15125
15126exports.UndoManager = UndoManager;
15127
15128});
15129
15130define("ace/layer/gutter",["require","exports","module","ace/lib/dom","ace/lib/oop","ace/lib/lang","ace/lib/event_emitter"], function(require, exports, module) {
15131"use strict";
15132
15133var dom = require("../lib/dom");
15134var oop = require("../lib/oop");
15135var lang = require("../lib/lang");
15136var EventEmitter = require("../lib/event_emitter").EventEmitter;
15137
15138var Gutter = function(parentEl) {
15139    this.element = dom.createElement("div");
15140    this.element.className = "ace_layer ace_gutter-layer";
15141    parentEl.appendChild(this.element);
15142    this.setShowFoldWidgets(this.$showFoldWidgets);
15143    
15144    this.gutterWidth = 0;
15145
15146    this.$annotations = [];
15147    this.$updateAnnotations = this.$updateAnnotations.bind(this);
15148
15149    this.$cells = [];
15150};
15151
15152(function() {
15153
15154    oop.implement(this, EventEmitter);
15155
15156    this.setSession = function(session) {
15157        if (this.session)
15158            this.session.removeEventListener("change", this.$updateAnnotations);
15159        this.session = session;
15160        if (session)
15161            session.on("change", this.$updateAnnotations);
15162    };
15163
15164    this.addGutterDecoration = function(row, className){
15165        if (window.console)
15166            console.warn && console.warn("deprecated use session.addGutterDecoration");
15167        this.session.addGutterDecoration(row, className);
15168    };
15169
15170    this.removeGutterDecoration = function(row, className){
15171        if (window.console)
15172            console.warn && console.warn("deprecated use session.removeGutterDecoration");
15173        this.session.removeGutterDecoration(row, className);
15174    };
15175
15176    this.setAnnotations = function(annotations) {
15177        this.$annotations = [];
15178        for (var i = 0; i < annotations.length; i++) {
15179            var annotation = annotations[i];
15180            var row = annotation.row;
15181            var rowInfo = this.$annotations[row];
15182            if (!rowInfo)
15183                rowInfo = this.$annotations[row] = {text: []};
15184           
15185            var annoText = annotation.text;
15186            annoText = annoText ? lang.escapeHTML(annoText) : annotation.html || "";
15187
15188            if (rowInfo.text.indexOf(annoText) === -1)
15189                rowInfo.text.push(annoText);
15190
15191            var type = annotation.type;
15192            if (type == "error")
15193                rowInfo.className = " ace_error";
15194            else if (type == "warning" && rowInfo.className != " ace_error")
15195                rowInfo.className = " ace_warning";
15196            else if (type == "info" && (!rowInfo.className))
15197                rowInfo.className = " ace_info";
15198        }
15199    };
15200
15201    this.$updateAnnotations = function (delta) {
15202        if (!this.$annotations.length)
15203            return;
15204        var firstRow = delta.start.row;
15205        var len = delta.end.row - firstRow;
15206        if (len === 0) {
15207        } else if (delta.action == 'remove') {
15208            this.$annotations.splice(firstRow, len + 1, null);
15209        } else {
15210            var args = new Array(len + 1);
15211            args.unshift(firstRow, 1);
15212            this.$annotations.splice.apply(this.$annotations, args);
15213        }
15214    };
15215
15216    this.update = function(config) {
15217        var session = this.session;
15218        var firstRow = config.firstRow;
15219        var lastRow = Math.min(config.lastRow + config.gutterOffset,  // needed to compensate for hor scollbar
15220            session.getLength() - 1);
15221        var fold = session.getNextFoldLine(firstRow);
15222        var foldStart = fold ? fold.start.row : Infinity;
15223        var foldWidgets = this.$showFoldWidgets && session.foldWidgets;
15224        var breakpoints = session.$breakpoints;
15225        var decorations = session.$decorations;
15226        var firstLineNumber = session.$firstLineNumber;
15227        var lastLineNumber = 0;
15228        
15229        var gutterRenderer = session.gutterRenderer || this.$renderer;
15230
15231        var cell = null;
15232        var index = -1;
15233        var row = firstRow;
15234        while (true) {
15235            if (row > foldStart) {
15236                row = fold.end.row + 1;
15237                fold = session.getNextFoldLine(row, fold);
15238                foldStart = fold ? fold.start.row : Infinity;
15239            }
15240            if (row > lastRow) {
15241                while (this.$cells.length > index + 1) {
15242                    cell = this.$cells.pop();
15243                    this.element.removeChild(cell.element);
15244                }
15245                break;
15246            }
15247
15248            cell = this.$cells[++index];
15249            if (!cell) {
15250                cell = {element: null, textNode: null, foldWidget: null};
15251                cell.element = dom.createElement("div");
15252                cell.textNode = document.createTextNode('');
15253                cell.element.appendChild(cell.textNode);
15254                this.element.appendChild(cell.element);
15255                this.$cells[index] = cell;
15256            }
15257
15258            var className = "ace_gutter-cell ";
15259            if (breakpoints[row])
15260                className += breakpoints[row];
15261            if (decorations[row])
15262                className += decorations[row];
15263            if (this.$annotations[row])
15264                className += this.$annotations[row].className;
15265            if (cell.element.className != className)
15266                cell.element.className = className;
15267
15268            var height = session.getRowLength(row) * config.lineHeight + "px";
15269            if (height != cell.element.style.height)
15270                cell.element.style.height = height;
15271
15272            if (foldWidgets) {
15273                var c = foldWidgets[row];
15274                if (c == null)
15275                    c = foldWidgets[row] = session.getFoldWidget(row);
15276            }
15277
15278            if (c) {
15279                if (!cell.foldWidget) {
15280                    cell.foldWidget = dom.createElement("span");
15281                    cell.element.appendChild(cell.foldWidget);
15282                }
15283                var className = "ace_fold-widget ace_" + c;
15284                if (c == "start" && row == foldStart && row < fold.end.row)
15285                    className += " ace_closed";
15286                else
15287                    className += " ace_open";
15288                if (cell.foldWidget.className != className)
15289                    cell.foldWidget.className = className;
15290
15291                var height = config.lineHeight + "px";
15292                if (cell.foldWidget.style.height != height)
15293                    cell.foldWidget.style.height = height;
15294            } else {
15295                if (cell.foldWidget) {
15296                    cell.element.removeChild(cell.foldWidget);
15297                    cell.foldWidget = null;
15298                }
15299            }
15300            
15301            var text = lastLineNumber = gutterRenderer
15302                ? gutterRenderer.getText(session, row)
15303                : row + firstLineNumber;
15304            if (text !== cell.textNode.data)
15305                cell.textNode.data = text;
15306
15307            row++;
15308        }
15309
15310        this.element.style.height = config.minHeight + "px";
15311
15312        if (this.$fixedWidth || session.$useWrapMode)
15313            lastLineNumber = session.getLength() + firstLineNumber;
15314
15315        var gutterWidth = gutterRenderer 
15316            ? gutterRenderer.getWidth(session, lastLineNumber, config)
15317            : lastLineNumber.toString().length * config.characterWidth;
15318        
15319        var padding = this.$padding || this.$computePadding();
15320        gutterWidth += padding.left + padding.right;
15321        if (gutterWidth !== this.gutterWidth && !isNaN(gutterWidth)) {
15322            this.gutterWidth = gutterWidth;
15323            this.element.style.width = Math.ceil(this.gutterWidth) + "px";
15324            this._emit("changeGutterWidth", gutterWidth);
15325        }
15326    };
15327
15328    this.$fixedWidth = false;
15329    
15330    this.$showLineNumbers = true;
15331    this.$renderer = "";
15332    this.setShowLineNumbers = function(show) {
15333        this.$renderer = !show && {
15334            getWidth: function() {return "";},
15335            getText: function() {return "";}
15336        };
15337    };
15338    
15339    this.getShowLineNumbers = function() {
15340        return this.$showLineNumbers;
15341    };
15342    
15343    this.$showFoldWidgets = true;
15344    this.setShowFoldWidgets = function(show) {
15345        if (show)
15346            dom.addCssClass(this.element, "ace_folding-enabled");
15347        else
15348            dom.removeCssClass(this.element, "ace_folding-enabled");
15349
15350        this.$showFoldWidgets = show;
15351        this.$padding = null;
15352    };
15353    
15354    this.getShowFoldWidgets = function() {
15355        return this.$showFoldWidgets;
15356    };
15357
15358    this.$computePadding = function() {
15359        if (!this.element.firstChild)
15360            return {left: 0, right: 0};
15361        var style = dom.computedStyle(this.element.firstChild);
15362        this.$padding = {};
15363        this.$padding.left = parseInt(style.paddingLeft) + 1 || 0;
15364        this.$padding.right = parseInt(style.paddingRight) || 0;
15365        return this.$padding;
15366    };
15367
15368    this.getRegion = function(point) {
15369        var padding = this.$padding || this.$computePadding();
15370        var rect = this.element.getBoundingClientRect();
15371        if (point.x < padding.left + rect.left)
15372            return "markers";
15373        if (this.$showFoldWidgets && point.x > rect.right - padding.right)
15374            return "foldWidgets";
15375    };
15376
15377}).call(Gutter.prototype);
15378
15379exports.Gutter = Gutter;
15380
15381});
15382
15383define("ace/layer/marker",["require","exports","module","ace/range","ace/lib/dom"], function(require, exports, module) {
15384"use strict";
15385
15386var Range = require("../range").Range;
15387var dom = require("../lib/dom");
15388
15389var Marker = function(parentEl) {
15390    this.element = dom.createElement("div");
15391    this.element.className = "ace_layer ace_marker-layer";
15392    parentEl.appendChild(this.element);
15393};
15394
15395(function() {
15396
15397    this.$padding = 0;
15398
15399    this.setPadding = function(padding) {
15400        this.$padding = padding;
15401    };
15402    this.setSession = function(session) {
15403        this.session = session;
15404    };
15405    
15406    this.setMarkers = function(markers) {
15407        this.markers = markers;
15408    };
15409
15410    this.update = function(config) {
15411        if (!config) return;
15412
15413        this.config = config;
15414
15415
15416        var html = [];
15417        for (var key in this.markers) {
15418            var marker = this.markers[key];
15419
15420            if (!marker.range) {
15421                marker.update(html, this, this.session, config);
15422                continue;
15423            }
15424
15425            var range = marker.range.clipRows(config.firstRow, config.lastRow);
15426            if (range.isEmpty()) continue;
15427
15428            range = range.toScreenRange(this.session);
15429            if (marker.renderer) {
15430                var top = this.$getTop(range.start.row, config);
15431                var left = this.$padding + (this.session.$bidiHandler.isBidiRow(range.start.row)
15432                    ? this.session.$bidiHandler.getPosLeft(range.start.column)
15433                    : range.start.column * config.characterWidth);
15434                marker.renderer(html, range, left, top, config);
15435            } else if (marker.type == "fullLine") {
15436                this.drawFullLineMarker(html, range, marker.clazz, config);
15437            } else if (marker.type == "screenLine") {
15438                this.drawScreenLineMarker(html, range, marker.clazz, config);
15439            } else if (range.isMultiLine()) {
15440                if (marker.type == "text")
15441                    this.drawTextMarker(html, range, marker.clazz, config);
15442                else
15443                    this.drawMultiLineMarker(html, range, marker.clazz, config);
15444            } else {
15445                if (this.session.$bidiHandler.isBidiRow(range.start.row)) {
15446                    this.drawBidiSingleLineMarker(html, range, marker.clazz + " ace_start" + " ace_br15", config);
15447                } else {
15448                    this.drawSingleLineMarker(html, range, marker.clazz + " ace_start" + " ace_br15", config);
15449                }
15450            }
15451        }
15452        this.element.innerHTML = html.join("");
15453    };
15454
15455    this.$getTop = function(row, layerConfig) {
15456        return (row - layerConfig.firstRowScreen) * layerConfig.lineHeight;
15457    };
15458
15459    function getBorderClass(tl, tr, br, bl) {
15460        return (tl ? 1 : 0) | (tr ? 2 : 0) | (br ? 4 : 0) | (bl ? 8 : 0);
15461    }
15462    this.drawTextMarker = function(stringBuilder, range, clazz, layerConfig, extraStyle) {
15463        var session = this.session;
15464        var start = range.start.row;
15465        var end = range.end.row;
15466        var row = start;
15467        var prev = 0; 
15468        var curr = 0;
15469        var next = session.getScreenLastRowColumn(row);
15470        var clazzModified = null;
15471        var lineRange = new Range(row, range.start.column, row, curr);
15472        for (; row <= end; row++) {
15473            lineRange.start.row = lineRange.end.row = row;
15474            lineRange.start.column = row == start ? range.start.column : session.getRowWrapIndent(row);
15475            lineRange.end.column = next;
15476            prev = curr;
15477            curr = next;
15478            next = row + 1 < end ? session.getScreenLastRowColumn(row + 1) : row == end ? 0 : range.end.column;
15479            clazzModified = clazz + (row == start  ? " ace_start" : "") + " ace_br"
15480                + getBorderClass(row == start || row == start + 1 && range.start.column, prev < curr, curr > next, row == end);
15481            
15482            if (this.session.$bidiHandler.isBidiRow(row)) {
15483                this.drawBidiSingleLineMarker(stringBuilder, lineRange, clazzModified, 
15484                    layerConfig, row == end ? 0 : 1, extraStyle);
15485            } else {
15486                this.drawSingleLineMarker(stringBuilder, lineRange, clazzModified,  
15487                    layerConfig, row == end ? 0 : 1, extraStyle);
15488            }
15489        }
15490    };
15491    this.drawMultiLineMarker = function(stringBuilder, range, clazz, config, extraStyle) {
15492        var padding = this.$padding;
15493        var height, top, left;
15494        extraStyle = extraStyle || "";
15495       if (this.session.$bidiHandler.isBidiRow(range.start.row)) {
15496           var range1 = range.clone();
15497           range1.end.row = range1.start.row;
15498           range1.end.column = this.session.getLine(range1.start.row).length;
15499           this.drawBidiSingleLineMarker(stringBuilder, range1, clazz + " ace_br1 ace_start", config, null, extraStyle);
15500        } else {
15501           height = config.lineHeight;
15502           top = this.$getTop(range.start.row, config);
15503           left = padding + range.start.column * config.characterWidth;
15504           stringBuilder.push(
15505               "<div class='", clazz, " ace_br1 ace_start' style='",
15506               "height:", height, "px;",
15507               "right:0;",
15508               "top:", top, "px;",
15509               "left:", left, "px;", extraStyle, "'></div>"
15510           );
15511        }
15512        if (this.session.$bidiHandler.isBidiRow(range.end.row)) {
15513           var range1 = range.clone();
15514           range1.start.row = range1.end.row;
15515           range1.start.column = 0;
15516           this.drawBidiSingleLineMarker(stringBuilder, range1, clazz + " ace_br12", config, null, extraStyle);
15517        } else {
15518           var width = range.end.column * config.characterWidth;
15519           height = config.lineHeight;
15520           top = this.$getTop(range.end.row, config);
15521           stringBuilder.push(
15522               "<div class='", clazz, " ace_br12' style='",
15523               "height:", height, "px;",
15524               "width:", width, "px;",
15525               "top:", top, "px;",
15526               "left:", padding, "px;", extraStyle, "'></div>"
15527           );
15528        }
15529        height = (range.end.row - range.start.row - 1) * config.lineHeight;
15530        if (height <= 0)
15531            return;
15532        top = this.$getTop(range.start.row + 1, config);
15533        
15534        var radiusClass = (range.start.column ? 1 : 0) | (range.end.column ? 0 : 8);
15535
15536        stringBuilder.push(
15537            "<div class='", clazz, (radiusClass ? " ace_br" + radiusClass : ""), "' style='",
15538            "height:", height, "px;",
15539            "right:0;",
15540            "top:", top, "px;",
15541            "left:", padding, "px;", extraStyle, "'></div>"
15542        );
15543    };
15544    this.drawSingleLineMarker = function(stringBuilder, range, clazz, config, extraLength, extraStyle) {
15545        var height = config.lineHeight;
15546        var width = (range.end.column + (extraLength || 0) - range.start.column) * config.characterWidth;
15547
15548        var top = this.$getTop(range.start.row, config);
15549        var left = this.$padding + range.start.column * config.characterWidth;
15550
15551        stringBuilder.push(
15552            "<div class='", clazz, "' style='",
15553            "height:", height, "px;",
15554            "width:", width, "px;",
15555            "top:", top, "px;",
15556            "left:", left, "px;", extraStyle || "", "'></div>"
15557        );
15558    };
15559    this.drawBidiSingleLineMarker = function(stringBuilder, range, clazz, config, extraLength, extraStyle) {
15560        var height = config.lineHeight, top = this.$getTop(range.start.row, config), padding = this.$padding;
15561        var selections = this.session.$bidiHandler.getSelections(range.start.column, range.end.column);
15562
15563        selections.forEach(function(selection) {
15564            stringBuilder.push(
15565                "<div class='", clazz, "' style='",
15566                "height:", height, "px;",
15567                "width:", selection.width + (extraLength || 0), "px;",
15568                "top:", top, "px;",
15569                "left:", padding + selection.left, "px;", extraStyle || "", "'></div>"
15570            );
15571        });
15572    };
15573
15574    this.drawFullLineMarker = function(stringBuilder, range, clazz, config, extraStyle) {
15575        var top = this.$getTop(range.start.row, config);
15576        var height = config.lineHeight;
15577        if (range.start.row != range.end.row)
15578            height += this.$getTop(range.end.row, config) - top;
15579
15580        stringBuilder.push(
15581            "<div class='", clazz, "' style='",
15582            "height:", height, "px;",
15583            "top:", top, "px;",
15584            "left:0;right:0;", extraStyle || "", "'></div>"
15585        );
15586    };
15587    
15588    this.drawScreenLineMarker = function(stringBuilder, range, clazz, config, extraStyle) {
15589        var top = this.$getTop(range.start.row, config);
15590        var height = config.lineHeight;
15591
15592        stringBuilder.push(
15593            "<div class='", clazz, "' style='",
15594            "height:", height, "px;",
15595            "top:", top, "px;",
15596            "left:0;right:0;", extraStyle || "", "'></div>"
15597        );
15598    };
15599
15600}).call(Marker.prototype);
15601
15602exports.Marker = Marker;
15603
15604});
15605
15606define("ace/layer/text",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/lang","ace/lib/useragent","ace/lib/event_emitter"], function(require, exports, module) {
15607"use strict";
15608
15609var oop = require("../lib/oop");
15610var dom = require("../lib/dom");
15611var lang = require("../lib/lang");
15612var useragent = require("../lib/useragent");
15613var EventEmitter = require("../lib/event_emitter").EventEmitter;
15614
15615var Text = function(parentEl) {
15616    this.element = dom.createElement("div");
15617    this.element.className = "ace_layer ace_text-layer";
15618    parentEl.appendChild(this.element);
15619    this.$updateEolChar = this.$updateEolChar.bind(this);
15620};
15621
15622(function() {
15623
15624    oop.implement(this, EventEmitter);
15625
15626    this.EOF_CHAR = "\xB6";
15627    this.EOL_CHAR_LF = "\xAC";
15628    this.EOL_CHAR_CRLF = "\xa4";
15629    this.EOL_CHAR = this.EOL_CHAR_LF;
15630    this.TAB_CHAR = "\u2014"; //"\u21E5";
15631    this.SPACE_CHAR = "\xB7";
15632    this.$padding = 0;
15633    this.MAX_LINE_LENGTH = 10000;
15634
15635    this.$updateEolChar = function() {
15636        var EOL_CHAR = this.session.doc.getNewLineCharacter() == "\n"
15637           ? this.EOL_CHAR_LF
15638           : this.EOL_CHAR_CRLF;
15639        if (this.EOL_CHAR != EOL_CHAR) {
15640            this.EOL_CHAR = EOL_CHAR;
15641            return true;
15642        }
15643    };
15644
15645    this.setPadding = function(padding) {
15646        this.$padding = padding;
15647        this.element.style.padding = "0 " + padding + "px";
15648    };
15649
15650    this.getLineHeight = function() {
15651        return this.$fontMetrics.$characterSize.height || 0;
15652    };
15653
15654    this.getCharacterWidth = function() {
15655        return this.$fontMetrics.$characterSize.width || 0;
15656    };
15657    
15658    this.$setFontMetrics = function(measure) {
15659        this.$fontMetrics = measure;
15660        this.$fontMetrics.on("changeCharacterSize", function(e) {
15661            this._signal("changeCharacterSize", e);
15662        }.bind(this));
15663        this.$pollSizeChanges();
15664    };
15665
15666    this.checkForSizeChanges = function() {
15667        this.$fontMetrics.checkForSizeChanges();
15668    };
15669    this.$pollSizeChanges = function() {
15670        return this.$pollSizeChangesTimer = this.$fontMetrics.$pollSizeChanges();
15671    };
15672    this.setSession = function(session) {
15673        this.session = session;
15674        if (session)
15675            this.$computeTabString();
15676    };
15677
15678    this.showInvisibles = false;
15679    this.setShowInvisibles = function(showInvisibles) {
15680        if (this.showInvisibles == showInvisibles)
15681            return false;
15682
15683        this.showInvisibles = showInvisibles;
15684        this.$computeTabString();
15685        return true;
15686    };
15687
15688    this.displayIndentGuides = true;
15689    this.setDisplayIndentGuides = function(display) {
15690        if (this.displayIndentGuides == display)
15691            return false;
15692
15693        this.displayIndentGuides = display;
15694        this.$computeTabString();
15695        return true;
15696    };
15697
15698    this.$tabStrings = [];
15699    this.onChangeTabSize =
15700    this.$computeTabString = function() {
15701        var tabSize = this.session.getTabSize();
15702        this.tabSize = tabSize;
15703        var tabStr = this.$tabStrings = [0];
15704        for (var i = 1; i < tabSize + 1; i++) {
15705            if (this.showInvisibles) {
15706                tabStr.push("<span class='ace_invisible ace_invisible_tab'>"
15707                    + lang.stringRepeat(this.TAB_CHAR, i)
15708                    + "</span>");
15709            } else {
15710                tabStr.push(lang.stringRepeat(" ", i));
15711            }
15712        }
15713        if (this.displayIndentGuides) {
15714            this.$indentGuideRe =  /\s\S| \t|\t |\s$/;
15715            var className = "ace_indent-guide";
15716            var spaceClass = "";
15717            var tabClass = "";
15718            if (this.showInvisibles) {
15719                className += " ace_invisible";
15720                spaceClass = " ace_invisible_space";
15721                tabClass = " ace_invisible_tab";
15722                var spaceContent = lang.stringRepeat(this.SPACE_CHAR, this.tabSize);
15723                var tabContent = lang.stringRepeat(this.TAB_CHAR, this.tabSize);
15724            } else{
15725                var spaceContent = lang.stringRepeat(" ", this.tabSize);
15726                var tabContent = spaceContent;
15727            }
15728
15729            this.$tabStrings[" "] = "<span class='" + className + spaceClass + "'>" + spaceContent + "</span>";
15730            this.$tabStrings["\t"] = "<span class='" + className + tabClass + "'>" + tabContent + "</span>";
15731        }
15732    };
15733
15734    this.updateLines = function(config, firstRow, lastRow) {
15735        if (this.config.lastRow != config.lastRow ||
15736            this.config.firstRow != config.firstRow) {
15737            this.scrollLines(config);
15738        }
15739        this.config = config;
15740
15741        var first = Math.max(firstRow, config.firstRow);
15742        var last = Math.min(lastRow, config.lastRow);
15743
15744        var lineElements = this.element.childNodes;
15745        var lineElementsIdx = 0;
15746
15747        for (var row = config.firstRow; row < first; row++) {
15748            var foldLine = this.session.getFoldLine(row);
15749            if (foldLine) {
15750                if (foldLine.containsRow(first)) {
15751                    first = foldLine.start.row;
15752                    break;
15753                } else {
15754                    row = foldLine.end.row;
15755                }
15756            }
15757            lineElementsIdx ++;
15758        }
15759
15760        var row = first;
15761        var foldLine = this.session.getNextFoldLine(row);
15762        var foldStart = foldLine ? foldLine.start.row : Infinity;
15763
15764        while (true) {
15765            if (row > foldStart) {
15766                row = foldLine.end.row+1;
15767                foldLine = this.session.getNextFoldLine(row, foldLine);
15768                foldStart = foldLine ? foldLine.start.row :Infinity;
15769            }
15770            if (row > last)
15771                break;
15772
15773            var lineElement = lineElements[lineElementsIdx++];
15774            if (lineElement) {
15775                var html = [];
15776                this.$renderLine(
15777                    html, row, !this.$useLineGroups(), row == foldStart ? foldLine : false
15778                );
15779                lineElement.style.height = config.lineHeight * this.session.getRowLength(row) + "px";
15780                lineElement.innerHTML = html.join("");
15781            }
15782            row++;
15783        }
15784    };
15785
15786    this.scrollLines = function(config) {
15787        var oldConfig = this.config;
15788        this.config = config;
15789
15790        if (!oldConfig || oldConfig.lastRow < config.firstRow)
15791            return this.update(config);
15792
15793        if (config.lastRow < oldConfig.firstRow)
15794            return this.update(config);
15795
15796        var el = this.element;
15797        if (oldConfig.firstRow < config.firstRow)
15798            for (var row=this.session.getFoldedRowCount(oldConfig.firstRow, config.firstRow - 1); row>0; row--)
15799                el.removeChild(el.firstChild);
15800
15801        if (oldConfig.lastRow > config.lastRow)
15802            for (var row=this.session.getFoldedRowCount(config.lastRow + 1, oldConfig.lastRow); row>0; row--)
15803                el.removeChild(el.lastChild);
15804
15805        if (config.firstRow < oldConfig.firstRow) {
15806            var fragment = this.$renderLinesFragment(config, config.firstRow, oldConfig.firstRow - 1);
15807            if (el.firstChild)
15808                el.insertBefore(fragment, el.firstChild);
15809            else
15810                el.appendChild(fragment);
15811        }
15812
15813        if (config.lastRow > oldConfig.lastRow) {
15814            var fragment = this.$renderLinesFragment(config, oldConfig.lastRow + 1, config.lastRow);
15815            el.appendChild(fragment);
15816        }
15817    };
15818
15819    this.$renderLinesFragment = function(config, firstRow, lastRow) {
15820        var fragment = this.element.ownerDocument.createDocumentFragment();
15821        var row = firstRow;
15822        var foldLine = this.session.getNextFoldLine(row);
15823        var foldStart = foldLine ? foldLine.start.row : Infinity;
15824
15825        while (true) {
15826            if (row > foldStart) {
15827                row = foldLine.end.row+1;
15828                foldLine = this.session.getNextFoldLine(row, foldLine);
15829                foldStart = foldLine ? foldLine.start.row : Infinity;
15830            }
15831            if (row > lastRow)
15832                break;
15833
15834            var container = dom.createElement("div");
15835
15836            var html = [];
15837            this.$renderLine(html, row, false, row == foldStart ? foldLine : false);
15838            container.innerHTML = html.join("");
15839            if (this.$useLineGroups()) {
15840                container.className = 'ace_line_group';
15841                fragment.appendChild(container);
15842                container.style.height = config.lineHeight * this.session.getRowLength(row) + "px";
15843
15844            } else {
15845                while(container.firstChild)
15846                    fragment.appendChild(container.firstChild);
15847            }
15848
15849            row++;
15850        }
15851        return fragment;
15852    };
15853
15854    this.update = function(config) {
15855        this.config = config;
15856
15857        var html = [];
15858        var firstRow = config.firstRow, lastRow = config.lastRow;
15859
15860        var row = firstRow;
15861        var foldLine = this.session.getNextFoldLine(row);
15862        var foldStart = foldLine ? foldLine.start.row : Infinity;
15863
15864        while (true) {
15865            if (row > foldStart) {
15866                row = foldLine.end.row+1;
15867                foldLine = this.session.getNextFoldLine(row, foldLine);
15868                foldStart = foldLine ? foldLine.start.row :Infinity;
15869            }
15870            if (row > lastRow)
15871                break;
15872
15873            if (this.$useLineGroups())
15874                html.push("<div class='ace_line_group' style='height:", config.lineHeight*this.session.getRowLength(row), "px'>");
15875
15876            this.$renderLine(html, row, false, row == foldStart ? foldLine : false);
15877
15878            if (this.$useLineGroups())
15879                html.push("</div>"); // end the line group
15880
15881            row++;
15882        }
15883        this.element.innerHTML = html.join("");
15884    };
15885
15886    this.$textToken = {
15887        "text": true,
15888        "rparen": true,
15889        "lparen": true
15890    };
15891
15892    this.$renderToken = function(stringBuilder, screenColumn, token, value) {
15893        var self = this;
15894        var replaceReg = /\t|&|<|>|( +)|([\x00-\x1f\x80-\xa0\xad\u1680\u180E\u2000-\u200f\u2028\u2029\u202F\u205F\u3000\uFEFF\uFFF9-\uFFFC])|[\u1100-\u115F\u11A3-\u11A7\u11FA-\u11FF\u2329-\u232A\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFB\u3000-\u303E\u3041-\u3096\u3099-\u30FF\u3105-\u312D\u3131-\u318E\u3190-\u31BA\u31C0-\u31E3\u31F0-\u321E\u3220-\u3247\u3250-\u32FE\u3300-\u4DBF\u4E00-\uA48C\uA490-\uA4C6\uA960-\uA97C\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFAFF\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE66\uFE68-\uFE6B\uFF01-\uFF60\uFFE0-\uFFE6]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
15895        var replaceFunc = function(c, a, b, tabIdx, idx4) {
15896            if (a) {
15897                return self.showInvisibles
15898                    ? "<span class='ace_invisible ace_invisible_space'>" + lang.stringRepeat(self.SPACE_CHAR, c.length) + "</span>"
15899                    : c;
15900            } else if (c == "&") {
15901                return "&#38;";
15902            } else if (c == "<") {
15903                return "&#60;";
15904            } else if (c == ">") {
15905                return "&#62;";
15906            } else if (c == "\t") {
15907                var tabSize = self.session.getScreenTabSize(screenColumn + tabIdx);
15908                screenColumn += tabSize - 1;
15909                return self.$tabStrings[tabSize];
15910            } else if (c == "\u3000") {
15911                var classToUse = self.showInvisibles ? "ace_cjk ace_invisible ace_invisible_space" : "ace_cjk";
15912                var space = self.showInvisibles ? self.SPACE_CHAR : "";
15913                screenColumn += 1;
15914                return "<span class='" + classToUse + "' style='width:" +
15915                    (self.config.characterWidth * 2) +
15916                    "px'>" + space + "</span>";
15917            } else if (b) {
15918                return "<span class='ace_invisible ace_invisible_space ace_invalid'>" + self.SPACE_CHAR + "</span>";
15919            } else {
15920                screenColumn += 1;
15921                return "<span class='ace_cjk' style='width:" +
15922                    (self.config.characterWidth * 2) +
15923                    "px'>" + c + "</span>";
15924            }
15925        };
15926
15927        var output = value.replace(replaceReg, replaceFunc);
15928
15929        if (!this.$textToken[token.type]) {
15930            var classes = "ace_" + token.type.replace(/\./g, " ace_");
15931            var style = "";
15932            if (token.type == "fold")
15933                style = " style='width:" + (token.value.length * this.config.characterWidth) + "px;' ";
15934            stringBuilder.push("<span class='", classes, "'", style, ">", output, "</span>");
15935        }
15936        else {
15937            stringBuilder.push(output);
15938        }
15939        return screenColumn + value.length;
15940    };
15941
15942    this.renderIndentGuide = function(stringBuilder, value, max) {
15943        var cols = value.search(this.$indentGuideRe);
15944        if (cols <= 0 || cols >= max)
15945            return value;
15946        if (value[0] == " ") {
15947            cols -= cols % this.tabSize;
15948            stringBuilder.push(lang.stringRepeat(this.$tabStrings[" "], cols/this.tabSize));
15949            return value.substr(cols);
15950        } else if (value[0] == "\t") {
15951            stringBuilder.push(lang.stringRepeat(this.$tabStrings["\t"], cols));
15952            return value.substr(cols);
15953        }
15954        return value;
15955    };
15956
15957    this.$renderWrappedLine = function(stringBuilder, tokens, splits, onlyContents) {
15958        var chars = 0;
15959        var split = 0;
15960        var splitChars = splits[0];
15961        var screenColumn = 0;
15962
15963        for (var i = 0; i < tokens.length; i++) {
15964            var token = tokens[i];
15965            var value = token.value;
15966            if (i == 0 && this.displayIndentGuides) {
15967                chars = value.length;
15968                value = this.renderIndentGuide(stringBuilder, value, splitChars);
15969                if (!value)
15970                    continue;
15971                chars -= value.length;
15972            }
15973
15974            if (chars + value.length < splitChars) {
15975                screenColumn = this.$renderToken(stringBuilder, screenColumn, token, value);
15976                chars += value.length;
15977            } else {
15978                while (chars + value.length >= splitChars) {
15979                    screenColumn = this.$renderToken(
15980                        stringBuilder, screenColumn,
15981                        token, value.substring(0, splitChars - chars)
15982                    );
15983                    value = value.substring(splitChars - chars);
15984                    chars = splitChars;
15985
15986                    if (!onlyContents) {
15987                        stringBuilder.push("</div>",
15988                            "<div class='ace_line' style='height:",
15989                            this.config.lineHeight, "px'>"
15990                        );
15991                    }
15992
15993                    stringBuilder.push(lang.stringRepeat("\xa0", splits.indent));
15994
15995                    split ++;
15996                    screenColumn = 0;
15997                    splitChars = splits[split] || Number.MAX_VALUE;
15998                }
15999                if (value.length != 0) {
16000                    chars += value.length;
16001                    screenColumn = this.$renderToken(
16002                        stringBuilder, screenColumn, token, value
16003                    );
16004                }
16005            }
16006        }
16007    };
16008
16009    this.$renderSimpleLine = function(stringBuilder, tokens) {
16010        var screenColumn = 0;
16011        var token = tokens[0];
16012        var value = token.value;
16013        if (this.displayIndentGuides)
16014            value = this.renderIndentGuide(stringBuilder, value);
16015        if (value)
16016            screenColumn = this.$renderToken(stringBuilder, screenColumn, token, value);
16017        for (var i = 1; i < tokens.length; i++) {
16018            token = tokens[i];
16019            value = token.value;
16020            if (screenColumn + value.length > this.MAX_LINE_LENGTH)
16021                return this.$renderOverflowMessage(stringBuilder, screenColumn, token, value);
16022            screenColumn = this.$renderToken(stringBuilder, screenColumn, token, value);
16023        }
16024    };
16025    
16026    this.$renderOverflowMessage = function(stringBuilder, screenColumn, token, value) {
16027        this.$renderToken(stringBuilder, screenColumn, token,
16028            value.slice(0, this.MAX_LINE_LENGTH - screenColumn));
16029        stringBuilder.push(
16030            "<span style='position:absolute;right:0' class='ace_inline_button ace_keyword ace_toggle_wrap'>&lt;click to see more...&gt;</span>"
16031        );
16032    };
16033    this.$renderLine = function(stringBuilder, row, onlyContents, foldLine) {
16034        if (!foldLine && foldLine != false)
16035            foldLine = this.session.getFoldLine(row);
16036
16037        if (foldLine)
16038            var tokens = this.$getFoldLineTokens(row, foldLine);
16039        else
16040            var tokens = this.session.getTokens(row);
16041
16042
16043        if (!onlyContents) {
16044            stringBuilder.push(
16045                "<div class='ace_line' style='height:", 
16046                    this.config.lineHeight * (
16047                        this.$useLineGroups() ? 1 :this.session.getRowLength(row)
16048                    ), "px'>"
16049            );
16050        }
16051
16052        if (tokens.length) {
16053            var splits = this.session.getRowSplitData(row);
16054            if (splits && splits.length)
16055                this.$renderWrappedLine(stringBuilder, tokens, splits, onlyContents);
16056            else
16057                this.$renderSimpleLine(stringBuilder, tokens);
16058        }
16059
16060        if (this.showInvisibles) {
16061            if (foldLine)
16062                row = foldLine.end.row;
16063
16064            stringBuilder.push(
16065                "<span class='ace_invisible ace_invisible_eol'>",
16066                row == this.session.getLength() - 1 ? this.EOF_CHAR : this.EOL_CHAR,
16067                "</span>"
16068            );
16069        }
16070        if (!onlyContents)
16071            stringBuilder.push("</div>");
16072    };
16073
16074    this.$getFoldLineTokens = function(row, foldLine) {
16075        var session = this.session;
16076        var renderTokens = [];
16077
16078        function addTokens(tokens, from, to) {
16079            var idx = 0, col = 0;
16080            while ((col + tokens[idx].value.length) < from) {
16081                col += tokens[idx].value.length;
16082                idx++;
16083
16084                if (idx == tokens.length)
16085                    return;
16086            }
16087            if (col != from) {
16088                var value = tokens[idx].value.substring(from - col);
16089                if (value.length > (to - from))
16090                    value = value.substring(0, to - from);
16091
16092                renderTokens.push({
16093                    type: tokens[idx].type,
16094                    value: value
16095                });
16096
16097                col = from + value.length;
16098                idx += 1;
16099            }
16100
16101            while (col < to && idx < tokens.length) {
16102                var value = tokens[idx].value;
16103                if (value.length + col > to) {
16104                    renderTokens.push({
16105                        type: tokens[idx].type,
16106                        value: value.substring(0, to - col)
16107                    });
16108                } else
16109                    renderTokens.push(tokens[idx]);
16110                col += value.length;
16111                idx += 1;
16112            }
16113        }
16114
16115        var tokens = session.getTokens(row);
16116        foldLine.walk(function(placeholder, row, column, lastColumn, isNewRow) {
16117            if (placeholder != null) {
16118                renderTokens.push({
16119                    type: "fold",
16120                    value: placeholder
16121                });
16122            } else {
16123                if (isNewRow)
16124                    tokens = session.getTokens(row);
16125
16126                if (tokens.length)
16127                    addTokens(tokens, lastColumn, column);
16128            }
16129        }, foldLine.end.row, this.session.getLine(foldLine.end.row).length);
16130
16131        return renderTokens;
16132    };
16133
16134    this.$useLineGroups = function() {
16135        return this.session.getUseWrapMode();
16136    };
16137
16138    this.destroy = function() {
16139        clearInterval(this.$pollSizeChangesTimer);
16140        if (this.$measureNode)
16141            this.$measureNode.parentNode.removeChild(this.$measureNode);
16142        delete this.$measureNode;
16143    };
16144
16145}).call(Text.prototype);
16146
16147exports.Text = Text;
16148
16149});
16150
16151define("ace/layer/cursor",["require","exports","module","ace/lib/dom"], function(require, exports, module) {
16152"use strict";
16153
16154var dom = require("../lib/dom");
16155var isIE8;
16156
16157var Cursor = function(parentEl) {
16158    this.element = dom.createElement("div");
16159    this.element.className = "ace_layer ace_cursor-layer";
16160    parentEl.appendChild(this.element);
16161    
16162    if (isIE8 === undefined)
16163        isIE8 = !("opacity" in this.element.style);
16164
16165    this.isVisible = false;
16166    this.isBlinking = true;
16167    this.blinkInterval = 1000;
16168    this.smoothBlinking = false;
16169
16170    this.cursors = [];
16171    this.cursor = this.addCursor();
16172    dom.addCssClass(this.element, "ace_hidden-cursors");
16173    this.$updateCursors = (isIE8
16174        ? this.$updateVisibility
16175        : this.$updateOpacity).bind(this);
16176};
16177
16178(function() {
16179    
16180    this.$updateVisibility = function(val) {
16181        var cursors = this.cursors;
16182        for (var i = cursors.length; i--; )
16183            cursors[i].style.visibility = val ? "" : "hidden";
16184    };
16185    this.$updateOpacity = function(val) {
16186        var cursors = this.cursors;
16187        for (var i = cursors.length; i--; )
16188            cursors[i].style.opacity = val ? "" : "0";
16189    };
16190    
16191
16192    this.$padding = 0;
16193    this.setPadding = function(padding) {
16194        this.$padding = padding;
16195    };
16196
16197    this.setSession = function(session) {
16198        this.session = session;
16199    };
16200
16201    this.setBlinking = function(blinking) {
16202        if (blinking != this.isBlinking){
16203            this.isBlinking = blinking;
16204            this.restartTimer();
16205        }
16206    };
16207
16208    this.setBlinkInterval = function(blinkInterval) {
16209        if (blinkInterval != this.blinkInterval){
16210            this.blinkInterval = blinkInterval;
16211            this.restartTimer();
16212        }
16213    };
16214
16215    this.setSmoothBlinking = function(smoothBlinking) {
16216        if (smoothBlinking != this.smoothBlinking && !isIE8) {
16217            this.smoothBlinking = smoothBlinking;
16218            dom.setCssClass(this.element, "ace_smooth-blinking", smoothBlinking);
16219            this.$updateCursors(true);
16220            this.$updateCursors = (this.$updateOpacity).bind(this);
16221            this.restartTimer();
16222        }
16223    };
16224
16225    this.addCursor = function() {
16226        var el = dom.createElement("div");
16227        el.className = "ace_cursor";
16228        this.element.appendChild(el);
16229        this.cursors.push(el);
16230        return el;
16231    };
16232
16233    this.removeCursor = function() {
16234        if (this.cursors.length > 1) {
16235            var el = this.cursors.pop();
16236            el.parentNode.removeChild(el);
16237            return el;
16238        }
16239    };
16240
16241    this.hideCursor = function() {
16242        this.isVisible = false;
16243        dom.addCssClass(this.element, "ace_hidden-cursors");
16244        this.restartTimer();
16245    };
16246
16247    this.showCursor = function() {
16248        this.isVisible = true;
16249        dom.removeCssClass(this.element, "ace_hidden-cursors");
16250        this.restartTimer();
16251    };
16252
16253    this.restartTimer = function() {
16254        var update = this.$updateCursors;
16255        clearInterval(this.intervalId);
16256        clearTimeout(this.timeoutId);
16257        if (this.smoothBlinking) {
16258            dom.removeCssClass(this.element, "ace_smooth-blinking");
16259        }
16260        
16261        update(true);
16262
16263        if (!this.isBlinking || !this.blinkInterval || !this.isVisible)
16264            return;
16265
16266        if (this.smoothBlinking) {
16267            setTimeout(function(){
16268                dom.addCssClass(this.element, "ace_smooth-blinking");
16269            }.bind(this));
16270        }
16271        
16272        var blink = function(){
16273            this.timeoutId = setTimeout(function() {
16274                update(false);
16275            }, 0.6 * this.blinkInterval);
16276        }.bind(this);
16277
16278        this.intervalId = setInterval(function() {
16279            update(true);
16280            blink();
16281        }, this.blinkInterval);
16282
16283        blink();
16284    };
16285
16286    this.getPixelPosition = function(position, onScreen) {
16287        if (!this.config || !this.session)
16288            return {left : 0, top : 0};
16289
16290        if (!position)
16291            position = this.session.selection.getCursor();
16292        var pos = this.session.documentToScreenPosition(position);
16293        var cursorLeft = this.$padding + (this.session.$bidiHandler.isBidiRow(pos.row, position.row)
16294            ? this.session.$bidiHandler.getPosLeft(pos.column)
16295            : pos.column * this.config.characterWidth);
16296
16297        var cursorTop = (pos.row - (onScreen ? this.config.firstRowScreen : 0)) *
16298            this.config.lineHeight;
16299
16300        return {left : cursorLeft, top : cursorTop};
16301    };
16302
16303    this.update = function(config) {
16304        this.config = config;
16305
16306        var selections = this.session.$selectionMarkers;
16307        var i = 0, cursorIndex = 0;
16308
16309        if (selections === undefined || selections.length === 0){
16310            selections = [{cursor: null}];
16311        }
16312
16313        for (var i = 0, n = selections.length; i < n; i++) {
16314            var pixelPos = this.getPixelPosition(selections[i].cursor, true);
16315            if ((pixelPos.top > config.height + config.offset ||
16316                 pixelPos.top < 0) && i > 1) {
16317                continue;
16318            }
16319
16320            var style = (this.cursors[cursorIndex++] || this.addCursor()).style;
16321            
16322            if (!this.drawCursor) {
16323                style.left = pixelPos.left + "px";
16324                style.top = pixelPos.top + "px";
16325                style.width = config.characterWidth + "px";
16326                style.height = config.lineHeight + "px";
16327            } else {
16328                this.drawCursor(style, pixelPos, config, selections[i], this.session);
16329            }
16330        }
16331        while (this.cursors.length > cursorIndex)
16332            this.removeCursor();
16333
16334        var overwrite = this.session.getOverwrite();
16335        this.$setOverwrite(overwrite);
16336        this.$pixelPos = pixelPos;
16337        this.restartTimer();
16338    };
16339    
16340    this.drawCursor = null;
16341
16342    this.$setOverwrite = function(overwrite) {
16343        if (overwrite != this.overwrite) {
16344            this.overwrite = overwrite;
16345            if (overwrite)
16346                dom.addCssClass(this.element, "ace_overwrite-cursors");
16347            else
16348                dom.removeCssClass(this.element, "ace_overwrite-cursors");
16349        }
16350    };
16351
16352    this.destroy = function() {
16353        clearInterval(this.intervalId);
16354        clearTimeout(this.timeoutId);
16355    };
16356
16357}).call(Cursor.prototype);
16358
16359exports.Cursor = Cursor;
16360
16361});
16362
16363define("ace/scrollbar",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/event","ace/lib/event_emitter"], function(require, exports, module) {
16364"use strict";
16365
16366var oop = require("./lib/oop");
16367var dom = require("./lib/dom");
16368var event = require("./lib/event");
16369var EventEmitter = require("./lib/event_emitter").EventEmitter;
16370var MAX_SCROLL_H = 0x8000;
16371var ScrollBar = function(parent) {
16372    this.element = dom.createElement("div");
16373    this.element.className = "ace_scrollbar ace_scrollbar" + this.classSuffix;
16374
16375    this.inner = dom.createElement("div");
16376    this.inner.className = "ace_scrollbar-inner";
16377    this.element.appendChild(this.inner);
16378
16379    parent.appendChild(this.element);
16380
16381    this.setVisible(false);
16382    this.skipEvent = false;
16383
16384    event.addListener(this.element, "scroll", this.onScroll.bind(this));
16385    event.addListener(this.element, "mousedown", event.preventDefault);
16386};
16387
16388(function() {
16389    oop.implement(this, EventEmitter);
16390
16391    this.setVisible = function(isVisible) {
16392        this.element.style.display = isVisible ? "" : "none";
16393        this.isVisible = isVisible;
16394        this.coeff = 1;
16395    };
16396}).call(ScrollBar.prototype);
16397var VScrollBar = function(parent, renderer) {
16398    ScrollBar.call(this, parent);
16399    this.scrollTop = 0;
16400    this.scrollHeight = 0;
16401    renderer.$scrollbarWidth = 
16402    this.width = dom.scrollbarWidth(parent.ownerDocument);
16403    this.inner.style.width =
16404    this.element.style.width = (this.width || 15) + 5 + "px";
16405    this.$minWidth = 0;
16406};
16407
16408oop.inherits(VScrollBar, ScrollBar);
16409
16410(function() {
16411
16412    this.classSuffix = '-v';
16413    this.onScroll = function() {
16414        if (!this.skipEvent) {
16415            this.scrollTop = this.element.scrollTop;
16416            if (this.coeff != 1) {
16417                var h = this.element.clientHeight / this.scrollHeight;
16418                this.scrollTop = this.scrollTop * (1 - h) / (this.coeff - h);
16419            }
16420            this._emit("scroll", {data: this.scrollTop});
16421        }
16422        this.skipEvent = false;
16423    };
16424    this.getWidth = function() {
16425        return Math.max(this.isVisible ? this.width : 0, this.$minWidth || 0);
16426    };
16427    this.setHeight = function(height) {
16428        this.element.style.height = height + "px";
16429    };
16430    this.setInnerHeight = 
16431    this.setScrollHeight = function(height) {
16432        this.scrollHeight = height;
16433        if (height > MAX_SCROLL_H) {
16434            this.coeff = MAX_SCROLL_H / height;
16435            height = MAX_SCROLL_H;
16436        } else if (this.coeff != 1) {
16437            this.coeff = 1;
16438        }
16439        this.inner.style.height = height + "px";
16440    };
16441    this.setScrollTop = function(scrollTop) {
16442        if (this.scrollTop != scrollTop) {
16443            this.skipEvent = true;
16444            this.scrollTop = scrollTop;
16445            this.element.scrollTop = scrollTop * this.coeff;
16446        }
16447    };
16448
16449}).call(VScrollBar.prototype);
16450var HScrollBar = function(parent, renderer) {
16451    ScrollBar.call(this, parent);
16452    this.scrollLeft = 0;
16453    this.height = renderer.$scrollbarWidth;
16454    this.inner.style.height =
16455    this.element.style.height = (this.height || 15) + 5 + "px";
16456};
16457
16458oop.inherits(HScrollBar, ScrollBar);
16459
16460(function() {
16461
16462    this.classSuffix = '-h';
16463    this.onScroll = function() {
16464        if (!this.skipEvent) {
16465            this.scrollLeft = this.element.scrollLeft;
16466            this._emit("scroll", {data: this.scrollLeft});
16467        }
16468        this.skipEvent = false;
16469    };
16470    this.getHeight = function() {
16471        return this.isVisible ? this.height : 0;
16472    };
16473    this.setWidth = function(width) {
16474        this.element.style.width = width + "px";
16475    };
16476    this.setInnerWidth = function(width) {
16477        this.inner.style.width = width + "px";
16478    };
16479    this.setScrollWidth = function(width) {
16480        this.inner.style.width = width + "px";
16481    };
16482    this.setScrollLeft = function(scrollLeft) {
16483        if (this.scrollLeft != scrollLeft) {
16484            this.skipEvent = true;
16485            this.scrollLeft = this.element.scrollLeft = scrollLeft;
16486        }
16487    };
16488
16489}).call(HScrollBar.prototype);
16490
16491
16492exports.ScrollBar = VScrollBar; // backward compatibility
16493exports.ScrollBarV = VScrollBar; // backward compatibility
16494exports.ScrollBarH = HScrollBar; // backward compatibility
16495
16496exports.VScrollBar = VScrollBar;
16497exports.HScrollBar = HScrollBar;
16498});
16499
16500define("ace/renderloop",["require","exports","module","ace/lib/event"], function(require, exports, module) {
16501"use strict";
16502
16503var event = require("./lib/event");
16504
16505
16506var RenderLoop = function(onRender, win) {
16507    this.onRender = onRender;
16508    this.pending = false;
16509    this.changes = 0;
16510    this.window = win || window;
16511};
16512
16513(function() {
16514
16515
16516    this.schedule = function(change) {
16517        this.changes = this.changes | change;
16518        if (!this.pending && this.changes) {
16519            this.pending = true;
16520            var _self = this;
16521            event.nextFrame(function() {
16522                _self.pending = false;
16523                var changes;
16524                while (changes = _self.changes) {
16525                    _self.changes = 0;
16526                    _self.onRender(changes);
16527                }
16528            }, this.window);
16529        }
16530    };
16531
16532}).call(RenderLoop.prototype);
16533
16534exports.RenderLoop = RenderLoop;
16535});
16536
16537define("ace/layer/font_metrics",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/lang","ace/lib/useragent","ace/lib/event_emitter"], function(require, exports, module) {
16538
16539var oop = require("../lib/oop");
16540var dom = require("../lib/dom");
16541var lang = require("../lib/lang");
16542var useragent = require("../lib/useragent");
16543var EventEmitter = require("../lib/event_emitter").EventEmitter;
16544
16545var CHAR_COUNT = 256;
16546var USE_OBSERVER = typeof ResizeObserver == "function";
16547
16548var FontMetrics = exports.FontMetrics = function(parentEl) {
16549    this.el = dom.createElement("div");
16550    this.$setMeasureNodeStyles(this.el.style, true);
16551    
16552    this.$main = dom.createElement("div");
16553    this.$setMeasureNodeStyles(this.$main.style);
16554    
16555    this.$measureNode = dom.createElement("div");
16556    this.$setMeasureNodeStyles(this.$measureNode.style);
16557    
16558    
16559    this.el.appendChild(this.$main);
16560    this.el.appendChild(this.$measureNode);
16561    parentEl.appendChild(this.el);
16562    
16563    this.$measureNode.innerHTML = lang.stringRepeat("X", CHAR_COUNT);
16564    
16565    this.$characterSize = {width: 0, height: 0};
16566    
16567    
16568    if (USE_OBSERVER)
16569        this.$addObserver();
16570    else
16571        this.checkForSizeChanges();
16572};
16573
16574(function() {
16575
16576    oop.implement(this, EventEmitter);
16577        
16578    this.$characterSize = {width: 0, height: 0};
16579    
16580    this.$setMeasureNodeStyles = function(style, isRoot) {
16581        style.width = style.height = "auto";
16582        style.left = style.top = "0px";
16583        style.visibility = "hidden";
16584        style.position = "absolute";
16585        style.whiteSpace = "pre";
16586
16587        if (useragent.isIE < 8) {
16588            style["font-family"] = "inherit";
16589        } else {
16590            style.font = "inherit";
16591        }
16592        style.overflow = isRoot ? "hidden" : "visible";
16593    };
16594
16595    this.checkForSizeChanges = function(size) {
16596        if (size === undefined)
16597            size = this.$measureSizes();
16598        if (size && (this.$characterSize.width !== size.width || this.$characterSize.height !== size.height)) {
16599            this.$measureNode.style.fontWeight = "bold";
16600            var boldSize = this.$measureSizes();
16601            this.$measureNode.style.fontWeight = "";
16602            this.$characterSize = size;
16603            this.charSizes = Object.create(null);
16604            this.allowBoldFonts = boldSize && boldSize.width === size.width && boldSize.height === size.height;
16605            this._emit("changeCharacterSize", {data: size});
16606        }
16607    };
16608    
16609    this.$addObserver = function() {
16610        var self = this;
16611        this.$observer = new window.ResizeObserver(function(e) {
16612            var rect = e[0].contentRect;
16613            self.checkForSizeChanges({
16614                height: rect.height,
16615                width: rect.width / CHAR_COUNT
16616            });
16617        });
16618        this.$observer.observe(this.$measureNode);
16619    };
16620
16621    this.$pollSizeChanges = function() {
16622        if (this.$pollSizeChangesTimer || this.$observer)
16623            return this.$pollSizeChangesTimer;
16624        var self = this;
16625        return this.$pollSizeChangesTimer = setInterval(function() {
16626            self.checkForSizeChanges();
16627        }, 500);
16628    };
16629    
16630    this.setPolling = function(val) {
16631        if (val) {
16632            this.$pollSizeChanges();
16633        } else if (this.$pollSizeChangesTimer) {
16634            clearInterval(this.$pollSizeChangesTimer);
16635            this.$pollSizeChangesTimer = 0;
16636        }
16637    };
16638
16639    this.$measureSizes = function(node) {
16640        var size = {
16641            height: (node || this.$measureNode).clientHeight,
16642            width: (node || this.$measureNode).clientWidth / CHAR_COUNT
16643        };
16644        if (size.width === 0 || size.height === 0)
16645            return null;
16646        return size;
16647    };
16648
16649    this.$measureCharWidth = function(ch) {
16650        this.$main.innerHTML = lang.stringRepeat(ch, CHAR_COUNT);
16651        var rect = this.$main.getBoundingClientRect();
16652        return rect.width / CHAR_COUNT;
16653    };
16654    
16655    this.getCharacterWidth = function(ch) {
16656        var w = this.charSizes[ch];
16657        if (w === undefined) {
16658            w = this.charSizes[ch] = this.$measureCharWidth(ch) / this.$characterSize.width;
16659        }
16660        return w;
16661    };
16662
16663    this.destroy = function() {
16664        clearInterval(this.$pollSizeChangesTimer);
16665        if (this.el && this.el.parentNode)
16666            this.el.parentNode.removeChild(this.el);
16667    };
16668
16669}).call(FontMetrics.prototype);
16670
16671});
16672
16673define("ace/virtual_renderer",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/config","ace/lib/useragent","ace/layer/gutter","ace/layer/marker","ace/layer/text","ace/layer/cursor","ace/scrollbar","ace/scrollbar","ace/renderloop","ace/layer/font_metrics","ace/lib/event_emitter"], function(require, exports, module) {
16674"use strict";
16675
16676var oop = require("./lib/oop");
16677var dom = require("./lib/dom");
16678var config = require("./config");
16679var useragent = require("./lib/useragent");
16680var GutterLayer = require("./layer/gutter").Gutter;
16681var MarkerLayer = require("./layer/marker").Marker;
16682var TextLayer = require("./layer/text").Text;
16683var CursorLayer = require("./layer/cursor").Cursor;
16684var HScrollBar = require("./scrollbar").HScrollBar;
16685var VScrollBar = require("./scrollbar").VScrollBar;
16686var RenderLoop = require("./renderloop").RenderLoop;
16687var FontMetrics = require("./layer/font_metrics").FontMetrics;
16688var EventEmitter = require("./lib/event_emitter").EventEmitter;
16689var editorCss = ".ace_editor {\
16690position: relative;\
16691overflow: hidden;\
16692font: 12px/normal 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', monospace;\
16693direction: ltr;\
16694text-align: left;\
16695-webkit-tap-highlight-color: rgba(0, 0, 0, 0);\
16696}\
16697.ace_scroller {\
16698position: absolute;\
16699overflow: hidden;\
16700top: 0;\
16701bottom: 0;\
16702background-color: inherit;\
16703-ms-user-select: none;\
16704-moz-user-select: none;\
16705-webkit-user-select: none;\
16706user-select: none;\
16707cursor: text;\
16708}\
16709.ace_content {\
16710position: absolute;\
16711box-sizing: border-box;\
16712min-width: 100%;\
16713}\
16714.ace_dragging .ace_scroller:before{\
16715position: absolute;\
16716top: 0;\
16717left: 0;\
16718right: 0;\
16719bottom: 0;\
16720content: '';\
16721background: rgba(250, 250, 250, 0.01);\
16722z-index: 1000;\
16723}\
16724.ace_dragging.ace_dark .ace_scroller:before{\
16725background: rgba(0, 0, 0, 0.01);\
16726}\
16727.ace_selecting, .ace_selecting * {\
16728cursor: text !important;\
16729}\
16730.ace_gutter {\
16731position: absolute;\
16732overflow : hidden;\
16733width: auto;\
16734top: 0;\
16735bottom: 0;\
16736left: 0;\
16737cursor: default;\
16738z-index: 4;\
16739-ms-user-select: none;\
16740-moz-user-select: none;\
16741-webkit-user-select: none;\
16742user-select: none;\
16743}\
16744.ace_gutter-active-line {\
16745position: absolute;\
16746left: 0;\
16747right: 0;\
16748}\
16749.ace_scroller.ace_scroll-left {\
16750box-shadow: 17px 0 16px -16px rgba(0, 0, 0, 0.4) inset;\
16751}\
16752.ace_gutter-cell {\
16753padding-left: 19px;\
16754padding-right: 6px;\
16755background-repeat: no-repeat;\
16756}\
16757.ace_gutter-cell.ace_error {\
16758background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABOFBMVEX/////////QRswFAb/Ui4wFAYwFAYwFAaWGAfDRymzOSH/PxswFAb/SiUwFAYwFAbUPRvjQiDllog5HhHdRybsTi3/Tyv9Tir+Syj/UC3////XurebMBIwFAb/RSHbPx/gUzfdwL3kzMivKBAwFAbbvbnhPx66NhowFAYwFAaZJg8wFAaxKBDZurf/RB6mMxb/SCMwFAYwFAbxQB3+RB4wFAb/Qhy4Oh+4QifbNRcwFAYwFAYwFAb/QRzdNhgwFAYwFAbav7v/Uy7oaE68MBK5LxLewr/r2NXewLswFAaxJw4wFAbkPRy2PyYwFAaxKhLm1tMwFAazPiQwFAaUGAb/QBrfOx3bvrv/VC/maE4wFAbRPBq6MRO8Qynew8Dp2tjfwb0wFAbx6eju5+by6uns4uH9/f36+vr/GkHjAAAAYnRSTlMAGt+64rnWu/bo8eAA4InH3+DwoN7j4eLi4xP99Nfg4+b+/u9B/eDs1MD1mO7+4PHg2MXa347g7vDizMLN4eG+Pv7i5evs/v79yu7S3/DV7/498Yv24eH+4ufQ3Ozu/v7+y13sRqwAAADLSURBVHjaZc/XDsFgGIBhtDrshlitm
16758k2IrbHFqL2pvXf/+78DPokj7+Fz9qpU/9UXJIlhmPaTaQ6QPaz0mm+5gwkgovcV6GZzd5JtCQwgsxoHOvJO15kleRLAnMgHFIESUEPmawB9ngmelTtipwwfASilxOLyiV5UVUyVAfbG0cCPHig+GBkzAENHS0AstVF6bacZIOzgLmxsHbt2OecNgJC83JERmePUYq8ARGkJx6XtFsdddBQgZE2nPR6CICZhawjA4Fb/chv+399kfR+MMMDGOQAAAABJRU5ErkJggg==\");\
16759background-repeat: no-repeat;\
16760background-position: 2px center;\
16761}\
16762.ace_gutter-cell.ace_warning {\
16763background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAmVBMVEX///8AAAD///8AAAAAAABPSzb/5sAAAAB/blH/73z/ulkAAAAAAAD85pkAAAAAAAACAgP/vGz/rkDerGbGrV7/pkQICAf////e0IsAAAD/oED/qTvhrnUAAAD/yHD/njcAAADuv2r/nz//oTj/p064oGf/zHAAAAA9Nir/tFIAAAD/tlTiuWf/tkIAAACynXEAAAAAAAAtIRW7zBpBAAAAM3RSTlMAABR1m7RXO8Ln31Z36zT+neXe5OzooRDfn+TZ4p3h2hTf4t3k3ucyrN1K5+Xaks52Sfs9CXgrAAAAjklEQVR42o3PbQ+CIBQFYEwboPhSYgoYunIqqLn6/z8uYdH8Vmdnu9vz4WwXgN/xTPRD2+sgOcZjsge/whXZgUaYYvT8QnuJaUrjrHUQreGczuEafQCO/SJTufTbroWsPgsllVhq3wJEk2jUSzX3CUEDJC84707djRc5MTAQxoLgupWRwW6UB5fS++NV8AbOZgnsC7BpEAAAAABJRU5ErkJggg==\");\
16764background-position: 2px center;\
16765}\
16766.ace_gutter-cell.ace_info {\
16767background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAAAAAA6mKC9AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAJ0Uk5TAAB2k804AAAAPklEQVQY02NgIB68QuO3tiLznjAwpKTgNyDbMegwisCHZUETUZV0ZqOquBpXj2rtnpSJT1AEnnRmL2OgGgAAIKkRQap2htgAAAAASUVORK5CYII=\");\
16768background-position: 2px center;\
16769}\
16770.ace_dark .ace_gutter-cell.ace_info {\
16771background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAJFBMVEUAAAChoaGAgIAqKiq+vr6tra1ZWVmUlJSbm5s8PDxubm56enrdgzg3AAAAAXRSTlMAQObYZgAAAClJREFUeNpjYMAPdsMYHegyJZFQBlsUlMFVCWUYKkAZMxZAGdxlDMQBAG+TBP4B6RyJAAAAAElFTkSuQmCC\");\
16772}\
16773.ace_scrollbar {\
16774position: absolute;\
16775right: 0;\
16776bottom: 0;\
16777z-index: 6;\
16778}\
16779.ace_scrollbar-inner {\
16780position: absolute;\
16781cursor: text;\
16782left: 0;\
16783top: 0;\
16784}\
16785.ace_scrollbar-v{\
16786overflow-x: hidden;\
16787overflow-y: scroll;\
16788top: 0;\
16789}\
16790.ace_scrollbar-h {\
16791overflow-x: scroll;\
16792overflow-y: hidden;\
16793left: 0;\
16794}\
16795.ace_print-margin {\
16796position: absolute;\
16797height: 100%;\
16798}\
16799.ace_text-input {\
16800position: absolute;\
16801z-index: 0;\
16802width: 0.5em;\
16803height: 1em;\
16804opacity: 0;\
16805background: transparent;\
16806-moz-appearance: none;\
16807appearance: none;\
16808border: none;\
16809resize: none;\
16810outline: none;\
16811overflow: hidden;\
16812font: inherit;\
16813padding: 0 1px;\
16814margin: 0 -1px;\
16815text-indent: -1em;\
16816-ms-user-select: text;\
16817-moz-user-select: text;\
16818-webkit-user-select: text;\
16819user-select: text;\
16820white-space: pre!important;\
16821}\
16822.ace_text-input.ace_composition {\
16823background: inherit;\
16824color: inherit;\
16825z-index: 1000;\
16826opacity: 1;\
16827text-indent: 0;\
16828}\
16829[ace_nocontext=true] {\
16830transform: none!important;\
16831filter: none!important;\
16832perspective: none!important;\
16833clip-path: none!important;\
16834mask : none!important;\
16835contain: none!important;\
16836perspective: none!important;\
16837mix-blend-mode: initial!important;\
16838z-index: auto;\
16839}\
16840.ace_layer {\
16841z-index: 1;\
16842position: absolute;\
16843overflow: hidden;\
16844word-wrap: normal;\
16845white-space: pre;\
16846height: 100%;\
16847width: 100%;\
16848box-sizing: border-box;\
16849pointer-events: none;\
16850}\
16851.ace_gutter-layer {\
16852position: relative;\
16853width: auto;\
16854text-align: right;\
16855pointer-events: auto;\
16856}\
16857.ace_text-layer {\
16858font: inherit !important;\
16859}\
16860.ace_cjk {\
16861display: inline-block;\
16862text-align: center;\
16863}\
16864.ace_cursor-layer {\
16865z-index: 4;\
16866}\
16867.ace_cursor {\
16868z-index: 4;\
16869position: absolute;\
16870box-sizing: border-box;\
16871border-left: 2px solid;\
16872transform: translatez(0);\
16873}\
16874.ace_multiselect .ace_cursor {\
16875border-left-width: 1px;\
16876}\
16877.ace_slim-cursors .ace_cursor {\
16878border-left-width: 1px;\
16879}\
16880.ace_overwrite-cursors .ace_cursor {\
16881border-left-width: 0;\
16882border-bottom: 1px solid;\
16883}\
16884.ace_hidden-cursors .ace_cursor {\
16885opacity: 0.2;\
16886}\
16887.ace_smooth-blinking .ace_cursor {\
16888transition: opacity 0.18s;\
16889}\
16890.ace_marker-layer .ace_step, .ace_marker-layer .ace_stack {\
16891position: absolute;\
16892z-index: 3;\
16893}\
16894.ace_marker-layer .ace_selection {\
16895position: absolute;\
16896z-index: 5;\
16897}\
16898.ace_marker-layer .ace_bracket {\
16899position: absolute;\
16900z-index: 6;\
16901}\
16902.ace_marker-layer .ace_active-line {\
16903position: absolute;\
16904z-index: 2;\
16905}\
16906.ace_marker-layer .ace_selected-word {\
16907position: absolute;\
16908z-index: 4;\
16909box-sizing: border-box;\
16910}\
16911.ace_line .ace_fold {\
16912box-sizing: border-box;\
16913display: inline-block;\
16914height: 11px;\
16915margin-top: -2px;\
16916vertical-align: middle;\
16917background-image:\
16918url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII=\"),\
16919url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACJJREFUeNpi+P//fxgTAwPDBxDxD078RSX+YeEyDFMCIMAAI3INmXiwf2YAAAAASUVORK5CYII=\");\
16920background-repeat: no-repeat, repeat-x;\
16921background-position: center center, top left;\
16922color: transparent;\
16923border: 1px solid black;\
16924border-radius: 2px;\
16925cursor: pointer;\
16926pointer-events: auto;\
16927}\
16928.ace_dark .ace_fold {\
16929}\
16930.ace_fold:hover{\
16931background-image:\
16932url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII=\"),\
16933url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACBJREFUeNpi+P//fz4TAwPDZxDxD5X4i5fLMEwJgAADAEPVDbjNw87ZAAAAAElFTkSuQmCC\");\
16934}\
16935.ace_tooltip {\
16936background-color: #FFF;\
16937background-image: linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.1));\
16938border: 1px solid gray;\
16939border-radius: 1px;\
16940box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);\
16941color: black;\
16942max-width: 100%;\
16943padding: 3px 4px;\
16944position: fixed;\
16945z-index: 999999;\
16946box-sizing: border-box;\
16947cursor: default;\
16948white-space: pre;\
16949word-wrap: break-word;\
16950line-height: normal;\
16951font-style: normal;\
16952font-weight: normal;\
16953letter-spacing: normal;\
16954pointer-events: none;\
16955}\
16956.ace_folding-enabled > .ace_gutter-cell {\
16957padding-right: 13px;\
16958}\
16959.ace_fold-widget {\
16960box-sizing: border-box;\
16961margin: 0 -12px 0 1px;\
16962display: none;\
16963width: 11px;\
16964vertical-align: top;\
16965background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42mWKsQ0AMAzC8ixLlrzQjzmBiEjp0A6WwBCSPgKAXoLkqSot7nN3yMwR7pZ32NzpKkVoDBUxKAAAAABJRU5ErkJggg==\");\
16966background-repeat: no-repeat;\
16967background-position: center;\
16968border-radius: 3px;\
16969border: 1px solid transparent;\
16970cursor: pointer;\
16971}\
16972.ace_folding-enabled .ace_fold-widget {\
16973display: inline-block;   \
16974}\
16975.ace_fold-widget.ace_end {\
16976background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42m3HwQkAMAhD0YzsRchFKI7sAikeWkrxwScEB0nh5e7KTPWimZki4tYfVbX+MNl4pyZXejUO1QAAAABJRU5ErkJggg==\");\
16977}\
16978.ace_fold-widget.ace_closed {\
16979background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAGCAYAAAAG5SQMAAAAOUlEQVR42jXKwQkAMAgDwKwqKD4EwQ26sSOkVWjgIIHAzPiCgaqiqnJHZnKICBERHN194O5b9vbLuAVRL+l0YWnZAAAAAElFTkSuQmCCXA==\");\
16980}\
16981.ace_fold-widget:hover {\
16982border: 1px solid rgba(0, 0, 0, 0.3);\
16983background-color: rgba(255, 255, 255, 0.2);\
16984box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);\
16985}\
16986.ace_fold-widget:active {\
16987border: 1px solid rgba(0, 0, 0, 0.4);\
16988background-color: rgba(0, 0, 0, 0.05);\
16989box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);\
16990}\
16991.ace_dark .ace_fold-widget {\
16992background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHklEQVQIW2P4//8/AzoGEQ7oGCaLLAhWiSwB146BAQCSTPYocqT0AAAAAElFTkSuQmCC\");\
16993}\
16994.ace_dark .ace_fold-widget.ace_end {\
16995background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAH0lEQVQIW2P4//8/AxQ7wNjIAjDMgC4AxjCVKBirIAAF0kz2rlhxpAAAAABJRU5ErkJggg==\");\
16996}\
16997.ace_dark .ace_fold-widget.ace_closed {\
16998background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAHElEQVQIW2P4//+/AxAzgDADlOOAznHAKgPWAwARji8UIDTfQQAAAABJRU5ErkJggg==\");\
16999}\
17000.ace_dark .ace_fold-widget:hover {\
17001box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);\
17002background-color: rgba(255, 255, 255, 0.1);\
17003}\
17004.ace_dark .ace_fold-widget:active {\
17005box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);\
17006}\
17007.ace_inline_button {\
17008border: 1px solid lightgray;\
17009display: inline-block;\
17010margin: -1px 8px;\
17011padding: 0 5px;\
17012pointer-events: auto;\
17013cursor: pointer;\
17014}\
17015.ace_inline_button:hover {\
17016border-color: gray;\
17017background: rgba(200,200,200,0.2);\
17018display: inline-block;\
17019pointer-events: auto;\
17020}\
17021.ace_fold-widget.ace_invalid {\
17022background-color: #FFB4B4;\
17023border-color: #DE5555;\
17024}\
17025.ace_fade-fold-widgets .ace_fold-widget {\
17026transition: opacity 0.4s ease 0.05s;\
17027opacity: 0;\
17028}\
17029.ace_fade-fold-widgets:hover .ace_fold-widget {\
17030transition: opacity 0.05s ease 0.05s;\
17031opacity:1;\
17032}\
17033.ace_underline {\
17034text-decoration: underline;\
17035}\
17036.ace_bold {\
17037font-weight: bold;\
17038}\
17039.ace_nobold .ace_bold {\
17040font-weight: normal;\
17041}\
17042.ace_italic {\
17043font-style: italic;\
17044}\
17045.ace_error-marker {\
17046background-color: rgba(255, 0, 0,0.2);\
17047position: absolute;\
17048z-index: 9;\
17049}\
17050.ace_highlight-marker {\
17051background-color: rgba(255, 255, 0,0.2);\
17052position: absolute;\
17053z-index: 8;\
17054}\
17055.ace_br1 {border-top-left-radius    : 3px;}\
17056.ace_br2 {border-top-right-radius   : 3px;}\
17057.ace_br3 {border-top-left-radius    : 3px; border-top-right-radius:    3px;}\
17058.ace_br4 {border-bottom-right-radius: 3px;}\
17059.ace_br5 {border-top-left-radius    : 3px; border-bottom-right-radius: 3px;}\
17060.ace_br6 {border-top-right-radius   : 3px; border-bottom-right-radius: 3px;}\
17061.ace_br7 {border-top-left-radius    : 3px; border-top-right-radius:    3px; border-bottom-right-radius: 3px;}\
17062.ace_br8 {border-bottom-left-radius : 3px;}\
17063.ace_br9 {border-top-left-radius    : 3px; border-bottom-left-radius:  3px;}\
17064.ace_br10{border-top-right-radius   : 3px; border-bottom-left-radius:  3px;}\
17065.ace_br11{border-top-left-radius    : 3px; border-top-right-radius:    3px; border-bottom-left-radius:  3px;}\
17066.ace_br12{border-bottom-right-radius: 3px; border-bottom-left-radius:  3px;}\
17067.ace_br13{border-top-left-radius    : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius:  3px;}\
17068.ace_br14{border-top-right-radius   : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius:  3px;}\
17069.ace_br15{border-top-left-radius    : 3px; border-top-right-radius:    3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}\
17070.ace_text-input-ios {\
17071position: absolute !important;\
17072top: -100000px !important;\
17073left: -100000px !important;\
17074}\
17075";
17076
17077dom.importCssString(editorCss, "ace_editor.css");
17078
17079var VirtualRenderer = function(container, theme) {
17080    var _self = this;
17081
17082    this.container = container || dom.createElement("div");
17083
17084    dom.addCssClass(this.container, "ace_editor");
17085
17086    this.setTheme(theme);
17087
17088    this.$gutter = dom.createElement("div");
17089    this.$gutter.className = "ace_gutter";
17090    this.container.appendChild(this.$gutter);
17091    this.$gutter.setAttribute("aria-hidden", true);
17092
17093    this.scroller = dom.createElement("div");
17094    this.scroller.className = "ace_scroller";
17095    this.container.appendChild(this.scroller);
17096
17097    this.content = dom.createElement("div");
17098    this.content.className = "ace_content";
17099    this.scroller.appendChild(this.content);
17100
17101    this.$gutterLayer = new GutterLayer(this.$gutter);
17102    this.$gutterLayer.on("changeGutterWidth", this.onGutterResize.bind(this));
17103
17104    this.$markerBack = new MarkerLayer(this.content);
17105
17106    var textLayer = this.$textLayer = new TextLayer(this.content);
17107    this.canvas = textLayer.element;
17108
17109    this.$markerFront = new MarkerLayer(this.content);
17110
vendor: 5,562 bytes, lines 17111-17291
17111    this.$cursorLayer = new CursorLayer(this.content);
17112    this.$horizScroll = false;
17113    this.$vScroll = false;
17114
17115    this.scrollBar = 
17116    this.scrollBarV = new VScrollBar(this.container, this);
17117    this.scrollBarH = new HScrollBar(this.container, this);
17118    this.scrollBarV.addEventListener("scroll", function(e) {
17119        if (!_self.$scrollAnimation)
17120            _self.session.setScrollTop(e.data - _self.scrollMargin.top);
17121    });
17122    this.scrollBarH.addEventListener("scroll", function(e) {
17123        if (!_self.$scrollAnimation)
17124            _self.session.setScrollLeft(e.data - _self.scrollMargin.left);
17125    });
17126
17127    this.scrollTop = 0;
17128    this.scrollLeft = 0;
17129
17130    this.cursorPos = {
17131        row : 0,
17132        column : 0
17133    };
17134
17135    this.$fontMetrics = new FontMetrics(this.container);
17136    this.$textLayer.$setFontMetrics(this.$fontMetrics);
17137    this.$textLayer.addEventListener("changeCharacterSize", function(e) {
17138        _self.updateCharacterSize();
17139        _self.onResize(true, _self.gutterWidth, _self.$size.width, _self.$size.height);
17140        _self._signal("changeCharacterSize", e);
17141    });
17142
17143    this.$size = {
17144        width: 0,
17145        height: 0,
17146        scrollerHeight: 0,
17147        scrollerWidth: 0,
17148        $dirty: true
17149    };
17150
17151    this.layerConfig = {
17152        width : 1,
17153        padding : 0,
17154        firstRow : 0,
17155        firstRowScreen: 0,
17156        lastRow : 0,
17157        lineHeight : 0,
17158        characterWidth : 0,
17159        minHeight : 1,
17160        maxHeight : 1,
17161        offset : 0,
17162        height : 1,
17163        gutterOffset: 1
17164    };
17165    
17166    this.scrollMargin = {
17167        left: 0,
17168        right: 0,
17169        top: 0,
17170        bottom: 0,
17171        v: 0,
17172        h: 0
17173    };
17174
17175    this.$loop = new RenderLoop(
17176        this.$renderChanges.bind(this),
17177        this.container.ownerDocument.defaultView
17178    );
17179    this.$loop.schedule(this.CHANGE_FULL);
17180
17181    this.updateCharacterSize();
17182    this.setPadding(4);
17183    config.resetOptions(this);
17184    config._emit("renderer", this);
17185};
17186
17187(function() {
17188
17189    this.CHANGE_CURSOR = 1;
17190    this.CHANGE_MARKER = 2;
17191    this.CHANGE_GUTTER = 4;
17192    this.CHANGE_SCROLL = 8;
17193    this.CHANGE_LINES = 16;
17194    this.CHANGE_TEXT = 32;
17195    this.CHANGE_SIZE = 64;
17196    this.CHANGE_MARKER_BACK = 128;
17197    this.CHANGE_MARKER_FRONT = 256;
17198    this.CHANGE_FULL = 512;
17199    this.CHANGE_H_SCROLL = 1024;
17200
17201    oop.implement(this, EventEmitter);
17202
17203    this.updateCharacterSize = function() {
17204        if (this.$textLayer.allowBoldFonts != this.$allowBoldFonts) {
17205            this.$allowBoldFonts = this.$textLayer.allowBoldFonts;
17206            this.setStyle("ace_nobold", !this.$allowBoldFonts);
17207        }
17208
17209        this.layerConfig.characterWidth =
17210        this.characterWidth = this.$textLayer.getCharacterWidth();
17211        this.layerConfig.lineHeight =
17212        this.lineHeight = this.$textLayer.getLineHeight();
17213        this.$updatePrintMargin();
17214    };
17215    this.setSession = function(session) {
17216        if (this.session)
17217            this.session.doc.off("changeNewLineMode", this.onChangeNewLineMode);
17218            
17219        this.session = session;
17220        if (session && this.scrollMargin.top && session.getScrollTop() <= 0)
17221            session.setScrollTop(-this.scrollMargin.top);
17222
17223        this.$cursorLayer.setSession(session);
17224        this.$markerBack.setSession(session);
17225        this.$markerFront.setSession(session);
17226        this.$gutterLayer.setSession(session);
17227        this.$textLayer.setSession(session);
17228        if (!session)
17229            return;
17230        
17231        this.$loop.schedule(this.CHANGE_FULL);
17232        this.session.$setFontMetrics(this.$fontMetrics);
17233        this.scrollBarH.scrollLeft = this.scrollBarV.scrollTop = null;
17234        
17235        this.onChangeNewLineMode = this.onChangeNewLineMode.bind(this);
17236        this.onChangeNewLineMode();
17237        this.session.doc.on("changeNewLineMode", this.onChangeNewLineMode);
17238    };
17239    this.updateLines = function(firstRow, lastRow, force) {
17240        if (lastRow === undefined)
17241            lastRow = Infinity;
17242
17243        if (!this.$changedLines) {
17244            this.$changedLines = {
17245                firstRow: firstRow,
17246                lastRow: lastRow
17247            };
17248        }
17249        else {
17250            if (this.$changedLines.firstRow > firstRow)
17251                this.$changedLines.firstRow = firstRow;
17252
17253            if (this.$changedLines.lastRow < lastRow)
17254                this.$changedLines.lastRow = lastRow;
17255        }
17256        if (this.$changedLines.lastRow < this.layerConfig.firstRow) {
17257            if (force)
17258                this.$changedLines.lastRow = this.layerConfig.lastRow;
17259            else
17260                return;
17261        }
17262        if (this.$changedLines.firstRow > this.layerConfig.lastRow)
17263            return;
17264        this.$loop.schedule(this.CHANGE_LINES);
17265    };
17266
17267    this.onChangeNewLineMode = function() {
17268        this.$loop.schedule(this.CHANGE_TEXT);
17269        this.$textLayer.$updateEolChar();
17270        this.session.$bidiHandler.setEolChar(this.$textLayer.EOL_CHAR);
17271    };
17272    
17273    this.onChangeTabSize = function() {
17274        this.$loop.schedule(this.CHANGE_TEXT | this.CHANGE_MARKER);
17275        this.$textLayer.onChangeTabSize();
17276    };
17277    this.updateText = function() {
17278        this.$loop.schedule(this.CHANGE_TEXT);
17279    };
17280    this.updateFull = function(force) {
17281        if (force)
17282            this.$renderChanges(this.CHANGE_FULL, true);
17283        else
17284            this.$loop.schedule(this.CHANGE_FULL);
17285    };
17286    this.updateFontSize = function() {
17287        this.$textLayer.checkForSizeChanges();
17288    };
17289
17290    this.$changes = 0;
17291    this.$updateSizeAsync = function() {
17292        if (this.$loop.pending)
17293            this.$size.$dirty = true;
17294        else
17295            this.onResize();
17296    };
17297    this.onResize = function(force, gutterWidth, width, height) {
17298        if (this.resizing > 2)
17299            return;
17300        else if (this.resizing > 0)
17301            this.resizing++;
17302        else
17303            this.resizing = force ? 1 : 0;
17304        var el = this.container;
17305        if (!height)
17306            height = el.clientHeight || el.scrollHeight;
17307        if (!width)
17308            width = el.clientWidth || el.scrollWidth;
17309        var changes = this.$updateCachedSize(force, gutterWidth, width, height);
17310
17311        
17312        if (!this.$size.scrollerHeight || (!width && !height))
17313            return this.resizing = 0;
17314
17315        if (force)
17316            this.$gutterLayer.$padding = null;
17317
17318        if (force)
17319            this.$renderChanges(changes | this.$changes, true);
17320        else
17321            this.$loop.schedule(changes | this.$changes);
17322
17323        if (this.resizing)
17324            this.resizing = 0;
17325        this.scrollBarV.scrollLeft = this.scrollBarV.scrollTop = null;
17326    };
17327    
17328    this.$updateCachedSize = function(force, gutterWidth, width, height) {
17329        height -= (this.$extraHeight || 0);
17330        var changes = 0;
17331        var size = this.$size;
17332        var oldSize = {
17333            width: size.width,
17334            height: size.height,
17335            scrollerHeight: size.scrollerHeight,
17336            scrollerWidth: size.scrollerWidth
17337        };
17338        if (height && (force || size.height != height)) {
17339            size.height = height;
17340            changes |= this.CHANGE_SIZE;
17341
17342            size.scrollerHeight = size.height;
17343            if (this.$horizScroll)
17344                size.scrollerHeight -= this.scrollBarH.getHeight();
17345            this.scrollBarV.element.style.bottom = this.scrollBarH.getHeight() + "px";
17346
17347            changes = changes | this.CHANGE_SCROLL;
17348        }
17349
17350        if (width && (force || size.width != width)) {
17351            changes |= this.CHANGE_SIZE;
17352            size.width = width;
17353            
17354            if (gutterWidth == null)
17355                gutterWidth = this.$showGutter ? this.$gutter.offsetWidth : 0;
17356            
17357            this.gutterWidth = gutterWidth;
17358            
17359            this.scrollBarH.element.style.left = 
17360            this.scroller.style.left = gutterWidth + "px";
17361            size.scrollerWidth = Math.max(0, width - gutterWidth - this.scrollBarV.getWidth());           
17362            
17363            this.scrollBarH.element.style.right = 
17364            this.scroller.style.right = this.scrollBarV.getWidth() + "px";
17365            this.scroller.style.bottom = this.scrollBarH.getHeight() + "px";
17366
17367            if (this.session && this.session.getUseWrapMode() && this.adjustWrapLimit() || force)
17368                changes |= this.CHANGE_FULL;
17369        }
17370        
17371        size.$dirty = !width || !height;
17372
17373        if (changes)
17374            this._signal("resize", oldSize);
17375
17376        return changes;
17377    };
17378
17379    this.onGutterResize = function() {
17380        var gutterWidth = this.$showGutter ? this.$gutter.offsetWidth : 0;
17381        if (gutterWidth != this.gutterWidth)
17382            this.$changes |= this.$updateCachedSize(true, gutterWidth, this.$size.width, this.$size.height);
17383
17384        if (this.session.getUseWrapMode() && this.adjustWrapLimit()) {
17385            this.$loop.schedule(this.CHANGE_FULL);
17386        } else if (this.$size.$dirty) {
17387            this.$loop.schedule(this.CHANGE_FULL);
17388        } else {
17389            this.$computeLayerConfig();
17390            this.$loop.schedule(this.CHANGE_MARKER);
17391        }
17392    };
17393    this.adjustWrapLimit = function() {
17394        var availableWidth = this.$size.scrollerWidth - this.$padding * 2;
17395        var limit = Math.floor(availableWidth / this.characterWidth);
17396        return this.session.adjustWrapLimit(limit, this.$showPrintMargin && this.$printMarginColumn);
17397    };
17398    this.setAnimatedScroll = function(shouldAnimate){
17399        this.setOption("animatedScroll", shouldAnimate);
17400    };
17401    this.getAnimatedScroll = function() {
17402        return this.$animatedScroll;
17403    };
17404    this.setShowInvisibles = function(showInvisibles) {
17405        this.setOption("showInvisibles", showInvisibles);
17406        this.session.$bidiHandler.setShowInvisibles(showInvisibles);
17407    };
17408    this.getShowInvisibles = function() {
17409        return this.getOption("showInvisibles");
17410    };
17411    this.getDisplayIndentGuides = function() {
17412        return this.getOption("displayIndentGuides");
17413    };
17414
17415    this.setDisplayIndentGuides = function(display) {
17416        this.setOption("displayIndentGuides", display);
17417    };
17418    this.setShowPrintMargin = function(showPrintMargin) {
17419        this.setOption("showPrintMargin", showPrintMargin);
17420    };
17421    this.getShowPrintMargin = function() {
17422        return this.getOption("showPrintMargin");
17423    };
17424    this.setPrintMarginColumn = function(showPrintMargin) {
17425        this.setOption("printMarginColumn", showPrintMargin);
17426    };
17427    this.getPrintMarginColumn = function() {
17428        return this.getOption("printMarginColumn");
17429    };
17430    this.getShowGutter = function(){
17431        return this.getOption("showGutter");
17432    };
17433    this.setShowGutter = function(show){
17434        return this.setOption("showGutter", show);
17435    };
17436
17437    this.getFadeFoldWidgets = function(){
17438        return this.getOption("fadeFoldWidgets");
17439    };
17440
17441    this.setFadeFoldWidgets = function(show) {
17442        this.setOption("fadeFoldWidgets", show);
17443    };
17444
17445    this.setHighlightGutterLine = function(shouldHighlight) {
17446        this.setOption("highlightGutterLine", shouldHighlight);
17447    };
17448
17449    this.getHighlightGutterLine = function() {
17450        return this.getOption("highlightGutterLine");
17451    };
17452
17453    this.$updateGutterLineHighlight = function() {
17454        var pos = this.$cursorLayer.$pixelPos;
17455        var height = this.layerConfig.lineHeight;
17456        if (this.session.getUseWrapMode()) {
17457            var cursor = this.session.selection.getCursor();
17458            cursor.column = 0;
17459            pos = this.$cursorLayer.getPixelPosition(cursor, true);
17460            height *= this.session.getRowLength(cursor.row);
17461        }
17462        this.$gutterLineHighlight.style.top = pos.top - this.layerConfig.offset + "px";
17463        this.$gutterLineHighlight.style.height = height + "px";
17464    };
17465
17466    this.$updatePrintMargin = function() {
17467        if (!this.$showPrintMargin && !this.$printMarginEl)
17468            return;
17469
17470        if (!this.$printMarginEl) {
17471            var containerEl = dom.createElement("div");
17472            containerEl.className = "ace_layer ace_print-margin-layer";
17473            this.$printMarginEl = dom.createElement("div");
17474            this.$printMarginEl.className = "ace_print-margin";
17475            containerEl.appendChild(this.$printMarginEl);
17476            this.content.insertBefore(containerEl, this.content.firstChild);
17477        }
17478
17479        var style = this.$printMarginEl.style;
17480        style.left = Math.round(this.characterWidth * this.$printMarginColumn + this.$padding) + "px";
17481        style.visibility = this.$showPrintMargin ? "visible" : "hidden";
17482        
17483        if (this.session && this.session.$wrap == -1)
17484            this.adjustWrapLimit();
17485    };
17486    this.getContainerElement = function() {
17487        return this.container;
17488    };
17489    this.getMouseEventTarget = function() {
17490        return this.scroller;
17491    };
17492    this.getTextAreaContainer = function() {
17493        return this.container;
17494    };
17495    this.$moveTextAreaToCursor = function() {
17496        var style = this.textarea.style;
17497        if (!this.$keepTextAreaAtCursor) {
17498            style.left = -100 + "px";
17499            return;
17500        }
17501        var config = this.layerConfig;
17502        var posTop = this.$cursorLayer.$pixelPos.top;
17503        var posLeft = this.$cursorLayer.$pixelPos.left;
17504        posTop -= config.offset;
17505
17506        var h = this.lineHeight;
17507        if (posTop < 0 || posTop > config.height - h) {
17508            style.top = style.left = "0";
17509            return;
17510        }
17511
17512        var w = this.characterWidth;
17513        if (this.$composition) {
17514            var val = this.textarea.value.replace(/^\x01+/, "");
17515            w *= (this.session.$getStringScreenWidth(val)[0]+2);
17516            h += 2;
17517        }
17518        posLeft -= this.scrollLeft;
17519        if (posLeft > this.$size.scrollerWidth - w)
17520            posLeft = this.$size.scrollerWidth - w;
17521
17522        posLeft += this.gutterWidth;
17523        style.height = h + "px";
17524        style.width = w + "px";
17525        style.left = Math.min(posLeft, this.$size.scrollerWidth - w) + "px";
17526        style.top = Math.min(posTop, this.$size.height - h) + "px";
17527    };
17528    this.getFirstVisibleRow = function() {
17529        return this.layerConfig.firstRow;
17530    };
17531    this.getFirstFullyVisibleRow = function() {
17532        return this.layerConfig.firstRow + (this.layerConfig.offset === 0 ? 0 : 1);
17533    };
17534    this.getLastFullyVisibleRow = function() {
17535        var config = this.layerConfig;
17536        var lastRow = config.lastRow;
17537        var top = this.session.documentToScreenRow(lastRow, 0) * config.lineHeight;
17538        if (top - this.session.getScrollTop() > config.height - config.lineHeight)
17539            return lastRow - 1;
17540        return lastRow;
17541    };
17542    this.getLastVisibleRow = function() {
17543        return this.layerConfig.lastRow;
17544    };
17545
17546    this.$padding = null;
17547    this.setPadding = function(padding) {
17548        this.$padding = padding;
17549        this.$textLayer.setPadding(padding);
17550        this.$cursorLayer.setPadding(padding);
17551        this.$markerFront.setPadding(padding);
17552        this.$markerBack.setPadding(padding);
17553        this.$loop.schedule(this.CHANGE_FULL);
17554        this.$updatePrintMargin();
17555    };
17556    
17557    this.setScrollMargin = function(top, bottom, left, right) {
17558        var sm = this.scrollMargin;
17559        sm.top = top|0;
17560        sm.bottom = bottom|0;
17561        sm.right = right|0;
17562        sm.left = left|0;
17563        sm.v = sm.top + sm.bottom;
17564        sm.h = sm.left + sm.right;
17565        if (sm.top && this.scrollTop <= 0 && this.session)
17566            this.session.setScrollTop(-sm.top);
17567        this.updateFull();
17568    };
17569    this.getHScrollBarAlwaysVisible = function() {
17570        return this.$hScrollBarAlwaysVisible;
17571    };
17572    this.setHScrollBarAlwaysVisible = function(alwaysVisible) {
17573        this.setOption("hScrollBarAlwaysVisible", alwaysVisible);
17574    };
17575    this.getVScrollBarAlwaysVisible = function() {
17576        return this.$vScrollBarAlwaysVisible;
17577    };
17578    this.setVScrollBarAlwaysVisible = function(alwaysVisible) {
17579        this.setOption("vScrollBarAlwaysVisible", alwaysVisible);
17580    };
17581
17582    this.$updateScrollBarV = function() {
17583        var scrollHeight = this.layerConfig.maxHeight;
17584        var scrollerHeight = this.$size.scrollerHeight;
17585        if (!this.$maxLines && this.$scrollPastEnd) {
17586            scrollHeight -= (scrollerHeight - this.lineHeight) * this.$scrollPastEnd;
17587            if (this.scrollTop > scrollHeight - scrollerHeight) {
17588                scrollHeight = this.scrollTop + scrollerHeight;
17589                this.scrollBarV.scrollTop = null;
17590            }
17591        }
17592        this.scrollBarV.setScrollHeight(scrollHeight + this.scrollMargin.v);
17593        this.scrollBarV.setScrollTop(this.scrollTop + this.scrollMargin.top);
17594    };
17595    this.$updateScrollBarH = function() {
17596        this.scrollBarH.setScrollWidth(this.layerConfig.width + 2 * this.$padding + this.scrollMargin.h);
17597        this.scrollBarH.setScrollLeft(this.scrollLeft + this.scrollMargin.left);
17598    };
17599    
17600    this.$frozen = false;
17601    this.freeze = function() {
17602        this.$frozen = true;
17603    };
17604    
17605    this.unfreeze = function() {
17606        this.$frozen = false;
17607    };
17608
17609    this.$renderChanges = function(changes, force) {
17610        if (this.$changes) {
17611            changes |= this.$changes;
17612            this.$changes = 0;
17613        }
17614        if ((!this.session || !this.container.offsetWidth || this.$frozen) || (!changes && !force)) {
17615            this.$changes |= changes;
17616            return; 
17617        } 
17618        if (this.$size.$dirty) {
17619            this.$changes |= changes;
17620            return this.onResize(true);
17621        }
17622        if (!this.lineHeight) {
17623            this.$textLayer.checkForSizeChanges();
17624        }
17625        
17626        this._signal("beforeRender");
17627        
17628        if (this.session && this.session.$bidiHandler)
17629            this.session.$bidiHandler.updateCharacterWidths(this.$fontMetrics);
17630
17631        var config = this.layerConfig;
17632        if (changes & this.CHANGE_FULL ||
17633            changes & this.CHANGE_SIZE ||
17634            changes & this.CHANGE_TEXT ||
17635            changes & this.CHANGE_LINES ||
17636            changes & this.CHANGE_SCROLL ||
17637            changes & this.CHANGE_H_SCROLL
17638        ) {
17639            changes |= this.$computeLayerConfig();
17640            if (config.firstRow != this.layerConfig.firstRow && config.firstRowScreen == this.layerConfig.firstRowScreen) {
17641                var st = this.scrollTop + (config.firstRow - this.layerConfig.firstRow) * this.lineHeight;
17642                if (st > 0) {
17643                    this.scrollTop = st;
17644                    changes = changes | this.CHANGE_SCROLL;
17645                    changes |= this.$computeLayerConfig();
17646                }
17647            }
17648            config = this.layerConfig;
17649            this.$updateScrollBarV();
17650            if (changes & this.CHANGE_H_SCROLL)
17651                this.$updateScrollBarH();
17652            this.$gutterLayer.element.style.marginTop = (-config.offset) + "px";
17653            this.content.style.marginTop = (-config.offset) + "px";
17654            this.content.style.width = config.width + 2 * this.$padding + "px";
17655            this.content.style.height = config.minHeight + "px";
17656        }
17657        if (changes & this.CHANGE_H_SCROLL) {
17658            this.content.style.marginLeft = -this.scrollLeft + "px";
17659            this.scroller.className = this.scrollLeft <= 0 ? "ace_scroller" : "ace_scroller ace_scroll-left";
17660        }
17661        if (changes & this.CHANGE_FULL) {
17662            this.$textLayer.update(config);
17663            if (this.$showGutter)
17664                this.$gutterLayer.update(config);
17665            this.$markerBack.update(config);
17666            this.$markerFront.update(config);
17667            this.$cursorLayer.update(config);
17668            this.$moveTextAreaToCursor();
17669            this.$highlightGutterLine && this.$updateGutterLineHighlight();
17670            this._signal("afterRender");
17671            return;
17672        }
17673        if (changes & this.CHANGE_SCROLL) {
17674            if (changes & this.CHANGE_TEXT || changes & this.CHANGE_LINES)
17675                this.$textLayer.update(config);
17676            else
17677                this.$textLayer.scrollLines(config);
17678
17679            if (this.$showGutter)
17680                this.$gutterLayer.update(config);
17681            this.$markerBack.update(config);
17682            this.$markerFront.update(config);
17683            this.$cursorLayer.update(config);
17684            this.$highlightGutterLine && this.$updateGutterLineHighlight();
17685            this.$moveTextAreaToCursor();
17686            this._signal("afterRender");
17687            return;
17688        }
17689
17690        if (changes & this.CHANGE_TEXT) {
17691            this.$textLayer.update(config);
17692            if (this.$showGutter)
17693                this.$gutterLayer.update(config);
17694        }
17695        else if (changes & this.CHANGE_LINES) {
17696            if (this.$updateLines() || (changes & this.CHANGE_GUTTER) && this.$showGutter)
17697                this.$gutterLayer.update(config);
17698        }
17699        else if (changes & this.CHANGE_TEXT || changes & this.CHANGE_GUTTER) {
17700            if (this.$showGutter)
17701                this.$gutterLayer.update(config);
17702        }
17703
17704        if (changes & this.CHANGE_CURSOR) {
17705            this.$cursorLayer.update(config);
17706            this.$moveTextAreaToCursor();
17707            this.$highlightGutterLine && this.$updateGutterLineHighlight();
17708        }
17709
17710        if (changes & (this.CHANGE_MARKER | this.CHANGE_MARKER_FRONT)) {
17711            this.$markerFront.update(config);
17712        }
17713
17714        if (changes & (this.CHANGE_MARKER | this.CHANGE_MARKER_BACK)) {
17715            this.$markerBack.update(config);
17716        }
17717
17718        this._signal("afterRender");
17719    };
17720
17721    
17722    this.$autosize = function() {
17723        var height = this.session.getScreenLength() * this.lineHeight;
17724        var maxHeight = this.$maxLines * this.lineHeight;
17725        var desiredHeight = Math.min(maxHeight, 
17726            Math.max((this.$minLines || 1) * this.lineHeight, height)
17727        ) + this.scrollMargin.v + (this.$extraHeight || 0);
17728        if (this.$horizScroll)
17729            desiredHeight += this.scrollBarH.getHeight();
17730        if (this.$maxPixelHeight && desiredHeight > this.$maxPixelHeight)
17731            desiredHeight = this.$maxPixelHeight;
17732        var vScroll = height > maxHeight;
17733        
17734        if (desiredHeight != this.desiredHeight ||
17735            this.$size.height != this.desiredHeight || vScroll != this.$vScroll) {
17736            if (vScroll != this.$vScroll) {
17737                this.$vScroll = vScroll;
17738                this.scrollBarV.setVisible(vScroll);
17739            }
17740            
17741            var w = this.container.clientWidth;
17742            this.container.style.height = desiredHeight + "px";
17743            this.$updateCachedSize(true, this.$gutterWidth, w, desiredHeight);
17744            this.desiredHeight = desiredHeight;
17745            
17746            this._signal("autosize");
17747        }
17748    };
17749    
17750    this.$computeLayerConfig = function() {
17751        var session = this.session;
17752        var size = this.$size;
17753        
17754        var hideScrollbars = size.height <= 2 * this.lineHeight;
17755        var screenLines = this.session.getScreenLength();
17756        var maxHeight = screenLines * this.lineHeight;
17757
17758        var longestLine = this.$getLongestLine();
17759        
17760        var horizScroll = !hideScrollbars && (this.$hScrollBarAlwaysVisible ||
17761            size.scrollerWidth - longestLine - 2 * this.$padding < 0);
17762
17763        var hScrollChanged = this.$horizScroll !== horizScroll;
17764        if (hScrollChanged) {
17765            this.$horizScroll = horizScroll;
17766            this.scrollBarH.setVisible(horizScroll);
17767        }
17768        var vScrollBefore = this.$vScroll; // autosize can change vscroll value in which case we need to update longestLine
17769        if (this.$maxLines && this.lineHeight > 1)
17770            this.$autosize();
17771
17772        var offset = this.scrollTop % this.lineHeight;
17773        var minHeight = size.scrollerHeight + this.lineHeight;
17774        
17775        var scrollPastEnd = !this.$maxLines && this.$scrollPastEnd
17776            ? (size.scrollerHeight - this.lineHeight) * this.$scrollPastEnd
17777            : 0;
17778        maxHeight += scrollPastEnd;
17779        
17780        var sm = this.scrollMargin;
17781        this.session.setScrollTop(Math.max(-sm.top,
17782            Math.min(this.scrollTop, maxHeight - size.scrollerHeight + sm.bottom)));
17783
17784        this.session.setScrollLeft(Math.max(-sm.left, Math.min(this.scrollLeft, 
17785            longestLine + 2 * this.$padding - size.scrollerWidth + sm.right)));
17786        
17787        var vScroll = !hideScrollbars && (this.$vScrollBarAlwaysVisible ||
17788            size.scrollerHeight - maxHeight + scrollPastEnd < 0 || this.scrollTop > sm.top);
17789        var vScrollChanged = vScrollBefore !== vScroll;
17790        if (vScrollChanged) {
17791            this.$vScroll = vScroll;
17792            this.scrollBarV.setVisible(vScroll);
17793        }
17794
vendor: 4,118 bytes, lines 17795-17897
17795        var lineCount = Math.ceil(minHeight / this.lineHeight) - 1;
17796        var firstRow = Math.max(0, Math.round((this.scrollTop - offset) / this.lineHeight));
17797        var lastRow = firstRow + lineCount;
17798        var firstRowScreen, firstRowHeight;
17799        var lineHeight = this.lineHeight;
17800        firstRow = session.screenToDocumentRow(firstRow, 0);
17801        var foldLine = session.getFoldLine(firstRow);
17802        if (foldLine) {
17803            firstRow = foldLine.start.row;
17804        }
17805
17806        firstRowScreen = session.documentToScreenRow(firstRow, 0);
17807        firstRowHeight = session.getRowLength(firstRow) * lineHeight;
17808
17809        lastRow = Math.min(session.screenToDocumentRow(lastRow, 0), session.getLength() - 1);
17810        minHeight = size.scrollerHeight + session.getRowLength(lastRow) * lineHeight +
17811                                                firstRowHeight;
17812
17813        offset = this.scrollTop - firstRowScreen * lineHeight;
17814
17815        var changes = 0;
17816        if (this.layerConfig.width != longestLine || hScrollChanged) 
17817            changes = this.CHANGE_H_SCROLL;
17818        if (hScrollChanged || vScrollChanged) {
17819            changes = this.$updateCachedSize(true, this.gutterWidth, size.width, size.height);
17820            this._signal("scrollbarVisibilityChanged");
17821            if (vScrollChanged)
17822                longestLine = this.$getLongestLine();
17823        }
17824        
17825        this.layerConfig = {
17826            width : longestLine,
17827            padding : this.$padding,
17828            firstRow : firstRow,
17829            firstRowScreen: firstRowScreen,
17830            lastRow : lastRow,
17831            lineHeight : lineHeight,
17832            characterWidth : this.characterWidth,
17833            minHeight : minHeight,
17834            maxHeight : maxHeight,
17835            offset : offset,
17836            gutterOffset : lineHeight ? Math.max(0, Math.ceil((offset + size.height - size.scrollerHeight) / lineHeight)) : 0,
17837            height : this.$size.scrollerHeight
17838        };
17839
17840        return changes;
17841    };
17842
17843    this.$updateLines = function() {
17844        if (!this.$changedLines) return;
17845        var firstRow = this.$changedLines.firstRow;
17846        var lastRow = this.$changedLines.lastRow;
17847        this.$changedLines = null;
17848
17849        var layerConfig = this.layerConfig;
17850
17851        if (firstRow > layerConfig.lastRow + 1) { return; }
17852        if (lastRow < layerConfig.firstRow) { return; }
17853        if (lastRow === Infinity) {
17854            if (this.$showGutter)
17855                this.$gutterLayer.update(layerConfig);
17856            this.$textLayer.update(layerConfig);
17857            return;
17858        }
17859        this.$textLayer.updateLines(layerConfig, firstRow, lastRow);
17860        return true;
17861    };
17862
17863    this.$getLongestLine = function() {
17864        var charCount = this.session.getScreenWidth();
17865        if (this.showInvisibles && !this.session.$useWrapMode)
17866            charCount += 1;
17867            
17868        if (this.$textLayer && charCount > this.$textLayer.MAX_LINE_LENGTH)
17869            charCount = this.$textLayer.MAX_LINE_LENGTH + 30;
17870
17871        return Math.max(this.$size.scrollerWidth - 2 * this.$padding, Math.round(charCount * this.characterWidth));
17872    };
17873    this.updateFrontMarkers = function() {
17874        this.$markerFront.setMarkers(this.session.getMarkers(true));
17875        this.$loop.schedule(this.CHANGE_MARKER_FRONT);
17876    };
17877    this.updateBackMarkers = function() {
17878        this.$markerBack.setMarkers(this.session.getMarkers());
17879        this.$loop.schedule(this.CHANGE_MARKER_BACK);
17880    };
17881    this.addGutterDecoration = function(row, className){
17882        this.$gutterLayer.addGutterDecoration(row, className);
17883    };
17884    this.removeGutterDecoration = function(row, className){
17885        this.$gutterLayer.removeGutterDecoration(row, className);
17886    };
17887    this.updateBreakpoints = function(rows) {
17888        this.$loop.schedule(this.CHANGE_GUTTER);
17889    };
17890    this.setAnnotations = function(annotations) {
17891        this.$gutterLayer.setAnnotations(annotations);
17892        this.$loop.schedule(this.CHANGE_GUTTER);
17893    };
17894    this.updateCursor = function() {
17895        this.$loop.schedule(this.CHANGE_CURSOR);
17896    };
17897    this.hideCursor = function() {
17898        this.$cursorLayer.hideCursor();
17899    };
17900    this.showCursor = function() {
17901        this.$cursorLayer.showCursor();
17902    };
17903
17904    this.scrollSelectionIntoView = function(anchor, lead, offset) {
17905        this.scrollCursorIntoView(anchor, offset);
17906        this.scrollCursorIntoView(lead, offset);
17907    };
17908    this.scrollCursorIntoView = function(cursor, offset, $viewMargin) {
17909        if (this.$size.scrollerHeight === 0)
17910            return;
17911
17912        var pos = this.$cursorLayer.getPixelPosition(cursor);
17913
17914        var left = pos.left;
17915        var top = pos.top;
17916        
17917        var topMargin = $viewMargin && $viewMargin.top || 0;
17918        var bottomMargin = $viewMargin && $viewMargin.bottom || 0;
17919        
17920        var scrollTop = this.$scrollAnimation ? this.session.getScrollTop() : this.scrollTop;
17921        
17922        if (scrollTop + topMargin > top) {
17923            if (offset && scrollTop + topMargin > top + this.lineHeight)
17924                top -= offset * this.$size.scrollerHeight;
17925            if (top === 0)
17926                top = -this.scrollMargin.top;
17927            this.session.setScrollTop(top);
17928        } else if (scrollTop + this.$size.scrollerHeight - bottomMargin < top + this.lineHeight) {
17929            if (offset && scrollTop + this.$size.scrollerHeight - bottomMargin < top -  this.lineHeight)
17930                top += offset * this.$size.scrollerHeight;
17931            this.session.setScrollTop(top + this.lineHeight - this.$size.scrollerHeight);
17932        }
17933
17934        var scrollLeft = this.scrollLeft;
17935
17936        if (scrollLeft > left) {
17937            if (left < this.$padding + 2 * this.layerConfig.characterWidth)
17938                left = -this.scrollMargin.left;
17939            this.session.setScrollLeft(left);
17940        } else if (scrollLeft + this.$size.scrollerWidth < left + this.characterWidth) {
17941            this.session.setScrollLeft(Math.round(left + this.characterWidth - this.$size.scrollerWidth));
17942        } else if (scrollLeft <= this.$padding && left - scrollLeft < this.characterWidth) {
17943            this.session.setScrollLeft(0);
17944        }
17945    };
17946    this.getScrollTop = function() {
17947        return this.session.getScrollTop();
17948    };
17949    this.getScrollLeft = function() {
17950        return this.session.getScrollLeft();
17951    };
17952    this.getScrollTopRow = function() {
17953        return this.scrollTop / this.lineHeight;
17954    };
17955    this.getScrollBottomRow = function() {
17956        return Math.max(0, Math.floor((this.scrollTop + this.$size.scrollerHeight) / this.lineHeight) - 1);
17957    };
17958    this.scrollToRow = function(row) {
17959        this.session.setScrollTop(row * this.lineHeight);
17960    };
17961
17962    this.alignCursor = function(cursor, alignment) {
17963        if (typeof cursor == "number")
17964            cursor = {row: cursor, column: 0};
17965
17966        var pos = this.$cursorLayer.getPixelPosition(cursor);
17967        var h = this.$size.scrollerHeight - this.lineHeight;
17968        var offset = pos.top - h * (alignment || 0);
17969
17970        this.session.setScrollTop(offset);
17971        return offset;
17972    };
17973
17974    this.STEPS = 8;
17975    this.$calcSteps = function(fromValue, toValue){
17976        var i = 0;
17977        var l = this.STEPS;
17978        var steps = [];
17979
17980        var func  = function(t, x_min, dx) {
17981            return dx * (Math.pow(t - 1, 3) + 1) + x_min;
17982        };
17983
17984        for (i = 0; i < l; ++i)
17985            steps.push(func(i / this.STEPS, fromValue, toValue - fromValue));
17986
17987        return steps;
17988    };
17989    this.scrollToLine = function(line, center, animate, callback) {
17990        var pos = this.$cursorLayer.getPixelPosition({row: line, column: 0});
17991        var offset = pos.top;
17992        if (center)
17993            offset -= this.$size.scrollerHeight / 2;
17994
17995        var initialScroll = this.scrollTop;
17996        this.session.setScrollTop(offset);
17997        if (animate !== false)
17998            this.animateScrolling(initialScroll, callback);
17999    };
18000
18001    this.animateScrolling = function(fromValue, callback) {
18002        var toValue = this.scrollTop;
18003        if (!this.$animatedScroll)
18004            return;
18005        var _self = this;
18006        
18007        if (fromValue == toValue)
18008            return;
18009        
18010        if (this.$scrollAnimation) {
18011            var oldSteps = this.$scrollAnimation.steps;
18012            if (oldSteps.length) {
18013                fromValue = oldSteps[0];
18014                if (fromValue == toValue)
18015                    return;
18016            }
18017        }
18018        
18019        var steps = _self.$calcSteps(fromValue, toValue);
18020        this.$scrollAnimation = {from: fromValue, to: toValue, steps: steps};
18021
18022        clearInterval(this.$timer);
18023
18024        _self.session.setScrollTop(steps.shift());
18025        _self.session.$scrollTop = toValue;
18026        this.$timer = setInterval(function() {
18027            if (steps.length) {
18028                _self.session.setScrollTop(steps.shift());
18029                _self.session.$scrollTop = toValue;
18030            } else if (toValue != null) {
18031                _self.session.$scrollTop = -1;
18032                _self.session.setScrollTop(toValue);
18033                toValue = null;
18034            } else {
18035                _self.$timer = clearInterval(_self.$timer);
18036                _self.$scrollAnimation = null;
18037                callback && callback();
18038            }
18039        }, 10);
18040    };
18041    this.scrollToY = function(scrollTop) {
18042        if (this.scrollTop !== scrollTop) {
18043            this.$loop.schedule(this.CHANGE_SCROLL);
18044            this.scrollTop = scrollTop;
18045        }
18046    };
18047    this.scrollToX = function(scrollLeft) {
18048        if (this.scrollLeft !== scrollLeft)
18049            this.scrollLeft = scrollLeft;
18050        this.$loop.schedule(this.CHANGE_H_SCROLL);
18051    };
18052    this.scrollTo = function(x, y) {
18053        this.session.setScrollTop(y);
18054        this.session.setScrollLeft(y);
18055    };
18056    this.scrollBy = function(deltaX, deltaY) {
18057        deltaY && this.session.setScrollTop(this.session.getScrollTop() + deltaY);
18058        deltaX && this.session.setScrollLeft(this.session.getScrollLeft() + deltaX);
18059    };
18060    this.isScrollableBy = function(deltaX, deltaY) {
18061        if (deltaY < 0 && this.session.getScrollTop() >= 1 - this.scrollMargin.top)
18062           return true;
18063        if (deltaY > 0 && this.session.getScrollTop() + this.$size.scrollerHeight
18064            - this.layerConfig.maxHeight < -1 + this.scrollMargin.bottom)
18065           return true;
18066        if (deltaX < 0 && this.session.getScrollLeft() >= 1 - this.scrollMargin.left)
18067            return true;
18068        if (deltaX > 0 && this.session.getScrollLeft() + this.$size.scrollerWidth
18069            - this.layerConfig.width < -1 + this.scrollMargin.right)
18070           return true;
18071    };
18072
18073    this.pixelToScreenCoordinates = function(x, y) {
18074        var canvasPos = this.scroller.getBoundingClientRect();
18075
18076        var offsetX = x + this.scrollLeft - canvasPos.left - this.$padding;
18077        var offset = offsetX / this.characterWidth;
18078        var row = Math.floor((y + this.scrollTop - canvasPos.top) / this.lineHeight);
18079        var col = Math.round(offset);
18080
18081        return {row: row, column: col, side: offset - col > 0 ? 1 : -1, offsetX:  offsetX};
18082    };
18083
18084    this.screenToTextCoordinates = function(x, y) {
18085        var canvasPos = this.scroller.getBoundingClientRect();
18086        var offsetX = x + this.scrollLeft - canvasPos.left - this.$padding;
18087        
18088        var col = Math.round(offsetX / this.characterWidth);
18089
18090        var row = (y + this.scrollTop - canvasPos.top) / this.lineHeight;
18091
18092        return this.session.screenToDocumentPosition(row, Math.max(col, 0), offsetX);
18093    };
18094    this.textToScreenCoordinates = function(row, column) {
18095        var canvasPos = this.scroller.getBoundingClientRect();
18096        var pos = this.session.documentToScreenPosition(row, column);
18097
18098        var x = this.$padding + (this.session.$bidiHandler.isBidiRow(pos.row, row)
18099             ? this.session.$bidiHandler.getPosLeft(pos.column)
18100             : Math.round(pos.column * this.characterWidth));
18101        
18102        var y = pos.row * this.lineHeight;
18103
18104        return {
18105            pageX: canvasPos.left + x - this.scrollLeft,
18106            pageY: canvasPos.top + y - this.scrollTop
18107        };
18108    };
18109    this.visualizeFocus = function() {
18110        dom.addCssClass(this.container, "ace_focus");
18111    };
18112    this.visualizeBlur = function() {
18113        dom.removeCssClass(this.container, "ace_focus");
18114    };
18115    this.showComposition = function(position) {
18116        if (!this.$composition)
18117            this.$composition = {
18118                keepTextAreaAtCursor: this.$keepTextAreaAtCursor,
18119                cssText: this.textarea.style.cssText
18120            };
18121
18122        this.$keepTextAreaAtCursor = true;
18123        dom.addCssClass(this.textarea, "ace_composition");
18124        this.textarea.style.cssText = "";
18125        this.$moveTextAreaToCursor();
18126    };
18127    this.setCompositionText = function(text) {
18128        this.$moveTextAreaToCursor();
18129    };
18130    this.hideComposition = function() {
18131        if (!this.$composition)
18132            return;
18133
18134        dom.removeCssClass(this.textarea, "ace_composition");
18135        this.$keepTextAreaAtCursor = this.$composition.keepTextAreaAtCursor;
18136        this.textarea.style.cssText = this.$composition.cssText;
18137        this.$composition = null;
18138    };
18139    this.setTheme = function(theme, cb) {
18140        var _self = this;
18141        this.$themeId = theme;
18142        _self._dispatchEvent('themeChange',{theme:theme});
18143
18144        if (!theme || typeof theme == "string") {
18145            var moduleName = theme || this.$options.theme.initialValue;
18146            config.loadModule(["theme", moduleName], afterLoad);
18147        } else {
18148            afterLoad(theme);
18149        }
18150
18151        function afterLoad(module) {
18152            if (_self.$themeId != theme)
18153                return cb && cb();
18154            if (!module || !module.cssClass)
18155                throw new Error("couldn't load module " + theme + " or it didn't call define");
18156            if (module.$id)
18157                _self.$themeId = module.$id;
18158            dom.importCssString(
18159                module.cssText,
18160                module.cssClass,
18161                _self.container.ownerDocument
18162            );
18163
18164            if (_self.theme)
18165                dom.removeCssClass(_self.container, _self.theme.cssClass);
18166
18167            var padding = "padding" in module ? module.padding 
18168                : "padding" in (_self.theme || {}) ? 4 : _self.$padding;
18169            if (_self.$padding && padding != _self.$padding)
18170                _self.setPadding(padding);
18171            _self.$theme = module.cssClass;
18172
18173            _self.theme = module;
18174            dom.addCssClass(_self.container, module.cssClass);
18175            dom.setCssClass(_self.container, "ace_dark", module.isDark);
18176            if (_self.$size) {
18177                _self.$size.width = 0;
18178                _self.$updateSizeAsync();
18179            }
18180
18181            _self._dispatchEvent('themeLoaded', {theme:module});
18182            cb && cb();
18183        }
18184    };
18185    this.getTheme = function() {
18186        return this.$themeId;
18187    };
18188    this.setStyle = function(style, include) {
18189        dom.setCssClass(this.container, style, include !== false);
18190    };
18191    this.unsetStyle = function(style) {
18192        dom.removeCssClass(this.container, style);
18193    };
18194    
18195    this.setCursorStyle = function(style) {
18196        if (this.scroller.style.cursor != style)
18197            this.scroller.style.cursor = style;
18198    };
18199    this.setMouseCursor = function(cursorStyle) {
18200        this.scroller.style.cursor = cursorStyle;
18201    };
18202    this.destroy = function() {
18203        this.$textLayer.destroy();
18204        this.$cursorLayer.destroy();
18205    };
18206
18207}).call(VirtualRenderer.prototype);
18208
18209
18210config.defineOptions(VirtualRenderer.prototype, "renderer", {
18211    animatedScroll: {initialValue: false},
18212    showInvisibles: {
18213        set: function(value) {
18214            if (this.$textLayer.setShowInvisibles(value))
18215                this.$loop.schedule(this.CHANGE_TEXT);
18216        },
18217        initialValue: false
18218    },
18219    showPrintMargin: {
18220        set: function() { this.$updatePrintMargin(); },
18221        initialValue: true
18222    },
18223    printMarginColumn: {
18224        set: function() { this.$updatePrintMargin(); },
18225        initialValue: 80
18226    },
18227    printMargin: {
18228        set: function(val) {
18229            if (typeof val == "number")
18230                this.$printMarginColumn = val;
18231            this.$showPrintMargin = !!val;
18232            this.$updatePrintMargin();
18233        },
18234        get: function() {
18235            return this.$showPrintMargin && this.$printMarginColumn; 
18236        }
18237    },
18238    showGutter: {
18239        set: function(show){
18240            this.$gutter.style.display = show ? "block" : "none";
18241            this.$loop.schedule(this.CHANGE_FULL);
18242            this.onGutterResize();
18243        },
18244        initialValue: true
18245    },
18246    fadeFoldWidgets: {
18247        set: function(show) {
18248            dom.setCssClass(this.$gutter, "ace_fade-fold-widgets", show);
18249        },
18250        initialValue: false
18251    },
18252    showFoldWidgets: {
18253        set: function(show) {this.$gutterLayer.setShowFoldWidgets(show);},
18254        initialValue: true
18255    },
18256    showLineNumbers: {
18257        set: function(show) {
18258            this.$gutterLayer.setShowLineNumbers(show);
18259            this.$loop.schedule(this.CHANGE_GUTTER);
18260        },
18261        initialValue: true
18262    },
18263    displayIndentGuides: {
18264        set: function(show) {
18265            if (this.$textLayer.setDisplayIndentGuides(show))
18266                this.$loop.schedule(this.CHANGE_TEXT);
18267        },
18268        initialValue: true
18269    },
18270    highlightGutterLine: {
18271        set: function(shouldHighlight) {
18272            if (!this.$gutterLineHighlight) {
18273                this.$gutterLineHighlight = dom.createElement("div");
18274                this.$gutterLineHighlight.className = "ace_gutter-active-line";
18275                this.$gutter.appendChild(this.$gutterLineHighlight);
18276                return;
18277            }
18278
18279            this.$gutterLineHighlight.style.display = shouldHighlight ? "" : "none";
vendor: 27,777 bytes, lines 18280-19111
18280            if (this.$cursorLayer.$pixelPos)
18281                this.$updateGutterLineHighlight();
18282        },
18283        initialValue: false,
18284        value: true
18285    },
18286    hScrollBarAlwaysVisible: {
18287        set: function(val) {
18288            if (!this.$hScrollBarAlwaysVisible || !this.$horizScroll)
18289                this.$loop.schedule(this.CHANGE_SCROLL);
18290        },
18291        initialValue: false
18292    },
18293    vScrollBarAlwaysVisible: {
18294        set: function(val) {
18295            if (!this.$vScrollBarAlwaysVisible || !this.$vScroll)
18296                this.$loop.schedule(this.CHANGE_SCROLL);
18297        },
18298        initialValue: false
18299    },
18300    fontSize:  {
18301        set: function(size) {
18302            if (typeof size == "number")
18303                size = size + "px";
18304            this.container.style.fontSize = size;
18305            this.updateFontSize();
18306        },
18307        initialValue: 12
18308    },
18309    fontFamily: {
18310        set: function(name) {
18311            this.container.style.fontFamily = name;
18312            this.updateFontSize();
18313        }
18314    },
18315    maxLines: {
18316        set: function(val) {
18317            this.updateFull();
18318        }
18319    },
18320    minLines: {
18321        set: function(val) {
18322            this.updateFull();
18323        }
18324    },
18325    maxPixelHeight: {
18326        set: function(val) {
18327            this.updateFull();
18328        },
18329        initialValue: 0
18330    },
18331    scrollPastEnd: {
18332        set: function(val) {
18333            val = +val || 0;
18334            if (this.$scrollPastEnd == val)
18335                return;
18336            this.$scrollPastEnd = val;
18337            this.$loop.schedule(this.CHANGE_SCROLL);
18338        },
18339        initialValue: 0,
18340        handlesSet: true
18341    },
18342    fixedWidthGutter: {
18343        set: function(val) {
18344            this.$gutterLayer.$fixedWidth = !!val;
18345            this.$loop.schedule(this.CHANGE_GUTTER);
18346        }
18347    },
18348    theme: {
18349        set: function(val) { this.setTheme(val); },
18350        get: function() { return this.$themeId || this.theme; },
18351        initialValue: "./theme/textmate",
18352        handlesSet: true
18353    }
18354});
18355
18356exports.VirtualRenderer = VirtualRenderer;
18357});
18358
18359define("ace/worker/worker_client",["require","exports","module","ace/lib/oop","ace/lib/net","ace/lib/event_emitter","ace/config"], function(require, exports, module) {
18360"use strict";
18361
18362var oop = require("../lib/oop");
18363var net = require("../lib/net");
18364var EventEmitter = require("../lib/event_emitter").EventEmitter;
18365var config = require("../config");
18366
18367function $workerBlob(workerUrl) {
18368    var script = "importScripts('" + net.qualifyURL(workerUrl) + "');";
18369    try {
18370        return new Blob([script], {"type": "application/javascript"});
18371    } catch (e) { // Backwards-compatibility
18372        var BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder;
18373        var blobBuilder = new BlobBuilder();
18374        blobBuilder.append(script);
18375        return blobBuilder.getBlob("application/javascript");
18376    }
18377}
18378
18379function createWorker(workerUrl) {
18380    if (typeof Worker == "undefined")
18381        return { postMessage: function() {}, terminate: function() {} };
18382    var blob = $workerBlob(workerUrl);
18383    var URL = window.URL || window.webkitURL;
18384    var blobURL = URL.createObjectURL(blob);
18385    return new Worker(blobURL);
18386}
18387
18388var WorkerClient = function(topLevelNamespaces, mod, classname, workerUrl, importScripts) {
18389    this.$sendDeltaQueue = this.$sendDeltaQueue.bind(this);
18390    this.changeListener = this.changeListener.bind(this);
18391    this.onMessage = this.onMessage.bind(this);
18392    if (require.nameToUrl && !require.toUrl)
18393        require.toUrl = require.nameToUrl;
18394    
18395    if (config.get("packaged") || !require.toUrl) {
18396        workerUrl = workerUrl || config.moduleUrl(mod, "worker");
18397    } else {
18398        var normalizePath = this.$normalizePath;
18399        workerUrl = workerUrl || normalizePath(require.toUrl("ace/worker/worker.js", null, "_"));
18400
18401        var tlns = {};
18402        topLevelNamespaces.forEach(function(ns) {
18403            tlns[ns] = normalizePath(require.toUrl(ns, null, "_").replace(/(\.js)?(\?.*)?$/, ""));
18404        });
18405    }
18406
18407    this.$worker = createWorker(workerUrl);
18408    if (importScripts) {
18409        this.send("importScripts", importScripts);
18410    }
18411    this.$worker.postMessage({
18412        init : true,
18413        tlns : tlns,
18414        module : mod,
18415        classname : classname
18416    });
18417
18418    this.callbackId = 1;
18419    this.callbacks = {};
18420
18421    this.$worker.onmessage = this.onMessage;
18422};
18423
18424(function(){
18425
18426    oop.implement(this, EventEmitter);
18427
18428    this.onMessage = function(e) {
18429        var msg = e.data;
18430        switch (msg.type) {
18431            case "event":
18432                this._signal(msg.name, {data: msg.data});
18433                break;
18434            case "call":
18435                var callback = this.callbacks[msg.id];
18436                if (callback) {
18437                    callback(msg.data);
18438                    delete this.callbacks[msg.id];
18439                }
18440                break;
18441            case "error":
18442                this.reportError(msg.data);
18443                break;
18444            case "log":
18445                window.console && console.log && console.log.apply(console, msg.data);
18446                break;
18447        }
18448    };
18449    
18450    this.reportError = function(err) {
18451        window.console && console.error && console.error(err);
18452    };
18453
18454    this.$normalizePath = function(path) {
18455        return net.qualifyURL(path);
18456    };
18457
18458    this.terminate = function() {
18459        this._signal("terminate", {});
18460        this.deltaQueue = null;
18461        this.$worker.terminate();
18462        this.$worker = null;
18463        if (this.$doc)
18464            this.$doc.off("change", this.changeListener);
18465        this.$doc = null;
18466    };
18467
18468    this.send = function(cmd, args) {
18469        this.$worker.postMessage({command: cmd, args: args});
18470    };
18471
18472    this.call = function(cmd, args, callback) {
18473        if (callback) {
18474            var id = this.callbackId++;
18475            this.callbacks[id] = callback;
18476            args.push(id);
18477        }
18478        this.send(cmd, args);
18479    };
18480
18481    this.emit = function(event, data) {
18482        try {
18483            this.$worker.postMessage({event: event, data: {data: data.data}});
18484        }
18485        catch(ex) {
18486            console.error(ex.stack);
18487        }
18488    };
18489
18490    this.attachToDocument = function(doc) {
18491        if (this.$doc)
18492            this.terminate();
18493
18494        this.$doc = doc;
18495        this.call("setValue", [doc.getValue()]);
18496        doc.on("change", this.changeListener);
18497    };
18498
18499    this.changeListener = function(delta) {
18500        if (!this.deltaQueue) {
18501            this.deltaQueue = [];
18502            setTimeout(this.$sendDeltaQueue, 0);
18503        }
18504        if (delta.action == "insert")
18505            this.deltaQueue.push(delta.start, delta.lines);
18506        else
18507            this.deltaQueue.push(delta.start, delta.end);
18508    };
18509
18510    this.$sendDeltaQueue = function() {
18511        var q = this.deltaQueue;
18512        if (!q) return;
18513        this.deltaQueue = null;
18514        if (q.length > 50 && q.length > this.$doc.getLength() >> 1) {
18515            this.call("setValue", [this.$doc.getValue()]);
18516        } else
18517            this.emit("change", {data: q});
18518    };
18519
18520}).call(WorkerClient.prototype);
18521
18522
18523var UIWorkerClient = function(topLevelNamespaces, mod, classname) {
18524    this.$sendDeltaQueue = this.$sendDeltaQueue.bind(this);
18525    this.changeListener = this.changeListener.bind(this);
18526    this.callbackId = 1;
18527    this.callbacks = {};
18528    this.messageBuffer = [];
18529
18530    var main = null;
18531    var emitSync = false;
18532    var sender = Object.create(EventEmitter);
18533    var _self = this;
18534
18535    this.$worker = {};
18536    this.$worker.terminate = function() {};
18537    this.$worker.postMessage = function(e) {
18538        _self.messageBuffer.push(e);
18539        if (main) {
18540            if (emitSync)
18541                setTimeout(processNext);
18542            else
18543                processNext();
18544        }
18545    };
18546    this.setEmitSync = function(val) { emitSync = val; };
18547
18548    var processNext = function() {
18549        var msg = _self.messageBuffer.shift();
18550        if (msg.command)
18551            main[msg.command].apply(main, msg.args);
18552        else if (msg.event)
18553            sender._signal(msg.event, msg.data);
18554    };
18555
18556    sender.postMessage = function(msg) {
18557        _self.onMessage({data: msg});
18558    };
18559    sender.callback = function(data, callbackId) {
18560        this.postMessage({type: "call", id: callbackId, data: data});
18561    };
18562    sender.emit = function(name, data) {
18563        this.postMessage({type: "event", name: name, data: data});
18564    };
18565
18566    config.loadModule(["worker", mod], function(Main) {
18567        main = new Main[classname](sender);
18568        while (_self.messageBuffer.length)
18569            processNext();
18570    });
18571};
18572
18573UIWorkerClient.prototype = WorkerClient.prototype;
18574
18575exports.UIWorkerClient = UIWorkerClient;
18576exports.WorkerClient = WorkerClient;
18577exports.createWorker = createWorker;
18578
18579
18580});
18581
18582define("ace/placeholder",["require","exports","module","ace/range","ace/lib/event_emitter","ace/lib/oop"], function(require, exports, module) {
18583"use strict";
18584
18585var Range = require("./range").Range;
18586var EventEmitter = require("./lib/event_emitter").EventEmitter;
18587var oop = require("./lib/oop");
18588
18589var PlaceHolder = function(session, length, pos, others, mainClass, othersClass) {
18590    var _self = this;
18591    this.length = length;
18592    this.session = session;
18593    this.doc = session.getDocument();
18594    this.mainClass = mainClass;
18595    this.othersClass = othersClass;
18596    this.$onUpdate = this.onUpdate.bind(this);
18597    this.doc.on("change", this.$onUpdate);
18598    this.$others = others;
18599    
18600    this.$onCursorChange = function() {
18601        setTimeout(function() {
18602            _self.onCursorChange();
18603        });
18604    };
18605    
18606    this.$pos = pos;
18607    var undoStack = session.getUndoManager().$undoStack || session.getUndoManager().$undostack || {length: -1};
18608    this.$undoStackDepth = undoStack.length;
18609    this.setup();
18610
18611    session.selection.on("changeCursor", this.$onCursorChange);
18612};
18613
18614(function() {
18615
18616    oop.implement(this, EventEmitter);
18617    this.setup = function() {
18618        var _self = this;
18619        var doc = this.doc;
18620        var session = this.session;
18621        
18622        this.selectionBefore = session.selection.toJSON();
18623        if (session.selection.inMultiSelectMode)
18624            session.selection.toSingleRange();
18625
18626        this.pos = doc.createAnchor(this.$pos.row, this.$pos.column);
18627        var pos = this.pos;
18628        pos.$insertRight = true;
18629        pos.detach();
18630        pos.markerId = session.addMarker(new Range(pos.row, pos.column, pos.row, pos.column + this.length), this.mainClass, null, false);
18631        this.others = [];
18632        this.$others.forEach(function(other) {
18633            var anchor = doc.createAnchor(other.row, other.column);
18634            anchor.$insertRight = true;
18635            anchor.detach();
18636            _self.others.push(anchor);
18637        });
18638        session.setUndoSelect(false);
18639    };
18640    this.showOtherMarkers = function() {
18641        if (this.othersActive) return;
18642        var session = this.session;
18643        var _self = this;
18644        this.othersActive = true;
18645        this.others.forEach(function(anchor) {
18646            anchor.markerId = session.addMarker(new Range(anchor.row, anchor.column, anchor.row, anchor.column+_self.length), _self.othersClass, null, false);
18647        });
18648    };
18649    this.hideOtherMarkers = function() {
18650        if (!this.othersActive) return;
18651        this.othersActive = false;
18652        for (var i = 0; i < this.others.length; i++) {
18653            this.session.removeMarker(this.others[i].markerId);
18654        }
18655    };
18656    this.onUpdate = function(delta) {
18657        if (this.$updating)
18658            return this.updateAnchors(delta);
18659            
18660        var range = delta;
18661        if (range.start.row !== range.end.row) return;
18662        if (range.start.row !== this.pos.row) return;
18663        this.$updating = true;
18664        var lengthDiff = delta.action === "insert" ? range.end.column - range.start.column : range.start.column - range.end.column;
18665        var inMainRange = range.start.column >= this.pos.column && range.start.column <= this.pos.column + this.length + 1;
18666        var distanceFromStart = range.start.column - this.pos.column;
18667        
18668        this.updateAnchors(delta);
18669        
18670        if (inMainRange)
18671            this.length += lengthDiff;
18672
18673        if (inMainRange && !this.session.$fromUndo) {
18674            if (delta.action === 'insert') {
18675                for (var i = this.others.length - 1; i >= 0; i--) {
18676                    var otherPos = this.others[i];
18677                    var newPos = {row: otherPos.row, column: otherPos.column + distanceFromStart};
18678                    this.doc.insertMergedLines(newPos, delta.lines);
18679                }
18680            } else if (delta.action === 'remove') {
18681                for (var i = this.others.length - 1; i >= 0; i--) {
18682                    var otherPos = this.others[i];
18683                    var newPos = {row: otherPos.row, column: otherPos.column + distanceFromStart};
18684                    this.doc.remove(new Range(newPos.row, newPos.column, newPos.row, newPos.column - lengthDiff));
18685                }
18686            }
18687        }
18688        
18689        this.$updating = false;
18690        this.updateMarkers();
18691    };
18692    
18693    this.updateAnchors = function(delta) {
18694        this.pos.onChange(delta);
18695        for (var i = this.others.length; i--;)
18696            this.others[i].onChange(delta);
18697        this.updateMarkers();
18698    };
18699    
18700    this.updateMarkers = function() {
18701        if (this.$updating)
18702            return;
18703        var _self = this;
18704        var session = this.session;
18705        var updateMarker = function(pos, className) {
18706            session.removeMarker(pos.markerId);
18707            pos.markerId = session.addMarker(new Range(pos.row, pos.column, pos.row, pos.column+_self.length), className, null, false);
18708        };
18709        updateMarker(this.pos, this.mainClass);
18710        for (var i = this.others.length; i--;)
18711            updateMarker(this.others[i], this.othersClass);
18712    };
18713
18714    this.onCursorChange = function(event) {
18715        if (this.$updating || !this.session) return;
18716        var pos = this.session.selection.getCursor();
18717        if (pos.row === this.pos.row && pos.column >= this.pos.column && pos.column <= this.pos.column + this.length) {
18718            this.showOtherMarkers();
18719            this._emit("cursorEnter", event);
18720        } else {
18721            this.hideOtherMarkers();
18722            this._emit("cursorLeave", event);
18723        }
18724    };    
18725    this.detach = function() {
18726        this.session.removeMarker(this.pos && this.pos.markerId);
18727        this.hideOtherMarkers();
18728        this.doc.removeEventListener("change", this.$onUpdate);
18729        this.session.selection.removeEventListener("changeCursor", this.$onCursorChange);
18730        this.session.setUndoSelect(true);
18731        this.session = null;
18732    };
18733    this.cancel = function() {
18734        if (this.$undoStackDepth === -1)
18735            return;
18736        var undoManager = this.session.getUndoManager();
18737        var undosRequired = (undoManager.$undoStack || undoManager.$undostack).length - this.$undoStackDepth;
18738        for (var i = 0; i < undosRequired; i++) {
18739            undoManager.undo(this.session, true);
18740        }
18741        if (this.selectionBefore)
18742            this.session.selection.fromJSON(this.selectionBefore);
18743    };
18744}).call(PlaceHolder.prototype);
18745
18746
18747exports.PlaceHolder = PlaceHolder;
18748});
18749
18750define("ace/mouse/multi_select_handler",["require","exports","module","ace/lib/event","ace/lib/useragent"], function(require, exports, module) {
18751
18752var event = require("../lib/event");
18753var useragent = require("../lib/useragent");
18754function isSamePoint(p1, p2) {
18755    return p1.row == p2.row && p1.column == p2.column;
18756}
18757
18758function onMouseDown(e) {
18759    var ev = e.domEvent;
18760    var alt = ev.altKey;
18761    var shift = ev.shiftKey;
18762    var ctrl = ev.ctrlKey;
18763    var accel = e.getAccelKey();
18764    var button = e.getButton();
18765    
18766    if (ctrl && useragent.isMac)
18767        button = ev.button;
18768
18769    if (e.editor.inMultiSelectMode && button == 2) {
18770        e.editor.textInput.onContextMenu(e.domEvent);
18771        return;
18772    }
18773    
18774    if (!ctrl && !alt && !accel) {
18775        if (button === 0 && e.editor.inMultiSelectMode)
18776            e.editor.exitMultiSelectMode();
18777        return;
18778    }
18779    
18780    if (button !== 0)
18781        return;
18782
18783    var editor = e.editor;
18784    var selection = editor.selection;
18785    var isMultiSelect = editor.inMultiSelectMode;
18786    var pos = e.getDocumentPosition();
18787    var cursor = selection.getCursor();
18788    var inSelection = e.inSelection() || (selection.isEmpty() && isSamePoint(pos, cursor));
18789
18790    var mouseX = e.x, mouseY = e.y;
18791    var onMouseSelection = function(e) {
18792        mouseX = e.clientX;
18793        mouseY = e.clientY;
18794    };
18795    
18796    var session = editor.session;
18797    var screenAnchor = editor.renderer.pixelToScreenCoordinates(mouseX, mouseY);
18798    var screenCursor = screenAnchor;
18799    
18800    var selectionMode;
18801    if (editor.$mouseHandler.$enableJumpToDef) {
18802        if (ctrl && alt || accel && alt)
18803            selectionMode = shift ? "block" : "add";
18804        else if (alt && editor.$blockSelectEnabled)
18805            selectionMode = "block";
18806    } else {
18807        if (accel && !alt) {
18808            selectionMode = "add";
18809            if (!isMultiSelect && shift)
18810                return;
18811        } else if (alt && editor.$blockSelectEnabled) {
18812            selectionMode = "block";
18813        }
18814    }
18815    
18816    if (selectionMode && useragent.isMac && ev.ctrlKey) {
18817        editor.$mouseHandler.cancelContextMenu();
18818    }
18819
18820    if (selectionMode == "add") {
18821        if (!isMultiSelect && inSelection)
18822            return; // dragging
18823
18824        if (!isMultiSelect) {
18825            var range = selection.toOrientedRange();
18826            editor.addSelectionMarker(range);
18827        }
18828
18829        var oldRange = selection.rangeList.rangeAtPoint(pos);
18830        
18831        editor.inVirtualSelectionMode = true;
18832        
18833        if (shift) {
18834            oldRange = null;
18835            range = selection.ranges[0] || range;
18836            editor.removeSelectionMarker(range);
18837        }
18838        editor.once("mouseup", function() {
18839            var tmpSel = selection.toOrientedRange();
18840
18841            if (oldRange && tmpSel.isEmpty() && isSamePoint(oldRange.cursor, tmpSel.cursor))
18842                selection.substractPoint(tmpSel.cursor);
18843            else {
18844                if (shift) {
18845                    selection.substractPoint(range.cursor);
18846                } else if (range) {
18847                    editor.removeSelectionMarker(range);
18848                    selection.addRange(range);
18849                }
18850                selection.addRange(tmpSel);
18851            }
18852            editor.inVirtualSelectionMode = false;
18853        });
18854
18855    } else if (selectionMode == "block") {
18856        e.stop();
18857        editor.inVirtualSelectionMode = true;        
18858        var initialRange;
18859        var rectSel = [];
18860        var blockSelect = function() {
18861            var newCursor = editor.renderer.pixelToScreenCoordinates(mouseX, mouseY);
18862            var cursor = session.screenToDocumentPosition(newCursor.row, newCursor.column, newCursor.offsetX);
18863
18864            if (isSamePoint(screenCursor, newCursor) && isSamePoint(cursor, selection.lead))
18865                return;
18866            screenCursor = newCursor;
18867            
18868            editor.selection.moveToPosition(cursor);
18869            editor.renderer.scrollCursorIntoView();
18870
18871            editor.removeSelectionMarkers(rectSel);
18872            rectSel = selection.rectangularRangeBlock(screenCursor, screenAnchor);
18873            if (editor.$mouseHandler.$clickSelection && rectSel.length == 1 && rectSel[0].isEmpty())
18874                rectSel[0] = editor.$mouseHandler.$clickSelection.clone();
18875            rectSel.forEach(editor.addSelectionMarker, editor);
18876            editor.updateSelectionMarkers();
18877        };
18878        if (isMultiSelect && !accel) {
18879            selection.toSingleRange();
18880        } else if (!isMultiSelect && accel) {
18881            initialRange = selection.toOrientedRange();
18882            editor.addSelectionMarker(initialRange);
18883        }
18884        
18885        if (shift)
18886            screenAnchor = session.documentToScreenPosition(selection.lead);            
18887        else
18888            selection.moveToPosition(pos);
18889        
18890        screenCursor = {row: -1, column: -1};
18891
18892        var onMouseSelectionEnd = function(e) {
18893            clearInterval(timerId);
18894            editor.removeSelectionMarkers(rectSel);
18895            if (!rectSel.length)
18896                rectSel = [selection.toOrientedRange()];
18897            if (initialRange) {
18898                editor.removeSelectionMarker(initialRange);
18899                selection.toSingleRange(initialRange);
18900            }
18901            for (var i = 0; i < rectSel.length; i++)
18902                selection.addRange(rectSel[i]);
18903            editor.inVirtualSelectionMode = false;
18904            editor.$mouseHandler.$clickSelection = null;
18905        };
18906
18907        var onSelectionInterval = blockSelect;
18908
18909        event.capture(editor.container, onMouseSelection, onMouseSelectionEnd);
18910        var timerId = setInterval(function() {onSelectionInterval();}, 20);
18911
18912        return e.preventDefault();
18913    }
18914}
18915
18916
18917exports.onMouseDown = onMouseDown;
18918
18919});
18920
18921define("ace/commands/multi_select_commands",["require","exports","module","ace/keyboard/hash_handler"], function(require, exports, module) {
18922exports.defaultCommands = [{
18923    name: "addCursorAbove",
18924    exec: function(editor) { editor.selectMoreLines(-1); },
18925    bindKey: {win: "Ctrl-Alt-Up", mac: "Ctrl-Alt-Up"},
18926    scrollIntoView: "cursor",
18927    readOnly: true
18928}, {
18929    name: "addCursorBelow",
18930    exec: function(editor) { editor.selectMoreLines(1); },
18931    bindKey: {win: "Ctrl-Alt-Down", mac: "Ctrl-Alt-Down"},
18932    scrollIntoView: "cursor",
18933    readOnly: true
18934}, {
18935    name: "addCursorAboveSkipCurrent",
18936    exec: function(editor) { editor.selectMoreLines(-1, true); },
18937    bindKey: {win: "Ctrl-Alt-Shift-Up", mac: "Ctrl-Alt-Shift-Up"},
18938    scrollIntoView: "cursor",
18939    readOnly: true
18940}, {
18941    name: "addCursorBelowSkipCurrent",
18942    exec: function(editor) { editor.selectMoreLines(1, true); },
18943    bindKey: {win: "Ctrl-Alt-Shift-Down", mac: "Ctrl-Alt-Shift-Down"},
18944    scrollIntoView: "cursor",
18945    readOnly: true
18946}, {
18947    name: "selectMoreBefore",
18948    exec: function(editor) { editor.selectMore(-1); },
18949    bindKey: {win: "Ctrl-Alt-Left", mac: "Ctrl-Alt-Left"},
18950    scrollIntoView: "cursor",
18951    readOnly: true
18952}, {
18953    name: "selectMoreAfter",
18954    exec: function(editor) { editor.selectMore(1); },
18955    bindKey: {win: "Ctrl-Alt-Right", mac: "Ctrl-Alt-Right"},
18956    scrollIntoView: "cursor",
18957    readOnly: true
18958}, {
18959    name: "selectNextBefore",
18960    exec: function(editor) { editor.selectMore(-1, true); },
18961    bindKey: {win: "Ctrl-Alt-Shift-Left", mac: "Ctrl-Alt-Shift-Left"},
18962    scrollIntoView: "cursor",
18963    readOnly: true
18964}, {
18965    name: "selectNextAfter",
18966    exec: function(editor) { editor.selectMore(1, true); },
18967    bindKey: {win: "Ctrl-Alt-Shift-Right", mac: "Ctrl-Alt-Shift-Right"},
18968    scrollIntoView: "cursor",
18969    readOnly: true
18970}, {
18971    name: "splitIntoLines",
18972    exec: function(editor) { editor.multiSelect.splitIntoLines(); },
18973    bindKey: {win: "Ctrl-Alt-L", mac: "Ctrl-Alt-L"},
18974    readOnly: true
18975}, {
18976    name: "alignCursors",
18977    exec: function(editor) { editor.alignCursors(); },
18978    bindKey: {win: "Ctrl-Alt-A", mac: "Ctrl-Alt-A"},
18979    scrollIntoView: "cursor"
18980}, {
18981    name: "findAll",
18982    exec: function(editor) { editor.findAll(); },
18983    bindKey: {win: "Ctrl-Alt-K", mac: "Ctrl-Alt-G"},
18984    scrollIntoView: "cursor",
18985    readOnly: true
18986}];
18987exports.multiSelectCommands = [{
18988    name: "singleSelection",
18989    bindKey: "esc",
18990    exec: function(editor) { editor.exitMultiSelectMode(); },
18991    scrollIntoView: "cursor",
18992    readOnly: true,
18993    isAvailable: function(editor) {return editor && editor.inMultiSelectMode;}
18994}];
18995
18996var HashHandler = require("../keyboard/hash_handler").HashHandler;
18997exports.keyboardHandler = new HashHandler(exports.multiSelectCommands);
18998
18999});
19000
19001define("ace/multi_select",["require","exports","module","ace/range_list","ace/range","ace/selection","ace/mouse/multi_select_handler","ace/lib/event","ace/lib/lang","ace/commands/multi_select_commands","ace/search","ace/edit_session","ace/editor","ace/config"], function(require, exports, module) {
19002
19003var RangeList = require("./range_list").RangeList;
19004var Range = require("./range").Range;
19005var Selection = require("./selection").Selection;
19006var onMouseDown = require("./mouse/multi_select_handler").onMouseDown;
19007var event = require("./lib/event");
19008var lang = require("./lib/lang");
19009var commands = require("./commands/multi_select_commands");
19010exports.commands = commands.defaultCommands.concat(commands.multiSelectCommands);
19011var Search = require("./search").Search;
19012var search = new Search();
19013
19014function find(session, needle, dir) {
19015    search.$options.wrap = true;
19016    search.$options.needle = needle;
19017    search.$options.backwards = dir == -1;
19018    return search.find(session);
19019}
19020var EditSession = require("./edit_session").EditSession;
19021(function() {
19022    this.getSelectionMarkers = function() {
19023        return this.$selectionMarkers;
19024    };
19025}).call(EditSession.prototype);
19026(function() {
19027    this.ranges = null;
19028    this.rangeList = null;
19029    this.addRange = function(range, $blockChangeEvents) {
19030        if (!range)
19031            return;
19032
19033        if (!this.inMultiSelectMode && this.rangeCount === 0) {
19034            var oldRange = this.toOrientedRange();
19035            this.rangeList.add(oldRange);
19036            this.rangeList.add(range);
19037            if (this.rangeList.ranges.length != 2) {
19038                this.rangeList.removeAll();
19039                return $blockChangeEvents || this.fromOrientedRange(range);
19040            }
19041            this.rangeList.removeAll();
19042            this.rangeList.add(oldRange);
19043            this.$onAddRange(oldRange);
19044        }
19045
19046        if (!range.cursor)
19047            range.cursor = range.end;
19048
19049        var removed = this.rangeList.add(range);
19050
19051        this.$onAddRange(range);
19052
19053        if (removed.length)
19054            this.$onRemoveRange(removed);
19055
19056        if (this.rangeCount > 1 && !this.inMultiSelectMode) {
19057            this._signal("multiSelect");
19058            this.inMultiSelectMode = true;
19059            this.session.$undoSelect = false;
19060            this.rangeList.attach(this.session);
19061        }
19062
19063        return $blockChangeEvents || this.fromOrientedRange(range);
19064    };
19065
19066    this.toSingleRange = function(range) {
19067        range = range || this.ranges[0];
19068        var removed = this.rangeList.removeAll();
19069        if (removed.length)
19070            this.$onRemoveRange(removed);
19071
19072        range && this.fromOrientedRange(range);
19073    };
19074    this.substractPoint = function(pos) {
19075        var removed = this.rangeList.substractPoint(pos);
19076        if (removed) {
19077            this.$onRemoveRange(removed);
19078            return removed[0];
19079        }
19080    };
19081    this.mergeOverlappingRanges = function() {
19082        var removed = this.rangeList.merge();
19083        if (removed.length)
19084            this.$onRemoveRange(removed);
19085        else if(this.ranges[0])
19086            this.fromOrientedRange(this.ranges[0]);
19087    };
19088
19089    this.$onAddRange = function(range) {
19090        this.rangeCount = this.rangeList.ranges.length;
19091        this.ranges.unshift(range);
19092        this._signal("addRange", {range: range});
19093    };
19094
19095    this.$onRemoveRange = function(removed) {
19096        this.rangeCount = this.rangeList.ranges.length;
19097        if (this.rangeCount == 1 && this.inMultiSelectMode) {
19098            var lastRange = this.rangeList.ranges.pop();
19099            removed.push(lastRange);
19100            this.rangeCount = 0;
19101        }
19102
19103        for (var i = removed.length; i--; ) {
19104            var index = this.ranges.indexOf(removed[i]);
19105            this.ranges.splice(index, 1);
19106        }
19107
19108        this._signal("removeRange", {ranges: removed});
19109
19110        if (this.rangeCount === 0 && this.inMultiSelectMode) {
19111            this.inMultiSelectMode = false;
19112            this._signal("singleSelect");
19113            this.session.$undoSelect = true;
19114            this.rangeList.detach(this.session);
19115        }
19116
19117        lastRange = lastRange || this.ranges[0];
19118        if (lastRange && !lastRange.isEqual(this.getRange()))
19119            this.fromOrientedRange(lastRange);
19120    };
19121    this.$initRangeList = function() {
19122        if (this.rangeList)
19123            return;
19124
19125        this.rangeList = new RangeList();
19126        this.ranges = [];
19127        this.rangeCount = 0;
19128    };
19129    this.getAllRanges = function() {
19130        return this.rangeCount ? this.rangeList.ranges.concat() : [this.getRange()];
19131    };
19132
19133    this.splitIntoLines = function () {
19134        if (this.rangeCount > 1) {
19135            var ranges = this.rangeList.ranges;
19136            var lastRange = ranges[ranges.length - 1];
19137            var range = Range.fromPoints(ranges[0].start, lastRange.end);
19138
19139            this.toSingleRange();
19140            this.setSelectionRange(range, lastRange.cursor == lastRange.start);
19141        } else {
19142            var range = this.getRange();
19143            var isBackwards = this.isBackwards();
19144            var startRow = range.start.row;
19145            var endRow = range.end.row;
19146            if (startRow == endRow) {
19147                if (isBackwards)
19148                    var start = range.end, end = range.start;
19149                else
19150                    var start = range.start, end = range.end;
19151                
19152                this.addRange(Range.fromPoints(end, end));
19153                this.addRange(Range.fromPoints(start, start));
19154                return;
19155            }
19156
19157            var rectSel = [];
19158            var r = this.getLineRange(startRow, true);
19159            r.start.column = range.start.column;
19160            rectSel.push(r);
19161
19162            for (var i = startRow + 1; i < endRow; i++)
19163                rectSel.push(this.getLineRange(i, true));
19164
19165            r = this.getLineRange(endRow, true);
19166            r.end.column = range.end.column;
19167            rectSel.push(r);
19168
19169            rectSel.forEach(this.addRange, this);
19170        }
19171    };
19172    this.toggleBlockSelection = function () {
19173        if (this.rangeCount > 1) {
19174            var ranges = this.rangeList.ranges;
19175            var lastRange = ranges[ranges.length - 1];
19176            var range = Range.fromPoints(ranges[0].start, lastRange.end);
19177
19178            this.toSingleRange();
19179            this.setSelectionRange(range, lastRange.cursor == lastRange.start);
19180        } else {
19181            var cursor = this.session.documentToScreenPosition(this.cursor);
19182            var anchor = this.session.documentToScreenPosition(this.anchor);
19183
19184            var rectSel = this.rectangularRangeBlock(cursor, anchor);
19185            rectSel.forEach(this.addRange, this);
19186        }
19187    };
19188    this.rectangularRangeBlock = function(screenCursor, screenAnchor, includeEmptyLines) {
19189        var rectSel = [];
19190
19191        var xBackwards = screenCursor.column < screenAnchor.column;
19192        if (xBackwards) {
19193            var startColumn = screenCursor.column;
19194            var endColumn = screenAnchor.column;
19195            var startOffsetX = screenCursor.offsetX;
19196            var endOffsetX = screenAnchor.offsetX;
19197        } else {
19198            var startColumn = screenAnchor.column;
19199            var endColumn = screenCursor.column;
19200            var startOffsetX = screenAnchor.offsetX;
19201            var endOffsetX = screenCursor.offsetX;
19202        }
19203
19204        var yBackwards = screenCursor.row < screenAnchor.row;
19205        if (yBackwards) {
19206            var startRow = screenCursor.row;
19207            var endRow = screenAnchor.row;
19208        } else {
19209            var startRow = screenAnchor.row;
19210            var endRow = screenCursor.row;
19211        }
19212
19213        if (startColumn < 0)
19214            startColumn = 0;
19215        if (startRow < 0)
19216            startRow = 0;
19217
19218        if (startRow == endRow)
19219            includeEmptyLines = true;
19220
19221        var docEnd;
19222        for (var row = startRow; row <= endRow; row++) {
19223            var range = Range.fromPoints(
19224                this.session.screenToDocumentPosition(row, startColumn, startOffsetX),
19225                this.session.screenToDocumentPosition(row, endColumn, endOffsetX)
19226            );
19227            if (range.isEmpty()) {
19228                if (docEnd && isSamePoint(range.end, docEnd))
19229                    break;
19230                docEnd = range.end;
19231            }
19232            range.cursor = xBackwards ? range.start : range.end;
19233            rectSel.push(range);
19234        }
19235
19236        if (yBackwards)
19237            rectSel.reverse();
19238
19239        if (!includeEmptyLines) {
19240            var end = rectSel.length - 1;
19241            while (rectSel[end].isEmpty() && end > 0)
19242                end--;
19243            if (end > 0) {
19244                var start = 0;
19245                while (rectSel[start].isEmpty())
19246                    start++;
19247            }
19248            for (var i = end; i >= start; i--) {
19249                if (rectSel[i].isEmpty())
19250                    rectSel.splice(i, 1);
19251            }
19252        }
19253
19254        return rectSel;
19255    };
19256}).call(Selection.prototype);
19257var Editor = require("./editor").Editor;
19258(function() {
19259    this.updateSelectionMarkers = function() {
vendor: 24,328 bytes, lines 19260-19997
19260        this.renderer.updateCursor();
19261        this.renderer.updateBackMarkers();
19262    };
19263    this.addSelectionMarker = function(orientedRange) {
19264        if (!orientedRange.cursor)
19265            orientedRange.cursor = orientedRange.end;
19266
19267        var style = this.getSelectionStyle();
19268        orientedRange.marker = this.session.addMarker(orientedRange, "ace_selection", style);
19269
19270        this.session.$selectionMarkers.push(orientedRange);
19271        this.session.selectionMarkerCount = this.session.$selectionMarkers.length;
19272        return orientedRange;
19273    };
19274    this.removeSelectionMarker = function(range) {
19275        if (!range.marker)
19276            return;
19277        this.session.removeMarker(range.marker);
19278        var index = this.session.$selectionMarkers.indexOf(range);
19279        if (index != -1)
19280            this.session.$selectionMarkers.splice(index, 1);
19281        this.session.selectionMarkerCount = this.session.$selectionMarkers.length;
19282    };
19283
19284    this.removeSelectionMarkers = function(ranges) {
19285        var markerList = this.session.$selectionMarkers;
19286        for (var i = ranges.length; i--; ) {
19287            var range = ranges[i];
19288            if (!range.marker)
19289                continue;
19290            this.session.removeMarker(range.marker);
19291            var index = markerList.indexOf(range);
19292            if (index != -1)
19293                markerList.splice(index, 1);
19294        }
19295        this.session.selectionMarkerCount = markerList.length;
19296    };
19297
19298    this.$onAddRange = function(e) {
19299        this.addSelectionMarker(e.range);
19300        this.renderer.updateCursor();
19301        this.renderer.updateBackMarkers();
19302    };
19303
19304    this.$onRemoveRange = function(e) {
19305        this.removeSelectionMarkers(e.ranges);
19306        this.renderer.updateCursor();
19307        this.renderer.updateBackMarkers();
19308    };
19309
19310    this.$onMultiSelect = function(e) {
19311        if (this.inMultiSelectMode)
19312            return;
19313        this.inMultiSelectMode = true;
19314
19315        this.setStyle("ace_multiselect");
19316        this.keyBinding.addKeyboardHandler(commands.keyboardHandler);
19317        this.commands.setDefaultHandler("exec", this.$onMultiSelectExec);
19318
19319        this.renderer.updateCursor();
19320        this.renderer.updateBackMarkers();
19321    };
19322
19323    this.$onSingleSelect = function(e) {
19324        if (this.session.multiSelect.inVirtualMode)
19325            return;
19326        this.inMultiSelectMode = false;
19327
19328        this.unsetStyle("ace_multiselect");
19329        this.keyBinding.removeKeyboardHandler(commands.keyboardHandler);
19330
19331        this.commands.removeDefaultHandler("exec", this.$onMultiSelectExec);
19332        this.renderer.updateCursor();
19333        this.renderer.updateBackMarkers();
19334        this._emit("changeSelection");
19335    };
19336
19337    this.$onMultiSelectExec = function(e) {
19338        var command = e.command;
19339        var editor = e.editor;
19340        if (!editor.multiSelect)
19341            return;
19342        if (!command.multiSelectAction) {
19343            var result = command.exec(editor, e.args || {});
19344            editor.multiSelect.addRange(editor.multiSelect.toOrientedRange());
19345            editor.multiSelect.mergeOverlappingRanges();
19346        } else if (command.multiSelectAction == "forEach") {
19347            result = editor.forEachSelection(command, e.args);
19348        } else if (command.multiSelectAction == "forEachLine") {
19349            result = editor.forEachSelection(command, e.args, true);
19350        } else if (command.multiSelectAction == "single") {
19351            editor.exitMultiSelectMode();
19352            result = command.exec(editor, e.args || {});
19353        } else {
19354            result = command.multiSelectAction(editor, e.args || {});
19355        }
19356        return result;
19357    }; 
19358    this.forEachSelection = function(cmd, args, options) {
19359        if (this.inVirtualSelectionMode)
19360            return;
19361        var keepOrder = options && options.keepOrder;
19362        var $byLines = options == true || options && options.$byLines;
19363        var session = this.session;
19364        var selection = this.selection;
19365        var rangeList = selection.rangeList;
19366        var ranges = (keepOrder ? selection : rangeList).ranges;
19367        var result;
19368        
19369        if (!ranges.length)
19370            return cmd.exec ? cmd.exec(this, args || {}) : cmd(this, args || {});
19371        
19372        var reg = selection._eventRegistry;
19373        selection._eventRegistry = {};
19374
19375        var tmpSel = new Selection(session);
19376        this.inVirtualSelectionMode = true;
19377        for (var i = ranges.length; i--;) {
19378            if ($byLines) {
19379                while (i > 0 && ranges[i].start.row == ranges[i - 1].end.row)
19380                    i--;
19381            }
19382            tmpSel.fromOrientedRange(ranges[i]);
19383            tmpSel.index = i;
19384            this.selection = session.selection = tmpSel;
19385            var cmdResult = cmd.exec ? cmd.exec(this, args || {}) : cmd(this, args || {});
19386            if (!result && cmdResult !== undefined)
19387                result = cmdResult;
19388            tmpSel.toOrientedRange(ranges[i]);
19389        }
19390        tmpSel.detach();
19391
19392        this.selection = session.selection = selection;
19393        this.inVirtualSelectionMode = false;
19394        selection._eventRegistry = reg;
19395        selection.mergeOverlappingRanges();
19396        
19397        var anim = this.renderer.$scrollAnimation;
19398        this.onCursorChange();
19399        this.onSelectionChange();
19400        if (anim && anim.from == anim.to)
19401            this.renderer.animateScrolling(anim.from);
19402        
19403        return result;
19404    };
19405    this.exitMultiSelectMode = function() {
19406        if (!this.inMultiSelectMode || this.inVirtualSelectionMode)
19407            return;
19408        this.multiSelect.toSingleRange();
19409    };
19410
19411    this.getSelectedText = function() {
19412        var text = "";
19413        if (this.inMultiSelectMode && !this.inVirtualSelectionMode) {
19414            var ranges = this.multiSelect.rangeList.ranges;
19415            var buf = [];
19416            for (var i = 0; i < ranges.length; i++) {
19417                buf.push(this.session.getTextRange(ranges[i]));
19418            }
19419            var nl = this.session.getDocument().getNewLineCharacter();
19420            text = buf.join(nl);
19421            if (text.length == (buf.length - 1) * nl.length)
19422                text = "";
19423        } else if (!this.selection.isEmpty()) {
19424            text = this.session.getTextRange(this.getSelectionRange());
19425        }
19426        return text;
19427    };
19428    
19429    this.$checkMultiselectChange = function(e, anchor) {
19430        if (this.inMultiSelectMode && !this.inVirtualSelectionMode) {
19431            var range = this.multiSelect.ranges[0];
19432            if (this.multiSelect.isEmpty() && anchor == this.multiSelect.anchor)
19433                return;
19434            var pos = anchor == this.multiSelect.anchor
19435                ? range.cursor == range.start ? range.end : range.start
19436                : range.cursor;
19437            if (pos.row != anchor.row 
19438                || this.session.$clipPositionToDocument(pos.row, pos.column).column != anchor.column)
19439                this.multiSelect.toSingleRange(this.multiSelect.toOrientedRange());
19440        }
19441    };
19442    this.findAll = function(needle, options, additive) {
19443        options = options || {};
19444        options.needle = needle || options.needle;
19445        if (options.needle == undefined) {
19446            var range = this.selection.isEmpty()
19447                ? this.selection.getWordRange()
19448                : this.selection.getRange();
19449            options.needle = this.session.getTextRange(range);
19450        }    
19451        this.$search.set(options);
19452        
19453        var ranges = this.$search.findAll(this.session);
19454        if (!ranges.length)
19455            return 0;
19456
19457        var selection = this.multiSelect;
19458
19459        if (!additive)
19460            selection.toSingleRange(ranges[0]);
19461
19462        for (var i = ranges.length; i--; )
19463            selection.addRange(ranges[i], true);
19464        if (range && selection.rangeList.rangeAtPoint(range.start))
19465            selection.addRange(range, true);
19466        
19467        return ranges.length;
19468    };
19469    this.selectMoreLines = function(dir, skip) {
19470        var range = this.selection.toOrientedRange();
19471        var isBackwards = range.cursor == range.end;
19472
19473        var screenLead = this.session.documentToScreenPosition(range.cursor);
19474        if (this.selection.$desiredColumn)
19475            screenLead.column = this.selection.$desiredColumn;
19476
19477        var lead = this.session.screenToDocumentPosition(screenLead.row + dir, screenLead.column);
19478
19479        if (!range.isEmpty()) {
19480            var screenAnchor = this.session.documentToScreenPosition(isBackwards ? range.end : range.start);
19481            var anchor = this.session.screenToDocumentPosition(screenAnchor.row + dir, screenAnchor.column);
19482        } else {
19483            var anchor = lead;
19484        }
19485
19486        if (isBackwards) {
19487            var newRange = Range.fromPoints(lead, anchor);
19488            newRange.cursor = newRange.start;
19489        } else {
19490            var newRange = Range.fromPoints(anchor, lead);
19491            newRange.cursor = newRange.end;
19492        }
19493
19494        newRange.desiredColumn = screenLead.column;
19495        if (!this.selection.inMultiSelectMode) {
19496            this.selection.addRange(range);
19497        } else {
19498            if (skip)
19499                var toRemove = range.cursor;
19500        }
19501
19502        this.selection.addRange(newRange);
19503        if (toRemove)
19504            this.selection.substractPoint(toRemove);
19505    };
19506    this.transposeSelections = function(dir) {
19507        var session = this.session;
19508        var sel = session.multiSelect;
19509        var all = sel.ranges;
19510
19511        for (var i = all.length; i--; ) {
19512            var range = all[i];
19513            if (range.isEmpty()) {
19514                var tmp = session.getWordRange(range.start.row, range.start.column);
19515                range.start.row = tmp.start.row;
19516                range.start.column = tmp.start.column;
19517                range.end.row = tmp.end.row;
19518                range.end.column = tmp.end.column;
19519            }
19520        }
19521        sel.mergeOverlappingRanges();
19522
19523        var words = [];
19524        for (var i = all.length; i--; ) {
19525            var range = all[i];
19526            words.unshift(session.getTextRange(range));
19527        }
19528
19529        if (dir < 0)
19530            words.unshift(words.pop());
19531        else
19532            words.push(words.shift());
19533
19534        for (var i = all.length; i--; ) {
19535            var range = all[i];
19536            var tmp = range.clone();
19537            session.replace(range, words[i]);
19538            range.start.row = tmp.start.row;
19539            range.start.column = tmp.start.column;
19540        }
19541    };
19542    this.selectMore = function(dir, skip, stopAtFirst) {
19543        var session = this.session;
19544        var sel = session.multiSelect;
19545
19546        var range = sel.toOrientedRange();
19547        if (range.isEmpty()) {
19548            range = session.getWordRange(range.start.row, range.start.column);
19549            range.cursor = dir == -1 ? range.start : range.end;
19550            this.multiSelect.addRange(range);
19551            if (stopAtFirst)
19552                return;
19553        }
19554        var needle = session.getTextRange(range);
19555
19556        var newRange = find(session, needle, dir);
19557        if (newRange) {
19558            newRange.cursor = dir == -1 ? newRange.start : newRange.end;
19559            this.session.unfold(newRange);
19560            this.multiSelect.addRange(newRange);
19561            this.renderer.scrollCursorIntoView(null, 0.5);
19562        }
19563        if (skip)
19564            this.multiSelect.substractPoint(range.cursor);
19565    };
19566    this.alignCursors = function() {
19567        var session = this.session;
19568        var sel = session.multiSelect;
19569        var ranges = sel.ranges;
19570        var row = -1;
19571        var sameRowRanges = ranges.filter(function(r) {
19572            if (r.cursor.row == row)
19573                return true;
19574            row = r.cursor.row;
19575        });
19576        
19577        if (!ranges.length || sameRowRanges.length == ranges.length - 1) {
19578            var range = this.selection.getRange();
19579            var fr = range.start.row, lr = range.end.row;
19580            var guessRange = fr == lr;
19581            if (guessRange) {
19582                var max = this.session.getLength();
19583                var line;
19584                do {
19585                    line = this.session.getLine(lr);
19586                } while (/[=:]/.test(line) && ++lr < max);
19587                do {
19588                    line = this.session.getLine(fr);
19589                } while (/[=:]/.test(line) && --fr > 0);
19590                
19591                if (fr < 0) fr = 0;
19592                if (lr >= max) lr = max - 1;
19593            }
19594            var lines = this.session.removeFullLines(fr, lr);
19595            lines = this.$reAlignText(lines, guessRange);
19596            this.session.insert({row: fr, column: 0}, lines.join("\n") + "\n");
19597            if (!guessRange) {
19598                range.start.column = 0;
19599                range.end.column = lines[lines.length - 1].length;
19600            }
19601            this.selection.setRange(range);
19602        } else {
19603            sameRowRanges.forEach(function(r) {
19604                sel.substractPoint(r.cursor);
19605            });
19606
19607            var maxCol = 0;
19608            var minSpace = Infinity;
19609            var spaceOffsets = ranges.map(function(r) {
19610                var p = r.cursor;
19611                var line = session.getLine(p.row);
19612                var spaceOffset = line.substr(p.column).search(/\S/g);
19613                if (spaceOffset == -1)
19614                    spaceOffset = 0;
19615
19616                if (p.column > maxCol)
19617                    maxCol = p.column;
19618                if (spaceOffset < minSpace)
19619                    minSpace = spaceOffset;
19620                return spaceOffset;
19621            });
19622            ranges.forEach(function(r, i) {
19623                var p = r.cursor;
19624                var l = maxCol - p.column;
19625                var d = spaceOffsets[i] - minSpace;
19626                if (l > d)
19627                    session.insert(p, lang.stringRepeat(" ", l - d));
19628                else
19629                    session.remove(new Range(p.row, p.column, p.row, p.column - l + d));
19630
19631                r.start.column = r.end.column = maxCol;
19632                r.start.row = r.end.row = p.row;
19633                r.cursor = r.end;
19634            });
19635            sel.fromOrientedRange(ranges[0]);
19636            this.renderer.updateCursor();
19637            this.renderer.updateBackMarkers();
19638        }
19639    };
19640
19641    this.$reAlignText = function(lines, forceLeft) {
19642        var isLeftAligned = true, isRightAligned = true;
19643        var startW, textW, endW;
19644
19645        return lines.map(function(line) {
19646            var m = line.match(/(\s*)(.*?)(\s*)([=:].*)/);
19647            if (!m)
19648                return [line];
19649
19650            if (startW == null) {
19651                startW = m[1].length;
19652                textW = m[2].length;
19653                endW = m[3].length;
19654                return m;
19655            }
19656
19657            if (startW + textW + endW != m[1].length + m[2].length + m[3].length)
19658                isRightAligned = false;
19659            if (startW != m[1].length)
19660                isLeftAligned = false;
19661
19662            if (startW > m[1].length)
19663                startW = m[1].length;
19664            if (textW < m[2].length)
19665                textW = m[2].length;
19666            if (endW > m[3].length)
19667                endW = m[3].length;
19668
19669            return m;
19670        }).map(forceLeft ? alignLeft :
19671            isLeftAligned ? isRightAligned ? alignRight : alignLeft : unAlign);
19672
19673        function spaces(n) {
19674            return lang.stringRepeat(" ", n);
19675        }
19676
19677        function alignLeft(m) {
19678            return !m[2] ? m[0] : spaces(startW) + m[2]
19679                + spaces(textW - m[2].length + endW)
19680                + m[4].replace(/^([=:])\s+/, "$1 ");
19681        }
19682        function alignRight(m) {
19683            return !m[2] ? m[0] : spaces(startW + textW - m[2].length) + m[2]
19684                + spaces(endW)
19685                + m[4].replace(/^([=:])\s+/, "$1 ");
19686        }
19687        function unAlign(m) {
19688            return !m[2] ? m[0] : spaces(startW) + m[2]
19689                + spaces(endW)
19690                + m[4].replace(/^([=:])\s+/, "$1 ");
19691        }
19692    };
19693}).call(Editor.prototype);
19694
19695
19696function isSamePoint(p1, p2) {
19697    return p1.row == p2.row && p1.column == p2.column;
19698}
19699exports.onSessionChange = function(e) {
19700    var session = e.session;
19701    if (session && !session.multiSelect) {
19702        session.$selectionMarkers = [];
19703        session.selection.$initRangeList();
19704        session.multiSelect = session.selection;
19705    }
19706    this.multiSelect = session && session.multiSelect;
19707
19708    var oldSession = e.oldSession;
19709    if (oldSession) {
19710        oldSession.multiSelect.off("addRange", this.$onAddRange);
19711        oldSession.multiSelect.off("removeRange", this.$onRemoveRange);
19712        oldSession.multiSelect.off("multiSelect", this.$onMultiSelect);
19713        oldSession.multiSelect.off("singleSelect", this.$onSingleSelect);
19714        oldSession.multiSelect.lead.off("change", this.$checkMultiselectChange);
19715        oldSession.multiSelect.anchor.off("change", this.$checkMultiselectChange);
19716    }
19717
19718    if (session) {
19719        session.multiSelect.on("addRange", this.$onAddRange);
19720        session.multiSelect.on("removeRange", this.$onRemoveRange);
19721        session.multiSelect.on("multiSelect", this.$onMultiSelect);
19722        session.multiSelect.on("singleSelect", this.$onSingleSelect);
19723        session.multiSelect.lead.on("change", this.$checkMultiselectChange);
19724        session.multiSelect.anchor.on("change", this.$checkMultiselectChange);
19725    }
19726
19727    if (session && this.inMultiSelectMode != session.selection.inMultiSelectMode) {
19728        if (session.selection.inMultiSelectMode)
19729            this.$onMultiSelect();
19730        else
19731            this.$onSingleSelect();
19732    }
19733};
19734function MultiSelect(editor) {
19735    if (editor.$multiselectOnSessionChange)
19736        return;
19737    editor.$onAddRange = editor.$onAddRange.bind(editor);
19738    editor.$onRemoveRange = editor.$onRemoveRange.bind(editor);
19739    editor.$onMultiSelect = editor.$onMultiSelect.bind(editor);
19740    editor.$onSingleSelect = editor.$onSingleSelect.bind(editor);
19741    editor.$multiselectOnSessionChange = exports.onSessionChange.bind(editor);
19742    editor.$checkMultiselectChange = editor.$checkMultiselectChange.bind(editor);
19743
19744    editor.$multiselectOnSessionChange(editor);
19745    editor.on("changeSession", editor.$multiselectOnSessionChange);
19746
19747    editor.on("mousedown", onMouseDown);
19748    editor.commands.addCommands(commands.defaultCommands);
19749
19750    addAltCursorListeners(editor);
19751}
19752
19753function addAltCursorListeners(editor){
19754    var el = editor.textInput.getElement();
19755    var altCursor = false;
19756    event.addListener(el, "keydown", function(e) {
19757        var altDown = e.keyCode == 18 && !(e.ctrlKey || e.shiftKey || e.metaKey);
19758        if (editor.$blockSelectEnabled && altDown) {
19759            if (!altCursor) {
19760                editor.renderer.setMouseCursor("crosshair");
19761                altCursor = true;
19762            }
19763        } else if (altCursor) {
19764            reset();
19765        }
19766    });
19767
19768    event.addListener(el, "keyup", reset);
19769    event.addListener(el, "blur", reset);
19770    function reset(e) {
19771        if (altCursor) {
19772            editor.renderer.setMouseCursor("");
19773            altCursor = false;
19774        }
19775    }
19776}
19777
19778exports.MultiSelect = MultiSelect;
19779
19780
19781require("./config").defineOptions(Editor.prototype, "editor", {
19782    enableMultiselect: {
19783        set: function(val) {
19784            MultiSelect(this);
19785            if (val) {
19786                this.on("changeSession", this.$multiselectOnSessionChange);
19787                this.on("mousedown", onMouseDown);
19788            } else {
19789                this.off("changeSession", this.$multiselectOnSessionChange);
19790                this.off("mousedown", onMouseDown);
19791            }
19792        },
19793        value: true
19794    },
19795    enableBlockSelect: {
19796        set: function(val) {
19797            this.$blockSelectEnabled = val;
19798        },
19799        value: true
19800    }
19801});
19802
19803
19804
19805});
19806
19807define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"], function(require, exports, module) {
19808"use strict";
19809
19810var Range = require("../../range").Range;
19811
19812var FoldMode = exports.FoldMode = function() {};
19813
19814(function() {
19815
19816    this.foldingStartMarker = null;
19817    this.foldingStopMarker = null;
19818    this.getFoldWidget = function(session, foldStyle, row) {
19819        var line = session.getLine(row);
19820        if (this.foldingStartMarker.test(line))
19821            return "start";
19822        if (foldStyle == "markbeginend"
19823                && this.foldingStopMarker
19824                && this.foldingStopMarker.test(line))
19825            return "end";
19826        return "";
19827    };
19828
19829    this.getFoldWidgetRange = function(session, foldStyle, row) {
19830        return null;
19831    };
19832
19833    this.indentationBlock = function(session, row, column) {
19834        var re = /\S/;
19835        var line = session.getLine(row);
19836        var startLevel = line.search(re);
19837        if (startLevel == -1)
19838            return;
19839
19840        var startColumn = column || line.length;
19841        var maxRow = session.getLength();
19842        var startRow = row;
19843        var endRow = row;
19844
19845        while (++row < maxRow) {
19846            var level = session.getLine(row).search(re);
19847
19848            if (level == -1)
19849                continue;
19850
19851            if (level <= startLevel)
19852                break;
19853
19854            endRow = row;
19855        }
19856
19857        if (endRow > startRow) {
19858            var endColumn = session.getLine(endRow).length;
19859            return new Range(startRow, startColumn, endRow, endColumn);
19860        }
19861    };
19862
19863    this.openingBracketBlock = function(session, bracket, row, column, typeRe) {
19864        var start = {row: row, column: column + 1};
19865        var end = session.$findClosingBracket(bracket, start, typeRe);
19866        if (!end)
19867            return;
19868
19869        var fw = session.foldWidgets[end.row];
19870        if (fw == null)
19871            fw = session.getFoldWidget(end.row);
19872
19873        if (fw == "start" && end.row > start.row) {
19874            end.row --;
19875            end.column = session.getLine(end.row).length;
19876        }
19877        return Range.fromPoints(start, end);
19878    };
19879
19880    this.closingBracketBlock = function(session, bracket, row, column, typeRe) {
19881        var end = {row: row, column: column};
19882        var start = session.$findOpeningBracket(bracket, end);
19883
19884        if (!start)
19885            return;
19886
19887        start.column++;
19888        end.column--;
19889
19890        return  Range.fromPoints(start, end);
19891    };
19892}).call(FoldMode.prototype);
19893
19894});
19895
19896define("ace/theme/textmate",["require","exports","module","ace/lib/dom"], function(require, exports, module) {
19897"use strict";
19898
19899exports.isDark = false;
19900exports.cssClass = "ace-tm";
19901exports.cssText = ".ace-tm .ace_gutter {\
19902background: #f0f0f0;\
19903color: #333;\
19904}\
19905.ace-tm .ace_print-margin {\
19906width: 1px;\
19907background: #e8e8e8;\
19908}\
19909.ace-tm .ace_fold {\
19910background-color: #6B72E6;\
19911}\
19912.ace-tm {\
19913background-color: #FFFFFF;\
19914color: black;\
19915}\
19916.ace-tm .ace_cursor {\
19917color: black;\
19918}\
19919.ace-tm .ace_invisible {\
19920color: rgb(191, 191, 191);\
19921}\
19922.ace-tm .ace_storage,\
19923.ace-tm .ace_keyword {\
19924color: blue;\
19925}\
19926.ace-tm .ace_constant {\
19927color: rgb(197, 6, 11);\
19928}\
19929.ace-tm .ace_constant.ace_buildin {\
19930color: rgb(88, 72, 246);\
19931}\
19932.ace-tm .ace_constant.ace_language {\
19933color: rgb(88, 92, 246);\
19934}\
19935.ace-tm .ace_constant.ace_library {\
19936color: rgb(6, 150, 14);\
19937}\
19938.ace-tm .ace_invalid {\
19939background-color: rgba(255, 0, 0, 0.1);\
19940color: red;\
19941}\
19942.ace-tm .ace_support.ace_function {\
19943color: rgb(60, 76, 114);\
19944}\
19945.ace-tm .ace_support.ace_constant {\
19946color: rgb(6, 150, 14);\
19947}\
19948.ace-tm .ace_support.ace_type,\
19949.ace-tm .ace_support.ace_class {\
19950color: rgb(109, 121, 222);\
19951}\
19952.ace-tm .ace_keyword.ace_operator {\
19953color: rgb(104, 118, 135);\
19954}\
19955.ace-tm .ace_string {\
19956color: rgb(3, 106, 7);\
19957}\
19958.ace-tm .ace_comment {\
19959color: rgb(76, 136, 107);\
19960}\
19961.ace-tm .ace_comment.ace_doc {\
19962color: rgb(0, 102, 255);\
19963}\
19964.ace-tm .ace_comment.ace_doc.ace_tag {\
19965color: rgb(128, 159, 191);\
19966}\
19967.ace-tm .ace_constant.ace_numeric {\
19968color: rgb(0, 0, 205);\
19969}\
19970.ace-tm .ace_variable {\
19971color: rgb(49, 132, 149);\
19972}\
19973.ace-tm .ace_xml-pe {\
19974color: rgb(104, 104, 91);\
19975}\
19976.ace-tm .ace_entity.ace_name.ace_function {\
19977color: #0000A2;\
19978}\
19979.ace-tm .ace_heading {\
19980color: rgb(12, 7, 255);\
19981}\
19982.ace-tm .ace_list {\
19983color:rgb(185, 6, 144);\
19984}\
19985.ace-tm .ace_meta.ace_tag {\
19986color:rgb(0, 22, 142);\
19987}\
19988.ace-tm .ace_string.ace_regex {\
19989color: rgb(255, 0, 0)\
19990}\
19991.ace-tm .ace_marker-layer .ace_selection {\
19992background: rgb(181, 213, 255);\
19993}\
19994.ace-tm.ace_multiselect .ace_selection.ace_start {\
19995box-shadow: 0 0 3px 0px white;\
19996}\
19997.ace-tm .ace_marker-layer .ace_step {\
19998background: rgb(252, 255, 0);\
19999}\
20000.ace-tm .ace_marker-layer .ace_stack {\
20001background: rgb(164, 229, 101);\
20002}\
20003.ace-tm .ace_marker-layer .ace_bracket {\
20004margin: -1px 0 0 -1px;\
20005border: 1px solid rgb(192, 192, 192);\
20006}\
20007.ace-tm .ace_marker-layer .ace_active-line {\
20008background: rgba(0, 0, 0, 0.07);\
20009}\
20010.ace-tm .ace_gutter-active-line {\
20011background-color : #dcdcdc;\
20012}\
20013.ace-tm .ace_marker-layer .ace_selected-word {\
20014background: rgb(250, 250, 255);\
20015border: 1px solid rgb(200, 200, 250);\
20016}\
20017.ace-tm .ace_indent-guide {\
20018background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\") right repeat-y;\
20019}\
20020";
20021exports.$id = "ace/theme/textmate";
20022
20023var dom = require("../lib/dom");
20024dom.importCssString(exports.cssText, exports.cssClass);
20025});
20026
20027define("ace/line_widgets",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/range"], function(require, exports, module) {
20028"use strict";
20029
20030var oop = require("./lib/oop");
20031var dom = require("./lib/dom");
20032var Range = require("./range").Range;
20033
20034
20035function LineWidgets(session) {
20036    this.session = session;
20037    this.session.widgetManager = this;
20038    this.session.getRowLength = this.getRowLength;
20039    this.session.$getWidgetScreenLength = this.$getWidgetScreenLength;
20040    this.updateOnChange = this.updateOnChange.bind(this);
20041    this.renderWidgets = this.renderWidgets.bind(this);
20042    this.measureWidgets = this.measureWidgets.bind(this);
20043    this.session._changedWidgets = [];
20044    this.$onChangeEditor = this.$onChangeEditor.bind(this);
20045    
20046    this.session.on("change", this.updateOnChange);
20047    this.session.on("changeFold", this.updateOnFold);
20048    this.session.on("changeEditor", this.$onChangeEditor);
20049}
20050
20051(function() {
20052    this.getRowLength = function(row) {
20053        var h;
20054        if (this.lineWidgets)
20055            h = this.lineWidgets[row] && this.lineWidgets[row].rowCount || 0;
20056        else 
20057            h = 0;
20058        if (!this.$useWrapMode || !this.$wrapData[row]) {
20059            return 1 + h;
20060        } else {
20061            return this.$wrapData[row].length + 1 + h;
20062        }
20063    };
20064
20065    this.$getWidgetScreenLength = function() {
20066        var screenRows = 0;
20067        this.lineWidgets.forEach(function(w){
20068            if (w && w.rowCount && !w.hidden)
20069                screenRows += w.rowCount;
20070        });
20071        return screenRows;
20072    };    
20073    
20074    this.$onChangeEditor = function(e) {
20075        this.attach(e.editor);
20076    };
20077    
20078    this.attach = function(editor) {
20079        if (editor  && editor.widgetManager && editor.widgetManager != this)
20080            editor.widgetManager.detach();
20081
20082        if (this.editor == editor)
20083            return;
20084
20085        this.detach();
20086        this.editor = editor;
20087        
20088        if (editor) {
20089            editor.widgetManager = this;
20090            editor.renderer.on("beforeRender", this.measureWidgets);
20091            editor.renderer.on("afterRender", this.renderWidgets);
20092        }
20093    };
20094    this.detach = function(e) {
20095        var editor = this.editor;
20096        if (!editor)
20097            return;
20098        
20099        this.editor = null;
20100        editor.widgetManager = null;
20101        
20102        editor.renderer.off("beforeRender", this.measureWidgets);
20103        editor.renderer.off("afterRender", this.renderWidgets);
20104        var lineWidgets = this.session.lineWidgets;
20105        lineWidgets && lineWidgets.forEach(function(w) {
20106            if (w && w.el && w.el.parentNode) {
20107                w._inDocument = false;
20108                w.el.parentNode.removeChild(w.el);
20109            }
20110        });
20111    };
20112
20113    this.updateOnFold = function(e, session) {
20114        var lineWidgets = session.lineWidgets;
20115        if (!lineWidgets || !e.action)
20116            return;
20117        var fold = e.data;
20118        var start = fold.start.row;
20119        var end = fold.end.row;
20120        var hide = e.action == "add";
20121        for (var i = start + 1; i < end; i++) {
20122            if (lineWidgets[i])
20123                lineWidgets[i].hidden = hide;
20124        }
20125        if (lineWidgets[end]) {
20126            if (hide) {
20127                if (!lineWidgets[start])
20128                    lineWidgets[start] = lineWidgets[end];
20129                else
20130                    lineWidgets[end].hidden = hide;
20131            } else {
20132                if (lineWidgets[start] == lineWidgets[end])
20133                    lineWidgets[start] = undefined;
20134                lineWidgets[end].hidden = hide;
20135            }
20136        }
20137    };
20138    
20139    this.updateOnChange = function(delta) {
20140        var lineWidgets = this.session.lineWidgets;
20141        if (!lineWidgets) return;
20142        
20143        var startRow = delta.start.row;
20144        var len = delta.end.row - startRow;
20145
20146        if (len === 0) {
20147        } else if (delta.action == 'remove') {
20148            var removed = lineWidgets.splice(startRow + 1, len);
20149            removed.forEach(function(w) {
20150                w && this.removeLineWidget(w);
20151            }, this);
20152            this.$updateRows();
20153        } else {
20154            var args = new Array(len);
20155            args.unshift(startRow, 0);
20156            lineWidgets.splice.apply(lineWidgets, args);
20157            this.$updateRows();
20158        }
20159    };
20160    
20161    this.$updateRows = function() {
20162        var lineWidgets = this.session.lineWidgets;
20163        if (!lineWidgets) return;
20164        var noWidgets = true;
vendor: 12,749 bytes, lines 20165-20565
20165        lineWidgets.forEach(function(w, i) {
20166            if (w) {
20167                noWidgets = false;
20168                w.row = i;
20169                while (w.$oldWidget) {
20170                    w.$oldWidget.row = i;
20171                    w = w.$oldWidget;
20172                }
20173            }
20174        });
20175        if (noWidgets)
20176            this.session.lineWidgets = null;
20177    };
20178
20179    this.addLineWidget = function(w) {
20180        if (!this.session.lineWidgets)
20181            this.session.lineWidgets = new Array(this.session.getLength());
20182        
20183        var old = this.session.lineWidgets[w.row];
20184        if (old) {
20185            w.$oldWidget = old;
20186            if (old.el && old.el.parentNode) {
20187                old.el.parentNode.removeChild(old.el);
20188                old._inDocument = false;
20189            }
20190        }
20191            
20192        this.session.lineWidgets[w.row] = w;
20193        
20194        w.session = this.session;
20195        
20196        var renderer = this.editor.renderer;
20197        if (w.html && !w.el) {
20198            w.el = dom.createElement("div");
20199            w.el.innerHTML = w.html;
20200        }
20201        if (w.el) {
20202            dom.addCssClass(w.el, "ace_lineWidgetContainer");
20203            w.el.style.position = "absolute";
20204            w.el.style.zIndex = 5;
20205            renderer.container.appendChild(w.el);
20206            w._inDocument = true;
20207        }
20208        
20209        if (!w.coverGutter) {
20210            w.el.style.zIndex = 3;
20211        }
20212        if (w.pixelHeight == null) {
20213            w.pixelHeight = w.el.offsetHeight;
20214        }
20215        if (w.rowCount == null) {
20216            w.rowCount = w.pixelHeight / renderer.layerConfig.lineHeight;
20217        }
20218        
20219        var fold = this.session.getFoldAt(w.row, 0);
20220        w.$fold = fold;
20221        if (fold) {
20222            var lineWidgets = this.session.lineWidgets;
20223            if (w.row == fold.end.row && !lineWidgets[fold.start.row])
20224                lineWidgets[fold.start.row] = w;
20225            else
20226                w.hidden = true;
20227        }
20228            
20229        this.session._emit("changeFold", {data:{start:{row: w.row}}});
20230        
20231        this.$updateRows();
20232        this.renderWidgets(null, renderer);
20233        this.onWidgetChanged(w);
20234        return w;
20235    };
20236    
20237    this.removeLineWidget = function(w) {
20238        w._inDocument = false;
20239        w.session = null;
20240        if (w.el && w.el.parentNode)
20241            w.el.parentNode.removeChild(w.el);
20242        if (w.editor && w.editor.destroy) try {
20243            w.editor.destroy();
20244        } catch(e){}
20245        if (this.session.lineWidgets) {
20246            var w1 = this.session.lineWidgets[w.row];
20247            if (w1 == w) {
20248                this.session.lineWidgets[w.row] = w.$oldWidget;
20249                if (w.$oldWidget)
20250                    this.onWidgetChanged(w.$oldWidget);
20251            } else {
20252                while (w1) {
20253                    if (w1.$oldWidget == w) {
20254                        w1.$oldWidget = w.$oldWidget;
20255                        break;
20256                    }
20257                    w1 = w1.$oldWidget;
20258                }
20259            }
20260        }
20261        this.session._emit("changeFold", {data:{start:{row: w.row}}});
20262        this.$updateRows();
20263    };
20264    
20265    this.getWidgetsAtRow = function(row) {
20266        var lineWidgets = this.session.lineWidgets;
20267        var w = lineWidgets && lineWidgets[row];
20268        var list = [];
20269        while (w) {
20270            list.push(w);
20271            w = w.$oldWidget;
20272        }
20273        return list;
20274    };
20275    
20276    this.onWidgetChanged = function(w) {
20277        this.session._changedWidgets.push(w);
20278        this.editor && this.editor.renderer.updateFull();
20279    };
20280    
20281    this.measureWidgets = function(e, renderer) {
20282        var changedWidgets = this.session._changedWidgets;
20283        var config = renderer.layerConfig;
20284        
20285        if (!changedWidgets || !changedWidgets.length) return;
20286        var min = Infinity;
20287        for (var i = 0; i < changedWidgets.length; i++) {
20288            var w = changedWidgets[i];
20289            if (!w || !w.el) continue;
20290            if (w.session != this.session) continue;
20291            if (!w._inDocument) {
20292                if (this.session.lineWidgets[w.row] != w)
20293                    continue;
20294                w._inDocument = true;
20295                renderer.container.appendChild(w.el);
20296            }
20297            
20298            w.h = w.el.offsetHeight;
20299            
20300            if (!w.fixedWidth) {
20301                w.w = w.el.offsetWidth;
20302                w.screenWidth = Math.ceil(w.w / config.characterWidth);
20303            }
20304            
20305            var rowCount = w.h / config.lineHeight;
20306            if (w.coverLine) {
20307                rowCount -= this.session.getRowLineCount(w.row);
20308                if (rowCount < 0)
20309                    rowCount = 0;
20310            }
20311            if (w.rowCount != rowCount) {
20312                w.rowCount = rowCount;
20313                if (w.row < min)
20314                    min = w.row;
20315            }
20316        }
20317        if (min != Infinity) {
20318            this.session._emit("changeFold", {data:{start:{row: min}}});
20319            this.session.lineWidgetWidth = null;
20320        }
20321        this.session._changedWidgets = [];
20322    };
20323    
20324    this.renderWidgets = function(e, renderer) {
20325        var config = renderer.layerConfig;
20326        var lineWidgets = this.session.lineWidgets;
20327        if (!lineWidgets)
20328            return;
20329        var first = Math.min(this.firstRow, config.firstRow);
20330        var last = Math.max(this.lastRow, config.lastRow, lineWidgets.length);
20331        
20332        while (first > 0 && !lineWidgets[first])
20333            first--;
20334        
20335        this.firstRow = config.firstRow;
20336        this.lastRow = config.lastRow;
20337
20338        renderer.$cursorLayer.config = config;
20339        for (var i = first; i <= last; i++) {
20340            var w = lineWidgets[i];
20341            if (!w || !w.el) continue;
20342            if (w.hidden) {
20343                w.el.style.top = -100 - (w.pixelHeight || 0) + "px";
20344                continue;
20345            }
20346            if (!w._inDocument) {
20347                w._inDocument = true;
20348                renderer.container.appendChild(w.el);
20349            }
20350            var top = renderer.$cursorLayer.getPixelPosition({row: i, column:0}, true).top;
20351            if (!w.coverLine)
20352                top += config.lineHeight * this.session.getRowLineCount(w.row);
20353            w.el.style.top = top - config.offset + "px";
20354            
20355            var left = w.coverGutter ? 0 : renderer.gutterWidth;
20356            if (!w.fixedWidth)
20357                left -= renderer.scrollLeft;
20358            w.el.style.left = left + "px";
20359            
20360            if (w.fullWidth && w.screenWidth) {
20361                w.el.style.minWidth = config.width + 2 * config.padding + "px";
20362            }
20363            
20364            if (w.fixedWidth) {
20365                w.el.style.right = renderer.scrollBar.getWidth() + "px";
20366            } else {
20367                w.el.style.right = "";
20368            }
20369        }
20370    };
20371    
20372}).call(LineWidgets.prototype);
20373
20374
20375exports.LineWidgets = LineWidgets;
20376
20377});
20378
20379define("ace/ext/error_marker",["require","exports","module","ace/line_widgets","ace/lib/dom","ace/range"], function(require, exports, module) {
20380"use strict";
20381var LineWidgets = require("../line_widgets").LineWidgets;
20382var dom = require("../lib/dom");
20383var Range = require("../range").Range;
20384
20385function binarySearch(array, needle, comparator) {
20386    var first = 0;
20387    var last = array.length - 1;
20388
20389    while (first <= last) {
20390        var mid = (first + last) >> 1;
20391        var c = comparator(needle, array[mid]);
20392        if (c > 0)
20393            first = mid + 1;
20394        else if (c < 0)
20395            last = mid - 1;
20396        else
20397            return mid;
20398    }
20399    return -(first + 1);
20400}
20401
20402function findAnnotations(session, row, dir) {
20403    var annotations = session.getAnnotations().sort(Range.comparePoints);
20404    if (!annotations.length)
20405        return;
20406    
20407    var i = binarySearch(annotations, {row: row, column: -1}, Range.comparePoints);
20408    if (i < 0)
20409        i = -i - 1;
20410    
20411    if (i >= annotations.length)
20412        i = dir > 0 ? 0 : annotations.length - 1;
20413    else if (i === 0 && dir < 0)
20414        i = annotations.length - 1;
20415    
20416    var annotation = annotations[i];
20417    if (!annotation || !dir)
20418        return;
20419
20420    if (annotation.row === row) {
20421        do {
20422            annotation = annotations[i += dir];
20423        } while (annotation && annotation.row === row);
20424        if (!annotation)
20425            return annotations.slice();
20426    }
20427    
20428    
20429    var matched = [];
20430    row = annotation.row;
20431    do {
20432        matched[dir < 0 ? "unshift" : "push"](annotation);
20433        annotation = annotations[i += dir];
20434    } while (annotation && annotation.row == row);
20435    return matched.length && matched;
20436}
20437
20438exports.showErrorMarker = function(editor, dir) {
20439    var session = editor.session;
20440    if (!session.widgetManager) {
20441        session.widgetManager = new LineWidgets(session);
20442        session.widgetManager.attach(editor);
20443    }
20444    
20445    var pos = editor.getCursorPosition();
20446    var row = pos.row;
20447    var oldWidget = session.widgetManager.getWidgetsAtRow(row).filter(function(w) {
20448        return w.type == "errorMarker";
20449    })[0];
20450    if (oldWidget) {
20451        oldWidget.destroy();
20452    } else {
20453        row -= dir;
20454    }
20455    var annotations = findAnnotations(session, row, dir);
20456    var gutterAnno;
20457    if (annotations) {
20458        var annotation = annotations[0];
20459        pos.column = (annotation.pos && typeof annotation.column != "number"
20460            ? annotation.pos.sc
20461            : annotation.column) || 0;
20462        pos.row = annotation.row;
20463        gutterAnno = editor.renderer.$gutterLayer.$annotations[pos.row];
20464    } else if (oldWidget) {
20465        return;
20466    } else {
20467        gutterAnno = {
20468            text: ["Looks good!"],
20469            className: "ace_ok"
20470        };
20471    }
20472    editor.session.unfold(pos.row);
20473    editor.selection.moveToPosition(pos);
20474    
20475    var w = {
20476        row: pos.row, 
20477        fixedWidth: true,
20478        coverGutter: true,
20479        el: dom.createElement("div"),
20480        type: "errorMarker"
20481    };
20482    var el = w.el.appendChild(dom.createElement("div"));
20483    var arrow = w.el.appendChild(dom.createElement("div"));
20484    arrow.className = "error_widget_arrow " + gutterAnno.className;
20485    
20486    var left = editor.renderer.$cursorLayer
20487        .getPixelPosition(pos).left;
20488    arrow.style.left = left + editor.renderer.gutterWidth - 5 + "px";
20489    
20490    w.el.className = "error_widget_wrapper";
20491    el.className = "error_widget " + gutterAnno.className;
20492    el.innerHTML = gutterAnno.text.join("<br>");
20493    
20494    el.appendChild(dom.createElement("div"));
20495    
20496    var kb = function(_, hashId, keyString) {
20497        if (hashId === 0 && (keyString === "esc" || keyString === "return")) {
20498            w.destroy();
20499            return {command: "null"};
20500        }
20501    };
20502    
20503    w.destroy = function() {
20504        if (editor.$mouseHandler.isMousePressed)
20505            return;
20506        editor.keyBinding.removeKeyboardHandler(kb);
20507        session.widgetManager.removeLineWidget(w);
20508        editor.off("changeSelection", w.destroy);
20509        editor.off("changeSession", w.destroy);
20510        editor.off("mouseup", w.destroy);
20511        editor.off("change", w.destroy);
20512    };
20513    
20514    editor.keyBinding.addKeyboardHandler(kb);
20515    editor.on("changeSelection", w.destroy);
20516    editor.on("changeSession", w.destroy);
20517    editor.on("mouseup", w.destroy);
20518    editor.on("change", w.destroy);
20519    
20520    editor.session.widgetManager.addLineWidget(w);
20521    
20522    w.el.onmousedown = editor.focus.bind(editor);
20523    
20524    editor.renderer.scrollCursorIntoView(null, 0.5, {bottom: w.el.offsetHeight});
20525};
20526
20527
20528dom.importCssString("\
20529    .error_widget_wrapper {\
20530        background: inherit;\
20531        color: inherit;\
20532        border:none\
20533    }\
20534    .error_widget {\
20535        border-top: solid 2px;\
20536        border-bottom: solid 2px;\
20537        margin: 5px 0;\
20538        padding: 10px 40px;\
20539        white-space: pre-wrap;\
20540    }\
20541    .error_widget.ace_error, .error_widget_arrow.ace_error{\
20542        border-color: #ff5a5a\
20543    }\
20544    .error_widget.ace_warning, .error_widget_arrow.ace_warning{\
20545        border-color: #F1D817\
20546    }\
20547    .error_widget.ace_info, .error_widget_arrow.ace_info{\
20548        border-color: #5a5a5a\
20549    }\
20550    .error_widget.ace_ok, .error_widget_arrow.ace_ok{\
20551        border-color: #5aaa5a\
20552    }\
20553    .error_widget_arrow {\
20554        position: absolute;\
20555        border: solid 5px;\
20556        border-top-color: transparent!important;\
20557        border-right-color: transparent!important;\
20558        border-left-color: transparent!important;\
20559        top: -5px;\
20560    }\
20561", "");
20562
20563});
20564
20565define("ace/ace",["require","exports","module","ace/lib/fixoldbrowsers","ace/lib/dom","ace/lib/event","ace/range","ace/editor","ace/edit_session","ace/undomanager","ace/virtual_renderer","ace/worker/wor
20565ker_client","ace/keyboard/hash_handler","ace/placeholder","ace/multi_select","ace/mode/folding/fold_mode","ace/theme/textmate","ace/ext/error_marker","ace/config"], function(require, exports, module) {
20566"use strict";
20567
20568require("./lib/fixoldbrowsers");
20569
20570var dom = require("./lib/dom");
20571var event = require("./lib/event");
20572
20573var Range = require("./range").Range;
20574var Editor = require("./editor").Editor;
20575var EditSession = require("./edit_session").EditSession;
20576var UndoManager = require("./undomanager").UndoManager;
20577var Renderer = require("./virtual_renderer").VirtualRenderer;
20578require("./worker/worker_client");
20579require("./keyboard/hash_handler");
20580require("./placeholder");
20581require("./multi_select");
20582require("./mode/folding/fold_mode");
20583require("./theme/textmate");
20584require("./ext/error_marker");
20585
20586exports.config = require("./config");
20587exports.require = require;
20588
20589if (typeof define === "function")
20590    exports.define = define;
20591exports.edit = function(el, options) {
20592    if (typeof el == "string") {
20593        var _id = el;
20594        el = document.getElementById(_id);
20595        if (!el)
20596            throw new Error("ace.edit can't find div #" + _id);
20597    }
20598
20599    if (el && el.env && el.env.editor instanceof Editor)
20600        return el.env.editor;
20601
20602    var value = "";
20603    if (el && /input|textarea/i.test(el.tagName)) {
20604        var oldNode = el;
20605        value = oldNode.value;
20606        el = dom.createElement("pre");
20607        oldNode.parentNode.replaceChild(el, oldNode);
20608    } else if (el) {
20609        value = el.textContent;
20610        el.innerHTML = "";
20611    }
20612
20613    var doc = exports.createEditSession(value);
20614
20615    var editor = new Editor(new Renderer(el), doc, options);
20616
20617    var env = {
20618        document: doc,
20619        editor: editor,
20620        onResize: editor.resize.bind(editor, null)
20621    };
20622    if (oldNode) env.textarea = oldNode;
20623    event.addListener(window, "resize", env.onResize);
20624    editor.on("destroy", function() {
20625        event.removeListener(window, "resize", env.onResize);
20626        env.editor.container.env = null; // prevent memory leak on old ie
20627    });
20628    editor.container.env = editor.env = env;
20629    return editor;
20630};
20631exports.createEditSession = function(text, mode) {
20632    var doc = new EditSession(text, mode);
20633    doc.setUndoManager(new UndoManager());
20634    return doc;
20635};
20636exports.Range = Range;
20637exports.EditSession = EditSession;
20638exports.UndoManager = UndoManager;
20639exports.VirtualRenderer = Renderer;
20640exports.version = "1.3.1";
20641});
20642            (function() {
20643                window.require(["ace/ace"], function(a) {
20644                    if (a) {
20645                        a.config.init(true);
20646                        a.define = window.define;
20647                    }
20648                    if (!window.ace)
20649                        window.ace = a;
20650                    for (var key in a) if (a.hasOwnProperty(key))
20651                        window.ace[key] = a[key];
20652                });
20653            })();
20654        

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.