diff --git a/gulliver/js/codemirror/.swp.php.html b/gulliver/js/codemirror/.swp.php.html new file mode 100755 index 000000000..5d4db0a09 Binary files /dev/null and b/gulliver/js/codemirror/.swp.php.html differ diff --git a/gulliver/js/codemirror/2/index.html b/gulliver/js/codemirror/2/index.html new file mode 100755 index 000000000..74a858a1e --- /dev/null +++ b/gulliver/js/codemirror/2/index.html @@ -0,0 +1,74 @@ + + + + CodeMirror 2 + + + + + + +

CodeMirror 2

+

This is a new project, aiming to create a CodeMirror-style + component without using an IFRAME. + The ACE editor proved + that this is viable, which motivated me to give it a shot. (Though I took a somewhat different + approach.)

+

No IE support so far, only tested with recent Chrome, Opera, + and Firefox builds. The JavaScript parser is the only one I've + ported over.

+

Code at https://github.com/marijnh/codemirror2.

+
+ + + diff --git a/gulliver/js/codemirror/2/issues b/gulliver/js/codemirror/2/issues new file mode 100755 index 000000000..6a0aa4598 --- /dev/null +++ b/gulliver/js/codemirror/2/issues @@ -0,0 +1,4 @@ +* Mouse drag to copy a region in X +* Indentation +* Line numbers +* Horizontal scrolling diff --git a/gulliver/js/codemirror/2/lib/codemirror.css b/gulliver/js/codemirror/2/lib/codemirror.css new file mode 100755 index 000000000..8fc49ca8b --- /dev/null +++ b/gulliver/js/codemirror/2/lib/codemirror.css @@ -0,0 +1,41 @@ +.CodeMirror { + position: relative; + border: 1px solid black; +} + +.CodeMirror-cursor { + width: 1px; + height: 1.2em !important; + background: black; + position: absolute; + margin-top: -.1em; + display: none; +} + +.CodeMirror-focused .CodeMirror-cursor { + display: block; +} + +.CodeMirror-code { + position: relative; + white-space: pre; + overflow: auto; + height: 300px; + font-family: monospace; + line-height: 1em; + padding: .4em; +} + +.CodeMirror-code div { + height: 1em; + min-width: 1px; +} + +span.CodeMirror-selected { + background: #bbb !important; + color: white !important; +} + +.CodeMirror-focused .CodeMirror-selected { + background: #88f !important; +} \ No newline at end of file diff --git a/gulliver/js/codemirror/2/lib/codemirror.js b/gulliver/js/codemirror/2/lib/codemirror.js new file mode 100755 index 000000000..9efc62c5b --- /dev/null +++ b/gulliver/js/codemirror/2/lib/codemirror.js @@ -0,0 +1,713 @@ +// TODO handle 0-offsets when editor is hidden + +var CodeMirror = (function() { + function Event(orig) {this.e = orig;} + Event.prototype = { + stop: function() { + if (this.e.stopPropagation) this.e.stopPropagation(); + else this.e.cancelBubble = true; + if (this.e.preventDefault) this.e.preventDefault(); + else this.e.returnValue = false; + }, + target: function() { + return this.e.target || this.e.srcElement; + }, + button: function() { + if (this.e.which) return this.e.which; + else if (this.e.button & 1) return 1; + else if (this.e.button & 2) return 3; + else if (this.e.button & 4) return 2; + } + }; + + function connect(node, type, handler, disconnect) { + function wrapHandler(event) {handler(new Event(event || window.event));} + if (typeof node.addEventListener == "function") { + node.addEventListener(type, wrapHandler, false); + if (disconnect) return function() {node.removeEventListener(type, wrapHandler, false);}; + } + else { + node.attachEvent("on" + type, wrapHandler); + if (disconnect) return function() {node.detachEvent("on" + type, wrapHandler);}; + } + } + + var lineSep = window.opera ? "\r\n" : "\n"; + + function removeElement(node) { + if (node.parentNode) node.parentNode.removeChild(node); + } + function eltOffset(node) { + var x = 0, y = 0; + while (node) { + x += node.offsetLeft; y += node.offsetTop; + node = node.offsetParent; + } + return {left: x, top: y}; + } + function addTextSpan(node, text) { + var span = node.appendChild(document.createElement("span")); + span.appendChild(document.createTextNode(text)); + return span; + } + + function posEq(a, b) {return a.line == b.line && a.ch == b.ch;} + function posLess(a, b) {return a.line < b.line || (a.line == b.line && a.ch < b.ch);} + function copyPos(x) {return {line: x.line, ch: x.ch};} + + function htmlEscape(str) { + return str.replace(/[<&]/, function(str) {return str == "&" ? "&" : "<";}); + } + + var movementKeys = {}; + for (var i = 35; i <= 40; i++) + movementKeys[i] = movementKeys["c" + i] = true; + + function lineElt(line) {return line.selDiv || line.div;} + + function CodeMirror(place, options) { + var div = this.div = document.createElement("div"); + if (place.appendChild) place.appendChild(div); else place(div); + div.className = "CodeMirror"; + var te = this.input = div.appendChild(document.createElement("textarea")); + te.style.position = "absolute"; + te.style.width = "10000px"; + te.style.left = te.style.top = "-100000px"; + var code = this.code = div.appendChild(document.createElement("div")); + code.className = "CodeMirror-code"; + this.cursor = code.appendChild(document.createElement("div")); + this.cursor.className = "CodeMirror-cursor"; + this.cursor.style.display = "none"; + this.restartBlink(); + this.measure = code.appendChild(document.createElement("span")); + this.measure.style.position = "absolute"; + this.measure.style.visibility = "hidden"; + this.measure.innerHTML = "-"; + + this.parser = parsers[options.parser || defaultParser]; + if (!this.parser) throw new Error("No parser found."); + + this.lines = []; this.work = []; + var zero = {line: 0, ch: 0}; + this.selection = {from: zero, to: zero}; this.prevSelection = {from: zero, to: zero}; + this.$setValue(options.value || ""); + this.endOperation(); + + var self = this; + connect(code, "mousedown", this.operation("onMouseDown")); + connect(te, "keyup", this.operation("onKeyUp")); + connect(te, "keydown", this.operation("onKeyDown")); + connect(te, "focus", function(){self.onFocus();}); + connect(te, "blur", function(){self.onBlur();}); + + connect(code, "dragenter", function(e){e.stop();}); + connect(code, "dragover", function(e){e.stop();}); + connect(code, "drop", this.operation("onDrop")); + connect(code, "paste", function(e){self.input.focus(); self.schedulePoll(20);}); + + if (document.activeElement == te) this.onFocus(); + else this.onBlur(); + } + + CodeMirror.prototype = { + $setValue: function(code) { + this.replaceLines(0, this.lines.length, code.split(/\r?\n/g)); + }, + getValue: function(code) { + var lines = []; + for (var i = 0, l = this.lines.length; i < l; i++) + lines.push(this.lines[i].text); + return lines.join("\n"); + }, + + onMouseDown: function(e) { + // Make sure we're not clicking the scrollbar + var corner = eltOffset(this.code); + if (e.e.pageX - corner.left > this.code.clientWidth || + e.e.pageY - corner.top > this.code.clientHeight) return; + + this.shiftSelecting = null; + var start = this.mouseEventPos(e), last = start, self = this; + this.setCursor(start.line, start.ch, false); + if (e.button() != 1) return; + + e.stop(); + function end() { + if (!self.focused) { + self.input.focus(); + self.onFocus(); + self.prepareInput(); + } + self.updateInput = true; + move(); up(); leave(); + } + + var move = connect(this.div, "mousemove", this.operation(function(e) { + var cur = this.clipPos(this.mouseEventPos(e)); + if (!posEq(cur, last)) { + last = cur; + this.setSelection(this.clipPos(start), cur); + } + }), true); + var up = connect(this.div, "mouseup", this.operation(function(e) { + this.setSelection(this.clipPos(start), this.clipPos(this.mouseEventPos(e))); + end(); + }), true); + // TODO dragging out of window should scroll + var leave = connect(this.div, "mouseout", this.operation(function(e) { + if (e.target() == this.div) end(); + }), true); + }, + onDrop: function(e) { + try {var text = e.e.dataTransfer.getData("Text");} + catch(e){} + if (!text) return; + var pos = this.clipPos(this.mouseEventPos(e)); + this.setSelection(pos, pos); + this.$replaceSelection(text); + }, + onKeyDown: function(e) { + if (!this.focused) this.onFocus(); + + var code = e.e.keyCode, ctrl = e.e.ctrlKey && !e.e.altKey; + if (code == 33 || code == 34) { // page up/down + this.scrollPage(code == 34); + e.stop(); + } + else if (ctrl && (code == 36 || code == 35)) { // ctrl-home/end + this.scrollEnd(code == 36); + e.stop(); + } + else if (ctrl && code == 65) { // ctrl-a + this.selectAll(); + e.stop(); + } + else if (!ctrl && code == 13) { // enter + this.insertNewline(); + e.stop(); + } + else if (!ctrl && code == 9) { // tab + this.handleTab(); + e.stop(); + } + else if (code == 16) { // shift + this.shiftSelecting = this.selection.inverted ? this.selection.to : this.selection.from; + } + else { + var id = (ctrl ? "c" : "") + code; + if (this.selection.inverted && movementKeys.hasOwnProperty(id)) { + this.reducedSelection = {anchor: this.input.selectionStart}; + this.input.selectionEnd = this.input.selectionStart; + } + this.schedulePoll(20, id); + } + }, + onKeyUp: function(e) { + if (this.reducedSelection) { + this.reducedSelection = null; + this.prepareInput(); + } + if (e.e.keyCode == 16) + this.shiftSelecting = null; + }, + + onFocus: function() { + this.focused = true; + this.schedulePoll(2000); + if (this.div.className.search(/\bCodeMirror-focused\b/) == -1) + this.div.className += " CodeMirror-focused"; + }, + onBlur: function() { + this.shiftSelecting = null; + this.focused = false; + this.div.className = this.div.className.replace(" CodeMirror-focused", ""); + }, + + replaceLines: function(from, to, newText) { + // Make sure only changed lines are replaced + var lines = this.lines; + while (from < to && newText[0] == lines[from].text) { + from++; newText.shift(); + } + while (to > from + 1 && newText[newText.length-1] == lines[to-1].text) { + to--; newText.pop(); + } + + // Update this.lines length and the associated DIVs + var lendiff = newText.length - (to - from); + if (lendiff < 0) { + var removed = lines.splice(from, -lendiff); + for (var i = 0, l = removed.length; i < l; i++) + removeElement(lineElt(removed[i])); + } + else if (lendiff > 0) { + var spliceargs = [from, 0], before = lines[from] ? lines[from].div : null; + for (var i = 0; i < lendiff; i++) { + var div = this.code.insertBefore(document.createElement("div"), before); + spliceargs.push({div: div}); + } + lines.splice.apply(lines, spliceargs); + } + for (var i = 0, l = newText.length; i < l; i++) { + var line = lines[from + i]; + var text = line.text = newText[i]; + if (line.selDiv) this.code.replaceChild(line.div, line.selDiv); + line.stateAfter = line.selDiv = null; + line.div.innerHTML = ""; + addTextSpan(line.div, line.text); + } + + var newWork = []; + for (var i = 0, l = this.work.length; i < l; i++) { + var task = this.work[i]; + if (task < from) newWork.push(task); + else if (task >= to) newWork.push(task + lendiff); + } + if (newText.length) newWork.push(from); + this.work = newWork; + this.startWorker(100); + + var selLine = this.selection.from.line; + if (lendiff || from != selLine || to != selLine + 1) + this.updateInput = true; + }, + + schedulePoll: function(time, keyId) { + var self = this; + function pollForKey() { + var state = self.readInput(); + if (state == "moved") movementKeys[keyId] = true; + if (state) self.schedulePoll(200, keyId); + else self.schedulePoll(2000); + } + function poll() { + self.readInput(); + if (self.focused) self.schedulePoll(2000); + } + clearTimeout(this.pollTimer); + if (time) this.pollTimer = setTimeout(this.operation(keyId ? pollForKey : poll), time); + }, + + readInput: function() { + var ed = this.editing, changed = false, sel = this.selection, te = this.input; + var text = te.value, selstart = te.selectionStart, selend = te.selectionEnd; + var changed = ed.text != text, rs = this.reducedSelection; + var moved = changed || selstart != ed.start || selend != (rs ? ed.start : ed.end); + if (!moved) return false; + + function computeOffset(n, startLine) { + var pos = 0; + while (true) { + var found = text.indexOf("\n", pos); + if (found == -1 || (text.charAt(found-1) == "\r" ? found - 1 : found) >= n) + return {line: startLine, ch: n - pos}; + startLine++; + pos = found + 1; + } + } + var from = computeOffset(selstart, ed.from), + to = computeOffset(selend, ed.from); + if (rs) { + from = selstart == rs.anchor ? to : from; + to = this.shiftSelecting ? sel.to : selstart == rs.anchor ? from : to; + if (!posLess(from, to)) { + this.reducedSelection = null; + this.selection.inverted = false; + var tmp = from; from = to; to = tmp; + } + } + + if (changed) { + this.shiftSelecting = null; + this.replaceLines(ed.from, ed.to, text.split(/\r?\n/g)); + } + ed.text = text; ed.start = selstart; ed.end = selend; + + this.setSelection(from, to); + return changed ? "changed" : moved ? "moved" : false; + }, + + prepareInput: function() { + var sel = this.selection, text = []; + var from = Math.max(0, sel.from.line - 1), to = Math.min(this.lines.length, sel.to.line + 2); + for (var i = from; i < to; i++) text.push(this.lines[i].text); + text = this.input.value = text.join(lineSep); + var startch = sel.from.ch, endch = sel.to.ch; + for (var i = from; i < sel.from.line; i++) + startch += lineSep.length + this.lines[i].text.length; + for (var i = from; i < sel.to.line; i++) + endch += lineSep.length + this.lines[i].text.length; + this.editing = {text: text, from: from, to: to, start: startch, end: endch}; + this.input.setSelectionRange(startch, this.reducedSelection ? startch : endch); + }, + + displaySelection: function() { + var sel = this.selection, pr = this.prevSelection; + if (posEq(sel.from, sel.to)) { + this.cursor.style.display = ""; + if (!posEq(pr.from, pr.to)) { + for (var i = pr.from.line; i <= pr.to.line; i++) + this.removeSelectedStyle(i); + } + var linediv = lineElt(this.lines[sel.from.line]); + this.cursor.style.top = linediv.offsetTop + "px"; + this.cursor.style.left = (linediv.offsetLeft + this.charWidth() * sel.from.ch) + "px"; + } + else { + this.cursor.style.display = "none"; + if (!posEq(pr.from, pr.to)) { + for (var i = pr.from.line, e = Math.min(sel.from.line, pr.to.line + 1); i < e; i++) + this.removeSelectedStyle(i); + for (var i = Math.max(sel.to.line + 1, pr.from.line); i <= pr.to.line; i++) + this.removeSelectedStyle(i); + } + if (sel.from.line == sel.to.line) { + this.setSelectedStyle(sel.from.line, sel.from.ch, sel.to.ch); + } + else { + this.setSelectedStyle(sel.from.line, sel.from.ch, null); + for (var i = sel.from.line + 1; i < sel.to.line; i++) + this.setSelectedStyle(i, 0, null); + this.setSelectedStyle(sel.to.line, 0, sel.to.ch); + } + } + + var head = sel.inverted ? sel.from : sel.to, headLine = lineElt(this.lines[head.line]); + var ypos = headLine.offsetTop, line = this.lineHeight(), + screen = this.code.clientHeight, screentop = this.code.scrollTop; + if (ypos < screentop) + this.code.scrollTop = Math.max(0, ypos - 10); + else if (ypos + line > screentop + screen) + this.code.scrollTop = (ypos + line + 10) - screen; + + var xpos = head.ch * this.charWidth(), + screenw = headLine.offsetWidth, screenleft = this.code.scrollLeft; + if (xpos < screenleft) + this.code.scrollLeft = Math.max(0, xpos - 10); + else if (xpos > screenw + screenleft) + this.code.scrollLeft = (xpos + 10) - screenw; + }, + + setSelection: function(from, to) { + var sel = this.selection, sh = this.shiftSelecting; + if (posLess(to, from)) {var tmp = to; to = from; from = tmp;} + if (sh) { + if (posLess(sh, from)) from = sh; + else if (posLess(to, sh)) to = sh; + } + + var startEq = posEq(sel.to, to), endEq = posEq(sel.from, from); + if (posEq(from, to)) sel.inverted = false; + else if (startEq && !endEq) sel.inverted = true; + else if (endEq && !startEq) sel.inverted = false; + sel.from = from; sel.to = to; + }, + + setCursor: function(line, ch) { + var pos = this.clipPos({line: line, ch: ch || 0}); + this.setSelection(pos, pos); + }, + scrollPage: function(down) { + var linesPerPage = Math.floor(this.div.clientHeight / this.lineHeight()); + this.setCursor(this.selection.from.line + (Math.max(linesPerPage - 1, 1) * (down ? 1 : -1))); + }, + scrollEnd: function(top) { + this.setCursor(top ? 0 : this.lines.length - 1); + }, + selectAll: function() { + this.shiftSelecting = null; + var endLine = this.lines.length - 1; + this.setSelection({line: 0, ch: 0}, {line: endLine, ch: this.lines[endLine].text.length}); + }, + insertNewline: function() { + this.$replaceSelection("\n", "end"); + this.indentLine(this.selection.from.line); + }, + handleTab: function() { + var sel = this.selection; + for (var i = sel.from.line, e = sel.to.line; i <= e; i++) + this.indentLine(i); + }, + indentLine: function(n) { + var state = this.getStateBefore(n); + if (!state) return; + var text = this.lines[n].text; + var curSpace = text.match(/^\s*/)[0].length; + var indentation = this.parser.indent(state, text.slice(curSpace)), diff = indentation - curSpace; + if (!diff) return; + + if (diff > 0) { + var space = ""; + for (var i = 0; i < diff; i++) space = space + " "; + this.replaceLines(n, n + 1, [space + text]); + } + else + this.replaceLines(n, n + 1, [text.slice(-diff)]); + var from = copyPos(this.selection.from), to = copyPos(this.selection.to); + if (from.line == n) from.ch = Math.max(indentation, from.ch + diff); + if (to.line == n) to.ch = Math.max(indentation, to.ch + diff); + this.setSelection(from, to); + }, + + $replaceSelection: function(code, collapse) { + var lines = code.split(/\r?\n/g), sel = this.selection; + lines[0] = this.lines[sel.from.line].text.slice(0, sel.from.ch) + lines[0]; + var endch = lines[lines.length-1].length; + lines[lines.length-1] += this.lines[sel.to.line].text.slice(sel.to.ch); + var from = sel.from, to = {line: sel.from.line + lines.length - 1, ch: endch}; + this.replaceLines(sel.from.line, sel.to.line + 1, lines); + if (collapse == "end") from = to; + else if (collapse == "start") to = from; + this.setSelection(from, to); + }, + + lineHeight: function() { + var firstline = this.lines[0]; + return lineElt(firstline).offsetHeight; + }, + charWidth: function() { + return this.measure.offsetWidth || 1; + }, + mouseEventPos: function(e) { + var off = eltOffset(lineElt(this.lines[0])), + x = e.e.pageX - off.left + this.code.scrollLeft, + y = e.e.pageY - off.top + this.code.scrollTop; + return {line: Math.floor(y / this.lineHeight()), ch: Math.floor(x / this.charWidth())}; + }, + clipPos: function(pos) { + pos.line = Math.max(0, Math.min(this.lines.length - 1, pos.line)); + pos.ch = Math.max(0, Math.min(this.lines[pos.line].text.length, pos.ch)); + return pos; + }, + + removeSelectedStyle: function(line) { + if (line >= this.lines.length) return; + line = this.lines[line]; + if (!line.selDiv) return; + this.code.replaceChild(line.div, line.selDiv); + line.selDiv = null; + }, + setSelectedStyle: function(line, start, end) { + line = this.lines[line]; + var div = line.selDiv, repl = line.div; + if (div) { + if (div.start == start && div.end == end) return; + repl = div; + } + div = line.selDiv = document.createElement("div"); + if (start > 0) + addTextSpan(div, line.text.slice(0, start)); + var seltext = line.text.slice(start, end == null ? line.text.length : end); + if (end == null) seltext += " "; + addTextSpan(div, seltext).className = "CodeMirror-selected"; + if (end != null && end < line.text.length) + addTextSpan(div, line.text.slice(end)); + div.start = start; div.end = end; + this.code.replaceChild(div, repl); + }, + + restartBlink: function() { + clearInterval(this.blinker); + this.cursor.style.visibility = ""; + var self = this; + this.blinker = setInterval(function() { + if (!self.div.parentNode) clearInterval(self.blinker); + var st = self.cursor.style; + st.visibility = st.visibility ? "" : "hidden"; + }, 650); + }, + + highlightLine: function(line, state) { + var stream = new StringStream(line.text), html = []; + while (!stream.done()) { + var start = stream.pos, style = this.parser.token(stream, state, start == 0); + var str = line.text.slice(start, stream.pos); + html.push("" + htmlEscape(str) + ""); + } + // TODO benchmark with removing/cloning/hiding/whatever + line.div.innerHTML = html.join(""); + }, + getStateBefore: function(n) { + var state; + for (var search = n - 1, lim = n - 40;; search--) { + if (search < 0) {state = this.parser.startState(); break;} + if (search < lim) return null; + if (state = this.lines[search].stateAfter) {state = copyState(state); break;} + } + for (search++; search < n; search++) { + var line = this.lines[search]; + this.highlightLine(line, state); + line.stateAfter = copyState(state); + } + if (!this.lines[n].stateAfter) this.work.push(n); + return state; + }, + highlightWorker: function(start) { + // TODO have a mode where the document is always parsed to the end + var end = +new Date + 200; + while (this.work.length) { + var task = this.work.pop() + if (this.lines[task].stateAfter) continue; + if (task) { + var state = this.lines[task-1].stateAfter; + if (!state) continue; + state = copyState(state); + } + else var state = this.parser.startState(); + + for (var i = task, l = this.lines.length; i < l; i++) { + var line = this.lines[i]; + if (line.stateAfter) break; + if (+new Date > end) { + this.work.push(i); + this.startWorker(300); + return; + } + this.highlightLine(line, state); + line.stateAfter = copyState(state); + } + } + }, + startWorker: function(time) { + if (!this.work.length) return; + var self = this; + clearTimeout(this.highlightTimeout); + this.highlightTimeout = setTimeout(this.operation("highlightWorker"), time); + }, + + startOperation: function() { + var ps = this.prevSelection, sel = this.selection; + ps.from = sel.from; ps.to = sel.to; + this.updateInput = false; + }, + endOperation: function() { + var ps = this.prevSelection, sel = this.selection; + if (!posEq(ps.from, sel.from) || !posEq(ps.to, sel.to)) { + this.displaySelection(); + this.restartBlink(); + } + if (ps.from.line != sel.from.line || ps.to.line != sel.to.line || this.updateInput) + this.prepareInput(); + }, + operation: function(f) { + var self = this; + if (typeof f == "string") f = this[f]; + return function() { + self.startOperation(); + var result = f.apply(self, arguments); + self.endOperation(); + return result; + }; + } + }; + + // Wrap API functions as operations + var proto = CodeMirror.prototype; + function apiOp(name) { + var f = proto[name]; + proto[name.slice(1)] = function() { + this.startOperation(); + return f.apply(this, arguments); + this.endOperation(); + }; + } + for (var n in proto) if (n.charAt(0) == "$") apiOp(n); + + var parsers = {}, defaultParser = null; + CodeMirror.addParser = function(name, parser) { + if (!defaultParser) defaultParser = name; + parsers[name] = parser; + }; + + CodeMirror.fromTextArea = function(textarea, options) { + if (options && options.value == null) + options.value = textarea.value; + + function save() {textarea.value = instance.getValue();} + if (textarea.form) { + var rmSubmit = connect(textarea.form, "submit", save); + var realSubmit = textarea.form.submit; + function wrappedSubmit() { + updateField(); + textarea.form.submit = realSubmit; + textarea.form.submit(); + textarea.form.submit = wrappedSubmit; + } + textarea.form.submit = wrappedSubmit; + } + + textarea.style.display = "none"; + var instance = new CodeMirror(function(node) { + textarea.parentNode.insertBefore(node, textarea.nextSibling); + }, options); + instance.save = save; + instance.toTextArea = function() { + save(); + textaarea.parentNode.removeChild(instance.div); + textarea.style.display = ""; + if (textarea.form) { + textarea.form.submit = realSubmit; + rmSubmit(); + } + }; + return instance; + }; + + function StringStream(string) { + this.pos = 0; + this.string = string; + } + StringStream.prototype = { + done: function() {return this.pos >= this.string.length;}, + peek: function() {return this.string.charAt(this.pos);}, + next: function() { + if (this.pos < this.string.length) + return this.string.charAt(this.pos++); + }, + eat: function(match) { + var ch = this.string.charAt(this.pos); + if (typeof match == "string") var ok = ch == match; + else var ok = ch && match.test ? match.test(ch) : match(ch); + if (ok) {this.pos++; return ch;} + }, + eatWhile: function(match) { + var start = this.pos; + while (this.eat(match)); + if (this.pos > start) return this.string.slice(start, this.pos); + }, + backUp: function(n) {this.pos -= n;}, + column: function() {return this.pos;}, + eatSpace: function() { + var start = this.pos; + while (/\s/.test(this.string.charAt(this.pos))) this.pos++; + return this.pos - start; + }, + match: function(pattern, consume, caseInsensitive) { + if (typeof pattern == "string") { + function cased(str) {return caseInsensitive ? str.toLowerCase() : str;} + if (cased(this.string).indexOf(cased(pattern), this.pos) == this.pos) { + if (consume !== false) this.pos += str.length; + return true; + } + } + else { + var match = this.string.slice(this.pos).match(pattern); + if (match && consume !== false) this.pos += match[0].length; + return match; + } + } + }; + + function copyState(state) { + if (state.copy) return state.copy(); + var nstate = {}; + for (var n in state) { + var val = state[n]; + if (val instanceof Array) val = val.concat([]); + nstate[n] = val; + } + return nstate; + } + + return CodeMirror; +})(); diff --git a/gulliver/js/codemirror/2/mode/javascript/javascript.css b/gulliver/js/codemirror/2/mode/javascript/javascript.css new file mode 100755 index 000000000..638113e13 --- /dev/null +++ b/gulliver/js/codemirror/2/mode/javascript/javascript.css @@ -0,0 +1,8 @@ +span.js-punctuation {color: #666;} +span.js-operator {color: #666;} +span.js-keyword {color: #90b;} +span.js-atom {color: #281;} +span.js-variabledef {color: #00f;} +span.js-localvariable {color: #049;} +span.js-comment {color: #a70;} +span.js-string {color: #a22;} diff --git a/gulliver/js/codemirror/2/mode/javascript/javascript.js b/gulliver/js/codemirror/2/mode/javascript/javascript.js new file mode 100755 index 000000000..82e491fd1 --- /dev/null +++ b/gulliver/js/codemirror/2/mode/javascript/javascript.js @@ -0,0 +1,328 @@ +CodeMirror.addParser("javascript", (function() { + // Tokenizer + + var keywords = function(){ + function kw(type) {return {type: type, style: "js-keyword"};} + var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c"); + var operator = kw("operator"), atom = {type: "atom", style: "js-atom"}; + return { + "if": A, "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B, + "return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C, + "var": kw("var"), "function": kw("function"), "catch": kw("catch"), + "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"), + "in": operator, "typeof": operator, "instanceof": operator, + "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom + }; + }(); + + var isOperatorChar = /[+\-*&%=<>!?|]/; + + function chain(stream, state, f) { + state.tokenize = f; + return f(stream, state); + } + + function nextUntilUnescaped(stream, end) { + var escaped = false, next; + while ((next = stream.next()) != null) { + if (next == end && !escaped) + return false; + escaped = !escaped && next == "\\"; + } + return escaped; + } + + function jsTokenBase(stream, state) { + function readOperator(ch) { + return {type: "operator", style: "js-operator", content: ch + stream.eatWhile(isOperatorChar)}; + } + + var ch = stream.next(); + if (ch == '"' || ch == "'") + return chain(stream, state, jsTokenString(ch)); + else if (/[\[\]{}\(\),;\:\.]/.test(ch)) + return {type: ch, style: "js-punctuation"}; + else if (ch == "0" && stream.eat(/x/i)) { + while (stream.eat(/[\da-f]/i)); + return {type: "number", style: "js-atom"}; + } + else if (/\d/.test(ch)) { + stream.match(/^\d*(?:\.\d*)?(?:e[+\-]?\d+)?/); + return {type: "number", style: "js-atom"}; + } + else if (ch == "/") { + if (stream.eat("*")) { + return chain(stream, state, jsTokenComment); + } + else if (stream.eat("/")) { + while (stream.next() != null); + return {type: "comment", style: "js-comment"}; + } + else if (state.reAllowed) { + nextUntilUnescaped(stream, "/"); + while (stream.eat(/[gimy]/)); // 'y' is "sticky" option in Mozilla + return {type: "regexp", style: "js-string"}; + } + else return readOperator(ch); + } + else if (isOperatorChar.test(ch)) + return readOperator(ch); + else { + var word = ch + stream.eatWhile(/[\w\$_]/); + var known = keywords.propertyIsEnumerable(word) && keywords[word]; + return known ? {type: known.type, style: known.style, content: word} : + {type: "variable", style: "js-variable", content: word}; + } + } + + function jsTokenString(quote) { + return function(stream, state) { + if (!nextUntilUnescaped(stream, quote)) + state.tokenize = jsTokenBase; + return {type: "string", style: "js-string"}; + }; + } + + function jsTokenComment(stream, state) { + var maybeEnd = false, ch; + while (ch = stream.next()) { + if (ch == "/" && maybeEnd) { + state.tokenize = jsTokenBase; + break; + } + maybeEnd = (ch == "*"); + } + return {type: "comment", style: "js-comment"}; + } + + // Parser + + var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true}; + + function JSLexical(indented, column, type, align, prev, info) { + this.indented = indented; + this.column = column; + this.type = type; + this.prev = prev; + this.info = info; + if (align != null) this.align = align; + } + + function indentJS(state, textAfter) { + var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical, + type = lexical.type, closing = firstChar == type, iu = state.indentUnit; + if (type == "vardef") return lexical.indented + 4; + else if (type == "form" && firstChar == "{") return lexical.indented; + else if (type == "stat" || type == "form") return lexical.indented + iu; + else if (lexical.info == "switch" && !closing) + return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? iu : 2 * iu); + else if (lexical.align) return lexical.column - (closing ? 1 : 0); + else return lexical.indented + (closing ? 0 : iu); + } + + function startState(basecolumn, indentUnit) { + if (!indentUnit) indentUnit = 2; + return { + tokenize: jsTokenBase, + reAllowed: true, + cc: [], + lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false), + context: null, + indented: 0, + indentUnit: indentUnit + }; + } + + function parseJS(token, column, indent, state) { + var cc = state.cc, type = token.type; + + function pass() { + for (var i = arguments.length - 1; i >= 0; i--) cc.push(arguments[i]); + } + var cx = { + state: state, + column: column, + pass: pass, + cont: function(){pass.apply(null, arguments); return true;}, + register: function(varname) { + if (state.context) { + cx.marked = "js-variabledef"; + state.context.vars[varname] = true; + } + } + }; + function inScope(varname) { + var cursor = state.context; + while (cursor) { + if (cursor.vars[varname]) + return true; + cursor = cursor.prev; + } + } + + if (indent != null) { + if (!state.lexical.hasOwnProperty("align")) + state.lexical.align = false; + state.indented = indent; + } + + if (type == "whitespace" || type == "comment") + return token.style; + if (!state.lexical.hasOwnProperty("align")) + state.lexical.align = true; + + while(true) { + var combinator = cc.length ? cc.pop() : state.json ? expression : statement; + if (combinator(cx, type, token.content)) { + while(cc.length && cc[cc.length - 1].lex) + cc.pop()(cx); + if (cx.marked) return cx.marked; + if (type == "variable" && inScope(token.content)) return "js-localvariable"; + return token.style; + } + } + } + + // Combinators + + function pushcontext(cx) { + cx.state.context = {prev: cx.state.context, vars: {"this": true, "arguments": true}}; + } + function popcontext(cx) { + cx.state.context = cx.state.context.prev; + } + function pushlex(type, info) { + var result = function(cx) { + var state = cx.state; + state.lexical = new JSLexical(state.indented, cx.column, type, null, state.lexical, info) + }; + result.lex = true; + return result; + } + function poplex(cx) { + var state = cx.state; + if (state.lexical.type == ")") + state.indented = state.lexical.indented; + state.lexical = state.lexical.prev; + } + poplex.lex = true; + + function expect(wanted) { + return function expecting(cx, type) { + if (type == wanted) return cx.cont(); + else if (wanted == ";") return; + else return cx.cont(arguments.callee); + }; + } + + function statement(cx, type) { + if (type == "var") return cx.cont(pushlex("vardef"), vardef1, expect(";"), poplex); + if (type == "keyword a") return cx.cont(pushlex("form"), expression, statement, poplex); + if (type == "keyword b") return cx.cont(pushlex("form"), statement, poplex); + if (type == "{") return cx.cont(pushlex("}"), block, poplex); + if (type == ";") return cx.cont(); + if (type == "function") return cx.cont(functiondef); + if (type == "for") return cx.cont(pushlex("form"), expect("("), pushlex(")"), forspec1, expect(")"), + poplex, statement, poplex); + if (type == "variable") return cx.cont(pushlex("stat"), maybelabel); + if (type == "switch") return cx.cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"), + block, poplex, poplex); + if (type == "case") return cx.cont(expression, expect(":")); + if (type == "default") return cx.cont(expect(":")); + if (type == "catch") return cx.cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"), + statement, poplex, popcontext); + return cx.pass(pushlex("stat"), expression, expect(";"), poplex); + } + function expression(cx, type) { + if (atomicTypes.hasOwnProperty(type)) return cx.cont(maybeoperator); + if (type == "function") return cx.cont(functiondef); + if (type == "keyword c") return cx.cont(expression); + if (type == "(") return cx.cont(pushlex(")"), expression, expect(")"), poplex, maybeoperator); + if (type == "operator") return cx.cont(expression); + if (type == "[") return cx.cont(pushlex("]"), commasep(expression, "]"), poplex, maybeoperator); + if (type == "{") return cx.cont(pushlex("}"), commasep(objprop, "}"), poplex, maybeoperator); + return cx.cont(); + } + function maybeoperator(cx, type, value) { + if (type == "operator" && /\+\+|--/.test(value)) return cx.cont(maybeoperator); + if (type == "operator") return cx.cont(expression); + if (type == ";") return; + if (type == "(") return cx.cont(pushlex(")"), commasep(expression, ")"), poplex, maybeoperator); + if (type == ".") return cx.cont(property, maybeoperator); + if (type == "[") return cx.cont(pushlex("]"), expression, expect("]"), poplex, maybeoperator); + } + function maybelabel(cx, type) { + if (type == ":") return cx.cont(poplex, statement); + return cx.pass(maybeoperator, expect(";"), poplex); + } + function property(cx, type) { + if (type == "variable") {cx.marked = "js-property"; return cx.cont();} + } + function objprop(cx, type) { + if (type == "variable") cx.marked = "js-property"; + if (atomicTypes.hasOwnProperty(type)) return cx.cont(expect(":"), expression); + } + function commasep(what, end) { + function proceed(cx, type) { + if (type == ",") return cx.cont(what, proceed); + if (type == end) return cx.cont(); + return cx.cont(expect(end)); + } + return function commaSeparated(cx, type) { + if (type == end) return cx.cont(); + else return cx.pass(what, proceed); + }; + } + function block(cx, type) { + if (type == "}") return cx.cont(); + return cx.pass(statement, block); + } + function vardef1(cx, type, value) { + if (type == "variable"){cx.register(value); return cx.cont(vardef2);} + return cx.cont(); + } + function vardef2(cx, type, value) { + if (value == "=") return cx.cont(expression, vardef2); + if (type == ",") return cx.cont(vardef1); + } + function forspec1(cx, type) { + if (type == "var") return cx.cont(vardef1, forspec2); + if (type == ";") return cx.pass(forspec2); + if (type == "variable") return cx.cont(formaybein); + return cx.pass(forspec2); + } + function formaybein(cx, type, value) { + if (value == "in") return cx.cont(expression); + return cx.cont(maybeoperator, forspec2); + } + function forspec2(cx, type, value) { + if (type == ";") return cx.cont(forspec3); + if (value == "in") return cx.cont(expression); + return cx.cont(expression, expect(";"), forspec3); + } + function forspec3(cx, type) { + if (type != ")") cx.cont(expression); + } + function functiondef(cx, type, value) { + if (type == "variable") {cx.register(value); return cx.cont(functiondef);} + if (type == "(") return cx.cont(pushcontext, commasep(funarg, ")"), statement, popcontext); + } + function funarg(cx, type, value) { + if (type == "variable") {cx.register(value); return cx.cont();} + } + + // Interface + + return { + startState: startState, + token: function(stream, state) { + if (stream.column() == 0) + var indent = stream.eatSpace(); + var token = state.tokenize(stream, state); + state.reAllowed = token.type == "operator" || token.type == "keyword c" || token.type.match(/^[\[{}\(,;:]$/); + stream.eatSpace(); + return parseJS(token, stream.column(), indent, state); + }, + indent: indentJS + }; +})()); diff --git a/gulliver/js/codemirror/LICENSE b/gulliver/js/codemirror/LICENSE new file mode 100755 index 000000000..aab5d221f --- /dev/null +++ b/gulliver/js/codemirror/LICENSE @@ -0,0 +1,23 @@ + Copyright (c) 2007-2010 Marijn Haverbeke + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any + damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and + redistribute it freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + Marijn Haverbeke + marijnh@gmail.com diff --git a/gulliver/js/codemirror/contrib/csharp/css/csharpcolors.css b/gulliver/js/codemirror/contrib/csharp/css/csharpcolors.css new file mode 100755 index 000000000..234f1ad00 --- /dev/null +++ b/gulliver/js/codemirror/contrib/csharp/css/csharpcolors.css @@ -0,0 +1,60 @@ +html { + cursor: text; +} + +.editbox { + margin: .4em; + padding: 0; + font-family: monospace; + font-size: 10pt; + color: black; +} + +pre.code, .editbox { + color: #666666; +} + +.editbox p { + margin: 0; +} + +span.csharp-punctuation { + color: green; +} + +span.csharp-operator { + color: purple; +} + +span.csharp-keyword { + color: blue; +} + +span.csharp-atom { + color: brown; +} + +span.csharp-variable { + color: black; +} + +span.csharp-variabledef { + color: #0000FF; +} + +span.csharp-localvariable { + color: #004499; +} + +span.csharp-property { + color: black; +} + +span.csharp-comment { + color: green; +} + +span.csharp-string { + color: red; +} + diff --git a/gulliver/js/codemirror/contrib/csharp/index.html b/gulliver/js/codemirror/contrib/csharp/index.html new file mode 100755 index 000000000..e846f0216 --- /dev/null +++ b/gulliver/js/codemirror/contrib/csharp/index.html @@ -0,0 +1,61 @@ + + + + CodeMirror: C# demonstration + + + + +

Demonstration of CodeMirror's C# highlighter.

+ +

Written by Boris Gaber and Christopher Buchino (license).

+ +
+ +
+ + + + + diff --git a/gulliver/js/codemirror/contrib/csharp/js/parsecsharp.js b/gulliver/js/codemirror/contrib/csharp/js/parsecsharp.js new file mode 100755 index 000000000..214571199 --- /dev/null +++ b/gulliver/js/codemirror/contrib/csharp/js/parsecsharp.js @@ -0,0 +1,329 @@ +/* Parse function for JavaScript. Makes use of the tokenizer from + * tokenizecsharp.js. Note that your parsers do not have to be + * this complicated -- if you don't want to recognize local variables, + * in many languages it is enough to just look for braces, semicolons, + * parentheses, etc, and know when you are inside a string or comment. + * + * See manual.html for more info about the parser interface. + */ + +var JSParser = Editor.Parser = (function() { + // Token types that can be considered to be atoms. + var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true}; + // Setting that can be used to have JSON data indent properly. + var json = false; + // Constructor for the lexical context objects. + function CSharpLexical(indented, column, type, align, prev, info) { + // indentation at start of this line + this.indented = indented; + // column at which this scope was opened + this.column = column; + // type of scope ('vardef', 'stat' (statement), 'form' (special form), '[', '{', or '(') + this.type = type; + // '[', '{', or '(' blocks that have any text after their opening + // character are said to be 'aligned' -- any lines below are + // indented all the way to the opening character. + if (align != null) + this.align = align; + // Parent scope, if any. + this.prev = prev; + this.info = info; + } + + // CSharp indentation rules. + function indentCSharp(lexical) { + return function(firstChars) { + var firstChar = firstChars && firstChars.charAt(0), type = lexical.type; + var closing = firstChar == type; + if (type == "vardef") + return lexical.indented + 4; + else if (type == "form" && firstChar == "{") + return lexical.indented; + else if (type == "stat" || type == "form") + return lexical.indented + indentUnit; + else if (lexical.info == "switch" && !closing) + return lexical.indented + (/^(?:case|default)\b/.test(firstChars) ? indentUnit : 2 * indentUnit); + else if (lexical.align) + return lexical.column - (closing ? 1 : 0); + else + return lexical.indented + (closing ? 0 : indentUnit); + }; + } + + // The parser-iterator-producing function itself. + function parseCSharp(input, basecolumn) { + // Wrap the input in a token stream + var tokens = tokenizeCSharp(input); + // The parser state. cc is a stack of actions that have to be + // performed to finish the current statement. For example we might + // know that we still need to find a closing parenthesis and a + // semicolon. Actions at the end of the stack go first. It is + // initialized with an infinitely looping action that consumes + // whole statements. + var cc = [statements]; + // The lexical scope, used mostly for indentation. + var lexical = new CSharpLexical((basecolumn || 0) - indentUnit, 0, "block", false); + // Current column, and the indentation at the start of the current + // line. Used to create lexical scope objects. + var column = 0; + var indented = 0; + // Variables which are used by the mark, cont, and pass functions + // below to communicate with the driver loop in the 'next' + // function. + var consume, marked; + + // The iterator object. + var parser = {next: next, copy: copy}; + + function next(){ + // Start by performing any 'lexical' actions (adjusting the + // lexical variable), or the operations below will be working + // with the wrong lexical state. + while(cc[cc.length - 1].lex) + cc.pop()(); + + // Fetch a token. + var token = tokens.next(); + + // Adjust column and indented. + if (token.type == "whitespace" && column == 0) + indented = token.value.length; + column += token.value.length; + if (token.content == "\n"){ + indented = column = 0; + // If the lexical scope's align property is still undefined at + // the end of the line, it is an un-aligned scope. + if (!("align" in lexical)) + lexical.align = false; + // Newline tokens get an indentation function associated with + // them. + token.indentation = indentCSharp(lexical); + } + // No more processing for meaningless tokens. + if (token.type == "whitespace" || token.type == "comment") + return token; + // When a meaningful token is found and the lexical scope's + // align is undefined, it is an aligned scope. + if (!("align" in lexical)) + lexical.align = true; + + // Execute actions until one 'consumes' the token and we can + // return it. + while(true) { + consume = marked = false; + // Take and execute the topmost action. + cc.pop()(token.type, token.content); + if (consume){ + // Marked is used to change the style of the current token. + if (marked) + token.style = marked; + return token; + } + } + } + + // This makes a copy of the parser state. It stores all the + // stateful variables in a closure, and returns a function that + // will restore them when called with a new input stream. Note + // that the cc array has to be copied, because it is contantly + // being modified. Lexical objects are not mutated, and context + // objects are not mutated in a harmful way, so they can be shared + // between runs of the parser. + function copy(){ + var _lexical = lexical, _cc = cc.concat([]), _tokenState = tokens.state; + + return function copyParser(input){ + lexical = _lexical; + cc = _cc.concat([]); // copies the array + column = indented = 0; + tokens = tokenizeCSharp(input, _tokenState); + return parser; + }; + } + + // Helper function for pushing a number of actions onto the cc + // stack in reverse order. + function push(fs){ + for (var i = fs.length - 1; i >= 0; i--) + cc.push(fs[i]); + } + // cont and pass are used by the action functions to add other + // actions to the stack. cont will cause the current token to be + // consumed, pass will leave it for the next action. + function cont(){ + push(arguments); + consume = true; + } + function pass(){ + push(arguments); + consume = false; + } + // Used to change the style of the current token. + function mark(style){ + marked = style; + } + + // Push a new lexical context of the given type. + function pushlex(type, info) { + var result = function(){ + lexical = new CSharpLexical(indented, column, type, null, lexical, info) + }; + result.lex = true; + return result; + } + // Pop off the current lexical context. + function poplex(){ + lexical = lexical.prev; + } + poplex.lex = true; + // The 'lex' flag on these actions is used by the 'next' function + // to know they can (and have to) be ran before moving on to the + // next token. + + // Creates an action that discards tokens until it finds one of + // the given type. + function expect(wanted){ + return function expecting(type){ + if (type == wanted) cont(); + else cont(arguments.callee); + }; + } + + // Looks for a statement, and then calls itself. + function statements(type){ + return pass(statement, statements); + } + // Dispatches various types of statements based on the type of the + // current token. + function statement(type){ + if (type == "var") cont(pushlex("vardef"), vardef1, expect(";"), poplex); + else if (type == "keyword a") cont(pushlex("form"), expression, statement, poplex); + else if (type == "keyword b") cont(pushlex("form"), statement, poplex); + else if (type == "{" && json) cont(pushlex("}"), commasep(objprop, "}"), poplex); + else if (type == "{") cont(pushlex("}"), block, poplex); + else if (type == "function") cont(functiondef); + else if (type == "for") cont(pushlex("form"), expect("("), pushlex(")"), forspec1, expect(")"), poplex, statement, poplex); + else if (type == "variable") cont(pushlex("stat"), maybelabel); + else if (type == "switch") cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"), block, poplex, poplex); + else if (type == "case") cont(expression, expect(":")); + else if (type == "default") cont(expect(":")); + else if (type == "catch") cont(pushlex("form"), expect("("), funarg, expect(")"), statement, poplex); + + else if (type == "class") cont(classdef); + else if (type == "keyword d") cont(statement); + + else pass(pushlex("stat"), expression, expect(";"), poplex); + } + // Dispatch expression types. + function expression(type){ + if (atomicTypes.hasOwnProperty(type)) cont(maybeoperator); + else if (type == "function") cont(functiondef); + else if (type == "keyword c") cont(expression); + else if (type == "(") cont(pushlex(")"), expression, expect(")"), poplex, maybeoperator); + else if (type == "operator") cont(expression); + else if (type == "[") cont(pushlex("]"), commasep(expression, "]"), poplex, maybeoperator); + else if (type == "{") cont(pushlex("}"), commasep(objprop, "}"), poplex, maybeoperator); + } + // Called for places where operators, function calls, or + // subscripts are valid. Will skip on to the next action if none + // is found. + function maybeoperator(type){ + if (type == "operator") cont(expression); + else if (type == "(") cont(pushlex(")"), expression, commasep(expression, ")"), poplex, maybeoperator); + else if (type == ".") cont(property, maybeoperator); + else if (type == "[") cont(pushlex("]"), expression, expect("]"), poplex, maybeoperator); + } + // When a statement starts with a variable name, it might be a + // label. If no colon follows, it's a regular statement. + function maybelabel(type){ + if (type == ":") cont(poplex, statement); + else if (type == "(") cont(commasep(funarg, ")"), poplex, statement); // method definition + else if (type == "{") cont(poplex, pushlex("}"), block, poplex); // property definition + else pass(maybeoperator, expect(";"), poplex); + } + // Property names need to have their style adjusted -- the + // tokenizer thinks they are variables. + function property(type){ + if (type == "variable") {mark("csharp-property"); cont();} + } + // This parses a property and its value in an object literal. + function objprop(type){ + if (type == "variable") mark("csharp-property"); + if (atomicTypes.hasOwnProperty(type)) cont(expect(":"), expression); + } + // Parses a comma-separated list of the things that are recognized + // by the 'what' argument. + function commasep(what, end){ + function proceed(type) { + if (type == ",") cont(what, proceed); + else if (type == end) cont(); + else cont(expect(end)); + }; + return function commaSeparated(type) { + if (type == end) cont(); + else pass(what, proceed); + }; + } + // Look for statements until a closing brace is found. + function block(type){ + if (type == "}") cont(); + else pass(statement, block); + } + // Variable definitions are split into two actions -- 1 looks for + // a name or the end of the definition, 2 looks for an '=' sign or + // a comma. + function vardef1(type, value){ + if (type == "variable"){cont(vardef2);} + else cont(); + } + function vardef2(type, value){ + if (value == "=") cont(expression, vardef2); + else if (type == ",") cont(vardef1); + } + // For loops. + function forspec1(type){ + if (type == "var") cont(vardef1, forspec2); + else if (type == "keyword d") cont(vardef1, forspec2); + else if (type == ";") pass(forspec2); + else if (type == "variable") cont(formaybein); + else pass(forspec2); + } + function formaybein(type, value){ + if (value == "in") cont(expression); + else cont(maybeoperator, forspec2); + } + function forspec2(type, value){ + if (type == ";") cont(forspec3); + else if (value == "in") cont(expression); + else cont(expression, expect(";"), forspec3); + } + function forspec3(type) { + if (type == ")") pass(); + else cont(expression); + } + // A function definition creates a new context, and the variables + // in its argument list have to be added to this context. + function functiondef(type, value){ + if (type == "variable") cont(functiondef); + else if (type == "(") cont(commasep(funarg, ")"), statement); + } + function funarg(type, value){ + if (type == "variable"){cont();} + } + + function classdef(type) { + if (type == "variable") cont(classdef, statement); + else if (type == ":") cont(classdef, statement); + } + + return parser; + } + + return { + make: parseCSharp, + electricChars: "{}:", + configure: function(obj) { + if (obj.json != null) json = obj.json; + } + }; +})(); diff --git a/gulliver/js/codemirror/contrib/csharp/js/tokenizecsharp.js b/gulliver/js/codemirror/contrib/csharp/js/tokenizecsharp.js new file mode 100755 index 000000000..5d89e2615 --- /dev/null +++ b/gulliver/js/codemirror/contrib/csharp/js/tokenizecsharp.js @@ -0,0 +1,196 @@ +/* Tokenizer for CSharp code */ + +var tokenizeCSharp = (function() { + // Advance the stream until the given character (not preceded by a + // backslash) is encountered, or the end of the line is reached. + function nextUntilUnescaped(source, end) { + var escaped = false; + var next; + while (!source.endOfLine()) { + var next = source.next(); + if (next == end && !escaped) + return false; + escaped = !escaped && next == "\\"; + } + return escaped; + } + + // A map of JavaScript's keywords. The a/b/c keyword distinction is + // very rough, but it gives the parser enough information to parse + // correct code correctly (we don't care that much how we parse + // incorrect code). The style information included in these objects + // is used by the highlighter to pick the correct CSS style for a + // token. + var keywords = function(){ + function result(type, style){ + return {type: type, style: "csharp-" + style}; + } + // keywords that take a parenthised expression, and then a + // statement (if) + var keywordA = result("keyword a", "keyword"); + // keywords that take just a statement (else) + var keywordB = result("keyword b", "keyword"); + // keywords that optionally take an expression, and form a + // statement (return) + var keywordC = result("keyword c", "keyword"); + var operator = result("operator", "keyword"); + var atom = result("atom", "atom"); + // just a keyword with no indentation implications + var keywordD = result("keyword d", "keyword"); + + return { + "if": keywordA, "while": keywordA, "with": keywordA, + "else": keywordB, "do": keywordB, "try": keywordB, "finally": keywordB, + "return": keywordC, "break": keywordC, "continue": keywordC, "new": keywordC, "delete": keywordC, "throw": keywordC, + "in": operator, "typeof": operator, "instanceof": operator, + "var": result("var", "keyword"), "function": result("function", "keyword"), "catch": result("catch", "keyword"), + "for": result("for", "keyword"), "switch": result("switch", "keyword"), + "case": result("case", "keyword"), "default": result("default", "keyword"), + "true": atom, "false": atom, "null": atom, + + "class": result("class", "keyword"), "namespace": result("class", "keyword"), + + "public": keywordD, "private": keywordD, "protected": keywordD, "internal": keywordD, + "extern": keywordD, "override": keywordD, "virtual": keywordD, "abstract": keywordD, + "static": keywordD, "out": keywordD, "ref": keywordD, "const": keywordD, + + "foreach": result("for", "keyword"), "using": keywordC, + + "int": keywordD, "double": keywordD, "long": keywordD, "bool": keywordD, "char": keywordD, + "void": keywordD, "string": keywordD, "byte": keywordD, "sbyte": keywordD, "decimal": keywordD, + "float": keywordD, "uint": keywordD, "ulong": keywordD, "object": keywordD, + "short": keywordD, "ushort": keywordD, + + "get": keywordD, "set": keywordD, "value": keywordD + }; + }(); + + // Some helper regexps + var isOperatorChar = /[+\-*&%=<>!?|]/; + var isHexDigit = /[0-9A-Fa-f]/; + var isWordChar = /[\w\$_]/; + + // Wrapper around jsToken that helps maintain parser state (whether + // we are inside of a multi-line comment and whether the next token + // could be a regular expression). + function jsTokenState(inside, regexp) { + return function(source, setState) { + var newInside = inside; + var type = jsToken(inside, regexp, source, function(c) {newInside = c;}); + var newRegexp = type.type == "operator" || type.type == "keyword c" || type.type.match(/^[\[{}\(,;:]$/); + if (newRegexp != regexp || newInside != inside) + setState(jsTokenState(newInside, newRegexp)); + return type; + }; + } + + // The token reader, inteded to be used by the tokenizer from + // tokenize.js (through jsTokenState). Advances the source stream + // over a token, and returns an object containing the type and style + // of that token. + function jsToken(inside, regexp, source, setInside) { + function readHexNumber(){ + source.next(); // skip the 'x' + source.nextWhileMatches(isHexDigit); + return {type: "number", style: "csharp-atom"}; + } + + function readNumber() { + source.nextWhileMatches(/[0-9]/); + if (source.equals(".")){ + source.next(); + source.nextWhileMatches(/[0-9]/); + } + if (source.equals("e") || source.equals("E")){ + source.next(); + if (source.equals("-")) + source.next(); + source.nextWhileMatches(/[0-9]/); + } + return {type: "number", style: "csharp-atom"}; + } + // Read a word, look it up in keywords. If not found, it is a + // variable, otherwise it is a keyword of the type found. + function readWord() { + source.nextWhileMatches(isWordChar); + var word = source.get(); + var known = keywords.hasOwnProperty(word) && keywords.propertyIsEnumerable(word) && keywords[word]; + return known ? {type: known.type, style: known.style, content: word} : + {type: "variable", style: "csharp-variable", content: word}; + } + function readRegexp() { + nextUntilUnescaped(source, "/"); + source.nextWhileMatches(/[gi]/); + return {type: "regexp", style: "csharp-string"}; + } + // Mutli-line comments are tricky. We want to return the newlines + // embedded in them as regular newline tokens, and then continue + // returning a comment token for every line of the comment. So + // some state has to be saved (inside) to indicate whether we are + // inside a /* */ sequence. + function readMultilineComment(start){ + var newInside = "/*"; + var maybeEnd = (start == "*"); + while (true) { + if (source.endOfLine()) + break; + var next = source.next(); + if (next == "/" && maybeEnd){ + newInside = null; + break; + } + maybeEnd = (next == "*"); + } + setInside(newInside); + return {type: "comment", style: "csharp-comment"}; + } + function readOperator() { + source.nextWhileMatches(isOperatorChar); + return {type: "operator", style: "csharp-operator"}; + } + function readString(quote) { + var endBackSlash = nextUntilUnescaped(source, quote); + setInside(endBackSlash ? quote : null); + return {type: "string", style: "csharp-string"}; + } + + // Fetch the next token. Dispatches on first character in the + // stream, or first two characters when the first is a slash. + if (inside == "\"" || inside == "'") + return readString(inside); + var ch = source.next(); + if (inside == "/*") + return readMultilineComment(ch); + else if (ch == "\"" || ch == "'") + return readString(ch); + // with punctuation, the type of the token is the symbol itself + else if (/[\[\]{}\(\),;\:\.]/.test(ch)) + return {type: ch, style: "csharp-punctuation"}; + else if (ch == "0" && (source.equals("x") || source.equals("X"))) + return readHexNumber(); + else if (/[0-9]/.test(ch)) + return readNumber(); + else if (ch == "/"){ + if (source.equals("*")) + { source.next(); return readMultilineComment(ch); } + else if (source.equals("/")) + { nextUntilUnescaped(source, null); return {type: "comment", style: "csharp-comment"};} + else if (regexp) + return readRegexp(); + else + return readOperator(); + } + else if (ch == "#") { // treat c# regions like comments + nextUntilUnescaped(source, null); return {type: "comment", style: "csharp-comment"}; + } + else if (isOperatorChar.test(ch)) + return readOperator(); + else + return readWord(); + } + + // The external interface to the tokenizer. + return function(source, startState) { + return tokenizer(source, startState || jsTokenState(false, true)); + }; +})(); diff --git a/gulliver/js/codemirror/contrib/freemarker/LICENSE b/gulliver/js/codemirror/contrib/freemarker/LICENSE new file mode 100755 index 000000000..fbbb800fd --- /dev/null +++ b/gulliver/js/codemirror/contrib/freemarker/LICENSE @@ -0,0 +1,24 @@ +Copyright (c) 2010, Keybroker AB +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Keybroker AB nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL Keybroker AB BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/gulliver/js/codemirror/contrib/freemarker/css/freemarkercolors.css b/gulliver/js/codemirror/contrib/freemarker/css/freemarkercolors.css new file mode 100755 index 000000000..9e7a8f3d8 --- /dev/null +++ b/gulliver/js/codemirror/contrib/freemarker/css/freemarkercolors.css @@ -0,0 +1,63 @@ +html { + cursor: text; +} + +.editbox { + margin: .4em; + padding: 0; + font-family: monospace; + font-size: 12px; + font-size-adjust: none; + font-style: normal; + font-variant: normal; + font-weight: normal; + line-height: normal; + color: black; +} + +pre.code, .editbox { + color: black; +} + +.editbox p { + margin: 0; +} + +span.freemarker-comment { + color: #BB9977; +} + +span.freemarker-generic { +} + +span.freemarker-boundary { + color: darkblue; +} + +span.freemarker-directive { + color: darkblue; +} + +span.freemarker-identifier { + color: purple; +} + +span.freemarker-builtin { + color: gray; +} + +span.freemarker-punctuation { + color: blue; +} + +span.freemarker-string { + color: darkGreen; +} + +span.freemarker-number { + color: blue; +} + +span.freemarker-error { + color: #F00 !important; +} diff --git a/gulliver/js/codemirror/contrib/freemarker/index.html b/gulliver/js/codemirror/contrib/freemarker/index.html new file mode 100755 index 000000000..8d31fa873 --- /dev/null +++ b/gulliver/js/codemirror/contrib/freemarker/index.html @@ -0,0 +1,75 @@ + + + + + CodeMirror: Freemarker demonstration + + + + + +

This page demonstrates CodeMirror's +Freemarker parser. Written by Magnus Ljung, released under a BSD-style license.

+ +
+ +
+ + + + diff --git a/gulliver/js/codemirror/contrib/freemarker/js/parsefreemarker.js b/gulliver/js/codemirror/contrib/freemarker/js/parsefreemarker.js new file mode 100755 index 000000000..562e06287 --- /dev/null +++ b/gulliver/js/codemirror/contrib/freemarker/js/parsefreemarker.js @@ -0,0 +1,380 @@ +var FreemarkerParser = Editor.Parser = (function() { + var autoSelfClosers = {"else": true, "elseif": true}; + + // Simple stateful tokenizer for Freemarker documents. Returns a + // MochiKit-style iterator, with a state property that contains a + // function encapsulating the current state. See tokenize.js. + var tokenizeFreemarker = (function() { + function inText(source, setState) { + var ch = source.next(); + if (ch == "<") { + if (source.equals("!")) { + source.next(); + if (source.lookAhead("--", true)) { + setState(inBlock("freemarker-comment", "-->")); + return null; + } else { + return "freemarker-text"; + } + } else { + source.nextWhileMatches(/[\#\@\/]/); + setState(inFreemarker(">")); + return "freemarker-boundary"; + } + } + else if (ch == "[") { + if(source.matches(/[\#\@]/)) { + setState(pendingFreemarker(source.peek(), "]", false)); + return "freemarker-boundary"; + } else if(source.matches(/\//)) { + setState(pendingFreemarkerEnd("]")); + return "freemarker-boundary"; + } else { + return "freemarker-text"; + } + } + else if (ch == "$") { + if(source.matches(/[\{\w]/)) { + setState(pendingFreemarker("{", "}", true)); + return "freemarker-boundary"; + } else { + return "freemarker-text"; + } + } + else { + source.nextWhileMatches(/[^\$<\n]/); + return "freemarker-text"; + } + } + + function pendingFreemarker(startChar, endChar, nextCanBeIdentifier) { + return function(source, setState) { + var ch = source.next(); + if(ch == startChar) { + setState(inFreemarker(endChar)); + return "freemarker-boundary"; + } else if(nextCanBeIdentifier) { + source.nextWhileMatches(/\w/); + setState(inText); + return "freemarker-identifier"; + } else { + setState(inText); + return null; + } + } + } + + function pendingFreemarkerEnd(endChar) { + return function(source, setState) { + var ch = source.next(); + if(ch == "/") { + setState(pendingFreemarker(source.peek(), endChar, false)); + return "freemarker-boundary"; + } else { + setState(inText); + return null; + } + } + } + + function inFreemarker(terminator) { + return function(source, setState) { + var ch = source.next(); + if (ch == terminator) { + setState(inText); + return "freemarker-boundary"; + } else if (/[?\/]/.test(ch) && source.equals(terminator)) { + source.next(); + setState(inText); + return "freemarker-boundary"; + } else if(/[?!]/.test(ch)) { + if(ch == "?") { + if(source.peek() == "?") { + source.next(); + } else { + setState(inBuiltIn(inFreemarker(terminator))); + } + } + return "freemarker-punctuation"; + } else if(/[()+\/\-*%=]/.test(ch)) { + return "freemarker-punctuation"; + } else if (/[0-9]/.test(ch)) { + source.nextWhileMatches(/[0-9]+\.?[0-9]* /); + return "freemarker-number"; + } else if (/\w/.test(ch)) { + source.nextWhileMatches(/\w/); + return "freemarker-identifier"; + } else if(/[\'\"]/.test(ch)) { + setState(inString(ch, inFreemarker(terminator))); + return "freemarker-string"; + } else { + source.nextWhileMatches(/[^\s\u00a0<>\"\'\}?!\/]/); + return "freemarker-generic"; + } + }; + } + + function inBuiltIn(nextState) { + return function(source, setState) { + var ch = source.peek(); + if(/[a-zA-Z_]/.test(ch)) { + source.next(); + source.nextWhileMatches(/[a-zA-Z_0-9]+/); + setState(nextState); + return "freemarker-builtin"; + } else { + setState(nextState); + } + }; + } + + function inString(quote, nextState) { + return function(source, setState) { + while (!source.endOfLine()) { + if (source.next() == quote) { + setState(nextState); + break; + } + } + return "freemarker-string"; + }; + } + + function inBlock(style, terminator) { + return function(source, setState) { + while (!source.endOfLine()) { + if (source.lookAhead(terminator, true)) { + setState(inText); + break; + } + source.next(); + } + return style; + }; + } + + return function(source, startState) { + return tokenizer(source, startState || inText); + }; + })(); + + // The parser. The structure of this function largely follows that of + // parseXML in parsexml.js + function parseFreemarker(source) { + var tokens = tokenizeFreemarker(source), token; + var cc = [base]; + var tokenNr = 0, indented = 0; + var currentTag = null, context = null; + var consume; + + function push(fs) { + for (var i = fs.length - 1; i >= 0; i--) + cc.push(fs[i]); + } + function cont() { + push(arguments); + consume = true; + } + function pass() { + push(arguments); + consume = false; + } + + function markErr() { + token.style += " freemarker-error"; + } + + function expect(text) { + return function(style, content) { + if (content == text) cont(); + else {markErr(); cont(arguments.callee);} + }; + } + + function pushContext(tagname, startOfLine) { + context = {prev: context, name: tagname, indent: indented, startOfLine: startOfLine}; + } + + function popContext() { + context = context.prev; + } + + function computeIndentation(baseContext) { + return function(nextChars, current, direction, firstToken) { + var context = baseContext; + + nextChars = getThreeTokens(firstToken); + + if ((context && /^<\/\#/.test(nextChars)) || + (context && /^\[\/\#/.test(nextChars))) { + context = context.prev; + } + + while (context && !context.startOfLine) { + context = context.prev; + } + + if (context) { + if(/^<\#else/.test(nextChars) || + /^\[\#else/.test(nextChars)) { + return context.indent; + } + return context.indent + indentUnit; + } else { + return 0; + } + }; + } + + function getThreeTokens(firstToken) { + var secondToken = firstToken ? firstToken.nextSibling : null; + var thirdToken = secondToken ? secondToken.nextSibling : null; + + var nextChars = (firstToken && firstToken.currentText) ? firstToken.currentText : ""; + if(secondToken && secondToken.currentText) { + nextChars = nextChars + secondToken.currentText; + if(thirdToken && thirdToken.currentText) { + nextChars = nextChars + thirdToken.currentText; + } + } + + return nextChars; + } + + function base() { + return pass(element, base); + } + + var harmlessTokens = { "freemarker-text": true, "freemarker-comment": true }; + + function element(style, content) { + if (content == "<#") { + cont(tagname, notEndTag, endtag("/>", ">", tokenNr == 1)); + } else if (content == "")); + } else if(content == "[" && style == "freemarker-boundary") { + cont(hashOrCloseHash); + } else { + cont(); + } + } + + function hashOrCloseHash(style, content) { + if(content == "#") { + cont(tagname, notHashEndTag, endtag("/]", "]", tokenNr == 2)); + } else if(content == "/") { + cont(closeHash); + } else { + markErr(); + } + } + + function closeHash(style, content) { + if(content == "#") { + cont(closetagname, expect("]")); + } else { + markErr(); + } + } + + + function tagname(style, content) { + if (style == "freemarker-identifier") { + currentTag = content.toLowerCase(); + token.style = "freemarker-directive"; + cont(); + } else { + currentTag = null; + pass(); + } + } + + function closetagname(style, content) { + if (style == "freemarker-identifier") { + token.style = "freemarker-directive"; + if (context && content.toLowerCase() == context.name) { + popContext(); + } else { + markErr(); + } + } + cont(); + } + + function notEndTag(style, content) { + if (content == "/>" || content == ">") { + pass(); + } else { + cont(notEndTag); + } + } + + function notHashEndTag(style, content) { + if (content == "/]" || content == "]") { + pass(); + } else { + cont(notHashEndTag); + } + } + + function endtag(closeTagPattern, endTagPattern, startOfLine) { + return function(style, content) { + if (content == closeTagPattern || (content == endTagPattern && autoSelfClosers.hasOwnProperty(currentTag))) { + cont(); + } else if (content == endTagPattern) { + pushContext(currentTag, startOfLine); + cont(); + } else { + markErr(); + cont(arguments.callee); + } + }; + } + + + return { + indentation: function() { return indented; }, + + next: function() { + token = tokens.next(); + if (token.style == "whitespace" && tokenNr == 0) + indented = token.value.length; + else + tokenNr++; + if (token.content == "\n") { + indented = tokenNr = 0; + token.indentation = computeIndentation(context); + } + + if (token.style == "whitespace" || token.type == "freemarker-comment") + return token; + + while(true) { + consume = false; + cc.pop()(token.style, token.content); + if (consume) { + return token; + } + } + }, + + copy: function(){ + var _cc = cc.concat([]), _tokenState = tokens.state, _context = context; + var parser = this; + + return function(input){ + cc = _cc.concat([]); + tokenNr = indented = 0; + context = _context; + tokens = tokenizeFreemarker(input, _tokenState); + return parser; + }; + } + }; + } + + return { + make: parseFreemarker, + electricChars: ">" + }; + })(); diff --git a/gulliver/js/codemirror/contrib/groovy/index.html b/gulliver/js/codemirror/contrib/groovy/index.html new file mode 100755 index 000000000..524adcf3c --- /dev/null +++ b/gulliver/js/codemirror/contrib/groovy/index.html @@ -0,0 +1,57 @@ + + + + CodeMirror: Groovy demonstration + + + + +

Demonstration of CodeMirror's Groovy highlighter.

+ +

Created by eXo Platform SAS (license).

+ +

Note that the files for this parser aren't included in the CodeMirror repository, but have to fetched from svn.exoplatform.org:

+ + + +
+ +
+ + + + + diff --git a/gulliver/js/codemirror/contrib/java/LICENSE b/gulliver/js/codemirror/contrib/java/LICENSE new file mode 100755 index 000000000..ba4282470 --- /dev/null +++ b/gulliver/js/codemirror/contrib/java/LICENSE @@ -0,0 +1,20 @@ + Copyright (c) 2010 Patrick Wied + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any + damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and + redistribute it freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. diff --git a/gulliver/js/codemirror/contrib/java/css/javacolors.css b/gulliver/js/codemirror/contrib/java/css/javacolors.css new file mode 100755 index 000000000..64ea0ea74 --- /dev/null +++ b/gulliver/js/codemirror/contrib/java/css/javacolors.css @@ -0,0 +1,64 @@ + +html { + cursor: text; +} + +.editbox { + margin: .4em; + padding: 0; + font-family: monospace; + font-size: 10pt; + color: black; +} + +pre.code, .editbox { + color: #666666; +} + +.editbox p { + margin: 0; +} + +span.java-punctuation { + color: black; +} + +span.java-operator { + color: purple; +} + +span.java-keyword { + color: #7f0055; + font-weight:bold; +} + +span.java-atom { + color: brown; +} + +span.java-variable { + color: black; +} + + +span.java-property { + color: black; +} + +span.java-comment { + color: green; +} + +span.javadoc-comment { + color: #3e5797; + font-weight:bold; +} + +span.java-string { + color: blue; +} + +span.java-annotation{ + color: gray; +} + diff --git a/gulliver/js/codemirror/contrib/java/index.html b/gulliver/js/codemirror/contrib/java/index.html new file mode 100755 index 000000000..15df0a9cc --- /dev/null +++ b/gulliver/js/codemirror/contrib/java/index.html @@ -0,0 +1,66 @@ + + + + + Demonstration of CodeMirrors Java highlighter written by Patrick Wied + + + + +

Demonstration of CodeMirror's Java highlighter.

+ +

Written by Patrick Wied.

+ +
+ +
+ + + diff --git a/gulliver/js/codemirror/contrib/java/js/parsejava.js b/gulliver/js/codemirror/contrib/java/js/parsejava.js new file mode 100755 index 000000000..1b104db4b --- /dev/null +++ b/gulliver/js/codemirror/contrib/java/js/parsejava.js @@ -0,0 +1,285 @@ +/** + * Java parser for codemirror + * + * @author Patrick Wied + */ + +var JavaParser = Editor.Parser = (function() { + // Token types that can be considered to be atoms. + var atomicTypes = {"atom": true, "number": true, "string": true, "regexp": true}; + // Setting that can be used to have JSON data indent properly. + var json = false; + // Constructor for the lexical context objects. + function JavaLexical(indented, column, type, align, prev, info) { + // indentation at start of this line + this.indented = indented; + // column at which this scope was opened + this.column = column; + // type of scope ( 'stat' (statement), 'form' (special form), '[', '{', or '(') + this.type = type; + // '[', '{', or '(' blocks that have any text after their opening + // character are said to be 'aligned' -- any lines below are + // indented all the way to the opening character. + if (align != null) + this.align = align; + // Parent scope, if any. + this.prev = prev; + this.info = info; + } + + // java indentation rules. + function indentJava(lexical) { + return function(firstChars) { + var firstChar = firstChars && firstChars.charAt(0), type = lexical.type; + var closing = firstChar == type; + if (type == "form" && firstChar == "{") + return lexical.indented; + else if (type == "stat" || type == "form") + return lexical.indented + indentUnit; + else if (lexical.info == "switch" && !closing) + return lexical.indented + (/^(?:case|default)\b/.test(firstChars) ? indentUnit : 2 * indentUnit); + else if (lexical.align) + return lexical.column - (closing ? 1 : 0); + else + return lexical.indented + (closing ? 0 : indentUnit); + }; + } + + // The parser-iterator-producing function itself. + function parseJava(input, basecolumn) { + // Wrap the input in a token stream + var tokens = tokenizeJava(input); + // The parser state. cc is a stack of actions that have to be + // performed to finish the current statement. For example we might + // know that we still need to find a closing parenthesis and a + // semicolon. Actions at the end of the stack go first. It is + // initialized with an infinitely looping action that consumes + // whole statements. + var cc = [statements]; + // The lexical scope, used mostly for indentation. + var lexical = new JavaLexical(basecolumn || 0, 0, "block", false); + // Current column, and the indentation at the start of the current + // line. Used to create lexical scope objects. + var column = 0; + var indented = 0; + // Variables which are used by the mark, cont, and pass functions + // below to communicate with the driver loop in the 'next' + // function. + var consume, marked; + + // The iterator object. + var parser = {next: next, copy: copy}; + + function next(){ + // Start by performing any 'lexical' actions (adjusting the + // lexical variable), or the operations below will be working + // with the wrong lexical state. + while(cc[cc.length - 1].lex) + cc.pop()(); + + // Fetch a token. + var token = tokens.next(); + + // Adjust column and indented. + if (token.type == "whitespace" && column == 0) + indented = token.value.length; + column += token.value.length; + if (token.content == "\n"){ + indented = column = 0; + // If the lexical scope's align property is still undefined at + // the end of the line, it is an un-aligned scope. + if (!("align" in lexical)) + lexical.align = false; + // Newline tokens get an indentation function associated with + // them. + token.indentation = indentJava(lexical); + + } + // No more processing for meaningless tokens. + if (token.type == "whitespace" || token.type == "comment" || token.type == "javadoc" || token.type == "annotation") + return token; + + // When a meaningful token is found and the lexical scope's + // align is undefined, it is an aligned scope. + if (!("align" in lexical)) + lexical.align = true; + + // Execute actions until one 'consumes' the token and we can + // return it. + while(true) { + consume = marked = false; + // Take and execute the topmost action. + cc.pop()(token.type, token.content); + if (consume){ + // Marked is used to change the style of the current token. + if (marked) + token.style = marked; + return token; + } + } + } + + // This makes a copy of the parser state. It stores all the + // stateful variables in a closure, and returns a function that + // will restore them when called with a new input stream. Note + // that the cc array has to be copied, because it is contantly + // being modified. Lexical objects are not mutated, and context + // objects are not mutated in a harmful way, so they can be shared + // between runs of the parser. + function copy(){ + var _lexical = lexical, _cc = cc.concat([]), _tokenState = tokens.state; + + return function copyParser(input){ + lexical = _lexical; + cc = _cc.concat([]); // copies the array + column = indented = 0; + tokens = tokenizeJava(input, _tokenState); + return parser; + }; + } + + // Helper function for pushing a number of actions onto the cc + // stack in reverse order. + function push(fs){ + for (var i = fs.length - 1; i >= 0; i--) + cc.push(fs[i]); + } + // cont and pass are used by the action functions to add other + // actions to the stack. cont will cause the current token to be + // consumed, pass will leave it for the next action. + function cont(){ + push(arguments); + consume = true; + } + function pass(){ + push(arguments); + consume = false; + } + // Used to change the style of the current token. + function mark(style){ + marked = style; + } + + // Push a new lexical context of the given type. + function pushlex(type, info) { + var result = function(){ + lexical = new JavaLexical(indented, column, type, null, lexical, info) + }; + result.lex = true; + return result; + } + // Pop off the current lexical context. + function poplex(){ + lexical = lexical.prev; + } + poplex.lex = true; + // The 'lex' flag on these actions is used by the 'next' function + // to know they can (and have to) be ran before moving on to the + // next token. + + // Creates an action that discards tokens until it finds one of + // the given type. + function expect(wanted){ + return function expecting(type){ + if (type == wanted) cont(); + else cont(arguments.callee); + }; + } + + // Looks for a statement, and then calls itself. + function statements(type){ + return pass(statement, statements); + } + // Dispatches various types of statements based on the type of the + // current token. + function statement(type){ + if (type == "keyword a") cont(pushlex("form"), expression, statement, poplex); + else if (type == "keyword b") cont(pushlex("form"), statement, poplex); + else if (type == "{") cont(pushlex("}"), block, poplex); + else if (type == "for") cont(pushlex("form"), expect("("), pushlex(")"), forspec1, expect(")"), poplex, statement, poplex); + else if (type == "variable") cont(pushlex("stat"), maybelabel); + else if (type == "switch") cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"), block, poplex, poplex); + else if (type == "case") cont(expression, expect(":")); + else if (type == "default") cont(expect(":")); + else if (type == "catch") cont(pushlex("form"), expect("("), function(){}, expect(")"), statement, poplex); + else if (type == "class") cont(); + else if (type == "interface") cont(); + else if (type == "keyword c") cont(statement); + else pass(pushlex("stat"), expression, expect(";"), poplex); + } + // Dispatch expression types. + function expression(type){ + if (atomicTypes.hasOwnProperty(type)) cont(maybeoperator); + //else if (type == "function") cont(functiondef); + else if (type == "keyword c") cont(expression); + else if (type == "(") cont(pushlex(")"), expression, expect(")"), poplex, maybeoperator); + else if (type == "operator") cont(expression); + else if (type == "[") cont(pushlex("]"), commasep(expression, "]"), poplex, maybeoperator); + } + // Called for places where operators, function calls, or + // subscripts are valid. Will skip on to the next action if none + // is found. + function maybeoperator(type){ + if (type == "operator") cont(expression); + else if (type == "(") cont(pushlex(")"), expression, commasep(expression, ")"), poplex, maybeoperator); + else if (type == "[") cont(pushlex("]"), expression, expect("]"), poplex, maybeoperator); + } + // When a statement starts with a variable name, it might be a + // label. If no colon follows, it's a regular statement. + + function maybelabel(type){ + if (type == "(") cont(commasep(function(){}, ")"), poplex, statement); // method definition + else if (type == "{") cont(poplex, pushlex("}"), block, poplex); // property definition + else pass(maybeoperator, expect(";"), poplex); + } + + // Parses a comma-separated list of the things that are recognized + // by the 'what' argument. + function commasep(what, end){ + function proceed(type) { + if (type == ",") cont(what, proceed); + else if (type == end) cont(); + else cont(expect(end)); + }; + return function commaSeparated(type) { + if (type == end) cont(); + else pass(what, proceed); + }; + } + // Look for statements until a closing brace is found. + function block(type){ + if (type == "}") cont(); + else pass(statement, block); + } + + // For loops. + + function forspec1(type){ + if (type == ";") pass(forspec2); + else pass(forspec2); + } + function formaybein(type, value){ + if (value == "in") cont(expression); + else cont(maybeoperator, forspec2); + } + function forspec2(type, value){ + if (type == ";") cont(forspec3); + else if (value == "in") cont(expression); + else cont(expression, expect(";"), forspec3); + } + function forspec3(type) { + if (type == ")") pass(); + else cont(expression); + } + + return parser; + } + + return { + make: parseJava, + electricChars: "{}:", + configure: function(obj) { + if (obj.json != null) json = obj.json; + } + }; +})(); diff --git a/gulliver/js/codemirror/contrib/java/js/tokenizejava.js b/gulliver/js/codemirror/contrib/java/js/tokenizejava.js new file mode 100755 index 000000000..1b58901ad --- /dev/null +++ b/gulliver/js/codemirror/contrib/java/js/tokenizejava.js @@ -0,0 +1,222 @@ +/** + * Java tokenizer for codemirror + * + * @author Patrick Wied + * @version 2010-10-07 + */ +var tokenizeJava = (function() { + // Advance the stream until the given character (not preceded by a + // backslash) is encountered, or the end of the line is reached. + function nextUntilUnescaped(source, end) { + var escaped = false; + var next; + while (!source.endOfLine()) { + var next = source.next(); + if (next == end && !escaped) + return false; + escaped = !escaped && next == "\\"; + } + return escaped; + } + + // A map of Java's keywords. The a/b/c keyword distinction is + // very rough, but it gives the parser enough information to parse + // correct code correctly (we don't care that much how we parse + // incorrect code). The style information included in these objects + // is used by the highlighter to pick the correct CSS style for a + // token. + var keywords = function(){ + function result(type, style){ + return {type: type, style: "java-" + style}; + } + // keywords that take a parenthised expression, and then a + // statement (if) + var keywordA = result("keyword a", "keyword"); + // keywords that take just a statement (else) + var keywordB = result("keyword b", "keyword"); + // keywords that optionally take an expression, and form a + // statement (return) + var keywordC = result("keyword c", "keyword"); + var operator = result("operator", "keyword"); + var atom = result("atom", "atom"); + + return { + "if": keywordA, "while": keywordA, "with": keywordA, + "else": keywordB, "do": keywordB, "try": keywordB, "finally": keywordB, + "return": keywordC, "break": keywordC, "continue": keywordC, "new": keywordC, "throw": keywordC, "throws": keywordB, + "in": operator, "typeof": operator, "instanceof": operator, + "catch": result("catch", "keyword"), "for": result("for", "keyword"), "switch": result("switch", "keyword"), + "case": result("case", "keyword"), "default": result("default", "keyword"), + "true": atom, "false": atom, "null": atom, + + "class": result("class", "keyword"), "interface": result("interface", "keyword"), "package": keywordC, "import": keywordC, + "implements": keywordC, "extends": keywordC, "super": keywordC, + + "public": keywordC, "private": keywordC, "protected": keywordC, "transient": keywordC, "this": keywordC, + "static": keywordC, "final": keywordC, "const": keywordC, "abstract": keywordC, "static": keywordC, + + "int": keywordC, "double": keywordC, "long": keywordC, "boolean": keywordC, "char": keywordC, + "void": keywordC, "byte": keywordC, "float": keywordC, "short": keywordC + }; + }(); + + // Some helper regexps + var isOperatorChar = /[+\-*&%=<>!?|]/; + var isHexDigit = /[0-9A-Fa-f]/; + var isWordChar = /[\w\$_]/; + // Wrapper around javaToken that helps maintain parser state (whether + // we are inside of a multi-line comment and whether the next token + // could be a regular expression). + function javaTokenState(inside, regexp) { + return function(source, setState) { + var newInside = inside; + var type = javaToken(inside, regexp, source, function(c) {newInside = c;}); + var newRegexp = type.type == "operator" || type.type == "keyword c" || type.type.match(/^[\[{}\(,;:]$/); + if (newRegexp != regexp || newInside != inside) + setState(javaTokenState(newInside, newRegexp)); + return type; + }; + } + + // The token reader, inteded to be used by the tokenizer from + // tokenize.js (through jsTokenState). Advances the source stream + // over a token, and returns an object containing the type and style + // of that token. + function javaToken(inside, regexp, source, setInside) { + function readHexNumber(){ + source.next(); // skip the 'x' + source.nextWhileMatches(isHexDigit); + return {type: "number", style: "java-atom"}; + } + + function readNumber() { + source.nextWhileMatches(/[0-9]/); + if (source.equals(".")){ + source.next(); + source.nextWhileMatches(/[0-9]/); + } + if (source.equals("e") || source.equals("E")){ + source.next(); + if (source.equals("-")) + source.next(); + source.nextWhileMatches(/[0-9]/); + } + return {type: "number", style: "java-atom"}; + } + // Read a word, look it up in keywords. If not found, it is a + // variable, otherwise it is a keyword of the type found. + function readWord() { + source.nextWhileMatches(isWordChar); + var word = source.get(); + var known = keywords.hasOwnProperty(word) && keywords.propertyIsEnumerable(word) && keywords[word]; + return known ? {type: known.type, style: known.style, content: word} : + {type: "variable", style: "java-variable", content: word}; + } + function readRegexp() { + nextUntilUnescaped(source, "/"); + source.nextWhileMatches(/[gi]/); + return {type: "regexp", style: "java-string"}; + } + // Mutli-line comments are tricky. We want to return the newlines + // embedded in them as regular newline tokens, and then continue + // returning a comment token for every line of the comment. So + // some state has to be saved (inside) to indicate whether we are + // inside a /* */ sequence. + function readMultilineComment(start){ + var newInside = "/*"; + var maybeEnd = (start == "*"); + while (true) { + if (source.endOfLine()) + break; + var next = source.next(); + if (next == "/" && maybeEnd){ + newInside = null; + break; + } + maybeEnd = (next == "*"); + } + setInside(newInside); + return {type: "comment", style: "java-comment"}; + } + + // for reading javadoc + function readJavaDocComment(start){ + var newInside = "/**"; + var maybeEnd = (start == "*"); + while (true) { + if (source.endOfLine()) + break; + var next = source.next(); + if (next == "/" && maybeEnd){ + newInside = null; + break; + } + maybeEnd = (next == "*"); + } + setInside(newInside); + return {type: "javadoc", style: "javadoc-comment"}; + } + // for reading annotations (word based) + function readAnnotation(){ + source.nextWhileMatches(isWordChar); + var word = source.get(); + return {type: "annotation", style: "java-annotation", content:word}; + } + + function readOperator() { + source.nextWhileMatches(isOperatorChar); + return {type: "operator", style: "java-operator"}; + } + function readString(quote) { + var endBackSlash = nextUntilUnescaped(source, quote); + setInside(endBackSlash ? quote : null); + return {type: "string", style: "java-string"}; + } + + // Fetch the next token. Dispatches on first character in the + // stream, or first two characters when the first is a slash. + if (inside == "\"" || inside == "'") + return readString(inside); + var ch = source.next(); + if (inside == "/*") + return readMultilineComment(ch); + else if(inside == "/**") + return readJavaDocComment(ch); + else if (ch == "\"" || ch == "'") + return readString(ch); + // with punctuation, the type of the token is the symbol itself + else if (/[\[\]{}\(\),;\:\.]/.test(ch)) + return {type: ch, style: "java-punctuation"}; + else if (ch == "0" && (source.equals("x") || source.equals("X"))) + return readHexNumber(); + else if (/[0-9]/.test(ch)) + return readNumber(); + else if (ch == "@"){ + return readAnnotation(); + }else if (ch == "/"){ + if (source.equals("*")){ + source.next(); + + if(source.equals("*")) + return readJavaDocComment(ch); + + return readMultilineComment(ch); + } + else if (source.equals("/")) + { nextUntilUnescaped(source, null); return {type: "comment", style: "java-comment"};} + else if (regexp) + return readRegexp(); + else + return readOperator(); + } + else if (isOperatorChar.test(ch)) + return readOperator(); + else + return readWord(); + } + + // The external interface to the tokenizer. + return function(source, startState) { + return tokenizer(source, startState || javaTokenState(false, true)); + }; +})(); diff --git a/gulliver/js/codemirror/contrib/lua/LICENSE b/gulliver/js/codemirror/contrib/lua/LICENSE new file mode 100755 index 000000000..5b867cd52 --- /dev/null +++ b/gulliver/js/codemirror/contrib/lua/LICENSE @@ -0,0 +1,32 @@ +Copyright (c) 2009, Franciszek Wawrzak +All rights reserved. + +This software is provided for use in connection with the +CodeMirror suite of modules and utilities, hosted and maintained +at http://codemirror.net/. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/gulliver/js/codemirror/contrib/lua/css/luacolors.css b/gulliver/js/codemirror/contrib/lua/css/luacolors.css new file mode 100755 index 000000000..e9015296f --- /dev/null +++ b/gulliver/js/codemirror/contrib/lua/css/luacolors.css @@ -0,0 +1,63 @@ +html { + cursor: text; +} + +.editbox { + margin: .4em; + padding: 0; + font-family: monospace; + font-size: 10pt; + color: black; +} + +pre.code, .editbox { + color: #666666; +} + +.editbox p { + margin: 0; +} + +span.lua-comment { + color: #BB9977; +} + +span.lua-keyword { + font-weight: bold; + color: blue; +} + +span.lua-string { + color: #AA2222; +} + +span.lua-stdfunc { + font-weight: bold; + color: #077; +} +span.lua-customfunc { + font-weight: bold; + color: #0AA; +} + + +span.lua-identifier { + color: black; +} + +span.lua-number { + color: #3A3; +} + +span.lua-token { + color: #151; +} + +span.lua-error { + color: #FFF; + background-color: #F00; +} + + + + diff --git a/gulliver/js/codemirror/contrib/lua/index.html b/gulliver/js/codemirror/contrib/lua/index.html new file mode 100755 index 000000000..03a322998 --- /dev/null +++ b/gulliver/js/codemirror/contrib/lua/index.html @@ -0,0 +1,68 @@ + + + + CodeMirror: Lua demonstration + + + +

This page demonstrates CodeMirror's +Lua parser. Written by Franciszek +Wawrzak, released under a BSD-style license.

+ +
+ +
+ + + + diff --git a/gulliver/js/codemirror/contrib/lua/js/parselua.js b/gulliver/js/codemirror/contrib/lua/js/parselua.js new file mode 100755 index 000000000..5d508b2cd --- /dev/null +++ b/gulliver/js/codemirror/contrib/lua/js/parselua.js @@ -0,0 +1,254 @@ +/* + Simple parser for LUA + Written for Lua 5.1, based on parsecss and other parsers. + features: highlights keywords, strings, comments (no leveling supported! ("[==[")),tokens, basic indenting + + to make this parser highlight your special functions pass table with this functions names to parserConfig argument of creator, + + parserConfig: ["myfunction1","myfunction2"], + */ + + +function findFirstRegexp(words) { + return new RegExp("^(?:" + words.join("|") + ")", "i"); +} + +function matchRegexp(words) { + return new RegExp("^(?:" + words.join("|") + ")$", "i"); +} + + + +var luaCustomFunctions= matchRegexp([]); + +function configureLUA(parserConfig){ + if(parserConfig) + luaCustomFunctions= matchRegexp(parserConfig); +} + + +//long list of standard functions from lua manual +var luaStdFunctions = matchRegexp([ +"_G","_VERSION","assert","collectgarbage","dofile","error","getfenv","getmetatable","ipairs","load","loadfile","loadstring","module","next","pairs","pcall","print","rawequal","rawget","rawset","require","select","setfenv","setmetatable","tonumber","tostring","type","unpack","xpcall", + +"coroutine.create","coroutine.resume","coroutine.running","coroutine.status","coroutine.wrap","coroutine.yield", + +"debug.debug","debug.getfenv","debug.gethook","debug.getinfo","debug.getlocal","debug.getmetatable","debug.getregistry","debug.getupvalue","debug.setfenv","debug.sethook","debug.setlocal","debug.setmetatable","debug.setupvalue","debug.traceback", + +"close","flush","lines","read","seek","setvbuf","write", + +"io.close","io.flush","io.input","io.lines","io.open","io.output","io.popen","io.read","io.stderr","io.stdin","io.stdout","io.tmpfile","io.type","io.write", + +"math.abs","math.acos","math.asin","math.atan","math.atan2","math.ceil","math.cos","math.cosh","math.deg","math.exp","math.floor","math.fmod","math.frexp","math.huge","math.ldexp","math.log","math.log10","math.max","math.min","math.modf","math.pi","math.pow","math.rad","math.random","math.randomseed","math.sin","math.sinh","math.sqrt","math.tan","math.tanh", + +"os.clock","os.date","os.difftime","os.execute","os.exit","os.getenv","os.remove","os.rename","os.setlocale","os.time","os.tmpname", + +"package.cpath","package.loaded","package.loaders","package.loadlib","package.path","package.preload","package.seeall", + +"string.byte","string.char","string.dump","string.find","string.format","string.gmatch","string.gsub","string.len","string.lower","string.match","string.rep","string.reverse","string.sub","string.upper", + +"table.concat","table.insert","table.maxn","table.remove","table.sort" +]); + + + + var luaKeywords = matchRegexp(["and","break","elseif","false","nil","not","or","return", + "true","function", "end", "if", "then", "else", "do", + "while", "repeat", "until", "for", "in", "local" ]); + + var luaIndentKeys = matchRegexp(["function", "if","repeat","for","while", "[\(]", "{"]); + var luaUnindentKeys = matchRegexp(["end", "until", "[\)]", "}"]); + + var luaUnindentKeys2 = findFirstRegexp(["end", "until", "[\)]", "}"]); + var luaMiddleKeys = findFirstRegexp(["else","elseif"]); + + + +var LUAParser = Editor.Parser = (function() { + var tokenizeLUA = (function() { + function normal(source, setState) { + var ch = source.next(); + + if (ch == "-" && source.equals("-")) { + source.next(); + setState(inSLComment); + return null; + } + else if (ch == "\"" || ch == "'") { + setState(inString(ch)); + return null; + } + if (ch == "[" && (source.equals("[") || source.equals("="))) { + var level = 0; + while(source.equals("=")){ + level ++; + source.next(); + } + if(! source.equals("[") ) + return "lua-error"; + setState(inMLSomething(level,"lua-string")); + return null; + } + + else if (ch == "=") { + if (source.equals("=")) + source.next(); + return "lua-token"; + } + + else if (ch == ".") { + if (source.equals(".")) + source.next(); + if (source.equals(".")) + source.next(); + return "lua-token"; + } + + else if (ch == "+" || ch == "-" || ch == "*" || ch == "/" || ch == "%" || ch == "^" || ch == "#" ) { + return "lua-token"; + } + else if (ch == ">" || ch == "<" || ch == "(" || ch == ")" || ch == "{" || ch == "}" || ch == "[" ) { + return "lua-token"; + } + else if (ch == "]" || ch == ";" || ch == ":" || ch == ",") { + return "lua-token"; + } + else if (source.equals("=") && (ch == "~" || ch == "<" || ch == ">")) { + source.next(); + return "lua-token"; + } + + else if (/\d/.test(ch)) { + source.nextWhileMatches(/[\w.%]/); + return "lua-number"; + } + else { + source.nextWhileMatches(/[\w\\\-_.]/); + return "lua-identifier"; + } + } + +function inSLComment(source, setState) { + var start = true; + var count=0; + while (!source.endOfLine()) { + var ch = source.next(); + var level = 0; + if ((ch =="[") && start){ + while(source.equals("=")){ + source.next(); + level++; + } + if (source.equals("[")){ + setState(inMLSomething(level,"lua-comment")); + return null; + } + } + start = false; + } + setState(normal); + return "lua-comment"; + + } + + function inMLSomething(level,what) { + //wat sholud be "lua-string" or "lua-comment", level is the number of "=" in opening mark. + return function(source, setState){ + var dashes = 0; + while (!source.endOfLine()) { + var ch = source.next(); + if (dashes == level+1 && ch == "]" ) { + setState(normal); + break; + } + if (dashes == 0) + dashes = (ch == "]") ? 1:0; + else + dashes = (ch == "=") ? dashes + 1 : 0; + } + return what; + } + } + + + function inString(quote) { + return function(source, setState) { + var escaped = false; + while (!source.endOfLine()) { + var ch = source.next(); + if (ch == quote && !escaped) + break; + escaped = !escaped && ch == "\\"; + } + if (!escaped) + setState(normal); + return "lua-string"; + }; + } + + return function(source, startState) { + return tokenizer(source, startState || normal); + }; + })(); + + function indentLUA(indentDepth, base) { + return function(nextChars) { + + var closing = (luaUnindentKeys2.test(nextChars) || luaMiddleKeys.test(nextChars)); + + + return base + ( indentUnit * (indentDepth - (closing?1:0)) ); + }; + } + + +function parseLUA(source,basecolumn) { + basecolumn = basecolumn || 0; + + var tokens = tokenizeLUA(source); + var indentDepth = 0; + + var iter = { + next: function() { + var token = tokens.next(), style = token.style, content = token.content; + + + + if (style == "lua-identifier" && luaKeywords.test(content)){ + token.style = "lua-keyword"; + } + if (style == "lua-identifier" && luaStdFunctions.test(content)){ + token.style = "lua-stdfunc"; + } + if (style == "lua-identifier" && luaCustomFunctions.test(content)){ + token.style = "lua-customfunc"; + } + + if (luaIndentKeys.test(content)) + indentDepth++; + else if (luaUnindentKeys.test(content)) + indentDepth--; + + + if (content == "\n") + token.indentation = indentLUA( indentDepth, basecolumn); + + return token; + }, + + copy: function() { + var _tokenState = tokens.state, _indentDepth = indentDepth; + return function(source) { + tokens = tokenizeLUA(source, _tokenState); + + indentDepth = _indentDepth; + return iter; + }; + } + }; + return iter; + } + + return {make: parseLUA, configure:configureLUA, electricChars: "delf})"}; //en[d] els[e] unti[l] elsei[f] // this should be taken from Keys keywords +})(); + diff --git a/gulliver/js/codemirror/contrib/ometa/LICENSE b/gulliver/js/codemirror/contrib/ometa/LICENSE new file mode 100755 index 000000000..44ceed6c3 --- /dev/null +++ b/gulliver/js/codemirror/contrib/ometa/LICENSE @@ -0,0 +1,23 @@ + Copyright (c) 2007-2009 Marijn Haverbeke + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any + damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and + redistribute it freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + Marijn Haverbeke + marijnh at gmail diff --git a/gulliver/js/codemirror/contrib/ometa/css/ometacolors.css b/gulliver/js/codemirror/contrib/ometa/css/ometacolors.css new file mode 100755 index 000000000..f797b45b2 --- /dev/null +++ b/gulliver/js/codemirror/contrib/ometa/css/ometacolors.css @@ -0,0 +1,63 @@ +html { + cursor: text; +} + +.editbox { + margin: .4em; + padding: 0; + font-family: monospace; + font-size: 10pt; + color: black; +} + +pre.code, .editbox { + color: #666666; +} + +.editbox p { + margin: 0; +} + +span.js-punctuation { + color: #666666; +} + +span.js-operator { + color: #E1570F; +} + +span.js-keyword { + color: #770088; +} + +span.js-atom { + color: #228811; +} + +span.js-variable { + color: black; +} + +span.js-variabledef { + color: #0000FF; +} + +span.js-localvariable { + color: #004499; +} + +span.js-property { + color: black; +} + +span.js-comment { + color: #AA7700; +} + +span.js-string { + color: #AA2222; +} + +span.ometa-binding { + color: #FF0000; +} diff --git a/gulliver/js/codemirror/contrib/ometa/index.html b/gulliver/js/codemirror/contrib/ometa/index.html new file mode 100755 index 000000000..bd25d6a0e --- /dev/null +++ b/gulliver/js/codemirror/contrib/ometa/index.html @@ -0,0 +1,77 @@ + + + + CodeMirror: OmetaJS demonstration + + + + +

This page demonstrates CodeMirror's OmetaJS parser.

+ +

Adapted from the official Javascript parser by Eric KEDJI + <eric.kedji@gmail.com>.

+ +
+ +
+ + + + + diff --git a/gulliver/js/codemirror/contrib/ometa/js/parseometa.js b/gulliver/js/codemirror/contrib/ometa/js/parseometa.js new file mode 100755 index 000000000..efb715e94 --- /dev/null +++ b/gulliver/js/codemirror/contrib/ometa/js/parseometa.js @@ -0,0 +1,364 @@ +/* Parse function for JavaScript. Makes use of the tokenizer from + * tokenizejavascript.js. Note that your parsers do not have to be + * this complicated -- if you don't want to recognize local variables, + * in many languages it is enough to just look for braces, semicolons, + * parentheses, etc, and know when you are inside a string or comment. + * + * See manual.html for more info about the parser interface. + */ + +var JSParser = Editor.Parser = (function() { + // Token types that can be considered to be atoms. + var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true}; + // Setting that can be used to have JSON data indent properly. + var json = false; + // Constructor for the lexical context objects. + function JSLexical(indented, column, type, align, prev, info) { + // indentation at start of this line + this.indented = indented; + // column at which this scope was opened + this.column = column; + // type of scope ('vardef', 'stat' (statement), 'form' (special form), '[', '{', or '(') + this.type = type; + // '[', '{', or '(' blocks that have any text after their opening + // character are said to be 'aligned' -- any lines below are + // indented all the way to the opening character. + if (align != null) + this.align = align; + // Parent scope, if any. + this.prev = prev; + this.info = info; + } + + // My favourite JavaScript indentation rules. + function indentJS(lexical) { + return function(firstChars) { + var firstChar = firstChars && firstChars.charAt(0), type = lexical.type; + var closing = firstChar == type; + if (type == "vardef") + return lexical.indented + 4; + else if (type == "form" && firstChar == "{") + return lexical.indented; + else if (type == "stat" || type == "form") + return lexical.indented + indentUnit; + else if (lexical.info == "switch" && !closing) + return lexical.indented + (/^(?:case|default)\b/.test(firstChars) ? indentUnit : 2 * indentUnit); + else if (lexical.align) + return lexical.column - (closing ? 1 : 0); + else + return lexical.indented + (closing ? 0 : indentUnit); + }; + } + + // The parser-iterator-producing function itself. + function parseJS(input, basecolumn) { + // Wrap the input in a token stream + var tokens = tokenizeJavaScript(input); + // The parser state. cc is a stack of actions that have to be + // performed to finish the current statement. For example we might + // know that we still need to find a closing parenthesis and a + // semicolon. Actions at the end of the stack go first. It is + // initialized with an infinitely looping action that consumes + // whole statements. + var cc = [json ? expressions : statements]; + // Context contains information about the current local scope, the + // variables defined in that, and the scopes above it. + var context = null; + // The lexical scope, used mostly for indentation. + var lexical = new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false); + // Current column, and the indentation at the start of the current + // line. Used to create lexical scope objects. + var column = 0; + var indented = 0; + // Variables which are used by the mark, cont, and pass functions + // below to communicate with the driver loop in the 'next' + // function. + var consume, marked; + + // The iterator object. + var parser = {next: next, copy: copy}; + + function next(){ + // Start by performing any 'lexical' actions (adjusting the + // lexical variable), or the operations below will be working + // with the wrong lexical state. + while(cc[cc.length - 1].lex) + cc.pop()(); + + // Fetch a token. + var token = tokens.next(); + + // Adjust column and indented. + if (token.type == "whitespace" && column == 0) + indented = token.value.length; + column += token.value.length; + if (token.content == "\n"){ + indented = column = 0; + // If the lexical scope's align property is still undefined at + // the end of the line, it is an un-aligned scope. + if (!("align" in lexical)) + lexical.align = false; + // Newline tokens get an indentation function associated with + // them. + token.indentation = indentJS(lexical); + // special handling for multiline strings: keep everything in the first + // column, as spaces at the start of a multiline string are significant + if (lexical.info == "multilineString") { + lexical.align = false; + token.indentation = function () { return 0; }; + } + } + // No more processing for meaningless tokens. + if (token.type == "whitespace" || token.type == "comment") + return token; + // Take note when a multiline string is found, so as to + // correctly handle indentation at the end of the line + // (see above, line 95) + if (token.type == "multilineString") + lexical.info = 'multilineString'; + // When a meaningful token is found and the lexical scope's + // align is undefined, it is an aligned scope. + if (!("align" in lexical)) + lexical.align = true; + + // Execute actions until one 'consumes' the token and we can + // return it. + while(true) { + consume = marked = false; + // Take and execute the topmost action. + cc.pop()(token.type, token.content); + if (consume){ + // Marked is used to change the style of the current token. + if (marked) + token.style = marked; + // Here we differentiate between local and global variables. + else if (token.type == "variable" && inScope(token.content)) + token.style = "js-localvariable"; + return token; + } + } + } + + // This makes a copy of the parser state. It stores all the + // stateful variables in a closure, and returns a function that + // will restore them when called with a new input stream. Note + // that the cc array has to be copied, because it is contantly + // being modified. Lexical objects are not mutated, and context + // objects are not mutated in a harmful way, so they can be shared + // between runs of the parser. + function copy(){ + var _context = context, _lexical = lexical, _cc = cc.concat([]), _tokenState = tokens.state; + + return function copyParser(input){ + context = _context; + lexical = _lexical; + cc = _cc.concat([]); // copies the array + column = indented = 0; + tokens = tokenizeJavaScript(input, _tokenState); + return parser; + }; + } + + // Helper function for pushing a number of actions onto the cc + // stack in reverse order. + function push(fs){ + for (var i = fs.length - 1; i >= 0; i--) + cc.push(fs[i]); + } + // cont and pass are used by the action functions to add other + // actions to the stack. cont will cause the current token to be + // consumed, pass will leave it for the next action. + function cont(){ + push(arguments); + consume = true; + } + function pass(){ + push(arguments); + consume = false; + } + // Used to change the style of the current token. + function mark(style){ + marked = style; + } + + // Push a new scope. Will automatically link the current scope. + function pushcontext(){ + context = {prev: context, vars: {"this": true, "arguments": true}}; + } + // Pop off the current scope. + function popcontext(){ + context = context.prev; + } + // Register a variable in the current scope. + function register(varname){ + if (context){ + mark("js-variabledef"); + context.vars[varname] = true; + } + } + // Check whether a variable is defined in the current scope. + function inScope(varname){ + var cursor = context; + while (cursor) { + if (cursor.vars[varname]) + return true; + cursor = cursor.prev; + } + return false; + } + + // Push a new lexical context of the given type. + function pushlex(type, info) { + var result = function(){ + lexical = new JSLexical(indented, column, type, null, lexical, info) + }; + result.lex = true; + return result; + } + // Pop off the current lexical context. + function poplex(){ + lexical = lexical.prev; + } + poplex.lex = true; + // The 'lex' flag on these actions is used by the 'next' function + // to know they can (and have to) be ran before moving on to the + // next token. + + // Creates an action that discards tokens until it finds one of + // the given type. + function expect(wanted){ + return function expecting(type){ + if (type == wanted) cont(); + else cont(arguments.callee); + }; + } + + // Looks for a statement, and then calls itself. + function statements(type){ + return pass(statement, statements); + } + function expressions(type){ + return pass(expression, expressions); + } + // Dispatches various types of statements based on the type of the + // current token. + function statement(type){ + if (type == "var") cont(pushlex("vardef"), vardef1, expect(";"), poplex); + else if (type == "keyword a") cont(pushlex("form"), expression, statement, poplex); + else if (type == "keyword b") cont(pushlex("form"), statement, poplex); + else if (type == "{") cont(pushlex("}"), block, poplex); + else if (type == "function") cont(functiondef); + else if (type == "for") cont(pushlex("form"), expect("("), pushlex(")"), forspec1, expect(")"), poplex, statement, poplex); + else if (type == "variable") cont(pushlex("stat"), maybelabel); + else if (type == "switch") cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"), block, poplex, poplex); + else if (type == "case") cont(expression, expect(":")); + else if (type == "default") cont(expect(":")); + else if (type == "catch") cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"), statement, poplex, popcontext); + else pass(pushlex("stat"), expression, expect(";"), poplex); + } + // Dispatch expression types. + function expression(type){ + if (atomicTypes.hasOwnProperty(type)) cont(maybeoperator); + else if (type == "function") cont(functiondef); + else if (type == "keyword c") cont(expression); + else if (type == "(") cont(pushlex(")"), expression, expect(")"), poplex, maybeoperator); + else if (type == "operator") cont(expression); + else if (type == "[") cont(pushlex("]"), commasep(expression, "]"), poplex, maybeoperator); + else if (type == "{") cont(pushlex("}"), commasep(objprop, "}"), poplex, maybeoperator); + else cont(); + } + // Called for places where operators, function calls, or + // subscripts are valid. Will skip on to the next action if none + // is found. + function maybeoperator(type){ + if (type == "operator") cont(expression); + else if (type == "(") cont(pushlex(")"), commasep(expression, ")"), poplex, maybeoperator); + else if (type == ".") cont(property, maybeoperator); + else if (type == "[") cont(pushlex("]"), expression, expect("]"), poplex, maybeoperator); + } + // When a statement starts with a variable name, it might be a + // label. If no colon follows, it's a regular statement. + function maybelabel(type){ + if (type == ":") cont(poplex, statement); + else pass(maybeoperator, expect(";"), poplex); + } + // Property names need to have their style adjusted -- the + // tokenizer thinks they are variables. + function property(type){ + if (type == "variable") {mark("js-property"); cont();} + } + // This parses a property and its value in an object literal. + function objprop(type){ + if (type == "variable") mark("js-property"); + if (atomicTypes.hasOwnProperty(type)) cont(expect(":"), expression); + } + // Parses a comma-separated list of the things that are recognized + // by the 'what' argument. + function commasep(what, end){ + function proceed(type) { + if (type == ",") cont(what, proceed); + else if (type == end) cont(); + else cont(expect(end)); + } + return function commaSeparated(type) { + if (type == end) cont(); + else pass(what, proceed); + }; + } + // Look for statements until a closing brace is found. + function block(type){ + if (type == "}") cont(); + else pass(statement, block); + } + // Variable definitions are split into two actions -- 1 looks for + // a name or the end of the definition, 2 looks for an '=' sign or + // a comma. + function vardef1(type, value){ + if (type == "variable"){register(value); cont(vardef2);} + else cont(); + } + function vardef2(type, value){ + if (value == "=") cont(expression, vardef2); + else if (type == ",") cont(vardef1); + } + // For loops. + function forspec1(type){ + if (type == "var") cont(vardef1, forspec2); + else if (type == ";") pass(forspec2); + else if (type == "variable") cont(formaybein); + else pass(forspec2); + } + function formaybein(type, value){ + if (value == "in") cont(expression); + else cont(maybeoperator, forspec2); + } + function forspec2(type, value){ + if (type == ";") cont(forspec3); + else if (value == "in") cont(expression); + else cont(expression, expect(";"), forspec3); + } + function forspec3(type) { + if (type == ")") pass(); + else cont(expression); + } + // A function definition creates a new context, and the variables + // in its argument list have to be added to this context. + function functiondef(type, value){ + if (type == "variable"){register(value); cont(functiondef);} + else if (type == "(") cont(pushcontext, commasep(funarg, ")"), statement, popcontext); + } + function funarg(type, value){ + if (type == "variable"){register(value); cont();} + } + + return parser; + } + + return { + make: parseJS, + electricChars: "{}:", + configure: function(obj) { + if (obj.json != null) json = obj.json; + } + }; +})(); diff --git a/gulliver/js/codemirror/contrib/ometa/js/tokenizeometa.js b/gulliver/js/codemirror/contrib/ometa/js/tokenizeometa.js new file mode 100755 index 000000000..430206ca5 --- /dev/null +++ b/gulliver/js/codemirror/contrib/ometa/js/tokenizeometa.js @@ -0,0 +1,209 @@ +/* Tokenizer for JavaScript code */ + +var tokenizeJavaScript = (function() { + // Advance the stream until the given character (not preceded by a + // backslash) is encountered, or the end of the line is reached. + function nextUntilUnescaped(source, end) { + var escaped = false; + while (!source.endOfLine()) { + var next = source.next(); + if (next == end && !escaped) + return false; + escaped = !escaped && next == "\\"; + } + return escaped; + } + + // A map of JavaScript's keywords. The a/b/c keyword distinction is + // very rough, but it gives the parser enough information to parse + // correct code correctly (we don't care that much how we parse + // incorrect code). The style information included in these objects + // is used by the highlighter to pick the correct CSS style for a + // token. + var keywords = function(){ + function result(type, style){ + return {type: type, style: "js-" + style}; + } + // keywords that take a parenthised expression, and then a + // statement (if) + var keywordA = result("keyword a", "keyword"); + // keywords that take just a statement (else) + var keywordB = result("keyword b", "keyword"); + // keywords that optionally take an expression, and form a + // statement (return) + var keywordC = result("keyword c", "keyword"); + var operator = result("operator", "keyword"); + var atom = result("atom", "atom"); + return { + "if": keywordA, "while": keywordA, "with": keywordA, + "else": keywordB, "do": keywordB, "try": keywordB, "finally": keywordB, + "return": keywordC, "break": keywordC, "continue": keywordC, "new": keywordC, "delete": keywordC, "throw": keywordC, + "in": operator, "typeof": operator, "instanceof": operator, + "var": result("var", "keyword"), "function": result("function", "keyword"), "catch": result("catch", "keyword"), + "for": result("for", "keyword"), "switch": result("switch", "keyword"), + "case": result("case", "keyword"), "default": result("default", "keyword"), + "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom, + "ometa": keywordB + }; + }(); + + // Some helper regexps + var isOperatorChar = /[+\-*&%=<>!?|~]/; + var isHexDigit = /[0-9A-Fa-f]/; + var isWordChar = /[\w\$_]/; + + // Wrapper around jsToken that helps maintain parser state (whether + // we are inside of a multi-line comment and whether the next token + // could be a regular expression). + function jsTokenState(inside, regexp) { + return function(source, setState) { + var newInside = inside; + var type = jsToken(inside, regexp, source, function(c) {newInside = c;}); + var newRegexp = type.type == "operator" || type.type == "keyword c" || type.type.match(/^[\[{}\(,;:]$/); + if (newRegexp != regexp || newInside != inside) + setState(jsTokenState(newInside, newRegexp)); + return type; + }; + } + + // The token reader, intended to be used by the tokenizer from + // tokenize.js (through jsTokenState). Advances the source stream + // over a token, and returns an object containing the type and style + // of that token. + function jsToken(inside, regexp, source, setInside) { + function readHexNumber(){ + source.next(); // skip the 'x' + source.nextWhileMatches(isHexDigit); + return {type: "number", style: "js-atom"}; + } + + function readNumber() { + source.nextWhileMatches(/[0-9]/); + if (source.equals(".")){ + source.next(); + source.nextWhileMatches(/[0-9]/); + } + if (source.equals("e") || source.equals("E")){ + source.next(); + if (source.equals("-")) + source.next(); + source.nextWhileMatches(/[0-9]/); + } + return {type: "number", style: "js-atom"}; + } + // Read a word, look it up in keywords. If not found, it is a + // variable, otherwise it is a keyword of the type found. + function readWord() { + source.nextWhileMatches(isWordChar); + var word = source.get(); + var known = keywords.hasOwnProperty(word) && keywords.propertyIsEnumerable(word) && keywords[word]; + return known ? {type: known.type, style: known.style, content: word} : + {type: "variable", style: "js-variable", content: word}; + } + function readRegexp() { + nextUntilUnescaped(source, "/"); + source.nextWhileMatches(/[gi]/); + return {type: "regexp", style: "js-string"}; + } + // Mutli-line comments are tricky. We want to return the newlines + // embedded in them as regular newline tokens, and then continue + // returning a comment token for every line of the comment. So + // some state has to be saved (inside) to indicate whether we are + // inside a /* */ sequence. + function readMultilineComment(start){ + var newInside = "/*"; + var maybeEnd = (start == "*"); + while (true) { + if (source.endOfLine()) + break; + var next = source.next(); + if (next == "/" && maybeEnd){ + newInside = null; + break; + } + maybeEnd = (next == "*"); + } + setInside(newInside); + return {type: "comment", style: "js-comment"}; + } + function readMultilineString(start, quotes) { + var newInside = quotes; + var quote = quotes.charAt(0); + var maybeEnd = (start == quote); + while (true) { + if (source.endOfLine()) + break; + var next = source.next(); + if (next == quote && source.peek() == quote && maybeEnd) { + source.next(); + newInside = null; + break; + } + maybeEnd = (next == quote); + } + setInside(newInside); + return {type: "multilineString", style: "js-string"}; + } + function readOperator() { + source.nextWhileMatches(isOperatorChar); + return {type: "operator", style: "js-operator"}; + } + function readString(quote) { + var endBackSlash = nextUntilUnescaped(source, quote); + setInside(endBackSlash ? quote : null); + return {type: "string", style: "js-string"}; + } + function readOmetaIdentifierString() { + source.nextWhileMatches(isWordChar); + return {type: "string", style: "js-string"}; + } + function readOmetaBinding() { + source.nextWhileMatches(isWordChar); + return {type: "variable", style: "ometa-binding"}; + } + + // Fetch the next token. Dispatches on first character in the + // stream, or first two characters when the first is a slash. + if (inside == "\"" || inside == "'") + return readString(inside); + var ch = source.next(); + if (inside == "/*") + return readMultilineComment(ch); + if (inside == '"""' || inside == "'''") + return readMultilineString(ch, inside); + if (ch == '"' && source.lookAhead('""', true) || ch == "'" && source.lookAhead("''", true)) + return readMultilineString('-', ch+ch+ch); // work as far as '-' is not '"' nor "'" + else if (ch == "\"" || ch == "'") + return readString(ch); + else if (ch == "`" || ch == "#" ) + return readOmetaIdentifierString(); + else if (ch == ':' && isWordChar.test(source.peek())) + return readOmetaBinding(); + // with punctuation, the type of the token is the symbol itself + else if (/[\[\]{}\(\),;\:\.]/.test(ch)) + return {type: ch, style: "js-punctuation"}; + else if (ch == "0" && (source.equals("x") || source.equals("X"))) + return readHexNumber(); + else if (/[0-9]/.test(ch)) + return readNumber(); + else if (ch == "/"){ + if (source.equals("*")) + { source.next(); return readMultilineComment(ch); } + else if (source.equals("/")) + { nextUntilUnescaped(source, null); return {type: "comment", style: "js-comment"};} + else if (regexp) + return readRegexp(); + else + return readOperator(); + } + else if (isOperatorChar.test(ch)) + return readOperator(); + else + return readWord(); + } + + // The external interface to the tokenizer. + return function(source, startState) { + return tokenizer(source, startState || jsTokenState(false, true)); + }; +})(); diff --git a/gulliver/js/codemirror/contrib/php/LICENSE b/gulliver/js/codemirror/contrib/php/LICENSE new file mode 100755 index 000000000..32f48cad0 --- /dev/null +++ b/gulliver/js/codemirror/contrib/php/LICENSE @@ -0,0 +1,37 @@ +Copyright (c) 2008-2009, Yahoo! Inc. +All rights reserved. + +This software is provided for use in connection with the +CodeMirror suite of modules and utilities, hosted and maintained +at http://codemirror.net/. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of Yahoo! Inc. nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of Yahoo! Inc. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/gulliver/js/codemirror/contrib/php/css/phpcolors.css b/gulliver/js/codemirror/contrib/php/css/phpcolors.css new file mode 100755 index 000000000..43d4057b1 --- /dev/null +++ b/gulliver/js/codemirror/contrib/php/css/phpcolors.css @@ -0,0 +1,114 @@ +/* +Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved. +The copyrights embodied in the content of this file are licensed by +Yahoo! Inc. under the BSD (revised) open source license + +@author Dan Vlad Dascalescu +*/ + +html { + cursor: text; +} + +.editbox { + margin: .4em; + padding: 0; + font-family: monospace; + font-size: 10pt; +} + +/*We should define specific styles for every element of the syntax. + the setting below will cause some annoying color to show through if we missed + defining a style for a token. This is also the "color" of the whitespace and + of the cursor. +*/ +pre.code, .editbox { + color: red; +} + +.editbox p { + margin: 0; +} + +span.php-punctuation { + color: blue; +} + +span.php-keyword { + color: #770088; + font-weight: bold; +} + +span.php-operator { + color: blue; +} + +/* __FILE__ etc.; http://php.net/manual/en/reserved.php */ +span.php-compile-time-constant { + color: #776088; + font-weight: bold; +} + +/* output of get_defined_constants(). Differs from http://php.net/manual/en/reserved.constants.php */ +span.php-predefined-constant { + color: darkgreen; + font-weight: bold; +} + +/* PHP reserved "language constructs"... echo() etc.; http://php.net/manual/en/reserved.php */ +span.php-reserved-language-construct { + color: green; + font-weight: bold; +} + +/* PHP built-in functions: glob(), chr() etc.; output of get_defined_functions()["internal"] */ +span.php-predefined-function { + color: green; +} + +/* PHP predefined classes: PDO, Exception etc.; output of get_declared_classes() and different from http://php.net/manual/en/reserved.classes.php */ +span.php-predefined-class { + color: green; +} + +span.php-atom { + color: #228811; +} + +/* class, interface, namespace or function names, but not $variables */ +span.php-t_string { + color: black; +} + +span.php-variable { + color: black; + font-weight: bold; +} + + +span.js-localvariable { + color: #004499; +} + +span.php-comment { + color: #AA7700; + font-stretch: condensed; +/* font-style: italic; This causes line height to slightly change, getting line numbers out of sync */ +} + +span.php-string-single-quoted { + color: #AA2222; +} +/* double quoted strings allow interpolation */ +span.php-string-double-quoted { + color: #AA2222; + font-weight: bold; +} + +span.syntax-error { + background-color: red; +} + +span.deprecated { + font-size: smaller; +} diff --git a/gulliver/js/codemirror/contrib/php/index.html b/gulliver/js/codemirror/contrib/php/index.html new file mode 100755 index 000000000..006cb563e --- /dev/null +++ b/gulliver/js/codemirror/contrib/php/index.html @@ -0,0 +1,310 @@ + + + + + + + CodeMirror: PHP+HTML+JavaScript+CSS mixed-mode demonstration + + + + +

This is a complex demonstration of the PHP+HTML+JavaScript+CSS mixed-mode + syntax highlight capabilities of CodeMirror. + <?php ... ?> tags use the PHP parser, <script> tags use the JavaScript + parser, and <style> tags use the CSS parser. The rest of the content is + parsed using the XML parser in HTML mode.

+ +

Features of the PHP parser: +

+ +
+ +
+ + + + + + diff --git a/gulliver/js/codemirror/contrib/php/js/parsephp.js b/gulliver/js/codemirror/contrib/php/js/parsephp.js new file mode 100755 index 000000000..7d0ad1f3b --- /dev/null +++ b/gulliver/js/codemirror/contrib/php/js/parsephp.js @@ -0,0 +1,419 @@ +/* +Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved. +The copyrights embodied in the content of this file are licensed by +Yahoo! Inc. under the BSD (revised) open source license + +@author Dan Vlad Dascalescu + + +Parse function for PHP. Makes use of the tokenizer from tokenizephp.js. +Based on parsejavascript.js by Marijn Haverbeke. + + +Features: + + special "deprecated" style for PHP4 keywords like 'var' + + support for PHP 5.3 keywords: 'namespace', 'use' + + 911 predefined constants, 1301 predefined functions, 105 predeclared classes + from a typical PHP installation in a LAMP environment + + new feature: syntax error flagging, thus enabling strict parsing of: + + function definitions with explicitly or implicitly typed arguments and default values + + modifiers (public, static etc.) applied to method and member definitions + + foreach(array_expression as $key [=> $value]) loops + + differentiation between single-quoted strings and double-quoted interpolating strings + +*/ + + +// add the Array.indexOf method for JS engines that don't support it (e.g. IE) +// code from https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Global_Objects/Array/IndexOf +if (!Array.prototype.indexOf) +{ + Array.prototype.indexOf = function(elt /*, from*/) + { + var len = this.length; + + var from = Number(arguments[1]) || 0; + from = (from < 0) + ? Math.ceil(from) + : Math.floor(from); + if (from < 0) + from += len; + + for (; from < len; from++) + { + if (from in this && + this[from] === elt) + return from; + } + return -1; + }; +} + + +var PHPParser = Editor.Parser = (function() { + // Token types that can be considered to be atoms, part of operator expressions + var atomicTypes = { + "atom": true, "number": true, "variable": true, "string": true + }; + // Constructor for the lexical context objects. + function PHPLexical(indented, column, type, align, prev, info) { + // indentation at start of this line + this.indented = indented; + // column at which this scope was opened + this.column = column; + // type of scope ('stat' (statement), 'form' (special form), '[', '{', or '(') + this.type = type; + // '[', '{', or '(' blocks that have any text after their opening + // character are said to be 'aligned' -- any lines below are + // indented all the way to the opening character. + if (align != null) + this.align = align; + // Parent scope, if any. + this.prev = prev; + this.info = info; + } + + // PHP indentation rules + function indentPHP(lexical) { + return function(firstChars) { + var firstChar = firstChars && firstChars.charAt(0), type = lexical.type; + var closing = firstChar == type; + if (type == "form" && firstChar == "{") + return lexical.indented; + else if (type == "stat" || type == "form") + return lexical.indented + indentUnit; + else if (lexical.info == "switch" && !closing) + return lexical.indented + (/^(?:case|default)\b/.test(firstChars) ? indentUnit : 2 * indentUnit); + else if (lexical.align) + return lexical.column - (closing ? 1 : 0); + else + return lexical.indented + (closing ? 0 : indentUnit); + }; + } + + // The parser-iterator-producing function itself. + function parsePHP(input, basecolumn) { + // Wrap the input in a token stream + var tokens = tokenizePHP(input); + // The parser state. cc is a stack of actions that have to be + // performed to finish the current statement. For example we might + // know that we still need to find a closing parenthesis and a + // semicolon. Actions at the end of the stack go first. It is + // initialized with an infinitely looping action that consumes + // whole statements. + var cc = [statements]; + // The lexical scope, used mostly for indentation. + var lexical = new PHPLexical((basecolumn || 0) - indentUnit, 0, "block", false); + // Current column, and the indentation at the start of the current + // line. Used to create lexical scope objects. + var column = 0; + var indented = 0; + // Variables which are used by the mark, cont, and pass functions + // below to communicate with the driver loop in the 'next' function. + var consume, marked; + + // The iterator object. + var parser = {next: next, copy: copy}; + + // parsing is accomplished by calling next() repeatedly + function next(){ + // Start by performing any 'lexical' actions (adjusting the + // lexical variable), or the operations below will be working + // with the wrong lexical state. + while(cc[cc.length - 1].lex) + cc.pop()(); + + // Fetch the next token. + var token = tokens.next(); + + // Adjust column and indented. + if (token.type == "whitespace" && column == 0) + indented = token.value.length; + column += token.value.length; + if (token.content == "\n"){ + indented = column = 0; + // If the lexical scope's align property is still undefined at + // the end of the line, it is an un-aligned scope. + if (!("align" in lexical)) + lexical.align = false; + // Newline tokens get an indentation function associated with + // them. + token.indentation = indentPHP(lexical); + } + // No more processing for meaningless tokens. + if (token.type == "whitespace" || token.type == "comment" + || token.type == "string_not_terminated" ) + return token; + // When a meaningful token is found and the lexical scope's + // align is undefined, it is an aligned scope. + if (!("align" in lexical)) + lexical.align = true; + + // Execute actions until one 'consumes' the token and we can + // return it. 'marked' is used to change the style of the current token. + while(true) { + consume = marked = false; + // Take and execute the topmost action. + var action = cc.pop(); + action(token); + + if (consume){ + if (marked) + token.style = marked; + // Here we differentiate between local and global variables. + return token; + } + } + return 1; // Firebug workaround for http://code.google.com/p/fbug/issues/detail?id=1239#c1 + } + + // This makes a copy of the parser state. It stores all the + // stateful variables in a closure, and returns a function that + // will restore them when called with a new input stream. Note + // that the cc array has to be copied, because it is contantly + // being modified. Lexical objects are not mutated, so they can + // be shared between runs of the parser. + function copy(){ + var _lexical = lexical, _cc = cc.concat([]), _tokenState = tokens.state; + + return function copyParser(input){ + lexical = _lexical; + cc = _cc.concat([]); // copies the array + column = indented = 0; + tokens = tokenizePHP(input, _tokenState); + return parser; + }; + } + + // Helper function for pushing a number of actions onto the cc + // stack in reverse order. + function push(fs){ + for (var i = fs.length - 1; i >= 0; i--) + cc.push(fs[i]); + } + // cont and pass are used by the action functions to add other + // actions to the stack. cont will cause the current token to be + // consumed, pass will leave it for the next action. + function cont(){ + push(arguments); + consume = true; + } + function pass(){ + push(arguments); + consume = false; + } + // Used to change the style of the current token. + function mark(style){ + marked = style; + } + // Add a lyer of style to the current token, for example syntax-error + function mark_add(style){ + marked = marked + ' ' + style; + } + + // Push a new lexical context of the given type. + function pushlex(type, info) { + var result = function pushlexing() { + lexical = new PHPLexical(indented, column, type, null, lexical, info) + }; + result.lex = true; + return result; + } + // Pop off the current lexical context. + function poplex(){ + if (lexical.prev) + lexical = lexical.prev; + } + poplex.lex = true; + // The 'lex' flag on these actions is used by the 'next' function + // to know they can (and have to) be ran before moving on to the + // next token. + + // Creates an action that discards tokens until it finds one of + // the given type. This will ignore (and recover from) syntax errors. + function expect(wanted){ + return function expecting(token){ + if (token.type == wanted) cont(); // consume the token + else { + cont(arguments.callee); // continue expecting() - call itself + } + }; + } + + // Require a specific token type, or one of the tokens passed in the 'wanted' array + // Used to detect blatant syntax errors. 'execute' is used to pass extra code + // to be executed if the token is matched. For example, a '(' match could + // 'execute' a cont( compasep(funcarg), require(")") ) + function require(wanted, execute){ + return function requiring(token){ + var ok; + var type = token.type; + if (typeof(wanted) == "string") + ok = (type == wanted) -1; + else + ok = wanted.indexOf(type); + if (ok >= 0) { + if (execute && typeof(execute[ok]) == "function") pass(execute[ok]); + else cont(); + } + else { + if (!marked) mark(token.style); + mark_add("syntax-error"); + cont(arguments.callee); + } + }; + } + + // Looks for a statement, and then calls itself. + function statements(token){ + return pass(statement, statements); + } + // Dispatches various types of statements based on the type of the current token. + function statement(token){ + var type = token.type; + if (type == "keyword a") cont(pushlex("form"), expression, altsyntax, statement, poplex); + else if (type == "keyword b") cont(pushlex("form"), altsyntax, statement, poplex); + else if (type == "{") cont(pushlex("}"), block, poplex); + else if (type == "function") funcdef(); + // technically, "class implode {...}" is correct, but we'll flag that as an error because it overrides a predefined function + else if (type == "class") classdef(); + else if (type == "foreach") cont(pushlex("form"), require("("), pushlex(")"), expression, require("as"), require("variable"), /* => $value */ expect(")"), altsyntax, poplex, statement, poplex); + else if (type == "for") cont(pushlex("form"), require("("), pushlex(")"), expression, require(";"), expression, require(";"), expression, require(")"), altsyntax, poplex, statement, poplex); + // public final function foo(), protected static $bar; + else if (type == "modifier") cont(require(["modifier", "variable", "function", "abstract"], + [null, commasep(require("variable")), funcdef, absfun])); + else if (type == "abstract") abs(); + else if (type == "switch") cont(pushlex("form"), require("("), expression, require(")"), pushlex("}", "switch"), require([":", "{"]), block, poplex, poplex); + else if (type == "case") cont(expression, require(":")); + else if (type == "default") cont(require(":")); + else if (type == "catch") cont(pushlex("form"), require("("), require("t_string"), require("variable"), require(")"), statement, poplex); + else if (type == "const") cont(require("t_string")); // 'const static x=5' is a syntax error + // technically, "namespace implode {...}" is correct, but we'll flag that as an error because it overrides a predefined function + else if (type == "namespace") cont(namespacedef, require(";")); + // $variables may be followed by operators, () for variable function calls, or [] subscripts + else pass(pushlex("stat"), expression, require(";"), poplex); + } + // Dispatch expression types. + function expression(token){ + var type = token.type; + if (atomicTypes.hasOwnProperty(type)) cont(maybeoperator); + else if (type == "<<<") cont(require("string"), maybeoperator); // heredoc/nowdoc + else if (type == "t_string") cont(maybe_double_colon, maybeoperator); + else if (type == "keyword c" || type == "operator") cont(expression); + // lambda + else if (type == "function") lambdadef(); + // function call or parenthesized expression: $a = ($b + 1) * 2; + else if (type == "(") cont(pushlex(")"), commasep(expression), require(")"), poplex, maybeoperator); + } + // Called for places where operators, function calls, or subscripts are + // valid. Will skip on to the next action if none is found. + function maybeoperator(token){ + var type = token.type; + if (type == "operator") { + if (token.content == "?") cont(expression, require(":"), expression); // ternary operator + else cont(expression); + } + else if (type == "(") cont(pushlex(")"), expression, commasep(expression), require(")"), poplex, maybeoperator /* $varfunc() + 3 */); + else if (type == "[") cont(pushlex("]"), expression, require("]"), maybeoperator /* for multidimensional arrays, or $func[$i]() */, poplex); + } + // A regular use of the double colon to specify a class, as in self::func() or myclass::$var; + // Differs from `namespace` or `use` in that only one class can be the parent; chains (A::B::$var) are a syntax error. + function maybe_double_colon(token) { + if (token.type == "t_double_colon") + // A::$var, A::func(), A::const + cont(require(["t_string", "variable"]), maybeoperator); + else { + // a t_string wasn't followed by ::, such as in a function call: foo() + pass(expression) + } + } + // the declaration or definition of a function + function funcdef() { + cont(require("t_string"), require("("), pushlex(")"), commasep(funcarg), require(")"), poplex, block); + } + // the declaration or definition of a lambda + function lambdadef() { + cont(require("("), pushlex(")"), commasep(funcarg), require(")"), maybe_lambda_use, poplex, require("{"), pushlex("}"), block, poplex); + } + // optional lambda 'use' statement + function maybe_lambda_use(token) { + if(token.type == "namespace") { + cont(require('('), commasep(funcarg), require(')')); + } + else { + pass(expression); + } + } + // the definition of a class + function classdef() { + cont(require("t_string"), expect("{"), pushlex("}"), block, poplex); + } + // either funcdef if the current token is "function", or the keyword "function" + funcdef + function absfun(token) { + if(token.type == "function") funcdef(); + else cont(require(["function"], [funcdef])); + } + // the abstract class or function (with optional modifier) + function abs(token) { + cont(require(["modifier", "function", "class"], [absfun, funcdef, classdef])); + } + // Parses a comma-separated list of the things that are recognized + // by the 'what' argument. + function commasep(what){ + function proceed(token) { + if (token.type == ",") cont(what, proceed); + } + return function commaSeparated() { + pass(what, proceed); + }; + } + // Look for statements until a closing brace is found. + function block(token) { + if (token.type == "}") cont(); + else pass(statement, block); + } + function empty_parens_if_array(token) { + if(token.content == "array") + cont(require("("), require(")")); + } + function maybedefaultparameter(token){ + if (token.content == "=") cont(require(["t_string", "string", "number", "atom"], [empty_parens_if_array, null, null])); + } + function var_or_reference(token) { + if(token.type == "variable") cont(maybedefaultparameter); + else if(token.content == "&") cont(require("variable"), maybedefaultparameter); + } + // support for default arguments: http://us.php.net/manual/en/functions.arguments.php#functions.arguments.default + function funcarg(token){ + // function foo(myclass $obj) {...} or function foo(myclass &objref) {...} + if (token.type == "t_string") cont(var_or_reference); + // function foo($var) {...} or function foo(&$ref) {...} + else var_or_reference(token); + } + + // A namespace definition or use + function maybe_double_colon_def(token) { + if (token.type == "t_double_colon") + cont(namespacedef); + } + function namespacedef(token) { + pass(require("t_string"), maybe_double_colon_def); + } + + function altsyntax(token){ + if(token.content==':') + cont(altsyntaxBlock,poplex); + } + + function altsyntaxBlock(token){ + if (token.type == "altsyntaxend") cont(require(';')); + else pass(statement, altsyntaxBlock); + } + + + return parser; + } + + return {make: parsePHP, electricChars: "{}:"}; + +})(); diff --git a/gulliver/js/codemirror/contrib/php/js/parsephphtmlmixed.js b/gulliver/js/codemirror/contrib/php/js/parsephphtmlmixed.js new file mode 100755 index 000000000..fa189c18c --- /dev/null +++ b/gulliver/js/codemirror/contrib/php/js/parsephphtmlmixed.js @@ -0,0 +1,116 @@ +/* +Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved. +The copyrights embodied in the content of this file are licensed by +Yahoo! Inc. under the BSD (revised) open source license + +@author Dan Vlad Dascalescu + +Based on parsehtmlmixed.js by Marijn Haverbeke. +*/ + +var PHPHTMLMixedParser = Editor.Parser = (function() { + var processingInstructions = [""); + break; + } + } + else if (token.style == "xml-attribute" && token.content == "\"php\"" && inTag == "script" && lastAtt == "language") + inTag = "script/php"; + // "xml-processing" tokens are ignored, because they should be handled by a specific local parser + else if (token.content == ">") { + if (inTag == "script/php") + iter.next = local(PHPParser, ""); + else if (inTag == "script") + iter.next = local(JSParser, " + + +Tokenizer for PHP code + +References: + + http://php.net/manual/en/reserved.php + + http://php.net/tokens + + get_defined_constants(), get_defined_functions(), get_declared_classes() + executed on a realistic (not vanilla) PHP installation with typical LAMP modules. + Specifically, the PHP bundled with the Uniform Web Server (www.uniformserver.com). + +*/ + + +// add the forEach method for JS engines that don't support it (e.g. IE) +// code from https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference:Objects:Array:forEach +if (!Array.prototype.forEach) +{ + Array.prototype.forEach = function(fun /*, thisp*/) + { + var len = this.length; + if (typeof fun != "function") + throw new TypeError(); + + var thisp = arguments[1]; + for (var i = 0; i < len; i++) + { + if (i in this) + fun.call(thisp, this[i], i, this); + } + }; +} + + +var tokenizePHP = (function() { + /* A map of PHP's reserved words (keywords, predefined classes, functions and + constants. Each token has a type ('keyword', 'operator' etc.) and a style. + The style corresponds to the CSS span class in phpcolors.css. + + Keywords can be of three types: + a - takes an expression and forms a statement - e.g. if + b - takes just a statement - e.g. else + c - takes an optinoal expression, but no statement - e.g. return + This distinction gives the parser enough information to parse + correct code correctly (we don't care that much how we parse + incorrect code). + + Reference: http://us.php.net/manual/en/reserved.php + */ + var keywords = function(){ + function token(type, style){ + return {type: type, style: style}; + } + var result = {}; + + // for each(var element in ["...", "..."]) can pick up elements added to + // Array.prototype, so we'll use the loop structure below. See also + // http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Statements/for_each...in + + // keywords that take an expression and form a statement + ["if", "elseif", "while", "declare"].forEach(function(element, index, array) { + result[element] = token("keyword a", "php-keyword"); + }); + + // keywords that take just a statement + ["do", "else", "try" ].forEach(function(element, index, array) { + result[element] = token("keyword b", "php-keyword"); + }); + + // keywords that take an optional expression, but no statement + ["return", "break", "continue", // the expression is optional + "new", "clone", "throw" // the expression is mandatory + ].forEach(function(element, index, array) { + result[element] = token("keyword c", "php-keyword"); + }); + + ["__CLASS__", "__DIR__", "__FILE__", "__FUNCTION__", "__METHOD__", "__NAMESPACE__"].forEach(function(element, index, array) { + result[element] = token("atom", "php-compile-time-constant"); + }); + + ["true", "false", "null"].forEach(function(element, index, array) { + result[element] = token("atom", "php-atom"); + }); + + ["and", "or", "xor", "instanceof"].forEach(function(element, index, array) { + result[element] = token("operator", "php-keyword php-operator"); + }); + + ["class", "interface"].forEach(function(element, index, array) { + result[element] = token("class", "php-keyword"); + }); + ["namespace", "use", "extends", "implements"].forEach(function(element, index, array) { + result[element] = token("namespace", "php-keyword"); + }); + + // reserved "language constructs"... http://php.net/manual/en/reserved.php + [ "die", "echo", "empty", "exit", "eval", "include", "include_once", "isset", + "list", "require", "require_once", "return", "print", "unset", + "array" // a keyword rather, but mandates a parenthesized parameter list + ].forEach(function(element, index, array) { + result[element] = token("t_string", "php-reserved-language-construct"); + }); + + result["switch"] = token("switch", "php-keyword"); + result["case"] = token("case", "php-keyword"); + result["default"] = token("default", "php-keyword"); + result["catch"] = token("catch", "php-keyword"); + result["function"] = token("function", "php-keyword"); + + // http://php.net/manual/en/control-structures.alternative-syntax.php must be followed by a ':' + ["endif", "endwhile", "endfor", "endforeach", "endswitch", "enddeclare"].forEach(function(element, index, array) { + result[element] = token("altsyntaxend", "php-keyword"); + }); + + result["const"] = token("const", "php-keyword"); + + ["final", "private", "protected", "public", "global", "static"].forEach(function(element, index, array) { + result[element] = token("modifier", "php-keyword"); + }); + result["var"] = token("modifier", "php-keyword deprecated"); + result["abstract"] = token("abstract", "php-keyword"); + + result["foreach"] = token("foreach", "php-keyword"); + result["as"] = token("as", "php-keyword"); + result["for"] = token("for", "php-keyword"); + + // PHP built-in functions - output of get_defined_functions()["internal"] + [ "zend_version", "func_num_args", "func_get_arg", "func_get_args", "strlen", + "strcmp", "strncmp", "strcasecmp", "strncasecmp", "each", "error_reporting", + "define", "defined", "get_class", "get_parent_class", "method_exists", + "property_exists", "class_exists", "interface_exists", "function_exists", + "get_included_files", "get_required_files", "is_subclass_of", "is_a", + "get_class_vars", "get_object_vars", "get_class_methods", "trigger_error", + "user_error", "set_error_handler", "restore_error_handler", + "set_exception_handler", "restore_exception_handler", "get_declared_classes", + "get_declared_interfaces", "get_defined_functions", "get_defined_vars", + "create_function", "get_resource_type", "get_loaded_extensions", + "extension_loaded", "get_extension_funcs", "get_defined_constants", + "debug_backtrace", "debug_print_backtrace", "bcadd", "bcsub", "bcmul", "bcdiv", + "bcmod", "bcpow", "bcsqrt", "bcscale", "bccomp", "bcpowmod", "jdtogregorian", + "gregoriantojd", "jdtojulian", "juliantojd", "jdtojewish", "jewishtojd", + "jdtofrench", "frenchtojd", "jddayofweek", "jdmonthname", "easter_date", + "easter_days", "unixtojd", "jdtounix", "cal_to_jd", "cal_from_jd", + "cal_days_in_month", "cal_info", "variant_set", "variant_add", "variant_cat", + "variant_sub", "variant_mul", "variant_and", "variant_div", "variant_eqv", + "variant_idiv", "variant_imp", "variant_mod", "variant_or", "variant_pow", + "variant_xor", "variant_abs", "variant_fix", "variant_int", "variant_neg", + "variant_not", "variant_round", "variant_cmp", "variant_date_to_timestamp", + "variant_date_from_timestamp", "variant_get_type", "variant_set_type", + "variant_cast", "com_create_guid", "com_event_sink", "com_print_typeinfo", + "com_message_pump", "com_load_typelib", "com_get_active_object", "ctype_alnum", + "ctype_alpha", "ctype_cntrl", "ctype_digit", "ctype_lower", "ctype_graph", + "ctype_print", "ctype_punct", "ctype_space", "ctype_upper", "ctype_xdigit", + "strtotime", "date", "idate", "gmdate", "mktime", "gmmktime", "checkdate", + "strftime", "gmstrftime", "time", "localtime", "getdate", "date_create", + "date_parse", "date_format", "date_modify", "date_timezone_get", + "date_timezone_set", "date_offset_get", "date_time_set", "date_date_set", + "date_isodate_set", "timezone_open", "timezone_name_get", + "timezone_name_from_abbr", "timezone_offset_get", "timezone_transitions_get", + "timezone_identifiers_list", "timezone_abbreviations_list", + "date_default_timezone_set", "date_default_timezone_get", "date_sunrise", + "date_sunset", "date_sun_info", "filter_input", "filter_var", + "filter_input_array", "filter_var_array", "filter_list", "filter_has_var", + "filter_id", "ftp_connect", "ftp_login", "ftp_pwd", "ftp_cdup", "ftp_chdir", + "ftp_exec", "ftp_raw", "ftp_mkdir", "ftp_rmdir", "ftp_chmod", "ftp_alloc", + "ftp_nlist", "ftp_rawlist", "ftp_systype", "ftp_pasv", "ftp_get", "ftp_fget", + "ftp_put", "ftp_fput", "ftp_size", "ftp_mdtm", "ftp_rename", "ftp_delete", + "ftp_site", "ftp_close", "ftp_set_option", "ftp_get_option", "ftp_nb_fget", + "ftp_nb_get", "ftp_nb_continue", "ftp_nb_put", "ftp_nb_fput", "ftp_quit", + "hash", "hash_file", "hash_hmac", "hash_hmac_file", "hash_init", "hash_update", + "hash_update_stream", "hash_update_file", "hash_final", "hash_algos", "iconv", + "ob_iconv_handler", "iconv_get_encoding", "iconv_set_encoding", "iconv_strlen", + "iconv_substr", "iconv_strpos", "iconv_strrpos", "iconv_mime_encode", + "iconv_mime_decode", "iconv_mime_decode_headers", "json_encode", "json_decode", + "odbc_autocommit", "odbc_binmode", "odbc_close", "odbc_close_all", + "odbc_columns", "odbc_commit", "odbc_connect", "odbc_cursor", + "odbc_data_source", "odbc_execute", "odbc_error", "odbc_errormsg", "odbc_exec", + "odbc_fetch_array", "odbc_fetch_object", "odbc_fetch_row", "odbc_fetch_into", + "odbc_field_len", "odbc_field_scale", "odbc_field_name", "odbc_field_type", + "odbc_field_num", "odbc_free_result", "odbc_gettypeinfo", "odbc_longreadlen", + "odbc_next_result", "odbc_num_fields", "odbc_num_rows", "odbc_pconnect", + "odbc_prepare", "odbc_result", "odbc_result_all", "odbc_rollback", + "odbc_setoption", "odbc_specialcolumns", "odbc_statistics", "odbc_tables", + "odbc_primarykeys", "odbc_columnprivileges", "odbc_tableprivileges", + "odbc_foreignkeys", "odbc_procedures", "odbc_procedurecolumns", "odbc_do", + "odbc_field_precision", "preg_match", "preg_match_all", "preg_replace", + "preg_replace_callback", "preg_split", "preg_quote", "preg_grep", + "preg_last_error", "session_name", "session_module_name", "session_save_path", + "session_id", "session_regenerate_id", "session_decode", "session_register", + "session_unregister", "session_is_registered", "session_encode", + "session_start", "session_destroy", "session_unset", + "session_set_save_handler", "session_cache_limiter", "session_cache_expire", + "session_set_cookie_params", "session_get_cookie_params", + "session_write_close", "session_commit", "spl_classes", "spl_autoload", + "spl_autoload_extensions", "spl_autoload_register", "spl_autoload_unregister", + "spl_autoload_functions", "spl_autoload_call", "class_parents", + "class_implements", "spl_object_hash", "iterator_to_array", "iterator_count", + "iterator_apply", "constant", "bin2hex", "sleep", "usleep", "flush", + "wordwrap", "htmlspecialchars", "htmlentities", "html_entity_decode", + "htmlspecialchars_decode", "get_html_translation_table", "sha1", "sha1_file", + "md5", "md5_file", "crc32", "iptcparse", "iptcembed", "getimagesize", + "image_type_to_mime_type", "image_type_to_extension", "phpinfo", "phpversion", + "phpcredits", "php_logo_guid", "php_real_logo_guid", "php_egg_logo_guid", + "zend_logo_guid", "php_sapi_name", "php_uname", "php_ini_scanned_files", + "strnatcmp", "strnatcasecmp", "substr_count", "strspn", "strcspn", "strtok", + "strtoupper", "strtolower", "strpos", "stripos", "strrpos", "strripos", + "strrev", "hebrev", "hebrevc", "nl2br", "basename", "dirname", "pathinfo", + "stripslashes", "stripcslashes", "strstr", "stristr", "strrchr", "str_shuffle", + "str_word_count", "str_split", "strpbrk", "substr_compare", "strcoll", + "substr", "substr_replace", "quotemeta", "ucfirst", "ucwords", "strtr", + "addslashes", "addcslashes", "rtrim", "str_replace", "str_ireplace", + "str_repeat", "count_chars", "chunk_split", "trim", "ltrim", "strip_tags", + "similar_text", "explode", "implode", "setlocale", "localeconv", "soundex", + "levenshtein", "chr", "ord", "parse_str", "str_pad", "chop", "strchr", + "sprintf", "printf", "vprintf", "vsprintf", "fprintf", "vfprintf", "sscanf", + "fscanf", "parse_url", "urlencode", "urldecode", "rawurlencode", + "rawurldecode", "http_build_query", "unlink", "exec", "system", + "escapeshellcmd", "escapeshellarg", "passthru", "shell_exec", "proc_open", + "proc_close", "proc_terminate", "proc_get_status", "rand", "srand", + "getrandmax", "mt_rand", "mt_srand", "mt_getrandmax", "getservbyname", + "getservbyport", "getprotobyname", "getprotobynumber", "getmyuid", "getmygid", + "getmypid", "getmyinode", "getlastmod", "base64_decode", "base64_encode", + "convert_uuencode", "convert_uudecode", "abs", "ceil", "floor", "round", "sin", + "cos", "tan", "asin", "acos", "atan", "atan2", "sinh", "cosh", "tanh", "pi", + "is_finite", "is_nan", "is_infinite", "pow", "exp", "log", "log10", "sqrt", + "hypot", "deg2rad", "rad2deg", "bindec", "hexdec", "octdec", "decbin", + "decoct", "dechex", "base_convert", "number_format", "fmod", "ip2long", + "long2ip", "getenv", "putenv", "microtime", "gettimeofday", "uniqid", + "quoted_printable_decode", "convert_cyr_string", "get_current_user", + "set_time_limit", "get_cfg_var", "magic_quotes_runtime", + "set_magic_quotes_runtime", "get_magic_quotes_gpc", "get_magic_quotes_runtime", + "import_request_variables", "error_log", "error_get_last", "call_user_func", + "call_user_func_array", "call_user_method", "call_user_method_array", + "serialize", "unserialize", "var_dump", "var_export", "debug_zval_dump", + "print_r", "memory_get_usage", "memory_get_peak_usage", + "register_shutdown_function", "register_tick_function", + "unregister_tick_function", "highlight_file", "show_source", + "highlight_string", "php_strip_whitespace", "ini_get", "ini_get_all", + "ini_set", "ini_alter", "ini_restore", "get_include_path", "set_include_path", + "restore_include_path", "setcookie", "setrawcookie", "header", "headers_sent", + "headers_list", "connection_aborted", "connection_status", "ignore_user_abort", + "parse_ini_file", "is_uploaded_file", "move_uploaded_file", "gethostbyaddr", + "gethostbyname", "gethostbynamel", "intval", "floatval", "doubleval", "strval", + "gettype", "settype", "is_null", "is_resource", "is_bool", "is_long", + "is_float", "is_int", "is_integer", "is_double", "is_real", "is_numeric", + "is_string", "is_array", "is_object", "is_scalar", "is_callable", "ereg", + "ereg_replace", "eregi", "eregi_replace", "split", "spliti", "join", + "sql_regcase", "dl", "pclose", "popen", "readfile", "rewind", "rmdir", "umask", + "fclose", "feof", "fgetc", "fgets", "fgetss", "fread", "fopen", "fpassthru", + "ftruncate", "fstat", "fseek", "ftell", "fflush", "fwrite", "fputs", "mkdir", + "rename", "copy", "tempnam", "tmpfile", "file", "file_get_contents", + "file_put_contents", "stream_select", "stream_context_create", + "stream_context_set_params", "stream_context_set_option", + "stream_context_get_options", "stream_context_get_default", + "stream_filter_prepend", "stream_filter_append", "stream_filter_remove", + "stream_socket_client", "stream_socket_server", "stream_socket_accept", + "stream_socket_get_name", "stream_socket_recvfrom", "stream_socket_sendto", + "stream_socket_enable_crypto", "stream_socket_shutdown", + "stream_copy_to_stream", "stream_get_contents", "fgetcsv", "fputcsv", "flock", + "get_meta_tags", "stream_set_write_buffer", "set_file_buffer", + "set_socket_blocking", "stream_set_blocking", "socket_set_blocking", + "stream_get_meta_data", "stream_get_line", "stream_wrapper_register", + "stream_register_wrapper", "stream_wrapper_unregister", + "stream_wrapper_restore", "stream_get_wrappers", "stream_get_transports", + "get_headers", "stream_set_timeout", "socket_set_timeout", "socket_get_status", + "realpath", "fsockopen", "pfsockopen", "pack", "unpack", "get_browser", + "crypt", "opendir", "closedir", "chdir", "getcwd", "rewinddir", "readdir", + "dir", "scandir", "glob", "fileatime", "filectime", "filegroup", "fileinode", + "filemtime", "fileowner", "fileperms", "filesize", "filetype", "file_exists", + "is_writable", "is_writeable", "is_readable", "is_executable", "is_file", + "is_dir", "is_link", "stat", "lstat", "chown", "chgrp", "chmod", "touch", + "clearstatcache", "disk_total_space", "disk_free_space", "diskfreespace", + "mail", "ezmlm_hash", "openlog", "syslog", "closelog", + "define_syslog_variables", "lcg_value", "metaphone", "ob_start", "ob_flush", + "ob_clean", "ob_end_flush", "ob_end_clean", "ob_get_flush", "ob_get_clean", + "ob_get_length", "ob_get_level", "ob_get_status", "ob_get_contents", + "ob_implicit_flush", "ob_list_handlers", "ksort", "krsort", "natsort", + "natcasesort", "asort", "arsort", "sort", "rsort", "usort", "uasort", "uksort", + "shuffle", "array_walk", "array_walk_recursive", "count", "end", "prev", + "next", "reset", "current", "key", "min", "max", "in_array", "array_search", + "extract", "compact", "array_fill", "array_fill_keys", "range", + "array_multisort", "array_push", "array_pop", "array_shift", "array_unshift", + "array_splice", "array_slice", "array_merge", "array_merge_recursive", + "array_keys", "array_values", "array_count_values", "array_reverse", + "array_reduce", "array_pad", "array_flip", "array_change_key_case", + "array_rand", "array_unique", "array_intersect", "array_intersect_key", + "array_intersect_ukey", "array_uintersect", "array_intersect_assoc", + "array_uintersect_assoc", "array_intersect_uassoc", "array_uintersect_uassoc", + "array_diff", "array_diff_key", "array_diff_ukey", "array_udiff", + "array_diff_assoc", "array_udiff_assoc", "array_diff_uassoc", + "array_udiff_uassoc", "array_sum", "array_product", "array_filter", + "array_map", "array_chunk", "array_combine", "array_key_exists", "pos", + "sizeof", "key_exists", "assert", "assert_options", "version_compare", + "str_rot13", "stream_get_filters", "stream_filter_register", + "stream_bucket_make_writeable", "stream_bucket_prepend", + "stream_bucket_append", "stream_bucket_new", "output_add_rewrite_var", + "output_reset_rewrite_vars", "sys_get_temp_dir", "token_get_all", "token_name", + "readgzfile", "gzrewind", "gzclose", "gzeof", "gzgetc", "gzgets", "gzgetss", + "gzread", "gzopen", "gzpassthru", "gzseek", "gztell", "gzwrite", "gzputs", + "gzfile", "gzcompress", "gzuncompress", "gzdeflate", "gzinflate", "gzencode", + "ob_gzhandler", "zlib_get_coding_type", "libxml_set_streams_context", + "libxml_use_internal_errors", "libxml_get_last_error", "libxml_clear_errors", + "libxml_get_errors", "dom_import_simplexml", "simplexml_load_file", + "simplexml_load_string", "simplexml_import_dom", "wddx_serialize_value", + "wddx_serialize_vars", "wddx_packet_start", "wddx_packet_end", "wddx_add_vars", + "wddx_deserialize", "xml_parser_create", "xml_parser_create_ns", + "xml_set_object", "xml_set_element_handler", "xml_set_character_data_handler", + "xml_set_processing_instruction_handler", "xml_set_default_handler", + "xml_set_unparsed_entity_decl_handler", "xml_set_notation_decl_handler", + "xml_set_external_entity_ref_handler", "xml_set_start_namespace_decl_handler", + "xml_set_end_namespace_decl_handler", "xml_parse", "xml_parse_into_struct", + "xml_get_error_code", "xml_error_string", "xml_get_current_line_number", + "xml_get_current_column_number", "xml_get_current_byte_index", + "xml_parser_free", "xml_parser_set_option", "xml_parser_get_option", + "utf8_encode", "utf8_decode", "xmlwriter_open_uri", "xmlwriter_open_memory", + "xmlwriter_set_indent", "xmlwriter_set_indent_string", + "xmlwriter_start_comment", "xmlwriter_end_comment", + "xmlwriter_start_attribute", "xmlwriter_end_attribute", + "xmlwriter_write_attribute", "xmlwriter_start_attribute_ns", + "xmlwriter_write_attribute_ns", "xmlwriter_start_element", + "xmlwriter_end_element", "xmlwriter_full_end_element", + "xmlwriter_start_element_ns", "xmlwriter_write_element", + "xmlwriter_write_element_ns", "xmlwriter_start_pi", "xmlwriter_end_pi", + "xmlwriter_write_pi", "xmlwriter_start_cdata", "xmlwriter_end_cdata", + "xmlwriter_write_cdata", "xmlwriter_text", "xmlwriter_write_raw", + "xmlwriter_start_document", "xmlwriter_end_document", + "xmlwriter_write_comment", "xmlwriter_start_dtd", "xmlwriter_end_dtd", + "xmlwriter_write_dtd", "xmlwriter_start_dtd_element", + "xmlwriter_end_dtd_element", "xmlwriter_write_dtd_element", + "xmlwriter_start_dtd_attlist", "xmlwriter_end_dtd_attlist", + "xmlwriter_write_dtd_attlist", "xmlwriter_start_dtd_entity", + "xmlwriter_end_dtd_entity", "xmlwriter_write_dtd_entity", + "xmlwriter_output_memory", "xmlwriter_flush", "gd_info", "imagearc", + "imageellipse", "imagechar", "imagecharup", "imagecolorat", + "imagecolorallocate", "imagepalettecopy", "imagecreatefromstring", + "imagecolorclosest", "imagecolordeallocate", "imagecolorresolve", + "imagecolorexact", "imagecolorset", "imagecolortransparent", + "imagecolorstotal", "imagecolorsforindex", "imagecopy", "imagecopymerge", + "imagecopymergegray", "imagecopyresized", "imagecreate", + "imagecreatetruecolor", "imageistruecolor", "imagetruecolortopalette", + "imagesetthickness", "imagefilledarc", "imagefilledellipse", + "imagealphablending", "imagesavealpha", "imagecolorallocatealpha", + "imagecolorresolvealpha", "imagecolorclosestalpha", "imagecolorexactalpha", + "imagecopyresampled", "imagegrabwindow", "imagegrabscreen", "imagerotate", + "imageantialias", "imagesettile", "imagesetbrush", "imagesetstyle", + "imagecreatefrompng", "imagecreatefromgif", "imagecreatefromjpeg", + "imagecreatefromwbmp", "imagecreatefromxbm", "imagecreatefromgd", + "imagecreatefromgd2", "imagecreatefromgd2part", "imagepng", "imagegif", + "imagejpeg", "imagewbmp", "imagegd", "imagegd2", "imagedestroy", + "imagegammacorrect", "imagefill", "imagefilledpolygon", "imagefilledrectangle", + "imagefilltoborder", "imagefontwidth", "imagefontheight", "imageinterlace", + "imageline", "imageloadfont", "imagepolygon", "imagerectangle", + "imagesetpixel", "imagestring", "imagestringup", "imagesx", "imagesy", + "imagedashedline", "imagettfbbox", "imagettftext", "imageftbbox", + "imagefttext", "imagepsloadfont", "imagepsfreefont", "imagepsencodefont", + "imagepsextendfont", "imagepsslantfont", "imagepstext", "imagepsbbox", + "imagetypes", "jpeg2wbmp", "png2wbmp", "image2wbmp", "imagelayereffect", + "imagecolormatch", "imagexbm", "imagefilter", "imageconvolution", + "mb_convert_case", "mb_strtoupper", "mb_strtolower", "mb_language", + "mb_internal_encoding", "mb_http_input", "mb_http_output", "mb_detect_order", + "mb_substitute_character", "mb_parse_str", "mb_output_handler", + "mb_preferred_mime_name", "mb_strlen", "mb_strpos", "mb_strrpos", "mb_stripos", + "mb_strripos", "mb_strstr", "mb_strrchr", "mb_stristr", "mb_strrichr", + "mb_substr_count", "mb_substr", "mb_strcut", "mb_strwidth", "mb_strimwidth", + "mb_convert_encoding", "mb_detect_encoding", "mb_list_encodings", + "mb_convert_kana", "mb_encode_mimeheader", "mb_decode_mimeheader", + "mb_convert_variables", "mb_encode_numericentity", "mb_decode_numericentity", + "mb_send_mail", "mb_get_info", "mb_check_encoding", "mb_regex_encoding", + "mb_regex_set_options", "mb_ereg", "mb_eregi", "mb_ereg_replace", + "mb_eregi_replace", "mb_split", "mb_ereg_match", "mb_ereg_search", + "mb_ereg_search_pos", "mb_ereg_search_regs", "mb_ereg_search_init", + "mb_ereg_search_getregs", "mb_ereg_search_getpos", "mb_ereg_search_setpos", + "mbregex_encoding", "mbereg", "mberegi", "mbereg_replace", "mberegi_replace", + "mbsplit", "mbereg_match", "mbereg_search", "mbereg_search_pos", + "mbereg_search_regs", "mbereg_search_init", "mbereg_search_getregs", + "mbereg_search_getpos", "mbereg_search_setpos", "mysql_connect", + "mysql_pconnect", "mysql_close", "mysql_select_db", "mysql_query", + "mysql_unbuffered_query", "mysql_db_query", "mysql_list_dbs", + "mysql_list_tables", "mysql_list_fields", "mysql_list_processes", + "mysql_error", "mysql_errno", "mysql_affected_rows", "mysql_insert_id", + "mysql_result", "mysql_num_rows", "mysql_num_fields", "mysql_fetch_row", + "mysql_fetch_array", "mysql_fetch_assoc", "mysql_fetch_object", + "mysql_data_seek", "mysql_fetch_lengths", "mysql_fetch_field", + "mysql_field_seek", "mysql_free_result", "mysql_field_name", + "mysql_field_table", "mysql_field_len", "mysql_field_type", + "mysql_field_flags", "mysql_escape_string", "mysql_real_escape_string", + "mysql_stat", "mysql_thread_id", "mysql_client_encoding", "mysql_ping", + "mysql_get_client_info", "mysql_get_host_info", "mysql_get_proto_info", + "mysql_get_server_info", "mysql_info", "mysql_set_charset", "mysql", + "mysql_fieldname", "mysql_fieldtable", "mysql_fieldlen", "mysql_fieldtype", + "mysql_fieldflags", "mysql_selectdb", "mysql_freeresult", "mysql_numfields", + "mysql_numrows", "mysql_listdbs", "mysql_listtables", "mysql_listfields", + "mysql_db_name", "mysql_dbname", "mysql_tablename", "mysql_table_name", + "mysqli_affected_rows", "mysqli_autocommit", "mysqli_change_user", + "mysqli_character_set_name", "mysqli_close", "mysqli_commit", "mysqli_connect", + "mysqli_connect_errno", "mysqli_connect_error", "mysqli_data_seek", + "mysqli_debug", "mysqli_disable_reads_from_master", "mysqli_disable_rpl_parse", + "mysqli_dump_debug_info", "mysqli_enable_reads_from_master", + "mysqli_enable_rpl_parse", "mysqli_embedded_server_end", + "mysqli_embedded_server_start", "mysqli_errno", "mysqli_error", + "mysqli_stmt_execute", "mysqli_execute", "mysqli_fetch_field", + "mysqli_fetch_fields", "mysqli_fetch_field_direct", "mysqli_fetch_lengths", + "mysqli_fetch_array", "mysqli_fetch_assoc", "mysqli_fetch_object", + "mysqli_fetch_row", "mysqli_field_count", "mysqli_field_seek", + "mysqli_field_tell", "mysqli_free_result", "mysqli_get_charset", + "mysqli_get_client_info", "mysqli_get_client_version", "mysqli_get_host_info", + "mysqli_get_proto_info", "mysqli_get_server_info", "mysqli_get_server_version", + "mysqli_get_warnings", "mysqli_init", "mysqli_info", "mysqli_insert_id", + "mysqli_kill", "mysqli_set_local_infile_default", + "mysqli_set_local_infile_handler", "mysqli_master_query", + "mysqli_more_results", "mysqli_multi_query", "mysqli_next_result", + "mysqli_num_fields", "mysqli_num_rows", "mysqli_options", "mysqli_ping", + "mysqli_prepare", "mysqli_report", "mysqli_query", "mysqli_real_connect", + "mysqli_real_escape_string", "mysqli_real_query", "mysqli_rollback", + "mysqli_rpl_parse_enabled", "mysqli_rpl_probe", "mysqli_rpl_query_type", + "mysqli_select_db", "mysqli_set_charset", "mysqli_stmt_attr_get", + "mysqli_stmt_attr_set", "mysqli_stmt_field_count", "mysqli_stmt_init", + "mysqli_stmt_prepare", "mysqli_stmt_result_metadata", + "mysqli_stmt_send_long_data", "mysqli_stmt_bind_param", + "mysqli_stmt_bind_result", "mysqli_stmt_fetch", "mysqli_stmt_free_result", + "mysqli_stmt_get_warnings", "mysqli_stmt_insert_id", "mysqli_stmt_reset", + "mysqli_stmt_param_count", "mysqli_send_query", "mysqli_slave_query", + "mysqli_sqlstate", "mysqli_ssl_set", "mysqli_stat", + "mysqli_stmt_affected_rows", "mysqli_stmt_close", "mysqli_stmt_data_seek", + "mysqli_stmt_errno", "mysqli_stmt_error", "mysqli_stmt_num_rows", + "mysqli_stmt_sqlstate", "mysqli_store_result", "mysqli_stmt_store_result", + "mysqli_thread_id", "mysqli_thread_safe", "mysqli_use_result", + "mysqli_warning_count", "mysqli_bind_param", "mysqli_bind_result", + "mysqli_client_encoding", "mysqli_escape_string", "mysqli_fetch", + "mysqli_param_count", "mysqli_get_metadata", "mysqli_send_long_data", + "mysqli_set_opt", "pdo_drivers", "socket_select", "socket_create", + "socket_create_listen", "socket_accept", "socket_set_nonblock", + "socket_set_block", "socket_listen", "socket_close", "socket_write", + "socket_read", "socket_getsockname", "socket_getpeername", "socket_connect", + "socket_strerror", "socket_bind", "socket_recv", "socket_send", + "socket_recvfrom", "socket_sendto", "socket_get_option", "socket_set_option", + "socket_shutdown", "socket_last_error", "socket_clear_error", "socket_getopt", + "socket_setopt", "eaccelerator_put", "eaccelerator_get", "eaccelerator_rm", + "eaccelerator_gc", "eaccelerator_lock", "eaccelerator_unlock", + "eaccelerator_caching", "eaccelerator_optimizer", "eaccelerator_clear", + "eaccelerator_clean", "eaccelerator_info", "eaccelerator_purge", + "eaccelerator_cached_scripts", "eaccelerator_removed_scripts", + "eaccelerator_list_keys", "eaccelerator_encode", "eaccelerator_load", + "_eaccelerator_loader_file", "_eaccelerator_loader_line", + "eaccelerator_set_session_handlers", "_eaccelerator_output_handler", + "eaccelerator_cache_page", "eaccelerator_rm_page", "eaccelerator_cache_output", + "eaccelerator_cache_result", "xdebug_get_stack_depth", + "xdebug_get_function_stack", "xdebug_print_function_stack", + "xdebug_get_declared_vars", "xdebug_call_class", "xdebug_call_function", + "xdebug_call_file", "xdebug_call_line", "xdebug_var_dump", "xdebug_debug_zval", + "xdebug_debug_zval_stdout", "xdebug_enable", "xdebug_disable", + "xdebug_is_enabled", "xdebug_break", "xdebug_start_trace", "xdebug_stop_trace", + "xdebug_get_tracefile_name", "xdebug_get_profiler_filename", + "xdebug_dump_aggr_profiling_data", "xdebug_clear_aggr_profiling_data", + "xdebug_memory_usage", "xdebug_peak_memory_usage", "xdebug_time_index", + "xdebug_start_error_collection", "xdebug_stop_error_collection", + "xdebug_get_collected_errors", "xdebug_start_code_coverage", + "xdebug_stop_code_coverage", "xdebug_get_code_coverage", + "xdebug_get_function_count", "xdebug_dump_superglobals", + "_", /* alias for gettext()*/ + "get_called_class","class_alias","gc_collect_cycles","gc_enabled","gc_enable", + "gc_disable","date_create_from_format","date_parse_from_format", + "date_get_last_errors","date_add","date_sub","date_diff","date_timestamp_set", + "date_timestamp_get","timezone_location_get","timezone_version_get", + "date_interval_create_from_date_string","date_interval_format", + "libxml_disable_entity_loader","openssl_pkey_free","openssl_pkey_new", + "openssl_pkey_export","openssl_pkey_export_to_file","openssl_pkey_get_private", + "openssl_pkey_get_public","openssl_pkey_get_details","openssl_free_key", + "openssl_get_privatekey","openssl_get_publickey","openssl_x509_read", + "openssl_x509_free","openssl_x509_parse","openssl_x509_checkpurpose", + "openssl_x509_check_private_key","openssl_x509_export","openssl_x509_export_to_file", + "openssl_pkcs12_export","openssl_pkcs12_export_to_file","openssl_pkcs12_read", + "openssl_csr_new","openssl_csr_export","openssl_csr_export_to_file", + "openssl_csr_sign","openssl_csr_get_subject","openssl_csr_get_public_key", + "openssl_digest","openssl_encrypt","openssl_decrypt","openssl_cipher_iv_length", + "openssl_sign","openssl_verify","openssl_seal","openssl_open","openssl_pkcs7_verify", + "openssl_pkcs7_decrypt","openssl_pkcs7_sign","openssl_pkcs7_encrypt", + "openssl_private_encrypt","openssl_private_decrypt","openssl_public_encrypt", + "openssl_public_decrypt","openssl_get_md_methods","openssl_get_cipher_methods", + "openssl_dh_compute_key","openssl_random_pseudo_bytes","openssl_error_string", + "preg_filter","bzopen","bzread","bzwrite","bzflush","bzclose","bzerrno", + "bzerrstr","bzerror","bzcompress","bzdecompress","curl_init","curl_copy_handle", + "curl_version","curl_setopt","curl_setopt_array","curl_exec","curl_getinfo", + "curl_error","curl_errno","curl_close","curl_multi_init","curl_multi_add_handle", + "curl_multi_remove_handle","curl_multi_select","curl_multi_exec","curl_multi_getcontent", + "curl_multi_info_read","curl_multi_close","exif_read_data","read_exif_data", + "exif_tagname","exif_thumbnail","exif_imagetype","ftp_ssl_connect", + "imagecolorclosesthwb","imagecreatefromxpm","textdomain","gettext","dgettext", + "dcgettext","bindtextdomain","ngettext","dngettext","dcngettext", + "bind_textdomain_codeset","hash_copy","imap_open","imap_reopen","imap_close", + "imap_num_msg","imap_num_recent","imap_headers","imap_headerinfo", + "imap_rfc822_parse_headers","imap_rfc822_write_address","imap_rfc822_parse_adrlist", + "imap_body","imap_bodystruct","imap_fetchbody","imap_savebody","imap_fetchheader", + "imap_fetchstructure","imap_gc","imap_expunge","imap_delete","imap_undelete", + "imap_check","imap_listscan","imap_mail_copy","imap_mail_move","imap_mail_compose", + "imap_createmailbox","imap_renamemailbox","imap_deletemailbox","imap_subscribe", + "imap_unsubscribe","imap_append","imap_ping","imap_base64","imap_qprint","imap_8bit", + "imap_binary","imap_utf8","imap_status","imap_mailboxmsginfo","imap_setflag_full", + "imap_clearflag_full","imap_sort","imap_uid","imap_msgno","imap_list","imap_lsub", + "imap_fetch_overview","imap_alerts","imap_errors","imap_last_error","imap_search", + "imap_utf7_decode","imap_utf7_encode","imap_mime_header_decode","imap_thread", + "imap_timeout","imap_get_quota","imap_get_quotaroot","imap_set_quota","imap_setacl", + "imap_getacl","imap_mail","imap_header","imap_listmailbox","imap_getmailboxes", + "imap_scanmailbox","imap_listsubscribed","imap_getsubscribed","imap_fetchtext", + "imap_scan","imap_create","imap_rename","json_last_error","mb_encoding_aliases", + "mcrypt_ecb","mcrypt_cbc","mcrypt_cfb","mcrypt_ofb","mcrypt_get_key_size", + "mcrypt_get_block_size","mcrypt_get_cipher_name","mcrypt_create_iv","mcrypt_list_algorithms", + "mcrypt_list_modes","mcrypt_get_iv_size","mcrypt_encrypt","mcrypt_decrypt", + "mcrypt_module_open","mcrypt_generic_init","mcrypt_generic","mdecrypt_generic", + "mcrypt_generic_end","mcrypt_generic_deinit","mcrypt_enc_self_test", + "mcrypt_enc_is_block_algorithm_mode","mcrypt_enc_is_block_algorithm", + "mcrypt_enc_is_block_mode","mcrypt_enc_get_block_size","mcrypt_enc_get_key_size", + "mcrypt_enc_get_supported_key_sizes","mcrypt_enc_get_iv_size", + "mcrypt_enc_get_algorithms_name","mcrypt_enc_get_modes_name","mcrypt_module_self_test", + "mcrypt_module_is_block_algorithm_mode","mcrypt_module_is_block_algorithm", + "mcrypt_module_is_block_mode","mcrypt_module_get_algo_block_size", + "mcrypt_module_get_algo_key_size","mcrypt_module_get_supported_key_sizes", + "mcrypt_module_close","mysqli_refresh","posix_kill","posix_getpid","posix_getppid", + "posix_getuid","posix_setuid","posix_geteuid","posix_seteuid","posix_getgid", + "posix_setgid","posix_getegid","posix_setegid","posix_getgroups","posix_getlogin", + "posix_getpgrp","posix_setsid","posix_setpgid","posix_getpgid","posix_getsid", + "posix_uname","posix_times","posix_ctermid","posix_ttyname","posix_isatty", + "posix_getcwd","posix_mkfifo","posix_mknod","posix_access","posix_getgrnam", + "posix_getgrgid","posix_getpwnam","posix_getpwuid","posix_getrlimit", + "posix_get_last_error","posix_errno","posix_strerror","posix_initgroups", + "pspell_new","pspell_new_personal","pspell_new_config","pspell_check", + "pspell_suggest","pspell_store_replacement","pspell_add_to_personal", + "pspell_add_to_session","pspell_clear_session","pspell_save_wordlist", + "pspell_config_create","pspell_config_runtogether","pspell_config_mode", + "pspell_config_ignore","pspell_config_personal","pspell_config_dict_dir", + "pspell_config_data_dir","pspell_config_repl","pspell_config_save_repl", + "snmpget","snmpgetnext","snmpwalk","snmprealwalk","snmpwalkoid", + "snmp_get_quick_print","snmp_set_quick_print","snmp_set_enum_print", + "snmp_set_oid_output_format","snmp_set_oid_numeric_print","snmpset", + "snmp2_get","snmp2_getnext","snmp2_walk","snmp2_real_walk","snmp2_set", + "snmp3_get","snmp3_getnext","snmp3_walk","snmp3_real_walk","snmp3_set", + "snmp_set_valueretrieval","snmp_get_valueretrieval","snmp_read_mib", + "use_soap_error_handler","is_soap_fault","socket_create_pair","time_nanosleep", + "time_sleep_until","strptime","php_ini_loaded_file","money_format","lcfirst", + "nl_langinfo","str_getcsv","readlink","linkinfo","symlink","link","proc_nice", + "atanh","asinh","acosh","expm1","log1p","inet_ntop","inet_pton","getopt", + "sys_getloadavg","getrusage","quoted_printable_encode","forward_static_call", + "forward_static_call_array","header_remove","parse_ini_string","gethostname", + "dns_check_record","checkdnsrr","dns_get_mx","getmxrr","dns_get_record", + "stream_context_get_params","stream_context_set_default","stream_socket_pair", + "stream_supports_lock","stream_set_read_buffer","stream_resolve_include_path", + "stream_is_local","fnmatch","chroot","lchown","lchgrp","realpath_cache_size", + "realpath_cache_get","array_replace","array_replace_recursive","ftok","xmlrpc_encode", + "xmlrpc_decode","xmlrpc_decode_request","xmlrpc_encode_request","xmlrpc_get_type", + "xmlrpc_set_type","xmlrpc_is_fault","xmlrpc_server_create","xmlrpc_server_destroy", + "xmlrpc_server_register_method","xmlrpc_server_call_method", + "xmlrpc_parse_method_descriptions","xmlrpc_server_add_introspection_data", + "xmlrpc_server_register_introspection_callback","zip_open","zip_close", + "zip_read","zip_entry_open","zip_entry_close","zip_entry_read","zip_entry_filesize", + "zip_entry_name","zip_entry_compressedsize","zip_entry_compressionmethod", + "svn_checkout","svn_cat","svn_ls","svn_log","svn_auth_set_parameter", + "svn_auth_get_parameter","svn_client_version","svn_config_ensure","svn_diff", + "svn_cleanup","svn_revert","svn_resolved","svn_commit","svn_lock","svn_unlock", + "svn_add","svn_status","svn_update","svn_import","svn_info","svn_export", + "svn_copy","svn_switch","svn_blame","svn_delete","svn_mkdir","svn_move", + "svn_proplist","svn_propget","svn_repos_create","svn_repos_recover", + "svn_repos_hotcopy","svn_repos_open","svn_repos_fs", + "svn_repos_fs_begin_txn_for_commit","svn_repos_fs_commit_txn", + "svn_fs_revision_root","svn_fs_check_path","svn_fs_revision_prop", + "svn_fs_dir_entries","svn_fs_node_created_rev","svn_fs_youngest_rev", + "svn_fs_file_contents","svn_fs_file_length","svn_fs_txn_root","svn_fs_make_file", + "svn_fs_make_dir","svn_fs_apply_text","svn_fs_copy","svn_fs_delete", + "svn_fs_begin_txn2","svn_fs_is_dir","svn_fs_is_file","svn_fs_node_prop", + "svn_fs_change_node_prop","svn_fs_contents_changed","svn_fs_props_changed", + "svn_fs_abort_txn","sqlite_open","sqlite_popen","sqlite_close","sqlite_query", + "sqlite_exec","sqlite_array_query","sqlite_single_query","sqlite_fetch_array", + "sqlite_fetch_object","sqlite_fetch_single","sqlite_fetch_string", + "sqlite_fetch_all","sqlite_current","sqlite_column","sqlite_libversion", + "sqlite_libencoding","sqlite_changes","sqlite_last_insert_rowid", + "sqlite_num_rows","sqlite_num_fields","sqlite_field_name","sqlite_seek", + "sqlite_rewind","sqlite_next","sqlite_prev","sqlite_valid","sqlite_has_more", + "sqlite_has_prev","sqlite_escape_string","sqlite_busy_timeout","sqlite_last_error", + "sqlite_error_string","sqlite_unbuffered_query","sqlite_create_aggregate", + "sqlite_create_function","sqlite_factory","sqlite_udf_encode_binary", + "sqlite_udf_decode_binary","sqlite_fetch_column_types" + ].forEach(function(element, index, array) { + result[element] = token("t_string", "php-predefined-function"); + }); + + // output of get_defined_constants(). Differs significantly from http://php.net/manual/en/reserved.constants.php + [ "E_ERROR", "E_RECOVERABLE_ERROR", "E_WARNING", "E_PARSE", "E_NOTICE", + "E_STRICT", "E_CORE_ERROR", "E_CORE_WARNING", "E_COMPILE_ERROR", + "E_COMPILE_WARNING", "E_USER_ERROR", "E_USER_WARNING", "E_USER_NOTICE", + "E_ALL", "TRUE", "FALSE", "NULL", "ZEND_THREAD_SAFE", "PHP_VERSION", "PHP_OS", + "PHP_SAPI", "DEFAULT_INCLUDE_PATH", "PEAR_INSTALL_DIR", "PEAR_EXTENSION_DIR", + "PHP_EXTENSION_DIR", "PHP_PREFIX", "PHP_BINDIR", "PHP_LIBDIR", "PHP_DATADIR", + "PHP_SYSCONFDIR", "PHP_LOCALSTATEDIR", "PHP_CONFIG_FILE_PATH", + "PHP_CONFIG_FILE_SCAN_DIR", "PHP_SHLIB_SUFFIX", "PHP_EOL", "PHP_EOL", + "PHP_INT_MAX", "PHP_INT_SIZE", "PHP_OUTPUT_HANDLER_START", + "PHP_OUTPUT_HANDLER_CONT", "PHP_OUTPUT_HANDLER_END", "UPLOAD_ERR_OK", + "UPLOAD_ERR_INI_SIZE", "UPLOAD_ERR_FORM_SIZE", "UPLOAD_ERR_PARTIAL", + "UPLOAD_ERR_NO_FILE", "UPLOAD_ERR_NO_TMP_DIR", "UPLOAD_ERR_CANT_WRITE", + "UPLOAD_ERR_EXTENSION", "CAL_GREGORIAN", "CAL_JULIAN", "CAL_JEWISH", + "CAL_FRENCH", "CAL_NUM_CALS", "CAL_DOW_DAYNO", "CAL_DOW_SHORT", "CAL_DOW_LONG", + "CAL_MONTH_GREGORIAN_SHORT", "CAL_MONTH_GREGORIAN_LONG", + "CAL_MONTH_JULIAN_SHORT", "CAL_MONTH_JULIAN_LONG", "CAL_MONTH_JEWISH", + "CAL_MONTH_FRENCH", "CAL_EASTER_DEFAULT", "CAL_EASTER_ROMAN", + "CAL_EASTER_ALWAYS_GREGORIAN", "CAL_EASTER_ALWAYS_JULIAN", + "CAL_JEWISH_ADD_ALAFIM_GERESH", "CAL_JEWISH_ADD_ALAFIM", + "CAL_JEWISH_ADD_GERESHAYIM", "CLSCTX_INPROC_SERVER", "CLSCTX_INPROC_HANDLER", + "CLSCTX_LOCAL_SERVER", "CLSCTX_REMOTE_SERVER", "CLSCTX_SERVER", "CLSCTX_ALL", + "VT_NULL", "VT_EMPTY", "VT_UI1", "VT_I1", "VT_UI2", "VT_I2", "VT_UI4", "VT_I4", + "VT_R4", "VT_R8", "VT_BOOL", "VT_ERROR", "VT_CY", "VT_DATE", "VT_BSTR", + "VT_DECIMAL", "VT_UNKNOWN", "VT_DISPATCH", "VT_VARIANT", "VT_INT", "VT_UINT", + "VT_ARRAY", "VT_BYREF", "CP_ACP", "CP_MACCP", "CP_OEMCP", "CP_UTF7", "CP_UTF8", + "CP_SYMBOL", "CP_THREAD_ACP", "VARCMP_LT", "VARCMP_EQ", "VARCMP_GT", + "VARCMP_NULL", "NORM_IGNORECASE", "NORM_IGNORENONSPACE", "NORM_IGNORESYMBOLS", + "NORM_IGNOREWIDTH", "NORM_IGNOREKANATYPE", "DISP_E_DIVBYZERO", + "DISP_E_OVERFLOW", "DISP_E_BADINDEX", "MK_E_UNAVAILABLE", "INPUT_POST", + "INPUT_GET", "INPUT_COOKIE", "INPUT_ENV", "INPUT_SERVER", "INPUT_SESSION", + "INPUT_REQUEST", "FILTER_FLAG_NONE", "FILTER_REQUIRE_SCALAR", + "FILTER_REQUIRE_ARRAY", "FILTER_FORCE_ARRAY", "FILTER_NULL_ON_FAILURE", + "FILTER_VALIDATE_INT", "FILTER_VALIDATE_BOOLEAN", "FILTER_VALIDATE_FLOAT", + "FILTER_VALIDATE_REGEXP", "FILTER_VALIDATE_URL", "FILTER_VALIDATE_EMAIL", + "FILTER_VALIDATE_IP", "FILTER_DEFAULT", "FILTER_UNSAFE_RAW", + "FILTER_SANITIZE_STRING", "FILTER_SANITIZE_STRIPPED", + "FILTER_SANITIZE_ENCODED", "FILTER_SANITIZE_SPECIAL_CHARS", + "FILTER_SANITIZE_EMAIL", "FILTER_SANITIZE_URL", "FILTER_SANITIZE_NUMBER_INT", + "FILTER_SANITIZE_NUMBER_FLOAT", "FILTER_SANITIZE_MAGIC_QUOTES", + "FILTER_CALLBACK", "FILTER_FLAG_ALLOW_OCTAL", "FILTER_FLAG_ALLOW_HEX", + "FILTER_FLAG_STRIP_LOW", "FILTER_FLAG_STRIP_HIGH", "FILTER_FLAG_ENCODE_LOW", + "FILTER_FLAG_ENCODE_HIGH", "FILTER_FLAG_ENCODE_AMP", + "FILTER_FLAG_NO_ENCODE_QUOTES", "FILTER_FLAG_EMPTY_STRING_NULL", + "FILTER_FLAG_ALLOW_FRACTION", "FILTER_FLAG_ALLOW_THOUSAND", + "FILTER_FLAG_ALLOW_SCIENTIFIC", "FILTER_FLAG_SCHEME_REQUIRED", + "FILTER_FLAG_HOST_REQUIRED", "FILTER_FLAG_PATH_REQUIRED", + "FILTER_FLAG_QUERY_REQUIRED", "FILTER_FLAG_IPV4", "FILTER_FLAG_IPV6", + "FILTER_FLAG_NO_RES_RANGE", "FILTER_FLAG_NO_PRIV_RANGE", "FTP_ASCII", + "FTP_TEXT", "FTP_BINARY", "FTP_IMAGE", "FTP_AUTORESUME", "FTP_TIMEOUT_SEC", + "FTP_AUTOSEEK", "FTP_FAILED", "FTP_FINISHED", "FTP_MOREDATA", "HASH_HMAC", + "ICONV_IMPL", "ICONV_VERSION", "ICONV_MIME_DECODE_STRICT", + "ICONV_MIME_DECODE_CONTINUE_ON_ERROR", "ODBC_TYPE", "ODBC_BINMODE_PASSTHRU", + "ODBC_BINMODE_RETURN", "ODBC_BINMODE_CONVERT", "SQL_ODBC_CURSORS", + "SQL_CUR_USE_DRIVER", "SQL_CUR_USE_IF_NEEDED", "SQL_CUR_USE_ODBC", + "SQL_CONCURRENCY", "SQL_CONCUR_READ_ONLY", "SQL_CONCUR_LOCK", + "SQL_CONCUR_ROWVER", "SQL_CONCUR_VALUES", "SQL_CURSOR_TYPE", + "SQL_CURSOR_FORWARD_ONLY", "SQL_CURSOR_KEYSET_DRIVEN", "SQL_CURSOR_DYNAMIC", + "SQL_CURSOR_STATIC", "SQL_KEYSET_SIZE", "SQL_FETCH_FIRST", "SQL_FETCH_NEXT", + "SQL_CHAR", "SQL_VARCHAR", "SQL_LONGVARCHAR", "SQL_DECIMAL", "SQL_NUMERIC", + "SQL_BIT", "SQL_TINYINT", "SQL_SMALLINT", "SQL_INTEGER", "SQL_BIGINT", + "SQL_REAL", "SQL_FLOAT", "SQL_DOUBLE", "SQL_BINARY", "SQL_VARBINARY", + "SQL_LONGVARBINARY", "SQL_DATE", "SQL_TIME", "SQL_TIMESTAMP", + "PREG_PATTERN_ORDER", "PREG_SET_ORDER", "PREG_OFFSET_CAPTURE", + "PREG_SPLIT_NO_EMPTY", "PREG_SPLIT_DELIM_CAPTURE", "PREG_SPLIT_OFFSET_CAPTURE", + "PREG_GREP_INVERT", "PREG_NO_ERROR", "PREG_INTERNAL_ERROR", + "PREG_BACKTRACK_LIMIT_ERROR", "PREG_RECURSION_LIMIT_ERROR", + "PREG_BAD_UTF8_ERROR", "DATE_ATOM", "DATE_COOKIE", "DATE_ISO8601", + "DATE_RFC822", "DATE_RFC850", "DATE_RFC1036", "DATE_RFC1123", "DATE_RFC2822", + "DATE_RFC3339", "DATE_RSS", "DATE_W3C", "SUNFUNCS_RET_TIMESTAMP", + "SUNFUNCS_RET_STRING", "SUNFUNCS_RET_DOUBLE", "LIBXML_VERSION", + "LIBXML_DOTTED_VERSION", "LIBXML_NOENT", "LIBXML_DTDLOAD", "LIBXML_DTDATTR", + "LIBXML_DTDVALID", "LIBXML_NOERROR", "LIBXML_NOWARNING", "LIBXML_NOBLANKS", + "LIBXML_XINCLUDE", "LIBXML_NSCLEAN", "LIBXML_NOCDATA", "LIBXML_NONET", + "LIBXML_COMPACT", "LIBXML_NOXMLDECL", "LIBXML_NOEMPTYTAG", "LIBXML_ERR_NONE", + "LIBXML_ERR_WARNING", "LIBXML_ERR_ERROR", "LIBXML_ERR_FATAL", + "CONNECTION_ABORTED", "CONNECTION_NORMAL", "CONNECTION_TIMEOUT", "INI_USER", + "INI_PERDIR", "INI_SYSTEM", "INI_ALL", "PHP_URL_SCHEME", "PHP_URL_HOST", + "PHP_URL_PORT", "PHP_URL_USER", "PHP_URL_PASS", "PHP_URL_PATH", + "PHP_URL_QUERY", "PHP_URL_FRAGMENT", "M_E", "M_LOG2E", "M_LOG10E", "M_LN2", + "M_LN10", "M_PI", "M_PI_2", "M_PI_4", "M_1_PI", "M_2_PI", "M_SQRTPI", + "M_2_SQRTPI", "M_LNPI", "M_EULER", "M_SQRT2", "M_SQRT1_2", "M_SQRT3", "INF", + "NAN", "INFO_GENERAL", "INFO_CREDITS", "INFO_CONFIGURATION", "INFO_MODULES", + "INFO_ENVIRONMENT", "INFO_VARIABLES", "INFO_LICENSE", "INFO_ALL", + "CREDITS_GROUP", "CREDITS_GENERAL", "CREDITS_SAPI", "CREDITS_MODULES", + "CREDITS_DOCS", "CREDITS_FULLPAGE", "CREDITS_QA", "CREDITS_ALL", + "HTML_SPECIALCHARS", "HTML_ENTITIES", "ENT_COMPAT", "ENT_QUOTES", + "ENT_NOQUOTES", "STR_PAD_LEFT", "STR_PAD_RIGHT", "STR_PAD_BOTH", + "PATHINFO_DIRNAME", "PATHINFO_BASENAME", "PATHINFO_EXTENSION", + "PATHINFO_FILENAME", "CHAR_MAX", "LC_CTYPE", "LC_NUMERIC", "LC_TIME", + "LC_COLLATE", "LC_MONETARY", "LC_ALL", "SEEK_SET", "SEEK_CUR", "SEEK_END", + "LOCK_SH", "LOCK_EX", "LOCK_UN", "LOCK_NB", "STREAM_NOTIFY_CONNECT", + "STREAM_NOTIFY_AUTH_REQUIRED", "STREAM_NOTIFY_AUTH_RESULT", + "STREAM_NOTIFY_MIME_TYPE_IS", "STREAM_NOTIFY_FILE_SIZE_IS", + "STREAM_NOTIFY_REDIRECTED", "STREAM_NOTIFY_PROGRESS", "STREAM_NOTIFY_FAILURE", + "STREAM_NOTIFY_COMPLETED", "STREAM_NOTIFY_RESOLVE", + "STREAM_NOTIFY_SEVERITY_INFO", "STREAM_NOTIFY_SEVERITY_WARN", + "STREAM_NOTIFY_SEVERITY_ERR", "STREAM_FILTER_READ", "STREAM_FILTER_WRITE", + "STREAM_FILTER_ALL", "STREAM_CLIENT_PERSISTENT", "STREAM_CLIENT_ASYNC_CONNECT", + "STREAM_CLIENT_CONNECT", "STREAM_CRYPTO_METHOD_SSLv2_CLIENT", + "STREAM_CRYPTO_METHOD_SSLv3_CLIENT", "STREAM_CRYPTO_METHOD_SSLv23_CLIENT", + "STREAM_CRYPTO_METHOD_TLS_CLIENT", "STREAM_CRYPTO_METHOD_SSLv2_SERVER", + "STREAM_CRYPTO_METHOD_SSLv3_SERVER", "STREAM_CRYPTO_METHOD_SSLv23_SERVER", + "STREAM_CRYPTO_METHOD_TLS_SERVER", "STREAM_SHUT_RD", "STREAM_SHUT_WR", + "STREAM_SHUT_RDWR", "STREAM_PF_INET", "STREAM_PF_INET6", "STREAM_PF_UNIX", + "STREAM_IPPROTO_IP", "STREAM_IPPROTO_TCP", "STREAM_IPPROTO_UDP", + "STREAM_IPPROTO_ICMP", "STREAM_IPPROTO_RAW", "STREAM_SOCK_STREAM", + "STREAM_SOCK_DGRAM", "STREAM_SOCK_RAW", "STREAM_SOCK_SEQPACKET", + "STREAM_SOCK_RDM", "STREAM_PEEK", "STREAM_OOB", "STREAM_SERVER_BIND", + "STREAM_SERVER_LISTEN", "FILE_USE_INCLUDE_PATH", "FILE_IGNORE_NEW_LINES", + "FILE_SKIP_EMPTY_LINES", "FILE_APPEND", "FILE_NO_DEFAULT_CONTEXT", + "PSFS_PASS_ON", "PSFS_FEED_ME", "PSFS_ERR_FATAL", "PSFS_FLAG_NORMAL", + "PSFS_FLAG_FLUSH_INC", "PSFS_FLAG_FLUSH_CLOSE", "CRYPT_SALT_LENGTH", + "CRYPT_STD_DES", "CRYPT_EXT_DES", "CRYPT_MD5", "CRYPT_BLOWFISH", + "DIRECTORY_SEPARATOR", "PATH_SEPARATOR", "GLOB_BRACE", "GLOB_MARK", + "GLOB_NOSORT", "GLOB_NOCHECK", "GLOB_NOESCAPE", "GLOB_ERR", "GLOB_ONLYDIR", + "LOG_EMERG", "LOG_ALERT", "LOG_CRIT", "LOG_ERR", "LOG_WARNING", "LOG_NOTICE", + "LOG_INFO", "LOG_DEBUG", "LOG_KERN", "LOG_USER", "LOG_MAIL", "LOG_DAEMON", + "LOG_AUTH", "LOG_SYSLOG", "LOG_LPR", "LOG_NEWS", "LOG_UUCP", "LOG_CRON", + "LOG_AUTHPRIV", "LOG_PID", "LOG_CONS", "LOG_ODELAY", "LOG_NDELAY", + "LOG_NOWAIT", "LOG_PERROR", "EXTR_OVERWRITE", "EXTR_SKIP", "EXTR_PREFIX_SAME", + "EXTR_PREFIX_ALL", "EXTR_PREFIX_INVALID", "EXTR_PREFIX_IF_EXISTS", + "EXTR_IF_EXISTS", "EXTR_REFS", "SORT_ASC", "SORT_DESC", "SORT_REGULAR", + "SORT_NUMERIC", "SORT_STRING", "SORT_LOCALE_STRING", "CASE_LOWER", + "CASE_UPPER", "COUNT_NORMAL", "COUNT_RECURSIVE", "ASSERT_ACTIVE", + "ASSERT_CALLBACK", "ASSERT_BAIL", "ASSERT_WARNING", "ASSERT_QUIET_EVAL", + "STREAM_USE_PATH", "STREAM_IGNORE_URL", "STREAM_ENFORCE_SAFE_MODE", + "STREAM_REPORT_ERRORS", "STREAM_MUST_SEEK", "STREAM_URL_STAT_LINK", + "STREAM_URL_STAT_QUIET", "STREAM_MKDIR_RECURSIVE", "IMAGETYPE_GIF", + "IMAGETYPE_JPEG", "IMAGETYPE_PNG", "IMAGETYPE_SWF", "IMAGETYPE_PSD", + "IMAGETYPE_BMP", "IMAGETYPE_TIFF_II", "IMAGETYPE_TIFF_MM", "IMAGETYPE_JPC", + "IMAGETYPE_JP2", "IMAGETYPE_JPX", "IMAGETYPE_JB2", "IMAGETYPE_SWC", + "IMAGETYPE_IFF", "IMAGETYPE_WBMP", "IMAGETYPE_JPEG2000", "IMAGETYPE_XBM", + "T_INCLUDE", "T_INCLUDE_ONCE", "T_EVAL", "T_REQUIRE", "T_REQUIRE_ONCE", + "T_LOGICAL_OR", "T_LOGICAL_XOR", "T_LOGICAL_AND", "T_PRINT", "T_PLUS_EQUAL", + "T_MINUS_EQUAL", "T_MUL_EQUAL", "T_DIV_EQUAL", "T_CONCAT_EQUAL", "T_MOD_EQUAL", + "T_AND_EQUAL", "T_OR_EQUAL", "T_XOR_EQUAL", "T_SL_EQUAL", "T_SR_EQUAL", + "T_BOOLEAN_OR", "T_BOOLEAN_AND", "T_IS_EQUAL", "T_IS_NOT_EQUAL", + "T_IS_IDENTICAL", "T_IS_NOT_IDENTICAL", "T_IS_SMALLER_OR_EQUAL", + "T_IS_GREATER_OR_EQUAL", "T_SL", "T_SR", "T_INC", "T_DEC", "T_INT_CAST", + "T_DOUBLE_CAST", "T_STRING_CAST", "T_ARRAY_CAST", "T_OBJECT_CAST", + "T_BOOL_CAST", "T_UNSET_CAST", "T_NEW", "T_EXIT", "T_IF", "T_ELSEIF", "T_ELSE", + "T_ENDIF", "T_LNUMBER", "T_DNUMBER", "T_STRING", "T_STRING_VARNAME", + "T_VARIABLE", "T_NUM_STRING", "T_INLINE_HTML", "T_CHARACTER", + "T_BAD_CHARACTER", "T_ENCAPSED_AND_WHITESPACE", "T_CONSTANT_ENCAPSED_STRING", + "T_ECHO", "T_DO", "T_WHILE", "T_ENDWHILE", "T_FOR", "T_ENDFOR", "T_FOREACH", + "T_ENDFOREACH", "T_DECLARE", "T_ENDDECLARE", "T_AS", "T_SWITCH", "T_ENDSWITCH", + "T_CASE", "T_DEFAULT", "T_BREAK", "T_CONTINUE", "T_FUNCTION", "T_CONST", + "T_RETURN", "T_USE", "T_GLOBAL", "T_STATIC", "T_VAR", "T_UNSET", "T_ISSET", + "T_EMPTY", "T_CLASS", "T_EXTENDS", "T_INTERFACE", "T_IMPLEMENTS", + "T_OBJECT_OPERATOR", "T_DOUBLE_ARROW", "T_LIST", "T_ARRAY", "T_CLASS_C", + "T_FUNC_C", "T_METHOD_C", "T_LINE", "T_FILE", "T_COMMENT", "T_DOC_COMMENT", + "T_OPEN_TAG", "T_OPEN_TAG_WITH_ECHO", "T_CLOSE_TAG", "T_WHITESPACE", + "T_START_HEREDOC", "T_END_HEREDOC", "T_DOLLAR_OPEN_CURLY_BRACES", + "T_CURLY_OPEN", "T_PAAMAYIM_NEKUDOTAYIM", "T_DOUBLE_COLON", "T_ABSTRACT", + "T_CATCH", "T_FINAL", "T_INSTANCEOF", "T_PRIVATE", "T_PROTECTED", "T_PUBLIC", + "T_THROW", "T_TRY", "T_CLONE", "T_HALT_COMPILER", "FORCE_GZIP", + "FORCE_DEFLATE", "XML_ELEMENT_NODE", "XML_ATTRIBUTE_NODE", "XML_TEXT_NODE", + "XML_CDATA_SECTION_NODE", "XML_ENTITY_REF_NODE", "XML_ENTITY_NODE", + "XML_PI_NODE", "XML_COMMENT_NODE", "XML_DOCUMENT_NODE", + "XML_DOCUMENT_TYPE_NODE", "XML_DOCUMENT_FRAG_NODE", "XML_NOTATION_NODE", + "XML_HTML_DOCUMENT_NODE", "XML_DTD_NODE", "XML_ELEMENT_DECL_NODE", + "XML_ATTRIBUTE_DECL_NODE", "XML_ENTITY_DECL_NODE", "XML_NAMESPACE_DECL_NODE", + "XML_LOCAL_NAMESPACE", "XML_ATTRIBUTE_CDATA", "XML_ATTRIBUTE_ID", + "XML_ATTRIBUTE_IDREF", "XML_ATTRIBUTE_IDREFS", "XML_ATTRIBUTE_ENTITY", + "XML_ATTRIBUTE_NMTOKEN", "XML_ATTRIBUTE_NMTOKENS", "XML_ATTRIBUTE_ENUMERATION", + "XML_ATTRIBUTE_NOTATION", "DOM_PHP_ERR", "DOM_INDEX_SIZE_ERR", + "DOMSTRING_SIZE_ERR", "DOM_HIERARCHY_REQUEST_ERR", "DOM_WRONG_DOCUMENT_ERR", + "DOM_INVALID_CHARACTER_ERR", "DOM_NO_DATA_ALLOWED_ERR", + "DOM_NO_MODIFICATION_ALLOWED_ERR", "DOM_NOT_FOUND_ERR", + "DOM_NOT_SUPPORTED_ERR", "DOM_INUSE_ATTRIBUTE_ERR", "DOM_INVALID_STATE_ERR", + "DOM_SYNTAX_ERR", "DOM_INVALID_MODIFICATION_ERR", "DOM_NAMESPACE_ERR", + "DOM_INVALID_ACCESS_ERR", "DOM_VALIDATION_ERR", "XML_ERROR_NONE", + "XML_ERROR_NO_MEMORY", "XML_ERROR_SYNTAX", "XML_ERROR_NO_ELEMENTS", + "XML_ERROR_INVALID_TOKEN", "XML_ERROR_UNCLOSED_TOKEN", + "XML_ERROR_PARTIAL_CHAR", "XML_ERROR_TAG_MISMATCH", + "XML_ERROR_DUPLICATE_ATTRIBUTE", "XML_ERROR_JUNK_AFTER_DOC_ELEMENT", + "XML_ERROR_PARAM_ENTITY_REF", "XML_ERROR_UNDEFINED_ENTITY", + "XML_ERROR_RECURSIVE_ENTITY_REF", "XML_ERROR_ASYNC_ENTITY", + "XML_ERROR_BAD_CHAR_REF", "XML_ERROR_BINARY_ENTITY_REF", + "XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF", "XML_ERROR_MISPLACED_XML_PI", + "XML_ERROR_UNKNOWN_ENCODING", "XML_ERROR_INCORRECT_ENCODING", + "XML_ERROR_UNCLOSED_CDATA_SECTION", "XML_ERROR_EXTERNAL_ENTITY_HANDLING", + "XML_OPTION_CASE_FOLDING", "XML_OPTION_TARGET_ENCODING", + "XML_OPTION_SKIP_TAGSTART", "XML_OPTION_SKIP_WHITE", "XML_SAX_IMPL", "IMG_GIF", + "IMG_JPG", "IMG_JPEG", "IMG_PNG", "IMG_WBMP", "IMG_XPM", "IMG_COLOR_TILED", + "IMG_COLOR_STYLED", "IMG_COLOR_BRUSHED", "IMG_COLOR_STYLEDBRUSHED", + "IMG_COLOR_TRANSPARENT", "IMG_ARC_ROUNDED", "IMG_ARC_PIE", "IMG_ARC_CHORD", + "IMG_ARC_NOFILL", "IMG_ARC_EDGED", "IMG_GD2_RAW", "IMG_GD2_COMPRESSED", + "IMG_EFFECT_REPLACE", "IMG_EFFECT_ALPHABLEND", "IMG_EFFECT_NORMAL", + "IMG_EFFECT_OVERLAY", "GD_BUNDLED", "IMG_FILTER_NEGATE", + "IMG_FILTER_GRAYSCALE", "IMG_FILTER_BRIGHTNESS", "IMG_FILTER_CONTRAST", + "IMG_FILTER_COLORIZE", "IMG_FILTER_EDGEDETECT", "IMG_FILTER_GAUSSIAN_BLUR", + "IMG_FILTER_SELECTIVE_BLUR", "IMG_FILTER_EMBOSS", "IMG_FILTER_MEAN_REMOVAL", + "IMG_FILTER_SMOOTH", "PNG_NO_FILTER", "PNG_FILTER_NONE", "PNG_FILTER_SUB", + "PNG_FILTER_UP", "PNG_FILTER_AVG", "PNG_FILTER_PAETH", "PNG_ALL_FILTERS", + "MB_OVERLOAD_MAIL", "MB_OVERLOAD_STRING", "MB_OVERLOAD_REGEX", "MB_CASE_UPPER", + "MB_CASE_LOWER", "MB_CASE_TITLE", "MYSQL_ASSOC", "MYSQL_NUM", "MYSQL_BOTH", + "MYSQL_CLIENT_COMPRESS", "MYSQL_CLIENT_SSL", "MYSQL_CLIENT_INTERACTIVE", + "MYSQL_CLIENT_IGNORE_SPACE", "MYSQLI_READ_DEFAULT_GROUP", + "MYSQLI_READ_DEFAULT_FILE", "MYSQLI_OPT_CONNECT_TIMEOUT", + "MYSQLI_OPT_LOCAL_INFILE", "MYSQLI_INIT_COMMAND", "MYSQLI_CLIENT_SSL", + "MYSQLI_CLIENT_COMPRESS", "MYSQLI_CLIENT_INTERACTIVE", + "MYSQLI_CLIENT_IGNORE_SPACE", "MYSQLI_CLIENT_NO_SCHEMA", + "MYSQLI_CLIENT_FOUND_ROWS", "MYSQLI_STORE_RESULT", "MYSQLI_USE_RESULT", + "MYSQLI_ASSOC", "MYSQLI_NUM", "MYSQLI_BOTH", + "MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH", "MYSQLI_STMT_ATTR_CURSOR_TYPE", + "MYSQLI_CURSOR_TYPE_NO_CURSOR", "MYSQLI_CURSOR_TYPE_READ_ONLY", + "MYSQLI_CURSOR_TYPE_FOR_UPDATE", "MYSQLI_CURSOR_TYPE_SCROLLABLE", + "MYSQLI_STMT_ATTR_PREFETCH_ROWS", "MYSQLI_NOT_NULL_FLAG", + "MYSQLI_PRI_KEY_FLAG", "MYSQLI_UNIQUE_KEY_FLAG", "MYSQLI_MULTIPLE_KEY_FLAG", + "MYSQLI_BLOB_FLAG", "MYSQLI_UNSIGNED_FLAG", "MYSQLI_ZEROFILL_FLAG", + "MYSQLI_AUTO_INCREMENT_FLAG", "MYSQLI_TIMESTAMP_FLAG", "MYSQLI_SET_FLAG", + "MYSQLI_NUM_FLAG", "MYSQLI_PART_KEY_FLAG", "MYSQLI_GROUP_FLAG", + "MYSQLI_TYPE_DECIMAL", "MYSQLI_TYPE_TINY", "MYSQLI_TYPE_SHORT", + "MYSQLI_TYPE_LONG", "MYSQLI_TYPE_FLOAT", "MYSQLI_TYPE_DOUBLE", + "MYSQLI_TYPE_NULL", "MYSQLI_TYPE_TIMESTAMP", "MYSQLI_TYPE_LONGLONG", + "MYSQLI_TYPE_INT24", "MYSQLI_TYPE_DATE", "MYSQLI_TYPE_TIME", + "MYSQLI_TYPE_DATETIME", "MYSQLI_TYPE_YEAR", "MYSQLI_TYPE_NEWDATE", + "MYSQLI_TYPE_ENUM", "MYSQLI_TYPE_SET", "MYSQLI_TYPE_TINY_BLOB", + "MYSQLI_TYPE_MEDIUM_BLOB", "MYSQLI_TYPE_LONG_BLOB", "MYSQLI_TYPE_BLOB", + "MYSQLI_TYPE_VAR_STRING", "MYSQLI_TYPE_STRING", "MYSQLI_TYPE_CHAR", + "MYSQLI_TYPE_INTERVAL", "MYSQLI_TYPE_GEOMETRY", "MYSQLI_TYPE_NEWDECIMAL", + "MYSQLI_TYPE_BIT", "MYSQLI_RPL_MASTER", "MYSQLI_RPL_SLAVE", "MYSQLI_RPL_ADMIN", + "MYSQLI_NO_DATA", "MYSQLI_DATA_TRUNCATED", "MYSQLI_REPORT_INDEX", + "MYSQLI_REPORT_ERROR", "MYSQLI_REPORT_STRICT", "MYSQLI_REPORT_ALL", + "MYSQLI_REPORT_OFF", "AF_UNIX", "AF_INET", "AF_INET6", "SOCK_STREAM", + "SOCK_DGRAM", "SOCK_RAW", "SOCK_SEQPACKET", "SOCK_RDM", "MSG_OOB", + "MSG_WAITALL", "MSG_PEEK", "MSG_DONTROUTE", "SO_DEBUG", "SO_REUSEADDR", + "SO_KEEPALIVE", "SO_DONTROUTE", "SO_LINGER", "SO_BROADCAST", "SO_OOBINLINE", + "SO_SNDBUF", "SO_RCVBUF", "SO_SNDLOWAT", "SO_RCVLOWAT", "SO_SNDTIMEO", + "SO_RCVTIMEO", "SO_TYPE", "SO_ERROR", "SOL_SOCKET", "SOMAXCONN", + "PHP_NORMAL_READ", "PHP_BINARY_READ", "SOCKET_EINTR", "SOCKET_EBADF", + "SOCKET_EACCES", "SOCKET_EFAULT", "SOCKET_EINVAL", "SOCKET_EMFILE", + "SOCKET_EWOULDBLOCK", "SOCKET_EINPROGRESS", "SOCKET_EALREADY", + "SOCKET_ENOTSOCK", "SOCKET_EDESTADDRREQ", "SOCKET_EMSGSIZE", + "SOCKET_EPROTOTYPE", "SOCKET_ENOPROTOOPT", "SOCKET_EPROTONOSUPPORT", + "SOCKET_ESOCKTNOSUPPORT", "SOCKET_EOPNOTSUPP", "SOCKET_EPFNOSUPPORT", + "SOCKET_EAFNOSUPPORT", "SOCKET_EADDRINUSE", "SOCKET_EADDRNOTAVAIL", + "SOCKET_ENETDOWN", "SOCKET_ENETUNREACH", "SOCKET_ENETRESET", + "SOCKET_ECONNABORTED", "SOCKET_ECONNRESET", "SOCKET_ENOBUFS", "SOCKET_EISCONN", + "SOCKET_ENOTCONN", "SOCKET_ESHUTDOWN", "SOCKET_ETOOMANYREFS", + "SOCKET_ETIMEDOUT", "SOCKET_ECONNREFUSED", "SOCKET_ELOOP", + "SOCKET_ENAMETOOLONG", "SOCKET_EHOSTDOWN", "SOCKET_EHOSTUNREACH", + "SOCKET_ENOTEMPTY", "SOCKET_EPROCLIM", "SOCKET_EUSERS", "SOCKET_EDQUOT", + "SOCKET_ESTALE", "SOCKET_EREMOTE", "SOCKET_EDISCON", "SOCKET_SYSNOTREADY", + "SOCKET_VERNOTSUPPORTED", "SOCKET_NOTINITIALISED", "SOCKET_HOST_NOT_FOUND", + "SOCKET_TRY_AGAIN", "SOCKET_NO_RECOVERY", "SOCKET_NO_DATA", + "SOCKET_NO_ADDRESS", "SOL_TCP", "SOL_UDP", "EACCELERATOR_VERSION", + "EACCELERATOR_SHM_AND_DISK", "EACCELERATOR_SHM", "EACCELERATOR_SHM_ONLY", + "EACCELERATOR_DISK_ONLY", "EACCELERATOR_NONE", "XDEBUG_TRACE_APPEND", + "XDEBUG_TRACE_COMPUTERIZED", "XDEBUG_TRACE_HTML", "XDEBUG_CC_UNUSED", + "XDEBUG_CC_DEAD_CODE", "STDIN", "STDOUT", "STDERR", "DNS_HINFO", + "DNS_PTR", "SQLITE_EMPTY", "SVN_SHOW_UPDATES", "SVN_NO_IGNORE", "MSG_EOF", + "DNS_MX", "GD_EXTRA_VERSION", "PHP_VERSION_ID", "SQLITE_OK", + "LIBXML_LOADED_VERSION", "RADIXCHAR", "OPENSSL_VERSION_TEXT", "OPENSSL_VERSION_NUMBER", + "PCRE_VERSION", "CURLOPT_FILE", "CURLOPT_INFILE", "CURLOPT_URL", "CURLOPT_PROXY", + "CURLE_FUNCTION_NOT_FOUND", "SOCKET_ENOMSG", "CURLOPT_HTTPHEADER", "SOCKET_EIDRM", + "CURLOPT_PROGRESSFUNCTION", "SOCKET_ECHRNG", "SOCKET_EL2NSYNC", "SOCKET_EL3HLT", + "SOCKET_EL3RST", "SOCKET_ELNRNG", "SOCKET_ENOCSI", "SOCKET_EL2HLT", "SOCKET_EBADE", + "SOCKET_EXFULL", "CURLOPT_USERPWD", "CURLOPT_PROXYUSERPWD", "CURLOPT_RANGE", + "CURLOPT_TIMEOUT_MS", "CURLOPT_POSTFIELDS", "CURLOPT_REFERER", "CURLOPT_USERAGENT", + "CURLOPT_FTPPORT", "SOCKET_ERESTART", "SQLITE_CONSTRAINT", "SQLITE_MISMATCH", + "SQLITE_MISUSE", "CURLOPT_COOKIE", "CURLE_SSL_CERTPROBLEM", "CURLOPT_SSLCERT", + "CURLOPT_KEYPASSWD", "CURLOPT_WRITEHEADER", "CURLOPT_SSL_VERIFYHOST", + "CURLOPT_COOKIEFILE", "CURLE_HTTP_RANGE_ERROR", "CURLE_HTTP_POST_ERROR", + "CURLOPT_CUSTOMREQUEST", "CURLOPT_STDERR", "SOCKET_EBADR", "CURLOPT_RETURNTRANSFER", + "CURLOPT_QUOTE", "CURLOPT_POSTQUOTE", "CURLOPT_INTERFACE", "CURLOPT_KRB4LEVEL", + "SOCKET_ENODATA", "SOCKET_ESRMNT", "CURLOPT_WRITEFUNCTION", "CURLOPT_READFUNCTION", + "CURLOPT_HEADERFUNCTION", "SOCKET_EADV", "SOCKET_EPROTO", "SOCKET_EMULTIHOP", + "SOCKET_EBADMSG", "CURLOPT_FORBID_REUSE", "CURLOPT_RANDOM_FILE", "CURLOPT_EGDSOCKET", + "SOCKET_EREMCHG", "CURLOPT_CONNECTTIMEOUT_MS", "CURLOPT_CAINFO", "CURLOPT_CAPATH", + "CURLOPT_COOKIEJAR", "CURLOPT_SSL_CIPHER_LIST", "CURLOPT_BINARYTRANSFER", + "SQLITE_DONE", "CURLOPT_HTTP_VERSION", "CURLOPT_SSLKEY", "CURLOPT_SSLKEYTYPE", + "CURLOPT_SSLENGINE", "CURLOPT_SSLCERTTYPE", "CURLE_OUT_OF_MEMORY", "CURLOPT_ENCODING", + "CURLE_SSL_CIPHER", "SOCKET_EREMOTEIO", "CURLOPT_HTTP200ALIASES", "CURLAUTH_ANY", + "CURLAUTH_ANYSAFE", "CURLOPT_PRIVATE", "CURLINFO_EFFECTIVE_URL", "CURLINFO_HTTP_CODE", + "CURLINFO_HEADER_SIZE", "CURLINFO_REQUEST_SIZE", "CURLINFO_TOTAL_TIME", + "CURLINFO_NAMELOOKUP_TIME", "CURLINFO_CONNECT_TIME", "CURLINFO_PRETRANSFER_TIME", + "CURLINFO_SIZE_UPLOAD", "CURLINFO_SIZE_DOWNLOAD", "CURLINFO_SPEED_DOWNLOAD", + "CURLINFO_SPEED_UPLOAD", "CURLINFO_FILETIME", "CURLINFO_SSL_VERIFYRESULT", + "CURLINFO_CONTENT_LENGTH_DOWNLOAD", "CURLINFO_CONTENT_LENGTH_UPLOAD", + "CURLINFO_STARTTRANSFER_TIME", "CURLINFO_CONTENT_TYPE", "CURLINFO_REDIRECT_TIME", + "CURLINFO_REDIRECT_COUNT", "CURLINFO_PRIVATE", "CURLINFO_CERTINFO", + "SQLITE_PROTOCOL", "SQLITE_SCHEMA", "SQLITE_TOOBIG", "SQLITE_NOLFS", + "SQLITE_AUTH", "SQLITE_FORMAT", "SOCKET_ENOTTY", "SQLITE_NOTADB", + "SOCKET_ENOSPC", "SOCKET_ESPIPE", "SOCKET_EROFS", "SOCKET_EMLINK", "GD_RELEASE_VERSION", + "SOCKET_ENOLCK", "SOCKET_ENOSYS", "SOCKET_EUNATCH", "SOCKET_ENOANO", "SOCKET_EBADRQC", + "SOCKET_EBADSLT", "SOCKET_ENOSTR", "SOCKET_ETIME", "SOCKET_ENOSR", "SVN_REVISION_HEAD", + "XSD_ENTITY", "XSD_NOTATION", "CURLOPT_CERTINFO", "CURLOPT_POSTREDIR", "CURLOPT_SSH_AUTH_TYPES", + "CURLOPT_SSH_PUBLIC_KEYFILE", "CURLOPT_SSH_PRIVATE_KEYFILE", "CURLOPT_SSH_HOST_PUBLIC_KEY_MD5", + "CURLE_SSH", "CURLOPT_REDIR_PROTOCOLS", "CURLOPT_PROTOCOLS", "XSD_NONNEGATIVEINTEGER", + "XSD_BYTE","DNS_SRV","DNS_A6", "DNS_NAPTR", "DNS_AAAA", "FILTER_SANITIZE_FULL_SPECIAL_CHARS", + "ABDAY_1", "SVN_REVISION_UNSPECIFIED", "SVN_REVISION_BASE", "SVN_REVISION_COMMITTED", + "SVN_REVISION_PREV", "GD_VERSION", "MCRYPT_TRIPLEDES", "MCRYPT_ARCFOUR_IV", "MCRYPT_ARCFOUR", + "MCRYPT_BLOWFISH", "MCRYPT_BLOWFISH_COMPAT", "MCRYPT_CAST_128", "MCRYPT_CAST_256", + "MCRYPT_ENIGNA", "MCRYPT_DES", "MCRYPT_GOST", "MCRYPT_LOKI97", "MCRYPT_PANAMA", + "MCRYPT_RC2", "MCRYPT_RIJNDAEL_128", "MCRYPT_RIJNDAEL_192", "MCRYPT_RIJNDAEL_256", + "MCRYPT_SAFER64", "MCRYPT_SAFER128","MCRYPT_SAFERPLUS", "MCRYPT_SERPENT", "MCRYPT_THREEWAY", + "MCRYPT_TWOFISH", "MCRYPT_WAKE", "MCRYPT_XTEA", "MCRYPT_IDEA", "MCRYPT_MARS", + "MCRYPT_RC6", "MCRYPT_SKIPJACK", "MCRYPT_MODE_CBC", "MCRYPT_MODE_CFB", "MCRYPT_MODE_ECB", + "MCRYPT_MODE_NOFB", "MCRYPT_MODE_OFB", "MCRYPT_MODE_STREAM", "CL_EXPUNGE", + "SQLITE_ROW", "POSIX_S_IFBLK", "POSIX_S_IFSOCK", "XSD_IDREF", "ABDAY_2", + "ABDAY_3", "ABDAY_4", "ABDAY_5", "ABDAY_6", "ABDAY_7", "DAY_1", "DAY_2", + "DAY_3", "DAY_4", "DAY_5", "DAY_6", "DAY_7", "ABMON_1", "ABMON_2", "ABMON_3", + "ABMON_4", "ABMON_5", "ABMON_6", "ABMON_7","ABMON_8", "ABMON_9", "ABMON_10", + "ABMON_11", "ABMON_12", "MON_1", "MON_2", "MON_3", "MON_4", "MON_5", "MON_6", + "MON_7", "MON_8", "MON_9", "MON_10", "MON_11", "MON_12", "AM_STR", "PM_STR", + "D_T_FMT", "D_FMT", "T_FMT", "T_FMT_AMPM", "ERA", "ERA_D_T_FMT", "ERA_D_FMT", + "ERA_T_FMT", "ALT_DIGITS", "CRNCYSTR", "THOUSEP", "YESEXPR", "NOEXPR", + "SOCKET_ENOMEDIUM", "GLOB_AVAILABLE_FLAGS", "XSD_SHORT", "XSD_NMTOKENS", + "LOG_LOCAL3", "LOG_LOCAL4", "LOG_LOCAL5", "LOG_LOCAL6", "LOG_LOCAL7", + "DNS_ANY", "DNS_ALL", "SOCKET_ENOLINK", "SOCKET_ECOMM", "SOAP_FUNCTIONS_ALL", + "UNKNOWN_TYPE", "XSD_BASE64BINARY", "XSD_ANYURI", "XSD_QNAME", "SOCKET_EISNAM", + "SOCKET_EMEDIUMTYPE", "XSD_NCNAME", "XSD_ID", "XSD_ENTITIES", "XSD_INTEGER", + "XSD_NONPOSITIVEINTEGER", "XSD_NEGATIVEINTEGER", "XSD_LONG", "XSD_INT", + "XSD_UNSIGNEDLONG", "XSD_UNSIGNEDINT", "XSD_UNSIGNEDSHORT", "XSD_UNSIGNEDBYTE", + "XSD_POSITIVEINTEGER", "XSD_ANYTYPE", "XSD_ANYXML", "APACHE_MAP", "XSD_1999_TIMEINSTANT", + "XSD_NAMESPACE", "XSD_1999_NAMESPACE", "SOCKET_ENOTUNIQ", "SOCKET_EBADFD", + "SOCKET_ESTRPIPE", "T_GOTO", "T_NAMESPACE", "T_NS_C", "T_DIR", "T_NS_SEPARATOR", + "LIBXSLT_VERSION","LIBEXSLT_DOTTED_VERSION", "LIBEXSLT_VERSION", "SVN_AUTH_PARAM_DEFAULT_USERNAME", + "SVN_AUTH_PARAM_DEFAULT_PASSWORD", "SVN_AUTH_PARAM_NON_INTERACTIVE", + "SVN_AUTH_PARAM_DONT_STORE_PASSWORDS", "SVN_AUTH_PARAM_NO_AUTH_CACHE", + "SVN_AUTH_PARAM_SSL_SERVER_FAILURES", "SVN_AUTH_PARAM_SSL_SERVER_CERT_INFO", + "SVN_AUTH_PARAM_CONFIG", "SVN_AUTH_PARAM_SERVER_GROUP", + "SVN_AUTH_PARAM_CONFIG_DIR", "PHP_SVN_AUTH_PARAM_IGNORE_SSL_VERIFY_ERRORS", + "SVN_FS_CONFIG_FS_TYPE", "SVN_FS_TYPE_BDB", "SVN_FS_TYPE_FSFS", "SVN_PROP_REVISION_DATE", + "SVN_PROP_REVISION_ORIG_DATE", "SVN_PROP_REVISION_AUTHOR", "SVN_PROP_REVISION_LOG" + ].forEach(function(element, index, array) { + result[element] = token("atom", "php-predefined-constant"); + }); + + // PHP declared classes - output of get_declared_classes(). Differs from http://php.net/manual/en/reserved.classes.php + [ "stdClass", "Exception", "ErrorException", "COMPersistHelper", "com_exception", + "com_safearray_proxy", "variant", "com", "dotnet", "ReflectionException", + "Reflection", "ReflectionFunctionAbstract", "ReflectionFunction", + "ReflectionParameter", "ReflectionMethod", "ReflectionClass", + "ReflectionObject", "ReflectionProperty", "ReflectionExtension", "DateTime", + "DateTimeZone", "LibXMLError", "__PHP_Incomplete_Class", "php_user_filter", + "Directory", "SimpleXMLElement", "DOMException", "DOMStringList", + "DOMNameList", "DOMImplementationList", "DOMImplementationSource", + "DOMImplementation", "DOMNode", "DOMNameSpaceNode", "DOMDocumentFragment", + "DOMDocument", "DOMNodeList", "DOMNamedNodeMap", "DOMCharacterData", "DOMAttr", + "DOMElement", "DOMText", "DOMComment", "DOMTypeinfo", "DOMUserDataHandler", + "DOMDomError", "DOMErrorHandler", "DOMLocator", "DOMConfiguration", + "DOMCdataSection", "DOMDocumentType", "DOMNotation", "DOMEntity", + "DOMEntityReference", "DOMProcessingInstruction", "DOMStringExtend", + "DOMXPath", "RecursiveIteratorIterator", "IteratorIterator", "FilterIterator", + "RecursiveFilterIterator", "ParentIterator", "LimitIterator", + "CachingIterator", "RecursiveCachingIterator", "NoRewindIterator", + "AppendIterator", "InfiniteIterator", "RegexIterator", + "RecursiveRegexIterator", "EmptyIterator", "ArrayObject", "ArrayIterator", + "RecursiveArrayIterator", "SplFileInfo", "DirectoryIterator", + "RecursiveDirectoryIterator", "SplFileObject", "SplTempFileObject", + "SimpleXMLIterator", "LogicException", "BadFunctionCallException", + "BadMethodCallException", "DomainException", "InvalidArgumentException", + "LengthException", "OutOfRangeException", "RuntimeException", + "OutOfBoundsException", "OverflowException", "RangeException", + "UnderflowException", "UnexpectedValueException", "SplObjectStorage", + "XMLReader", "XMLWriter", "mysqli_sql_exception", "mysqli_driver", "mysqli", + "mysqli_warning", "mysqli_result", "mysqli_stmt", "PDOException", "PDO", + "PDOStatement", "PDORow","Closure", "DateInterval", "DatePeriod", "FilesystemIterator", + "GlobIterator", "MultipleIterator", "RecursiveTreeIterator", "SoapClient", + "SoapFault", "SoapHeader", "SoapParam", "SoapServer", "SoapVar", "SplDoublyLinkedList", + "SplFixedArray", "SplHeap", "SplMaxHeap", "SplMinHeap", "SplPriorityQueue", + "SplQueue", "SplStack", "SQLite3", "SQLite3Result", "SQLite3Stmt", "SQLiteDatabase", + "SQLiteException", "SQLiteResult", "SQLiteUnbuffered", "Svn", "SvnNode", "SvnWc", + "SvnWcSchedule", "XSLTProcessor", "ZipArchive", + ].forEach(function(element, index, array) { + result[element] = token("t_string", "php-predefined-class"); + }); + + return result; + + }(); + + // Helper regexps + var isOperatorChar = /[+*&%\/=<>!?.|^@-]/; + var isHexDigit = /[0-9A-Fa-f]/; + var isWordChar = /[\w\$_\\]/; + + // Wrapper around phpToken that helps maintain parser state (whether + // we are inside of a multi-line comment) + function phpTokenState(inside) { + return function(source, setState) { + var newInside = inside; + var type = phpToken(inside, source, function(c) {newInside = c;}); + if (newInside != inside) + setState(phpTokenState(newInside)); + return type; + }; + } + + // The token reader, inteded to be used by the tokenizer from + // tokenize.js (through phpTokenState). Advances the source stream + // over a token, and returns an object containing the type and style + // of that token. + function phpToken(inside, source, setInside) { + function readHexNumber(){ + source.next(); // skip the 'x' + source.nextWhileMatches(isHexDigit); + return {type: "number", style: "php-atom"}; + } + + function readNumber() { + source.nextWhileMatches(/[0-9]/); + if (source.equals(".")){ + source.next(); + source.nextWhileMatches(/[0-9]/); + } + if (source.equals("e") || source.equals("E")){ + source.next(); + if (source.equals("-")) + source.next(); + source.nextWhileMatches(/[0-9]/); + } + return {type: "number", style: "php-atom"}; + } + // Read a word and look it up in the keywords array. If found, it's a + // keyword of that type; otherwise it's a PHP T_STRING. + function readWord() { + source.nextWhileMatches(isWordChar); + var word = source.get(); + var known = keywords.hasOwnProperty(word) && keywords.propertyIsEnumerable(word) && keywords[word]; + // since we called get(), tokenize::take won't get() anything. Thus, we must set token.content + return known ? {type: known.type, style: known.style, content: word} : + {type: "t_string", style: "php-t_string", content: word}; + } + function readVariable() { + source.nextWhileMatches(isWordChar); + var word = source.get(); + // in PHP, '$this' is a reserved word, but 'this' isn't. You can have function this() {...} + if (word == "$this") + return {type: "variable", style: "php-keyword", content: word}; + else + return {type: "variable", style: "php-variable", content: word}; + } + + // Advance the stream until the given character (not preceded by a + // backslash) is encountered, or the end of the line is reached. + function nextUntilUnescaped(source, end) { + var escaped = false; + while(!source.endOfLine()){ + var next = source.next(); + if (next == end && !escaped) + return false; + escaped = next == "\\" && !escaped; + } + return escaped; + } + + function readSingleLineComment() { + // read until the end of the line or until ?>, which terminates single-line comments + // ` foo` will display "1 foo" + while(!source.lookAhead("?>") && !source.endOfLine()) + source.next(); + return {type: "comment", style: "php-comment"}; + } + /* For multi-line comments, we want to return a comment token for + every line of the comment, but we also want to return the newlines + in them as regular newline tokens. We therefore need to save a + state variable ("inside") to indicate whether we are inside a + multi-line comment. + */ + + function readMultilineComment(start){ + var newInside = "/*"; + var maybeEnd = (start == "*"); + while (true) { + if (source.endOfLine()) + break; + var next = source.next(); + if (next == "/" && maybeEnd){ + newInside = null; + break; + } + maybeEnd = (next == "*"); + } + setInside(newInside); + return {type: "comment", style: "php-comment"}; + } + + // similar to readMultilineComment and nextUntilUnescaped + // unlike comments, strings are not stopped by ?> + function readMultilineString(start){ + var newInside = start; + var escaped = false; + while (true) { + if (source.endOfLine()) + break; + var next = source.next(); + if (next == start && !escaped){ + newInside = null; // we're outside of the string now + break; + } + escaped = (next == "\\" && !escaped); + } + setInside(newInside); + return { + type: newInside == null? "string" : "string_not_terminated", + style: (start == "'"? "php-string-single-quoted" : "php-string-double-quoted") + }; + } + + // http://php.net/manual/en/language.types.string.php#language.types.string.syntax.heredoc + // See also 'nowdoc' on the page. Heredocs are not interrupted by the '?>' token. + function readHeredoc(identifier){ + var token = {}; + if (identifier == "<<<") { + // on our first invocation after reading the <<<, we must determine the closing identifier + if (source.equals("'")) { + // nowdoc + source.nextWhileMatches(isWordChar); + identifier = "'" + source.get() + "'"; + source.next(); // consume the closing "'" + } else if (source.matches(/[A-Za-z_]/)) { + // heredoc + source.nextWhileMatches(isWordChar); + identifier = source.get(); + } else { + // syntax error + setInside(null); + return { type: "error", style: "syntax-error" }; + } + setInside(identifier); + token.type = "string_not_terminated"; + token.style = identifier.charAt(0) == "'"? "php-string-single-quoted" : "php-string-double-quoted"; + token.content = identifier; + } else { + token.style = identifier.charAt(0) == "'"? "php-string-single-quoted" : "php-string-double-quoted"; + // consume a line of heredoc and check if it equals the closing identifier plus an optional semicolon + if (source.lookAhead(identifier, true) && (source.lookAhead(";\n") || source.endOfLine())) { + // the closing identifier can only appear at the beginning of the line + // note that even whitespace after the ";" is forbidden by the PHP heredoc syntax + token.type = "string"; + token.content = source.get(); // don't get the ";" if there is one + setInside(null); + } else { + token.type = "string_not_terminated"; + source.nextWhileMatches(/[^\n]/); + token.content = source.get(); + } + } + return token; + } + + function readOperator() { + source.nextWhileMatches(isOperatorChar); + return {type: "operator", style: "php-operator"}; + } + function readStringSingleQuoted() { + var endBackSlash = nextUntilUnescaped(source, "'", false); + setInside(endBackSlash ? "'" : null); + return {type: "string", style: "php-string-single-quoted"}; + } + function readStringDoubleQuoted() { + var endBackSlash = nextUntilUnescaped(source, "\"", false); + setInside(endBackSlash ? "\"": null); + return {type: "string", style: "php-string-double-quoted"}; + } + + // Fetch the next token. Dispatches on first character in the + // stream, or first two characters when the first is a slash. + switch (inside) { + case null: + case false: break; + case "'": + case "\"": return readMultilineString(inside); + case "/*": return readMultilineComment(source.next()); + default: return readHeredoc(inside); + } + var ch = source.next(); + if (ch == "'" || ch == "\"") + return readMultilineString(ch); + else if (ch == "#") + return readSingleLineComment(); + else if (ch == "$") + return readVariable(); + else if (ch == ":" && source.equals(":")) { + source.next(); + // the T_DOUBLE_COLON can only follow a T_STRING (class name) + return {type: "t_double_colon", style: "php-operator"}; + } + // with punctuation, the type of the token is the symbol itself + else if (/[\[\]{}\(\),;:]/.test(ch)) { + return {type: ch, style: "php-punctuation"}; + } + else if (ch == "0" && (source.equals("x") || source.equals("X"))) + return readHexNumber(); + else if (/[0-9]/.test(ch)) + return readNumber(); + else if (ch == "/") { + if (source.equals("*")) + { source.next(); return readMultilineComment(ch); } + else if (source.equals("/")) + return readSingleLineComment(); + else + return readOperator(); + } + else if (ch == "<") { + if (source.lookAhead("<<", true)) { + setInside("<<<"); + return {type: "<<<", style: "php-punctuation"}; + } + else + return readOperator(); + } + else if (isOperatorChar.test(ch)) + return readOperator(); + else + return readWord(); + } + + // The external interface to the tokenizer. + return function(source, startState) { + return tokenizer(source, startState || phpTokenState(false, true)); + }; +})(); diff --git a/gulliver/js/codemirror/contrib/plsql/LICENSE b/gulliver/js/codemirror/contrib/plsql/LICENSE new file mode 100755 index 000000000..b9ae48b4d --- /dev/null +++ b/gulliver/js/codemirror/contrib/plsql/LICENSE @@ -0,0 +1,22 @@ + Copyright (c) 2010 Peter Raganitsch + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any + damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and + redistribute it freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + Peter Raganitsch diff --git a/gulliver/js/codemirror/contrib/plsql/css/plsqlcolors.css b/gulliver/js/codemirror/contrib/plsql/css/plsqlcolors.css new file mode 100755 index 000000000..bc64c20b7 --- /dev/null +++ b/gulliver/js/codemirror/contrib/plsql/css/plsqlcolors.css @@ -0,0 +1,57 @@ +html { + cursor: text; +} + +.editbox { + margin: .4em; + padding: 0; + font-family: monospace; + font-size: 10pt; + color: black; +} + +.editbox p { + margin: 0; +} + +span.plsql-keyword { + color: blue; +} + +span.plsql-var { + color: red; +} + +span.plsql-comment { + color: #AA7700; +} + +span.plsql-literal { + color: green; +} + +span.plsql-operator { + color: blue; +} + +span.plsql-word { + color: black; +} + +span.plsql-function { + color: darkorange; +} + +span.plsql-type { + color: purple; +} + +span.plsql-separator { + color: #666666; +} + +span.plsql-number { + color: darkcyan; +} + + diff --git a/gulliver/js/codemirror/contrib/plsql/index.html b/gulliver/js/codemirror/contrib/plsql/index.html new file mode 100755 index 000000000..4c3548a12 --- /dev/null +++ b/gulliver/js/codemirror/contrib/plsql/index.html @@ -0,0 +1,67 @@ + + + + CodeMirror: PLSQL demonstration + + + + +

Demonstration of CodeMirror's PLSQL +highlighter.

+ +

Written by Peter Raganitsch (license), based +on John Benediktsson SQL parser.

+ +
+ +
+ + + + + diff --git a/gulliver/js/codemirror/contrib/plsql/js/parseplsql.js b/gulliver/js/codemirror/contrib/plsql/js/parseplsql.js new file mode 100755 index 000000000..cc35c8c1a --- /dev/null +++ b/gulliver/js/codemirror/contrib/plsql/js/parseplsql.js @@ -0,0 +1,233 @@ +var PlsqlParser = Editor.Parser = (function() { + + function wordRegexp(words) { + return new RegExp("^(?:" + words.join("|") + ")$", "i"); + } + + var functions = wordRegexp([ +"abs","acos","add_months","ascii","asin","atan","atan2","average", +"bfilename", +"ceil","chartorowid","chr","concat","convert","cos","cosh","count", +"decode","deref","dual","dump","dup_val_on_index", +"empty","error","exp", +"false","floor","found", +"glb","greatest", +"hextoraw", +"initcap","instr","instrb","isopen", +"last_day","least","lenght","lenghtb","ln","lower","lpad","ltrim","lub", +"make_ref","max","min","mod","months_between", +"new_time","next_day","nextval","nls_charset_decl_len","nls_charset_id","nls_charset_name","nls_initcap","nls_lower", +"nls_sort","nls_upper","nlssort","no_data_found","notfound","null","nvl", +"others", +"power", +"rawtohex","reftohex","round","rowcount","rowidtochar","rpad","rtrim", +"sign","sin","sinh","soundex","sqlcode","sqlerrm","sqrt","stddev","substr","substrb","sum","sysdate", +"tan","tanh","to_char","to_date","to_label","to_multi_byte","to_number","to_single_byte","translate","true","trunc", +"uid","upper","user","userenv", +"variance","vsize" + + ]); + + var keywords = wordRegexp([ +"abort","accept","access","add","all","alter","and","any","array","arraylen","as","asc","assert","assign","at","attributes","audit", +"authorization","avg", +"base_table","begin","between","binary_integer","body","boolean","by", +"case","cast","char","char_base","check","close","cluster","clusters","colauth","column","comment","commit","compress","connect", +"connected","constant","constraint","crash","create","current","currval","cursor", +"data_base","database","date","dba","deallocate","debugoff","debugon","decimal","declare","default","definition","delay","delete", +"desc","digits","dispose","distinct","do","drop", +"else","elsif","enable","end","entry","escape","exception","exception_init","exchange","exclusive","exists","exit","external", +"fast","fetch","file","for","force","form","from","function", +"generic","goto","grant","group", +"having", +"identified","if","immediate","in","increment","index","indexes","indicator","initial","initrans","insert","interface","intersect", +"into","is", +"key", +"level","library","like","limited","local","lock","log","logging","long","loop", +"master","maxextents","maxtrans","member","minextents","minus","mislabel","mode","modify","multiset", +"new","next","no","noaudit","nocompress","nologging","noparallel","not","nowait","number_base", +"object","of","off","offline","on","online","only","open","option","or","order","out", +"package","parallel","partition","pctfree","pctincrease","pctused","pls_integer","positive","positiven","pragma","primary","prior", +"private","privileges","procedure","public", +"raise","range","raw","read","rebuild","record","ref","references","refresh","release","rename","replace","resource","restrict","return", +"returning","reverse","revoke","rollback","row","rowid","rowlabel","rownum","rows","run", +"savepoint","schema","segment","select","separate","session","set","share","snapshot","some","space","split","sql","start","statement", +"storage","subtype","successful","synonym", +"tabauth","table","tables","tablespace","task","terminate","then","to","trigger","truncate","type", +"union","unique","unlimited","unrecoverable","unusable","update","use","using", +"validate","value","values","variable","view","views", +"when","whenever","where","while","with","work" + ]); + + var types = wordRegexp([ +"bfile","blob", +"character","clob", +"dec", +"float", +"int","integer", +"mlslabel", +"natural","naturaln","nchar","nclob","number","numeric","nvarchar2", +"real","rowtype", +"signtype","smallint","string", +"varchar","varchar2" + ]); + + var operators = wordRegexp([ + ":=", "<", "<=", "==", "!=", "<>", ">", ">=", "like", "rlike", "in", "xor", "between" + ]); + + var operatorChars = /[*+\-<>=&|:\/]/; + + var tokenizeSql = (function() { + function normal(source, setState) { + var ch = source.next(); + if (ch == "@" || ch == "$") { + source.nextWhileMatches(/[\w\d]/); + return "plsql-var"; + } + else if (ch == "\"" || ch == "'" || ch == "`") { + setState(inLiteral(ch)); + return null; + } + else if (ch == "," || ch == ";") { + return "plsql-separator" + } + else if (ch == '-') { + if (source.peek() == "-") { + while (!source.endOfLine()) source.next(); + return "plsql-comment"; + } + else if (/\d/.test(source.peek())) { + source.nextWhileMatches(/\d/); + if (source.peek() == '.') { + source.next(); + source.nextWhileMatches(/\d/); + } + return "plsql-number"; + } + else + return "plsql-operator"; + } + else if (operatorChars.test(ch)) { + source.nextWhileMatches(operatorChars); + return "plsql-operator"; + } + else if (/\d/.test(ch)) { + source.nextWhileMatches(/\d/); + if (source.peek() == '.') { + source.next(); + source.nextWhileMatches(/\d/); + } + return "plsql-number"; + } + else if (/[()]/.test(ch)) { + return "plsql-punctuation"; + } + else { + source.nextWhileMatches(/[_\w\d]/); + var word = source.get(), type; + if (operators.test(word)) + type = "plsql-operator"; + else if (keywords.test(word)) + type = "plsql-keyword"; + else if (functions.test(word)) + type = "plsql-function"; + else if (types.test(word)) + type = "plsql-type"; + else + type = "plsql-word"; + return {style: type, content: word}; + } + } + + function inLiteral(quote) { + return function(source, setState) { + var escaped = false; + while (!source.endOfLine()) { + var ch = source.next(); + if (ch == quote && !escaped) { + setState(normal); + break; + } + escaped = !escaped && ch == "\\"; + } + return quote == "`" ? "plsql-word" : "plsql-literal"; + }; + } + + return function(source, startState) { + return tokenizer(source, startState || normal); + }; + })(); + + function indentSql(context) { + return function(nextChars) { + var firstChar = nextChars && nextChars.charAt(0); + var closing = context && firstChar == context.type; + if (!context) + return 0; + else if (context.align) + return context.col - (closing ? context.width : 0); + else + return context.indent + (closing ? 0 : indentUnit); + } + } + + function parseSql(source) { + var tokens = tokenizeSql(source); + var context = null, indent = 0, col = 0; + function pushContext(type, width, align) { + context = {prev: context, indent: indent, col: col, type: type, width: width, align: align}; + } + function popContext() { + context = context.prev; + } + + var iter = { + next: function() { + var token = tokens.next(); + var type = token.style, content = token.content, width = token.value.length; + + if (content == "\n") { + token.indentation = indentSql(context); + indent = col = 0; + if (context && context.align == null) context.align = false; + } + else if (type == "whitespace" && col == 0) { + indent = width; + } + else if (!context && type != "plsql-comment") { + pushContext(";", 0, false); + } + + if (content != "\n") col += width; + + if (type == "plsql-punctuation") { + if (content == "(") + pushContext(")", width); + else if (content == ")") + popContext(); + } + else if (type == "plsql-separator" && content == ";" && context && !context.prev) { + popContext(); + } + + return token; + }, + + copy: function() { + var _context = context, _indent = indent, _col = col, _tokenState = tokens.state; + return function(source) { + tokens = tokenizeSql(source, _tokenState); + context = _context; + indent = _indent; + col = _col; + return iter; + }; + } + }; + return iter; + } + + return {make: parseSql, electricChars: ")"}; +})(); diff --git a/gulliver/js/codemirror/contrib/python/LICENSE b/gulliver/js/codemirror/contrib/python/LICENSE new file mode 100755 index 000000000..9512de2ef --- /dev/null +++ b/gulliver/js/codemirror/contrib/python/LICENSE @@ -0,0 +1,32 @@ +Copyright (c) 2009, Timothy Farrell +All rights reserved. + +This software is provided for use in connection with the +CodeMirror suite of modules and utilities, hosted and maintained +at http://codemirror.net/. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/gulliver/js/codemirror/contrib/python/css/pythoncolors.css b/gulliver/js/codemirror/contrib/python/css/pythoncolors.css new file mode 100755 index 000000000..fb9cea4b2 --- /dev/null +++ b/gulliver/js/codemirror/contrib/python/css/pythoncolors.css @@ -0,0 +1,58 @@ +html { + cursor: text; +} + +.editbox { + padding: .4em; + margin: 0; + font-family: monospace; + font-size: 10pt; + line-height: 1.1em; + color: black; +} + +pre.code, .editbox { + color: #666666; +} + +.editbox p { + margin: 0; +} + +span.py-delimiter, span.py-special { + color: #666666; +} + +span.py-operator { + color: #666666; +} + +span.py-error { + background-color: #660000; + color: #FFFFFF; +} + +span.py-keyword { + color: #770088; + font-weight: bold; +} + +span.py-literal { + color: #228811; +} + +span.py-identifier, span.py-func { + color: black; +} + +span.py-type, span.py-decorator { + color: #0000FF; +} + +span.py-comment { + color: #AA7700; +} + +span.py-string, span.py-bytes, span.py-raw, span.py-unicode { + color: #AA2222; +} diff --git a/gulliver/js/codemirror/contrib/python/index.html b/gulliver/js/codemirror/contrib/python/index.html new file mode 100755 index 000000000..31d2f0a0a --- /dev/null +++ b/gulliver/js/codemirror/contrib/python/index.html @@ -0,0 +1,141 @@ + + + + CodeMirror: Python demonstration + + + +

+ This is a simple demonstration of the Python syntax highlighting module + for CodeMirror. +

+

+ Features of this parser include: +

+
    +
  • Token-based syntax highlighting - currently very little lexical analysis happens. Few lexical errors will be detected.
  • +
  • Use the normal indentation mode to enforce regular indentation, otherwise the "shift" indentation mode will give you more flexibility.
  • +
  • Parser Options: +
      +
    • pythonVersion (Integer) - 2 or 3 to indicate which version of Python to parse. Default = 2
    • +
    • strictErrors (Bool) - true to highlight errors that may not be Python errors but cause confusion for this parser. Default = true
    • +
    +
  • +
+

Written by Timothy Farrell (license). Special +thanks to Adam Brand and Marijn Haverbeke for their help in debugging +and providing for this parser.

+ +
+ +
+ + + + diff --git a/gulliver/js/codemirror/contrib/python/js/parsepython.js b/gulliver/js/codemirror/contrib/python/js/parsepython.js new file mode 100755 index 000000000..787703db0 --- /dev/null +++ b/gulliver/js/codemirror/contrib/python/js/parsepython.js @@ -0,0 +1,541 @@ +var PythonParser = Editor.Parser = (function() { + function wordRegexp(words) { + return new RegExp("^(?:" + words.join("|") + ")$"); + } + var DELIMITERCLASS = 'py-delimiter'; + var LITERALCLASS = 'py-literal'; + var ERRORCLASS = 'py-error'; + var OPERATORCLASS = 'py-operator'; + var IDENTIFIERCLASS = 'py-identifier'; + var STRINGCLASS = 'py-string'; + var BYTESCLASS = 'py-bytes'; + var UNICODECLASS = 'py-unicode'; + var RAWCLASS = 'py-raw'; + var NORMALCONTEXT = 'normal'; + var STRINGCONTEXT = 'string'; + var singleOperators = '+-*/%&|^~<>'; + var doubleOperators = wordRegexp(['==', '!=', '\\<=', '\\>=', '\\<\\>', + '\\<\\<', '\\>\\>', '\\/\\/', '\\*\\*']); + var singleDelimiters = '()[]{}@,:`=;'; + var doubleDelimiters = ['\\+=', '\\-=', '\\*=', '/=', '%=', '&=', '\\|=', + '\\^=']; + var tripleDelimiters = wordRegexp(['//=','\\>\\>=','\\<\\<=','\\*\\*=']); + var singleStarters = singleOperators + singleDelimiters + '=!'; + var doubleStarters = '=<>*/'; + var identifierStarters = /[_A-Za-z]/; + + var wordOperators = wordRegexp(['and', 'or', 'not', 'is', 'in']); + var commonkeywords = ['as', 'assert', 'break', 'class', 'continue', + 'def', 'del', 'elif', 'else', 'except', 'finally', + 'for', 'from', 'global', 'if', 'import', + 'lambda', 'pass', 'raise', 'return', + 'try', 'while', 'with', 'yield']; + var commontypes = ['bool', 'classmethod', 'complex', 'dict', 'enumerate', + 'float', 'frozenset', 'int', 'list', 'object', + 'property', 'reversed', 'set', 'slice', 'staticmethod', + 'str', 'super', 'tuple', 'type']; + var py2 = {'types': ['basestring', 'buffer', 'file', 'long', 'unicode', + 'xrange'], + 'keywords': ['exec', 'print'], + 'version': 2 }; + var py3 = {'types': ['bytearray', 'bytes', 'filter', 'map', 'memoryview', + 'open', 'range', 'zip'], + 'keywords': ['nonlocal'], + 'version': 3}; + + var py, keywords, types, stringStarters, stringTypes, config; + + function configure(conf) { + if (!conf.hasOwnProperty('pythonVersion')) { + conf.pythonVersion = 2; + } + if (!conf.hasOwnProperty('strictErrors')) { + conf.strictErrors = true; + } + if (conf.pythonVersion != 2 && conf.pythonVersion != 3) { + alert('CodeMirror: Unknown Python Version "' + + conf.pythonVersion + + '", defaulting to Python 2.x.'); + conf.pythonVersion = 2; + } + if (conf.pythonVersion == 3) { + py = py3; + stringStarters = /[\'\"rbRB]/; + stringTypes = /[rb]/; + doubleDelimiters.push('\\-\\>'); + } else { + py = py2; + stringStarters = /[\'\"RUru]/; + stringTypes = /[ru]/; + } + config = conf; + keywords = wordRegexp(commonkeywords.concat(py.keywords)); + types = wordRegexp(commontypes.concat(py.types)); + doubleDelimiters = wordRegexp(doubleDelimiters); + } + + var tokenizePython = (function() { + function normal(source, setState) { + var stringDelim, threeStr, temp, type, word, possible = {}; + var ch = source.next(); + + function filterPossible(token, styleIfPossible) { + if (!possible.style && !possible.content) { + return token; + } else if (typeof(token) == STRINGCONTEXT) { + token = {content: source.get(), style: token}; + } + if (possible.style || styleIfPossible) { + token.style = styleIfPossible ? styleIfPossible : possible.style; + } + if (possible.content) { + token.content = possible.content + token.content; + } + possible = {}; + return token; + } + + // Handle comments + if (ch == '#') { + while (!source.endOfLine()) { + source.next(); + } + return 'py-comment'; + } + // Handle special chars + if (ch == '\\') { + if (!source.endOfLine()) { + var whitespace = true; + while (!source.endOfLine()) { + if(!(/[\s\u00a0]/.test(source.next()))) { + whitespace = false; + } + } + if (!whitespace) { + return ERRORCLASS; + } + } + return 'py-special'; + } + // Handle operators and delimiters + if (singleStarters.indexOf(ch) != -1 || (ch == "." && !source.matches(/\d/))) { + if (doubleStarters.indexOf(source.peek()) != -1) { + temp = ch + source.peek(); + // It must be a double delimiter or operator or triple delimiter + if (doubleOperators.test(temp)) { + source.next(); + var nextChar = source.peek(); + if (nextChar && tripleDelimiters.test(temp + nextChar)) { + source.next(); + return DELIMITERCLASS; + } else { + return OPERATORCLASS; + } + } else if (doubleDelimiters.test(temp)) { + source.next(); + return DELIMITERCLASS; + } + } + // It must be a single delimiter or operator + if (singleOperators.indexOf(ch) != -1 || ch == ".") { + return OPERATORCLASS; + } else if (singleDelimiters.indexOf(ch) != -1) { + if (ch == '@' && source.matches(/\w/)) { + source.nextWhileMatches(/[\w\d_]/); + return {style:'py-decorator', + content: source.get()}; + } else { + return DELIMITERCLASS; + } + } else { + return ERRORCLASS; + } + } + // Handle number literals + if (/\d/.test(ch) || (ch == "." && source.matches(/\d/))) { + if (ch === '0' && !source.endOfLine()) { + switch (source.peek()) { + case 'o': + case 'O': + source.next(); + source.nextWhileMatches(/[0-7]/); + return filterPossible(LITERALCLASS, ERRORCLASS); + case 'x': + case 'X': + source.next(); + source.nextWhileMatches(/[0-9A-Fa-f]/); + return filterPossible(LITERALCLASS, ERRORCLASS); + case 'b': + case 'B': + source.next(); + source.nextWhileMatches(/[01]/); + return filterPossible(LITERALCLASS, ERRORCLASS); + } + } + source.nextWhileMatches(/\d/); + if (ch != '.' && source.peek() == '.') { + source.next(); + source.nextWhileMatches(/\d/); + } + // Grab an exponent + if (source.matches(/e/i)) { + source.next(); + if (source.peek() == '+' || source.peek() == '-') { + source.next(); + } + if (source.matches(/\d/)) { + source.nextWhileMatches(/\d/); + } else { + return filterPossible(ERRORCLASS); + } + } + // Grab a complex number + if (source.matches(/j/i)) { + source.next(); + } + + return filterPossible(LITERALCLASS); + } + // Handle strings + if (stringStarters.test(ch)) { + var peek = source.peek(); + var stringType = STRINGCLASS; + if ((stringTypes.test(ch)) && (peek == '"' || peek == "'")) { + switch (ch.toLowerCase()) { + case 'b': + stringType = BYTESCLASS; + break; + case 'r': + stringType = RAWCLASS; + break; + case 'u': + stringType = UNICODECLASS; + break; + } + ch = source.next(); + stringDelim = ch; + if (source.peek() != stringDelim) { + setState(inString(stringType, stringDelim)); + return null; + } else { + source.next(); + if (source.peek() == stringDelim) { + source.next(); + threeStr = stringDelim + stringDelim + stringDelim; + setState(inString(stringType, threeStr)); + return null; + } else { + return stringType; + } + } + } else if (ch == "'" || ch == '"') { + stringDelim = ch; + if (source.peek() != stringDelim) { + setState(inString(stringType, stringDelim)); + return null; + } else { + source.next(); + if (source.peek() == stringDelim) { + source.next(); + threeStr = stringDelim + stringDelim + stringDelim; + setState(inString(stringType, threeStr)); + return null; + } else { + return stringType; + } + } + } + } + // Handle Identifier + if (identifierStarters.test(ch)) { + source.nextWhileMatches(/[\w\d_]/); + word = source.get(); + if (wordOperators.test(word)) { + type = OPERATORCLASS; + } else if (keywords.test(word)) { + type = 'py-keyword'; + } else if (types.test(word)) { + type = 'py-type'; + } else { + type = IDENTIFIERCLASS; + while (source.peek() == '.') { + source.next(); + if (source.matches(identifierStarters)) { + source.nextWhileMatches(/[\w\d]/); + } else { + type = ERRORCLASS; + break; + } + } + word = word + source.get(); + } + return filterPossible({style: type, content: word}); + } + + // Register Dollar sign and Question mark as errors. Always! + if (/\$\?/.test(ch)) { + return filterPossible(ERRORCLASS); + } + + return filterPossible(ERRORCLASS); + } + + function inString(style, terminator) { + return function(source, setState) { + var matches = []; + var found = false; + while (!found && !source.endOfLine()) { + var ch = source.next(), newMatches = []; + // Skip escaped characters + if (ch == '\\') { + if (source.peek() == '\n') { + break; + } + ch = source.next(); + } + if (ch == terminator.charAt(0)) { + matches.push(terminator); + } + for (var i = 0; i < matches.length; i++) { + var match = matches[i]; + if (match.charAt(0) == ch) { + if (match.length == 1) { + setState(normal); + found = true; + break; + } else { + newMatches.push(match.slice(1)); + } + } + } + matches = newMatches; + } + return style; + }; + } + + return function(source, startState) { + return tokenizer(source, startState || normal); + }; + })(); + + function parsePython(source, basecolumn) { + if (!keywords) { + configure({}); + } + basecolumn = basecolumn || 0; + + var tokens = tokenizePython(source); + var lastToken = null; + var column = basecolumn; + var context = {prev: null, + endOfScope: false, + startNewScope: false, + level: basecolumn, + next: null, + type: NORMALCONTEXT + }; + + function pushContext(level, type) { + type = type ? type : NORMALCONTEXT; + context = {prev: context, + endOfScope: false, + startNewScope: false, + level: level, + next: null, + type: type + }; + } + + function popContext(remove) { + remove = remove ? remove : false; + if (context.prev) { + if (remove) { + context = context.prev; + context.next = null; + } else { + context.prev.next = context; + context = context.prev; + } + } + } + + function indentPython(context) { + var temp; + return function(nextChars, currentLevel, direction) { + if (direction === null || direction === undefined) { + if (nextChars) { + while (context.next) { + context = context.next; + } + } + return context.level; + } + else if (direction === true) { + if (currentLevel == context.level) { + if (context.next) { + return context.next.level; + } else { + return context.level; + } + } else { + temp = context; + while (temp.prev && temp.prev.level > currentLevel) { + temp = temp.prev; + } + return temp.level; + } + } else if (direction === false) { + if (currentLevel > context.level) { + return context.level; + } else if (context.prev) { + temp = context; + while (temp.prev && temp.prev.level >= currentLevel) { + temp = temp.prev; + } + if (temp.prev) { + return temp.prev.level; + } else { + return temp.level; + } + } + } + return context.level; + }; + } + + var iter = { + next: function() { + var token = tokens.next(); + var type = token.style; + var content = token.content; + + if (lastToken) { + if (lastToken.content == 'def' && type == IDENTIFIERCLASS) { + token.style = 'py-func'; + } + if (lastToken.content == '\n') { + var tempCtx = context; + // Check for a different scope + if (type == 'whitespace' && context.type == NORMALCONTEXT) { + if (token.value.length < context.level) { + while (token.value.length < context.level) { + popContext(); + } + + if (token.value.length != context.level) { + context = tempCtx; + if (config.strictErrors) { + token.style = ERRORCLASS; + } + } else { + context.next = null; + } + } + } else if (context.level !== basecolumn && + context.type == NORMALCONTEXT) { + while (basecolumn !== context.level) { + popContext(); + } + + if (context.level !== basecolumn) { + context = tempCtx; + if (config.strictErrors) { + token.style = ERRORCLASS; + } + } + } + } + } + + // Handle Scope Changes + switch(type) { + case STRINGCLASS: + case BYTESCLASS: + case RAWCLASS: + case UNICODECLASS: + if (context.type !== STRINGCONTEXT) { + pushContext(context.level + 1, STRINGCONTEXT); + } + break; + default: + if (context.type === STRINGCONTEXT) { + popContext(true); + } + break; + } + switch(content) { + case '.': + case '@': + // These delimiters don't appear by themselves + if (content !== token.value) { + token.style = ERRORCLASS; + } + break; + case ':': + // Colons only delimit scope inside a normal scope + if (context.type === NORMALCONTEXT) { + context.startNewScope = context.level+indentUnit; + } + break; + case '(': + case '[': + case '{': + // These start a sequence scope + pushContext(column + content.length, 'sequence'); + break; + case ')': + case ']': + case '}': + // These end a sequence scope + popContext(true); + break; + case 'pass': + case 'return': + // These end a normal scope + if (context.type === NORMALCONTEXT) { + context.endOfScope = true; + } + break; + case '\n': + // Reset our column + column = basecolumn; + // Make any scope changes + if (context.endOfScope) { + context.endOfScope = false; + popContext(); + } else if (context.startNewScope !== false) { + var temp = context.startNewScope; + context.startNewScope = false; + pushContext(temp, NORMALCONTEXT); + } + // Newlines require an indentation function wrapped in a closure for proper context. + token.indentation = indentPython(context); + break; + } + + // Keep track of current column for certain scopes. + if (content != '\n') { + column += token.value.length; + } + + lastToken = token; + return token; + }, + + copy: function() { + var _context = context, _tokenState = tokens.state; + return function(source) { + tokens = tokenizePython(source, _tokenState); + context = _context; + return iter; + }; + } + }; + return iter; + } + + return {make: parsePython, + electricChars: "", + configure: configure}; +})(); diff --git a/gulliver/js/codemirror/contrib/regex/css/js-regexcolors.css b/gulliver/js/codemirror/contrib/regex/css/js-regexcolors.css new file mode 100755 index 000000000..1fa691db5 --- /dev/null +++ b/gulliver/js/codemirror/contrib/regex/css/js-regexcolors.css @@ -0,0 +1,214 @@ +/*///////////////////////////////*/ +html { + cursor: text; +} +.editbox { + margin: .4em; + padding: 0; + font-family: monospace; + font-size: 10pt; + color: black; +} +.editbox p { + margin: 0; +} + +html, body { +background: #cccccc !important; +} + +/*///////////////////////////////*/ +/* Inside character classes */ +span.regex-class-special-escape { + color: Coral; +} +span.regex-class-begin, span.regex-class-end { + color: YellowGreen; +} +span.regex-class-negator { + color: Wheat; +} +span.regex-class-range-hyphen { + color: Turquoise; +} +span.regex-class-final-hyphen { + color: Violet; +} + +/*///////////////////////////////*/ +/* Inside character classes (suffixable by -begin-range or -end-range if beginning or ending a range) */ +span.regex-unicode-class-inside { + color: Tomato; +} +span.regex-class-initial-hyphen { + color: Teal; +} +span.regex-class-character { + color: Tan; +} +span.regex-class-octal { + color: SteelBlue; +} +span.regex-class-hex { + color: SpringGreen; +} +span.regex-class-unicode-escape { + color: SlateGray; +} +span.regex-class-ascii-control { + color: SlateBlue; +} +span.regex-class-extra-escaped { + color: SkyBlue; +} +span.regex-class-escaped-special { + color: CornflowerBlue; +} + +/*///////////////////////////////*/ +span.class-special-escape-begin-range, span.class-special-escape-end-range { + color: Brown; +} +span.regex-unicode-class-inside-begin-range, span.regex-unicode-class-inside-end-range { + color: Silver; +} +span.regex-class-initial-hyphen-begin-range, span.regex-class-initial-hyphen-end-range { + color: SeaGreen; +} +span.regex-class-character-begin-range, span.regex-class-character-end-range { + color: SandyBrown; +} +span.regex-class-octal-begin-range, span.regex-class-octal-end-range { + color: Salmon; +} +span.regex-class-hex-begin-range, span.regex-class-hex-end-range { + color: SaddleBrown; +} +span.regex-class-unicode-escape-begin-range, span.regex-class-unicode-escape-end-range { + color: RoyalBlue; +} +span.regex-class-ascii-control-begin-range, span.regex-class-ascii-control-end-range { + color: RosyBrown; +} +span.regex-class-extra-escaped-begin-range, span.regex-class-extra-escaped-end-range { + color: Orange; +} +span.regex-class-escaped-special-begin-range, span.regex-class-escaped-special-end-range { + color: DarkKhaki; +} + + +/*///////////////////////////////*/ +/* Outside character classes */ +span.regex-special-escape { + color: Chocolate; +} +span.regex-escaped-special { + color: Orange; +} +span.regex-alternator { + color: darkpink; +} +span.regex-unicode-class-outside { + color: Green; +} +span.regex-octal { + color: MediumVioletRed; +} +span.regex-ascii { + color: MediumTurquoise; +} +span.regex-hex { + color: MediumSpringGreen; +} +span.regex-unicode-escape { + color:pink; +} +span.regex-ascii-control { + color: MediumSlateBlue; +} +span.regex-extra-escaped { + color: MediumSeaGreen; +} +span.regex-quantifier-escape { + color: Azure; +} +span.regex-quantifiers { + color: MediumPurple; +} +span.regex-repetition { + color: MediumOrchid; +} +span.regex-literal-begin, span.regex-literal-end { + color: MediumBlue; +} +span.regex-character { + color: Navy; +} + +/*///////////////////////////////*/ +/* Literals/Surrounding characters */ +span.regex-flags { + color: Green; +} + +/*///////////////////////////////*/ +/* Optional outside character class features*/ +span.regex-empty-class { + color: Lime; +} +span.regex-named-backreference { + color: LightSlateGray; +} +span.regex-free-spacing-mode { + background-color: LightSeaGreen; +} +span.regex-mode-modifier { + color: LightSalmon; +} +span.regex-comment-pattern { + color: LightGreen; +} +span.regex-capturing-group, span.regex-ending-capturing-group { + color: LightGray; +} +span.regex-named-capturing-group, span.regex-ending-named-capturing-group { + color: LightCoral; +} +span.regex-group, span.regex-ending-group { + color: LawnGreen; +} + + +span.regex-capturing-group1-1, span.regex-ending-capturing-group1-1 { + background-color: red; +} +span.regex-capturing-group1-2, span.regex-ending-capturing-group1-2 { + background-color: orange; +} +span.regex-capturing-group2-1, span.regex-ending-capturing-group2-1 { + background-color: yellow; +} +span.regex-capturing-group2-2, span.regex-ending-capturing-group2-2 { + background-color: green; +} + +/*///////////////////////////////*/ +/* Closing parentheses without opening, etc. */ +span.regex-bad-character, span.regex-bad-sequence { + color: red; +} + +/* Used if "uniform" inner_group_mode is used */ +span.regex-group-1-1 { + background-color: blue; +} +span.regex-group-1-2 { + background-color: green; +} +span.regex-group-2-1 { + background-color: pink; +} +span.regex-group-2-2 { + background-color: yellow; +} diff --git a/gulliver/js/codemirror/contrib/regex/css/regexcolors.css b/gulliver/js/codemirror/contrib/regex/css/regexcolors.css new file mode 100755 index 000000000..49ae6e91d --- /dev/null +++ b/gulliver/js/codemirror/contrib/regex/css/regexcolors.css @@ -0,0 +1,214 @@ +/*///////////////////////////////*/ +html { + cursor: text; +} +.editbox { + margin: .4em; + padding: 0; + font-family: monospace; + font-size: 10pt; + color: black; +} +.editbox p { + margin: 0; +} + +html, body { +background: #555555 !important; +} + +/*///////////////////////////////*/ +/* Inside character classes */ +span.regex-class-special-escape { + color: Coral; +} +span.regex-class-begin, span.regex-class-end { + color: YellowGreen; +} +span.regex-class-negator { + color: Wheat; +} +span.regex-class-range-hyphen { + color: Turquoise; +} +span.regex-class-final-hyphen { + color: Violet; +} + +/*///////////////////////////////*/ +/* Inside character classes (suffixable by -begin-range or -end-range if beginning or ending a range) */ +span.regex-unicode-class-inside { + color: Tomato; +} +span.regex-class-initial-hyphen { + color: Teal; +} +span.regex-class-character { + color: Tan; +} +span.regex-class-octal { + color: SteelBlue; +} +span.regex-class-hex { + color: SpringGreen; +} +span.regex-class-unicode-escape { + color: LightGray; +} +span.regex-class-ascii-control { + color: SlateBlue; +} +span.regex-class-extra-escaped { + color: SkyBlue; +} +span.regex-class-escaped-special { + color: CornflowerBlue; +} + +/*///////////////////////////////*/ +span.class-special-escape-begin-range, span.class-special-escape-end-range { + color: Brown; +} +span.regex-unicode-class-inside-begin-range, span.regex-unicode-class-inside-end-range { + color: Silver; +} +span.regex-class-initial-hyphen-begin-range, span.regex-class-initial-hyphen-end-range { + color: SeaGreen; +} +span.regex-class-character-begin-range, span.regex-class-character-end-range { + color: SandyBrown; +} +span.regex-class-octal-begin-range, span.regex-class-octal-end-range { + color: Salmon; +} +span.regex-class-hex-begin-range, span.regex-class-hex-end-range { + color: Tan; +} +span.regex-class-unicode-escape-begin-range, span.regex-class-unicode-escape-end-range { + color: LightBlue; +} +span.regex-class-ascii-control-begin-range, span.regex-class-ascii-control-end-range { + color: RosyBrown; +} +span.regex-class-extra-escaped-begin-range, span.regex-class-extra-escaped-end-range { + color: Orange; +} +span.regex-class-escaped-special-begin-range, span.regex-class-escaped-special-end-range { + color: DarkKhaki; +} + + +/*///////////////////////////////*/ +/* Outside character classes */ +span.regex-special-escape { + color: Chocolate; +} +span.regex-escaped-special { + color: Orange; +} +span.regex-alternator { + color: BurlyWood; +} +span.regex-unicode-class-outside { + color: Gold; +} +span.regex-octal { + color: MediumVioletRed; +} +span.regex-ascii { + color: MediumTurquoise; +} +span.regex-hex { + color: MediumSpringGreen; +} +span.regex-unicode-escape { + color:pink; +} +span.regex-ascii-control { + color: MediumSlateBlue; +} +span.regex-extra-escaped { + color: MediumSeaGreen; +} +span.regex-quantifier-escape { + color: Azure; +} +span.regex-quantifiers { + color: MediumPurple; +} +span.regex-repetition { + color: MediumOrchid; +} +span.regex-literal-begin, span.regex-literal-end { + color: MediumBlue; +} +span.regex-character { + color: #FFFFAA; +} + +/*///////////////////////////////*/ +/* Literals/Surrounding characters */ +span.regex-flags { + color: LimeGreen; +} + +/*///////////////////////////////*/ +/* Optional outside character class features*/ +span.regex-empty-class { + color: Lime; +} +span.regex-named-backreference { + color: LightSlateGray; +} +span.regex-free-spacing-mode { + background-color: LightSeaGreen; +} +span.regex-mode-modifier { + color: LightSalmon; +} +span.regex-comment-pattern { + color: LightGreen; +} +span.regex-capturing-group, span.regex-ending-capturing-group { + color: LightGray; +} +span.regex-named-capturing-group, span.regex-ending-named-capturing-group { + color: LightCoral; +} +span.regex-group, span.regex-ending-group { + color: LawnGreen; +} + + +span.regex-capturing-group1-1, span.regex-ending-capturing-group1-1 { + background-color: red; +} +span.regex-capturing-group1-2, span.regex-ending-capturing-group1-2 { + background-color: orange; +} +span.regex-capturing-group2-1, span.regex-ending-capturing-group2-1 { + background-color: yellow; +} +span.regex-capturing-group2-2, span.regex-ending-capturing-group2-2 { + background-color: green; +} + +/*///////////////////////////////*/ +/* Closing parentheses without opening, etc. */ +span.regex-bad-character, span.regex-bad-sequence { + color: red; +} + +/* Used if "uniform" inner_group_mode is used */ +span.regex-group-1-1 { + color: lightblue; +} +span.regex-group-1-2 { + color: lightgreen; +} +span.regex-group-2-1 { + color: pink; +} +span.regex-group-2-2 { + color: yellow; +} diff --git a/gulliver/js/codemirror/contrib/regex/index.html b/gulliver/js/codemirror/contrib/regex/index.html new file mode 100755 index 000000000..bbe46dab5 --- /dev/null +++ b/gulliver/js/codemirror/contrib/regex/index.html @@ -0,0 +1,114 @@ + + + +CodeMirror Regex Highlighting + + + + + +
+

CodeMirror Regex Code Editor Demonstration

+

The Regex parser for CodeMirror allows syntax coloring on regular expressions with some beginning customizability by + Regex flavor/language. For integrating styling of regular expression literals into JavaScript syntax highlighting, see this + JavaScript+Regex Demo.

+

Styling ability is fine-grained, so any token should be distinctly stylable if so desired. Parenthetical groups can + be styled with the same styles for inner content, and the script also enables styling by nesting depth and sequence, + including by imposing a limit such that styles will alternate.

+

Information can also be passed on (especially when the parseregex-unicode.js file is included) for use in CodeMirror's + activeTokens argument such as demonstrated below by tooltips which show which characters are present in a given + range or Unicode class.

+

Note that this editor does not support free-spacing mode, so it is not recommended to use multiple lines for input, but + for demonstration purposes, multiple lines are shown.

+ + +
+ + diff --git a/gulliver/js/codemirror/contrib/regex/js-regex.html b/gulliver/js/codemirror/contrib/regex/js-regex.html new file mode 100755 index 000000000..f3071c4a4 --- /dev/null +++ b/gulliver/js/codemirror/contrib/regex/js-regex.html @@ -0,0 +1,118 @@ + + + +CodeMirror Regex Highlighting + + + + + +
+

CodeMirror JavaScript-Integrated Regex Code Editor Demonstration

+

This demonstrates a parser in the regex folder which wraps the regular CodeMirror JavaScript editor and adds syntax coloring to + regular expression literals in JavaScript.

+ + +

While the above styles by depth or sequence no matter the grouping type, this parser also allows styling distinctly by grouping type (capturing, named, non-capturing), while also still allowing alternating of colors within a type.

+ +

One may also simply turn off the styling of content inside groups, allowing only individual tokens to be styled per the stylesheet (though the parentheses tokens themselves can still indicate depth or sequence):

+ +
+ + diff --git a/gulliver/js/codemirror/contrib/regex/js/parsejavascript_and_regex.js b/gulliver/js/codemirror/contrib/regex/js/parsejavascript_and_regex.js new file mode 100755 index 000000000..6a63d0d98 --- /dev/null +++ b/gulliver/js/codemirror/contrib/regex/js/parsejavascript_and_regex.js @@ -0,0 +1,91 @@ +// See the dependencies parsejavascript.js and parseregex.js (optionally with parseregex-unicode.js) for options + +var JSAndRegexParser = Editor.Parser = (function() { + // Parser + var run = function () {}, + regexParser, jsParser, lastRegexSrc, + regexPG = {}, jsPG = {}; + + function simpleStream (s) { + var str = s, pos = 0; + return { + next : function () { + if (pos >= str.length) { + throw StopIteration; + } + return str.charAt(pos++); + } + }; + } + + function regex () { + var token; + try { + token = regexParser.next(); + } + catch(e) { + _setState(js); + return js(); + } + _setState(regex); + return token; + } + function js () { + var token = jsParser.next(); + if (token.type === 'regexp') { + lastRegexSrc = stringStream(simpleStream(token.content)); + regexParser = RegexParser.make(lastRegexSrc); + return regex(); + } + return token; + } + + function _setState (func) { + run = func; + } + + function parseJSAndRegex (stream, basecolumn) { + JSParser.configure(jsPG); + RegexParser.configure(regexPG); + jsParser = JSParser.make(stream, basecolumn); + _setState(js); + + var iter = { + next: function() { + return run(stream); + }, + copy: function() { + var _run = run, _lastRegexSrc = lastRegexSrc, + _jsParser = jsParser.copy(), + _regexParser = regexParser && regexParser.copy(); + + return function (_stream) { + stream = _stream; + jsParser = _jsParser(_stream); + regexParser = _regexParser && _regexParser(_lastRegexSrc); + run = _run; + return iter; + }; + } + }; + return iter; + } + + // Parser object + return { + make: parseJSAndRegex, + configure: function (parserConfig) { + for (var opt in parserConfig) { + if ((/^regex_/).test(opt)) { + regexPG[opt.replace(/^regex_/, '')] = parserConfig[opt]; + } + else { // Doesn't need a js- prefix, but we'll strip if it does + jsPG[opt.replace(/^js_/, '')] = parserConfig[opt]; + } + } + regexPG.flavor = regexPG.flavor || 'ecma-262-ed3'; // Allow ed5, etc. if specified + regexPG.literal = true; // This is only for literals, since can't easily detect whether will be used for RegExp + regexPG.literal_initial = '/'; // Ensure it's always this for JavaScript regex literals + } + }; +})(); diff --git a/gulliver/js/codemirror/contrib/regex/js/parseregex-unicode.js b/gulliver/js/codemirror/contrib/regex/js/parseregex-unicode.js new file mode 100755 index 000000000..583a4f195 --- /dev/null +++ b/gulliver/js/codemirror/contrib/regex/js/parseregex-unicode.js @@ -0,0 +1,284 @@ + /* + * Note: To include Unicode validation, you must include your CodeMirror parserfile option in this sequence: + * parserfile: ["parseregex.js", "parseregex-unicode.js"] +*/ +(function () { + + +// Fix: Add non-BMP code points + +var UnicodeCategories = { + C: "0000-001F007F-009F00AD03780379037F-0383038B038D03A20526-05300557055805600588058B-059005C8-05CF05EB-05EF05F5-0605061C061D0620065F06DD070E070F074B074C07B2-07BF07FB-07FF082E082F083F-08FF093A093B094F095609570973-097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF00AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B72-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D290D3A-0D3C0D450D490D4E-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EDE-0EFF0F480F6D-0F700F8C-0F8F0F980FBD0FCD0FD9-0FFF10C6-10CF10FD-10FF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B-135E137D-137F139A-139F13F5-13FF169D-169F16F1-16FF170D1715-171F1737-173F1754-175F176D17711774-177F17B417B517DE17DF17EA-17EF17FA-17FF180F181A-181F1878-187F18AB-18AF18F6-18FF191D-191F192C-192F193C-193F1941-1943196E196F1975-197F19AC-19AF19CA-19CF19DB-19DD1A1C1A1D1A5F1A7D1A7E1A8A-1A8F1A9A-1A9F1AAE-1AFF1B4C-1B4F1B7D-1B7F1BAB-1BAD1BBA-1BFF1C38-1C3A1C4A-1C4C1C80-1CCF1CF3-1CFF1DE7-1DFC1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF200B-200F202A-202E2060-206F20722073208F2095-209F20B9-20CF20F1-20FF218A-218F23E9-23FF2427-243F244B-245F26CE26E226E4-26E727002705270A270B2728274C274E2753-2755275F27602795-279727B027BF27CB27CD-27CF2B4D-2B4F2B5A-2BFF2C2F2C5F2CF2-2CF82D26-2D2F2D66-2D6E2D70-2D7F2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E32-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31B8-31BF31E4-31EF321F32FF4DB6-4DBF9FCC-9FFFA48D-A48FA4C7-A4CFA62C-A63FA660A661A674-A67BA698-A69FA6F8-A6FFA78D-A7FAA82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAE0-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-F8FFFA2EFA2FFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBB2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFD-FF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFFBFFFEFFFF", + Cc: "0000-001F007F-009F", + Cf: "00AD0600-060306DD070F17B417B5200B-200F202A-202E2060-2064206A-206FFEFFFFF9-FFFB", + Co: "E000-F8FF", + Cs: "D800-DFFF", + Cn: "03780379037F-0383038B038D03A20526-05300557055805600588058B-059005C8-05CF05EB-05EF05F5-05FF06040605061C061D0620065F070E074B074C07B2-07BF07FB-07FF082E082F083F-08FF093A093B094F095609570973-097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF00AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B72-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D290D3A-0D3C0D450D490D4E-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EDE-0EFF0F480F6D-0F700F8C-0F8F0F980FBD0FCD0FD9-0FFF10C6-10CF10FD-10FF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B-135E137D-137F139A-139F13F5-13FF169D-169F16F1-16FF170D1715-171F1737-173F1754-175F176D17711774-177F17DE17DF17EA-17EF17FA-17FF180F181A-181F1878-187F18AB-18AF18F6-18FF191D-191F192C-192F193C-193F1941-1943196E196F1975-197F19AC-19AF19CA-19CF19DB-19DD1A1C1A1D1A5F1A7D1A7E1A8A-1A8F1A9A-1A9F1AAE-1AFF1B4C-1B4F1B7D-1B7F1BAB-1BAD1BBA-1BFF1C38-1C3A1C4A-1C4C1C80-1CCF1CF3-1CFF1DE7-1DFC1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF2065-206920722073208F2095-209F20B9-20CF20F1-20FF218A-218F23E9-23FF2427-243F244B-245F26CE26E226E4-26E727002705270A270B2728274C274E2753-2755275F27602795-279727B027BF27CB27CD-27CF2B4D-2B4F2B5A-2BFF2C2F2C5F2CF2-2CF82D26-2D2F2D66-2D6E2D70-2D7F2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E32-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31B8-31BF31E4-31EF321F32FF4DB6-4DBF9FCC-9FFFA48D-A48FA4C7-A4CFA62C-A63FA660A661A674-A67BA698-A69FA6F8-A6FFA78D-A7FAA82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAE0-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-D7FFFA2EFA2FFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBB2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFDFEFEFF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFF8FFFEFFFF", + L: "0041-005A0061-007A00AA00B500BA00C0-00D600D8-00F600F8-02C102C6-02D102E0-02E402EC02EE0370-037403760377037A-037D03860388-038A038C038E-03A103A3-03F503F7-0481048A-05250531-055605590561-058705D0-05EA05F0-05F20621-064A066E066F0671-06D306D506E506E606EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA07F407F507FA0800-0815081A082408280904-0939093D09500958-0961097109720979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E460E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EC60EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10A0-10C510D0-10FA10FC1100-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317D717DC1820-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541AA71B05-1B331B45-1B4B1B83-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C7D1CE9-1CEC1CEE-1CF11D00-1DBF1E00-1F151F18-1F1D1F20-1F451F48-1F4D1F50-1F571F591F5B1F5D1F5F-1F7D1F80-1FB41FB6-1FBC1FBE1FC2-1FC41FC6-1FCC1FD0-1FD31FD6-1FDB1FE0-1FEC1FF2-1FF41FF6-1FFC2071207F2090-209421022107210A-211321152119-211D212421262128212A-212D212F-2139213C-213F2145-2149214E218321842C00-2C2E2C30-2C5E2C60-2CE42CEB-2CEE2D00-2D252D30-2D652D6F2D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE2E2F300530063031-3035303B303C3041-3096309D-309F30A1-30FA30FC-30FF3105-312D3131-318E31A0-31B731F0-31FF3400-4DB54E00-9FCBA000-A48CA4D0-A4FDA500-A60CA610-A61FA62AA62BA640-A65FA662-A66EA67F-A697A6A0-A6E5A717-A71FA722-A788A78BA78CA7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2A9CFAA00-AA28AA40-AA42AA44-AA4BAA60-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADB-AADDABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA2DFA30-FA6DFA70-FAD9FB00-FB06FB13-FB17FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF21-FF3AFF41-FF5AFF66-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC", + Ll: "0061-007A00AA00B500BA00DF-00F600F8-00FF01010103010501070109010B010D010F01110113011501170119011B011D011F01210123012501270129012B012D012F01310133013501370138013A013C013E014001420144014601480149014B014D014F01510153015501570159015B015D015F01610163016501670169016B016D016F0171017301750177017A017C017E-0180018301850188018C018D019201950199-019B019E01A101A301A501A801AA01AB01AD01B001B401B601B901BA01BD-01BF01C601C901CC01CE01D001D201D401D601D801DA01DC01DD01DF01E101E301E501E701E901EB01ED01EF01F001F301F501F901FB01FD01FF02010203020502070209020B020D020F02110213021502170219021B021D021F02210223022502270229022B022D022F02310233-0239023C023F0240024202470249024B024D024F-02930295-02AF037103730377037B-037D039003AC-03CE03D003D103D5-03D703D903DB03DD03DF03E103E303E503E703E903EB03ED03EF-03F303F503F803FB03FC0430-045F04610463046504670469046B046D046F04710473047504770479047B047D047F0481048B048D048F04910493049504970499049B049D049F04A104A304A504A704A904AB04AD04AF04B104B304B504B704B904BB04BD04BF04C204C404C604C804CA04CC04CE04CF04D104D304D504D704D904DB04DD04DF04E104E304E504E704E904EB04ED04EF04F104F304F504F704F904FB04FD04FF05010503050505070509050B050D050F05110513051505170519051B051D051F0521052305250561-05871D00-1D2B1D62-1D771D79-1D9A1E011E031E051E071E091E0B1E0D1E0F1E111E131E151E171E191E1B1E1D1E1F1E211E231E251E271E291E2B1E2D1E2F1E311E331E351E371E391E3B1E3D1E3F1E411E431E451E471E491E4B1E4D1E4F1E511E531E551E571E591E5B1E5D1E5F1E611E631E651E671E691E6B1E6D1E6F1E711E731E751E771E791E7B1E7D1E7F1E811E831E851E871E891E8B1E8D1E8F1E911E931E95-1E9D1E9F1EA11EA31EA51EA71EA91EAB1EAD1EAF1EB11EB31EB51EB71EB91EBB1EBD1EBF1EC11EC31EC51EC71EC91ECB1ECD1ECF1ED11ED31ED51ED71ED91EDB1EDD1EDF1EE11EE31EE51EE71EE91EEB1EED1EEF1EF11EF31EF51EF71EF91EFB1EFD1EFF-1F071F10-1F151F20-1F271F30-1F371F40-1F451F50-1F571F60-1F671F70-1F7D1F80-1F871F90-1F971FA0-1FA71FB0-1FB41FB61FB71FBE1FC2-1FC41FC61FC71FD0-1FD31FD61FD71FE0-1FE71FF2-1FF41FF61FF7210A210E210F2113212F21342139213C213D2146-2149214E21842C30-2C5E2C612C652C662C682C6A2C6C2C712C732C742C76-2C7C2C812C832C852C872C892C8B2C8D2C8F2C912C932C952C972C992C9B2C9D2C9F2CA12CA32CA52CA72CA92CAB2CAD2CAF2CB12CB32CB52CB72CB92CBB2CBD2CBF2CC12CC32CC52CC72CC92CCB2CCD2CCF2CD12CD32CD52CD72CD92CDB2CDD2CDF2CE12CE32CE42CEC2CEE2D00-2D25A641A643A645A647A649A64BA64DA64FA651A653A655A657A659A65BA65DA65FA663A665A667A669A66BA66DA681A683A685A687A689A68BA68DA68FA691A693A695A697A723A725A727A729A72BA72DA72F-A731A733A735A737A739A73BA73DA73FA741A743A745A747A749A74BA74DA74FA751A753A755A757A759A75BA75DA75FA761A763A765A767A769A76BA76DA76FA771-A778A77AA77CA77FA781A783A785A787A78CFB00-FB06FB13-FB17FF41-FF5A", + Lu: "0041-005A00C0-00D600D8-00DE01000102010401060108010A010C010E01100112011401160118011A011C011E01200122012401260128012A012C012E01300132013401360139013B013D013F0141014301450147014A014C014E01500152015401560158015A015C015E01600162016401660168016A016C016E017001720174017601780179017B017D018101820184018601870189-018B018E-0191019301940196-0198019C019D019F01A001A201A401A601A701A901AC01AE01AF01B1-01B301B501B701B801BC01C401C701CA01CD01CF01D101D301D501D701D901DB01DE01E001E201E401E601E801EA01EC01EE01F101F401F6-01F801FA01FC01FE02000202020402060208020A020C020E02100212021402160218021A021C021E02200222022402260228022A022C022E02300232023A023B023D023E02410243-02460248024A024C024E03700372037603860388-038A038C038E038F0391-03A103A3-03AB03CF03D2-03D403D803DA03DC03DE03E003E203E403E603E803EA03EC03EE03F403F703F903FA03FD-042F04600462046404660468046A046C046E04700472047404760478047A047C047E0480048A048C048E04900492049404960498049A049C049E04A004A204A404A604A804AA04AC04AE04B004B204B404B604B804BA04BC04BE04C004C104C304C504C704C904CB04CD04D004D204D404D604D804DA04DC04DE04E004E204E404E604E804EA04EC04EE04F004F204F404F604F804FA04FC04FE05000502050405060508050A050C050E05100512051405160518051A051C051E0520052205240531-055610A0-10C51E001E021E041E061E081E0A1E0C1E0E1E101E121E141E161E181E1A1E1C1E1E1E201E221E241E261E281E2A1E2C1E2E1E301E321E341E361E381E3A1E3C1E3E1E401E421E441E461E481E4A1E4C1E4E1E501E521E541E561E581E5A1E5C1E5E1E601E621E641E661E681E6A1E6C1E6E1E701E721E741E761E781E7A1E7C1E7E1E801E821E841E861E881E8A1E8C1E8E1E901E921E941E9E1EA01EA21EA41EA61EA81EAA1EAC1EAE1EB01EB21EB41EB61EB81EBA1EBC1EBE1EC01EC21EC41EC61EC81ECA1ECC1ECE1ED01ED21ED41ED61ED81EDA1EDC1EDE1EE01EE21EE41EE61EE81EEA1EEC1EEE1EF01EF21EF41EF61EF81EFA1EFC1EFE1F08-1F0F1F18-1F1D1F28-1F2F1F38-1F3F1F48-1F4D1F591F5B1F5D1F5F1F68-1F6F1FB8-1FBB1FC8-1FCB1FD8-1FDB1FE8-1FEC1FF8-1FFB21022107210B-210D2110-211221152119-211D212421262128212A-212D2130-2133213E213F214521832C00-2C2E2C602C62-2C642C672C692C6B2C6D-2C702C722C752C7E-2C802C822C842C862C882C8A2C8C2C8E2C902C922C942C962C982C9A2C9C2C9E2CA02CA22CA42CA62CA82CAA2CAC2CAE2CB02CB22CB42CB62CB82CBA2CBC2CBE2CC02CC22CC42CC62CC82CCA2CCC2CCE2CD02CD22CD42CD62CD82CDA2CDC2CDE2CE02CE22CEB2CEDA640A642A644A646A648A64AA64CA64EA650A652A654A656A658A65AA65CA65EA662A664A666A668A66AA66CA680A682A684A686A688A68AA68CA68EA690A692A694A696A722A724A726A728A72AA72CA72EA732A734A736A738A73AA73CA73EA740A742A744A746A748A74AA74CA74EA750A752A754A756A758A75AA75CA75EA760A762A764A766A768A76AA76CA76EA779A77BA77DA77EA780A782A784A786A78BFF21-FF3A", + Lt: "01C501C801CB01F21F88-1F8F1F98-1F9F1FA8-1FAF1FBC1FCC1FFC", + Lm: "02B0-02C102C6-02D102E0-02E402EC02EE0374037A0559064006E506E607F407F507FA081A0824082809710E460EC610FC17D718431AA71C78-1C7D1D2C-1D611D781D9B-1DBF2071207F2090-20942C7D2D6F2E2F30053031-3035303B309D309E30FC-30FEA015A4F8-A4FDA60CA67FA717-A71FA770A788A9CFAA70AADDFF70FF9EFF9F", + Lo: "01BB01C0-01C3029405D0-05EA05F0-05F20621-063F0641-064A066E066F0671-06D306D506EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA0800-08150904-0939093D09500958-096109720979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E450E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10D0-10FA1100-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317DC1820-18421844-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541B05-1B331B45-1B4B1B83-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C771CE9-1CEC1CEE-1CF12135-21382D30-2D652D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE3006303C3041-3096309F30A1-30FA30FF3105-312D3131-318E31A0-31B731F0-31FF3400-4DB54E00-9FCBA000-A014A016-A48CA4D0-A4F7A500-A60BA610-A61FA62AA62BA66EA6A0-A6E5A7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2AA00-AA28AA40-AA42AA44-AA4BAA60-AA6FAA71-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADBAADCABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA2DFA30-FA6DFA70-FAD9FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF66-FF6FFF71-FF9DFFA0-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC", + M: "0300-036F0483-04890591-05BD05BF05C105C205C405C505C70610-061A064B-065E067006D6-06DC06DE-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0900-0903093C093E-094E0951-0955096209630981-098309BC09BE-09C409C709C809CB-09CD09D709E209E30A01-0A030A3C0A3E-0A420A470A480A4B-0A4D0A510A700A710A750A81-0A830ABC0ABE-0AC50AC7-0AC90ACB-0ACD0AE20AE30B01-0B030B3C0B3E-0B440B470B480B4B-0B4D0B560B570B620B630B820BBE-0BC20BC6-0BC80BCA-0BCD0BD70C01-0C030C3E-0C440C46-0C480C4A-0C4D0C550C560C620C630C820C830CBC0CBE-0CC40CC6-0CC80CCA-0CCD0CD50CD60CE20CE30D020D030D3E-0D440D46-0D480D4A-0D4D0D570D620D630D820D830DCA0DCF-0DD40DD60DD8-0DDF0DF20DF30E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F3E0F3F0F71-0F840F860F870F90-0F970F99-0FBC0FC6102B-103E1056-1059105E-10601062-10641067-106D1071-10741082-108D108F109A-109D135F1712-17141732-1734175217531772177317B6-17D317DD180B-180D18A91920-192B1930-193B19B0-19C019C819C91A17-1A1B1A55-1A5E1A60-1A7C1A7F1B00-1B041B34-1B441B6B-1B731B80-1B821BA1-1BAA1C24-1C371CD0-1CD21CD4-1CE81CED1CF21DC0-1DE61DFD-1DFF20D0-20F02CEF-2CF12DE0-2DFF302A-302F3099309AA66F-A672A67CA67DA6F0A6F1A802A806A80BA823-A827A880A881A8B4-A8C4A8E0-A8F1A926-A92DA947-A953A980-A983A9B3-A9C0AA29-AA36AA43AA4CAA4DAA7BAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1ABE3-ABEAABECABEDFB1EFE00-FE0FFE20-FE26", + Mn: "0300-036F0483-04870591-05BD05BF05C105C205C405C505C70610-061A064B-065E067006D6-06DC06DF-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0900-0902093C0941-0948094D0951-095509620963098109BC09C1-09C409CD09E209E30A010A020A3C0A410A420A470A480A4B-0A4D0A510A700A710A750A810A820ABC0AC1-0AC50AC70AC80ACD0AE20AE30B010B3C0B3F0B41-0B440B4D0B560B620B630B820BC00BCD0C3E-0C400C46-0C480C4A-0C4D0C550C560C620C630CBC0CBF0CC60CCC0CCD0CE20CE30D41-0D440D4D0D620D630DCA0DD2-0DD40DD60E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F71-0F7E0F80-0F840F860F870F90-0F970F99-0FBC0FC6102D-10301032-10371039103A103D103E10581059105E-10601071-1074108210851086108D109D135F1712-17141732-1734175217531772177317B7-17BD17C617C9-17D317DD180B-180D18A91920-19221927192819321939-193B1A171A181A561A58-1A5E1A601A621A65-1A6C1A73-1A7C1A7F1B00-1B031B341B36-1B3A1B3C1B421B6B-1B731B801B811BA2-1BA51BA81BA91C2C-1C331C361C371CD0-1CD21CD4-1CE01CE2-1CE81CED1DC0-1DE61DFD-1DFF20D0-20DC20E120E5-20F02CEF-2CF12DE0-2DFF302A-302F3099309AA66FA67CA67DA6F0A6F1A802A806A80BA825A826A8C4A8E0-A8F1A926-A92DA947-A951A980-A982A9B3A9B6-A9B9A9BCAA29-AA2EAA31AA32AA35AA36AA43AA4CAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1ABE5ABE8ABEDFB1EFE00-FE0FFE20-FE26", + Mc: "0903093E-09400949-094C094E0982098309BE-09C009C709C809CB09CC09D70A030A3E-0A400A830ABE-0AC00AC90ACB0ACC0B020B030B3E0B400B470B480B4B0B4C0B570BBE0BBF0BC10BC20BC6-0BC80BCA-0BCC0BD70C01-0C030C41-0C440C820C830CBE0CC0-0CC40CC70CC80CCA0CCB0CD50CD60D020D030D3E-0D400D46-0D480D4A-0D4C0D570D820D830DCF-0DD10DD8-0DDF0DF20DF30F3E0F3F0F7F102B102C10311038103B103C105610571062-10641067-106D108310841087-108C108F109A-109C17B617BE-17C517C717C81923-19261929-192B193019311933-193819B0-19C019C819C91A19-1A1B1A551A571A611A631A641A6D-1A721B041B351B3B1B3D-1B411B431B441B821BA11BA61BA71BAA1C24-1C2B1C341C351CE11CF2A823A824A827A880A881A8B4-A8C3A952A953A983A9B4A9B5A9BAA9BBA9BD-A9C0AA2FAA30AA33AA34AA4DAA7BABE3ABE4ABE6ABE7ABE9ABEAABEC", + Me: "0488048906DE20DD-20E020E2-20E4A670-A672", + N: "0030-003900B200B300B900BC-00BE0660-066906F0-06F907C0-07C90966-096F09E6-09EF09F4-09F90A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BF20C66-0C6F0C78-0C7E0CE6-0CEF0D66-0D750E50-0E590ED0-0ED90F20-0F331040-10491090-10991369-137C16EE-16F017E0-17E917F0-17F91810-18191946-194F19D0-19DA1A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C5920702074-20792080-20892150-21822185-21892460-249B24EA-24FF2776-27932CFD30073021-30293038-303A3192-31953220-32293251-325F3280-328932B1-32BFA620-A629A6E6-A6EFA830-A835A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19", + Nd: "0030-00390660-066906F0-06F907C0-07C90966-096F09E6-09EF0A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BEF0C66-0C6F0CE6-0CEF0D66-0D6F0E50-0E590ED0-0ED90F20-0F291040-10491090-109917E0-17E91810-18191946-194F19D0-19DA1A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C59A620-A629A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19", + Nl: "16EE-16F02160-21822185-218830073021-30293038-303AA6E6-A6EF", + No: "00B200B300B900BC-00BE09F4-09F90BF0-0BF20C78-0C7E0D70-0D750F2A-0F331369-137C17F0-17F920702074-20792080-20892150-215F21892460-249B24EA-24FF2776-27932CFD3192-31953220-32293251-325F3280-328932B1-32BFA830-A835", + P: "0021-00230025-002A002C-002F003A003B003F0040005B-005D005F007B007D00A100AB00B700BB00BF037E0387055A-055F0589058A05BE05C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E0964096509700DF40E4F0E5A0E5B0F04-0F120F3A-0F3D0F850FD0-0FD4104A-104F10FB1361-13681400166D166E169B169C16EB-16ED1735173617D4-17D617D8-17DA1800-180A1944194519DE19DF1A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601C3B-1C3F1C7E1C7F1CD32010-20272030-20432045-20512053-205E207D207E208D208E2329232A2768-277527C527C627E6-27EF2983-299829D8-29DB29FC29FD2CF9-2CFC2CFE2CFF2E00-2E2E2E302E313001-30033008-30113014-301F3030303D30A030FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFABEBFD3EFD3FFE10-FE19FE30-FE52FE54-FE61FE63FE68FE6AFE6BFF01-FF03FF05-FF0AFF0C-FF0FFF1AFF1BFF1FFF20FF3B-FF3DFF3FFF5BFF5DFF5F-FF65", + Pd: "002D058A05BE140018062010-20152E172E1A301C303030A0FE31FE32FE58FE63FF0D", + Ps: "0028005B007B0F3A0F3C169B201A201E2045207D208D23292768276A276C276E27702772277427C527E627E827EA27EC27EE2983298529872989298B298D298F299129932995299729D829DA29FC2E222E242E262E283008300A300C300E3010301430163018301A301DFD3EFE17FE35FE37FE39FE3BFE3DFE3FFE41FE43FE47FE59FE5BFE5DFF08FF3BFF5BFF5FFF62", + Pe: "0029005D007D0F3B0F3D169C2046207E208E232A2769276B276D276F27712773277527C627E727E927EB27ED27EF298429862988298A298C298E2990299229942996299829D929DB29FD2E232E252E272E293009300B300D300F3011301530173019301B301E301FFD3FFE18FE36FE38FE3AFE3CFE3EFE40FE42FE44FE48FE5AFE5CFE5EFF09FF3DFF5DFF60FF63", + Pi: "00AB2018201B201C201F20392E022E042E092E0C2E1C2E20", + Pf: "00BB2019201D203A2E032E052E0A2E0D2E1D2E21", + Pc: "005F203F20402054FE33FE34FE4D-FE4FFF3F", + Po: "0021-00230025-0027002A002C002E002F003A003B003F0040005C00A100B700BF037E0387055A-055F058905C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E0964096509700DF40E4F0E5A0E5B0F04-0F120F850FD0-0FD4104A-104F10FB1361-1368166D166E16EB-16ED1735173617D4-17D617D8-17DA1800-18051807-180A1944194519DE19DF1A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601C3B-1C3F1C7E1C7F1CD3201620172020-20272030-2038203B-203E2041-20432047-205120532055-205E2CF9-2CFC2CFE2CFF2E002E012E06-2E082E0B2E0E-2E162E182E192E1B2E1E2E1F2E2A-2E2E2E302E313001-3003303D30FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFABEBFE10-FE16FE19FE30FE45FE46FE49-FE4CFE50-FE52FE54-FE57FE5F-FE61FE68FE6AFE6BFF01-FF03FF05-FF07FF0AFF0CFF0EFF0FFF1AFF1BFF1FFF20FF3CFF61FF64FF65", + S: "0024002B003C-003E005E0060007C007E00A2-00A900AC00AE-00B100B400B600B800D700F702C2-02C502D2-02DF02E5-02EB02ED02EF-02FF03750384038503F604820606-0608060B060E060F06E906FD06FE07F609F209F309FA09FB0AF10B700BF3-0BFA0C7F0CF10CF20D790E3F0F01-0F030F13-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F13601390-139917DB194019E0-19FF1B61-1B6A1B74-1B7C1FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE20442052207A-207C208A-208C20A0-20B8210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B2140-2144214A-214D214F2190-2328232B-23E82400-24262440-244A249C-24E92500-26CD26CF-26E126E326E8-26FF2701-27042706-2709270C-27272729-274B274D274F-27522756-275E2761-276727942798-27AF27B1-27BE27C0-27C427C7-27CA27CC27D0-27E527F0-29822999-29D729DC-29FB29FE-2B4C2B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F309B309C319031913196-319F31C0-31E33200-321E322A-32503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A700-A716A720A721A789A78AA828-A82BA836-A839AA77-AA79FB29FDFCFDFDFE62FE64-FE66FE69FF04FF0BFF1C-FF1EFF3EFF40FF5CFF5EFFE0-FFE6FFE8-FFEEFFFCFFFD", + Sm: "002B003C-003E007C007E00AC00B100D700F703F60606-060820442052207A-207C208A-208C2140-2144214B2190-2194219A219B21A021A321A621AE21CE21CF21D221D421F4-22FF2308-230B23202321237C239B-23B323DC-23E125B725C125F8-25FF266F27C0-27C427C7-27CA27CC27D0-27E527F0-27FF2900-29822999-29D729DC-29FB29FE-2AFF2B30-2B442B47-2B4CFB29FE62FE64-FE66FF0BFF1C-FF1EFF5CFF5EFFE2FFE9-FFEC", + Sc: "002400A2-00A5060B09F209F309FB0AF10BF90E3F17DB20A0-20B8A838FDFCFE69FF04FFE0FFE1FFE5FFE6", + Sk: "005E006000A800AF00B400B802C2-02C502D2-02DF02E5-02EB02ED02EF-02FF0375038403851FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE309B309CA700-A716A720A721A789A78AFF3EFF40FFE3", + So: "00A600A700A900AE00B000B60482060E060F06E906FD06FE07F609FA0B700BF3-0BF80BFA0C7F0CF10CF20D790F01-0F030F13-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F13601390-1399194019E0-19FF1B61-1B6A1B74-1B7C210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B214A214C214D214F2195-2199219C-219F21A121A221A421A521A7-21AD21AF-21CD21D021D121D321D5-21F32300-2307230C-231F2322-2328232B-237B237D-239A23B4-23DB23E2-23E82400-24262440-244A249C-24E92500-25B625B8-25C025C2-25F72600-266E2670-26CD26CF-26E126E326E8-26FF2701-27042706-2709270C-27272729-274B274D274F-27522756-275E2761-276727942798-27AF27B1-27BE2800-28FF2B00-2B2F2B452B462B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F319031913196-319F31C0-31E33200-321E322A-32503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A828-A82BA836A837A839AA77-AA79FDFDFFE4FFE8FFEDFFEEFFFCFFFD", + Z: "002000A01680180E2000-200A20282029202F205F3000", + Zs: "002000A01680180E2000-200A202F205F3000", + Zl: "2028", + Zp: "2029" +}; + +var UnicodeBlocks = { + InBasic_Latin: "0000-007F", + InLatin_1_Supplement: "0080-00FF", + InLatin_Extended_A: "0100-017F", + InLatin_Extended_B: "0180-024F", + InIPA_Extensions: "0250-02AF", + InSpacing_Modifier_Letters: "02B0-02FF", + InCombining_Diacritical_Marks: "0300-036F", + InGreek_and_Coptic: "0370-03FF", + InCyrillic: "0400-04FF", + InCyrillic_Supplement: "0500-052F", + InArmenian: "0530-058F", + InHebrew: "0590-05FF", + InArabic: "0600-06FF", + InSyriac: "0700-074F", + InArabic_Supplement: "0750-077F", + InThaana: "0780-07BF", + InNKo: "07C0-07FF", + InSamaritan: "0800-083F", + InDevanagari: "0900-097F", + InBengali: "0980-09FF", + InGurmukhi: "0A00-0A7F", + InGujarati: "0A80-0AFF", + InOriya: "0B00-0B7F", + InTamil: "0B80-0BFF", + InTelugu: "0C00-0C7F", + InKannada: "0C80-0CFF", + InMalayalam: "0D00-0D7F", + InSinhala: "0D80-0DFF", + InThai: "0E00-0E7F", + InLao: "0E80-0EFF", + InTibetan: "0F00-0FFF", + InMyanmar: "1000-109F", + InGeorgian: "10A0-10FF", + InHangul_Jamo: "1100-11FF", + InEthiopic: "1200-137F", + InEthiopic_Supplement: "1380-139F", + InCherokee: "13A0-13FF", + InUnified_Canadian_Aboriginal_Syllabics: "1400-167F", + InOgham: "1680-169F", + InRunic: "16A0-16FF", + InTagalog: "1700-171F", + InHanunoo: "1720-173F", + InBuhid: "1740-175F", + InTagbanwa: "1760-177F", + InKhmer: "1780-17FF", + InMongolian: "1800-18AF", + InUnified_Canadian_Aboriginal_Syllabics_Extended: "18B0-18FF", + InLimbu: "1900-194F", + InTai_Le: "1950-197F", + InNew_Tai_Lue: "1980-19DF", + InKhmer_Symbols: "19E0-19FF", + InBuginese: "1A00-1A1F", + InTai_Tham: "1A20-1AAF", + InBalinese: "1B00-1B7F", + InSundanese: "1B80-1BBF", + InLepcha: "1C00-1C4F", + InOl_Chiki: "1C50-1C7F", + InVedic_Extensions: "1CD0-1CFF", + InPhonetic_Extensions: "1D00-1D7F", + InPhonetic_Extensions_Supplement: "1D80-1DBF", + InCombining_Diacritical_Marks_Supplement: "1DC0-1DFF", + InLatin_Extended_Additional: "1E00-1EFF", + InGreek_Extended: "1F00-1FFF", + InGeneral_Punctuation: "2000-206F", + InSuperscripts_and_Subscripts: "2070-209F", + InCurrency_Symbols: "20A0-20CF", + InCombining_Diacritical_Marks_for_Symbols: "20D0-20FF", + InLetterlike_Symbols: "2100-214F", + InNumber_Forms: "2150-218F", + InArrows: "2190-21FF", + InMathematical_Operators: "2200-22FF", + InMiscellaneous_Technical: "2300-23FF", + InControl_Pictures: "2400-243F", + InOptical_Character_Recognition: "2440-245F", + InEnclosed_Alphanumerics: "2460-24FF", + InBox_Drawing: "2500-257F", + InBlock_Elements: "2580-259F", + InGeometric_Shapes: "25A0-25FF", + InMiscellaneous_Symbols: "2600-26FF", + InDingbats: "2700-27BF", + InMiscellaneous_Mathematical_Symbols_A: "27C0-27EF", + InSupplemental_Arrows_A: "27F0-27FF", + InBraille_Patterns: "2800-28FF", + InSupplemental_Arrows_B: "2900-297F", + InMiscellaneous_Mathematical_Symbols_B: "2980-29FF", + InSupplemental_Mathematical_Operators: "2A00-2AFF", + InMiscellaneous_Symbols_and_Arrows: "2B00-2BFF", + InGlagolitic: "2C00-2C5F", + InLatin_Extended_C: "2C60-2C7F", + InCoptic: "2C80-2CFF", + InGeorgian_Supplement: "2D00-2D2F", + InTifinagh: "2D30-2D7F", + InEthiopic_Extended: "2D80-2DDF", + InCyrillic_Extended_A: "2DE0-2DFF", + InSupplemental_Punctuation: "2E00-2E7F", + InCJK_Radicals_Supplement: "2E80-2EFF", + InKangxi_Radicals: "2F00-2FDF", + InIdeographic_Description_Characters: "2FF0-2FFF", + InCJK_Symbols_and_Punctuation: "3000-303F", + InHiragana: "3040-309F", + InKatakana: "30A0-30FF", + InBopomofo: "3100-312F", + InHangul_Compatibility_Jamo: "3130-318F", + InKanbun: "3190-319F", + InBopomofo_Extended: "31A0-31BF", + InCJK_Strokes: "31C0-31EF", + InKatakana_Phonetic_Extensions: "31F0-31FF", + InEnclosed_CJK_Letters_and_Months: "3200-32FF", + InCJK_Compatibility: "3300-33FF", + InCJK_Unified_Ideographs_Extension_A: "3400-4DBF", + InYijing_Hexagram_Symbols: "4DC0-4DFF", + InCJK_Unified_Ideographs: "4E00-9FFF", + InYi_Syllables: "A000-A48F", + InYi_Radicals: "A490-A4CF", + InLisu: "A4D0-A4FF", + InVai: "A500-A63F", + InCyrillic_Extended_B: "A640-A69F", + InBamum: "A6A0-A6FF", + InModifier_Tone_Letters: "A700-A71F", + InLatin_Extended_D: "A720-A7FF", + InSyloti_Nagri: "A800-A82F", + InCommon_Indic_Number_Forms: "A830-A83F", + InPhags_pa: "A840-A87F", + InSaurashtra: "A880-A8DF", + InDevanagari_Extended: "A8E0-A8FF", + InKayah_Li: "A900-A92F", + InRejang: "A930-A95F", + InHangul_Jamo_Extended_A: "A960-A97F", + InJavanese: "A980-A9DF", + InCham: "AA00-AA5F", + InMyanmar_Extended_A: "AA60-AA7F", + InTai_Viet: "AA80-AADF", + InMeetei_Mayek: "ABC0-ABFF", + InHangul_Syllables: "AC00-D7AF", + InHangul_Jamo_Extended_B: "D7B0-D7FF", + InHigh_Surrogates: "D800-DB7F", + InHigh_Private_Use_Surrogates: "DB80-DBFF", + InLow_Surrogates: "DC00-DFFF", + InPrivate_Use_Area: "E000-F8FF", + InCJK_Compatibility_Ideographs: "F900-FAFF", + InAlphabetic_Presentation_Forms: "FB00-FB4F", + InArabic_Presentation_Forms_A: "FB50-FDFF", + InVariation_Selectors: "FE00-FE0F", + InVertical_Forms: "FE10-FE1F", + InCombining_Half_Marks: "FE20-FE2F", + InCJK_Compatibility_Forms: "FE30-FE4F", + InSmall_Form_Variants: "FE50-FE6F", + InArabic_Presentation_Forms_B: "FE70-FEFF", + InHalfwidth_and_Fullwidth_Forms: "FF00-FFEF", + InSpecials: "FFF0-FFFF" +}; + +var UnicodeScripts = { + Common: "0000-0040005B-0060007B-00A900AB-00B900BB-00BF00D700F702B9-02DF02E5-02FF0374037E0385038705890600-0603060C061B061F06400660-066906DD0964096509700CF10CF20E3F0FD5-0FD810FB16EB-16ED173517361802180318051CD31CE11CE9-1CEC1CEE-1CF22000-200B200E-2064206A-20702074-207E2080-208E20A0-20B82100-21252127-2129212C-21312133-214D214F-215F21892190-23E82400-24262440-244A2460-26CD26CF-26E126E326E8-26FF2701-27042706-2709270C-27272729-274B274D274F-27522756-275E2761-27942798-27AF27B1-27BE27C0-27CA27CC27D0-27FF2900-2B4C2B50-2B592E00-2E312FF0-2FFB3000-300430063008-30203030-3037303C-303F309B309C30A030FB30FC3190-319F31C0-31E33220-325F327F-32CF3358-33FF4DC0-4DFFA700-A721A788-A78AA830-A839FD3EFD3FFDFDFE10-FE19FE30-FE52FE54-FE66FE68-FE6BFEFFFF01-FF20FF3B-FF40FF5B-FF65FF70FF9EFF9FFFE0-FFE6FFE8-FFEEFFF9-FFFD", + Arabic: "0606-060B060D-061A061E0621-063F0641-064A0656-065E066A-066F0671-06DC06DE-06FF0750-077FFB50-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFCFE70-FE74FE76-FEFC", + Armenian: "0531-05560559-055F0561-0587058AFB13-FB17", + Balinese: "1B00-1B4B1B50-1B7C", + Bamum: "A6A0-A6F7", + Bengali: "0981-09830985-098C098F09900993-09A809AA-09B009B209B6-09B909BC-09C409C709C809CB-09CE09D709DC09DD09DF-09E309E6-09FB", + Bopomofo: "3105-312D31A0-31B7", + Braille: "2800-28FF", + Buginese: "1A00-1A1B1A1E1A1F", + Buhid: "1740-1753", + Canadian_Aboriginal: "1400-167F18B0-18F5", + Cham: "AA00-AA36AA40-AA4DAA50-AA59AA5C-AA5F", + Cherokee: "13A0-13F4", + Coptic: "03E2-03EF2C80-2CF12CF9-2CFF", + Cyrillic: "0400-04840487-05251D2B1D782DE0-2DFFA640-A65FA662-A673A67C-A697", + Devanagari: "0900-0939093C-094E09500953-09550958-09630966-096F097109720979-097FA8E0-A8FB", + Ethiopic: "1200-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A135F-137C1380-13992D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE", + Georgian: "10A0-10C510D0-10FA10FC2D00-2D25", + Glagolitic: "2C00-2C2E2C30-2C5E", + Greek: "0370-03730375-0377037A-037D038403860388-038A038C038E-03A103A3-03E103F0-03FF1D26-1D2A1D5D-1D611D66-1D6A1DBF1F00-1F151F18-1F1D1F20-1F451F48-1F4D1F50-1F571F591F5B1F5D1F5F-1F7D1F80-1FB41FB6-1FC41FC6-1FD31FD6-1FDB1FDD-1FEF1FF2-1FF41FF6-1FFE2126", + Gujarati: "0A81-0A830A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABC-0AC50AC7-0AC90ACB-0ACD0AD00AE0-0AE30AE6-0AEF0AF1", + Gurmukhi: "0A01-0A030A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A3C0A3E-0A420A470A480A4B-0A4D0A510A59-0A5C0A5E0A66-0A75", + Han: "2E80-2E992E9B-2EF32F00-2FD5300530073021-30293038-303B3400-4DB54E00-9FCBF900-FA2DFA30-FA6DFA70-FAD9", + Hangul: "1100-11FF3131-318E3200-321E3260-327EA960-A97CAC00-D7A3D7B0-D7C6D7CB-D7FBFFA0-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC", + Hanunoo: "1720-1734", + Hebrew: "0591-05C705D0-05EA05F0-05F4FB1D-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FB4F", + Hiragana: "3041-3096309D-309F", + Inherited: "0300-036F04850486064B-06550670095109521CD0-1CD21CD4-1CE01CE2-1CE81CED1DC0-1DE61DFD-1DFF200C200D20D0-20F0302A-302F3099309AFE00-FE0FFE20-FE26", + Javanese: "A980-A9CDA9CF-A9D9A9DEA9DF", + Kannada: "0C820C830C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBC-0CC40CC6-0CC80CCA-0CCD0CD50CD60CDE0CE0-0CE30CE6-0CEF", + Katakana: "30A1-30FA30FD-30FF31F0-31FF32D0-32FE3300-3357FF66-FF6FFF71-FF9D", + Kayah_Li: "A900-A92F", + Khmer: "1780-17DD17E0-17E917F0-17F919E0-19FF", + Lao: "0E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB90EBB-0EBD0EC0-0EC40EC60EC8-0ECD0ED0-0ED90EDC0EDD", + Latin: "0041-005A0061-007A00AA00BA00C0-00D600D8-00F600F8-02B802E0-02E41D00-1D251D2C-1D5C1D62-1D651D6B-1D771D79-1DBE1E00-1EFF2071207F2090-2094212A212B2132214E2160-21882C60-2C7FA722-A787A78BA78CA7FB-A7FFFB00-FB06FF21-FF3AFF41-FF5A", + Lepcha: "1C00-1C371C3B-1C491C4D-1C4F", + Limbu: "1900-191C1920-192B1930-193B19401944-194F", + Lisu: "A4D0-A4FF", + Malayalam: "0D020D030D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D-0D440D46-0D480D4A-0D4D0D570D60-0D630D66-0D750D79-0D7F", + Meetei_Mayek: "ABC0-ABEDABF0-ABF9", + Mongolian: "1800180118041806-180E1810-18191820-18771880-18AA", + Myanmar: "1000-109FAA60-AA7B", + New_Tai_Lue: "1980-19AB19B0-19C919D0-19DA19DE19DF", + NKo: "07C0-07FA", + Ogham: "1680-169C", + Ol_Chiki: "1C50-1C7F", + Oriya: "0B01-0B030B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3C-0B440B470B480B4B-0B4D0B560B570B5C0B5D0B5F-0B630B66-0B71", + Phags_Pa: "A840-A877", + Rejang: "A930-A953A95F", + Runic: "16A0-16EA16EE-16F0", + Samaritan: "0800-082D0830-083E", + Saurashtra: "A880-A8C4A8CE-A8D9", + Sinhala: "0D820D830D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60DCA0DCF-0DD40DD60DD8-0DDF0DF2-0DF4", + Sundanese: "1B80-1BAA1BAE-1BB9", + Syloti_Nagri: "A800-A82B", + Syriac: "0700-070D070F-074A074D-074F", + Tagalog: "1700-170C170E-1714", + Tagbanwa: "1760-176C176E-177017721773", + Tai_Le: "1950-196D1970-1974", + Tai_Tham: "1A20-1A5E1A60-1A7C1A7F-1A891A90-1A991AA0-1AAD", + Tai_Viet: "AA80-AAC2AADB-AADF", + Tamil: "0B820B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BBE-0BC20BC6-0BC80BCA-0BCD0BD00BD70BE6-0BFA", + Telugu: "0C01-0C030C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D-0C440C46-0C480C4A-0C4D0C550C560C580C590C60-0C630C66-0C6F0C78-0C7F", + Thaana: "0780-07B1", + Thai: "0E01-0E3A0E40-0E5B", + Tibetan: "0F00-0F470F49-0F6C0F71-0F8B0F90-0F970F99-0FBC0FBE-0FCC0FCE-0FD4", + Tifinagh: "2D30-2D652D6F", + Vai: "A500-A62B", + Yi: "A000-A48CA490-A4C6" +}; + +var unicode = { + categories: UnicodeCategories, + blocks: UnicodeBlocks, + scripts: UnicodeScripts +}; + +// EXPORTS +RegexParser.unicode = unicode; + +}()); diff --git a/gulliver/js/codemirror/contrib/regex/js/parseregex.js b/gulliver/js/codemirror/contrib/regex/js/parseregex.js new file mode 100755 index 000000000..8c2f2039d --- /dev/null +++ b/gulliver/js/codemirror/contrib/regex/js/parseregex.js @@ -0,0 +1,847 @@ +/* Simple parser for Regular Expressions */ +/* Thanks to Marijn for patiently addressing some questions and to + * Steven Levithan for XRegExp http://xregexp.com/ for pointing the way to the regexps for the regex (I + * only discovered his own regex syntax editor RegexPal later on) */ + +/* +// Possible future to-dos: +0) Unicode plugin fix for astral and update for Unicode 6.0.0 +1) Allow parsing of string escaped regular expressions (e.g., \\ as \ and regular \n as an actual newline) and + could potentially integrate into parsing for other languages where known (e.g., string inside RegExp constructor) +2) If configured, allow parsing of replace strings (e.g., $1, \1) +3) Shared classes + a) As with ranges and unicode classes, could also try to supply equivalents which list all + characters inside a whole character class + b) Add common classes for ranges, inside char. classes, and allow for alternation of colors +4) Groups + a) detect max's (or even inner_group_mode) from CSS if specified as "max-available" + _cssPropertyExists('span.regex-max-available') || _cssPropertyExists('.regex-max-available'); + b) Remove inner_group_mode and just always both uniform and type-based styles? (first improve + inner_group_mode performance when on) +5) Expand configuration for different flavors of regex or language implementations corresponding to config + options +6) Allow free-spacing mode to work with newlines? +*/ + +/** + * OPTIONS (SETUP): + * "possible_flags": {String} All flags to support (as a string of joined characters); default is 'imgxs'; + * if 'literal' is on, this will check for validity against the literal flags, but + * use the literal flags + * "flags": {String} List of flags to use on this query; will be added to any literals; default is '' + * "literal": {Boolean} Whether inside a literal or not + * "literal_initial": {String} The initial character to surround regular expression (optionally followed by flags); + * A forward slash ("/"), by default + * + * OPTIONS (STYLING) + * "inner_group_mode": {'type'|'uniform'} Indicates how (if at all) to style content inside groups; if by "type", + * the class will be assigned by type; if "uniform", a class named + * "regex-group--" where is the nesting level and + * is the sequence number; the "uniform" option allows grouped + * content to be styled consistently (but potentially differently from + * the parentheses themselves) no matter the type of group + * "max_levels": {Number|String} Maximum number of nesting levels before class numbers repeat + * "max_alternating": {Number|String} Maximum number of alternating sequences at the same level before + * class numbers repeat + * + * OPTIONS (PATTERNS) + * "flavor": {'all'|'ecma-262-ed5'|'ecma-262-ed3'} Sets defaults for the following patterns according to the regex flavor + * + * "unicode_mode": {'simple'|'validate'|'store'} Mode for handling Unicode classes; unless 'simple' is chosen, may + * affect performance given initial need to load and subsequent need + * to parse and validate (i.e., selectively color), and, if 'store' is chosen, + * also makes these (many) additional values on the token object, e.g., + * for use by activeTokens for adding tooltips; Default is 'simple' which + * simply checks that the values are plausible; + * Note: To include Unicode validation, you must include your + * CodeMirror parserfile in this sequence: + * parserfile: ["parseregex.js", "parseregex-unicode.js"] + * "unicode_classes": {Boolean} Whether to accept all Unicode classes (unless overridden); default is true + * "unicode_blocks": {Boolean} Whether to accept Unicode blocks (overrides unicode_classes default); e.g., \p{InArabic} + * "unicode_scripts": {Boolean} Whether to accept Unicode scripts (overrides unicode_classes default); e.g., \p{Hebrew} + * "unicode_categories": {Boolean} Whether to accept Unicode categories (overrides unicode_classes default); e.g., \p{Ll} (for lower-case letters) + * "named_backreferences": {Boolean} Whether to accept named backreferences; default is true + * "empty_char_class": {Boolean} Whether to allow [] or [^] as character classes; default is true + * "mode_modifier": {Boolean} Whether to allow (?imsx) mode modifiers + * + * NOTE + * You can add the following to your CodeMirror configuration object in order to get simple tooltips showing the + * character equivalent of an escape sequence: + activeTokens : function (spanNode, tokenObject, editor) { + if (tokenObject.equivalent) { + spanNode.title = tokenObject.equivalent; + } + }, +....or this more advanced one which adds ranges (though you may wish to change the character limit, being + aware that browsers have a limitation on tooltip size, unless you were to also use a tooltip library which used + this information to expand the visible content): + activeTokens : (function () { + var charLimit = 500; + var lastEquivalent, rangeBegan, lastRangeHyphen; + + function _buildTitle (beginChar, endChar) { + var beginCode = beginChar.charCodeAt(0), endCode = endChar.charCodeAt(0); + var title = ''; + if (endCode - beginCode <= charLimit) { + for (var i = beginCode; i <= endCode; i++) { + title += String.fromCharCode(i); + } + } + return title; + } + + return function (spanNode, token, editor) { + var content = token.content; + if (lastEquivalent && token.style === 'regex-class-range-hyphen') { + rangeBegan = true; + lastRangeHyphen = spanNode; + } + else if (rangeBegan) { + var beginChar = lastEquivalent; + var endChar = (token.equivalent || content); + lastRangeHyphen.title = _buildTitle(beginChar, endChar); + rangeBegan = false; + lastEquivalent = null; + //editor.reparseBuffer(); // title must be redrawn since already added previously (do below instead as locking up on undo?); too intensive to call this, but keeping here for record + } + else if (content === ']') { + rangeBegan = false; + } + else { + rangeBegan = false; + // Fix: 'regex-unicode-class-inside' not supported and should not be since it wouldn't make sense as a starting range? + lastEquivalent = token.equivalent || content; + } + + if (token.display) { + spanNode.title = token.display; + } + else if (token.equivalent) { + if (token.unicode) { + var range = /(.)-(.)/g; + spanNode.title = token.equivalent.replace(range, + function (n0, n1, n2) { + return _buildTitle(n1, n2); + } + ); + // editor.reparseBuffer(); // too intensive to call this, but keeping here for record + } + else { + spanNode.title = token.equivalent; + // editor.reparseBuffer(); // too intensive to call this, but keeping here for record + } + } + }; + }()), + */ + + +var RegexParser = Editor.Parser = (function() { + + var regexConfigBooleanOptions = ['unicode_blocks', 'unicode_scripts', 'unicode_categories', + 'unicode_classes', 'named_backreferences', 'empty_char_class', 'mode_modifier'], + regexConfigStringOptions = ['unicode_mode'], // Just for record-keeping + possibleFlags = 'imgxs', + config = {}, ucl; + // Resettable + var initialFound, endFound, charClassRangeBegun, negatedCharClass, mode_modifier_begun, flags = '', + groupTypes, groupCounts; + + config.literal_initial = '/'; + + // Adapted from tokenize.js (not distinctly treating whitespace except for newlines) + function noWSTokenizer (source, state) { + var tokenizer = { + state: state, + take: function(type) { + if (typeof(type) == "string") + type = {style: type, type: type}; + type.content = (type.content || "") + source.get(); + type.value = type.content + source.get(); + return type; + }, + next: function () { + if (!source.more()) throw StopIteration; + var type; + if (source.equals("\n")) { + source.next(); + return this.take("whitespace"); + } + while (!type) + type = this.state(source, function(s) {tokenizer.state = s;}); + return this.take(type); + } + }; + return tokenizer; + } + + // Private static utilities + function _expandRange (type, name) { // More efficient than unpack in targeting only which we need (though ideally would not need to convert at all) + var codePt = /\w{4}/g, + unicode = RegexParser.unicode, group = unicode[type]; + if (group.hasOwnProperty(name)) { + // group[name] = group[name].replace(codePt, '\\u$&'); // We shouldn't need this unless we start validating against a matching string + return group[name].replace(codePt, + function (n0) { + if (n0 === '002D') { + return 'U+' + n0; // Leave genuine hyphens unresolved so they won't get confused with range hyphens + } + return String.fromCharCode(parseInt('0x' + n0, 16)); // Fix: Would be more efficient to store as Unicode characters like this from the start + }); + } + return false; + } + + function _copyObj (obj, deep) { + var ret = {}; + for (var p in obj) { + if (obj.hasOwnProperty(p)) { + if (deep && typeof obj[p] === 'object' && obj[p] !== null) { + ret[p] = _copyObj(obj[p], deep); + } + else { + ret[p] = obj[p]; + } + } + } + return ret; + } + + function _forEach (arr, h) { + for (var i = 0, arrl = arr.length; i < arrl; i++) { + h(arr[i], i); + } + } + function _setOptions (arr, value) { + arr = typeof arr === 'string' ? [arr] : arr; + _forEach(arr, function (item) { + config[item] = value; + }); + } + + function _cssPropertyExists (selectorText) { + var i = 0, j = 0, dsl = 0, crl = 0, ss, d = document, + _getPropertyFromStyleSheet = + function (ss, selectorText) { + var rules = ss.cssRules ? ss.cssRules : ss.rules; /* Mozilla or IE */ + for (j = 0, crl = rules.length; j < crl; j++) { + var rule = rules[j]; + try { + if (rule.type === CSSRule.STYLE_RULE && rule.selectorText === selectorText) { + return true; + } + } + catch (err) { /* IE */ + if (rule.selectorText === selectorText) { + return true; + } + } + } + return false; + }; + + var value; + for (i = 0, dsl = d.styleSheets.length; i < dsl; i++) { + ss = d.styleSheets[i]; + value = _getPropertyFromStyleSheet(ss, selectorText); + if (value) { + break; + } + } + return value; + } + + function _addFlags (f) { + if ((/[^a-z]/).test(f)) { // Could insist on particular flags + throw 'Invalid flag supplied to the regular expression parser'; + } + flags += f; + } + function _setPossibleFlags (f) { + if ((/[^a-z]/).test(f)) { // Could insist on particular flags + throw 'Invalid flag supplied to the regular expression parser'; + } + possibleFlags = f; + } + function _esc (s) { + return s.replace(/"[.\\+*?\[\^\]$(){}=!<>|:\-]/g, '\\$&'); + } + + var tokenizeRegex = (function() { + // Private utilities + function _hasFlag (f) { + return flags.indexOf(f) > -1; + } + function _lookAheadMatches (source, regex) { + var matches = source.lookAheadRegex(regex, true); + if (matches && matches.length > 1) { // Allow us to return the position of a match out of alternates + for (var i = matches.length - 1; i >= 0; i--) { + if (matches[i] != null) { + return i; + } + } + } + return 0; + } + + function validateUnicodeClass (negated, place, source) { + var neg = ' regex-' + negated + 'unicode', ret = 'regex-unicode-class-' + place + neg, + name, unicode = RegexParser.unicode; + if (!unicode) { + throw 'Unicode plugin of the regular expression parser not properly loaded'; + } + if (config.unicode_categories) { + var categories = source.lookAheadRegex(/^\\[pP]{\^?([A-Z][a-z]?)}/, true); + if (categories) { + name = categories[1]; + if (unicode.categories[name]) { + return ret + '-category-' + place + neg + '-category-' + name + '-' + place; + } + return 'regex-bad-sequence'; + } + } + if (config.unicode_blocks) { + var blocks = source.lookAheadRegex(/^\\[pP]{\^?(In[A-Z][^}]*)}/, true); + if (blocks) { + name = blocks[1]; + if (unicode.blocks[name]) { + return ret + '-block-' + place + neg + '-block-' + name + '-' + place; + } + return 'regex-bad-sequence'; + } + } + if (config.unicode_scripts) { + var scripts = source.lookAheadRegex(/^\\[pP]{\^?([^}]*)}/, true); + if (scripts) { + name = scripts[1]; + if (unicode.scripts[name]) { + return ret + '-script-' + place + neg + '-script-' + name + '-' + place; + } + return 'regex-bad-sequence'; + } + } + return false; + } + + function unicode_class (source, place) { + var ret = 'regex-unicode-class-' + place + ' ', negated = ''; + if (source.lookAheadRegex(/^\\P/) || source.lookAheadRegex(/^\\p{\^/)) { + negated = 'negated'; + } + else if (source.lookAheadRegex(/^\\P{\^/)) { // Double-negative + return false; + } + switch (config.unicode_mode) { + case 'validate': case 'store': + return validateUnicodeClass(negated, place, source); + case 'simple': // Fall-through + default: + // generic: /^\\[pP]{\^?[^}]*}/ + if (config.unicode_categories && source.lookAheadRegex(/^\\[pP]{\^?[A-Z][a-z]?}/, true)) { + return ret + 'regex-' + negated + 'unicode-category'; + } + if (config.unicode_blocks && source.lookAheadRegex(/^\\[pP]{\^?In[A-Z][^}]*}/, true)) { + return ret + 'regex-' + negated + 'unicode-block'; + } + if (config.unicode_scripts && source.lookAheadRegex(/^\\[pP]{\^?[^}]*}/, true)) { + return ret + 'regex-' + negated + 'unicode-script'; + } + break; + } + return false; + } + + // State functions + // Changed [\s\S] to [^\n] to avoid accidentally grabbing a terminating (auto-inserted place-holder?) newline + var inside_class_meta = /^\\(?:([0-3][0-7]{0,2}|[4-7][0-7]?)|(x[\dA-Fa-f]{2})|(u[\dA-Fa-f]{4})|(c[A-Za-z])|(-\\]^)|([bBdDfnrsStvwW0])|([^\n]))/; + function inside_class (source, setState) { + var ret; + if (source.lookAhead(']', true)) { + // charClassRangeBegun = false; // Shouldn't be needed + setState(customOutsideClass); + return 'regex-class-end'; + } + if (negatedCharClass && source.lookAhead('^', true)) { + negatedCharClass = false; + return 'regex-class-negator'; + } + if (source.lookAhead('-', true)) { + if (!charClassRangeBegun) { + ret = 'regex-class-initial-hyphen'; + } + else if (source.equals(']')) { + ret = 'regex-class-final-hyphen'; + } + else { + return 'regex-class-range-hyphen'; + } + } + else if (!source.equals('\\')) { + var ch = source.next(); + if (config.literal && ch === config.literal_initial) { + return 'regex-bad-character'; + } + ret = 'regex-class-character'; + } + else if ((ucl = unicode_class(source, 'inside'))) { + ret = ucl; + } + else if (source.lookAheadRegex(/^\\(\n|$)/)) { // Treat an ending backslash like a bad + // character to avoid auto-adding of extra text + source.next(); + ret = 'regex-bad-character'; + } + else { + switch (_lookAheadMatches(source, inside_class_meta)) { + case 1: + ret = 'regex-class-octal'; + break; + case 2: + ret = 'regex-class-hex'; + break; + case 3: + ret = 'regex-class-unicode-escape'; + break; + case 4: + ret = 'regex-class-ascii-control'; + break; + case 5: + ret = 'regex-class-escaped-special'; + break; + case 6: + ret = 'regex-class-special-escape'; + break; + case 7: + ret = 'regex-class-extra-escaped'; + break; + default: + throw 'Unexpected character inside class, beginning ' + + source.lookAheadRegex(/^[\s\S]+$/)[0] + ' and of length '+ + source.lookAheadRegex(/^[\s\S]+$/)[0].length; // Shouldn't reach here + } + } + // Fix: Add this as a token property in the parser instead? + if (charClassRangeBegun) { + charClassRangeBegun = false; + ret += '-end-range'; + } + else if (source.equals('-')) { + charClassRangeBegun = true; + ret += '-begin-range'; + } + return ret; + } + + // Changed [\s\S] to [^\n] to avoid accidentally grabbing a terminating (auto-inserted place-holder?) newline + var outside_class_meta = /^(?:\\(?:(0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?)|([1-9]\d*)|(x[\dA-Fa-f]{2})|(u[\dA-Fa-f]{4})|(c[A-Za-z])|([bBdDfnrsStvwW0])|([?*+])|([.\\[$|{])|([^\n]))|([?*+]\??)|({\d+(?:,\d*)?}\??))/; + function outside_class (source, setState) { + if ((ucl = unicode_class(source, 'outside'))) { + return ucl; + } + switch (_lookAheadMatches(source, outside_class_meta)) { + case 1: + return 'regex-octal'; + case 2: + return 'regex-ascii'; + case 3: + return 'regex-hex'; + case 4: + return 'regex-unicode-escape'; + case 5: + return 'regex-ascii-control'; + case 6: + return 'regex-special-escape'; + case 7: + return 'regex-quantifier-escape'; // Fix: could probably just merge with escaped-special + case 8: + return 'regex-escaped-special'; + case 9: + return 'regex-extra-escaped'; + case 10: + return 'regex-quantifiers'; + case 11: + return 'regex-repetition'; + default: + if (config.literal && source.lookAhead(config.literal_initial, true)) { + if (!initialFound) { + initialFound = true; + return 'regex-literal-begin'; + } + endFound = true; + setState(beginFlags); + return 'regex-literal-end'; + } + if (source.lookAhead('|', true)) { + return 'regex-alternator'; + } + if (source.lookAheadRegex(/^\\$/, true)) { + return 'regex-bad-character'; + } + source.next(); + return 'regex-character'; + } + } + function beginFlags (source, setState) { + var endFlags = source.lookAheadRegex(new RegExp('^[' + possibleFlags + ']*', ''), true); + if (endFlags == null) { + // Unrecognized flag used in regular expression literal + return 'regex-bad-character'; + } + // Already confirmed validity earlier + setState(finished); + return 'regex-flags'; + } + function finished () { + throw StopIteration; + } + + function customOutsideClass (source, setState) { + if (config.named_backreferences && source.lookAheadRegex(/^\\k<([\w$]+)>/, true)) { + return 'regex-named-backreference'; + } + if (_hasFlag('x') && source.lookAheadRegex(/^(?:#.*)+?/, true)) { // Fix: lookAheadRegex will avoid new lines; added extra '?' at end + // Regex should be /^(?:\s+|#.*)+?/ but this was problematic + return 'regex-free-spacing-mode'; + } + + if (source.lookAhead('[', true)) { + if (source.lookAheadRegex(/^\^?]/, true)) { + return config.empty_char_class ? 'regex-empty-class' : 'regex-bad-character'; + } + if (source.equals('^')) { + negatedCharClass = true; + } + setState(inside_class); + return 'regex-class-begin'; + } + + // Unmatched ending parentheses + if (source.lookAhead(')', true)) { + return 'regex-ending-group'; + } + if (source.lookAhead('(', true)) { + if (config.mode_modifier && mode_modifier_begun) { + var mode_modifier = source.lookAheadRegex(/^\?([imsx]+)\)/, true); + if (mode_modifier) { // We know it should exist if we're here + // addFlags(mode_modifier[1]); // Handle flags earlier + mode_modifier_begun = false; + return 'regex-mode-modifier'; + } + } + if (source.lookAheadRegex(/^\?#[^)]*\)/, true)) { // No apparent nesting of comments? + return 'regex-comment-pattern'; + } + + var ret; + if (source.lookAheadRegex(/^(?!\?)/, true)) { + ret = 'regex-capturing-group'; + } + if (source.lookAheadRegex(/^\?<([$\w]+)>/, true)) { + ret = 'regex-named-capturing-group'; + } + if (source.lookAheadRegex(/^\?[:=!]/, true)) { + ret = 'regex-grouping'; + } + if (!ret) { + return 'regex-bad-character'; // 'Uncaught parenthetical in tokenizing regular expression'; + } + return ret; + } + return outside_class(source, setState); + } + + return function(source, startState) { + return noWSTokenizer(source, startState || customOutsideClass); + }; + })(); + + + function resetStateVariables () { + initialFound = false, endFound = false, charClassRangeBegun = false, negatedCharClass = false, + mode_modifier_begun = false; + flags = ''; + if (config.flags) { // Reset to configuration value + _addFlags(config.flags); + } + groupTypes = [], + groupCounts = { + 'capturing-group': {currentCount: 0}, + 'named-capturing-group': {currentCount: 0}, + 'grouping': {currentCount: 0} + }; + } + + // Parser + function parseRegex (source) { + resetStateVariables(); + + var tokens = tokenizeRegex(source); + + if (config.literal && !source.equals(config.literal_initial)) { + throw 'Regular expression literals must include a beginning "'+config.literal_initial+'"'; + } + + if (config.literal) { + var regex = new RegExp('^[\\s\\S]*' + _esc(config.literal_initial) + '([' + possibleFlags + ']*)$', ''); + var endFlags = source.lookAheadRegex(regex); + if (endFlags == null) { + // Unrecognized flag used in regular expression literal + } + else { + _addFlags(endFlags[1]); + } + } + else if (config.mode_modifier) { // Fix: We are not allowing both a mode modifier and + // literal syntax (presumably redundant) + var mode_modifier = source.lookAheadRegex(/^\(\?([imsx]+)\)/, true); + if (mode_modifier) { + mode_modifier_begun = true; + _addFlags(mode_modifier[1]); + } + } + var iter = { + next: function() { + try { + var level_num, + token = tokens.next(), + style = token.style, + content = token.content, + lastChildren, currentChildren, currentCount, currentGroupStyle, + type = style.replace(/^regex-/, ''); + + switch (type) { + case 'ending-group': + if (!groupTypes.length) { + // Closing parenthesis without an opening one + token.style = 'regex-bad-character'; + } + else { + level_num = config.max_levels ? + ((groupTypes.length % config.max_levels) || config.max_levels) : groupTypes.length; + var popped = groupTypes.pop(); + // Allow numbered classes + currentChildren = groupCounts[popped]; + while (currentChildren && currentChildren.currentChildren && + currentChildren.currentChildren.currentChildren) { // Find lowest level parent + currentChildren = currentChildren.currentChildren; + } + delete currentChildren.currentChildren; // Use parent to delete children + currentCount = currentChildren.currentCount; // Use parent as new child to get current count + currentCount = config.max_alternating ? + ((currentCount % config.max_alternating) || config.max_alternating) : currentCount; + + currentGroupStyle = level_num + '-' + currentCount; + token.style = 'regex-ending-' + popped + ' regex-ending-' + popped + currentGroupStyle; + if (config.inner_group_mode === 'uniform') { // 'type' is automatically processed for ending + token.style += ' regex-group-' + currentGroupStyle; + } + } + break; + case 'capturing-group': + case 'named-capturing-group': + case 'grouping': + lastChildren = groupCounts[type], + currentChildren = groupCounts[type].currentChildren; + while (currentChildren) { + lastChildren = currentChildren; + currentChildren = currentChildren.currentChildren; + } + currentCount = ++lastChildren.currentCount; + if (!lastChildren.currentChildren) { + lastChildren.currentChildren = {currentCount: 0}; + } + + groupTypes.push(type); + level_num = config.max_levels ? + ((groupTypes.length % config.max_levels) || config.max_levels) : groupTypes.length; + // Allow numbered classes + currentCount = config.max_alternating ? + ((currentCount % config.max_alternating) || config.max_alternating) : currentCount; + currentGroupStyle = level_num + '-' + currentCount; + var currentStyle = ' ' + token.style; + + + if (config.inner_group_mode) { + token.style += config.inner_group_mode === 'type' ? + currentStyle + currentGroupStyle : + ' regex-group-' + currentGroupStyle; + token.style += ' ' + style + currentGroupStyle; + } + else { + token.style += currentStyle + currentGroupStyle; + } + lastChildren.currentGroupStyle = currentGroupStyle; + lastChildren.currentStyle = currentStyle; + break; + // Allow ability to extract information on character equivalence, e.g., for use on tooltips + case 'class-octal': case 'octal': // Fall-through + case 'class-octal-begin-range': case 'class-octal-end-range': // Fall-through + case 'class-ascii-begin-range': case 'class-ascii-end-range': // Fall-through + case 'class-ascii': case 'ascii': // Firefox apparently treats ascii here as octals + token.equivalent = String.fromCharCode(parseInt(content.replace(/^\\/, ''), 8)); + break; + case 'class-hex': case 'hex': // Fall-through + case 'class-hex-begin-range': case 'class-hex-end-range': // Fall-through + case 'class-unicode-escape': case 'class-unicode-escape-begin-range': // Fall-through + case 'class-unicode-escape-end-range': case 'unicode-escape': + token.equivalent = String.fromCharCode(parseInt('0x'+content.replace(/^\\(x|u)/, ''), 16)); + break; + case 'class-ascii-control-begin-range': case 'class-ascii-control-end-range': // Fall-through + case 'class-ascii-control': case 'ascii-control': + token.equivalent = String.fromCharCode(content.replace(/^\\c/, '').charCodeAt(0) - 64); + break; + case 'class-special-escape': case 'class-special-escape-begin-range': // Fall-through + case 'class-special-escape-end-range': case 'special-escape': + // Others to ignore (though some (\d, \s, \w) could have theirs listed): bBdDsSwW + var chr = content.replace(/^\\/, ''), + pos = 'fnrtv'.indexOf(chr), + specialEquivs = '\f\n\r\t\v'; + if (pos !== -1) { // May not be visible without conversion to codepoints + var c = specialEquivs.charAt(pos); + var hex = c.charCodeAt(0).toString(16).toUpperCase(); + token.display = 'U+' + Array(5 - hex.length).join('0') + hex; + token.equivalent = c; + } + break; + case 'regex-class-escaped-special': case 'regex-class-escaped-special-begin-range': + case 'regex-class-escaped-special-end-range': + case 'class-extra-escaped-begin-range': case 'class-extra-escaped-end-range': + case 'class-extra-escaped': case 'extra-escaped': + token.equivalent = content.replace(/^\\/, ''); + break; + default: + if (config.unicode_mode === 'store') { + if (config.unicode_categories) { + var cat = type.match(/regex-unicode-category-(\w+?)-(?:outside|inside)/); + if (cat) { + token.equivalent = _expandRange('categories', cat[1]) || ''; + token.unicode = true; + break; + } + } + if (config.unicode_blocks) { + var block = type.match(/regex-unicode-block-(\w+)-(?:outside|inside)/); + if (block) { + token.equivalent = _expandRange('blocks', block[1]) || ''; + token.unicode = true; + break; + } + } + if (config.unicode_scripts) { + var script = type.match(/regex-unicode-script-(\w+)-(?:outside|inside)/); + if (script) { + token.equivalent = _expandRange('scripts', script[1]) || ''; + token.unicode = true; + break; + } + } + } + break; + } + if (config.inner_group_mode && type !== 'ending-group' && type !== 'capturing-group' && type !== 'named-capturing-group' && + type !== 'grouping') { + level_num = config.max_levels ? + ((groupTypes.length % config.max_levels) || config.max_levels) : groupTypes.length; + // Allow numbered classes + var last = groupTypes[groupTypes.length - 1]; + if (last) { + currentChildren = groupCounts[last]; + while (currentChildren && currentChildren.currentChildren && + currentChildren.currentChildren.currentChildren) { // Find lowest level parent + currentChildren = currentChildren.currentChildren; + } + token.style += config.inner_group_mode === 'type' ? + currentChildren.currentStyle + currentChildren.currentGroupStyle : + ' regex-group-' + currentChildren.currentGroupStyle; + } + } + if (!source.more()) { + if (groupTypes.length) { // Opening group without a closing parenthesis + token.style = 'regex-bad-character'; + } + else if (config.literal && !endFound) { + //throw 'Regular expression literals must include a (non-escaped) ending "' + + // config.literal_initial + '" (with optional flags).'; + token.style = 'regex-bad-character'; + } + } + } + catch (e) { +if (e != StopIteration) { + alert(e + '::'+e.lineNumber); +} + throw e; + } + return token; + }, + copy: function() { + var _initialFound = initialFound, _charClassRangeBegun = charClassRangeBegun, + _negatedCharClass = negatedCharClass, _flags = flags, + _endFound = endFound, _groupTypes = groupTypes, + _mode_modifier_begun = mode_modifier_begun, + _tokenState = tokens.state, + _groupCounts = _copyObj(groupCounts, true); + return function(source) { + initialFound = _initialFound; + charClassRangeBegun = _charClassRangeBegun; + negatedCharClass = _negatedCharClass; + flags = _flags; + endFound = _endFound; + groupTypes = _groupTypes; + mode_modifier_begun = _mode_modifier_begun; + tokens = tokenizeRegex(source, _tokenState); + groupCounts = _groupCounts; + return iter; + }; + } + }; + return iter; + } + + // Parser object + return { + make: parseRegex, + configure: function (parserConfig) { + var unicode = this.unicode; + + // Overridable + _setOptions('unicode_mode', 'simple'); + _setOptions(regexConfigBooleanOptions, false); + if (parserConfig.unicode_classes) { + _setOptions(['unicode_blocks', 'unicode_scripts', 'unicode_categories'], true); + } + switch (parserConfig.flavor) { + case 'ecma-262-ed5': + _setOptions(['empty_char_class'], true); + // Fall-through + case 'ecma-262-ed3': + config.possible_flags = 'gim'; // If wish for Firefox 'y', add it on parserConfig + break; + case 'all': + default: + _setOptions(regexConfigBooleanOptions, true); + break; + } + + // Setting with possible overrides + for (var opt in parserConfig) { + if ((/^regex_/).test(opt)) { // Use for compatibility with JS+Regex + config[opt.replace(/^regex_/, '')] = parserConfig[opt]; + continue; + } + config[opt] = parserConfig[opt]; + } + + // Post-processing + if (config.possible_flags) { + _setPossibleFlags(config.possible_flags); + } + + if (config.unicode_mode !== 'simple') { + if (!unicode) { + throw 'You must include the parseregex-unicode.js file in order to use validate or storage mode Unicode'; + } + } + } + }; +})(); diff --git a/gulliver/js/codemirror/contrib/scheme/LICENSE b/gulliver/js/codemirror/contrib/scheme/LICENSE new file mode 100755 index 000000000..9f8a9f340 --- /dev/null +++ b/gulliver/js/codemirror/contrib/scheme/LICENSE @@ -0,0 +1,23 @@ + Copyright (c) 2010 Danny Yoo + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any + damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and + redistribute it freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + Danny Yoo + dyoo@cs.wpi.edu diff --git a/gulliver/js/codemirror/contrib/scheme/css/schemecolors.css b/gulliver/js/codemirror/contrib/scheme/css/schemecolors.css new file mode 100755 index 000000000..7283510bc --- /dev/null +++ b/gulliver/js/codemirror/contrib/scheme/css/schemecolors.css @@ -0,0 +1,45 @@ +html { + cursor: text; + width: 100%; + height: 100%; + background-color: white; +} + +.editbox { + width: 100%; + height: 100%; + margin: 0pt; + padding: 0; + font-family: monospace; + font-size: 10pt; + color: black; +} + + + +pre.code, .editbox { + color: #666666; +} + +.editbox p { + margin: 0; +} + +span.scheme-string {color: green;} +span.scheme-number {color: blue;} +span.scheme-boolean {color: darkred;} +span.scheme-character {color: orange;} +span.scheme-symbol {color: steelblue;} +span.scheme-punctuation {color: black;} +span.scheme-lparen {color: black;} +span.scheme-rparen {color: black;} +span.scheme-comment { color: orange; } + +span.good-matching-paren { + font-weight: bold; + color: #3399FF; +} +span.bad-matching-paren { + font-weight: bold; + color: red; +} diff --git a/gulliver/js/codemirror/contrib/scheme/index.html b/gulliver/js/codemirror/contrib/scheme/index.html new file mode 100755 index 000000000..e48837696 --- /dev/null +++ b/gulliver/js/codemirror/contrib/scheme/index.html @@ -0,0 +1,82 @@ + + + + + CodeMirror: Scheme demonstration + + + + + + +

This page demonstrates CodeMirror's +Scheme parser. (license)

+ +
+ +
+ + + + + diff --git a/gulliver/js/codemirror/contrib/scheme/js/parsescheme.js b/gulliver/js/codemirror/contrib/scheme/js/parsescheme.js new file mode 100755 index 000000000..6b1ffba88 --- /dev/null +++ b/gulliver/js/codemirror/contrib/scheme/js/parsescheme.js @@ -0,0 +1,428 @@ +var SchemeParser = Editor.Parser = (function() { + + + // isLparen: char -> boolean + var isLparen = function(ch) { + return ch === '(' || ch === '[' || ch === '{'; + }; + + // isRparen: char -> boolean + var isRparen = function(ch) { + return ch === ')' || ch === ']' || ch === '}'; + }; + + // isMatchingParens: char char -> boolean + var isMatchingParens = function(lparen, rparen) { + return ((lparen === '(' && rparen === ')') || + (lparen === '[' && rparen === ']') || + (lparen === '{' && rparen === '}')); + }; + + + // Compute the indentation context enclosing the end of the token + // sequence tokens. + // The context is the token sequence of the enclosing s-expression, + // augmented with column information. + var getIndentationContext = function(tokenStack) { + var EMPTY_CONTEXT = []; + + var pendingParens = [], i = 0, j, line, column, context; + var tokens = []; + + // Scan for the start of the indentation context, accumulating tokens. + while (! isEmptyPair(tokenStack)) { + i++; + tokens.push(pairFirst(tokenStack)); + if (isLparen(pairFirst(tokenStack).type)) { + if (pendingParens.length === 0) { + break; + } else { + if (isMatchingParens(pairFirst(tokenStack).value, + pendingParens[pendingParens.length - 1])) { + pendingParens.pop(); + } else { + // Error condition: we see mismatching parens, + // so we exit with no known indentation context. + return EMPTY_CONTEXT; + } + } + } else if (isRparen(pairFirst(tokenStack).type)) { + pendingParens.push(pairFirst(tokenStack).type); + } + tokenStack = pairRest(tokenStack); + } + + // If we scanned backward too far, we couldn't find a context. Just + // return the empty context. + if (isEmptyPair(tokenStack)) { + return EMPTY_CONTEXT; + } + + // Position tokenStack to the next token beyond. + tokenStack = pairRest(tokenStack); + + // We now scan backwards to closest newline to figure out the column + // number: + while (! isEmptyPair(tokenStack)) { + if(pairFirst(tokenStack).type === 'whitespace' && + pairFirst(tokenStack).value === '\n') { + break; + } + tokens.push(pairFirst(tokenStack)); + tokenStack = pairRest(tokenStack); + } + + line = 0; + column = 0; + context = []; + // Start generating the context, walking forward. + for (j = tokens.length-1; j >= 0; j--) { + if (j < i) { + context.push({ type: tokens[j].type, + value: tokens[j].value, + line: line, + column: column }); + } + + if (tokens[j].type === 'whitespace' && + tokens[j].value === '\n') { + column = 0; + line++; + } else { + column += tokens[j].value.length; + } + } + return context; + + + }; + + + + + + // calculateIndentationFromContext: indentation-context number -> number + var calculateIndentationFromContext = function(context, currentIndentation) { + if (context.length === 0) { + return 0; + } + if (isBeginLikeContext(context)) { + return beginLikeIndentation(context); + } + if (isDefineLikeContext(context)) { + return defineLikeIndentation(context); + } + if (isLambdaLikeContext(context)) { + return lambdaLikeIndentation(context); + } + return beginLikeIndentation(context, 0); + }; + + + + // findContextElement: indentation-context number -> index or -1 + var findContextElement = function(context, index) { + var depth = 0; + for(var i = 0; i < context.length; i++) { + if (context[i].type !== 'whitespace' && depth === 1) { + if (index === 0) + return i; + else + index--; + } + + if (isLparen(context[i].type)) { + depth++; + } + if (isRparen(context[i].type)) { + depth = Math.max(depth - 1, 0); + } + } + return -1; + }; + + // contextElement: context -> (arrayof index) + var contextElements = function(context) { + var i = 0, index, results = []; + + while ((index = findContextElement(context, i++)) != -1) { + results.push(index); + } + return results; + }; + + + + ////////////////////////////////////////////////////////////////////// + + var BEGIN_LIKE_KEYWORDS = ["case-lambda", + "compound-unit", + "compound-unit/sig", + "cond", + "delay", + "inherit", + "match-lambda", + "match-lambda*", + "override", + "private", + "public", + "sequence", + "unit"]; + + var isBeginLikeContext = function(context) { + var j = findContextElement(context, 0); + if (j === -1) { return false; } + return (/^begin/.test(context[j].value) || + isMember(context[j].value, BEGIN_LIKE_KEYWORDS)); + }; + + + // Begin: if there's no elements within the begin context, + // the indentation is that of the begin keyword's column + offset. + // Otherwise, find the leading element on the last line. + // Also used for default indentation. + var beginLikeIndentation = function(context, offset) { + if (typeof(offset) === 'undefined') { offset = 1; } + + var indices = contextElements(context), j; + if (indices.length === 0) { + return context[0].column + 1; + } else if (indices.length === 1) { + // if we only see the begin keyword, indentation is based + // off the keyword. + return context[indices[0]].column + offset; + } else { + // Otherwise, we scan for the contextElement of the last line + for (j = indices.length -1; j > 1; j--) { + if (context[indices[j]].line !== + context[indices[j-1]].line) { + return context[indices[j]].column; + } + } + return context[indices[j]].column; + } + }; + + + + ////////////////////////////////////////////////////////////////////// + + + var DEFINE_LIKE_KEYWORDS = ["local"]; + + var isDefineLikeContext = function(context) { + var j = findContextElement(context, 0); + if (j === -1) { return false; } + return (/^def/.test(context[j].value) || + isMember(context[j].value, DEFINE_LIKE_KEYWORDS)); + }; + + + var defineLikeIndentation = function(context) { + var i = findContextElement(context, 0); + if (i === -1) { return 0; } + return context[i].column +1; + }; + + ////////////////////////////////////////////////////////////////////// + + var LAMBDA_LIKE_KEYWORDS = ["cases", + "instantiate", + "super-instantiate", + "syntax/loc", + "quasisyntax/loc", + "lambda", + "let", + "let*", + "letrec", + "recur", + "lambda/kw", + "letrec-values", + "with-syntax", + "with-continuation-mark", + "module", + "match", + "match-let", + "match-let*", + "match-letrec", + "let/cc", + "let/ec", + "letcc", + "catch", + "let-syntax", + "letrec-syntax", + "fluid-let-syntax", + "letrec-syntaxes+values", + "for", + "for/list", + "for/hash", + "for/hasheq", + "for/and", + "for/or", + "for/lists", + "for/first", + "for/last", + "for/fold", + "for*", + "for*/list", + "for*/hash", + "for*/hasheq", + "for*/and", + "for*/or", + "for*/lists", + "for*/first", + "for*/last", + "for*/fold", + "kernel-syntax-case", + "syntax-case", + "syntax-case*", + "syntax-rules", + "syntax-id-rules", + "let-signature", + "fluid-let", + "let-struct", + "let-macro", + "let-values", + "let*-values", + "case", + "when", + "unless", + "let-enumerate", + "class", + "class*", + "class-asi", + "class-asi*", + "class*/names", + "class100", + "class100*", + "class100-asi", + "class100-asi*", + "class100*/names", + "rec", + "make-object", + "mixin", + "define-some", + "do", + "opt-lambda", + "send*", + "with-method", + "define-record", + "catch", + "shared", + "unit/sig", + "unit/lang", + "with-handlers", + "interface", + "parameterize", + "call-with-input-file", + "call-with-input-file*", + "with-input-from-file", + "with-input-from-port", + "call-with-output-file", + "with-output-to-file", + "with-output-to-port", + "for-all"]; + + + var isLambdaLikeContext = function(context) { + var j = findContextElement(context, 0); + if (j === -1) { return false; } + return (isMember(context[j].value, LAMBDA_LIKE_KEYWORDS)); + }; + + + var lambdaLikeIndentation = function(context) { + var i = findContextElement(context, 0); + if (i === -1) { return 0; } + var j = findContextElement(context, 1); + if (j === -1) { + return context[i].column + 4; + } else { + return context[i].column + 1; + } + }; + + + + + ////////////////////////////////////////////////////////////////////// + // Helpers + var isMember = function(x, l) { + for (var i = 0; i < l.length; i++) { + if (x === l[i]) { return true; } + } + return false; + }; + + + + ////////////////////////////////////////////////////////////////////// + + var pair = function(x, y) { + return [x,y]; + }; + var EMPTY_PAIR = []; + var pairFirst = function(p) { return p[0]; } + var pairRest = function(p) { return p[1]; } + var isEmptyPair = function(p) { return p === EMPTY_PAIR; } + var pairLength = function(p) { + var l = 0; + while (! isEmptyPair(p)) { + p = pairRest(p); + } + return l; + }; + + ////////////////////////////////////////////////////////////////////// + + + + + var indentTo = function(tokenStack) { + return function(tokenText, currentIndentation, direction) { + + // If we're in the middle of an unclosed token, + // do not change indentation. + if ((! isEmptyPair(tokenStack)) && + (! isEmptyPair(pairRest(tokenStack))) && + (pairFirst(pairRest(tokenStack)).isUnclosed)) { + return currentIndentation; + } + + var indentationContext = + getIndentationContext(tokenStack); + return calculateIndentationFromContext(indentationContext, + currentIndentation); + }; + }; + + + var startParse = function(source) { + source = tokenizeScheme(source); + var tokenStack = EMPTY_PAIR; + var iter = { + next: function() { + var tok = source.next(); + tokenStack = pair(tok, tokenStack); + if (tok.type === "whitespace") { + if (tok.value === "\n") { + tok.indentation = indentTo(tokenStack); + } + } + return tok; + }, + + copy: function() { + var _tokenStack = tokenStack; + var _tokenState = source.state; + return function(_source) { + tokenStack = _tokenStack; + source = tokenizeScheme(_source, _tokenState); + return iter; + }; + } + }; + return iter; + }; + return { make: startParse }; +})(); diff --git a/gulliver/js/codemirror/contrib/scheme/js/tokenizescheme.js b/gulliver/js/codemirror/contrib/scheme/js/tokenizescheme.js new file mode 100755 index 000000000..37df0bb9e --- /dev/null +++ b/gulliver/js/codemirror/contrib/scheme/js/tokenizescheme.js @@ -0,0 +1,241 @@ +/* Tokenizer for Scheme code */ + + + + +/** + TODO: follow the definitions in: + + http://docs.racket-lang.org/reference/reader.html + + to the letter; at the moment, we've just done something quick-and-dirty. + +*/ + + +var tokenizeScheme = (function() { + var isWhiteSpace = function(ch) { + // The messy regexp is because IE's regexp matcher is of the + // opinion that non-breaking spaces are no whitespace. + return ch != "\n" && /^[\s\u00a0]*$/.test(ch); + }; + + + // scanUntilUnescaped: string-stream char -> boolean + // Advances the stream until the given character (not preceded by a + // backslash) is encountered. + // Returns true if we hit end of line without closing. + // Returns false otherwise. + var scanUntilUnescaped = function(source, end) { + var escaped = false; + while (true) { + if (source.endOfLine()) { + return true; + } + var next = source.next(); + if (next == end && !escaped) + return false; + escaped = !escaped && next == "\\"; + } + return false; + } + + + // Advance the stream until endline. + var scanUntilEndline = function(source, end) { + while (!source.endOfLine()) { + source.next(); + } + } + + + // Some helper regexps + var isHexDigit = /[0-9A-Fa-f]/; + + + var whitespaceChar = new RegExp("[\\s\\u00a0]"); + + var isDelimiterChar = + new RegExp("[\\s\\\(\\\)\\\[\\\]\\\{\\\}\\\"\\\,\\\'\\\`\\\;]"); + + var isNotDelimiterChar = + new RegExp("[^\\s\\\(\\\)\\\[\\\]\\\{\\\}\\\"\\\,\\\'\\\`\\\;]"); + + + var numberHeader = ("(?:(?:\\d+\\/\\d+)|"+ + ( "(?:(?:\\d+\\.\\d+|\\d+\\.|\\.\\d+)(?:[eE][+\\-]?\\d+)?)|")+ + ( "(?:\\d+(?:[eE][+\\-]?\\d+)?))")); + var numberPatterns = [ + // complex numbers + new RegExp("^((?:(?:\\#[ei])?[+\\-]?" + numberHeader +")?" + + "(?:[+\\-]" + numberHeader + ")i$)"), + /^((?:\#[ei])?[+-]inf.0)$/, + /^((?:\#[ei])?[+-]nan.0)$/, + new RegExp("^((?:\\#[ei])?[+\\-]?" + numberHeader + "$)"), + new RegExp("^0[xX][0-9A-Fa-f]+$")]; + + + // looksLikeNumber: string -> boolean + // Returns true if string s looks like a number. + var looksLikeNumber = function(s) { + for (var i = 0; i < numberPatterns.length; i++) { + if (numberPatterns[i].test(s)) { + return true; + } + } + return false; + }; + + + + var UNCLOSED_STRING = function(source, setState) { + var readNewline = function() { + var content = source.get(); + return { type:'whitespace', style:'whitespace', content: content }; + }; + + var ch = source.peek(); + if (ch === '\n') { + source.next(); + return readNewline(); + } else { + var isUnclosedString = scanUntilUnescaped(source, '"'); + if (isUnclosedString) { + setState(UNCLOSED_STRING); + } else { + setState(START); + } + var content = source.get(); + return {type: "string", style: "scheme-string", content: content, + isUnclosed: isUnclosedString}; + } + }; + + + + var START = function(source, setState) { + // Read a word, look it up in keywords. If not found, it is a + // variable, otherwise it is a keyword of the type found. + var readWordOrNumber = function() { + source.nextWhileMatches(isNotDelimiterChar); + var word = source.get(); + if (looksLikeNumber(word)) { + return {type: "number", style: "scheme-number", content: word}; + } else { + return {type: "variable", style: "scheme-symbol", content: word}; + } + }; + + + var readString = function(quote) { + var isUnclosedString = scanUntilUnescaped(source, quote); + if (isUnclosedString) { + setState(UNCLOSED_STRING); + } + var word = source.get(); + return {type: "string", style: "scheme-string", content: word, + isUnclosed: isUnclosedString}; + }; + + + var readPound = function() { + var text; + // FIXME: handle special things here + if (source.equals(";")) { + source.next(); + text = source.get(); + return {type: text, + style:"scheme-symbol", + content: text}; + } else { + text = source.get(); + + return {type : "symbol", + style: "scheme-symbol", + content: text}; + } + + }; + + var readLineComment = function() { + scanUntilEndline(source); + var text = source.get(); + return { type: "comment", style: "scheme-comment", content: text}; + }; + + + var readWhitespace = function() { + source.nextWhile(isWhiteSpace); + var content = source.get(); + return { type: 'whitespace', style:'whitespace', content: content }; + }; + + var readNewline = function() { + var content = source.get(); + return { type:'whitespace', style:'whitespace', content: content }; + }; + + + // Fetch the next token. Dispatches on first character in the + // stream, or first two characters when the first is a slash. + var ch = source.next(); + if (ch === '\n') { + return readNewline(); + } else if (whitespaceChar.test(ch)) { + return readWhitespace(); + } else if (ch === "#") { + return readPound(); + } else if (ch ===';') { + return readLineComment(); + } else if (ch === "\"") { + return readString(ch); + } else if (isDelimiterChar.test(ch)) { + return {type: ch, style: "scheme-punctuation"}; + } else { + return readWordOrNumber(); + } + } + + + + + + + + var makeTokenizer = function(source, state) { + // Newlines are always a separate token. + + var tokenizer = { + state: state, + + take: function(type) { + if (typeof(type) == "string") + type = {style: type, type: type}; + + type.content = (type.content || "") + source.get(); + type.value = type.content; + return type; + }, + + next: function () { + if (!source.more()) throw StopIteration; + + var type; + while (!type) { + type = tokenizer.state(source, function(s) { + tokenizer.state = s; + }); + } + var result = this.take(type); + return result; + } + }; + return tokenizer; + }; + + + // The external interface to the tokenizer. + return function(source, startState) { + return makeTokenizer(source, startState || START); + }; +})(); diff --git a/gulliver/js/codemirror/contrib/sql/LICENSE b/gulliver/js/codemirror/contrib/sql/LICENSE new file mode 100755 index 000000000..e3c6d2174 --- /dev/null +++ b/gulliver/js/codemirror/contrib/sql/LICENSE @@ -0,0 +1,22 @@ + Copyright (c) 2009 John Benediktsson + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any + damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and + redistribute it freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + John Benediktsson diff --git a/gulliver/js/codemirror/contrib/sql/css/sqlcolors.css b/gulliver/js/codemirror/contrib/sql/css/sqlcolors.css new file mode 100755 index 000000000..958425222 --- /dev/null +++ b/gulliver/js/codemirror/contrib/sql/css/sqlcolors.css @@ -0,0 +1,59 @@ +html { + cursor: text; +} + +.editbox { + margin: .4em; + padding: 0; + font-family: monospace; + font-size: 10pt; + color: black; +} + +.editbox p { + margin: 0; +} + +span.sql-keyword { + color: blue; +} + +span.sql-var { + color: red; +} + +span.sql-comment { + color: #AA7700; +} + +span.sql-literal { + color: green; +} + +span.sql-operator { + color: blue; +} + +span.sql-word { + color: black; +} + +span.sql-quoted-word { + color: #680; +} + +span.sql-function { + color: darkorange; +} + +span.sql-type { + color: purple; +} + +span.sql-separator { + color: #666666; +} + +span.sql-number { + color: darkcyan; +} diff --git a/gulliver/js/codemirror/contrib/sql/index.html b/gulliver/js/codemirror/contrib/sql/index.html new file mode 100755 index 000000000..3cea8ed20 --- /dev/null +++ b/gulliver/js/codemirror/contrib/sql/index.html @@ -0,0 +1,56 @@ + + + + CodeMirror: SQL demonstration + + + + +

Demonstration of CodeMirror's SQL +highlighter.

+ +

Written by John Benediktsson (license).

+ +
+ +
+ + + + + diff --git a/gulliver/js/codemirror/contrib/sql/js/parsesql.js b/gulliver/js/codemirror/contrib/sql/js/parsesql.js new file mode 100755 index 000000000..9b05d6066 --- /dev/null +++ b/gulliver/js/codemirror/contrib/sql/js/parsesql.js @@ -0,0 +1,267 @@ +var SqlParser = Editor.Parser = (function() { + + function wordRegexp(words) { + return new RegExp("^(?:" + words.join("|") + ")$", "i"); + } + + var functions = wordRegexp([ + "abs", "acos", "adddate", "aes_encrypt", "aes_decrypt", "ascii", + "asin", "atan", "atan2", "avg", "benchmark", "bin", "bit_and", + "bit_count", "bit_length", "bit_or", "cast", "ceil", "ceiling", + "char_length", "character_length", "coalesce", "concat", "concat_ws", + "connection_id", "conv", "convert", "cos", "cot", "count", "curdate", + "current_date", "current_time", "current_timestamp", "current_user", + "curtime", "database", "date_add", "date_format", "date_sub", + "dayname", "dayofmonth", "dayofweek", "dayofyear", "decode", "degrees", + "des_encrypt", "des_decrypt", "elt", "encode", "encrypt", "exp", + "export_set", "extract", "field", "find_in_set", "floor", "format", + "found_rows", "from_days", "from_unixtime", "get_lock", "greatest", + "group_unique_users", "hex", "ifnull", "inet_aton", "inet_ntoa", "instr", + "interval", "is_free_lock", "isnull", "last_insert_id", "lcase", "least", + "left", "length", "ln", "load_file", "locate", "log", "log2", "log10", + "lower", "lpad", "ltrim", "make_set", "master_pos_wait", "max", "md5", + "mid", "min", "mod", "monthname", "now", "nullif", "oct", "octet_length", + "ord", "password", "period_add", "period_diff", "pi", "position", + "pow", "power", "quarter", "quote", "radians", "rand", "release_lock", + "repeat", "reverse", "right", "round", "rpad", "rtrim", "sec_to_time", + "session_user", "sha", "sha1", "sign", "sin", "soundex", "space", "sqrt", + "std", "stddev", "strcmp", "subdate", "substring", "substring_index", + "sum", "sysdate", "system_user", "tan", "time_format", "time_to_sec", + "to_days", "trim", "ucase", "unique_users", "unix_timestamp", "upper", + "user", "version", "week", "weekday", "yearweek" + ]); + + var keywords = wordRegexp([ + "alter", "grant", "revoke", "primary", "key", "table", "start", "top", + "transaction", "select", "update", "insert", "delete", "create", "describe", + "from", "into", "values", "where", "join", "inner", "left", "natural", "and", + "or", "in", "not", "xor", "like", "using", "on", "order", "group", "by", + "asc", "desc", "limit", "offset", "union", "all", "as", "distinct", "set", + "commit", "rollback", "replace", "view", "database", "separator", "if", + "exists", "null", "truncate", "status", "show", "lock", "unique", "having", + "drop", "procedure", "begin", "end", "delimiter", "call", "else", "leave", + "declare", "temporary", "then" + ]); + + var types = wordRegexp([ + "bigint", "binary", "bit", "blob", "bool", "char", "character", "date", + "datetime", "dec", "decimal", "double", "enum", "float", "float4", "float8", + "int", "int1", "int2", "int3", "int4", "int8", "integer", "long", "longblob", + "longtext", "mediumblob", "mediumint", "mediumtext", "middleint", "nchar", + "numeric", "real", "set", "smallint", "text", "time", "timestamp", "tinyblob", + "tinyint", "tinytext", "varbinary", "varchar", "year" + ]); + + var operators = wordRegexp([ + ":=", "<", "<=", "==", "<>", ">", ">=", "like", "rlike", "in", "xor", "between" + ]); + + var operatorChars = /[*+\-<>=&|:\/]/; + + var CFG = {}; + + var tokenizeSql = (function() { + function normal(source, setState) { + var ch = source.next(); + if (ch == "@" || ch == "$") { + source.nextWhileMatches(/[\w\d]/); + return "sql-var"; + } + else if (ch == "["){ + setState(inAlias(ch)) + return null; + } + else if (ch == "\"" || ch == "'" || ch == "`") { + setState(inLiteral(ch)); + return null; + } + else if (ch == "," || ch == ";") { + return "sql-separator" + } + else if (ch == '#') { + while (!source.endOfLine()) source.next(); + return "sql-comment"; + } + else if (ch == '-') { + if (source.peek() == "-") { + while (!source.endOfLine()) source.next(); + return "sql-comment"; + } + else if (/\d/.test(source.peek())) { + source.nextWhileMatches(/\d/); + if (source.peek() == '.') { + source.next(); + source.nextWhileMatches(/\d/); + } + return "sql-number"; + } + else + return "sql-operator"; + } + else if (operatorChars.test(ch)) { + + if(ch == "/" && source.peek() == "*"){ + setState(inBlock("sql-comment", "*/")); + return null; + } + else{ + source.nextWhileMatches(operatorChars); + return "sql-operator"; + } + + } + else if (/\d/.test(ch)) { + source.nextWhileMatches(/\d/); + if (source.peek() == '.') { + source.next(); + source.nextWhileMatches(/\d/); + } + return "sql-number"; + } + else if (/[()]/.test(ch)) { + return "sql-punctuation"; + } + else { + source.nextWhileMatches(/[_\w\d]/); + var word = source.get(), type; + if (operators.test(word)) + type = "sql-operator"; + else if (keywords.test(word)) + type = "sql-keyword"; + else if (functions.test(word)) + type = "sql-function"; + else if (types.test(word)) + type = "sql-type"; + else + type = "sql-word"; + return {style: type, content: word}; + } + } + + function inAlias(quote) { + return function(source, setState) { + while (!source.endOfLine()) { + var ch = source.next(); + if (ch == ']') { + setState(normal); + break; + } + } + return "sql-word"; + } + } + + function inLiteral(quote) { + return function(source, setState) { + var escaped = false; + while (!source.endOfLine()) { + var ch = source.next(); + if (ch == quote && !escaped) { + setState(normal); + break; + } + escaped = CFG.extension == 'T-SQL' ? + !escaped && quote == ch && source.equals(quote) : + !escaped && ch == "\\"; + } + return quote == "`" ? "sql-quoted-word" : "sql-literal"; + }; + } + + function inBlock(style, terminator) { + return function(source, setState) { + while (!source.endOfLine()) { + if (source.lookAhead(terminator, true)) { + setState(normal); + break; + } + source.next(); + } + return style; + }; + } + + return function(source, startState) { + return tokenizer(source, startState || normal); + }; + })(); + + function indentSql(context) { + return function(nextChars) { + var firstChar = nextChars && nextChars.charAt(0); + var closing = context && firstChar == context.type; + if (!context) + return 0; + else if (context.align) + return context.col - (closing ? context.width : 0); + else + return context.indent + (closing ? 0 : indentUnit); + } + } + + function parseSql(source) { + var tokens = tokenizeSql(source); + var context = null, indent = 0, col = 0; + function pushContext(type, width, align) { + context = {prev: context, indent: indent, col: col, type: type, width: width, align: align}; + } + function popContext() { + context = context.prev; + } + + var iter = { + next: function() { + var token = tokens.next(); + var type = token.style, content = token.content, width = token.value.length; + + if (content == "\n") { + token.indentation = indentSql(context); + indent = col = 0; + if (context && context.align == null) context.align = false; + } + else if (type == "whitespace" && col == 0) { + indent = width; + } + else if (!context && type != "sql-comment") { + pushContext(";", 0, false); + } + + if (content != "\n") col += width; + + if (type == "sql-punctuation") { + if (content == "(") + pushContext(")", width); + else if (content == ")") + popContext(); + } + else if (type == "sql-separator" && content == ";" && context && !context.prev) { + popContext(); + } + + return token; + }, + + copy: function() { + var _context = context, _indent = indent, _col = col, _tokenState = tokens.state; + return function(source) { + tokens = tokenizeSql(source, _tokenState); + context = _context; + indent = _indent; + col = _col; + return iter; + }; + } + }; + return iter; + } + + function configure (parserConfig) { + for (var p in parserConfig) { + if (parserConfig.hasOwnProperty(p)) { + CFG[p] = parserConfig[p]; + } + } + } + + return {make: parseSql, electricChars: ")", configure: configure}; +})(); diff --git a/gulliver/js/codemirror/contrib/xquery/LICENSE b/gulliver/js/codemirror/contrib/xquery/LICENSE new file mode 100755 index 000000000..dd8e3e824 --- /dev/null +++ b/gulliver/js/codemirror/contrib/xquery/LICENSE @@ -0,0 +1,13 @@ +Copyright 2010 Mike Brevoort + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/gulliver/js/codemirror/contrib/xquery/css/xqcolors-dark.css b/gulliver/js/codemirror/contrib/xquery/css/xqcolors-dark.css new file mode 100755 index 000000000..97e538307 --- /dev/null +++ b/gulliver/js/codemirror/contrib/xquery/css/xqcolors-dark.css @@ -0,0 +1,93 @@ + +.editbox { + margin: .4em; + padding: 0; + font-family: monospace; + font-size: 10pt; + color: white; + background-color: black; + line-height: 16px; +} + +span.word { + color:white; +} + +span.xqueryKeyword { + color: #ffbd40; + /* font-weight: bold; */ +} + +span.xqueryComment { + color: #CDCDCD; + font-style:italic; +} + +span.xqueryModifier { +color:#6c8cd5; + font-weight: bold; +} + +span.xqueryType { + color:#6c8cd5; + font-weight: bold; +} + +span.xqueryAtom { + color:#6c8cd5; + font-weight: bold; +} + +span.xqueryString { + color: #9fee00; +} + +span.xqueryRegexp { + color: rgb(128,0,64); +} + +span.xqueryNumber { + color: rgb(255,0,0); +} + +span.xqueryVariable { + +} + +span.xqueryFunction { + color:#FFF700; +} + +span.xqueryLocalvariable { + color: white; +} + +span.xqueryProperty +{ + color: white; +} + +span.xqueryOperator { + color: orange; +} + +span.xqueryPunctuation { + color: white; +} + +span.xquery-doc-directive { + color: white; +} + +span.xml-tagname { + color: #ffbd40; ; +} + +span.xml-attribute { + color: #FFF700; +} + +span.xml-attribute-value { + color: #FFF700; + font-style:italic; +} \ No newline at end of file diff --git a/gulliver/js/codemirror/contrib/xquery/css/xqcolors.css b/gulliver/js/codemirror/contrib/xquery/css/xqcolors.css new file mode 100755 index 000000000..058c1815f --- /dev/null +++ b/gulliver/js/codemirror/contrib/xquery/css/xqcolors.css @@ -0,0 +1,99 @@ +/* +Copyright 2010 Mike Brevoort http://mike.brevoort.com (twitter:@mbrevoort) + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +This is an indirect collective derivative of the other parses in this package + +*/ +.editbox { + margin: .4em; + padding: 0; + font-family: monospace; + font-size: 10pt; + color: black; + background-color: white; + line-height: 16px; +} + +span.word { +} + +span.xqueryKeyword { + color: red; /* #1240AB; */ + /* font-weight: bold; */ +} + +span.xqueryComment { + color: gray; + font-style: italic; +} + +span.xqueryModifier { + color: rgb(0,102,153); + font-weight: bold; +} + +span.xqueryType { + color: purple; + font-weight: bold; +} + +span.xqueryAtom { + color: rgb(0,102,153); + font-weight: bold; +} + +span.xqueryString { + color: green; +} + +span.xqueryRegexp { + color: rgb(128,0,64); +} + +span.xqueryNumber { + color: #1240AB; +} + +span.xqueryVariable { + /* color: red; */ +} + +span.xqueryFunction { + color: #1240AB; + /* font-weight:bold; */ +} + + +span.xqueryOperator { + color: red; +} + +span.xqueryPunctuation { + color: DIMGray; +} + +span.xml-tagname { + color: purple; +} + +span.xml-attribute { + color: purple; + font-style:italic; +} + +span.xml-attribute-value { + color: purple; + font-style:italic; +} \ No newline at end of file diff --git a/gulliver/js/codemirror/contrib/xquery/css/xqcolors2.css b/gulliver/js/codemirror/contrib/xquery/css/xqcolors2.css new file mode 100755 index 000000000..accb7f734 --- /dev/null +++ b/gulliver/js/codemirror/contrib/xquery/css/xqcolors2.css @@ -0,0 +1,96 @@ +/* +Copyright 2010 Mike Brevoort http://mike.brevoort.com (twitter:@mbrevoort) + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +This is an indirect collective derivative of the other parses in this package + +*/ +.editbox { + margin: .4em; + padding: 0; + font-family: monospace; + font-size: 10pt; + color: black; + background-color: white; + line-height: 16px; +} + +span.word { +} + +span.xqueryKeyword { + color: blue; + /* font-weight: bold; */ +} + +span.xqueryComment { + color: gray; +} + +span.xqueryModifier { + color: rgb(0,102,153); + font-weight: bold; +} + +span.xqueryType { + color: rgb(0,135,255); + font-weight: bold; +} + +span.xqueryAtom { + color: rgb(0,102,153); + font-weight: bold; +} + +span.xqueryString { + color: green; +} + +span.xqueryRegexp { + color: rgb(128,0,64); +} + +span.xqueryNumber { + color: rgb(255,0,0); +} + +span.xqueryVariable { + color: red; +} + +span.xqueryFunction { + text-decoration:underline +} + + +span.xqueryOperator { + color: DimGray; +} + +span.xqueryPunctuation { +} + +span.xml-tagname { + color: purple; +} + +span.xml-attribute { + color: purple; + font-style:italic; +} + +span.xml-attribute-value { + color: purple; + font-style:italic; +} \ No newline at end of file diff --git a/gulliver/js/codemirror/contrib/xquery/index.html b/gulliver/js/codemirror/contrib/xquery/index.html new file mode 100755 index 000000000..eb1150f5b --- /dev/null +++ b/gulliver/js/codemirror/contrib/xquery/index.html @@ -0,0 +1,552 @@ + + + + + CodeMirror: XQuery highlighting demonstration + + + + +
+

XQuery Syntax Support for CodeMirror

+

This is a demonstration of the XQuery highlighting module +for CodeMirror. The formatting is CSS driven and very easy to customize to your liking. +There are three sample styles sets below. +You can edit or paste in any code below to give it a test run. +

+ +Light 1 Light 2 Dark + +
+ +
+ + +
+ + + diff --git a/gulliver/js/codemirror/contrib/xquery/js/parsexquery.js b/gulliver/js/codemirror/contrib/xquery/js/parsexquery.js new file mode 100755 index 000000000..56468c2db --- /dev/null +++ b/gulliver/js/codemirror/contrib/xquery/js/parsexquery.js @@ -0,0 +1,234 @@ +/* +Copyright 2010 Mike Brevoort http://mike.brevoort.com (twitter:@mbrevoort) + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +This is an indirect collective derivative of the other parses in this package + +*/ + +// The XQuery parser uses the xquery tokenizer in tokenizexquery.js. Given the +// stream of tokens, it makes decisions to override the tokens styles by evaluating +// it's context with respect to the other tokens. + +var XqueryParser = Editor.Parser = (function() { + function xqueryLexical(startColumn, currentToken, align, previousToken, encloseLevel) { + this.startColumn = startColumn; + this.currentToken = currentToken; + if (align != null) + this.align = align; + this.previousToken = previousToken; + this.encloseLevel = encloseLevel; + } + + // Xquery indentation rules. + function indentXquery(lexical) { + return function(firstChars, curIndent, direction) { + // test if this is next row after the open brace + if (lexical.encloseLevel !== 0 && firstChars === "}") { + return lexical.startColumn - indentUnit; + } + + return lexical.startColumn; + }; + } + + function parseXquery(source) { + var tokens = tokenizeXquery(source); + + var column = 0; + // tells the first non-whitespace symbol from the + // start of row. + var previousToken = null; + var previousTokens = []; + //mb + var align = false; + // tells if the text after the open brace + var encloseLevel = 0; + // tells curent opened braces quantity + var cc = [statements]; + var consume, + marked; + + var iter = { + next: function() { + var token = tokens.next(); + // since attribute and elements can be named the same, assume the + // following word of each is a variable + if (previousToken && (previousToken.content == "attribute" || previousToken.content == "element") && previousToken.type == "xqueryKeywordC") { + token.type = "variable"; + token.style = "xqueryVariable"; + } + + else if (previousToken && previousToken.content == "xquery" && token.content == "version") { + //token.type="variable"; + token.style = "xqueryModifier"; + } + + else if (token.type == "word" && (getPrevious(3).style == "xml-attribute" || (previousToken && previousToken.type == "xml-tag-open")) && + previousToken.content.substring(previousToken.content.length - 1) != ">") { + token.style = "xml-attribute"; + } + else if (previousToken && previousToken.content == "=" && previousTokens.length > 2 + && getPrevious(2).style == "xml-attribute") { + token.style = "xml-attribute-value"; + } + else if(token.type == "string" && previousToken && previousToken.type == "}") { + // looking for expressions within a string and detecting if the expression is within an attribute + var i=0; + while(i++ < previousTokens.length-1) { + if(getPrevious(i).style == "xml-attribute-value" ) { + token.style = "xml-attribute-value"; + break; + } + else if(getPrevious(i).type == "string") { + break; + } + } + } + else if(token.type == "string") { + // brute force check for strings inside XML TODO... something else + var i=0; + var closeCount = 0; + while(i++ < previousTokens.length-1) { + var prev = getPrevious(i); + if(prev.type == "xml-tag-open") { + if(closeCount == 0) { + token.style = "word"; + break; + } else { + closeCount--; + } + } + else if(prev.type == "xml-tag-close") { + closeCount++; + } + else if(prev.content == ":=" || prev.content == "return" || prev.content == "{") + break; + } + } + else if(getPrevious(2).content == "module" && getPrevious(1).content == "namespace") + token.style="xqueryFunction"; + else if(token.content == "=" && getPrevious(1).style == "xml-attribute") + token.style="xml-attribute" + + if (token.type == "whitespace") { + if (token.value == "\n") { + // test if this is end of line + if (previousToken !== null) { + if (previousToken.type === "{") { + // test if there is open brace at the end of line + align = true; + column += indentUnit; + encloseLevel++; + } + else + if (previousToken.type === "}") { + // test if there is close brace at the end of line + align = false; + if (encloseLevel > 0) { + encloseLevel--; + } + else { + encloseLevel = 0; + } + } + var lexical = new xqueryLexical(column, token, align, previousToken, encloseLevel); + token.indentation = indentXquery(lexical); + } + } + else + column = token.value.length; + } + + // maintain the previous tokens array so that it doesn't continue to leak + // keep only the last 5000 + if(previousTokens.length > 5000) previousTokens.shift(); + + while (true) { + consume = marked = false; + // Take and execute the topmost action. + cc.pop()(token.type, token.content); + if (consume) { + // Marked is used to change the style of the current token. + if (marked) + token.style = marked; + // Here we differentiate between local and global variables. + previousToken = token; + previousTokens[previousTokens.length] = token; + return token; + } + } + + }, + + copy: function() { + var _cc = cc.concat([]), + _tokenState = tokens.state, + _column = column; + + return function copyParser(_source) { + cc = _cc.concat([]); + column = indented = _column; + tokens = tokenizeXquery(_source, _tokenState); + return iter; + }; + + }, + + }; + + function statements(type) { + return pass(statement, statements); + } + + function statement(type) { + cont(); + } + + function push(fs) { + for (var i = fs.length - 1; i >= 0; i--) + cc.push(fs[i]); + } + + function cont() { + push(arguments); + consume = true; + } + + function pass() { + push(arguments); + consume = false; + } + + + function getPrevious(numberFromCurrent) { + var l = previousTokens.length; + if (l - numberFromCurrent >= 0) + return previousTokens[l - numberFromCurrent]; + else + return { + type: "", + style: "", + content: "" + }; + } + + return iter; + + + } + return { + make: parseXquery + }; +})(); \ No newline at end of file diff --git a/gulliver/js/codemirror/contrib/xquery/js/tokenizexquery.js b/gulliver/js/codemirror/contrib/xquery/js/tokenizexquery.js new file mode 100755 index 000000000..7f68b578f --- /dev/null +++ b/gulliver/js/codemirror/contrib/xquery/js/tokenizexquery.js @@ -0,0 +1,457 @@ +/* +Copyright 2010 Mike Brevoort http://mike.brevoort.com (twitter:@mbrevoort) + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +This is an indirect collective derivative of the other parses in this package + +*/ + +// A tokenizer for xQuery, looks at the source stream and tokenizes, applying +// metadata to be able to apply the proper CSS classes in the parser. + +var tokenizeXquery = (function() { + // Advance the stream until the given character (not preceded by a + // backslash) is encountered, or the end of the line is reached. + function nextUntilUnescaped(source, end) { + var escaped = false; + while (!source.endOfLine()) { + var next = source.next(); + if (next == end && !escaped) + return false; + escaped = !escaped && next == "\\"; + } + return escaped; + } + + // A map of Xquery's keywords. The a/b/c keyword distinction is + // very rough, but it gives the parser enough information to parse + // correct code correctly (we don't care that much how we parse + // incorrect code). The style information included in these objects + // is used by the highlighter to pick the correct CSS style for a + // token. + var keywords = function() { + function result(type, style) { + return { + type: type, + style: style + }; + } + + var allKeywords = {}; + var keywordsList = {}; + + // an array of all of the keywords that will be used by default, otherwise keywords will be more specifically specified and overridden below + var allKeywordsArray = new Array('after','ancestor','ancestor-or-self','and','as','ascending','assert','attribute','before','by','case','cast','child','comment','comment','declare','default','define','descendant','descendant-or-self','descending','document-node','element','element','else','eq','every','except','external','following','following-sibling','follows','for','function','if','import','in','instance','intersect','item','let','module','namespace','node','node','of','only','or','order','parent','precedes','preceding','preceding-sibling','processing-instruction','ref','return','returns','satisfies','schema','schema-element','self','some','sortby','stable','text','then','to','treat','typeswitch','union','variable','version','where','xquery'); + + for(var i in allKeywordsArray) { + allKeywords[allKeywordsArray[i]] = result("keyword", "xqueryKeyword"); + } + + /* This next bit is broken down this was for future indentation support */ + // keywords that take a parenthised expression, and then a statement (if) + keywordsList['xqueryKeywordA'] = new Array('if', 'switch', 'while', 'for'); + + // keywords that take just a statement (else) + keywordsList['xqueryKeywordB'] = new Array('else', 'then', 'try', 'finally'); + + // keywords that optionally take an expression, and form a statement (return) + keywordsList['xqueryKeywordC'] = new Array('element', 'attribute', 'let', 'implements', 'import', 'module', 'namespace', 'return', 'super', 'this', 'throws', 'where'); + + keywordsList['xqueryOperator'] = new Array('eq', 'ne', 'lt', 'le', 'gt', 'ge'); + + for (var keywordType in keywordsList) { + for (var i = 0; i < keywordsList[keywordType].length; i++) { + allKeywords[keywordsList[keywordType][i]] = result(keywordType, "xqueryKeyword"); + } + } + + keywordsList = {}; + + keywordsList['xqueryAtom'] = new Array('null', 'fn:false()', 'fn:true()'); + for (var keywordType in keywordsList) { + for (var i = 0; i < keywordsList[keywordType].length; i++) { + allKeywords[keywordsList[keywordType][i]] = result(keywordType, keywordType); + } + } + + keywordsList = {}; + keywordsList['xqueryModifier'] = new Array('xquery', 'ascending', 'descending'); + keywordsList['xqueryType'] = new Array('xs:string', 'xs:float', 'xs:decimal', 'xs:double', 'xs:integer', 'xs:boolean', 'xs:date', 'xs:dateTime', 'xs:time', 'xs:duration', 'xs:dayTimeDuration', 'xs:time', 'xs:yearMonthDuration', 'numeric', 'xs:hexBinary', 'xs:base64Binary', 'xs:anyURI', 'xs:QName', 'xs:byte','xs:boolean','xs:anyURI','xf:yearMonthDuration'); + for (var keywordType in keywordsList) { + for (var i = 0; i < keywordsList[keywordType].length; i++) { + allKeywords[keywordsList[keywordType][i]] = result('function', keywordType); + } + } + + allKeywords = objectConcat(allKeywords, { + "catch": result("catch", "xqueryKeyword"), + "for": result("for", "xqueryKeyword"), + "case": result("case", "xqueryKeyword"), + "default": result("default", "xqueryKeyword"), + "instanceof": result("operator", "xqueryKeyword") + }); + + // ------------------- xquery keywords + var keywordsList = {}; + + // keywords that optionally take an expression, and form a statement (return) + keywordsList['xqueryKeywordC'] = new Array('assert', 'property'); + for (var i = 0; i < keywordsList['xqueryKeywordC'].length; i++) { + allKeywords[keywordsList['xqueryKeywordC'][i]] = result("xqueryKeywordC", "xqueryKeyword"); + } + + // other xquery keywords + allKeywords = objectConcat(allKeywords, { + "as": result("operator", "xqueryKeyword"), + "in": result("operator", "xqueryKeyword"), + "at": result("operator", "xqueryKeyword"), + "declare": result("function", "xqueryKeyword"), + "function": result("function", "xqueryKeyword") + }); + return allKeywords; + } (); + + // there are some special cases where ordinarily text like xs:string() would + // look like a function call when it is really a type, etc. + function specialCases(source, word) { + if (word in { + "fn:true": "", + "fn:false": "" + } && source.lookAhead("()", false)) { + source.next(); + source.next(); + source.get(); + return { + type: "function", + style: "xqueryAtom", + content: word + "()" + }; + } + else if (word in { + "node": "", + "item": "", + "text": "" + } && source.lookAhead("()", false)) { + source.next(); + source.next(); + source.get(); + return { + type: "function", + style: "xqueryType", + content: word + "()" + }; + } + else if (source.lookAhead("(")) { + return { + type: "function", + style: "xqueryFunction", + content: word + }; + } + else return null; + } + + // Some helper regexp matchers. + var isOperatorChar = /[=+\-*&%!?@\/]/; + var isDigit = /[0-9]/; + var isHexDigit = /^[0-9A-Fa-f]$/; + var isWordChar = /[\w\:\-\$_]/; + var isVariableChar = /[\w\$_-]/; + var isXqueryVariableChar = /[\w\.()\[\]{}]/; + var isPunctuation = /[\[\]{}\(\),;\.]/; + var isStringDelimeter = /^[\/'"]$/; + var isRegexpDelimeter = /^[\/'$]/; + var tagnameChar = /[<\w\:\-\/_]/; + + // Wrapper around xqueryToken that helps maintain parser state (whether + // we are inside of a multi-line comment and whether the next token + // could be a regular expression). + function xqueryTokenState(inside, regexp) { + return function(source, setState) { + var newInside = inside; + var type = xqueryToken(inside, regexp, source, + function(c) { + newInside = c; + }); + var newRegexp = type.type == "operator" || type.type == "xqueryKeywordC" || type.type == "xqueryKeywordC" || type.type.match(/^[\[{}\(,;:]$/); + if (newRegexp != regexp || newInside != inside) + setState(xqueryTokenState(newInside, newRegexp)); + return type; + }; + } + + // The token reader, inteded to be used by the tokenizer from + // tokenize.js (through xqueryTokenState). Advances the source stream + // over a token, and returns an object containing the type and style + // of that token. + function xqueryToken(inside, regexp, source, setInside) { + function readHexNumber() { + setInside(null); + source.next(); + // skip the 'x' + source.nextWhileMatches(isHexDigit); + return { + type: "number", + style: "xqueryNumber" + }; + } + + function readNumber() { + setInside(null); + source.nextWhileMatches(isDigit); + if (source.equals(".")) { + source.next(); + + // read ranges + if (source.equals(".")) + source.next(); + + source.nextWhileMatches(isDigit); + } + if (source.equals("e") || source.equals("E")) { + source.next(); + if (source.equals("-")) + source.next(); + source.nextWhileMatches(isDigit); + } + return { + type: "number", + style: "xqueryNumber" + }; + } + // Read a word, look it up in keywords. If not found, it is a + // variable, otherwise it is a keyword of the type found. + function readWord() { + //setInside(null); + source.nextWhileMatches(isWordChar); + var word = source.get(); + var specialCase = specialCases(source, word); + if (specialCase) return specialCase; + var known = keywords.hasOwnProperty(word) && keywords.propertyIsEnumerable(word) && keywords[word]; + if (known) return { + type: known.type, + style: known.style, + content: word + } + return { + type: "word", + style: "word", + content: word + }; + } + + + // read regexp like /\w{1}:\\.+\\.+/ + function readRegexp() { + // go to the end / not \/ + nextUntilUnescaped(source, "/"); + + return { + type: "regexp", + style: "xqueryRegexp" + }; + } + + // Mutli-line comments are tricky. We want to return the newlines + // embedded in them as regular newline tokens, and then continue + // returning a comment token for every line of the comment. So + // some state has to be saved (inside) to indicate whether we are + // inside a (: :) sequence. + function readMultilineComment(start) { + var newInside = "(:"; + var maybeEnd = (start == ":"); + while (true) { + if (source.endOfLine()) + break; + var next = source.next(); + if (next == ")" && maybeEnd) { + newInside = null; + break; + } + maybeEnd = (next == ":"); + } + setInside(newInside); + return { + type: "comment", + style: "xqueryComment" + }; + } + + function readOperator() { + if (ch == "=") + setInside("=") + else if (ch == "~") + setInside("~") + else if (ch == ":" && source.equals("=")) { + setInside(null); + source.nextWhileMatches(/[:=]/); + var word = source.get(); + return { + type: "operator", + style: "xqueryOperator", + content: word + }; + } + else setInside(null); + + return { + type: "operator", + style: "xqueryOperator" + }; + } + + // read a string, but look for embedded expressions wrapped in curly + // brackets. + function readString(quote) { + var newInside = quote; + var previous = ""; + while (true) { + if (source.endOfLine()) + break; + if(source.lookAhead("{", false)) { + newInside = quote + "{"; + break; + } + var next = source.next(); + if (next == quote && previous != "\\") { + newInside = null; + break; + } + previous = next; + } + setInside(newInside); + return { + type: "string", + style: "xqueryString" + }; + } + + // Given an expression end by a closing curly bracket, mark the } as + // punctuation an resume the string processing by setting "inside" to + // the type of string it's embedded in. + // This is known because the readString() function sets inside to the + // quote type then an open curly bracket like "{ or '{ + function readExpressionEndInString(inside) { + var quote = inside.substr(0,1); + setInside(quote); + return { type: ch, style: "xqueryPunctuation"}; + } + + function readVariable() { + //setInside(null); + source.nextWhileMatches(isVariableChar); + var word = source.get(); + return { + type: "variable", + style: "xqueryVariable", + content: word + }; + } + + // read an XML Tagname, both closing and opening + function readTagname(lt) { + var tagtype = (source.lookAhead("/", false)) ? "xml-tag-close": "xml-tag-open"; + source.nextWhileMatches(tagnameChar); + var word = source.get(); + if (source.lookAhead(">", false)) { + source.next(); + } + return { + type: tagtype, + style: "xml-tagname", + content: word + }; + } + + // Fetch the next token. Dispatches on first character in the stream + // what follows is a big if statement that makes decisions based on the + // character, the following character and the inside variable + + if (inside == "\"" || inside == "'") + return readString(inside); + + var ch = source.next(); + if (inside && inside.indexOf("{") == 1 && ch == "}") { + return readExpressionEndInString(inside); + } + if (inside == "(:") + return readMultilineComment(ch); + else if (ch == "\"" || ch == "'") + return readString(ch); + + + // test if this is range + else if (ch == "." && source.equals(".")) { + source.next(); + return { + type: "..", + style: "xqueryOperator" + }; + } + + else if (ch == "(" && source.equals(":")) { + source.next(); + return readMultilineComment(ch); + } + else if (ch == "$") + return readVariable(); + else if (ch == ":" && source.equals("=")) + return readOperator(); + + // with punctuation, the type of the token is the symbol itself + else if (isPunctuation.test(ch)) + return { + type: ch, + style: "xqueryPunctuation" + }; + else if (ch == "0" && (source.equals("x") || source.equals("X"))) + return readHexNumber(); + else if (isDigit.test(ch)) + return readNumber(); + + else if (ch == "~") { + setInside("~"); + // prepare to read slashy string like ~ /\w{1}:\\.+\\.+/ + return readOperator(ch); + } + else if (isOperatorChar.test(ch)) { + return readOperator(ch); + } + // some xml handling stuff + else if (ch == "<") + return readTagname(ch); + else if (ch == ">") + return { + type: "xml-tag", + style: "xml-tagname" + }; + else + return readWord(); + } + + // returns new object = object1 + object2 + function objectConcat(object1, object2) { + for (var name in object2) { + if (!object2.hasOwnProperty(name)) continue; + if (object1.hasOwnProperty(name)) continue; + object1[name] = object2[name]; + } + return object1; + } + + // The external interface to the tokenizer. + return function(source, startState) { + return tokenizer(source, startState || xqueryTokenState(false, true)); + }; +})(); \ No newline at end of file diff --git a/gulliver/js/codemirror/css/baboon.png b/gulliver/js/codemirror/css/baboon.png new file mode 100755 index 000000000..6978aa144 Binary files /dev/null and b/gulliver/js/codemirror/css/baboon.png differ diff --git a/gulliver/js/codemirror/css/baboon_vector.ai b/gulliver/js/codemirror/css/baboon_vector.ai new file mode 100755 index 000000000..bbe1583fa --- /dev/null +++ b/gulliver/js/codemirror/css/baboon_vector.ai @@ -0,0 +1,962 @@ +%PDF-1.5 %âãÏÓ +1 0 obj <>/OCGs[5 0 R 6 0 R]>>/Pages 3 0 R/Type/Catalog>> endobj 2 0 obj <>stream + + + + + application/pdf + + + codemirror_baboon + + + + + Adobe Illustrator CS5 + 2010-10-08T15:33:07+02:00 + 2010-10-08T15:33:07+02:00 + 2010-10-08T15:33:07+02:00 + + + + 256 + 148 + JPEG + /9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgAlAEAAwER AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE 1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp 0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo +DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A9U4qgNZ1/Q9Dsze6zqFt ptoNjPdypClfDk5UV9sVeReaf+cuvym0cvFp0t1rtwuwFnCUi5e8s5i291DYq8r17/nNzzXOzLoP l6ysYzUK95JLdvTx/d/VlB+/6cVYFq3/ADlF+dmolgNeFlE3+6rS2t46dtnKNJ/w2KoS21j/AJyL 80sGs7vzRqMbbg27Xvojrv8Au6Rjr1xVNbf/AJx6/wCcgtZieW8065SLieTX17HyIUV4+mZHkPt8 OKs9/wCcH9ZEes+aNEZt7m3tr2ND1H1d3icj/pIWv0Yq+tsVdirsVdirsVWXFxBbwSXFxIsMESl5 ZZGCoqqKlmY0AAHfFXj3mr/nLD8otD5xWl5Prt0lR6enxEpy7VmmMUZHuhbFXjnmr/nNXzlec4vL ej2mkxHZZ7lmvJx7j+6jHyKNir3X8u/z5/LjWPLmkR6h5tsjr/1S3XUzdkWJa79NfWosqwx/3lac NvDFXpttdWt1Cs9rMk8LfZliYOp+TKSMVVcVdirsVdirsVdirsVdirsVdirsVdirsVdir4q8/f8A OWH5parf3Gj6JbR+WgsrWzRQAXN5zDFChmkXiDy/kjB98VYBrPkbz1fX0l7521q10686Sy67qSyX Y8QbaNrm8FP+MWKoA6T+V+n1+ua/f63KOkWlWYt4G8f9JvWSQf8ASNirINA0+61K3a48kfldNqkK kgalqAvNUpSm37kWlmW9jEcVQ+u+avzo8tEJeWU/lNPsxfVNLh0gbGvwyQQQM2/fka4q78t/zG81 jzzp91qWu29xJ6qstz5juLx4Veop/pMIlnhJr9r7H8+2Kv0Fs5Z5bSGWdEjmdFaSON/VRWIqQsnF OQ8DxFfDFXxj+Rbf4T/5ygvtB/u4ZbnVNK2+zwjLyxdezG3WmKvtTFXYq8H/AOck/wA8dQ8iSabp /ljVYBr7lnv9NkgW4CwMAY5HcsPTao+Fd+QNdqCqrw3/AKG8/OX/AJabH/pEX+uKu/6G8/OX/lps f+kRf64qxfz7+fP5l+eNOTTNb1FV05TyktLRBBHKdiPV47vSmwJpirz3FXYq7FXuf/OIOpeX7f8A M82Wpo/168t3/Q8wldI1uIwWdHjUhH5xcuJetCNtzir7hxV2KuxV2KuxV2KuxV2KuxV2KuxV2Kux V2Kvz5/5yP8ALJ8u/nHr0ca+nBfyrqdsw2qLtRJIR8puY+jFUi/NWlz5qGuqtI/Mlna6xXxmuoh9 b+67SZfoxVk3/ONHkryt5v8AzOi07zGvr2dvay3kFk32LiaJkCxvQglQrM5HfjQ7Yq++be3t7aCO 3tokht4VCQwxqEREUUVVUUAAHQDFWruztLy2ktbyCO5tZl4zQTKskbqezKwII+eKvgf/AJyR/K+L yH+YEg06D0fL+sKbzS1WvCM1pPAK/wC+3NQOysuKvpf/AJxQ1bzJf/lVax6uwntLWRotIvA4cm2U lPQcH41aCRGAr+wVptirwz80iPKX/OV8Gq/3ds+pabfsa0rFMsQuN/c+pir7ZxV5Z/zkR+bGoflz 5Liu9KiSTWNUmNpZSyUKQ/AXeYoftlQKKp2qd6jYqvgjU9T1DVNQuNR1G4ku767kaW5uZWLO7sal mJxVC4q7FXYq7FUZpmj6vqs/1fS7G4v5/wDfVtE8z/8AAoGOKtX+lX1g3p3iLDMDxeAuhlRh1Dxg l0PswGKt6Rq2oaRqtpqunTG3v7GZLi1mXqskbBlO/uMVZTe/nV+bd5qD38vm7VUuHNWWC6kgi27C GEpEBv0C4qmVh/zkX+dVjx9HzVcvx2HrpBcdqb+tHJX6cVeu/kN+fv5q+cvzC0/y9rGq2LWEiyzX LTQQxTSLElfSh9P0gzs3YDpyPbFX1hirsVdirsVdirsVdirsVdirsVdir5T/AOc3vLFJfLfmmNPt LLpl1J/qn17df+GmxV4Tq7DUvyw0C9G82hXt1pE58ILml9a/fI1192KoL8tvNN35V8+aHr1rX1LK 7jMiA05wufTmjr25xuy/Tir7l/Mf/lduo+ZLPQ/I72mi6G9uJ7/zPcKk8iSc2UwRwOGFeIB+wev2 lxVjcXn/APMzTdbuvy7tJLLWfNVrbIljrGoI0EdzcHjcySTRRPRV+rO3FVPVQd60ygZfXwvRZOxI js6OrjImV7jpV8P3sS/Ovyb+YOs/lRrep+c9X0nVr3y9LDcWUekRMpt5fVWO6ikdqEr6MoYgqDVR l7zqZf8AOFGqST+Qda0525LZ6n6sYPZZ4E2HtyiJxVgX/ObGktb+edA1dRxF5pxt+Y2q9rOzE/MC 4XFX1h5R1ldb8qaNrIPIalY213Xp/fxLJ0/2WKvmv/nOPUN/KGnKen164lHz9BE7/wCv2xV8q4qi LCwvdQvYLGxgkury5dYre3iUvI7saKqqNyTir0Lzfqvl/wAr6VpPlzQ9Nsl8xWPqv5nvJ47PV1e4 kEYECzXFuygwFGqsQ4DlTk5BbFWML+YHmOON44l0+FXpz9HS9NiJp7pbqcVbg/MTzdbsWgvI4mIo WS1tVJHhtFiqH1bzx5w1aD6tqGsXc9pv/ofqsluK7GkKFYxXv8OKpHirsVdirsVVbW6ubS5iurWV 4LmB1kgnjYo6OhqrKwoQQRUEYq+1/wDnHT/nIceeEXyx5kZY/NUEZa3uFAVL6OMVZqDZZlUVZRsR 8Q7gKveMVdirsVdirsVdirsVdirsVdiryz/nJryx+n/yc1sInO40oJqcHen1Zqyn/kQ0mKvi/wAk N9e8t+b9AO7XFgmq2o/4v0qT1WNPa0luMVYpZ2xubyC2BoZ5EjBAqQXYL079cVfoh+bvmPyFY6Xa aH51vrnTNL11nRb63eWFQ9uUk9KSaH4051+RANcVfPvnH8ydIT8xJfOPky6GrQ6aIPSmm9UCd7a3 SN1dnCSNyUULd+uYOTbKC+jdlfv+xpwG5iJj4/V+lb5M/ObTvOfmW48kad5ZsvLOkec4L631VopG nlnv7m2kEMrSFYwv709Atd+uZz5ykH/OMf5taJ+XXmHWNK80u9lpuqCNXueDSehc2pcASIgZ+LCR gSAaEDtUhV6D/wA5eT6T5m/Ljyz5t0eU3VhDfyW0Nz6UiBkuoSxZfUVDx5WwFaUJxV6f/wA4zayd U/JXy8ztyls0ms5KmtPQndYx/wAiuGKvHf8AnNry5rZ1PQvMh9M6GsI05aMfUW7Z5ZmqtKcWjUUN eoO2KvmGGGaeaOGGNpZpWCRRICzMzGiqqjcknoMVZwPMNr5K0eXS/L0yyeab5Sms69FQm1iIo1jY yDuf93Tofi+yh4gsyrC4LO6uI55YYy0dsnqTv0VFJCgsTtuzADxOKqGKuxV2KuxV2KrowhkUSErG SObAVIFdyBtiqtf2bWd7Pas6SmFynqxHlG4B2dG7qw3GKqKo7miqWIBNAK7KKk/QBirJvywh12b8 wNCj0C8hsNbN2h024uWZITOu6RuUVzSUj06UoeVDscVfpNYyXUtlbyXcIt7p40a4twwcRyFQXQON m4ttXviqtirsVdirsVdirsVdirsVdiqH1GwttQ0+5sLpedtdxPBOnjHKpRh9xxV+c3lgf4O/NW3s 9VFIdO1GXTNVB+GtvIzWd118YnfFUknhvvKnm54ZY0e+0G/KvFKp4NLZzUKutQeJZNxXFX0n/wA5 Zy6pP+WnkEaq3q61KPWv/gCFpls0Nw/BQAtHJJA6Yq8J8lepby3unTqA4pIB1BoSj+xoRTMPVx5F 772I1H95iPlL9B/Qk+lzXvl3zXBqFqypdaPeR3NsXrQvC/qRE0/ZZlUH55lQlxAF43tDSnT554j/ AAyPy6fY9c/Nv8u7y4htfzr8hKZNA1fjqt7AgV5dPu+dZiy0KvGJg3PaitWo45Jw2V+bPzQvPzV/ 5x71gahod3aaro62922pJbudMne3uI45vSnA4pJ6crMYm+gkdFWR/wDOEus+v5J17RyQWsNRW5A7 hLqFVA+XK3bFWZ/85S+W59c/JzVDbQtPc6XLBqEUaAs1In4StQfywyux9hir5N/ICEH8w4b64jgO k6TbXGoazcXMKXCw2NunOYqklU5SbRAkGnPbffFWGea9efzB5k1LWmhS2F/cSTJbRAKkSMfgiUKA KIlFG3bFWQebnt9M8k+U9DtFCPfW0mt6w4FGluJriWC2Vz4Q20QKDoPUY9WOKsKxV2KuxV2KuxV2 Ktkk9cVVbS6mtLqK5hIEsLB05AMpINaMpqGB7g7HFWSea7ODQ9Z0jW9BcwWup20Gs6YqklrZ/VeO SEMak+hdW8iKTuQBXeuKv0M8h+arbzZ5N0fzHb0CalapM6LuElpxlj/2EgZfoxVPsVdirsVdirsV dirsVdirsVdir4M/5yt8s/oT84dQuEXjb61BDqMQA25Ophl+kyws304qxP8AMud5vMOm+Zoeuvaf Z6nyIDA3KL9WuzQ1Brd20p3xV77/AM5b29y/lPyK927XLpDeLPdMKc5zZxlWalBydkJpir51/SkU Pm6SWySSe1EtxHHHGA5aJ5pHTh4ijKdz9OVZo3F3Xs/q5YNXGUYyldgiIskH9tFH+ZPL0upNHfW4 ENy68WtpSqsxHShBZeVPfMbDm4djyev9oOwpasxz4/RkIowlQJ7uRI4q83vX/OPMHm7W/wAgvNWi 6RfG01mwv5To5BHNZVjiuDBIj1UxTOGRg6kHk1a5nAvnE4GJMSKIeR/lDrvmRte8x+TI4RFY+aLD UbW/0oAokNyttK0UscRqVaKRQCB+zWuw2WLN/wDnCfWfq/nnXNIZqLf6cJ1HYvazKAPnxnY4q+yC ARQ7g9Rir48/5yNtvI35etrfl/ympg1rzk1vcazbRgCKzsoWaT0YaU4fWZwrlP5VpspUYq+bsVTy P6/5q1/R9LgWlxOLLSbOMnl8VEgXsPtOS1PfFUr1BbRb+5WyLNZrK4ti9CxiDHhyp340xVD4q7FX Yq7FXYq7FXYqirzUJ7q3sYJPsWEBt4f9RppJz/w0zYq+s/8AnCvzq13oOseT7hyZNNkF9Yg/74uD xlUeASUBv9nir6XxV2KuxV2KuxV2KuxV2KuxV2Kvmf8A5zb8s+voHl7zLGvxWVzLYXBA3KXKepGT 7K0DD/ZYq+db1hqf5VabP1n8u6pNYynwt9Sj+s2w+iW2ufvxV9k675Qsfzc/IfSbZJQt7c6faX2m XTEn0r6KECjnfqxeJ+vU98VfFmkCLQdR1HStbSbT9Rhk+rz1BDxvExEkZoCR8Q3pmPnhI1T1Hs3r tNg445pSgZ1Uh3DmNtxf4pNJfMmmXE8UFhay6pfH4LVRGWYt24gjnX5LXKYaefXZ6HW+1OijRhE5 px+kkbD4nf5Dd9N/84uflh5t8veWvMN/5l+s6ZdeZHRYrAn0pokjV/8ASDT4o5GaY0GxHHftTNAo U+dZcsskzOX1SJJ95eFahZaj5R/MdfNfnzWYIte0i/Scafp6xy39/JaSjjLKkJSCBZwnxvKwdgeX BySSWtZ/zjJc3i/nlpVxplnM1lI10lzHGDIIbeaGQKZHVaBUcp8RAGKvujW9XsdG0e+1e/f07LT4 JLq5fwjhQu34DFX5o+cvNGoeavNOqeYtQJN1qdw87KTXgpNI4wf5Y0ARfYYqk2Kph5e1m40PX9M1 q3UNcaXdwXkKnYF7eRZVB+lcVS/FXYq7FXYq7FXYq7FXYq7FX2N/zhX5SFl5Q1fzPMlJtXuhbWzH /lntBuV/1pZGB/1cVfR2KuxV2KuxV2KuxV2KuxV2KuxVgP58+Wf8R/lJ5l09V5TxWjXtuAKn1LMi 4AX3b0+P04q+H/y3gm1e38x+U4V9S51rTzLp0VQpa90+RbqMDlQVaFJkH+tir6f/AOcZ/Mt/5Z8l TeWvO8troyafOzaTNd3lqnOKZmaSHj6pYNHLyb4h0b2xVlHnPVf+cZ/MUnreZdS8t6jc8afWRc27 XHFduJmgf1duw5Yqk1p+bf8AzjL5A0+aby5JYrOEr6GlWzPdTb0CesyrX/npIMVeGfmZ/wA5WefP NjS6d5eDeXdHl+AJbMWvZQdvjnABSv8ALGB4EtiqO/Kn/nE/zX5oaPV/OLy6FpEh9T6sw/3IXAO9 eL19EHxkHL/J74q+uPJ/kfyr5O0ldL8uadFYWgoZOAJkkYbc5ZGq7t7scVeOf85h+f49H8jQeVLW Wmo+YZAbhF6rZW7B3J7jnIEUeI5Yq+OIraNtGuro/wB5Fc28S7fsyJOx3r/xWMVQWKtkEAEigO49 x0xVrFXYqy/8u/K0fmRPM9ksZlv7bRJ77TlXr61pcQTOFH7RaBZVAHjirEMVdirsVXMjpTmpXkAy 1FKg9Diq3FUYNLujpDaqFraJcC1dvCRkMij6VVvuxV+j/wCVnly28ufl15d0a3KstrYwmSRPsvLK vqzOvs8rs304qynFXYq7FXYq7FXYq7FXYq7FXYq06JIjRyKHRwVdGFQQdiCDir48vP8AnCfzq17c taa1piWZmk+qo7XBcQ8z6fOkX2uFOXv3PXFVNP8AnCXz4XUPr2lhKjkR9YJA70BjFfvxVE/9CQ+a v+plsf8AkTNirxP8y/IGp+QfN935a1GVLiW2WKSO6jBWOVJYw4ZQ2+xJU+4OKvpn/nELyT5Em8pr 5mfT1m81pcSobi6o7Rxo1I5LWNgAin7PqCp5Bhy/ZCr6E1jXdF0Sya+1i/t9Os0+1cXUqQxj25OV FcVeQeaP+cu/ym0dni06S7124WoH1OHhDyHjLOYtvdFbFXyL+aX5h6l+YHnO98x3yeistIrK05cx BbR19OINQV6lmNN2JOKpToGr2Ng0kV/Zi9tJniZ4yaUCMVcj3MMkir/KxDDcDFVnmbQZ9B1270qZ xKIGBguFFFmgkUSQTpX9mWJ1dfY4qhJr+eaxt7OSjR2rOYGp8SrIQWSv8vIcgOxJ8cVV9Y0v9HzW 4SZLiC7tobqCaM1FJUBdD/lRScon/wApTiqX4qm/lTzTrPlXzDZa/o03oajYvziYjkrAgq6Ov7SO pKsPA4qmXnZPLuo3H+IvLkYs7K+PK+0avxWFy27xp05W7neJh0HwtQjdVi2KuxV6D+Yl5oU/kT8u YrRF/S0Wl3f6QnUbtH+kJkgRvdGjl+g+FMVefqrMwVQWZjRVG5JOKpvoUWp61daZ5Vhulht9Q1CJ YhJURLcXJSASycQWIUU8aCtOpxV+kfku01Kz8naFaaonp6nb6daRX0fIPxnSBFlXkCQ1HB3xVOcV diqV+Z/M+heWNDutc1y7Wy0yzXlNO9T1NFVVFWZmJoqgVJxV8pee/wDnM/zLdzy23kvTotMshsl9 eqJ7pv8AKEdfRj+R5/PFXl19/wA5BfnNes7Tea71C/X0PTtx1rsIUjp9GKqNr+e/5w2snOLzbqLN saSy+sNv8mUOMVej+Sf+cyfPmmzxQ+arWDXrGoEs8aLa3YHQlTGBC1P5Sgr/ADDFX0/5N/N/8vvO C6emiatHLeajFNLDp7/Dcp9W4eskse/Bl9UGlfiFStQCcVZlirsVdirsVdirsVfBn50/nEnmXz1f 3DeWNNS50x5NNtb66Weef0beZ+JeJpBaluTE/FCxHSpAxV5xJ5z81vqcOqJqtzbX1tELe0mtXNt6 EAJYQwLB6axRgsSEQBd+mKoPVtd1vWbj6zq+oXOo3G/767mknffr8UhY4qgcVdiqN0jSL7Vr1bOz UFyrSSSOQkcUSDk8srnZERd2Y4q9J8z6fpPnfRdIs/Jcd5rOv+VrSHTdRl9Eh7615N6dzBEtXWG2 c+lWQBvTaPkBQ0VeaTWMtjqUthqkclrNbSPBdxMtJIpEJVlZT3VhuMVQtTSnbFWsVdirdT9/XFWs Vdiq5ndgoZiwQcUBNQBUmg8NyTirNNB8v/4Y/MXS4/MyCO20r6prGpwN19EQx3v1dgekj8hDxP7Z piqSeSJ/q/nTQLjjy9HUrSTjWleM6Gld8VfpzirsVdirwX/nLryX528zeVNHPly0m1G20+6km1HT 7ZWkmYugWGVYl+J+HxghQT8XhXFXk/5bf84f+b9dRL7zdP8A4dsG3WzCiW+ce614Q/7IlvFcVe86 D/zi1+S+kxqJNGfU5l63F/cSyMfmkZii/wCExVGar/zjZ+S2pWzQt5bitWIISe0kmgkUnuOL8T/s gRir5n/PH/nGjVvIUD67oU0mreVwQJmcA3VpU0HrcAFdD/vxQN9iBsSq8n8peZ9U8reZdO8w6W/C +02ZZovBgNnRv8l0JVvY4q/SDyd518vebtGttT0a7inWe3huJbdHVpYPXUlUmVTVGqrDfwOKp7ir sVdirsVdir4A/wCcjvy81fyp+Zer3sts40bW7qS/0+9C/umNwTLLEGGwaORmHHrSh6HFWD6F5O1X VYfr0jR6boqtwn1q+LRWiGtCqsAzyv8A8VxKz96Urir1+7/5ww/NKIcrbUNHu0O6cJ51YilQaPAF 3/1sVSef/nEv86o3CpptrMCK8kvIAPl8bIcVTHQP+cOvzVv7pF1R7HR7Wv72WSb15Av+RHCGDH2L r88VQf576Pof5bxWn5b+WgzNNBFfeZdXlAFxeSsxMMBI+xDHw5iNdqlSastcVeNw3NxB6noyvF6q GOXgxXkjdUanVTTpiqI1TV73VJIpr1/WuIokhNwf7x0jHFPUb9oqgCg9aAYqstbCa6t7qWH4mtEE 0id/S5BGYePEstfbfoDiqhNDNDK0UyNFKho8bgqwPgQd8VWYq7FXYq7FVa0uri0uY7m2cxXELB4p V+0rDoynsQdwexxVXtbTV9YvpEto57++lWWeUKGllcRqZZXbqxoqlmOKvZv+cavyh0DzZ5o9bzHc TRy6fDFqdnpkLCNpIxIAkkz/AG0RmoVVaMR8VQpXkq+4cVdirsVdirsVdirsVU7q1tru2ltbqJJ7 a4Rop4JFDI8bjiyMp2IYGhBxV8Af85B/lK35dedGhslY+XtVDXOkOangAf3luSdyYSwp4qV71xV6 V/zhBrtlBrnmjQ5X43d/b2t1aoTQMto0qSgf5X+kqfkPbFX1zirsVdirsVdiqB13So9W0a+012Mf 1uCWFZlqGjaRCodCN1Za1BG4xV8b6d/zjL+evnKeG482X/1OGFfTim1a7e7mWOv2Yo0MxXx4sy4q +w/K+k3Wj+W9L0m7vDqFzp9rDay3xT0zM0KBPUKcnoW41+0cVTPFXYq+EP8AnLW3eL86dRdjtPa2 ci/IQhP1pirxrFXYqmXl3XLnQ9Yt9Tt4452h5LJbTgtFNFKhjlhkAKkpJG7I1CDQ7Yq9Q/Mz8wdF 1/zjd2nm7R1axkitJbW7sOCajpxmtIZXgSUqiXUUUjsvpzL/AKrJirzzzT5Vj0ZLG9sdSg1jRtTV 2sb+BXjPKJgJYZopAGimj5KWXcUYEMQcVTTQPy3uPMXl671DQtQt7/VLUwkaEG9O+ZXLLLwhf+84 ngy+mWBWtaMOOKpPrXkjznocbSazoOoabEpoZbu1mhSpNB8Tqq79sVSTFXYqntn5jfSNLktdEklg vL4Aajf0EcojVgy20LKzERllDu2xfYUAU8lXsv8AziDr95cfnFqUl7MZZ9T0u4DsaLV0mgkWigUA VEIVRQAdOlMVfaWKuxV2KuxV2KuxV2KuxV5X/wA5LeRofNX5U6o6x8tR0RDqli4FWHoAmZNtzzh5 Cn81PDFXxj+T3mqXyt+Znl3WFf04o7yOG7NaA29wfRmr/wA83JHvir9IsVdirsVdirsVdirsVdir sVdir42/5zY0SW389aHrIQiDUNONvy3oZbWZmb/hLhMVfOyMyOrqaMpBB9xiqaalYxXFkus2Khbd mEV9br/x73DAkUH++peJZPDdf2QWVSuMIZFDtwQkBnAqQK7mm1cVTrzzeLeedNdukAWOXULlolU1 VU9ZuCg+AWgGKpQLicW7Wwc+gziRo+3NQVDfcxxVSxVVe5uHiWF5XaJPsRliVHyB2GKqWKuxV2Kv W/8AnFa7eD88NBjWvG5jvYpKV6fU5ZBsP8pBir75xV2KuxV2KuxV2KuxV2Kqd1bQ3VtLbTLzhnRo 5VPQq44sPuOKvywBIIINCNwR1rir9U8VdirsVdirsVdirsVdirsVdirzj8+/yuH5h+Q59PtQo1uw b65pDsQoMyghomY/syoSvhy4k9MVfnvc21xa3EttcxNDcQO0c0MgKujoeLKyncEEUIxVG6DrB0u9 MkkQurKdTBf2TGiz27EFkJ/ZOwZG6qwDDcYqiPM/l79E3EE9rKbrRtRj+saVfUp6kVaMjgbLLE1U lXsw2qpUlVJ3d5HZ3JZ3JZmPUk7knFVuKuxV2KuxV2KqsdtcSxyyxxM8cADTOoJCAniCxHQVNN8V e7/84Z6J9d/NC71J1rHpWmyujeEs7pEo+mMyYq+2MVdirsVdirsVdirsVdirDvzd87Wvkv8ALzWd dlkCXEcDQ6evd7uYFIFA70Y8m/yQT2xV8B/lj5Zl8z/mD5f0KNOa3t7EJx4QI3qTt/sYkY4q/S3F XYq7FXYq7FXYq7FXYq7FXYq7FXy7/wA5Z/kl9Yil/MPy/b/v4lH+IrWMfajUUF2oHdBtL7UbsxxV 8m4qy5K3H5SzVNRpuvRBRUfD+kLOWv8AlfF9Q+W2KsRxV2Kp55d8l+YvMAeXT7YCzibjNf3Dpb2y NSvEzSlE503CAlj2GCUgObfp9LlzS4ccTI+QtkiflDIY+UnmrRYpR1hP6TZq+HKOxeP7mplX5iHe 7gey/aBF+H/so/8AFJB5i8ieYdBt1vLmOO5012CJqNnIs9vzO4R2X4onPZJAre2WRmJcnVarRZtP LhyxMT5/o72PZJxVeyvr6wuUurG4ltbqOvpzwO0ci1FDxZSCNjirM/LH53fmh5auzdabrszPJT1x cqlyJQO0hmV2PzrXFX0N+XH/ADmVomoNFY+ebIaTctt+lLMPJak/5cR5yx/QX+jFX0VperaZq1hD qGl3cV7Y3C84LmB1kjcHuGUkYqisVdirsVdirsVUL6+srCynvr6dLaztkaW4uJWCIiIKszMdgAMV fBv/ADkN+dM35i+ZFttOZo/K2lMy6dGaqZ3OzXUimhqw2QH7K+BLYq9c/wCcO/yrmsrW4/MDVYCk t4htdDRxQiAn99cCv85HBD4BuzYq+ncVdirsVdirsVdirsVdirsVdirsVSbzb5o8qeXNGmvvM99b 2OmMpjkNyQRICN41jozSEj9lVJPhir84/PknlCTzdqcvk8Tp5dkmL2Ed0oR0VtyoAZjwDV4cvi40 rviqt5T13TILHUvLutBk0bWjA8l5EC0trdWvqC3uAg/vEX13WROpVjx+IDFUr17Qr/Q9Tl0+9C+o lGjmjPOGaJxWOaFxs8ci/EjDqMVUtI02bVNWstMhNJr6eK2iJ3AaZwi/i2Kvo3Qj5Qi1HUJtWhEv lzy3A0Gh6KrNGJpPU4QoeJBq9GlmbqxqTXNcZiUiZcg+r49Dk02mxYNN6cmSuOfdtcj+iKQ+Y/Nl 7rjhWtbOwsozW3srK3igjj+RVebE9yzHKpTt3Wj0EcA+qU5HnKUiSf0fIJdYahPZSM0YWSGVfTub WVecM8RNWjljOzoadPpFCAcEZmJsNms0WLU4zjyC4n7PMea938sSRixl8uWMmix7W9kfUWaIE1LL eIyXDOepLsyn+WgAF35mV289L2Q0hwiG4mP4+p945V+LQUnkz8pbgFvquuafIeoiu7W6jHb4Ve2g f3oX+nLRqx1DpsvsPMfRlB98a/SUrP5O2+rXsVl5S1hr2+nPGCw1G3+pyO1K8I5I5LmIn3kaMZbD URkadPr/AGX1Wmgch4ZQjzo/rAYZ5n8n+afK1+bDzDpdxplzvxW4QqrgdTG/2HHupIy95xH+RvzL 87eR703XlvVJbMOwae1Px28tNv3kLVRttq0qOxGKvpryD/zmd5cvljtfOunvpN1sG1CzDT2rHuzR bzR/Ic/nir3jy3518o+Z7cT+X9YtNTSlWFvKruo/y4680+TAYqnWKuxVhPn785fy88iwSHXNVjN8 o+DSrYia7Y9h6Sn4K/zScV98VfHH5y/85CeaPzGlawjB0rywj8otLjarSlT8L3LinM9wv2V9yK4q yL/nH/8A5xw1DzhdQeYvNNvJaeU4yJIIHrHLfkbhV6MsP8z/ALXRe5VV9r29vBbW8VtbxrDbwosc MKAKiIgoqqo2AAFAMVVMVdirsVdirsVdirsVdirsVadiqMyqXKgkItKkjsORA39zir5R/MX/AJyd /Nv1rxfLXlW40DS7Rmilv7+zkmuVdSQS9R9Xi/1SH/1sVfOPmfzb5l806o+qeYdRm1K+f/dszVCj +VEFERf8lQBiq/RvJfnHW4jNoug6jqcS/aks7Se4UfMxowxVB6noetaVJ6Wqafc2EnThcwyQtX5O FxVmH5d+WPMf5gsnlG1s5Lv0Fkk07UeJK2DbyFJZCQq28rdVO6ueSCpZXVWW3kTz55I806TqfmHy 7qFnaadfW9zNO0DmErBMrtSZA0Z2XscVZ15q0qfSfMmpafP9uC4cK3ZkY8o3FOzoQw9jmonGiQ+6 dn6iObBDJHlKI/b8ilWRct2KuxV2KvQvyK0K61P8xdPmjU/V9ND3dzJ2UKpVB82kZR9+X6eNzed9 qdVHFopA85+kfp+x9Ra75e0LX9Ok03W7CDUbCX7dvcosi17MOXRh2I3GbJ8ifOv5h/8AOGGk3Ze8 8i6idOmNT+i78tLbnwEc4DSp/sg/zGKvnnzd+Tf5m+U3f9NeX7qO3TrewJ9YtqdQfWh5oK+DEHFW HwTzQSrNBI0UyGqSISrKfEEbjFWYad+dH5sadGIrXzbqgjAoqS3MkwA8B6penTtiqnqf5sfmprf+ jXnmfVLlZfh+rpcyork7U9OMqrfdiqa+UPyA/NnzZKjWehT2lrIatf6kDaQ0P7Y9UCSQf8Y1bFX0 r+V//OJXlDyzLFqXmiVfMWrR0ZLdk42MTDf+6aplI8X2/wAnFXvKqqqFUBVUUVRsAB2GKt4q7FXY q7FXYq7FXYq7FXYq7FXYq7FWN3P/ACrf6y/1n9D/AFqvx+r9V9Tl78t64qyKH0vST0ePpcR6fCnH jTbjTalMVan9D0X9fj6ND6nOnHj3rXamKrLT6n6A+p+n6G/H0ePCtd6cdsVVsVeHf85Df8q75R/X vV/xX6Q9D6pxr6dTx+s8vh49aftfRmHqeDr9T3fsh+d34K/L3vxd/wDR8/s+L58zCfRGb/lr/wAq v/SUX+MfrXLl+76fUq9vW4fvvDpt47Zdi4L9To+2vz/Afy3D/v8A4X6f09ybec/+VD+vJ+hP0p6t TT6nx+rV/wCjr9518Nslk8Ppbh9m/wAr0PF8Ov6X1f7HZienf4A+t/7kv0t9U57fVvq3qcP9n8Nc qHD1t2+b85w+jwuLz4q+x9PflR/yr7/Dp/wXT6tzH1znX6z6tNvX5fFXw/Z/lzY4eGvS+W9vfnPG /wAK+rp/Nr+j+L72a5a6N2KuxVh3mj/lT3qyf4q/w961T6v6U+pcq1FeXr79aYqx2P8A6Fc9RfT/ AMEepUcOP6J5cq7Up3xVmvlv/AnH/nWf0Xx3/wCOb9XpSpr/AHHvXFU+xV2KuxV2Kv8A/9k= + + + + + + proof:pdf + uuid:65E6390686CF11DBA6E2D887CEACB407 + xmp.did:FB7F1174072068118C14B4E5CD987829 + uuid:177c6a2f-7c9a-f640-ae3c-c77b2ba8d3c3 + + xmp.iid:FA7F1174072068118C14B4E5CD987829 + xmp.did:FA7F1174072068118C14B4E5CD987829 + uuid:65E6390686CF11DBA6E2D887CEACB407 + proof:pdf + + + + + saved + xmp.iid:FA7F1174072068118C14B4E5CD987829 + 2010-10-08T15:32:44+02:00 + Adobe Illustrator CS5 + / + + + saved + xmp.iid:FB7F1174072068118C14B4E5CD987829 + 2010-10-08T15:32:56+02:00 + Adobe Illustrator CS5 + / + + + + + + Web + Document + + + 1 + False + False + + 1400.000000 + 768.000000 + Pixels + + + + Cyan + Magenta + Yellow + Black + + + + + + Standard-Farbfeldgruppe + 0 + + + + Weiß + RGB + PROCESS + 255 + 255 + 255 + + + Schwarz + RGB + PROCESS + 0 + 0 + 0 + + + RGB Rot + RGB + PROCESS + 255 + 0 + 0 + + + RGB Gelb + RGB + PROCESS + 255 + 255 + 0 + + + RGB Grün + RGB + PROCESS + 0 + 255 + 0 + + + RGB Cyan + RGB + PROCESS + 0 + 255 + 255 + + + RGB Blau + RGB + PROCESS + 0 + 0 + 255 + + + RGB Magenta + RGB + PROCESS + 255 + 0 + 255 + + + R=193 G=39 B=45 + RGB + PROCESS + 193 + 39 + 45 + + + R=237 G=28 B=36 + RGB + PROCESS + 237 + 28 + 36 + + + R=241 G=90 B=36 + RGB + PROCESS + 241 + 90 + 36 + + + R=247 G=147 B=30 + RGB + PROCESS + 247 + 147 + 30 + + + R=251 G=176 B=59 + RGB + PROCESS + 251 + 176 + 59 + + + R=252 G=238 B=33 + RGB + PROCESS + 252 + 238 + 33 + + + R=217 G=224 B=33 + RGB + PROCESS + 217 + 224 + 33 + + + R=140 G=198 B=63 + RGB + PROCESS + 140 + 198 + 63 + + + R=57 G=181 B=74 + RGB + PROCESS + 57 + 181 + 74 + + + R=0 G=146 B=69 + RGB + PROCESS + 0 + 146 + 69 + + + R=0 G=104 B=55 + RGB + PROCESS + 0 + 104 + 55 + + + R=34 G=181 B=115 + RGB + PROCESS + 34 + 181 + 115 + + + R=0 G=169 B=157 + RGB + PROCESS + 0 + 169 + 157 + + + R=41 G=171 B=226 + RGB + PROCESS + 41 + 171 + 226 + + + R=0 G=113 B=188 + RGB + PROCESS + 0 + 113 + 188 + + + R=46 G=49 B=146 + RGB + PROCESS + 46 + 49 + 146 + + + R=27 G=20 B=100 + RGB + PROCESS + 27 + 20 + 100 + + + R=102 G=45 B=145 + RGB + PROCESS + 102 + 45 + 145 + + + R=147 G=39 B=143 + RGB + PROCESS + 147 + 39 + 143 + + + R=158 G=0 B=93 + RGB + PROCESS + 158 + 0 + 93 + + + R=212 G=20 B=90 + RGB + PROCESS + 212 + 20 + 90 + + + R=237 G=30 B=121 + RGB + PROCESS + 237 + 30 + 121 + + + R=199 G=178 B=153 + RGB + PROCESS + 199 + 178 + 153 + + + R=153 G=134 B=117 + RGB + PROCESS + 153 + 134 + 117 + + + R=115 G=99 B=87 + RGB + PROCESS + 115 + 99 + 87 + + + R=83 G=71 B=65 + RGB + PROCESS + 83 + 71 + 65 + + + R=198 G=156 B=109 + RGB + PROCESS + 198 + 156 + 109 + + + R=166 G=124 B=82 + RGB + PROCESS + 166 + 124 + 82 + + + R=140 G=98 B=57 + RGB + PROCESS + 140 + 98 + 57 + + + R=117 G=76 B=36 + RGB + PROCESS + 117 + 76 + 36 + + + R=96 G=56 B=19 + RGB + PROCESS + 96 + 56 + 19 + + + R=66 G=33 B=11 + RGB + PROCESS + 66 + 33 + 11 + + + + + + Grautöne + 1 + + + + R=0 G=0 B=0 + RGB + PROCESS + 0 + 0 + 0 + + + R=26 G=26 B=26 + RGB + PROCESS + 26 + 26 + 26 + + + R=51 G=51 B=51 + RGB + PROCESS + 51 + 51 + 51 + + + R=77 G=77 B=77 + RGB + PROCESS + 77 + 77 + 77 + + + R=102 G=102 B=102 + RGB + PROCESS + 102 + 102 + 102 + + + R=128 G=128 B=128 + RGB + PROCESS + 128 + 128 + 128 + + + R=153 G=153 B=153 + RGB + PROCESS + 153 + 153 + 153 + + + R=179 G=179 B=179 + RGB + PROCESS + 179 + 179 + 179 + + + R=204 G=204 B=204 + RGB + PROCESS + 204 + 204 + 204 + + + R=230 G=230 B=230 + RGB + PROCESS + 230 + 230 + 230 + + + R=242 G=242 B=242 + RGB + PROCESS + 242 + 242 + 242 + + + + + + Webfarbgruppe + 1 + + + + R=63 G=169 B=245 + RGB + PROCESS + 63 + 169 + 245 + + + R=122 G=201 B=67 + RGB + PROCESS + 122 + 201 + 67 + + + R=255 G=147 B=30 + RGB + PROCESS + 255 + 147 + 30 + + + R=255 G=29 B=37 + RGB + PROCESS + 255 + 29 + 37 + + + R=255 G=123 B=172 + RGB + PROCESS + 255 + 123 + 172 + + + R=189 G=204 B=212 + RGB + PROCESS + 189 + 204 + 212 + + + + + + + + + Adobe PDF library 9.90 + + + + + + + + + + + + + + + + + + + + + + + + + endstream endobj 3 0 obj <> endobj 8 0 obj <>/Resources<>/ExtGState<>/Properties<>>>/Thumb 13 0 R/TrimBox[0.0 0.0 1400.0 768.0]/Type/Page>> endobj 9 0 obj <>stream +H‰´—ËÊ\É„÷ýõ§T÷ËÖ²ñj0ƒ~€Æ¶’a,èíýET·Ô£ù±ÁÔÕ9§*/‘‘‘ïþô>¼ûé} +¿ûýûpûå–Â+ä–R¸ô×?ÿzûKøÇíÝû?§pÿ²ÿ…Ïw¶þÈÖß?ß~a#ñ/‡ÖWÜ}äÐÇŽ{ÌîŸnzôéÖw\µökïáã-·רa÷¸fe£¬W^a­Xwc£öwm¡÷8ù„ÏâÈ5ôgá ÏG,›Ç¡U®,3\=ògøzk½Ä±ÈqùpûÛíç ’Ú5°c,Òß ð7æ¦TíÐRœ¶¸Ê ÀÊ“5×ØŽ %öfT&üˆÊ–źPØ ìšú– ”÷ NªPRÉöw°Nþb~³;2¦àÏö›:ø½ôëlñ†lëN{¥p +EH9P?ÏÛÿðÕûîÔr>µüó®f`=»¬&‡ëßUu)DCÏGN„´¿T5^ô@T»F0wX¯Øf¬T¥Å±dd©Ô2€O©ÉÍFeP”ÊkMú€"è ++ð>:,/òÂΊijg‚ Ò“ÅŽž@²…}<ËQúY*’àϘ„í<1"Œ:ëÊJñ \¶}+ÕUy|¿U +fAóz ï ¾°|ÃS9mN®/øÒ]…[¯M*•9Ê÷I.we»tQ6m +ÞdwɃ‹‹áàýõºÖ,+.dætñèAûöàà †ÀߢrMðb§ïìÞkðºu!^§î5Ìv¿e±§ƒLýQè˜Éñg=`€œI,ˆT¾ &Uuá+y£Èºòœ`¼¦Úë{ˆ’ʱÈ1ñ¾{×éP›Ú¾Þàï ˜jÌ T7¨Y(_b ¢FÁZ×`7ÜÇKYĵ Hõ¹¸?âÞžEWU €• @…lß»UŠ·k<°×UîøJF»>\*½%Ð61íN±>H6QƒÄB±´8¯`,(´–o+ðC °î¹¡Ûù¹ÄFÄu$7³ €Ê/b”áÉ8ÎrQìÏç_oðÂ~ðßä{±y¤ë/·lJ™ßß Ôz{TV®9ñËèÎ8W¸s-„" £µ Ñö +?‚ênü'£ßñ½jÂZšV(t”þÂsWuŽˆÜØfs" ÑàkÃ)!b¨yÂ.2ZF¡·Sê„ÇbÀEaŽ3çRŒ¤Ÿþ:}÷——Ü·Æ…XN_*¯–P⥹ÀÖYÈŠùÕ“nêFÒ¢E(GÂ7Ý›î/M•zwHX2|—ã!-ލUº .gF`·¹‡Ô·%3©>(щr¼Hæ+x%@¼·4ª‘AU?iIZË‘v?nÄ\¤¤‰WÇã@všÂÈ7 O¬Š|ï@+Wé¼ü¦¢ Ä€ Bž Öÿ6 +å% +å5ýB+åÿ„%ˆÃD`d­×)OpKºß5~Vš¦ÌW;!ú!«AmÏvÝk }ŒD”®qóéO§e|Ð,4,Nº%÷ªm99¬]#5‡çñ§K6ë¸:­¦ü3P”RBáv£›ê¹îدa…ae6Ý€/ѡɯHØW I¸scéVØíf³°ÖÝôȉ ùq‹Ó,*dôÉ3¢Æ¼kE¦\´¥Þ=u‚>mt)Ûù½KªÄçR§í¼Ó,{®®N4w©¿mOŸâî¢ÍסÛiþg&€ ô™Bë òÆRT=Ö0HŽ|7T ”R#^Ÿ>rõbÞúhÊÐÀ§r°eâ/ÃÊEM­%RÕTØEþõ`CÍ%™MÉÝ^¯y>´Ñ&M”ô£2ÃØî§Ú)‚ò…„è§eaïTÄ¥aüÊ }š±ØY]¶Ø$‘Gûn„H±F ÅwUªÊmóñ¦I9X‘(üäpKoÌÂYእkºähhÞÙÒÖ‡³.ÿâºÜ‘äÈ‘ ªó}¢%~™€¼6â +{š­4«ŽÙÜ~ßó¨’-‘ÊDþI<{<Ìq7º£ïæ××ÒHŒCmée»V¢ÇðGÌ÷}F²éËK<§²Â‘ÊÊpò=_+˜º1Ü–÷°‡Tà·CüKZæùV‰Ö”„qÕžê‘WKÅÂt´ÕÔcU®¨žOžšýÿ<ãô)™‘sþmueÁm3ýÊZ‰7 –q.&w$FDž_·(ÀuŽ ÔŠT†Á··×L_Œ;/4aP¡IÁžô w1îP¸˜½ ™tÆó^YÆ1@®Œw3tÏç8i[ÎõI;\C¦ÇZ ¬­$ýý·iÍ–rd¼^» ï³odOfùàÄÛÝÌ­ý€²à¸Fí]q`~ÛçÎýù.áJZ_ŽÊßÔC ñ¼÷°þ·.VßóõîÁl5ŽãÜwNÖãÈ{¤æ”ìuèñ¾¤§+˜}/9ß®”Lk®—áÈ™ÎBä””®{|®M»iæUk³%Ù¼ŸŠÝ…ÈÅÏ/.±jj;T™TæhÞ‹ þí20å äiæ¿×C²ÿ,¦{úN_IrMaü%¹M8é )Ï¢`E<²€1'"ÛIIb¹å ’-i銞z±ªÆœJ¤*>Ÿ^¡UZ¥w¡{°DÛºÛßwýÛ'ÐŽ%õˆ¹6Q² …$uN|Q  èÙv¯ˆj[‚Ï/o9ÊU¢ttz¨XŠúH>ôÓ&´¶¯Ø¥d·ÎÙšß{Þ‡á&—)Uk¥Üòþ¢Ìm)¡§®t’G)Õš_oðwï Çè¥È´waÀGëâÕP¼[}ZƒþáÖÕbv™ÐöŽØ~ÝT–!:*N4·:4ÀÕà ÔR¸æCµ™?bi¾r²»yF±íÈ8ïw~n‹ÑÓͦz2<. œ±I5S†4Ñ‹†:çpúu.Ô²UPk;™œ®½³B¹½ËxÚ“PÛ›ô_›LñÞ/'\¦½ôfN¼îY&å&zìN&½,5ó0—ÂEeñ«Å&øÆµlŽÖ Š˜'°²K§9 |(ëã@xÔ?_“êG>_÷w†€þþuä 3GAøø0§ª²*ßTlô™;ALoïÏÙ.ÌPGfç}~nÐÙnö‰+ÑK­º)º*HBÑ\çÞÔìÂr¦e´Å¬kñc +ííåÆ×)‡ÍßTxèØbC6…Äg‹Å^¾'…®Æ ï%Ý8Q•ÏŸŒiÍSz—Æ Žl>O%5ÅV¢úeéÖ¶pNgøªô¦H"×£6í¿Ç´ƒ™r/¡ŽV>>U%殣a„Z™åvB–u-_« +uwÄ™Šž~aùï$BçΉÐr<¦©cFÛ©%GX}Û:ˆQOÑ(ð¨òíRh¥¬Á*Šìž0Á„«îýàVpÂÍ[hò~îzqÆû П²¯Gþò)¨hVÝaÀK&ÜNש;¶ØMá>Ùk­ ÔëÔsmŽhŽc g¹Yˆ?Ô§]zt”xÍœ2¹E¯<-þì‡áÆ=¦e:ÜPntªÜûJ†!™ðŽ øž]L̃vA Ž>aõrÑlµøSÌ œÁñk*F´ ‹Qš­@ãT·6•xñ"þÊ^k1Üôè]õ¬û@.7ãÐÊžÃ2Pÿ ¸‰ %…1V’‰|ƒ½tbÆ]†lí\i9ýM]Òº.(òÞÑH"™”u¼"cKsÓ€¸¼îJR䎻{2îð4YÞH÷;1:z€Ï/ýó¹óÝÛªp™8+(ùÞ;|G_˜à;Am„âz‰­NÀô®º/@DÙº +#C7÷?v“ùÝpÖñïéq ‘çýV Å0Õk·r^©ãjÎÜ‹‚Ö8UÀxBWk’†lkd’ñb}°i3Î){iï•T:\Œ3 ÷k(C€rÖ>ˆ[Ót¶O>ÃÌp ýÔ¶•Ê“á’Ï÷²¾tù>U~i:cïà?€_‘f‡Å^[HWé(òªä™ •-̯ ¨zBÔug<”ã¿DOï)tÙùn"r$n=2çU©\[òéþ¬z>§Kᥬé¿=¶ùa¿—Üî.÷þLªM‰=gºðOÅ…QñC½`‚Øùr ed ÀØ®ûçÊ;nœ5}êªÊ³× +™ð~±2E­$ÞýöD²bûe—OpêŒûªHH—kN˜ý™§¨g3uK³ð„)×ÅÒÒúzâV(K>ɼÁŒ/ +tÖ¤#1õµ!°^¬E&¼É¨Üï5/ÇÛ›ôŸ÷¹1]§Ÿ¯O›+¼õ£—Ð\¦ôfW eD&µ¨¡è”^Eu”=x?®`’­Úí)zAé´02-¼ŒKåøú¹Ä„:4 é¢òs×@µñóåSÖ„[trž.šš<°eÌ™’0õÞYž )óâÿ¼¡M#Ö³‚ÿeH'//ˆxÄ"Úȱ‘·¾FlnnÅÇ-ÿ‘yP¹å£üG›õ±ûœ@ÃX©ùç=Tº‚^¯e© .Küµ©"ÛÊÿ@ ˆõwªÕyÉÔFõL‡_á”wà¨aä§9Þ¾æø¡~|ûï·ÿ|ûãßÿúàŸÿ 0‰—¡ endstream endobj 13 0 obj <>stream +8;ZEZ>7uQ2$jBK%s+QA>/Sq=c5Y6cWn>\:@j4%+nj$dh*&:QRH1_pWBe9qU,27T2H +1%?33Vg]q8\Q]Z8)`'?;SVcom!d\fh0N8iio1.*2C:L'mAB,=@Js%qs3Yn?geW>>3 +C:p#BQ'%5?K'\V[Q+\?'?@"5r"+dm(k8NQ7I]atp$fkATW.#qt_tmr,k5@94qC.9\ +Rp-%2CW#UC,i,s!n2iOYK"HDTTPEoEs5[4ZC2%ZGWg+'gE=F/tKdeP[kf?4.-F(Hs +-+d)C?u6f]UD"cEdfLr%)lj@[h2rhi]d&UkdL$7D=8"mFfN]NK4!7u"rYL_DTlpSb +*QKkUk-SLS`]u#1l=Y;pjLe.3\f<"iX$UiUpYQ-:9Auc7SE^0HH& endstream endobj 14 0 obj [/Indexed/DeviceRGB 255 15 0 R] endobj 15 0 obj <>stream +8;X]O>EqN@%''O_@%e@?J;%+8(9e>X=MR6S?i^YgA3=].HDXF.R$lIL@"pJ+EP(%0 +b]6ajmNZn*!='OQZeQ^Y*,=]?C.B+\Ulg9dhD*"iC[;*=3`oP1[!S^)?1)IZ4dup` +E1r!/,*0[*9.aFIR2&b-C#soRZ7Dl%MLY\.?d>Mn +6%Q2oYfNRF$$+ON<+]RUJmC0InDZ4OTs0S!saG>GGKUlQ*Q?45:CI&4J'_2j$XKrcYp0n+Xl_nU*O( +l[$6Nn+Z_Nq0]s7hs]`XX1nZ8&94a\~> endstream endobj 5 0 obj <> endobj 6 0 obj <> endobj 18 0 obj [/View/Design] endobj 19 0 obj <>>> endobj 16 0 obj [/View/Design] endobj 17 0 obj <>>> endobj 12 0 obj <> endobj 11 0 obj [/ICCBased 20 0 R] endobj 20 0 obj <>stream +H‰œ–yTSwÇoÉž•°Ãc [€°5la‘QIBHØADED„ª•2ÖmtFOE.®c­Ö}êÒõ0êè8´׎8GNg¦Óïï÷9÷wïïÝß½÷ó '¥ªµÕ0 Ö ÏJŒÅb¤  + 2y­.-;!à’ÆK°ZÜ ü‹ž^i½"LÊÀ0ðÿ‰-×é @8(”µrœ;q®ª7èLöœy¥•&†Qëñq¶4±jž½ç|æ9ÚÄ +V³)gB£0ñiœWו8#©8wÕ©•õ8_Å٥ʨQãüÜ«QÊj@é&»A)/ÇÙgº>'K‚óÈtÕ;\ú” Ó¥$ÕºF½ZUnÀÜå˜(4TŒ%)ë«”ƒ0C&¯”阤Z£“i˜¿óœ8¦Úbx‘ƒE¡ÁÁBÑ;…ú¯›¿P¦ÞÎӓ̹žAü om?çW= +€x¯Íú·¶Ò-Œ¯Àòæ[›Ëû0ñ¾¾øÎ}ø¦y)7ta¾¾õõõ>j¥ÜÇTÐ7úŸ¿@ï¼ÏÇtÜ›ò`qÊ2™±Ê€™ê&¯®ª6ê±ZL®Ä„?â_øóyxg)Ë”z¥ÈçL­UáíÖ*ÔuµSkÿSeØO4?׸¸c¯¯Ø°.òò· åÒR´ ßÞô-•’2ð5ßáÞüÜÏ ú÷Sá>Ó£V­š‹“då`r£¾n~ÏôY &à+`œ;ÂA4ˆÉ 䀰ÈA9Ð=¨- t°lÃ`;»Á~pŒƒÁ ðGp| ®[`Lƒ‡`<¯ "A ˆ YA+äùCb(ЇR¡,¨*T2B-Ð +¨ꇆ¡Ðnè÷ÐQètº}MA ï —0Óal»Á¾°ŽSàx ¬‚kà&¸^Á£ð>ø0|>_ƒ'á‡ð,ÂG!"F$H:Rˆ”!z¤éF‘Qd?r 9‹\A&‘GÈ ”ˆrQ ¢áhš‹ÊÑ´íE‡Ñ]èaô4zBgÐ×Á–àE#H ‹*B=¡‹0HØIøˆp†p0MxJ$ùD1„˜D, V›‰½Ä­ÄÄãÄKÄ»ÄY‰dEò"EÒI2’ÔEÚBÚGúŒt™4MzN¦‘Èþär!YKî ’÷?%_&ß#¿¢°(®”0J:EAi¤ôQÆ(Ç()Ó”WT6U@ æP+¨íÔ!ê~êêmêæD ¥eÒÔ´å´!ÚïhŸÓ¦h/èº']B/¢éëèÒÓ¿¢?a0nŒhF!ÃÀXÇØÍ8ÅøšñÜŒkæc&5S˜µ™˜6»lö˜Iaº2c˜K™MÌAæ!æEæ#…寒°d¬VÖë(ëk–Íe‹Øél »—½‡}Ž}ŸCâ¸qâ9 +N'çÎ)Î].ÂuæJ¸rî +î÷ wšGä xR^¯‡÷[ÞoÆœchžgÞ`>bþ‰ù$á»ñ¥ü*~ÿ ÿ:ÿ¥…EŒ…ÒbÅ~‹ËÏ,m,£-•–Ý–,¯Y¾´Â¬â­*­6X[ݱF­=­3­ë­·YŸ±~dó ·‘ÛtÛ´¹i ÛzÚfÙ6Û~`{ÁvÖÎÞ.ÑNg·Åî”Ý#{¾}´}…ý€ý§ö¸‘j‡‡ÏþŠ™c1X6„Æfm“Ž;'_9 œr:œ8Ýq¦:‹ËœœO:ϸ8¸¤¹´¸ìu¹éJq»–»nv=ëúÌMà–ï¶ÊmÜí¾ÀR 4 ö +n»3Ü£ÜkÜGݯz=Ä•[=¾ô„=ƒ<Ë=GTB(É/ÙSòƒ,]6*›-•–¾W:#—È7Ë*¢ŠÊe¿ò^YDYÙ}U„j£êAyTù`ù#µD=¬þ¶"©b{ųÊôÊ+¬Ê¯: !kJ4Gµm¥ötµ}uCõ%—®K7YV³©fFŸ¢ßY Õ.©=bàá?SŒîƕƩºÈº‘ºçõyõ‡Ø Ú† žkï5%4ý¦m–7Ÿlqlio™Z³lG+ÔZÚz²Í¹­³mzyâò]íÔöÊö?uøuôw|¿"űN»ÎåwW&®ÜÛe֥ﺱ*|ÕöÕèjõê‰5k¶¬yÝ­èþ¢Ç¯g°ç‡^yïkEk‡Öþ¸®lÝD_pß¶õÄõÚõ×7DmØÕÏîoê¿»1mãál {àûMśΠnßLÝlÜ<9”úO¤[þ˜¸™$™™üšhšÕ›B›¯œœ‰œ÷dÒž@ž®ŸŸ‹Ÿú i Ø¡G¡¶¢&¢–££v£æ¤V¤Ç¥8¥©¦¦‹¦ý§n§à¨R¨Ä©7©©ªª««u«é¬\¬Ð­D­¸®-®¡¯¯‹°°u°ê±`±Ö²K²Â³8³®´%´œµµŠ¶¶y¶ð·h·à¸Y¸Ñ¹J¹Âº;ºµ».»§¼!¼›½½¾ +¾„¾ÿ¿z¿õÀpÀìÁgÁãÂ_ÂÛÃXÃÔÄQÄÎÅKÅÈÆFÆÃÇAÇ¿È=ȼÉ:ɹÊ8Ê·Ë6˶Ì5̵Í5͵Î6ζÏ7ϸÐ9кÑ<ѾÒ?ÒÁÓDÓÆÔIÔËÕNÕÑÖUÖØ×\×àØdØèÙlÙñÚvÚûÛ€ÜÜŠÝÝ–ÞÞ¢ß)߯à6à½áDáÌâSâÛãcãëäsäü儿 æ–çç©è2è¼éFéÐê[êåëpëûì†ííœî(î´ï@ïÌðXðåñrñÿòŒóó§ô4ôÂõPõÞömöû÷Šøø¨ù8ùÇúWúçûwüü˜ý)ýºþKþÜÿmÿÿ ÷„óû endstream endobj 10 0 obj <> endobj 21 0 obj <> endobj 22 0 obj <>stream +%!PS-Adobe-3.0 %%Creator: Adobe Illustrator(R) 13.0 %%AI8_CreatorVersion: 15.0.1 %%For: (Christoph) () %%Title: (codemirror_baboon.ai) %%CreationDate: 08.10.10 15:33 %%Canvassize: 16383 %%BoundingBox: 55 -750 1318 -18 %%HiResBoundingBox: 55.6372 -749.6533 1317.4766 -18.5176 %%DocumentProcessColors: Cyan Magenta Yellow Black %AI5_FileFormat 9.0 %AI12_BuildNumber: 399 %AI3_ColorUsage: Color %AI7_ImageSettings: 0 %%RGBProcessColor: 0 0 0 ([Passermarken]) %AI3_TemplateBox: 700.5 -384.5 700.5 -384.5 %AI3_TileBox: 297 -663.5 1080 -104.5 %AI3_DocumentPreview: None %AI5_ArtSize: 14400 14400 %AI5_RulerUnits: 6 %AI9_ColorModel: 1 %AI5_ArtFlags: 0 0 0 1 0 0 1 0 0 %AI5_TargetResolution: 800 %AI5_NumLayers: 2 %AI9_OpenToView: -255 113 0.5 993 605 26 0 0 66 181 0 0 1 1 1 0 1 %AI5_OpenViewLayers: 77 %%PageOrigin:300 -684 %AI7_GridSettings: 72 8 72 8 1 0 0.8 0.8 0.8 0.9 0.9 0.9 %AI9_Flatten: 1 %AI12_CMSettings: 00.MS %%EndComments endstream endobj 23 0 obj <>stream +%%BoundingBox: 55 -750 1318 -18 %%HiResBoundingBox: 55.6372 -749.6533 1317.4766 -18.5176 %AI7_Thumbnail: 128 76 8 %%BeginData: 7878 Hex Bytes %0000330000660000990000CC0033000033330033660033990033CC0033FF %0066000066330066660066990066CC0066FF009900009933009966009999 %0099CC0099FF00CC0000CC3300CC6600CC9900CCCC00CCFF00FF3300FF66 %00FF9900FFCC3300003300333300663300993300CC3300FF333300333333 %3333663333993333CC3333FF3366003366333366663366993366CC3366FF %3399003399333399663399993399CC3399FF33CC0033CC3333CC6633CC99 %33CCCC33CCFF33FF0033FF3333FF6633FF9933FFCC33FFFF660000660033 %6600666600996600CC6600FF6633006633336633666633996633CC6633FF %6666006666336666666666996666CC6666FF669900669933669966669999 %6699CC6699FF66CC0066CC3366CC6666CC9966CCCC66CCFF66FF0066FF33 %66FF6666FF9966FFCC66FFFF9900009900339900669900999900CC9900FF %9933009933339933669933999933CC9933FF996600996633996666996699 %9966CC9966FF9999009999339999669999999999CC9999FF99CC0099CC33 %99CC6699CC9999CCCC99CCFF99FF0099FF3399FF6699FF9999FFCC99FFFF %CC0000CC0033CC0066CC0099CC00CCCC00FFCC3300CC3333CC3366CC3399 %CC33CCCC33FFCC6600CC6633CC6666CC6699CC66CCCC66FFCC9900CC9933 %CC9966CC9999CC99CCCC99FFCCCC00CCCC33CCCC66CCCC99CCCCCCCCCCFF %CCFF00CCFF33CCFF66CCFF99CCFFCCCCFFFFFF0033FF0066FF0099FF00CC %FF3300FF3333FF3366FF3399FF33CCFF33FFFF6600FF6633FF6666FF6699 %FF66CCFF66FFFF9900FF9933FF9966FF9999FF99CCFF99FFFFCC00FFCC33 %FFCC66FFCC99FFCCCCFFCCFFFFFF33FFFF66FFFF99FFFFCC110000001100 %000011111111220000002200000022222222440000004400000044444444 %550000005500000055555555770000007700000077777777880000008800 %000088888888AA000000AA000000AAAAAAAABB000000BB000000BBBBBBBB %DD000000DD000000DDDDDDDDEE000000EE000000EEEEEEEE0000000000FF %00FF0000FFFFFF0000FF00FFFFFF00FFFFFF %524C45FD13FFA8A87D7D52522727F8F827FD6FFFA87D522727FD0CF8A8FD %1EFFA8522752FD48FFA8A85227FD0DF82727F8F8A8FD1BFFA85227F8F8F8 %7DFD45FFA87D27FD0AF8272752277D7DA8FFFFF8F852FD18FFA827FD08F8 %27527DA8FD3EFFA87D2727FD07F8272752527D7D7D527DFD05FF27F87DFD %17FFA8FD0FF852FD3AFFA827FD08F852527D52522727FD05F87DFD04FF27 %F827FD0BFFFD04522752525227525252FD10F87DFD39FF27FD05F827277D %7D7D5252FD0AF852A8FFFFFF7DF827FD0BFF52FD1BF87DFD39FFF8F8F827 %527D52522727F8F8F82752525227FD05F87DFD04FF52F8F8A8FD09FF7DFD %1DF8FD39FF7DF8F827A8FD07F87DFD06FF5227F8F8F87DFFFFFFA8F8F87D %FD08FFA8FD1EF87DFFA8A8A8FD34FF7DF8F8F852FD06F8A8FD08FF7DFD04 %F8A8FFFFA8F8F87DFD07FF7DFD1FF82727FD04F8FD04275252A8FD2DFFF8 %F8F87D27FD04F87DFD0AFF27F8F8F827FFFFFFF8F852FD06FF7DFD2BF827 %A8FD2DFF27F8F82752FD04F827FD0AFF7DF8F8F8A8FFFFFF27F827FD06FF %27FD18F8272727FD10F827FD2EFF52F8F82752FD04F827FD0BFF27F8F87D %FFFFFF52F8F8FD06FF52FD0BF85227272752275227FD04527D5227FD12F8 %52FD2DFFA8F8F8F87DFD05F87DFFFF7D2727FFFFA8527D52F8F852FFFFFF %7DF8F8A8FD05FFFD0BF8A85252FD0A27FD16F852FD2DFF27F8F85227FD04 %F827FF7DF827A1B0BD052752A8F8F852FFFFFF7DF8F8A8FD05FFFD0AF852 %A8FD23F852FD2CFF27F8F85227FD04F827FFA87DFFCAB08DA8FFFFFF27F8 %52FFFFFFA8F8F852FD04FFA8FD09F8275227FD24F852FD2BFF7DF8F8277D %FD05F8FFFFFF7DFFB0B0FF7D52FF52F827FD04FF27F852FD04FFA8FD08F8 %277D27FD26F8A8FD2AFF7DF8F8F852FD05F8A8FFA852A8B68CC4A8A8A87D %F827A8FFFFFF27F827FD04FF7DFD07F8277D27FD27F852FD2BFFF8F8F87D %27FD04F8FD05FF93B045592727A8F8F87DFFFFFF52F827FD04FF52FD06F8 %277D27FD1DF827FD0BF8A8FD2AFF52F8F82752F8F8F827FFFF2784596FFC %68F8F8F8A8F8F8F8527DFF52F8F8A8FD04FF27FD05F85227FD05F827FD17 %F82727FD0AF87DA8FD2AFF7DF8F82752F8F8F827FFFF52F8F844B068F8F8 %F87D52F8F8F87DFFA8F8F87DFD04FF7DFD04F85252FD05F852FD19F827FD %05F82727F8F8F87DFD2BFFA8F8F8F87DF8F8F852A8FF27F8F8208CB0F8F8 %F87DA8F8F827FFFF7DF8F87DFD04FF7DF8F8F827FF7DFD04F87D27FD20F8 %2727F8F827FD2CFF27F8F85227F8F8F87DFF52F8F8F8B0FC45F8F8F8FF52 %F8F827A8FFF8F852FD05FFFD04F87D52F8F8F8277DFD22F87D27F8F8A8FD %2BFF27F8F85227F8F8F87DFF27F8F8F868B044F8F8F852FF52F8F8277D27 %F827FD05FFF8F8F827A8FD04F82752FD22F82752F8F827FD2BFF7DF8F827 %7DF8F8F8FFFF27F827F869B0B0F805F827FFFF52F852FF27F8F8FD05FF7D %F8F87D52FD04F85252FD22F82752F8F827FD2BFFA8F8F8F852F8F827A8FF %27F8F80520B0FC44F8F8F87DFF7D27F8A87DF8F8A8FD05FF7DF8A8FD05F8 %2727FD23F827F8F8F87DFD2BFFF8F8F87D27F8F8A8FF272727F8F88CB08C %20F8F852FF27F8F8277DF8F8A8FD06FFA87DFD05F827F8F8F827FD24F827 %FD2BFF52F8F82752F8F8A8FFF827F8F8F82044B08C44F852FFA8F8F8F87D %F8F852FD07FFFD09F82727FD25F8A8FD2AFF7DF8F82752F8F8FFFF52F827 %F82168B08C698D442EFFFF52F8277D27F852FD06FF27FD09F85227FD25F8 %A8FD2AFFA8F8F8F87DF8F87DFF7DF8F8F868698C8D68B020F8A8A85227F8 %7D27F827FD05FF7DFD0AF852FD26F8A8FD2BFF27F8F85227F8A8FFFF27F8 %20B08CB0B0B068F8F8FFA8F8F8277D52F827A8FD04FF52FD0AF82727FD24 %F827FD2CFF52F8F85227F852FFFFA8F8F8448D686820F8F87DFFFF52527D %27F8F8F8A8FFFFFFA8FD31F87DFD2CFF7DF8F8277DF852FFFFFF7DFD05F8 %0552A8FFFFFFA852FD04F852FD04FF52FD31F8A8FD2CFFA8F8F8F852F8F8 %FD04FFA85227277DA8FFFFFFA852FD05F8A8FD05FF27FD31F8FD2EFF27F8 %F87D27F852FD0BFF5227FD04F852FD06FFA8F8F8F827FD13F87D27FD18F8 %7DFD2EFF52F8F82752F827FD08FFA87DFD05F827A8FD07FF27F8F8F827FD %13F85252FD15F827F8F87DFD2EFF7DF8F8277D7D527D7D7D525227522727 %FD05F87DFD08FFA8FD04F827FD13F87DA8FD0CF827FD08F82752F8A8FD2F %FFFD12F827FD0AFF52FD04F82727FD05F827FD0DF8FF27FD0BF8277DFD07 %F82727F87DFD13FFA8A8FD057DA8A8FD13FF27FD10F87DFD0AFFA8FD05F8 %525227FD05F827FD0CF827A8FD0BF827FF27FD09F87DFD10FFA87D2727FD %07F82727A8FD11FFFD047D52FD047DA87DA87DFD04F8A8FD07FFA87D52FD %07F82727FD07F82727FD0AF8277DFD0AF827A8FD09F8277DFD0FFF52FD0E %F827A8FD1CFF27F8F8F87DFD05FF7D52FD0BF87DFD07F85227FD0BF82727 %FD09F82752FD06F827F8F852FD0FFF27FD10F827527DFD1AFF7DF8275252 %F87D5252FD0EF85252FD1FF827FD05F827F8F8F852FD0EFF52FD08F82727 %27FD09F8A8FD19FF7D522727FD13F852A8FD25F85227F8F852FD0EFF27FD %04F8277DA8FD05FFA852FD06F827FD18FF52FD16F827527D27FD04F827FD %1FF87DF8F8F852FD0EFF27F8F8277DFD0AFF7DFD06F8A8FD17FF52FD15F8 %275227F87D5252FD1FF87DF82727F8F8F827FD0FFF527DFD0DFFA8FD05F8 %52A8FD16FF52FD14F8277D27F8F827525227FD1DF85227FD06F827FD1FFF %7DFD06F8A8FD15FF7DFD13F827A852FD05F82727FD24F8277DFD20FF7DFD %05F8FD16FFA8FD06F8FD0527FD06F8277DFFA8FD2BF827A8FD22FF27FD04 %F8A8FD16FF7DF8F8F8275252FD05FFA8A8A8FFA8FFFFFF27FD0CF852FD1B %F8FD0427A8FD22FFA8FD04F87DFD17FFA852527DF8F87DFD0CFF27FD0DF8 %527D52FD18F8527D27F87DFD23FF27F8F8F827FD18FF7DFD04F852FD0CFF %FD0EF87DFF527D27FD15F82752F827F87DFD23FFA8FD04F8A8FD18FFF8F8 %F8527DFD0CFF27FD0EF852F8F87D52FD04F82727FD0EF827FD04F852FD24 %FF27F8F8F87DFD18FF7D7DFD0FFF27FD0EF852F8F8F8527DF8F8F852FF52 %522727FD0FF852FD24FF52F8F8F827FD29FF52FD0DF82752FD04F827FD05 %F852527D27FD0FF827FD24FFA8F8F8F827FD29FF52FD06F827FD07F852FD %05F827FD17F827FD24FFA827F8F8F8FD29FF7DFD07F827FD05F82727FD1E %F8FD25FFFD04F8FD29FFA8FD07F82727FD05F852FD1EF8A8FD24FF27F8F8 %F8FD2AFFFD08F852FD24F8FD25FFFD04F8FD2AFF7DFD07F82752FD22F852 %FD24FFA8F8F8F827FD2AFFA827FD07F82727FD21F852FD24FF7DF8F8F852 %FD2BFFA8FD08F87D27FD1CF827F8F8F8A8FD24FF27F8F8F87DFD2CFF52FD %08F87DFD1DF8522727A8FD23FF52FD04F8FD2EFF27FD07F85252FD1DF827 %277D7DFD21FFA8FD04F87DFD2FFFFD07F85227FD21F8277DFD1FFF27F8F8 %F827A8FD2FFFA8FD06F82752FD0BF827529B9AA19A7727FD10F8277DFD1C %FF52FD04F87DFD31FF52FD05F82752FD0AF8529AB58CB58DB0B0BC52F8F8 %05FD0EF827A8FD19FF52FD04F827FD33FF27FD05F87DFD09F852B6B0B6CA %C3B68CB08CB676529A772705FD0DF852A8FD16FF52FD04F827FD32FFA8FF %A8FD05F82752FD07F8059AFC9AFF948D8CB08CB08CB59AB08DBD9BA1767D %2E27FD0AF852A8FD12FFA827FD05F8FD35FF7DFD06F85252FD06F827BC8C %CAB6FC8CB08DB08CB08DB08CB08CB0B0B6B6BC9A9B5227FD09F8527DFD0F %FF52FD05F827FD34FF5227FD08F85227FD05F852B5B093B08CB08CB08CB0 %8CB08CB08CB08CB08CB08CFC8CCAAF7DFD0BF8527DFD09FFA852FD06F827 %FD32FFA8A827FD0BF85227FD04F852B68CB08CB08DB08CB08DB08CB08DB0 %8CB08DB08CB08DB0C4FFFFFF5227FD0BF852527D7D7D525227FD07F87DFD %31FF7D27FD0FF852FD04F85293B08CB08CB08CB08CB08CB08CB08CB08CB0 %8CB08CB08CCAFD04FFA87DFD17F852A8FD30FFA827FD12F85227F8F827C3 %8CB08CB08DB08CB08DB08CB08DB08CB08DB08CB08CB6FD08FF7D27FD11F8 %2752FD34FF52525227FD05F8527D7D5252F8F8F82752FFA87D522DA1B08C %B08CB08CB08CB08CFC8CB08CB08CB08CB08CFCC3FD0AFFA85227FD0BF827 %52A8A8FD3AFFA8A8A8FD07FFA8FD09FFC3B08CB08CB08DB08CB093B68CB0 %8CB08CB08CB0BDFD0FFFA8A8FD057DA8A8FD54FFA1B58CB08CB08CB59BFF %FFCA9ABC93B593BDCAFD2AFFFF %%EndData endstream endobj 24 0 obj <>stream +%AI12_CompressedDataxœì½ë’Ü6–.úx‡{΄¢TJI5]•¥]—vÛ/³ÿìǘýbgÝLfefeZbI,º¬L â²°°.ßZøâÿùáųÉëëW«gù8©/¾˜Ý¬Îî®oþ8¢ÒÑ7——÷·w7Xôå_4Ü7M¾©^ÊYÝÜ^\¯ÿ8ÒÅ8køãŸþröîæâöîúý»¯F_~¥?]Ü]® üüúõêêâææúæå«³W××ëñÙÅWþ½PÑüìn˪±†Ú2¨õyŽ>[ÿíìööâ7ø£vy…eÓëûõë‹õÛéõßÿ8*ŠÑ³²€r]žé +þþ¯?®n[7]^¸ÓÖcWä9Þ^Žmé>3.téàÁùõùýÕj}÷ÃÍõùêövv}y}sûÇÑì׳õèÛ³·ð—³Ñÿ»º¼¼þe4½<;ÿ«‚)^./.WÐ÷«³»Q£4ùF›—Óû‹Ë×ßÝ_½ZÁ äuÅùKªñÏ·PÔŠŸ±¸|ùÍ”¼XÝÝA{á}8Ò?þi· +éúò?~€ÑXÁËnþºZÿçW\íO««÷—0~Ô×2ËÆ0&yeáŸø‹Ü ­¥ûL]Žž9—ÃßuVe0Y¸©ˆÕß.V¿üqôÝõzŽÜܽàÙ°Y6*]ÅÅ?Þ_®nþ¼¾¸ƒö;,ª¹³ß´_ÂÍááååõ‘.ÝüŸoøéìæíê¦ïúòþŽÈ«ÊäO0˜ÏÏ~]á„~Á÷ïW럮ÿB |f€´ÎGØßºÎG.+FÆQý0ɺò¯Òô:iÖ€ÏûŠË†þ˜Œïo.Þ^¬ÿ˜CŸ¹Êò4ýéæâu3K@NÿªWÑoí¹¡Ðç»»ÕZ†¨cöm4ÛÙøÛðÚÅúõìú +Gýi|ï +¸¼~Ë Ÿé/ðøý{î} ôÃÍÅëTßÑ_ª—?\Þßþts}ÿþ›õ›kõ%/íŸnÎÎá¶Ñ÷¯þku~Ëô»³ów¿­.Îß­Wkø*qq·‚Eúþ«kƒ¾Ý¬FüGx˜¾úw?=_½•Ó<Î¥ÿúÿ™¼¼¼\­Ÿý¯ûÛ³»ß®®_ß_Â_ë¿­.¯ß¯Fgë×£?»y¿û?\ž­ÏnFTîëk}³¾[Ýœýõîâo£«³K€çƒÏ`4÷¨èæ= #=B·¤ïzè†èO{¼èìîpÕúõm¨{²~{‰óv¿~»1VØ ¾}wÝ/Α>oFÓ›ûÛw£Ÿ®¯/Ã+^¼_ývqvùþb}»ºl½B£§ð¡½èz`ýýš‡móußÂé|0©^¾ îÞþ–)l7Oä³³ËË‹·7gïß]œw½æßäïo.Voã硺_¯^]_^Ü^5Ä•üpvswq~¹zñ+ÌÓÕCµá¸¼¹X¿&æªÃö!ç~»º]ÝývL˜U}÷nI¼õ/™ÇìúÙ³ø¸®GÓuô÷?Ýœ½¾€-ªïV×ë|þ/o×°›¬¾Re¸ß•£ékõ*—E]Û?TE {]6vµ.süPg:sðoVÚBã¿¶ÌŠ?¶ÎŒ²£/^NoÔ¿¨™+ŸÙY1s³Él:›Íól®çfnçÅÜÍ«ùd>›ÏçËùr‘-ôÂЕÓU,]¥\Õ¢Rø¿EM×$ü_ÓèsûoMix^ÑÇêÁË¿ßѯ£vrY¹¸ÅÐvÿÓpeþ®ѵ‹fpMéšÐUÓUÑUÂÀàUÀeŒTN—qÃ+›g³%\ ¬cÆ?S¸&tÕtUt•p9¸ +¸,\9^<)®lº„ †Œ2›âÏ®®jZÂå¦\vš«ÿ³‰5âoAsŠ•ä\T¶ˆÿU.©Zü4…*§TõLþ…ÿ+z ¿«’·9z½sªá×L3øÕ“%LmÿŸCð;¥ßɤ¦ß’~š¿ùį™húÍê%þÂø.àw½›Õ“º¦ß²vð[Ô–~M­á7«–0íK˜‰™‚ÿM«IUÃUU%\®**áWW¦Ò岜mÌa° pþ¸ÒÂ:ÉK]feæ–0•Ð-7q•«•+]árg™sQ,aŽqŒë¢,ð'/taŠ H +¦¦ :b+ Ë .kÕVçK"¶Y>Íë|¢@ËÁ—¹Üæøcò,×y”8‡ß™™š ýV¦†ßÒøK³IɃXO*3Cë G¨†þâÈätexÑxÀˆÀ`Lh@Jº +º, …Qø¿ +”¾¦4.5ß ãâhlüèà…ル +éG©¦ T-çüZ«Üi¾`´ðZÀ˜!IO誡¥Œ“¡+³Kºp gv +£Ó«àÕP# % ¦ÍlFÃ9§æOÑ‚FTÓh.a4ç0š@O0Ž5Œ!ÌŸ±ÊÀxc2“é%\¸ª¦ºýûF“¥µf™-qÑÂ5áÁÌ`òá²ø þÙÿ¨ì?4›0†È…41š1”ØGŽü8rˆZV®õÉ+²Òƒe j˨‚µc¡‡PÁTÑâ(púaêqÚ+ }œè è}sZ¨Ã, +}×BØZH ÚÑt01OÌ@ƒoià3 bò ˜'^O¶3ä +¸0–ÇÆº£;Ñ…]‰AÑð`Þ%²ZâidZ~a¨iªé2téäzìà?81zgSçÑe¶\Û~²ÍK v_‹-×¼óÂ1ž)þ'¹¦[®É–«Ž/}©¶\å–Ëu]Ц½ë²[®|ËÅäb”ÿ®®‘N–³Ì&Œ Ü"[Òß5Í^ä Ì(¹~QUÃVÜcF›üù ¼CüÉaXX Oi*ËcB|·räóK³$¾¯åÈÚ€{!ç,—!ŸgýN¼n ½Eîdˆ Zòˆ-–°>+X¥à—Sàšsm–4h¸+A° ñÇÁâFÆ_ž/FYv3yíŒöˆ›Ü LÙ>ì}°N€S §ŸÇ_º%LžÆÁ]¡€ñ§îRþ1Eù…ö×…*—@š6]Ü~-¼ê„]¥¢ÍyÛôØÔœD¶%ÑîåØ{ÜÛíóx+îûSäo3¹(À…¢‚!Á¡ !¢¤}¥‹ É(¤-x6yu˜CžÁ:ÌÞ"Ì\f­¢)›úé¢Éâ©*T˜'ž¥y˜!ó#SÃÃÓ² SbÃtÔ~*”Ì„“àÂLýàËÐçaØ«0ä8à<Ú<Ö… += ƒ¼ ÌÃ[†¡…QÕaDy©aš¦¤P,‚B‘$¼W$õƒ| +bøb±„Ù ŠÊ4o]&ºtr1O[FW£\ˆ0?™)’¬øâŸšä,¼PRt,¼LHÀƒAÊI^EiUk\µy %²™"ÁuŠµÔµh%‘uA¢«%R7$ÂjÚ³—´Xh›&R,.˜TKb, +mZ͉²¸èXlcÁ ÚBÄ6D¶9 lhAåŵ‚Ä54lºKÒPT›1Í‘–åjÑ$ Mi]‘à–Ë¥iý0—]È5%ùª¦•VÊšcÁ¸™ìйl‚KÞóx'[ + ƱÅé«€?LhO©cñ.‚|ÎÑFPÛ/ä_ Õ`;h;o±÷ã~ú!pÈ£ÿCÁãÈÞ2êoNã€cÃc5¥|ëSñ¾Ç°>õï{ ëSñ¾Ç°>õï{˜õÑJ V"ÌE„(f=ž!1‹¢mšô‚ªqTUIÕñEõì ÕÎ?d+˜Šñ´ÿÙ–A’£uFVÃ&b–1^N‘UÁ‘}¡[C-[!ä-b kðl¾Ðv±i’-ZÍIÁC‡•‹¤ +±…x•’-$µ\Ìn¹+ò6¯(1¶ˆñE$Zf$&±2±ýÆÛs€>XZ¦×6Ñ9\úáK-̓W¾ã²íKµ +Š/·ãÞ¯ð[¯êÁ«îºTôe²ãš¦W¼3ï'óÐìù•߬ýŽÕ¯¢åßÈ>"'ñæÊœŠH’ÄNa šöa=-íÏ,~2£¨iŸ»˜)¯%Ë¢Š¤Gsb"VÄRf&¥Èµˆ§“ iÌDP%a5\À–ìD·ØJÃZÂÅï‰zR¡ßËY•³ñ¦¯DMdÛ×2Y3п^±eXthÖ²E ÷Š; 'J$ob;Û‹<[b­ÒÐS^*ÈXÇ;s0z[©%9U“4º Ë([D+0½4#a’MŸ“`Ü+ FÄÅ…Š“ $"j‘ çA.ldÂD"T-‘Ð˃^ÜK$S]E–:ÐKÑZdÄ^äth3ªÈjÄ&:#&:¶MÅzTFö#í-HŠ|"Óà@‚‰mHlAšÊ —4û– º±²µmÿÁòO—nŒÿ-ÃcöLÿ*²ý7Ö¾@vDï0Á Å(³d—€’=vÞò ´ý±‡ ”ÝÜÉön_÷‘ ¼¥g<‹ Ið[üÏ$xê Žp¢DRñr K1©ÒÕ¥h-Dýnï;÷–ÎÍ)Þ¦ÞÛÚñÚØLU«àáycco]@÷êAÉàa¹b‹0Ò|Ù!×´å –ÎlEô,E†­ƒ¤9 ÒåRTyÉ“^–ôB$£Ú éqdF&úXTŒ…ÄX<”ÕÕH‡ü³è ½x¸)F¡Ÿd™z%¸êÄY¹á’TžÊizKËÛ¹é”d–$lH bî3'O@ElÄËð¾€ ­vKÞãÕoö±§h"ž£{’Ø«Dj*nŽ<$±bTÜØªÈ6EKΪRGÁeFœkû(2úœì‡%lH9sÜ@h3´Q°iàÖ1!1'E eµœd5§Ä68!1½nKö‰GŽ•µX<›“ʶ¥Ý{VÜ}¥"¡¬_à,èosöŠç¹\|‹Nœµ8§âŒ\ ÑgŽixZ<—ìÅ´âÕtAßãõ‚ÿŸ+† _µ|›ÒÚ™)ñ¡’5,þ?ìb¼¨rZV8…øf«SˆlšlVl"›ç'ÄûçÁŠ“hã-1la«uF48²~Öb°žÑÎEôÄ&¦¤ŠLÞ° ‹<ÖŸCšê` +@²bÅ'c—Ÿ"ïSWlÓÚÒÈ,@zˆaäU´Î‰ŠÀNÇ©§l$Pâ¡ÌEU`ïe%Ê„63¿Y³ª`ä²âå›kq™Š¢°/ûV½õ€)oA´Vl4ÄÔ3 š9 ¼£ÂY¢ Ê‘?À´LaJ2˜ ˾‚Åj­çåZ¦Ð3#«¯Žð-9pÜ’ 32EkÚNÜælnó!µ}M¦ìö¥ÄLÙ}mó‚u:ÍXÕQ>¶m>¹zË•¸úTôe›—pÓŸ8²é¸ÔVŸå6ó̶–µáEÝæu<³ÞX7º×DŒüÞÀoƒY? ZØÛࣿ©`¾HñÃÛ-Öõ Ý¡eTˆÌÍ×¾ÅL¥ˆÓN[¨ÝXÛ ?ÎųŽz ZÇ3úÍH~žvqJú\)«Î»ÇQ Épõ‹Dsý ò !Û¦$£WÄ-kÒ­ÆxEú_KÎÿ«Ã*¥_B©Ðrm/ÙfÙNä·&5¢¤%\‘¤Îѯ%pU°ˆ-9+Ðe‘u.ç9©-Âà5ËÙÉr¶„Ê +Y¡“„¬³€<­?éȵBèIí-HÍÂÁ+Š,xI+vNÊŒ€¢ýwk ÜyIËvAV<qG6…‚$z±Ÿ²Ýts3åûdƒ­‚7Ó)a+2å‚8fLñT‘]û¼bZlø; `ß\¾¸CÖ4ÓÍ%£VgŠæÅÑèê lEœÑ¼qA ²³€.]„ŽÂ£*tÄ7Ú7Ï·ƒÑ¦o:'#9cN=êÔ[†qqJÀ§lØcª7ïÍh÷ ƒ1-yEõ`T6³¹Ï#RkE¦äi°ü 45€S5/T=DÕ‰!°¢-ŽªS1F’l‚‚Xõ°œdß"€JÚLë^õðÕ9[ ƒZ+Á±zXAARy™€ Èf{Pöå¼{sèÿªÃo.¦¤Øœdƒ]¨ s™|YxªÈªÃö¼IÂ@<Ãð¿ôR¯½)Åÿߨh-m°¼k5÷® qf,DX˜IÔT-úw)~RIeMx”òª¸x:»tñÝÚ8‹¤«NÏúúø$È6ÑÂIW‘?ÝP@ëߤ}³o†%Mü —ïŒtMKÜ…@ƒ#N¡&¬MeîJ +8±¢å™VB ˆðN]!!"€R6æ;®ÙC—¢¦;¯® ÂM‡].ìºvÆþ½äRÑ×¾˜RN´DΪN ´DF¨N ´DyK=$pј¤ ®$ _÷Vâ­™’CzÕE˜.Aº|DÁDà\óÈ¥El‚ +6à +¯¥î)¸,#àNê,Ê9AÑ{Öc¿zãS'ºDæDdÇćo@A kxqad"®…½/¿Q¨’ ·©ìMDêá­¥µ¥HÂnLؘÂVõÁË¿(¡bOÚTðT_ˆ‰—I— §“lU Û.-¡ Ÿ'†‡#HMPzBª)4º‚GJXÁH”¢3ÔŒ X„òxAAÑ l°¼|ÐY8m…Äà#d’dAfA>m¤n¼ÚN‘Y¹&sãŒôr˜Yþ·~ÚàÁÝl;ºdúqtûC×® (lUjëöàFHW窢/?ì{q»ûB=ЏÝ}¡EÜî¾Pù/hL6âõ§‚Äcž©”1wihþ<’O'¥D拨ª*网›þÈÆ#™û@#f¤8Æ(„ÅnÉà˜Ü,šÉ,±pÛ„ÇÃd)Ú[÷dâ Ü©ñR-rº.KÕ¡Ü;'°¬&x¬¬R€•xŒ@%Фù‚ÎTTÉvŒ£—wJvvv諎A}TÝúcK}´bNUH$ùí?3†?!xAyÆ +ÊÒ4x‰f"@uŸÀæÄ(KÓ‹=¡iFŒ=ôFàÁR›=eÑ÷€¶*Óèk ëó°·67Úd,ÍOe¡’`Ї"%ºà’aY¶œ&Û½"mwJë¯*ñäñ÷øo.ºð͇ü_y¤'tÏ&îþ¤É™²ß4* 8ÆM:’BЊ9ÚuPSVâÉòyáQ@5{úÄÛÔ½vI@sr³¢µ-=ÈÁ°ÈÑ,-)GÆd8(Qàø£Ñ†°~‚ÌBÍP´š ¡prâ­%aq<æoF“ Ë/žBðXÈ®›…ƒ€ ãÊç '#®Ÿ‹ŸÄ®Ç/žBœ*Nœ,¥8]H a/Œ_Q­UÅ+‹à…âÚ @ÃÆýc·ŠV]Al°"äû”ANÅׄL˜'2RzY^¥@Æ ,X‘ 92ì–´,ÙÓ•“ß‹c=æè8½x¦QêŽ!H]T„€@ȨEƒº"Ï[-ÑX@]KA”D[Iº (Ò’ ¤¬zë?2fàÈŠXñ‚hÈË­ˆVfD†ÈÀÑdÏžg ŠS2žç¾$´C=$r\H½ÈH§ŒÎøeNÛ·w-GFzE~,G9Ž*"§Fz°%Þ줨ÔOŠ:©—ê´¨Œº<)êÄ.ÕiQ'h”ßuâ-/“¦¹ÚVý2¹R‡@â,Plj®ÔÓÐþIÝižŠ%ƒ¢ü®Úö~¤¾‘YrµÝ*‘ËEISsµý5er¥®žÔ $AR"õ!=œø$M¾¹­TGr“Žd&‚ý’lE“MlͰñÁ«MLM¤fvÛ`5ig•`k Y&IŽ!Y”‡ÝQ²#Þyð]A®àŸùH‘¬Á8ëpEè%M‰*ShÅé©$³ZNLtA8¢™$˜«$…š!@P¦bÞã¡|EÀý¤Ø=¿}:ÊÎ=–ŒÔS!眣l]–†ß>÷SSÖ®R-MÞ®©äí²1^OQº‡*òM±WÊ'?ÛòÓÎiÖD2!=i¤/àŠQŽñ0@é<­)Q zì(£A€¦u¥„iý3%\Nüf4°œÍlAŽ·’À>A}85ç1›ªÀfƒRÄ)Ø£±XH&Öæ3Â!#|ª@›0ShjÊ x'ŒUðþ{ÏÿF>)ñöû|RE@éxœŽw‘ëH…lRùƒÙ¤–I6)L,ÞÈâå÷¹Jì,¦3—Ô´ÌïýKíp~ò2©LRí°~o°÷§y!`¼ã:ÆQt#)º±šBEpŠ, DbEˆôœb&µÌv¹áüö³Ìkd{Õ§ UE ·ñå®±AZ*Ai,7è‹ÍzuÈ´ÓE` q%9 »Ö(iÑu$ÎgÞ |”­®mªS[muLõ¢µÔmóäî~×fAµ•oúsw›+Ôëà†WWœ±Á;d§mm-J‰Ò¸fÏ‚ÒdNWIê“&}ºO ÞèÙMŽÉn’G6.[k%É"½ç6öÝz-¼-¤±Ž”V’"OÃiæâ«w”â*öÔ[ ç¥@EÛWIÛW\‹¼…ÚÂlÈL<‘]l.°o/ÕXZ镊„šÆ;ï]‹Eðdz^üˆäC4´ÁYÉí0!‡à 3/ȈK*‡ŠVnpì5­–,±œÄ òÇæ‹cý½‹­ÉœÀy˜È”µ¯‚,,ŒÄ.µZZÄæäHËɆ®Y΋@û¾B׎ BÝ’¡¢Þ/©ÛŽº<§[òLNÉCÆÙÐ76§<'vê¥1™‘e4§E[Ñrz¢\6>é#É…@¼ßsÏÿÛ g»¢Öëx'¦u­BкßüŽÆ¬›ÕY0{³9™ÌU²î}H^J#Öó$b}ŒbÞ£DIÉ”˜ÂCÀzð,¥ñêeð/yÓVK·­ÃÚ/¸‰`îW‘½¿Ûâßióß´ú{£¿Úb÷ï´üo±ýo±þwÛÿ€÷çxaˆ’ÿÐQòÍ©A#_ËÈ×2’ZFRËÈ×2òµŒÌ¨,Æ.ÓŨÌÇ ¬õ…úâå‰kÞÛÎ"Uå¸j:Q£ +¹uYŽ-ÍÆÚ‚2SɈPee€°J â'«±.lêéGô·›2³í¯<}*¨ÇΚê„T ž¤uu6®jëN×:_!¶¯¬/ñ¸gÆñÁ–5mXbÕhy¸=M¾™º£*¡1ʪÜil§ÍÊÒñ5ŒÙ”ØãJðY*0c£Ëh\Ž©äñcaÆ%0ì#ÇB*9 ½äcÞOÈÓ|…§iç ˆŸ°uR!µäXYY[¬Œ6f­ñŒÖ<+*šcoêPˆ SÉã©¶7ØÜ¤f©äñcáÆ(:9RÉñôb &¨°Æ +ï= Ñ´k= ]×cIOHÖ\´m:gHú£ »O‡üñúöl„_Ï.¿RÉ·‘†Jù@H¯Ùzt~Eè|NÙVOg‰ÞY­%f\ìÖJ’ˆN#Óµ!Õ­¿ÁèÇg±ÏxBxâEÀæJÒ:zì}cpnŸ6T:8ÍåØNúNÎÀͤ¢ìÒhÌÎY’ðÝ‘á;Mõ¥yWIp`ê»èò_ÄÞ‹p,Dã»h¼V’Œ6 Q?FÛ“Ñ\r„Úz„ÿ·}*Dl½óžè€•œá¯ö÷ô‰Ž+¶­èKö© ÛY'Ãy%IÞɶƒß)ñíû4”ì×÷žíéPø¥zÂOwúSïÎWbášSæ\R”Å™ÏTÏ”_HæSöÜT‚~žPZK^ +Œ±‡%¡HyOŽëŠ ep݇L»d![HšG-yw‹ú§S´|šìíÈ–]‰lßR!<">Õ™˜ÖH?ŠoÑŸ´¤oZYF‰Už_‹=H(§É³*A&MJ5m ¶ytq¢DËg9IËê/Υؾø!ÆäËåb9_Î(ûx-y´ +ŠÝh¢5æN¾ÑüD*8ŠÚ®¢ÔY»‹‚è+ŠÜF6‰[§Ît#:¬+6LòUªà¦o¼<­È°(ge“µ²#6ŒŒ,¹Jžòña>…å~8܉«Z`Ü8ËOŠÅиRòþzT.ó€ÃfƒS¦rÎÃt¨ëÁº°ëA»“Ý­€×_ÔtÅÿ½:¾º~ìö‹³ào£ÀMôØEƒÁW©ÄY™º+MšJcƒ +·ec žKœ—Ýt¸‰4mçMmQ¢ò'¡íˆR4Ó8Å jT)A&÷¡È”&-Â#ZdAÄÛtSfmuª¶IT7y{[tÓjD¯*!ÚMâtòÆÕX ÿC‰­O'Y1×ã¼íÔÖci·Þ&Z4ŠYeß"×5*)#ssZê +y#åê,‹5çÃrŸ‡¡4 +è˜6†Ñà>;ϱãÓäø XÙÓcYÚÙLñ<•øt±Çeä#<`.@’1º{aæblSƒnšµ@s ¶©àœjåŸñ‘¢‚™$žIβ•Ä3<~Š 4ù\_.úõŸ|Ž ŸÆeÒ~Mù¤DíÔ¢g1 Ú +©5|zXÿ²d7°|œwÖ%ù«â¬uSòdqŽú¶f­fíOÊú%Ye|ZLßU_æ¢ä÷±îØ|Nï,UëÖ¸ò8»þ¶¿ZùðIEÉ:ýâˆÓ÷ÇYÉØåS{Jê6Y8§ŒïDQ_íá/=èx0u¼·”—¾?h˱•æ„kv¦á<­*É W„Ó³H5W!`gl +Ö P0NÂê‚uCÁZ@0f^íÜÊ5uæUŽSŸ5©¢0éÉ:³5©lQÒ†+WrÐP|晉bI›0Ëeëü³pZ"=Žu]åm›YVW†>hØ ²WhFrMÛ üKÆë½õ˜JØï ÄžôîÅô¡‚ý˜|?ù¾Øx]cšk@IVÇn‰ÔÅVx[±ÕW[›ê‚p¨š\ºÒØòÉ&Ó!¢UËqG·Ä¡cÙa¦]ÖN¶w&xíÄî©ÃY•͸bðT‘Å3>övÚÆnG‡ÞÆF΀ãöBŒœ€äÑX­\4ŠåsÑÔ:›Ám(Jqƒ'º-'ÕÄXlÄfö$œƒeÂ5ÎhlQûé¦iärGìr0—¨H'ã—7#˜Óæ(fŸ,Gͨ“¥j/ÐÌäÀ¦2¤Îñ?“èšF×<ºâÜ1™ŠŽÂ‰ÓäÑeCÞÆ«û« Kxô£Â¡±ÓÈŸÐ 'î6Gîèàlˆ.Ž—M=6ñF„#gyn¶Þ8ë$Jĺi½d«Ñ&Ì ÓS +Ù,)h3Ujf +:TCµÌ$² +餉«šRî~ÇiX4ÑT•’Q•³¸O(‡» aSŠŸÂ|÷šB_§Ihç F¥B•¥¬öM`§¡è¨BQHL+f<Äœ†yX”2ÅñÔlj¢s’’¬Cq2¸˜¶f*ò‘Äf]ñOCÒ‘™[%–p]±ù<Î\'vˆÎò©T°™ùk]³èšJäQÏß:¨Ÿ5¾;tP=>k|wà“:,k|ËІ҃.,¹Ñ« [låb >”ÐÝm;ìI1ǹ"Ï4KSu)ÏXªr䄦Gœãz‹_xè£òFX`µE1¥± áô`ÁÍ!Fã§¶üwèslj5yÝ)×@qì,çKÓµÕX +¢^îÆ$sm±“Fwð%ݘ箿×[›wöŠ›ÞŠ[V‹CÖIê¾F`â¼PiÜp{å'ë^…ÜP>™_Xò­Xá‡V»_ë%, }w„°_㛫"-I¬‚ÙÆFá:Ý@€yºA‚@L"± +€²ðâðCŒwß{õé|^‰Gm£J(jã¡×ÑФ ó1OÊÓò8¨ûAšá-ÞdSPBì ÉÞîÑþÀ„Àg4OÉJð)€È€Ã&Á‘  IH˜Ñ჎2”ft^Ê„°Ÿž,èT$!CO$žϘQt$Ç„Áç„眔„äÌ`’1²¤ä#OÀÙœÈÁ“ƒ™ðK:ÓDÓY&S%ùïsÁoÎ(󽣦Ã9ÃY§»çlx' +CŽêh-³æÐÅêäþ¬­æôŽO@/÷æ…ÆÎôÁqÏã!Ô1Ï.ˆ§:ãÙñTÇ`<;‡ØŽñÜyæwçñ*=àÐãè ÖšgÑQ¬K>vÕQ¡ÓRk4‚“qa!æ…RHa …˜¢`¾=}§ÙXgõá.Wy¬í²±Íë­ù&¢;pg‡¶ñX´µ«:ÂP£­7WÖµ +ìØ,µc-Ä«¡Ñ:®ƒ=**r©tFµwør›°vïqk¦¥9Ó?î¦w㜗؇«¶fIKr¤ír¯èäÿÆŸLøfšoJ>æáÿÞÏ‘'ÁçMhºÍ/Bl~%ŸéVJäÒIðþM£ã™ç„ð‘ú ÍŠLë>3ò¢ñ­JN=›tFãûühËp²œy:—ãÄ9ý7ÊÚE¾—‰$ ŸËÙâ™ä4$ u†#UNaSŒMŠêDˆÁ¤¨NaSŒê6ÅCLb@àÀ¾yÈV6¢Ä›ÈðbCâð“HüV,þÏ™˜…`ü43 ?9@³‘bòUGPþfX~bLí“­Èü‰Ú8¥åsZZ'µDVJI]Ä¥";ezZKbóbÝšC'ÑÕn6á€et¹„&QRÅyM6’t¦Ø’@`'PMèz8…ÀƒIT;À¾i¶$X¨yó3 WœÎ’&*O€âëªéÁA J‰$MTœŸ<Úû|NR“Ƹ{“•ÆJNò&¯¼œÂµ*ºsZ=º‚£Ó H3„G âÇ.°U kU<ˆµjR†öwŸÄ¶Í#¬”¬|6RzÚœõ³) ƒxLk³R¶hm ¦-Ã$RŒjÃ@¢1jgÝ =¤"øPzNÝÄŸUFp›â‡ø´•=Õœšb¨æCµ EÅ¡ñ$ΩÓÈt#©RÉncHT‚Ñ+#pŒ×Š–r@›“.#pç"¨ã”“¯†DÃã8— Ü]¸¦, KÉŽê(ª?Ç:§(ƒ?ϧ_˜ÊÙw6:GSÚßÏÇŽàù8%ƒÄïÈá8ŠP]x6ÎTNÆ ˆ.:•‰OÆ)€Ö@ÔsЮ2`ᜇâøGRYB=(LìqÜH[’Pû7²é„à³OÚ5!nïÚž§©¤ÝSû¦ÒîÏÜ ‹‰;¨NqXLÜ=µïa1i÷Zš?¾÷%PHjGißmY:ô£(LN‘à²mfœñ?4qàÉÞw’Úh.ê\S ^À ôBg'ÄÉ8OyŸòYŸ)ÆUç›i†NQÙQÛsçîœn΢Œ`ñ,.¤0€Å°ø¤0€Å°ø1?X|‹°Ð§ Ha …R؉½§÷;Õá÷~¤Û¡ÿPZ³cÕèn=:Mi¶К`Ö{¡¬÷ën1’uÀ3÷|n ·UG×}P!„ Ù ÔçêâìÓ(çY>gf“,Ú8öó°geóÃQðüĺˆ’P_×GIñg»ƒÝnTjló`TâŒÈ²8Ôç›&%³TA¦~Ùµ×Õe&P§3JWìÀ²¤I=ã´ž ÷©}Ïg8/ix±1@;µáýé6lðl8ÆÄ¨Ô­Óéè·«T RÙDP‚|SáÐ<Q`7NóˆWØ~¦ý_u*-1%>5 LxÔŠ`VÈqÐ+´%ÇJèp¸„%b ÇJÈÿËÏRÓ!•1ž¤åá,Ìã[ÇKX9ÇÞ‘jXÒ®0‘cÿ<¦eFNl:ïøV m –A¬ê­XåÅÞ%"æ4K³Ñh`ˆá¡ ÞB¦b®Zš-Ѩ11 fãh B6¨Î³-6O·Ðn1mp4ªuºÅæùDÓÀhÚÇ[$µB4‹ ‹ãü=£<ÓÌϲ®4°š­Y˜³6¸f ´¦}PP'²f °¦óTõ ªfÖ©Ùq&‡Ú÷PŽ¡4˜Fm?”c+f®q¾ÉK®Ó•ÊT —,Õ¥œÁÁ(–ÊRîgï«"¿XŠ|yd\(º$§"‘œ†ó¥†ó¥†ó¥†ó¥†ó¥>ÒùRý8Eé¨S¡b$ê1µµ×¹®½Î%³a¯öºa¯öºa¯ûH{]?ö˜¾ì¹ßëÊ®½®`–Ìr€Y0Ëf9À,˜å³`–Oßó7`ëRHa …fù;¸G;sU§–¥J´(Gê8XÙn0Uªjƒ©<„ªÁJɯڀQÙ Fí6$oxʼn…¸EÞ¬©£D”¾¬ÁsÑ«Ud3ÍE_iì¨6±™ÆU)›éÉX˜œ ¯Žc`»aˆòÈ”cj—È´IíbSŒªÁªÈW±o¸Á¬NàUwù€b¾–ò¶..·ÉíºøÞ´+1Ö&+Üd‰Ý)³„QºŽ+°Ë”Ú $XrxX’¤ÏœO0QyàYí‹ÖÁ[ÁïÍüþýìövu O>Àã…gr![·-Y9 +Á––dï¨ÈÞ]“Í{BtA>>¢`áü9ÌØ­ï]lœ‘]Ð[ó’óÚî·Ô<9q@äÞÙ\ÐóA±UâÕ$¡-TmU)ì¤1ÀŠJD˜–ö!Õ¤¥œÐûw¨E(Eña!—UðN´ü¦åŸp!­U“ÒjBþVúQ䳘?XJê'ÏNž%j˜‹4mh¿âÜIÞgH˜.h›BiF¾(ž¢B‰InÊI”8()—Ú=ö Žö!K¤ ù!ýûf‰{CKÖ¦Bs6î’ÓaW²HO´ e?Óñ\7³«ÁñœÃ¬«  “6Ì1MÕaûúzL`[“™MãÔ]‰Ë%FǤIY¡eªåËk'2kzi`ËDléKoÁÜ]µüz©o½2iÂVŸ²Õ»ùgŸäwô^¿½ò¸ž‚t~ß +½TæÏhô1¾J¹j‘ &l’ŸHH êÔs^¤šÏ5 Œ¯:„Îh Al®\ÂsÁ1ƈ¯œ,û’+ÖÒq ¼îÙ¡Å7: HÜüþà_ÕÎÇ‹à9ëhOøîÿÍ•tL +d‰Ÿ2y+ÚžÔÁƧ»Ôq¦§ŽŒ]VÈÜñà&õ*ƒxš¸æa8‡ô4ÙX Ú£¢htTzxTƒ÷‰Ó´ú“&]+ÃfÍÁRÓ°ºë(ô¤9dʧqu[xî‘Gñ(F THàBŒ‰ÚÄî´µµï);,Rõ}iµ© +_' +i£sÚŽÀA­Rm>S…~’ S d+3· +œ¦á*‹à9KDà ʎÀB˜ µ]ØmÙì¶m&Zþ¥žÆK–øz«3€=Õ©¯»ñž[r_«ó)sÑöáØœ¢ÿ-ÊhÍA¶²d½‹Ó„,‘q€j\•ÎÆ®#kâ“.€_gXKžU%¥Ðí*sŽ• †Xª¦°Z—Xæ(±4×S–ãè>jÑñuIrlg-=œ½¢tže‹7˜Ô˜Ý“|ZeVÔ\AaÆÆ–&NýøJ87(KÝãY˜²â­«,'k.ò˜o•‰µ¦ÐcàÑ$SÉ©Í>Pðò»ëõ7뻋õÛgÏ"kPüõÝ{üKÎùáìînu³þãèËÏîïVë_þñß7oV—_©Ö÷‘°•´çÐÓQUèjTÖãôDhð=5Ú;þ•¾þOøø_PøËÈŽ¾ýÇf£×TþóðO«Ê«¦Hj=‡¢Ö›’2ÿèóÍÚ°hÝñøÕþïÙ˜5õè{I¯‰*A&Ï1mûØTU.+£òIÛ1™-åÁ¡Õ?ŸÁ³¶c‚ÙQáÆ¸ÝP;óSëüͺ¬¦·‡Dœ–åf\áBôÏ>ï¨ËÞDå¹g5´"~1°® Çñ{â2ÿÿìóŽúü{\1F¹,<ï)jX®y™ ²>.ƒ… +Û²IÞÝ®¯ý?ñ{¨MeG;¥Ì¿'Ëv}þ=íñÀ÷è–²u»èHçcmò£û¦cvã·Ä-—·ÄEò–]´ÓQqåp¯±Éóq™§ÿìóŽúÚsCÏç6™›]´êç&~w»>ÿ¿*ãµSVãÒf»ç¶4c +Aòîv}í÷ÄkÇ¿g­ú÷Äë¤]_û=ñüø÷l)óï‰ç¢]_›Úüó1µÅ}j‹‹„ÚvQË¿M®¼ªiW6(ÂÜåy#¿À¿|–làÄ+‰3îÛÊ}9ã¶vî\{2CûrÆm«o_NâïË’7tÝÑæ"ûòø}yï6¿ïžµ/ïݶgÅÜNº“¥ n/¦Ûª¦U{܉,e{1ÛŽEÏv'ÆäU2ÛñzÜ—×¶ë;”§ïËk÷âéf;Oß—×vñ°½öu™Á}yí¶}}_9Åß—%o躣½÷Ý5º¤ÒZ“"Øyß¶]c×.˜+s @#Ä%Ï“’²Ô¨Çh*¦§6Kø©54›ð½"•­š9i 3,¬.}'hËwÍj2ìúÙèG²dš°%š%ɨ»*/(Õd¤LéªÁ’p8–¦jž ’?ú›ojœ9‡5㬤µ…/Ðò¸øy«ØŽA?+x ¢J¶‡J^¥ÕÔ%ôßÔ<¸Íý¾¸UMm¡»YÝn˶âPÉ«–9F±³3WÛëÝÒŠ-]ï¨WêϪ}ùÕèçÔÄÃÛ +¹Ÿˆüp†Z Uš1cÌÄ>œ.jVð9*<—ö[§mëÞ¦SQ­q!µà|c\Š´‡´V¬´Rx®ÒÖF÷Æ“j݃sõæ¤ô\¶´ƒé6†ÌÙè¹y`KqCÏòŠj\£±MÊÍ +HH¹)Nh¶©dKñïKÊM«RŽ‹Ñ3+‹¼EžåÌlr5¶¹6dï;•,¦0"åx\Ñ5µ&äé[rÓÚèÞxB­cpjR®EÊ]Ú®­@•· KʺlbñÚîFILÅ' £|\¹´éoE†ÓEe¢×^ Sr•öÅ•-„)™ÊJ!‚w}!¼ + gåe¸š)꜋kmµÜëò‚DXÄdTˆ-Ðy%…¨œKà +””¸Xˆí7ËUP«óEuíß$ðãdkc¸8Ë@¬ä{ùýØà¾ÎÖ %}ñò“›»ùÅùÝÅõúìæ×Ñ¡èËgc0¾ýáÅÝÍÅúíèËétr~~õãõÝÞûÕèŸáίáׯ¼9: îò$U7„~f±1ÄÛY,+#ÅYåÂ,jXþÐF,…ˆ# B猎f‘7 ©L˜Å\ +‹¼payéC!,úf«Ò;]„Y´µÔ*- y,5· Ì<áÜ9§žIÿƺ"_õï3“øŽ~ jŒt +”ÀE`…)å<6|kvIaÅ*´£È½ +Å%+fŒÁroQdRhMUŠ™™R¤Xkµ_Ò°¯f…в-„`_:à +_é5Üù +j <¯MîUXXÂpKã|­­18åLBåE&"kÁþÈßm&]-ƒ‹™ï¢™4¾ö»0“^Ž%6V¹ˆ¬eé5šI/š¢ 3i½tê +›‡™´²Ò«Šh&¿·¬ý¤Uu-…¡8“Ú‰Ðl +Ídî[kE{™tB +uÁBóæœx&­ßQ*lòï5“VL.” j£ Æ Ì†(ÅN´þä‚Z6DâGÏ3‡aÞyîm¹GPúÜ[èÌk/uå+æ(……Öž»wžl +#œØŽ+Døq­¾PXZß‚† ¸r¾µuV˽”!†ûU[_؃SÎ$T.}6ÞQ~ê™Ün÷:¢3þÓ‹¿üiyq Õ¨?„ÐÈ?üüíóï®_¯àã—o¨šúçõÅ9”ùÿýêr _ŸáÿÐÀ†Mnúÿõog—÷ôg=úÃ7ë»ôw¿¾§¿Á@ÝœýÚ~÷êOg÷··gëéåýlÃ×ÍßÏß]\¾¾YÑŒü!™É¸¡·w¯ç«¿]ÈÜíÓÌ/íÃ÷…›“58º HçæâÕýÝêoƒ?¤øç¤s7«ÛûË»=»õjçD}àžùÖ§}ºØwš^\ßßœ¯&—ïßõª[kù°íŽn­¤ïß¼¹]í9‹e Df×Ô›Ý\ái[ïÏÅ3xýë“äoØìVGþþ4;ò÷×ý‹÷«óû˳›çoß¡ð±vò®A¡Fô˜íKÜÏ(ž¿W„±AàûÒ÷³¢o]ù{»+¿íÛÓ»iùmçr}„°ùëåjϹ”Uÿìüúòú濼»¸Ûñè<©3GHœ·À྿ßq÷ œX¸•meñ÷÷×ëÕzßÉÒýZ›½èîåìz}{w¶/{Ùɦ­NÞß¼9;_½8?Û›­ýê`Òƒ¤£ÙõÕûëÛLñé(FŸ 7ìc—6âÅÚA%°_ÀôA ܹ…ŽûÅŽpÐðˆ :`÷¸ :`¯u§Aü¬tÀ~‰‰O\üöúæý»ëËë·{®ýAð9•às ¨ðúâò¬g¡nÛð¦xçý¾k¤óC+GÒôSË?{±·ùêÝzµ~Ù¯øÛÀßþöxþæzÕ¥>ð·~ÈÀßþö!øÛêæzVü)²·~ +•½-`†/V7ƒ7p¸Ãõ¢Kƒ÷{q¸~ ÊçpCNГô#¬ ˜êüŸÛów«›_]œ¿û ÿ·^Ý 6ía=í³žÊ^‘I×S¿jXO=]Oýb»CÎêO@i"¶õ$'i'—jcæ>Õ Ü7«×ýKföégà2qäŽtGìï¿vzÕ›ƒ¹ÙòòúzÏþ~$ñfÿ,Éo°/’"ùÕåÙù_¿qÑõû³ó‹»_ÿ˜ûE{ÇgM¦ÎöªO[8ö¾kª:xI=Pý #ô™âŽèù\}ÒÁbx·ïÎ^_ÿ2ëÊöæoÞÜß®>ö%ó ÊŽÞ÷#Jö¦:ú¡_‰b˜4âÞ¬.¡ X \¿2|FÍOûuöÛÅÕýþá.y¿²Ã„ÖŸÚH}ôðšùB¯FæÓ7+|r§A<Šyö‘ö6¹gzºÏž]ëß@ín´ÌC<Oú–>tiî‡,¹~u/iÿA²__N§û$…¿^ÑÈ û ²ßaÇ!_èÛaŸü7ìöT¶ÝÏî`·ÏBöýœŸ(Ûïk·†SìºzÖcGÁçÌzyèÊç„ÔÛ›5ôÒx6œb÷$dÚ#N±ë—2œb×»ŽzŠÝ°…>-´—}:ö Ø~* Ãú$ØÜplßfd8öcøô>©#G{Ï| e|*“ÓcäxÞ“:œ1œql×NyBFÏœ’':"cßUö´ô¸þúÚ]zÌÙŸÖù—×7ßžÁM{nöÍ_íÑ—0øƒ˜ÄŸ !·»ÿO‹Gô”óm²jÀÞ»Ô(“«ëS(éU—}bCb”'–¥·êæ'-k°¢>­”"ß÷ÛÆq$Ñõ¶_G¤yÖ/©öˆÜ"ÏúÅÂ9¹Èçì«Äá’ù©oÇØÉú)˜ã°ì9ÛŸºô­ÇýÚ†N&Ç<°_‘üG2ÁÞ2÷ƒ%pÚw1Âä§›³õí›—uty¿>ÿ±Çëú{ÜÝÙ«žm]æ8jå_1ô˜Q¿üIKþÄö§ØúLlãr”úÕ¯£Èm:[¯ÉM?aæöûk²?ƒd°¼¸é×Ìšìçn9a ÷§Fq½]IÇRö3l°œ (ÖS%{ÌšN—|4Û¦‰ž\^öjT†}Ú‘y·Ú?ÓÒ—ºÈ¾èÕ¨øÖ§Œâ—‹×ûgýé[—¤ñiövêžõfø·°o=Ù8d€Ï6‚Þí«š]¿ú¯ÕùÝôú~ýnš^÷ é–ô§%Cís¤Õ¿^_þvuv»º¹ß•=®oyû}ŠÕ“8Gö  ¶_nÉOÂt„Êðúâò¬g9šŽNÕÞ³)ÚÈÄxпzÜ3Wä~Gü~êÜ­_~Ô#¹[ÏÌÀÓúNoOûÔÀÀ¯úðplâ×^uæÄoÏp²šþþ ¬_vð±9C°õl}l×NlÝ/ æ‰b­?-ØeßXÞIB«³žÉn¡ÕÛúÕ©Gêvûþòì|uµZß}{ö¾Ç[Ôaü`G*­œ”ì¢èÛzÙ„Nì¿ôûEc›ªõ ¯Ð™~õå¶ë$_gïÎÖëÕå‹Õåê|£Î¤W=ÛìDËú¸Nîˆ(øÐÎÐŽN°' ‰Kž@â’Wý20»Ãö‹ÿuì°{ïJýš—Í]é œ+M^•ÑÆG|ìU¯ŸPÚ•¸ gë‹«Êtß\ìÞEvªÕê·~Y¨¸õ鼟½~}qwñ·}·’›©k½êVÓ…ýäîìfoØÇå/g¿îà ~Sá¤ýáôüÛë}‘¾_^^¬Wgý:N®éA‹ÏÏï¯îw;A#kéºg´õ e³Z½Ý[ÈúE‡ÒôÖ†qs}µ¯Û´W½á†·üZûny_ýšjxkù{¾£6ïÕ«ý³)|èõ”v&íéÝõ“ô9`³O ”L:Œ^ ÊÉ’a¼ê×d«öL:B1ì×¼ì©ø´`3çýZýl†;ò¬êUOŽ€ÍôŒÀØÌ›yÒ°™OóŒ‚ó~¹c܆úÆóN„›éû™ÛŸúEypF¦¥_ްO!ìœéÛz98Ó3;8Ó/…aÎ À™8ó¡Õ¥ÃvØ~YÝa{ÆËoíÙ¼œ8£àÌ̘ޫÉ9™‹è¼_ +í±,°gŒãدy9X'î`AûÓtÏ(aýJøT&£ožÛÏz2ú˜òäx(ËiÁ0‡e´=Kåw‚¬‘}ËNx\ÖȾMÐã³FýêÈ4òAûã7/ÿíÿýîr5½é›ÏüIçŒü¤¢<ãûGªômŠvD|rg•û}¿ã‘§µzúGjG@‡Ê>X‡yBÙ'ÍúV8Ö©ßW†w<ƒè£¬p,{8»¹¸{wµºëßÛ–½ÿ¯;ÖJ£µ÷ª;ØìVGvÀÿzŠdÂf·:²ÄÓ×±Ù—ôlFÌ[é€õ9Ö§·{x?Ñ ƒ“6uÒþpñ÷Õåíû‹ÕåËž‘Ï„zOûj“·&ýbøQôïÆ;?s4‘=º Möuÿ–Ààtþ<ÎCÅÁé|\§§sW·§óÇ㋃Ó9¨Áéü$¬ãý5$wj°OrŠ‘‘æÍ›ûÛÕsŒ^€ÆºÝ Ûuôé×Õååõ/_¿½Y­Ö_ѯ¾†Íñâíõ×»¸¾\Ý}}³zýõõÍÙz—quPú¥oPú¥o³[=Ó’ŽUú>Í„ó—"%<;ÇœA½êá ù=˜uðîl}÷|ÿøÚ"c­.á ¨}®_æ¨ù­•öÛÅÕýþaÀU¿ºZ +Ÿê£uá׬¦ôjd>}éíýÍ}_Ù°_Y'ÒtÙYsýê^Òþƒä”ïWç HÜ Æ¨‡wÎÏÜ%¦'6F‰eŠlRƒ1j0F ƨÁ5£Rñ`0F ƨÁu˜Œµ·vx¹»#]7,k£Á²¶eTnEéê[Èâg`]“‘_üý=ˆQû3zfbÛèEw/5Ùôk­nöâhKißæñSé£l‹ †÷ªƒ›†Å¤–O.ÿeû}íր߭ÚôªCC~¯ÒÜýpv±k«~ZŒ¡ÏinÏzéšòrl“øzÕ#òrôK6òrô®#‡æåød·Ð~-ù#÷Ð^ÊÇlŸýÕ†-ôIð¹!µUßfdHmõáSŸXj«~îÝCZ«'–ÖjßùèNá!­U:‹w~ºyúµ†¼ [úÓ_ÿÂ"Ð÷oÞÜ®ú *:ˆÌ®©7ÈnV¯û7;Ÿ>>ãõ¾g]öë(ï×']¾Þ÷¨Ëžuäïƒ +ô‘T žóžÏû0é¾»2µß:ê‹ówPçjÝËÄ˃×;5ÎõŠL5nPã5®/D×»Et„Wõª#G¨q=ëÈ Æ jÜiv†Ojr5î°}·Ú?dôKg_ôjL}ëS’þåâõþá‹¶g]’Ƨ=Úw³}¦‹~õfc»Ýw·í]OþÞîÉ`Ùbé—ƒò‰@~º¿yu¹ZïÊN3ämÚ+xòIäm² Ù‹†ìE {Ñ››ë«}¹ã~–sÓ[¦Œ½³ß|š¹‹^Ý®–7«ÿ}Û剹O©‹î®÷¦Á~Ƀ o³÷Ï, ÓÁÒ +7v¯Áyssv~wvùÝõEÏbQC‰ìâîüÝO—{#_××/è™^u-éFÚÃõýÕ÷0Û»ƒ=K¶·ÿßy¿Ô»#=-ç=óÖoøYØÓz+«´úÐa[x‚„wð™`O!wÿuÓ³ÉÁtJW½êÐÞ‰`cL±±)öîìîâ¶g¢Õ`ˆýýù÷ÚÅÝžýt‹>êý£œHµ@’ìU¿º•‹Ç‰äYÏeòÏU’íÑ ²ìg-ËÈÉz†^9 §o]: +Ó³¾<ŽÓ³~ `œà_V7¿\ܼZ]ޯ߾ܑ=iÐ?g=pð2}ø®RìWtù  îÜIÇýš±Aì+Í Šà Š`º4(‚ýëÇ ¢ö˽¯"øÅä½\¬_…‹ +,yùÝõúè@ôŒ‹§x®güõÝ{©ƒþôâ׫W×—08÷o~ûÇÿ}‡sûÛêâüÝj==ýåúæ—üßn•&ðûó/ê®lô=üêQF×Ͽ—ÿ þ Š~élôíè?þ3½Æ~TÏÊ"+FeYÙÑ}©Çµ3–K໦Õ8ËK¾×ùh¦äKeôèyó¥àÇ㚪<Ékð#>iË’¿<§/†«—;­«’šä»æ'ñ 6àyøÒ´®©‰[O¯Á³¸ŸÏÕô•Êdx¦ï@šûòÏk¤Ä×£·7g¯/V@Pî+üëØÚLg>ê±3ÆUþÿô­2n\”}æ¿À{k¯rã²(ìhz¥ÞÀû¦SõO09cè%>1ÎM©+ËÍ€V¦†/ãÿÅ?W´5ý|†ËÔ4EØÉ¢ªj.ÁA¨y¸¬Öºùî‡«Ž‡«æá¢ÇãšÊªh†«ˆ‡«àɅɤêåÎBçIMü=E“Ež´®©‰[Ïdgq?Ÿ«%L˼¡-ÔYð®F‹¿âªf ù¢¥5E3ü¥*å6ªj…îæM;ð “§nn³®l*à/Òkúâ{-_¸9R74ôgwî9PÈ?ýYý™Èòç×ʾüjôó¿«/^êÑxÂË ã‹—Ñ+¯¢¯¾9IC}ÎéÆÐ½Kþšt=.yÎåeüÕÅã'৆Ÿ =»”¯ñ$ƒã‡í<í>·Æ¥9Y_¯GÎå4Žò7ó7;úVÉ¢«2;®òBVJ]ó¼°Q15tœ×¶>9g™| ~/Ǧ®<›˜ˆé ÔQÔ\GÅ¡°jˆ¸Š‰¸âÉǘˆ¿Ó–YR“|÷äE­àÇÝØe.i«­røèФWiçgÈáºØZùòš23VM|-wvƒ¯=ƒ»ðÇŒžåå¸Î¼ØºQS꙲çe^Œ~¾ +Àн"/‹îGŠl\ãúŸžü–éÞoAÖ¤”ã[„÷&;"î‚D 8…ö­Ka®°kšÁ¬ä)¨‰ƒÂnT¹¼) O=ß6Ö&§ÁvP‘–ц®ØR õ3,ÕE]TcípaØJÃô]ÂÄàÎã»>À`d¦ Ý î7¦p´`¸y8öãKèÓõ¬«¡CY]˜èYœG¾vºçkiEVé£a‚¾x Û]"“}ñòËgÀ8ʬ¬]$AN§ ”úñú.d‚‡ã'GøîúîÇÕùõÍk˜’&úÀˆÿáÇÕÙå·gPýßáÖÑ—³É7’iüéÍõÍÿ‰ßRàäõõ«ÕËÉ7õKhð‹»_/W/›—Ë]ðK$ÌèÃH­åHãã÷ržgŲ12Í£ÍÇï^ÂÜ£/|Ûº{¼õèÓëëKèã7º dæ?¬nÞ€ÖÁ²è¿ž­_óñ ÒÅ?o©ÆŒr‡ÿiC}h0Ôžÿ€1Ø7ëúÅå; +sû§›‹×ÿ¶’1ŒÛâï^¬Ï^]®þtñšEï/^¢D7ýÂóíÝ ÇO¢ |ñÒlÞˆgÖÞÜ5·ìè=¿ü¯«xŽk¿SÑŸ…ö=Åøg£ïÎÎß ïÄøÓ‹ñú«ìye x|2EfmEò¼Ö9¼¶µÐ,¼ØS'yÞáýÞÕ42Àö “ƒP?õƒP¬Pïê#™Þ52}éË­}õ°DoO&ÑÛ‡$ú*’èSíƒ%ú¢ˆû”tü!y%â\W ëz‰æ%/·Iôð¾ÜŽ3äBݲv5.ó*oKôÄóÜn‘è¡#V»X¢ß÷-Ó½ßRÖv슼Ú%Ñ ÕÚ óüåyø>·Å_°þ²ª…:23Q6Ö¸ÞzltVÇ%z§7ÁÔf#–ïtn³Š%Ql¿vFƒtŒ —%½ 3c J”’›Ò “°©.+œ)ú[ ƒêL³Ûf÷ƒø諲pè'Žç#^:=襵İËɦ²¿Ö¹ÈF$¦ÀÖIƒ(Ö³qîò<Ü>À\fUT%nͰáëäÕñ fÍ â€çÙáâ{~ï‘u¹”ÕZº“»Úë °5sLàÓ•c*€õ£-Iz%ûb±Ð1¹FßpLeNW¥g½°ïU–e;kD=J²…fp;hBá>âD*,Ʀ(jgMw:øXÐ,Sy.…aÑëyÙºf1:ø“ìp ,ÜÐ+„fßTÓodYUÔ­1ÂâJ”v?šØTГÓ)ê ¤Y7mÓ‚¶í4 Å  Ñ–øo>‚½½!Š5åã7Ÿìƒo>‡n'ÿzqùf•l&´•ÌŸíÄUúÕíŒÏÚbá3éñ9ÈTe!| Ò¬6J |<—­«:üW^^’#TPè_P7¯:'ž Ò%’4n@ór)£54?]V5~:¼Šá™b·¥,ƒƒ?ž«¸òÇÐÓ¨‚0&ñ«€mó’ˆÊ¢ÆoŽ(ŠÁ¼üêŒôªäO<Ô¸@KRkp‡«|hh9Ô‚¬19e2ÖðL]û? “4I Èä2â}ám<Úðª w"” â +–Wál*0¢¡QU<àþe n2;‰[$“†•Ͻ7$³t8®! Nò6ë´çôM˚¨£{Î ç%Ø)1#²O›Ó•4 VPÉ*{ky‡²ºØ(ï_æ7X_È|œ·§øÞ +· ǵºŒG8ËÐaEû -ÖùÁÌÇ™ÍiE—ÄFóçÀ㘨\©k),5 ˆ+yž ›®q#æñA×”Ç]Á^Vj™OL2*V'`ÿ°š7r(Ìrÿ.Ó|Çò±.HD„Ý\k¦õÚ„{+TÜr™’…_Ès^C/MÞ‹ÅŒF +c±f«’¶Boe`°Ô A¥ºAyjªšL#Ð +*I a6`œ¤‚¦ºX8ÿ.g8ÌÜpV*nªÈ½È$##oÖìÁ«îØÞ £"ÄÒa朗ÝtFRšvrëGв´ +Å0Ú¦à)€y±VäÖB×…–7“¡Í£öï‡ePp Ý"A@¿-ß BYÑ*˜qWaÄÅ ìøÈ|`—Ž íbÍ®rX[F¦ F¾Ìåe¹X¢`\a%•Ü,âx~¸uAô z(DJɃC@à1ž³’a\hAŸ‹à kÈðÐÚRÜ fdœ#^Tz¡å|b0]y]Éx—H<µL­+y¼¡ÐTÔ$]¸VaÁóé+ðÅ À:í_VZ6¸Ã»X}Úd&Âßb,š=xƒÈKo¦©\‹\Ì{‰•@ÿ¸ X¬¶@âó€Ñ°~%K8EE.åí¾]ÑN§÷Âl5B¥MYòú¨¸iiSiÜ¥îã¸l“îÜ^‹B‹û”E¹»¾yÕ–äôï$Éé䪅£3Þä°4^Ëzu «H”â¿(`37ì é¶¡P\r°7æñ½^Ã(óÜ&UX\ÏT:y2ƒóíâjs¿Ë¡æ‡$ÆÚTÅ«·]ÜîÛs2-z]֢㊠ü'*FõšwhkEj Ú|é^k¹S +ÏEfž–Ü›wÕš·[0SI1š#Mé‚ÓÀÃŒ› †ÊËÊšïMæ ÏUÒ‰ø^×U«k·`Ö=bÏ™…Ð…Ä'FC7Î@z]2ë§çAû©)b^<ˆ ±ŠöZr Ê‹\»†š +/”|-ÊÞo–‹$FöË´XµK@\l€ƒf”ÔŠj|ÆPjiÑ–Y i£Œº¼2bºÝ,1°dqq°ùZ †ï9ÿ½± +ãdÕ•øÈ­ðêQR/JÞ5a>øõþ»_JyU•QqXJ›Aï­EI€ý¶?ó°Íi™1ïpq—x+«Æ•æÐ™hP÷"C¥Ôl®HŒÖ¿L´„œ8ç[å½Êc Ûî˜Óí>¡Ÿ} ͈آŽGM¾Q=E ýó¦$LNTo3ƒi÷qHDfbÒ€žjíÁ›0䯲²†q6eˆ>Ôƒ}³Š› J,¬È¼U¢«®ê¨‚`Z-؆©Y9fɧðÖƒF¬YYŠ +AÁ©X‰*°¬Å +¨ì`yÅVRDq,+54u¨T/[D… z‘…Á??kh·yLíÆUŽKµ +Ïa wŽî¬²`0I¹¥…éËeèwGøbÎÌò m–ÕI‘FÓ\а© ¡dÞRªË +ZèQòj_è5l2L§÷ ò¢Œj …Éë›Ò¨¡Ò¸?}?÷¶ì‡”`èyFëý⟲šsÿvu9z6š^žÝ'êŽöˆ½¿Aº@ŸM.YƒœâªUlÙ´Á«ƒ¶E(ly¥–ˆœ½Œ%³pïéˆjˆ åml& ÅèýÊÅ›*yÒ +ª®ÖÑwÏC£¢Ûšæ7vtõ|ôbž%7hŒN"˜¡)×áJè´ÍGE º›u¡À–24K˜±Äþg¥ì uÍÆrlç%y¶±Œ±g‹~wdF4ˆ] de0ä–¨¸+p–æíd΄-ª§M)É Ü"Ó +lÃi!q*m„h›bƒ¤zÕYY ¬&䃿y’«ê<¹Åçd*ŠÊâw6ÅQûš*£ž¤ýíV‡áêÒÖ"íÒ9cnaË-7í°Qj-Øðgþ‹lµ5¼¨Š¼v™²ƒ …a94¤[5(ªÊÕBŠ@‰µCèmi@©©zëÒÛ r ‘)}Õ<ŒÀÏ«¬N ý8ÎT\Ì&4›â*qÜr“Ž#}÷ò{íÈ Ô܆ÄPTžp¤Â¦0yyTÜ4´©5ô§ép„àÂÓAÇ’÷ é«°Ò(P+-haEH˜Q‰a‹“0ûzç|I¸Ÿªc„‚ üž4°"Ék¾}¿ÿág¹D!aS0>Øå"OSÕQƒèD¢@òÛ¨DU¡{L%Q¹H°FÌÁÚz„Q¡bî¢ÈÄŽƒ qÚZH☩¿ö¦&¡‚FN*2-ŽÈ](%ð̆ÓIZÍ +ÀÀѯÄkŽ=vË¡2Ë9œŸøüÇLû2­œßj”ò$b”‡»FY¤uy>úˆ`@³©€ŽÇfdH;Ä0Q·p(‘LÓ± ®%c/çxU1‡„¯UÁ4Ëí²,H„ +E´ qRhÿ†D¼Sam É ™Àæ9âô‚.ª‚udžF˜É ÷<"¾ƒø¤»€`$B®Áú3ßé<ˆœ º‰2"ñÏ1áý‰ŽМU~QÓEc]L‹¬ +- ä¹ ©n‚š‡¹ ˜s½sÎ{àm/ÓSQ¢)\Þ’‚D”ýoVÆ>ŠÆ_‹‘C˜%SžNÙŽ¢…e&ÛhÌÇs*Ui$QeÞ~xç@¶¢™÷å¼Bí+¼¬1¯ [rpäªÌ³[g^R¨uÄŠ¹B‰ ’›#ºÂ"Ïiàd5 9‰ÀãƒÜÚà´ˆÔÁ +¢u‰º7âG‘ˆ4-c •Ä‘rmD9¡(‘Uv›¤h,í¦>R¨“ŒLà@QJ§RÂôˆÙ™Ücèp…'i úGZ›,1cÖ ¾Zâ‘À* ×Ë`ÕK8¥\/ +‚Bâúe0ñ`VIc–„O.VPgô†p‹ê¨21ìA&($æã!þ”>J…X6Ø&PçØG¬%s‘¬,‰Y€j™åGþ™.ÄÎß5*æ6ˆÊ_‹éÌ[x .‰&¨Tˆ'A2|DãÃF²‚¶°#v‹–‰~€åâf­;EšJ 2ÎÝÅÇŽ™æÎ@´CÂÆ±´!ô*³n†C½gÐø/±ˆ|eû]LO‘¸É€ÝV–eó’ g/Ç•æÿ  (°æÎÑÐùešòJ1¯?Žd !ŸH"O8œñ­?âX¿&×1œªÒyÁLA*ëÄW¥QŽ þÔÄeŒˆôÞ~_-ìèüdr‰S±g-\ò "íA@ÒRW>Âëpsˆï À¾ÃþƒJ‘ú‰ôC</€£ØóTU¥Bõe…°!EWD0»Às7,ÃKAó ß¼‚âÈë€ æ˜¯˜d„Øw \DáGp¡óÑ–´¨¡„¯+I:°êË2± ½g¾X«cIЀgJê; <:¸dëž_…Á_‹ÿ˜A& ÜóUžî€U…ù3Ú‹EšEßß°ä’b“˜¿™o‰ÎgVÙúèг‘Ñ'+膽pç<Ä—ÐÝì‡PñÿzÚc9¡¿Šú𼿉þÀ7ük"‰ÞGŽ?ˆ[YÎì ÐWç«ûhÌÜy©ä•3“_÷¼ p+ +®Xࢱ7S,@&I*Ž!ìQ=‰ãhq$®é,Ý.$ìL¦’‡½ª6ß§­ŒÏîÛh±Ž¯áXF*ÍH †g…L'¤SµÕµÖdët~ý°—Säõqáâ ƒ¨Ñ_kjˆ8„§€+Šƒ%9 ôÑF$äÞ‡ø¡-’ElC +vž2‹ ´q,6Ea:7DZ¤Ëœl:J銦‘ûP¤¸0M•Ñ ŽÓ€°¹—–œ(P¨£ÝMÍ‹H9bé+Íb0È(fÐ:ÄÜ›¾ŒºÎòýI¹%Ä®X‚kázÓ‹Á@a€k/ÎÁ¢Ë° È l‰/¶„óP•œ$åO}MeËÃ.aäºCÖTsy´X„4uUÕ¬¡‘ÄÀöB0Çà½c•ð cƒ—Õ—F~›£i4‹°$pÄ`ŒK09GÂ×礄h•Ö°:¶Òñ­Û4­¾¨Biަ²lµŽõ/ÍGOÂ,E]’qF-*Õ©:ñ—gÿ—D$æ€ ¶$SèLÂ{ì,d"°eÉñ´V±šþVcHøê˜SxûèЩ¯t<Õ®ká0Q$ ©ØÉ†S9’Ô^à°Ï5⌺ÆaÛŒ*È¥ÖIÐ(‰E¨áErÉKMÀy‰‹¬‰s– Q!CG!x¯š2Ë€°“ô¦Òð7a†„9R 9P •$§m€Æs+ÐŽ­Bk¶2kªVo+6Ûfð¨mÐ8%[3Éœ¦FblHzdjÎFÇ'£Ð6MͶ‘Ü’Y½ÑýïØ!Î=«²Ç‰Añ'†a²Ï йiÇV¡Uf™5U«7ê–ì€Á,×XžúØŠ#år¸lv‹1 5ÒÔYZ˜-µƒ}7ì¥gfGVƒu‚™â²Y¸,Þ”qÓ™ÒÂL©M³¸œá™ÎÙ +˜‡ñ²2+ŽâÔÂ@Ž,+6€r;Xès 6 0ÂHæ\+’‘.£ÓQlÑ&ü»§‘¬˜  ™lBרu›i¡ (žÞÐ: +!é;q,ðsñO5Ù eZŽó-½6»íl†2†îA}'›á8Ù? +‰²„9ARàIÆ:®FZE‰†v#ÉÂÍùÕoä9ÀÉÉÌ”‹“‰I’­˜€I¦àY˜³­Ðv¶[e<¹a¶w‰ÝsT'%˜Ç7YŽºàŽAÉÆêÕVho•Ùæivi_ÑüêmÙ;¬g`Æ1²bB¾ŠI¾8y±£Ð67« ¡„æº6»Ä9çA#Ù@ƒ#5‰ë³U²šÌzµZ˜1Ëló4»´¯h~õéÅ@yÿ+|3êÍ•Zs_¸ÊyˆPv¾~ !=ƒÚ~!öây~ù´‹…0\í(Ôfd#É”¨ÝF¥Þ‡Çⲡ?E3;)˜µÀò¬³ô£Žv_õäÚÜ ¸wò*Üç‚7¤õz±ïƒñ˜L‹‡<ê’dWm±„Ž‘o6†ûe{k|ÀÔ× Lè$Ui5tž# +H…ë3ðÑ€{c0¡«nÛïEJxÆ_‘ìN픿ÒËì¼LP'‡~!êÐtDöÔEC!¤ØÄÏ#õìǾ‡D*FrýÂÎY»E%«rî½ÿ19z¹DCc÷ûØÎÁ×£NŪn­oI?…å7!ßõ)<ö˜5KëÅ^Ãû îJÔaŒ=iGm$,Í'²Ÿöû ReCŸûÉ*ÿØÇíÞg`ýÛŸ›sXY…ïffH¨JÞŸ¥¦Q’¹ŒÜ3àLT䯅&$°ZfV³„IRö¾˜ÂÆF3_G¿\úʘe²‘Hò2SsæIjx«c[¡ife%¶iZ}Ñ0 s4óYcÇú—žA:ÉfN9–™´syììO™Â "`áá- 3j›µRd €DH º´Z‹´ô­Ö²HØÍÌúc§¾flU§·?3Ç’*( »A¶[ bªˆ Ï³D| +[à©Zx(ì®ä rг²"ÑGµÓbÒDü>­2ê²i•È$îÍìé½T@5eîG ^4wé×*c£ÛJÌ9Z=­ØŒüÍÃÔ)ikf©éA`J7\F´*IÎBsŽª¹¼?hï‹”mf6*3BK,“®9ɽٱUhaÈ,±¦iõEÖâ\ÿ,£ÞeYµ­€„kÛÌ«l©äÃR 8aÇL VYa¶Ìx ;&¤³ãž¦gfk~`–(Û¾p~° fö¿¶3(`&«¬0SfÇŸÉ ZZ …é™Ùš +˰±òƒ©qPÁΠËÔãK&ǽd&Æ$J¤œãÚD›ùAªýXñBuðˆ)“?d/}ý}ðûžÑýûÅ•Ie4ù«Á‘dÄxEÅÌ>Înê(¿D¼Æ^Ȥù×9ó1vmQ¸1A| q“àé 9PyÈ‚Ì<«ð¢F‹!§„@=0ð (}ÉÆ…ƒ ÞÔ,€7tÌqyAiÂÔ'HØ"hÚLß o&‡sÑ<&,É…9Ž&0?fó-ˆE¶&8Pk®âBM1æÂ‘ž8QLÍÄYGuô‹Yºc[³d÷æÜeeY²ân2W`5ùÁÏdÃ3k²ä’!ñv$°CÔ„ þvú¯äò£™r± +óA†¤ÑEg‡ ‘ìÄà i +vö†—è࢞±`†8ûQè1þ9‚LM4œhîy úŽ (ñš¨!¨Pa›BŒæê),èÀÙ©ª³ÇŽíS€xY}Çç²—”4œu›UQ³C–'a>l»ð$Aœ½žªÏôG=µ‰Lgù$͹9×°¨ä-]c +Äwz~,\>3+âîœ;)›_¥9– ÄI|r¤\œëw¤ÏyœÍ¯kÖKB±yI`QG#epf’0'ht82Q¶D¢0u…m#™Ýã´väšò3Á“.Ø+Ò*Õ| +uö¼ 8¢Só+\³] ™oU· L‹ñšÑ^ÎQ™m[“ÙÖp6@|»)r4p¾’R…=Žî¬¬ÂKëúl×àHkØ&‚ô©™mÖ$…#¢¤æ륮@/5[©Ä;PÐUru¢‚ƒ¸¢áàýá™qM¿Š&q‰r n +œÄtxÌ›\KÀÍ ?¯{k:N[¶#¬ä,n ð&@T5•ª}õ ©w +AX*Ëš¤CŠ[{LÇ2ƒ08WmЦýºkܪ WoP· ‚oÅ„,Ü,°cnc°s[ƒìÆoÚf Êìö`Üjvƒò[„|X°I(ϘÛ&¤|ÁF!lÆ•æ6‹Ó2»]èf7Ì$¬¸”ùöÍYY#òÝ.>,fOk-£?wG0ý1' gkDŒà +¡=Z¬á;?8XÄ?¤F’IP£IT°ˆH^ +`Tfjg$‹"Û°ÔÜ¥’”Àë,}<Ç6’Ü¢ÎG"²”òOÞï*Í|²]áC0°DzÅσ‰}¢Y5.ŒóñaYNgñ +Í…íà‚à"š! +ÌV%³åÙ‹ëPÌ ì9^‘3Ë4btÄNX¸L%ÏüÕö»ÈÝÍ®4Ǧô?@>PúÉ“" Ë>|j™è2‡\òáÐË΂ý´ÉäÃ7 y ¬¡gˆ[ºÀ¨Ã8õ>Ù…Ðbr]T=æ!»&;‘àTaO“`2F OërTÑUÞ䫼õÄ3yµ°lˆ•ØÞÀta±U•£2æÖaYpCn‰8w"K Ç ©VJEÈÕ†B&‚“–$_Ô ÷  ²À!¤½ÁɈ$‘dõ—’w{si‚HbÄ!`M!†>AeOEBx¹NbÃÐT¨5¼ ©24ÐId¢­,ͬ’£˜(ö¢FÞt÷jž=K@’ìÂfuN43Ÿˆôí2e°Ä/f(<{Ï‘¼a3«ÀÆ—TöL*$‚‘è»:G2, 噺\%âÃ:›“›í#OZãSXX)¡RY’èKXH²b™iT–Á +' H3•˜ xày–ëq0jEE‰6ÇŒIV­ç”yUbñjyä mê$‰ 𔢳.4’Ø ^QØP?Mø¥ãl4g¢HM±óØÕmØU­ô¢VUÈ*F–Îó"MIçdš U@Š%/ˆ¨S¨Â‡ß¡!‚2/‘àgd¸ÁÚ*K1޽«ÑbQQ)uò:¶UÀ=‡D¼£Ñž¡¹ÿEŽœ +é5VLâ| Xe–wÕö¾‰È$'v\Ï“Ez1µ¼å=d.ò‚þ5ÞCËŒÀ2èÐEÈù „.õRRdþW2TÞ,Wª‹Œº»õù€Y—&‚¡Žd2¡JüèzÁ,Üö$ù xC¢oøæF¡~·ºŽSoô¥lIg­Ô!‹`<X’ÛÒê“æº¤£â>d•Lª`ŸáRí[ÆÚ7¸UK‚é4ÂëÀVÄæA¢Px¢“ÍÜÄßçÜB篠‹³yð8â/l£ ÔŠ[ûø8©÷éy8U³;)NgàN/q0n°vÊ"+8o9’Ð÷Gý 1?6+$z’øù* 7*£úP™.’ì‡Ð§H(Bv9G•ç(‚Veˆ ´,;û$¿Ù¨„"ì3+X%æÜqŸ$§‰¡qÀ#ý†å†çxì@Cã:e]_J;øÁUœ{,„_Ú´£G"‡¢ +9œnFˆı¸ äÈÐÉ &õa€cÂ+KI¶1KWÄQÚIYÄ!s޶ 3¡6C`2yJÚNe¤µLÒ+Ù‰mæÃš£ÉÈt‡ËÒsó—éE.·Ó Kh.Ü© ‘Y¡E‘¤…½o&ù ³©¼Ÿ>Q7²êˆŒsäX¶†el›”h›!½°ãÕ¼lÍÚzŽÍ™^s²tÙb$mÙâ'¤†Ù±­M‚0†ñüü'=qœ^zìH$ÁqQÄÊèÒÓ2@›nN¼Þ4ÍyÈ R_XOšIϳºËÔ;ºÄÏ5 +Žlè :Þ»ZÄlÐQiL«Ü¤BŶÓtHŸÙµÓ!y”~n¯ +‚çg§IòÁÆui²nfè“>ì¤OÅdv +%ë±<ÌIƒeå6ºù°„|¬Š’ðV¥8X•œMV¥šuít¶¹£ÄMz`œk™Çåìå“lù€Íñ!ò:¨Mr”ù>³³TVíÇ:ˆˆ"š» zßà ò‹ø!]`¡“ú_¡ˆ3l™œÓv¶L-“ðõ¥@ºa¿ ‰_æ +=@„øZy Ã}¾“=s8 ì­a_d'Ÿ~{€Ô{§éÒ¬ä}³,YÀÁ€íµóª3íÞ&\Ú%›/(3ÌUqðUZòMGþ_J[& ?OûE§½ª->íÕe§½ºè´WöŒ®çN{Jó§½°è´75ûioê³§½´ä´_U¾ð´—øå”ë8í)õÎö 5³§=¥dÇi/ë N{K1™9íe}ñi¯joöäayÛÉAŸ•§O¬ÓB1ᢂ3ØpÁž¢EXÃïcª4k‰ ÒÜvfº‹@^²£m@¥²43ön­Uˆç@ã.ðHutas~Ãu²ëTÿஊWèÿ`µ+¤e $Ó«SÕfËã(¯ÍF! +Tð 4o´–! „¢Í>:vêkÆÆIñÀ[ÊbN,Ù-L“–…‰¾9A­ô…U‘W%ó7~"LRXŒ?!`ÓóO ±øF𻑣Oò*é6ªÁS؉";¦NúäÌ¥9Áñ†écô…ŸG Žbönf LØ IA¶‘xrÛ9c`z×8©Œ&+Þáú3¯:0§óŸY€Ã¢*ÿ +„ ?ŸNýâ¨ÝŸ I‡B¤«ök'Cø¢‘/Åîý{Z}A¯‘àeWj4·\Ç•~¥iŒ\§£º1 +¬þæ"Ó•n·6ɰծњe´Äˆëô·J©3‚«8 Gæ*£Í´æ_ÜB^Üb¦r®‹»¨ÔZïnrnI!—hUÆ]¼ÝB]Ñ=îb®ï˜"ËÓ>"‰–£óT¥ß7F¨îW¤d³ r±a´»Ãvlt]G#£=6"W˜ Q¥_Cß“––€ÑL®kÃúÍ£¿d&ŽëÌYŸ[µ²¯×N‹xXþ‡4 Ç–ÉŒ}ÿ¨ëåñZCH™ÉÈüÙAˆxh²RžãÈtÝ?àö­†ÑÿØÐ¶ÿý¨Us`tÎ|tàï¹m}4/²÷ÑèÐp1QƒÔ@•#.ö?|d¹0qò¦Œñ—M~;BóžçGËã’¤÷•b6¸¢¶°T`¸` ‰¸ %é@J'_XŽñZä¨?ø½ aƒ†ßFNÐÑùI"Aä7ƒ}¤©cl®ÝE@…úéV¥Ýw‘ +¤”˜&"´Êö¢F¥I¥ÖYÝ(U·kV ‚ËÒd4è®ÓFclLFV?ùJ>†+í!ZªbÐùýÉtô›1×Zm£:í7w\´ÄP¶Ñ0:¨ÓH¹=éBU÷Ý=ÑQѤV¥c‰jThfç_‘!ùn76žXG"£áŠºÖ\~Ûð yùúã6¸-›.™öxØ­üA~BS³Ž5Û^‹ºðz]Ñ5ÇÊh²+éA¿>mO–àpECìjü¯54·ýËòêgIÞïëèÍéØL‹±‘ýÍèŸÖëK ¹>©®Ž€¯noAèбVdµ_:÷µHö_Fm +sÀpÛEÜÄ¥(â'Gùnåca˜KŠðÉP¾7C±Eé.â- +žPX‚‡¼m<ÄÅ( rÙ}r–p铳|r–OÎòÉY¾;g‘?9Ë'gùgsž¸#k’ Ùð ¡/'a‡v^œÏ-òÉb>Æb”OóÉb>YÌ'‹ùq,Fýd1Ÿ,æ“Å|²˜Çb´OóÉb>YÌ'‹ùQ,çYúûYÌWôëó¥w€Ãüdÿ¸ã÷ Ä¿Ÿ¥.â£Ì\ø}Øè¯LDÕ2„¿ýø)ÙÏ#àóø<þŠ#à)P>¹ÿ?†ûû¿?÷ÿdäÿLkGù} +þ£ŒîSÏ÷6ÿ)üDÿ¡BØ5A…ôŸ\Xâ$?K+k}ÁÂF©Ûº*ð2*]f„Ç<N ä/°]>…Ãwš\áÞGó’ÖqQåqš9xø†×Ôdsý•)ê×^ÆGΑŸÂ+øzŽüJ2æ/@öŸçÁjcôAð®Ê'ÓÿÇÚ~ + ñ¯Ï¿± «~ÿ[‘5•Wq¤*õÑšŠÓ™‡9Me(á™[¯H*§ü‚jÁÏcjø.\QqæAEãÈ-I=(H÷òm<^&ù®Úîsì‚Ô9èv§8¹ÿ`® óŒl­cô]•êugôm,b%È’^ÈåršŽ—m¡ïÁ)‡ZÕä'‘F&òµëýÜù+w¾®ÿ¦Éÿ éBæ‘,s‚ª­ŒùÀˆÓ`pa ’Žc`›ãgbŒ¿U¢ ¦6Q—àÁJSßR±kΧ@ñ-lå§°Týg°•ïã<ýÉQþŽøuxnL‡ÇâT]âˆï4§éÂ'‡ùFóÇþ3kÿ¼bƒx3Ùý¯ÅøÙ4÷Sø)*~}¦ð)vüĬä-,vè<<¶ŒÓª <‘:$AúŒØúz3Uþpµ£ö´ +]×½_Å)‹ï?!Ïù´@þ[ ÉRUúãÆ`ÔûKºÙG۽ߒn.bšÓ\ÄcºDbgï ~3.ŸŠ“±cá¨I}ÐkÁà€¼Ï´ö¸VéBucTC\ÌÑ*´û$—?ïh±ÿ”«ÔÐ#à±cã)c4Gi¤Óôÿýi/=¶iO3£ïÏŒîèì±×JÁ .m3Pûâ÷Ùâ%:ú°Ý/Ú3«®Q›\/*¼ùϹ¸“=EÔÑ4•QÕè®Jý Ié'†ë¨ÒŸÿù—Tò¼¤ú~0"ò¤ønÍAˆ|ƒOKåØb£Rw™bì‡nðð6zéO†t[ÑÍÖm÷ðöcƒÆxòέóÝå9$ H6†ìך&ʪD6TXVIÅî<üõ·xÜÿ‚ž2KçþqþsÞˆw‡ ÀM /£cð|SXPå¿(DŽ0·ÜôË—?\Ç•qç¸ÿ•Ñ®µ¬Së]ì7EŽóUÌÿ{Ã'KÿëÈý/$aÊpÔÕUÅÿc í2Dï}x¹¨Ýï#‰‹<©ó©‘ÿ$ÇÕ?I#?€gƒ\ùîà÷9𠆥V¥>ø}) #åwŸ”‡6'`ÊxjµÛÇK᪩V †•Z`‰ÜJ¹Ñ7Gƒ6k]¬ ›ƒV»ÓÑ?L‘- +;qUM£ßøó¿F½vÓÕ2F¿ FM£5 äÏÆ¡þZtõ[a³û‡ÔÃàûò+Ú_£m÷¯¾þRD7űd¿IèÁ¤èL‡i3áj—•Q»}qhÌŒÂ:¯‹äê?™LÔCžUA†?$ð[ám.€»9ÿÁ;çã~®ÈE¿]Ô¥7,–, +ˆîc,ŽFò§Õ—s4ÆŽk¶Ç·±¿ð…æèÇéP˜_™#eŒ!Ú…ãÓ¾ý+ùÂôçF·;©›Úš.BÊôW¨S¿"§¾ §¶KDŸìø“ƒ“ KúeÇÿ¾·œD=@drˆ¢¬k + aUà4所­i"/|_É¥ý/?°ÿ~d/Ä0°1ÐOŸ“¯Ñ"Ëm£ñSªŠÿPcÖOÉš¿›Ýæ»Þ¢€ÁËE,^_i ëVšHÇ’÷KÀat˜Pq ÐXÀ•M¢^uÛ¾Â4(KÐÛÒ$‘‚£_oè˜ÂLoÅa¥Í +°´Sjöß«,v +: +g j!û‚[ƒÑ—Ï;´Ž;ÄÏúÙõç,µ{îÉ9—ìœ"2Ș +tEªP5]–4k=+<]gÇS’(".1±Í¿Wžíדækåo>y^¬t ´ð´‹Õ÷LÔW¬ŒÇƨ‡èÞè?ðZ¯¿¬Í–¯kóÀ€Ì?ÿòí0©à-û{‘ í.¬KŠ,â7ÀE•E“" îy>å:Lh÷œ.ê: ”ÔEI É®pmV7ot«´²"“Ú–LaVýùß}ZKV9]Rq—¼(É‚d®ŽÕNÿQa•‘ˆ©«88“ã9&ºq¶º©neJëŠèÿÀŸAÞ87'aU>®4‘üS¡õyUP $^×0 e™üÁ)ІÃEUY!ŒÇÊ8A|Ep—1^]ù˜¨»R1I¶— N4'ÇI‚ŠS" ~†ò8ÐþQEý êOTÌþTJÇý!fH±AL‘hտġ¢| iߎŽd^æñ|tž—tt„ˆ§¶À w3âÑ¿¨'ÎìIT%Y…á5^WH¶¾°ÌgðÀ´Ø~„!²žd˜L1“uF_ª +d"š¬Ê’@{‚D˜æàÿ`Nn¬' $b0‰´'ÔGæPRÚ'’¦ÒƒÃÙ¡(ÐÖ,¨œÈ“ÖŠŽAÀ‘t0#:¤@¢Ö0JKÓaB +ëQ%Y4 DÆdF‚ƒžZ¤'C[ãQGªÄö€¨h™»ˆ¡¢é¼ H˜¬t‘!³èe4}YÓhwxZ@\a×TQã0á UH¸3Ú\[+À¹qä*ãaØ{ãZ²Ì))¢.ã6Š*£_t_S´™‹¤†sÜ b"lJ¢ ÃÖ#3›£27!v/«¬#NSûh? ÎHY:‹±©f‰ÁT‚º”iG!M˜’ ( R2'À‹*hÛH²iY€Wo¬aup- Ûç‹0M£=èèOMÄû ¡ŠRyʞ¼ŽÀ«ZÈ£sQPO^”Ħ¢+<'`ž)§4‘´/V%£r‘tL©9p4 $Qñ"~¤Š$f±74'Â(s°ã`R²¹Sîq²ÌÉ´‹‹0¾$S+1Ý)*c˜¼ÄvŠˆF"¹¶Ãˆe¼Ñ8´H‚0´9(‹4Ùé iòù,KgýðÚ° +ái8ƒâë¢Jø/p ØJ˜!ÙAE¦É‚À`¥[¼Nçu‰@ÁL¥¼Îäã„Y¢±}ò6.b˜ `ßh +a0Š*‘N4Ìz)Æá|¡Å;q$Šc& ”¨vb“ˆk,½̓îG´…,€ê°rNM ¤øXA Eó Ä0ðöD2'Á3!Ï6G8+éCSÄ •l!bÍ¢²ìŸÿ]5FÍJ¿éú2e¾|«lZ+ÚѾfÑcÐ è²ÝìƒtÿF÷óõ­)_a™þh¥…“9Œ+.°ÞUºoôb¯ ]ùÏ+S¤¥ÿþçmÌ›ºüïÎÖσk8Û:á]þü•þù_},Åæ{r,4OE"‡ªÊó&]DHÜ€ŽÐÌákv–ôyöÊ]0 6ó¨V‹&9ã$Q䟑8ÂÄè…´`þGE-8óeà,2cÑ +š€„ +!1EÊ’ŒÈÓ?…JĽéœfÿ ½ªx[´¬š, X +žDhJH Äs‚„{›ÿÙ\ø8c&h6<ææˆÙc‚X«(ãÍÈ8!›Ôì´[3>¬` ÙVUd’͘S1ßCZÁ8ÄTˆDoþç8AdÑq(!%4‚ ªàžÌ/‹ä€3yÏüA;TÉ)‡•ñ”O‘H%ªN´/÷ìÂñÌô?Jœ„o`¿è_&ðˆCâ³A“uË:‰è)Îæ2û;Æ9¬gý +Lùüä¤.Ré8rì I“ê:ååÎÿÏT),]H€Sô/ÛZWF¢jš£éphm¯ÞÁ–)š±`‰iH­)Èp +Ò +=lUv’ ¤GF'DÂç®jéïžÀJš¼Hq|Ÿƒ­V#ZsP”“³,¸½ÄòB*v!ŒL@À4ªšç1–ÑvÖH.ID­Ô¡’’Ò•]yå5Ý".žtVL™¦!f²lBvcÑÚɘ•ðfX*´Ç‡E̼Tx;Øj¹wíêhØ÷x¿ÍYÀðDß4‚-X0Ï‘O¥?zÕAºùŸðÆh‚&²ßî6`!GhB0¯)Z,=WAsiCóR –3m|ùóß­î´ßÁ®û}WÈuë$ãÕu¦ý îvE•n»ßy£˜%5n§£?ÿ»ÖYòU¸Œ~ÿóß#<Õ£iÓè¢2b·4Vº“F÷ÏCLÂâbÁ*/WªŽ¶O¥‰1ê›? ô¾ì°_ŽCJš™AmÚ3ú“LeRYó>EØo×þe³0ÃïëãÂÉ nà~OÖµåøW¯ÛGBð\A‚íØû´øûo•î”V`¡öÏ“?†ôk„Ð÷ü zƤRGÿö ð_7ßÀû¡Ú5J„–þý“øÛçðWB!jÕ©µÚÝ:Ž™Þ^@¶¶Š• ¼Š¤Ý1©% œkÙWàz¶Ä_ŒØw/É9chóö4ý¾þø©6O½è’ʶ9 -ØæÑ?ìüö¾å!:ÿ¬‹ƒ5l¿‡¿’ +ºƒZǨ¿ §þ oü| b³_°+#´ OðÞZ[µÝ¯£ïüÏ·>û*~$|€üÌ›å@r®}Üøýo;ÇÝví?âøÃ ) ¦£š‘÷šŸrMÎ)#½¨Ùz[øQE>Ì#-–ùhü$ôÎf?ŠßÛupZcY¼ ðHuÕ…Ÿl]töóËúãÍ%…TIµ_üÉ–ôÇBåÍåÈrXÕŸ ?ÿZ´˜ê`‚äÂјœŽÚH?|›ú˜;ÕO²ªùü$§-:œ~ñÃöû8ßiò6 „ƒ“<ï*ŽŒ±1úÍp•M\Ùz{R©¶»í ÝÃ4®lš=Œ6º +•~sZi®â`8ÒÞQÍ6¬AºÒÿ­2.Ñ ZÞ'E–EÙ¬¥»*£IuPÕ]µAw0rñ.H‚ÕgݪI² Úòª‚kÄdç7kÚ&ðfÝêÜ>_ÍI·ð'"VRk áÚu×øýð1ÂYØÔ]ÃÊСnzÓ®mâ}­”aPét:N'®óÊxbŒÚ_pE×¹1t§V^v´96Æ­7Zp²b$çj£Z•‰`d`ceåN©74¹æhÀÊwÜžLºÆÈp%§îŸÿ5žö›óáG‹4×Å®¸&˜Ì'.K±˜ÝB,Ý0Å•ÊU¶Ã3Ó®tÛ㙢ñp0™)êá|,¦Çë°R¯›;3y€Ö4˜5ÌHåT×0êÀ¤/-ÖçüX mßLÜ|wP­tÏá´;¶cÈÖòÄ©Ëy鳓<(VF$liœíUzq4h´»Æ‘Ay‚jQ&Ϲ&ŒGx¡ß È,çBãWúµ~íèüªÕ®µf;7¹“£*8±# Zk±31ûñtÛ}Ã5Æõ³8ZRy‚Xߪы™Lѽ5Ú2ñ9j—¦UDj¹A2>‡­b.M²mhJ™@¹gÓ +tê*¿ÁEôªÕÕºí!b`vûbMºD?/…¹0g;9ÑœrÓn—íˆK43T}]=ăߌÑláãÅÆyÈ–Œî~e‚C+4F™1þºè86kµJ6¤½®½BL¥0ê"òMaÆNûšY¡ˆÖ:4pØIñÕ'ØAÙMÌpEU¼+ìu£PÓôŸì;9Úšl¼à:T]§Ch0vYÇßÇOU¶d«A±ý/£‹–Ð0Þ˜ YŒXbB¤Ö 3¤&-cädKjÖztœ[{¦""£Í€èOÐPwåNóçIQwÝûJ§.ðÕTCÂŽÀqNH;ÃÑç†Æœbåôzƒúœ¶m¯2ªÆabÜ¥3[=,®_é÷ t3W‰í ±Åsæ&H*Nûµ7ª ™Q~ýc矽— ÖX½hTa0¬Oߨ0~«‡Ú`96P`W«+ úòB˜õʱhM§–—ÔD‚›S0ÁâÏ¢š£ÙšæÁ6SÑq”-$!!€ÕèG•ÐÁà¬g“Íf«¶*u„ôÕýuù>˜VVB°›`cöÊ:3ì’z}£‰¤—£Uª¶ÿÐ.™¸uØ-©ÑŸ„Çè]±0¨RïGyD-š©fñe!¸›½NBKƃF#LtãwWYv©…ð€ÊU8² òtl îO°ñ»G˜ †ï®ÛEgÝÌy¹|6ö•¾£ºm¥ï¨mÎúu³^ B¬ùT+£UêX„3®&e¨:D§l»ß¼5òȶ’ø¥u ¹Â²×Hœ6›ß¢._U´‡&½Êp–C½q\á1Pë ¾¿9­Ãué2Ç,ÐmEÇáµõµQ= Òe·2 ÿöÎz+ Õ&H.gºåBÑÕ×jýU …Ôvkóòý|µJ×`s³^ë­5ŽšoÃÕi™JÞ¹ãöj¢‡Zˆþ†,êry­ÁâáߨCµî(lj Õn¥ÖY]—öHQ^±‰¡¦Å®ß _Ø)«%¨'X“-õŽª69s‘tkÖ«Ò‹ŸUÖq»Ù ’Ãá(ŒíA«È*µô-–ÕÕ~_5ûÊŠÎ,nåÏLGµ–«<2ÚU¤,"vÖî·qÐòJ&ƒ:±°¤q‹E(T©ÝCÙq*ɪºº²ýôÕVW5¤·*Z§‘& ˪Úa'ë‹Y¾x ¥TA±2í®:ÿP¥(-ãI—V롆jth³Þ;zFua{vmvûw4‚íbŒ÷!+'Dê3 ˆ¹‚†®Œjä²]7‘ãAµÝ}C B"pÜäð&Ó^ nG•¥ÐƵ¾ظƒ÷Z¾çMDï8qÙmöÅ^¾Ÿ­£·ÛeMÞ8-aÇV&oç#Í0åÆ*¨9î´‡H0éwÞ7ÉU–#\¶5;YÉá z€t #áíW3ýeQuµûØŠ íKä%ÉNx–‰X½lÆCûÓŒépXé3­ú-,ÿßÿçÿúÿüoÿ×ÿ÷¿ÿ/ÿïÿø«1Þîwºc¤Ž×FÑërÌÐj5$Mœð9èw\àgírØrhJ•ߌcÄòÛˆÖ“N*18k¥-õ™IµÙ“¥ôÁ&g X|”öN}wÁÝ«Øf´r½}(úNC©Ä(ßkí4ûîÜ{Û¿™nWÂã åb?«xvùø±´·S¸ß"kÞD´à±J‡“Tsÿ¬Ø•ŒRº‹×2áðfsn¨Bý§frÞõ6?ɼ<¤¤ÛÐv²7(ŒD&­`\ñLsiã*õÒݼZófÜauagªÞP/Ïîî“åtørù öz;‰ÝNî!±3÷‚™mï4çÏ×k^ ¬ÜóÓé4Óx¸RSÝD÷z§‘jMÒ-õ–w€ãÙ—©ñ…×ÄîÞæéMyœ~l>Ð_¾×ÌAýÀ +i/ÉRÈÓ's¸®Ô§k^ýŬekò™?Ý’ž¢»I¯è ¦N¶Ÿƒ‰ôæE.mL·â—‡žV´V«tà¯v0Û(´ÈÈ<©¨£öÆóNûñ°žêz÷6C£àý4Y(ù^aþDô°%®y•èåC"Ù¯mö‚±ãhDíÝÇÚª7Ää¨vÀ;;¼Ùc-s8¾D`S7 õJäê;ít¤‚ðËÇü¡m#ÕU‹=²‚›‚7‘>Øõ\e·uyŒðrp§xâjzðܽ¬ßíUÏî6Þ÷¢Å•- äN¹RÎú§xªPB”4/ëŽðg"•]_μÁ( +|xĽà*k^®º~ ῃñÜ.ýk÷*{Dª§·³Ï¤3áF8@¤{Íãñì¶ÙkÆh?W±ÝhýåäcÒœ0êï4%ÓQP¥Ô¡9k¼?v• —ÉîTæ ƒ:cŒ÷$åVy©%Ë™—`¦9zÍV*›)¥zq¶»ŸyŠ'Ë­Ú$Yܨ'Ë‚ˆ°ŸTn<¨Mý6{ý¼75AD¨ÖA¦«3­í3„Ý 2R¶Žá‰º­‚qOôŠ`z^ófŸøàeJº>Ì%F£Ö…´s|µ‡1¤Éí‘‚·µL ôÇYP:n‡;ƒA,tµæcS.ÓåSÜ¡¼ƒþÉsmÒO\©Ñòd=Y>œLçA9ƒIÜâ¯Gn(+#>ön'gá4=לß7 ¤[Êùm¶ÊíneŒÑh›3б¨9…|òéÇÔ¶zÎÁN= +g^Ô +Ùû¡Zéµw”<}LçÒC¤®Uë¹t½wƒ™çäS]%veõ­L +±ÛÔ~Ù›™ÃšÍÂ8Íä;^ u¶ Fä;WƒùÙÎÖ«¡¿¶'ùázU׃Qéd"уñ ‘nÛ +pËÐ]Qxö­UE_íäó×q0vx{ÈmÞ#>&¢¯ÞÂV~òTï%Kχ™H;æÏ‘›ûJ²|6Þ Ý +a̾»Íb±Íäyw¸e¯wVÙGìoSRÏ[[áäÑM©¿æµ±pöý)QV}§éÂk™w[¾L#¹ùè8Îs¹§€»…—xnß@[J®Î|¥Ø‡ïÇIck½…Ñü »]®ÅÏ®ÐÆ¾ÞÆcŠˆ¿&KÛ‰~ºÝ>«ÃÒÜP¥œ9:Úåv³r…µ4·ú¤zù8áMu¹0àêÎÚŸÊ«?0•—ÕˆZÜ?>ã«I1¹Ê Ç4ŸOvuóqø+?¨r(sõbð!¶æu¶‰Cé.TOâœQ݉›mðÏ=~ÛŸÞÃ?¡EÊì¶d5ÔRA(Â?gk^\€ûžn‡óç žîÑêLé7£ÇÖDpë+Y‹Ï½‘%‹„¶¸+Äù5Éx¬ìs>J0gf Ï;…;#‹„eP˸-Lé—¡QÌïæP)<2îÖ„<þ' +•÷à|Ù³ú¾KŠÆŠXèÙ –ÁKÌÑ.´N›kI8¡xnÍÆjaáÜDll†@Ð(PÉü}/B—¢¾0ÉYÖ¼¸æGf7Á–\í¸IŒ:JÉNtÇ̵œ| öqWaïe¦LšŽâáñ(¤ +ŒBúƒ9ॡQ0UÈǬ9³8¦³3e'ØâòëËôÐZ3žæ àgѱ %Ð㢭iÛûŽíš_@|1˜aÓ,¥1ذ¹E5ñ"uQÙ,Å£¹–1<‘‹÷EEŒüâïÜ>)'Mg1Y(O플×»öhÙß ZÛ &¡¿S‹Ó’ýR²˜42#Ó˜ª\†è\xéqª'ûÉóFóI«GÙs(Y¾<êç<ßÉ{óOh†²_ÁÏš—“Ó3ïnîiRÞJD¹¢;˜½¼Þg'dhÃ&¥Ø„YåË^kD&BçzСññ:ÒƒŽRÊ&’(wK•45z[È%ÅÎÆ!V/œ +b½Crj6´Ý2G{¯’s”Ô“‘<ï—.’¥ÉA/,DüίÝ\B÷™®r°t:2ÀÁ]ù5yšNM‘­‡ÁÎdÁH±áιV› £FkçIõþð5Fk^*Q”’îæJ^­’¼W!®TDcÆQ¦q6.EÚÅ;DœÙ×4ãEaýnµŽõ. Ñçš×¶8¢¸_'Os™—«§tûE‰D=o‰Í[<‚IüYUÏë˜^È»¨t\ê>ÌwEÕ$óÿ…eF]ÁÒÅ÷WX˜º¢la#¢dPÓ2ÍP` p&ÆŸ‘üwº™noÒ‘v<¶Cqå„“CÅé ²ç,ýÚ¶â>È–ühXÑ6‰¡yJœt*«t_œÐ¹µŠûÝKK©À*H}T©°MTïGi´ z0÷ü×3ùµ´ü¬À yéx¶Û3wà~‘îÃ}>ýå"˜Gì3‡˜t=Kv V€Ãê„q=îú:Ëö•š{|Øòä²ýé³àÕ{ÆþîöFäNSk…ÃÔY1×rÓ;¡vƒé7yvRºÌeõ"ý`±ãS;Ój‘+U‡–ê=kÊn;žtëÞ½ŒçŸž0 Í"®<„ÃG©Îqi ņµkwÀ€ó˜ê1·õÁ´/p;õ^—ƒã }»Ôˆ‚(yÁØßod‚gt"O†á³àÞeå• PVÑ£›u¤•¶ÜξO“¥|ýá%6nÝÂAÌ? ¹ù°×O1Šõ3ÄRñ(ÔEyœ}òÕDôb3l³½ rw=Ú˜_’å‹Ê `§Ëåî"šÍ~Èäγv½›4,zYó:)†7kšû×ÞÙ;w¯h€x÷¢Q–î_AIú2UÉ(áý»j÷Ú&»·y— »Ñ\F¾‚ñ›‡-Æ“í=¾Ãx`ë¶`Û½©ÂS‹Áópš Ÿ×C‰“—Κ×<¢ÊÊz®Ÿ¦GD~¡áë ‰\G ž›F¤e<><ÇtrùLŒrЫ˜ ½êÆe‡Øq‚ÎýÔéT¼E >gƒ[JÃvbYt‡å Ï«–عzmGûÕfbç:çµuF861 èU|^ïnß(û¸g´+­³›ÖäüHýŸÔo£cxZÀâ„â)H(2Gåãukxõ²[(£ƒno#ûÄõ2r¦‘ÝO“r"y—­»k&KT¡Ϧ·ƒXª¾®Ž#'—Ér!ÛPÍO~ן…ôi²xyØi?j „ó«-»pÃì–±¢˜ÂPî/rOÑVdvP!þÚCHnº¯{5Ãú¸š&µê°æ÷/·iB±VÞx åü=€?À(ì_-Væù +S> ¥º=®(¦s«ÄwNoÑ¡ÎÏ/Í^OÕÎ[¸ +“ÇTک׫¯óý܆2œ~»™KJ'YÎTøTWóhœ°ýÚN윞u)åPChˆÈÉ”ŠðµG¬v}‡6Mæ8y^N¼ÎÓ†gœnǎljœ·¢ì)×ùôIúrÏ”)Eì¶kw™ƒÚy1%] »Kÿèq£Ãƒ;Ëù÷ +úþ}nB…`‚ˆXÚ‘=ÚH62Mσ¤î Ãi$µ·æºj ¹»5ïn`Ãûô½›­Fn‡NÉ›ÌL+û6J¹'¯„Ö¼Ï>¾LjØ´9Ïü$[MmùwŽƒâ]²\ö¦nbÿjïÀì¶@_”, +„i°Ÿ÷Kdß“K'ˆ˜8¸Îe¶Ë²iˆTÈ(wz'™-'Uý¼©KÏ©Zfг*ÍTƒ ªR Ôß.›âR°Ê—{Än|x•êö9ßÂQŒTgsr˜’nÖ/öc÷Ò¦c[,[)ó{/þð}ªÛ98AÊGv`‡âɉœ†‡`Bõ¢ý+zŠp«[]ìðšû$¸)N’G7|Ý6hì褞©÷ômǼüˆÇŸvš˜ûÚve!4xnɶMl^І<¼dúa7SÝj{õÂóh7—ìö×±•u†^ðýàÎI:rŸ9:Ú žŒE5á¬Êeù†?·“<_g½ò#Î_Ž(±\2žR¼C9sPéÎѾÐ-tΗ†3Gëé™íƒ(y{Z¼É%¸ÉÂy¿šsomóH…½€6º€vŽøŒ¶ážfëVÜòˆr©–ÕGv%–ðÎðHA4ç?è%×¼zëþÄ“ËK9ïPBÌåÊh&ÄÔ­díE*¡¿, _ &Õ’'Dÿí'vCáÀ‚Q Š/Òx,~*eÅù=æé$%ê"ëW€‘ð³ÀâÆÛ·hã†n–ŒRBœ?%å…]ð›‡uP™’ƒÖé–]sZµS‘½IcÂ7múwørp%d*¥ü}ޛнt¦¶Ê“Bîa?±Ezõ©$Ž3áÓÖ®ã|‰+ÛƒÜV`[AbäEªD¢‹ï0£†^»¤7{Êá…}¥vÄž‹n¯/PàÙía½‘óåu;’1­žÝ{àC7YªD_”õfª·®½Ø$¥ÄþÈ?¶ó…Žr%îVÔèÙi1Yš^óŠ<ÊôÚctl¥zhŽ]%÷|ìÕ—K§;»çéãzÁc!›J}32…¦"µlu°ZLf½²ïê![y>XOõ‚¾4ÈŽ“k„é¶Í`¦3Û¾›[)('„Äý­W$rœØ˜çËhó:ç› ¸›¦¾4m›NŽ+õüâ ál7õòRLdêg“̡ߟƒÛÕr•ìVzX4ÊN|n6²]xÅ¢«]†™‘`©;òÔî¶“g[O脬õx;;>œN¸ƒ»üî¢ý€Ä“Zyç䱊 –{~z@c¢yGk'¥˜‘šáµ^®s‡‡k¦áz”ÉÑ$–{ê†#¶ÊíÇí&ÂÅÉüêÎc°×LÁY¼ˆ¾ˆ©’”67:uIjùñ¼HwP¹NŒ×뙣Ç׌±û¸î@س„èÆ1{Äù•ê©ï#­u¤^íïçž&¡\bÓ(;ïø,QŒ©E_pÍK„Zq;Ÿ¿ÕÊ÷Ùj9y•iʾö ÷2ãY&»"4EIcßk¦[w»¯¹d11\óî§§iPQ^yýýRQÛM¥º¹²îP*Òê×+zój„æºÑ)>Ývßmfƒ[µ× ·êãÃ}Í+»Ó[<Ò zëHÜ¿¨æÁvêåÅÿ9núé9c•38_(ö$o£3¹Ðå`Ô¬T ˆ0z³ž§ö.ÞïqzwÐíNqÌÖ`²?„õAßîEþ0-4÷'êGyЯ¡¡P«â Ûf‘>o¸¼².Hâ xyÇÙÔþ¤Ýh¯rB}wüþª©“q!°¾?¡Ë€5ÛW°ªyçÒ8öæ›>7A³ïÏ ñ¨-Ìé°¤óÍ*Ø2FÐ 4 GX2_³efð{Ÿ¤6=€hdu`†».Œ9^ÜvY|À¢–C‹'¬| áQ»_Ï2q»¯]çLãÙ…J+úƒ7ž£ygéqk­Ñ g,×âñùÆË—½$ûý wVŒÏr4%k£Aµ2)Tþ0V…Á²m[U†C‰¹0t˜ @xÏ¡&G“ߣNê­è¥- fìÔÇÚ¯Ž¢fkBÚö¤MÂéìŒìcc•Ì-´¨W+ƒ ‰°xóZJJ¶]+¯ÚíÀ`ʈ÷Z¡þLۻƨ½«Þ†˜rtí>"µ.d[7ú®ªÑî¹JCœu}Ôw¡ˆ§ÚO\tÖmW¥;Ƈ|fÐÁ!a×¥1úÝè£SÎUB£Ɔ+kïzÛ…¾›_]¤ŸñðÏÃË›í¾}‚&.ƒá{.Dˆ«Gƒæ¨Òë¹~G­¿„]©°ë ŸÁ“hÖã¿ ìêýù_á¿Oú€ÿЬšþwwÒnl–8³üïF­ƒ+©LûU£Séã,T‹^¬_B`µQ{øîkÖÿq²2õÍD_'Š¼Í .ÆS)Û¥WSfóNr{ó [DÓ«v3#Ø÷é‹zk¿,äö«x}qé+£zÙ6~ÿFlŒé}œ€äöj¯ŠM2Ä‚(ºÜšöªýJ»»*LØÙ¿Éåá°p7—Üêí®M&º,á«]µ{Ç•Qçê­`cG÷oŸæÔ¿ÉÑŠøÙÙ™¼C„4ßîS~jeb +V1 ÛøoÁ~ /™­„‰¦y{E$p˜)/ø•b•È ç1{Gç$j–X6“q®Ül„–m™ß/ ÙNH[‰vfº2$É+Û¶ì—¨ 9 Ó¦Æøvè˜ÛíÎNõâaêÉ}‹™Èé¾ÍU¼£XªÔ8öÄè‰Û=ºâÜ>iÿ<±sš˜èíÜñýíôfÚŠû—/_ÜîÀsÆíÞÚ\w»ý‡ëk^M.dO¿Xÿ‡Fq ‰ÑÙþØÁÏrR}hvÑÞ3ôϺ–O%Œ<ž¯ßåÄåÃký±¹‰fŸk‡ð3ЦD-º?OIåòmm~ÖðϤv&Ñþuè{7©_è¯@ ~–×¼ùÍprý½•ÖÏóÞΉˆþÚ>ÖÙt{\ŽÀOÑ!Í¥Ñ+ü¼€Ÿ¡ìsüÕTÐ?ºœZÕþ‰×¢£™)rÏúžK7b_”[eØÊVËÜzn73M†ÅÂÞ–˜Š„ŠÉòëØ›Ë¦¶kÿC¶º±s‡/3GSñƒ S\óbà“wKȈÇBfãn‡{¾äÏ¿|ñ 7F‰9 J/døXó¿Å€¼‹EÞVç–Ú¾nŒh<ëçà.D­Qñ!ZææÑ#*î´YÝõÀÎéúrpnÍVÅÔ’:+íiâýI˜Ï§nnÏ“çõ=_*ñH0¸ùúÌÄ;±¬op½•OÝ+Ï©ÎN};ñzÓNÙHÉêõÑôk[~Ý×׿4·›;8U”£Ä îï³Ç"Ô`¶;QÄiíË—HçðÈŒOF*³1îÐèŽf}²æU{÷ñ0Üz©ÙÛF.…ï"G ¤öîø‹™ÙGÆû§Ù*·=MÝx“/ÁTH?»ƒÁMzµšêÊÞª#8O€í±~vˆF. ’¥©»Le…F>ÉB'Xevè{1“:>ŽÏ¢”àò ¦á/nO€¹=‘ZϽ^ßq»3W¢ÙQÚíÞ;œÀ<×)®[ëîÀÉõ«{kGßÂ4ŽñŠjÐë€_žœ q_”«P7˜š| +m»}îußÃŽÛ³9qoÁªÛ«¢­ë‹Êˆö7w¸¼Û¿×½s²¥{ë(vÏÖSîíËÇKwè>ûâWCw¤Ù޹¹^ñÌÍUÃ-z&nqz¡¸eßî¡[Ùö<ºUþiäÖÇ¢[ÏIûî ÷£;Z«! ¹c¾+Õžº÷.cMw¢ÏÝ©­Œ;}çyrg}£ w®øšpï{‡÷îƒÓ¡Ç}š&Ý…Š÷É}² ¸‹>åÀ}VM¶Ý¥ƒcÉ}Á]_¸/§/ëîëÁvÖ}ûk¡Qî¯/T÷ãY÷Þý\–·ÝÕËó’»~=Üp7êñ‚»5¨LÜ·ïîíܼº§á¼ûµvõêžl ûëîƒÊtÝ3L¯ûRߺ¿u}±Lïq롱÷y;®D×Eþ¸·æ]—_v×µ“Mÿzt§¿߬ì®'F7¯ëéÖyi=÷x$­<t× ÷û§ë§õciý¼{Ö_¿˜\–×o8ÔÏ}²»¾þTr?­W{häFô@Xo_ zžáÃú°¨ Q&›Šg½4Úðø¤½–'Ю^yB%eßË7šGö‰AÖ«Œ=»Ïц'qþrëÉœžzöK\ÎS¸êÄ<Åû3ÉS~‰…<7žÀ¦çA®{*ÅÊÈc4K=Ï‹pô²æõôÏÓ-ÏØ—ln¬Ÿî566·ÓÍàc¾µÁE^6d÷EoC¿z݈ Ýé ¿¹±/&CÇÁ+yã|{Û¸ +ïä7î#—ÅÊŽçn£q|ÔÚè<§ÃI>ìuG§±5¯×w}Rð§›÷^þ¤Ò÷*“dл{â‹{S\£äÍ·ÎZÞã£XÀ[Rà ïÍúäÚûØí¼zë/mÅûòô\ôµžÏ]¯H¾ÍNýÌöõ†>I]úvŠü/ÑNú×¼¾¼ryä;¾îô}eßvÌw{–¯ú*\[ò5 ùÎ×Ï\…}ÓPàjÓ7¾ +m†ŒÈõ¦tùÞŒžEï7SGióà´Tß,ÞÇ÷6¯Úþáæã´u¼ÙPn‚›½ÂÁÓæ¤“ØCüo3sûà ýÚ¯èÊŽ?ö¢MüÙ\ôÚŒ¸¢¿Ü/ùü÷÷•š¿~8,ø»)NñORGëÍ”Q DÒÁb@-â½Çq8ÍŒÅp§¸>L_žî£@;^F£^»š¼åͼ·Â¾;Ï–òyÝÚÛ—:[û↱uæT¶nÆãVµ[¹ßê´î¶&ƒ§»` Ð| +Úà)Ý_¯3Ï\#x²é¯Ž¯GÁÊúØ|9ÖÂÁÉú¹ºæÝö?yRÛBîàd{74¸ÛÎŽsííÓÚØ³}óP·kÏbv»Wí\…ÖûåN(äCêN(Jž¼^…ŽºAèR¾CÏ÷WÇ¡Nø¼š6o¹p0uwV|Õn8Ñ¢QÂG—þ«ðeaw#\9ºØwûÝÈú¡¸ ŸW#ZÝ#GÒÓýÇÈéÎDŒÜ^>F!Ê‘×âc•óû“»œxáép{r%ÇNŠî²™¹âªg¢ÌõѸ¼÷À_XóòüI ÂÇJPáŽù‹*ðU>=àûûÅKÁûÚN +Bl3(ÄÙ®p”~¼®·ÂyéPªðZðlŠL©/*RàYLËÏbQMŠúFB|)45iýê”[óJ‘I:(ÅvUŸtx\—®·6&’q³1–ÆâÆXv¶&²~¥®ËùtÚ+_DNr-Ôää×í-UÙÚJí)ÿ¼¯äR‘’R>/=)Õ®¿«¼ê7>uë^RT=PÏ¡ó,ÿxt­^Æ…ŽZ ¶ÔqΖãÓ+mw¨¥S’vžhí£Ä‹î9Mº`õ”ïr¨Ÿe[»ú³±ö»¶»½³Õ¾9ÛÙÉ­»ÏÚËïÜ­áN»ˬy£GÝATJçsÑLfs-g +ÑúÕáftRá®v9¿GÞM¤_Ú»ÅVí`·¢Ýv_·Ï±ÐÞM:ߪb'•V-öt¹qÊb|;4ŠÇ2Õ‡øÉÑÖAüéöa?>l}{¡Pº³?=ì ŽJn;³7VôDä4I$Uq3Qò{݉z¯3Lº:I±r×Nfë7ÍäUóª‘|Ù¬´R›»—”~6í¥Ž†Ü(õ˜Ê{RÃQ-¸æM‡O¶ÄtR(ÄÓ¥Éä0ݨæ/3×ÓzF==gOÃáÌÃU+™>—²_¼Mi[ìŽ;™moõnr›W/ã\4ÒÒs'Fç"W=Œóî@,/‡´ÇüAà’ðÖŽó¯ÁÀhŸÓÒû™â¨³ÝÊÆ÷{[ÝæÁvù(~ ^.îjéƒ=?: L…“øá –Ê­‡ÃÖ¥?òŸÞb·—GHÙÒ¿lO +~mtSˆ= ©5o¡´™Ü*´.ï^޼ûò8ÞN¥Ëmáø%uŸÕfë$©dïN®dÏÉIo÷>s>ÎEO3œpz·>Ý>}Ív6‹B«â)ìÝO‹O“ÇÉ™û¡1=Órƒõ³SÝï]óž5‚JàÜ)rç{â‹z~©EöÎ{'‡¥ˆá»(å#çÕÒãi`Xv¯ßËZyo·\ÜñŸ–›“Fõb«vé¹HÝí\Ü–g£r´s)?ÆøËãVüø²á˾\R%iÍ{•l6.®n5ïúÕ¨Ï^+û/×§AôºÙ9®ÝŸ7Ô›ÌÃEõæáNÐnÝ•vãv§UØ»-oï n{Ù@áŽoŒ·îŽÄæã]ý±¿Äjîû´·}{_ÆÜaßš÷!z²S}¸8+å®ú(UÏã©û¶ñØV·.žÂÙ§?¯>Õ®[Áç€t0}N÷ùÎóãݤVÙ8¨ÞWö—W•ÛD±T™ϪÑób±zY¿,VG[Õóšv2¹\óÖJcþ®68:¨Ô•íæKý¬Æê½Ë»€!r²QŒÝ¦Œn:zÞ÷_kÓ«ëi£ÓHˆMQš§%ßS³3¸[âY?Ú*Fz—­ng4jK÷hûìbç®Ý?) éóE)Ö^J÷ÁÞ˰yëè¾n½s™Iªñ˰ÒÝÍžiÝ›)oôÖ¯{ñ^b·Ôë= +¹Ãþ¦_ßìg7ùû~-ÂÅÛjx28ܯ­j|w(p§ža±ôô<݇kÞWí9.¿^TÖGn1lŒá‡ËÑÓ–š¼ Ýq;—÷źˆÎßœFÍ'IT‚ªL®„LDìÛV¡í% uß`\~Vƒ{—Õ o÷Zþ¤Ý³Ñüpfþ…?DŽò$•ièùξç=7$<Ý)¹·¯3îw,p‘Ø/»Ó3i,ŒÑä2iïô9.¦4QCcï§2ÀuÖWnÿÉH¯yGˆEV“ÛÓÃÄ‘>Žkû»WáÜàVºÌŽîo¹Ìm‹%c5~+©öé(âÆY0Ú:Gã”eË% Bª¾ 6W©0¢ã2dû€‹H%² kfc-7¹H>®ûx<ò©Õíèµi0žwûðÂ1^2pd¬å%í5ú‚~滨õMÆ9èýèáøþlñ yõQÞ9x /ôqãì3ÃZƒ*í£¼wñ »nÿhÌ{G‹-ò÷Òº°³e ŠNvsØñæöqhÉ rË_Ù¼É.T +Üw…æâ•"½ñCÏŰ[X´V.—:J,TñlôGØ’Ao¹\ã¤d ŠÓ ™ÃæÝ»>þð©¼pÐü¾P^ +^á6^~ƃ"Z¬f8½B”|?`ØÀî=Ÿ/tÍ»!ú£÷‹×ºë~{ZÆùâAÏÒøëF¯°hÐ`´»·Exq’ÒÖÞmâtñ ÒÍ —Ó¹“…ƒ®çšêÆyO8]4èš—Ë=<ä–¬Uñx;ýãô²A+\~ûùrñ y.¹iøÕ<(vßqxâÙÞ£ƒÞ„ü3Þ;‘b¼ÙûNÎ1èí.WPC< º53èšw¼¾o ”óJH@êÃYú-ÜÝV– ªxÔN=÷¸lÐ w¼õ ãAÆfÖzðº“xœ/´Ý—zd”DnÑ Àù¥»Wz +¬ÿÿµ}çZͲõè PšÈ @6`‚`266Á{¾óç\ûW«z$ÍŒ&Jò³÷ö­Q‡êêªUi:h­íñ­õûog§…|à ÇÓ/¿C=xØ¿ºáAÉê[ëÙšt¼õ6<è¶š;j.Ï/ú¶94(Éd {|¹6þBà³]éÇÒV=xÐÅÆåÅþÏŸƒþÜ}ÜàA¡_ú×ú·¥ß5C=·¤Ÿí§rð ßþ¾=ïÚ–ê”Fáa/7Ê/¡þȳ!ƒ¶Ž¤ÆŸçÍÀA­oåñìòÏ2É1vöÝh¾.ÍKgеà;4…ÓíëT™^̯{Wº-]ÍÌ®`ÐRoPÃR·ß;BáÃ?hûujÁôs©è[iöüú¬ ]mÉ^AXúh-fi¶Ò/•6ʼV´öÙ' +×Ç 1è’¼Uö ÂÒ›öMhur¶¶ÅƒbgØÉë› *ùýøX¹íðïfÖ7h[ÿ;ëhš¥Ùýмã¯÷W‡?Ü__ÞI­M]¼Î†~ÛÚ—ŸÃ¾}Ö¯r_½oû$?‰ÞúTȯi¦ŠµÎ¼þÞ›¾o K¾§?8|çH‹UZóùŠ#-ûŽîUþÔùîrÐ,6¿>á2u°ì;ñÕ?³¥Þ?‹où»CÇX‡Löþâ[aþ­Ûcž»X´×'ÿò,íµ³: ®ëFV{¢É~±‘sþ)í¼:0î ÐÅ–4ZÜ›xÈç}"±·Z}¸¯çºÿ|w#fÇg¶Û}¸ŽQÖÜ˽Ú\r|J4å£=j˜ ýšéPGàvG»V°7å%`×ãF–6õ\ŽÿCþðZIA“z´7|“rOéòkšXw§¤L/I.?šÏÈ$'iùóku+ŽèøÇ™¼0æÖ7 ]_&×[!ÿºƒý;ß¿‰îúf Z!ÀëQ±’ïß+ó§°,+¢3yfõo3´«Lvïk®œŠ³z|åÑÈ‚³ÖÎßÓS>înNNšòÊꩽM÷L8±¼¢§Ð/z.^Ñ£†ŠžLë6Î7>ÜìNÙCÀ)!z‚iwцq2ŸR£$þqh'¿Ó®UΆŠí°SÉþ¸À¥µÆÓ/Í­ÅxqêÒñáN©×¶¦œhBàDêEߪÜZ̵ªû½Ê”³û}b´A£¿¦ZP„!Þ!sîÄEÛî1tóùUaŠ&wRÙ¦Ò›|=9½Îs~þ #…ké‡×âB‡s\œÌNàÎä¤uÅtwEyfúÏÝu3鹋>u¤+¯ÇO¾"÷rB.É%üsVt)úØ‚$c¾±´D1÷†âÚО#ºŸ7h}])ØÏ»ûÝ)¹æÅkù\ œÙâÚM;l‘ËÒýçQµ…õoIÏâÛ)öoÉÝZ +K*z-¼0+L1%ÀŒ½‡ Íœ}†ª¥L.Íþ®&ëéÑSÐÙ¿[óÊébí¼öoÄ”>—6Cuåîwg>I M)Ðu¶.“K¶ƒdåG‹8ÌïÙÁ—\$°H±k{Ͻ®'ÑÙÁK‚yáEÌI:ó*”´óêDxÎZÑFLšEºQÝлü!ż-å¼Þ¼~˜+ó£Ïpý\lˆŽ=ñšÏz1h´²zò‘c.€|*?—ÆGv*WOÞ'ÓÊ"Û·“ë™l÷hK<=uZãSI.¶ôSg±ÝU˱n„``¸î +ç%~›ÛÑ&žo"'÷O%F +$šˆ[F“˜c°‘‹!*ê÷:\×g)lr”ô&us{”Ÿí›ŠË¡MŸ6Àó„85 f#0L ø9 Ѱ#“K3©‰€WZâÈýüÌE«å¤`£'’Úûáë›N@òL2¢{°B¼?Ãä{¾¾¿êýSÕ?åÆÏöZO2xrá Ÿ›œxÿAMÊŸNÄ*ŠXÉx¨ÙÃV+å÷«{Äùê¤ýXõðM¬Å{Ä­îxïqíx2I”/aÓï’õÏ&Ê%ëóQâ¯uŒDœì’›OÛJ/ù¡4ñA¸3Ñ‘É À4¨¼å‡Òih'ðÏ'=Ÿ¤þuéÈœöq„ËK¥·|Hx°ó2»_ˆ^Z<Ÿoõ”_W¿ à~Ûòë½°erœN¼ãUzƒ€¥£œž‰Ùód„¹ŒqÒg|ª. Ëu|Š.N¹±¬X‹KÕ!X5íÎßÀª¨- 3„ž:'×h>•t>ïþ5Ÿi;oT4q’: ó·y[…eæoEg)_°½D‡&“:HÁ»­ò2‰ûñ’éfãÄÄE?Þ@ÑKךìõÒ‘ÉiúI¯÷ºö~@gža:%êN3º(彈³Æiª#‰0Ô8ù4“‹?† Ô :S*©c|! ¹œ3‰H邟³ï-æ—híÇBŸDk?úx $Z ‡¤F„Y~V¢õ$ZÇzMƒàýÅK´LÂ:\¢uOåÚñë$íZDK}ö©Ÿô­Ïw!ú^¢¡—ác¯ÜOD4¨´šïFqª™\ð(¡ã×( Ú: Æ(Zé»7ß’lž>ß8Ú† Àvô˯é÷p1”™Õèœï~fáO'f©³ãl*!›É…ŠÙ³¼‡ù˜mi%>@¡]ó%5…I˜ø~’AûÐ^ØCý ŸÁ½„Ô¾È{|?Þ {B÷r@4;…¯ZèBZ_è« ©µ< ¾w1éõø÷öÐßɤÞ,—ï"TþH…ï£}°èlx|þ¤ Ój1ìZz—V¿C?Ãà{W/]]8¸ã~ð}P/]ë5¤Ÿ¤Ú0Z²„9Zztá¥?NÌ£PëHÒ‘ ó°]éIžê¥a„bˈ-q“²” úvr2Œ¯Úçç§Î†=Ý®yœíè\ëŠ%‚»Ä(aíe%Ñ9ˆžÖˆžÇÕÏU‚t:ß”B9‚s{b—_1Õ*å>µT«TÙ• “²zršžž¹bïÓÌ”d¤Lp¸nڣ˶¥ÎBc7]oOÒ„zêLœÛÚ…‡„(f¦ƒ!9ˆØÉËJ"¬è,ä°·"“oGd:þûD“JÈ}‡ËÑÈâèöôÙ¢¾óhY8{ÀÕríßÙòËþ%ÞBØÈ–WÔ ÔÍ5‚*èÄ›[†¯¡sk±þ +:_ÅÐÀ5tÑt,“GPC:(WÐ…V ¦¬¡‹® sW SC]AçA}CÔÐEWÐyª‡¨¡‹® ‹¨LUC]AÇÕ‚#¨¡‹~Ω­º†®ïàz*躖Å5tÑtŒÇâkè< Éf{ÓÍ ´ž^ äKvI0¥@Oo=>q{&Y½TÓg#œ [÷£ßç@ROïYÝ«íÓm+ÆW÷'l L§¹»zkE»:>Ÿ¤ìþïýqœÅã‹ê,:+ÙúØ×W9—x}>ÏUÿyINôjú)…T>Æx®¢¦T2‡µ¤*šK$k¾T^nOºªÏT© ",0$½Û8ÌiÌoÚ_Õ*OD/-“°ØÍ› ™Ö1ÈœL{>¬ÇX»……m¼VR\±[¸}ppIËFd2ˆÇ43C¾jO¥p²Î¼)XrÄæFy«|L&³®›©Œ^>•afïžB™ªÄ”kßvVÆÛöD¬ Xvõ»Îâ‡Ö›ÏMB¿= +Lš bµ +»B«À\HÉ_ »×ñ}ÅåÀ§¨ã»‰«™ð8­ÂKÓ‹`¢¡tüôÂÃDؤ–ƒJ4Ã÷/6>qÁݚ׃¸Iëø¬¸š˜(fðf§£³‘Uˆ~ô"a•)i:‹çøäó:X‡¤Xl™hòEö$Ú@ó:~•Õ“VÙ›è´îK¬¨äJ†eû|¾ýfV÷¨ö[F×ËùºéàqÜ«‘º¸R.düsyº×{]‹/ÆØû½žØØ ëÀŸ£8@q¯F¡}î¾U#Y©Ü@;t)Åë—¤ >(q‹w2d"]Ò¨J 1âúØ>ªF.Sæœ äÉ Š~åI¦Ï¼ŠÀ‘³í¾Tþ|ý3É]‘‘0Nþ»‘ν`* ¤S ×'uÂ+¢>µùxl#é‰ï÷P<öw#{'¼ÌΟA40b< Ÿ)Î)=2ž)yê‘iRJ÷GÄ”¼‡9^‹EÐIK:¥èìôø¢¸¨)ùßÝQñùEIÒ(<2›ì‘2KðdŒã‹)Ï™œ­L ã‘qÙû›Ã{d¨ƒ|DvGŠ2´A<2}Õ‚Ã{dP†æóÈ„U¤ÆÕçi©<2~þÍå9ÉŠsP¢G.ž““¥ïáªÉ –·z`9h‚ˆkÍa/¨"õzü2AiŠÔëñ›$.ƒ˜R¿‘T¤ž¿¦"ýŒ¢"õbÃW¤¢—QT¤¢Ÿd¯ö™ÄAy}|@Â_šš:ɨPvvß{ O†>†¾R¸`96êR8ÎçÌèE)\ྌ¼np¿¥—bѶ{ +»rˆR8÷;ˆ¸ÂxþA)\°,¡}ÖŠ†nQà~rTáÓCh®j’7Â{ñX­c%MôBWz"b2: ³]J Ó÷’á´ÁW5z+a'êí¼$ʃT^o”øâf]ÝyèëpüÊ¡ã P½ó‹[ãJAã9{ÀW\.î>¬=__Ö'î¾M{rù¢y¸¸×X®~N“äo.™-¾6¼~ÚøX^Y77k«•ÛZmµº…KÞ:ê(÷ä²ãqòÖbUÁJrj”ÎÂëάýÙ=7{y‹ÝænwwÜÎg× úÃLn>ûVa§µN¢ŠÝƒJÍÃÕ¨ +»ÜîŸë°A¯"]+Û®AýµX³Å¶Ë ç/vÓN¶»7úJÀÆóQÅnrÅ7¨÷>¾¹ç° +;cbâÝø:+v;‹ª:{Ž®°{=< tjûþá.lÐûèûøöOÂm|;[ %ïä‹:w6è¾·ÂŽw•¬³jþäðùlÂçæ‚ž^Ï“Úùv¢µÂžxÎQÛFýÖ±’›_O~…å;NrëE°Å±OŒhoêu4¥=ñª~¯Iø=Vï ¦äŠ‹EL*.95.ÏCX¯£¼I.èÚ‘€wª$ð.EÝ$—Ê wVOœ"S Éï„L‘×w‰\d^_r~йD.t}A÷¾Å]6’t}ñw $&zÜ=#¾w© q\òó²v~QhºkÒ è¢=½ƒTÓ æ‡I[Mdtîâ]5]Â÷à YMäôŸ—á«é‚jé­| ¯¦ òÅgÚSMç!‹sfß?6T5]PW1o šn@œ²š.(NÓÕ•#«¦ ª¥sÛû£©¦ ª¥K˜Û“¢š.È×Þ¹}tÕtA»ËžÞ‘VÓwîèhªé‚jéBÞ6?D5]ÿ”&‘ҠÕtAà4“u5]ÐþdC YMçï*öNáªé°åh«é’Sl˜j:_Wþ˜øˆªé¢XêjºÈ«‘UÓ×Vºš.¨eÄÕtAÑ_üªé‚ă×zE5]LddDÕtñúeÕtAÄè¡ñQUÓÅUr¦š.¨–.ô>¾á ÀrÏôÜ/–êÕMá·xõ_Ré¿›#aáÓ{Ìa÷_{ »Ëfðûêú¦ô‰(Ï¨ï« GÉèôYœNE§•<™¨ÉŒ YÀS Rõ6)ß”’Š‚·ËySM £I¥ºv9jJÁ‰¡&‚N×.‡ˆLh1¯E´$o¶}‘:i¿Å\lí™ëÞ–uÑÝÐ×ܹÞs•’rÍ]èír[‰j•^sVÉ•¬.Q‚Dt~ráöj­õ–ä–™H/U¢kîb=Š ÌÐ×Ü9&ú¢»¡¯¹µo1Ý% ½mà=WêÒ‘½‰Éë,¶F–¢ô¶ÕƒÜ×òÐÒ +Iù34ʃ êbsãøet0ž#=ð‰ +é’d4gâ+ Ó8×Ò(i‡)’È@Pן—““ݰE#OLûë‰ðÒÔÐ5½*,Þ³¶÷<`a—'Š˜*&èÚþÄiР|î)­ôú=êÁ­ãðA£¦'³‹†Ä÷¥î'§ókf¡êÝýçÔšúœ»¾Rºš™]IÐcqöõ³ÑS“´æ–æÝ`ãíñ*ÏZ„Ÿ¸«è¦MQõGƒ<·˜Å'N&ÐÍÔ÷‚¿°)ÖC^’ÔŸZ:%prø¤jIJ›â ›Ú£º™…º17³$õ$Õ£S«B·®ïfà M +ZTÕïÍ“CT¥Ådh +*e’ñ“/è•v}]¯5êîRß²2¥¾,-ÿyILôTYZ™\Ô¤ÂýÄé¦DÒ2‹!®e‹®dJUce§zÏkJ¾ú—»µ(ßq,÷LÉ•ªïD«]§6e)àãd‚RN÷{®"Jã®4ŽÙ¿^äýn-¾P'13øî5¼e&Egq·èLû«k#:ói•á([Ë“|‘ÞÈ勽O'ŶµóÎúÊ…ƒÐ¡C±«“Ö&~IXX¢ÀˆìôU€IkûýÉiª“Öºßp˜¾ +0i {­®ô°J„…éσMW˜´¼ +°GÏh¹á­±J[˜´°k#T2¥¾@w¼ŖUÃ_Ê—üF¶a.ås­å^Ê×çUø'—òÅÝÈ6šKùDÍH4@þR¾L.ŽüR¾þû‘ÿÅ¥|á÷#òR¾D÷Ws)ŸÛ«€I¡“rHW~«ßðï†ÚÅ»¡Þë—èÝPCßëçZÚÞ v¯_º<¥Aïõ‹¾Õo wCÜëí +¶ÄÓßëÌ|‘ï†à^¿xNŽ~Ñ™!]ÏÕ÷úÅUrÈ¡y«_&—Ê¡z¯_ôÒ|¾‹ïõóL¤ïV¿n ¼×/zAAªƒÜëXŽõVóä„I\)ø.èîõ‹~óW7&>ä½~‘Š®ÆZl÷úE»…S½*â^¿hS70 z€{ý‚Ê${Go¸ûøFPóžê^¿è^àçŽ~Ñ•Lâ~†)|÷W¤z¯_ÔtÝêç¾Aâ^?ß1”¼·úyÞÙ•ºí½~ÑHo<Ž~a:ü¸?’8XýV8߉$Æø{ý¢ãÍÞ,‚ÁïõóRÛo-z_º$ðûøFp|º·ú _’"¦¸·7ôçj¤»ŠÏ_‘:ܽ~Çvß­~¢bhø{ýº¥RQ÷Š}¯_4Ì á±Ô÷úEßê7ô[›œ{ý†ôõ%¼×/AÝëîõ‹¾Õ/õ}|Uáú¤eÿ½~ƒûnõs2Ô½~ý®d÷­~ao9K{¯_tz—O‹ |¯_t¢“ϧ4ð½~ûâºÕ/ú½pÉïõÜoé¥Xúš§»rˆ{ýz‚+èV¿³}÷úEr„ëáîõ‹†Âzþ^¿è‚XG#}¯Ÿw‘þ[ýúðXâ7Yyïõ AÃļÉ*á½~‰0ÌÐ÷ú¹w²?€Q]r>ƒïõ‹V‘Uœ#+ˆz¿ N£0ÚîQpƇÿ½RâŠ>]I­á®ÝèÄ{_Ù¢‡›:<Ö‹Þ,.¼¹ëà…oÊ*ïÑ•×a¤êî½Ñ¥ç7%ºÝFí›Ò~È’ZÙÌϾMJÕ“GS<„zªìäÎâFEÊ¿d«·gošúñ°Ù\|úiïÍäËÏ…éÕ÷Uiý÷·•‰÷¯U#{~}§Ò§«åœnÍ­Oíì¾×ß[g™œ©W´[k§yRÙª|dõí5íjõûãÑÒÝÁŽñãáðþ›þ~œ¿ÿ5ùc¥ ÕÿŽ~ßzœ}š?y½_Ê¿¼_šï¹åã[öÇ·¥éI5¿fä~ml¾&δ×óûYçìsmçâÑáÁq¶R¼XÎ*¿ß‹óêô²Ô\ÝZ•š¿n7¥5cêûÇÇ•ÿh[?6ÚÆM[¿9ÛëVZªåuÛý­~´Ï_qÙœ=!j«ûeˆ§¾tîtûÒ^¹ÝƒAݽ÷I~]ɹ™•åíÍ b11h¹ŸSØu2ºV®hÌ_OßïMŸ.N¾|T›SŠöûkâé.{‡JÒÍNqhö«ô¦}C¾ÚÎ ×$fWš‡‡9iòþŽíý½W/dóZÚ^ÍU4×ó·º–Fb-ˆ‹F®ö•ÉÕO›÷'|fíçæÄzããlþ’‹mW¯v~ÔVÊa½¾T´¶zÏ5퉃wêçø½Ó­¸>3/M”2¶.–ç¶³¼ª•çWpòÊÖ—ÅÆñÉ:>Ñ‚÷ž*(Ú- ³~Qo}°å$U?óÈF¸ü’¸ªW¦;Ÿä<ûމ"æ ýiÎpÕ/ œ7ús¡Äfbš´ØÙ5Ô*6«Í†²cQ·ëR±^Ê}5óëriúá¹qûønKÕE³ÀÅä~Ê35y®öçº*Ó E×דµ…L®óU­ÜûJY==Zê|±ÑoË=^yrã¡C˜o¯òÚöøu·­Ø{8““×.*·Ý¯Ê®~ÖÞf%´U|¤“Peô,¯ÛÊ‹êÒQ–äáÞòLw†—ì‚¡¶f Tš!ëû~ÕñôB +Zss—h··[E?%"å;I½#™£NÚÏŸôç™ZÝ9xTé·‡ÅââÄü¾-Ò•g©ÚÚî‘åª7Ê‘Ã8-׫×óS³¿_¦šó í¯¯ÞÚ`ß m;ø¶+‰mšáK-¨¿LnÀ;UäÜcaÓÚ·­µæòôýa}ãn!ëÈéÖ‰Ì{Êk9Tz»¡ž.'.j]kÝ¥_Ó(Ÿ¶Ã7»efv‡uoŽª³ßœHòÍöF>É»Þ\(°+7Ú­›kU|R&.ßV÷êÙÛfv¦r*ÉöÎÛì·ßs7‡SïÌJÆçÛìfsåéú¹óg~qþ*{q„’ŽWþsaåÛîr3¿µfw¼=ÔÏåò[ápqåõawÆá'ã›±rX?|oŽÚÍüíyÅaCcIjÎJ•ÕÇü÷—Õ§å§ÃÚŸ¿Fµ¾±ñã«™-å§År•§O}åð¸ñ¾òý¥€{xk¿¶äåù¥|®G6óxÿìpþæôøaùø×Q³öûw;ëãÔjÜêW…o•¯ÚÃWs}ùcââ³þëõ£bœw§™\ãôn³”–Ñ`k‹ül±¹ú”;Ü[žÝÍß6nÂüŠV[­gr«åÙû7±Lµð2At:š¬o<]ÿ^Ÿ¨äLlòìò¼1ó²bdwN:ß.¬7òÎW ó—$¯ÉËy¢»þgu÷óâ€y¬öpvûeàÛ±÷¦fˆbõÂÝ>°Þäܯ‰§+<‰Î~ªö:)4ïç³ØâÜýìÔ“ØóÓçõ§ú¯\û¨}¢­l>}é=’Éu’&|ÀÊ"Ÿòh•®ÐÒ*=]AÒ²«Uô§›¥×ÆÇÏã­¦=ytO*øj»ñcõýx¹ú¹º½ø>ù¼í£ƒ#à6Ÿ³Ñ¼,0YH +lXêt£¢43¨‡ +JžþÖ§ˆi´\}máüzu?×ȃvvý×ôºJreå¼¾9s6IS:Ý–”ra’8yåy¶T{Ð.WżÑÚ\ùjßÒq͵œ?ŸÚÉêͤ#>¸m}û\H*p¢ð'¾àëü™÷æ~l·¯— 8Z_OOé¯M—QÁm㵕qúÙ÷OÆ=oÝ]Ü]”þ4|]k“K.0\WòvKí™ +Ü6>¾¸´&Ýå^êeáuÆ ^ ™¶Ç›Í\¯ é~\¯úº89Ù[]Pòž3»ö„mÊ jœÏ•39ujîL¦¯—€3„GƒÛHåWDÛÏö¥Ê©ƒf.?=”§ó)®×V~ïwúÏ8§}ÁÕæ0rÆñUËûÆ’éXžYþ1sÝÁÄ J‹÷‚ì×Öü—|ãæÞ¾|e1lVìÖ>›‚¨ÈvÞÍbO8­?}s­Ò‹C±ÕÂV±ó2’õŸ•ñ¿GD§b“­”† ûÅûž’ú#Íl­è¡Þ>èá¼G„âÜ×Ùn—¾7Å]$8ûPoõõÞÓ#Bíôî¢Cš›hD„(ÌLºH°T{õäŽ.åë‚Π{çyK¼D"DOU ªš» ”/™ïï!‚ª=Æ>ɾV‚«­³ ò7“ßσø@xf\tÌÍg¯‚X)´‹Þ+\CyѵûaÜèÄŸ†˜C9“¶‹J‚#•ÉE.Cf7¨ƒRÑeï ®NËÓ¥’ïX„Ò+…gQI° uy?Ÿw:¸^Úõv ÷æÉ…Î"Š”%¥Ó…1ÑÛöøÚVÍó\u¦G1cbòEÛë¼ÚèYñnN~X) ÏcÕdr‘]ÈÃòXax› á±¾z<æï¢œ€M=sð/£êá±Av£$¥ÚNÒ•}]TýJ(ˆQs¨ú%_O‹%]F5Œ”Ûé­ºª&9ñ‘sdl¦XâeHé—á‹]U‡=U%t|öœª?‡uma§V|,êªO#+I˜*jJ)zŽ?9tèb¦òvPZZ*IÀ ¡ñM¤¤;âs}<¦xµŠ¢:ÆBþî,èå¶°gVÎWÜ–øÚ¼°"zÖiãbvÞñpíÞ¿°ÉŒxåÉcY¹\¿+IÕë÷2›Ô(RcX…muéhœ½¿Ó§ÜÄ4'›‘Á­„9Þ8_~¥?g‹Â§;½ðýÍqþo;iß³#sZœŸ¿j^ζ`pÿîØ¾[ù®åÿSºËçg;ÎÙÙ—C×µ‚Åå’Ë;½´½Øóôºmmå"«^òxré­ÖOv{hWß¡_¾Í¸ÛŽò7]üäõôþÖîº_‰š_Oòúä²$\ëå&ä7âÚ›‚ûkG +{cÝF2‘Ùaë8÷6Êãñ«óVsjÝ®¯.ÞqB~—ˆŠ72ýs‡?OD·êÒ!ñïZa²Rp•­ ¦vÑíoíVxuÕR­¹û‹Â/¢ØƒÑÜ]}²&,W" ÄApÑ™¿Ü§Ú§¿W}=õ‡S™¸Ç#©×£q´0[[9šš»ª=˜[o+‡+/?„ xõlæ‚÷T)Üžü὞^µ³P—ŽßV;Ýí’ËÓ+ß7ßEDymñézüX8~‰ä3âÓê©ºŽ³ÖR~~ÍoˆHâ |†+¦½Ë‡avõé,û¼rXÿMÛyú4W\4JíU½°~·rx˜Ûâ?—g¿-šõ_g“'?ëÖÊËúÌ{s¾aþ½ü}Ü>˜Ý)ªg™ÿw•ÝÆµßöϵåÅ}WÈÁïãiNÎi§ífí׎íö<ÊæòûÏæµ11{rи-Í—W7¿Š™\ÇO¬|ÕþdËwÍüëÌøÊîÅVcµ<77Ëžûõœûªm¿íž}Ënac¡¹²¸jäÞôúÆmq¿ögaq¶·‰™\(cøÙ¢÷-ä­ÖSíng©¶S9+6¯ò—§ìcî.’ÖÒóÌÒ”ç§V€ßÖ|Ÿ\–W¾*S«ë‡…«°ÖhæïV}³8Màµõ#—¬,?ùmï¦þóOk¢ë@Ÿ§¾ÛÚêc>¿ßlXû-z|¦Ðœ),ΙÇåñæÕNÎî;*úç±ï‘^žÒ¶érè²KHxTZy!fç+,à;QýàÍy„¤xÑ Ðiù^€®S›Æ[Þ‘;ú÷z½Àá(dÍñŸôOëµâÈñåìOGXרí´WâsPýsòY †J³EVFêä\c38»ƒÎâ·-ß&ã‹#Ç%â‹ç±Pô…ò8j¸Xãó™‡ |ÔÒ…yßådðÍãõÚÕãÊ[¬Í@þ¦, KT$)ouQ¾Êܦìç?—gÛGâÃÉ÷ÆMõz +ÁUÄ+—›WÇ­…•—›ë+ö·Ú+³úýôg{>Q¯^7̕Úöƒ€ñÆúÓÞÛÜÿÓáÊ“:Ï›ÛæK¯×®Gîß +wn2·²D‚D¸UWþo1cj¶X®~J¯"$áóL‹•v34:>>”Ï©laþ›–-W§‘ØQ§µLÖ­j¶TX^Fëf¶¸?þ ëû†/–²åõ.[Ú9YÏμO|à4Zna7¥ç¹sóò²Ã¿{¯½°åÁ›\úý{Q„J„Zª^Dv¥|¥*B ÷×—yçÓßûçL[¹Ï4ÿ9›‡lXñ BlkN¿Žf?;Q” ©wòܰ%Eؽt'evwGDæ~¯t¾Ø•»_\8Ù +k =xáy­Vr¥,\¸Ç^Û¨ Â4£¬žœ3,-ØøûE_|çøx!iØ½Ø º ÑüoÂîÅnä”Ù? »÷ú]ÿ&ì^ìÝ3¹vïÝ;øvï݉ÇþYؽtÏüð{/è ó¯Âî½ ;ñØ? »÷‚î1ÿYؽt÷¦]Ž6ì^û¹öýdöçîkžµØÎæjáé7'ë« ©r8wºý²¸öt|r¾²ndoŠ®l1'™kÚÑ*+ß›[è Â½W缜< +ÅCÂꢳ]òg|oª«KÚñ_™æ·Ó9¢L|€ïšødìþ…ZZ/õ¢õˆCÂó±^áTSÀ©ŠS:‚è$ÊÖ«!….ëü^Z·^eªóªÊ%é媋ðfœØz-wÓ3ü¶JNë‘ ´»UíÁ@ÎÙ–$ýfk)À€¼Î߻ ÐÁ¿áUq ò0\8BT˜É…âÂ8TÏ•BD¼Ü¼c!¸rß‘bù±PýÛs‰²q+Ã~'ýQô:¹‹ù¥W祊·‹‡Å£Ë™F'.Ú> +ÙO¸Cö§Ê¦'±[$–ÎïöºØïïâËÓÅúÔºÒñé@DœœÒ7¯ï&TZ/â;Öj·•ؽtðëCœ:C§>«-•Ðç"çü,ȉÒgÈõÜó÷n¸¼.‡M.Ï䂿ár~‡y@¬8A¤X ‹ÄQ›—.¿ Ÿ¯Dºÿ\¶`ö•. ózòù\D,§ZzÇ¿tŠ Ê²ªN¼c½¯wSê12È÷íGöïÎ8]y¼$,qñg­RFxçg"¡^xGÏÝ‘E-ïròq÷ÅÛÅ(?•Ÿ_Ë=ƒÛåäõdØÚr¼¶\t9y]#¯5{ÎÒ ¾ÊîõíªãÛXÛ•D•ð¼q÷ÅÛ9?úˆ»/ Úå±ÑFÜ}ý¼²sw_¼=“û'w_¼=óo"î¾x{&÷O"î¾x;|ãÿ âîc a‰<âî‹·óÙ}ÄÝoï¤øŒ8âî‹·;id£Ž¸ûâíâ5d#¸ûâíÎ+¢Fq÷ÅÛi_RFÜájM[Á”É%¨aº‚‰% GŠÛÿ·˜™#ÆÞåËÆË;–žÉå¨åàþóë è—«÷¿ÿ¼l_ÿïýGFÿ‘è?øE×ÇLÿ•Æt4nßdò›û—û1¥0¶ý’É]VW>>ën?ÿ¼¾\üïØ,šNv¶6êc³câÙKzvn,O“‘.éiúª€øý%Mð2#­ÐÿNþ‡þÙÍHcRwlyìä:#9“¡'þ—þؤ©éÆdilgìì§4v‡_ÏhºU±uC+˶U‘TE{Îè²U1mY§FŪ¦©Œ=e I¯XŠfR£¤TdÝF£©ÚÓÔ44ÚCµLj´dµbY¶AšRQLód­¢¶Š&­¢Ê†6ö=§WÍF›QQucÌ¢)X–b•I­h¦lŽýoƖ劬È4CÅ´*ŠAs}¢Fƒú“h†ªiTdÓÂdlš—mÈÔ¡&ÉU¥qi2Ô§")ôs&#«ª…FÓ®X},kÍA¿Ö*ŠŠ¥h¦T¡5èN£©êÜhT$I]JSQˆºjT ꂟ4iI+ªT‘hI•°† ÕÎÒ\¾SÁ4ÁŸãŒ +‘ÅsPšÛ<ģªC»Ù¼Ñ!:,C\jC%åeา™HìHãê€Å@ïl´ÔªØ0 z™·„t%+ ŒmÒ×Ü;LeCŒObÁ¤å“ˆRx]Pˆ¶oÁ&d}¦]Ñà &“( Aa°¯ÃR!²¡wŒÿ©+á5‘5 ä7I1 @Vwì˜î$éDÂö;O¿P5xf€p·-frŠÏ¸žL Ô¤ûÐDX…`ŽÆƒå™˜ŠlYI«…H2¶T-Þ¸:lqLဠT§’u¯)¼zÖx6œXC H™öÊ2¨gì$;Ê2É8cPÆpr˜¬iÙº +P 1/™Ðä2˜Ê"! Á*q-q£ÉÐ*Yçc³—”FPQCÏ™‚b4cr`'°„Ô%ÉYP1*¦ ~'»Ç^bë‹+ »Œ‡`ÍgpžÙÇDˆKH7…p"ë +GÄšNW ‡ÄŽâ9ØQ¼8ò,&Mã¾À£ðé +@¯ÁÒB“À :lw ì¨Î1!ô©ÀÁFPƒ4ÉTZ7A†  k^ÂäU @`D¢Ã‹¯ +ÍÂÐ…6Ya‡07$%4€ØwœWMR ÅáPÁÔ°dgi´)Åí +¨M2;@y´€ …iìß ý¥Úˆ¤ÎÀµ6š 0².°ë é\àÇ$á™ýn 0™ÜY8t°Ì¸XÃ~Ûlî’Zƒþn#ýÜÂR„ƒÖÁ4ÐlöP‘Ž£P@À|‡¤€5é`ÒÇŸÒùx§ÛDC§_³LÏs&ޙә‚Í&dHDQÅ  +fTc.7Y,E8Ž`’®˜b –ezš:K¥A]$$R½Ð¼d(A•Àƒƒ€ù’n»šny©,À\Ϲ¨Ùé­ŸÀ·=©TbkŠƒcleÏìA¥•ËÂæØGPpšÄþ2êZRœF@Fê¤í5CØ\t +.(€ ¦åøø„­‹#Bò@vdP—‘&F6sT¦ ÂhŒ uxX,Y4Zl\¹‹lµ‘ÊPÙg(ÁRÔ@Ò l]GÇÍlÊl7Áø2  Åv|Ù¦¸®©ÄQÂN• a—>·Üjèº%@šA(†ñ-[-,¡HÿQúPÙO.à±9È蔥" HEñÄàP3Ø) ÊÝF’¬*ÄÊ!MøBI±±¾VʱËÖúSôÁº¢#ò»f-,ä75UY´ ¥¬Zoèø`€GuÓ1²mÃv?‰F Ôƒÿ +…¥ Sa@ѸÈB¥Â} +­Àf“c ä#ÅŽá3y6ÀÛ´‰ó0ZLì(<º  + +K%x¥ÀG¦-ºUA=f…‡%¢Y`´`š¬Ë!X—„Q!Ã8³öjÀ[)ík³CF“®1b ©’f78X‡DvT+:ÇÝM´K$Ax@j”D¼ ^’üa©t4;ª 6m±ÑÐÒk°' ÌÖqu0ŸãdX’Ñý›¸ˆ ^᳑e6tá^‘™èìÆ/ (6V*£Y†Š€ìh4„«šE†)Îzÿä¶;'Ö~8F’d«ŽÆwŒè R§Ü©*Œ6*lro l ³ƒøpí6+-&žÔaeŠ9q(HNe¹»c’¦ ³Ž%†pN1¸fo„%@CÀØÔxÏ *{!5ñS,Tƒ—Y&þ—%T‚8&$ ä• ÷•m°íÅ1 æ·Ì¶3ûÄ 2&L°“¡¬/oŸY®Ê’™N‡LÆÉ7Ø:E_%Á‡=€› ¨H‡§ž{œMh +61,…#;24»ec’Pã¡aF!ˤlº—ñc‰BÖ³UaPÞfHÏ9zÄ€?þà—s$Ó ’Õ8†ü 2¸lÀ„áCøúðK’t&å1 Þ?…³!`•Úh:Ñ ÑBö&6 A!&/5j"Øf]ó,€ PÌâŒPÌbŠœIÊ5 Ëa¡)0 €NËáF[î 'ýølf$¤lg, ®#èk¨$p*ƶŽ‹ ðl±ÍhÁT09u…—džùY‡DÔEwðN±'Z—e‘é#ºãÀ'Y¸,â,“Ã6ºð¬m%Ñt±`n¤“FRD&œ%Ž”ðóÙ4Ýb5jÃwckü  —9ZœÌ§ËVÔŒ4ºdL@Р#^mI'Ûœ>DøÂþ(IáöúÜâÌLZ>dG ¤!Éb± +Ž A +د&{|`qfvL/N"~æ\‰Ez)CãjZ—±;âÙDôg†½BÜ!©<’oSh!cÙˆ:h ®XÞ=ƒN‡ c€v‹fÍܤÓÎX¼h]iðâsÜ”ÿ‚q*ƒ… t˜ðšÊîdÇÏF@pòŽ:ðÊȶx’XQ¸üdüMÔ•ƒÇœ½ÝÛÉ9ÔF³âh<{¶-‘4¡Áø1ÙÙH2€]4ð‚ªlGrÐÔ ~eŽæ²n ‹±¢0$@PÎäêœN `Sf½DRßñzËHò B|”ô1¬Z¶RøŠL7²ta*Ññ†Udò¯U' ‘M‘‡& È©½sp©Ž”-a Ò|TVj|&&¤pb‰mƒúR GYí›2‡W5 Á¥2ˆm +¡#öÚÚˆñÒO4ÄÕU¤ À-'@›ð&–ággÏ-í L^0¯Ê,KÒ n5€sÊ C„ƒ,ñQF O5àfFÆdC:{çˆJì ì&v$µØl€ÆÚO$ÖL ŒY±i U@v*ëžüÇÖ+ç¹v¡Ãe +û7H¡ ?D$wÐd"Õƒš8’Æf¤n‰Ä ’)Èû@ìMá¬!¡ð ÊìT ƒ# 9&¡ÿ[¶À…{EfœÂ‘<:FRÀ ÅÑ;–§ô]%lhñúm0jØ¡–ÎálöQë#D­Ã„¥ih€«e4’ŠÄÍšk"d‚:â5+::IX»*5ÃAÁ[Άã<$Z²tÖÁެ½¡öhµp¥ãì‹Ì@42CùÇÐä*/ºNÄÉ9MQ×4E!_±‹&§˜h8èpN`#4…q;²Žˆ!…$›§ÃÙA¤¥ž¹”!Ky}=BÏe6‘Y·,Û8{¶¬#Šw…S™@ìn“ÿ»ªq”@˜÷–h€ÜÈ $,qÐdÒ +9<: :kX£BDpȱMÒ×\GÓ³_"?…ýH-è‡ü$‚¥¡—!9Ï4€÷ç)%Òã}ì¤&¤û²_¾7S…­D'¹¤$ +WÓ´íš@e®ç ¼9ËHQ„ H‡ŠyºÛDt³,½ç°pöt;3ؼãÌ".{Áo3†jàÚbe6b.m‹t§%²ïÜ™4:l6k€÷Ȉ6Ý#YèP×Ù™G‚Á têHL‘u¡m¤ÛòÏIÉ ˜¥Cbh†“`ã@¹€”ßí ä`ÑÈ,J†ØÃb«R»i iú˜³¼DÔ ÙDH·åÜ9ƒs…àøBH“.}%òÃ?õ-£ Ъlh@ÛHjWÔN¢ +?•ìÍJsšn øÈ"ƒÖõlf†=ØBüc&䀱,îè—¤äDÖ‘†x²"rÁ,ÆHNR€ô‘l'©š³G2 ‘”GàH²D¢žŽˆsY˜&AË´d„$9/ûÏÂyåh'ú"ìAétè‘Ó‹hÆÙxøP³è ‘Ѝ‹ÆF4X _j'í„@…TŸEØÐ6ÌÕr²ÌHù™°I±ÐËrNì"„ÜÙ+Ž=2žÈ¨BÂGáÙ!|`w2Í,¯-!Ñl‘[ÿÌø•3žYòqF™–ÄÀ’£Šyÿ1ä7Xi 4÷cC+$6Xð*Â6Õ8 e –½T†J“Å¡·ˆ(,ðHÖ;]ÀôI$|_Ô”Ž”^‰DiÏ9[ ¿ ¹¯³M§KK*Gîe KÊd™Ø¹³ð¥!Lµ%¡jaIIŽÅ…$nER`#:6 5Ñ‚ ÕâþdáÙ¤qèê×??LèN6Ø_µyÚpÀÚNôß Ã†ËĦ²³OµaØ!‹U–Øk©#áR¶¨ÊF +²"MÕd"êpú)‰«ó¦€ˆ2{k‘•È‚½1*h÷€Ù!ÿM‡BT9ÿɼ´À!ÏdŒq ±m̘®Úb¥Ô£)=Éq80$Xqp¨Ñ1$9ŽàªÄ˜Q C2.‹Ã#j„äIÞC0+Nv;"ÿcÍ/ üõT‚héh€Ä$Ó õ& 7,áñT9‡X5y-|æMŒ@¹r¢ I9ÊŒ9ªð±­w`ë\D ØC— Hÿ LG( ΀1%*äÐ(d‹¦J⤱-¯ãøjÈ8«:ò +,†‘:›ZlJ@&±‹‡?Ý?ˆÛâ> endobj xref 0 27 0000000000 65535 f +0000000016 00000 n +0000000156 00000 n +0000048791 00000 n +0000000000 00000 f +0000055920 00000 n +0000055990 00000 n +0000139587 00000 n +0000048842 00000 n +0000049216 00000 n +0000059088 00000 n +0000056405 00000 n +0000056292 00000 n +0000054762 00000 n +0000055359 00000 n +0000055407 00000 n +0000056176 00000 n +0000056207 00000 n +0000056060 00000 n +0000056091 00000 n +0000056440 00000 n +0000059162 00000 n +0000059358 00000 n +0000060338 00000 n +0000068419 00000 n +0000134007 00000 n +0000139616 00000 n +trailer <<6C961835BB254CBB9A3B8EA3C06F5B33>]>> startxref 139797 %%EOF \ No newline at end of file diff --git a/gulliver/js/codemirror/css/csscolors.css b/gulliver/js/codemirror/css/csscolors.css new file mode 100755 index 000000000..cd4b79e3c --- /dev/null +++ b/gulliver/js/codemirror/css/csscolors.css @@ -0,0 +1,55 @@ +html { + cursor: text; +} + +.editbox { + margin: .4em; + padding: 0; + font-family: monospace; + font-size: 10pt; + color: black; +} + +pre.code, .editbox { + color: #666; +} + +.editbox p { + margin: 0; +} + +span.css-at { + color: #708; +} + +span.css-unit { + color: #281; +} + +span.css-value { + color: #708; +} + +span.css-identifier { + color: black; +} + +span.css-selector { + color: #11B; +} + +span.css-important { + color: #00F; +} + +span.css-colorcode { + color: #299; +} + +span.css-comment { + color: #A70; +} + +span.css-string { + color: #A22; +} diff --git a/gulliver/js/codemirror/css/docs.css b/gulliver/js/codemirror/css/docs.css new file mode 100755 index 000000000..dbe1e0828 --- /dev/null +++ b/gulliver/js/codemirror/css/docs.css @@ -0,0 +1,158 @@ +body { + font-family: Arial, sans-serif; + line-height: 1.5; + max-width: 64.3em; + margin: 3em auto; + padding: 0 1em; +} +body.droid { + font-family: Droid Sans, Arial, sans-serif; +} + +h1 { + letter-spacing: -3px; + font-size: 3.23em; + font-weight: bold; + margin: 0; +} + +h2 { + font-size: 1.23em; + font-weight: bold; + margin: .5em 0; + letter-spacing: -1px; +} + +h3 { + font-size: 1em; + font-weight: bold; + margin: .4em 0; +} + +pre { + font-family: Courier New, monospaced; + background-color: #eee; + -moz-border-radius: 6px; + -webkit-border-radius: 6px; + border-radius: 6px; + padding: 1em; +} + +pre.code { + margin: 0 1em; +} + +.grey { + font-size: 2em; + padding: .5em 1em; + line-height: 1.2em; + margin-top: .5em; + position: relative; +} + +img.logo { + position: absolute; + right: -25px; + bottom: 4px; +} + +a:link, a:visited, .quasilink { + color: #df0019; + cursor: pointer; + text-decoration: none; +} + +a:hover, .quasilink:hover { + color: #800004; +} + +h1 a:link, h1 a:visited, h1 a:hover { + color: black; +} + +ul { + margin: 0; + padding-left: 1.2em; +} + +a.download { + color: white; + background-color: #df0019; + width: 100%; + display: block; + text-align: center; + font-size: 1.23em; + font-weight: bold; + text-decoration: none; + -moz-border-radius: 6px; + -webkit-border-radius: 6px; + border-radius: 6px; + padding: .5em 0; + margin-bottom: 1em; +} + +a.download:hover { + background-color: #bb0010; +} + +.rel { + margin-bottom: 0; +} + +.rel-note { + color: #777; + font-size: .9em; + margin-top: .1em; +} + +.logo-braces { + color: #df0019; + position: relative; + top: -4px; +} + +.blk { + float: left; +} + +.left { + width: 37em; + padding-right: 6.53em; + padding-bottom: 1em; +} + +.left1 { + width: 15.24em; + padding-right: 6.45em; +} + +.left2 { + width: 15.24em; +} + +.right { + width: 20.68em; +} + +.leftbig { + width: 42.44em; + padding-right: 6.53em; +} + +.rightsmall { + width: 15.24em; +} + +.clear:after { + visibility: hidden; + display: block; + font-size: 0; + content: " "; + clear: both; + height: 0; +} +.clear { display: inline-block; } +/* start commented backslash hack \*/ +* html .clear { height: 1%; } +.clear { display: block; } +/* close commented backslash hack */ diff --git a/gulliver/js/codemirror/css/font.js b/gulliver/js/codemirror/css/font.js new file mode 100755 index 000000000..9e913b14f --- /dev/null +++ b/gulliver/js/codemirror/css/font.js @@ -0,0 +1,15 @@ +function waitForStyles() { + for (var i = 0; i < document.styleSheets.length; i++) + if (/googleapis/.test(document.styleSheets[i].href)) + return document.body.className += " droid"; + setTimeout(waitForStyles, 100); +} +setTimeout(function() { + if (/AppleWebKit/.test(navigator.userAgent) && /iP[oa]d|iPhone/.test(navigator.userAgent)) return; + var link = document.createElement("LINK"); + link.type = "text/css"; + link.rel = "stylesheet"; + link.href = "http://fonts.googleapis.com/css?family=Droid+Sans|Droid+Sans:bold"; + document.documentElement.getElementsByTagName("HEAD")[0].appendChild(link); + waitForStyles(); +}, 20); diff --git a/gulliver/js/codemirror/css/jscolors.css b/gulliver/js/codemirror/css/jscolors.css new file mode 100755 index 000000000..7c65d7df4 --- /dev/null +++ b/gulliver/js/codemirror/css/jscolors.css @@ -0,0 +1,59 @@ +html { + cursor: text; +} + +.editbox { + margin: .4em; + padding: 0; + font-family: monospace; + font-size: 10pt; + color: black; +} + +pre.code, .editbox { + color: #666666; +} + +.editbox p { + margin: 0; +} + +span.js-punctuation { + color: #666666; +} + +span.js-operator { + color: #666666; +} + +span.js-keyword { + color: #770088; +} + +span.js-atom { + color: #228811; +} + +span.js-variable { + color: black; +} + +span.js-variabledef { + color: #0000FF; +} + +span.js-localvariable { + color: #004499; +} + +span.js-property { + color: black; +} + +span.js-comment { + color: #AA7700; +} + +span.js-string { + color: #AA2222; +} diff --git a/gulliver/js/codemirror/css/people.jpg b/gulliver/js/codemirror/css/people.jpg new file mode 100755 index 000000000..734789542 Binary files /dev/null and b/gulliver/js/codemirror/css/people.jpg differ diff --git a/gulliver/js/codemirror/css/sparqlcolors.css b/gulliver/js/codemirror/css/sparqlcolors.css new file mode 100755 index 000000000..13a24fd1e --- /dev/null +++ b/gulliver/js/codemirror/css/sparqlcolors.css @@ -0,0 +1,43 @@ +html { + cursor: text; +} + +.editbox { + margin: .4em; + padding: 0; + font-family: monospace; + font-size: 10pt; + color: black; +} + +.editbox p { + margin: 0; +} + +span.sp-keyword { + color: #708; +} + +span.sp-prefixed { + color: #5d1; +} + +span.sp-var { + color: #00c; +} + +span.sp-comment { + color: #a70; +} + +span.sp-literal { + color: #a22; +} + +span.sp-uri { + color: #292; +} + +span.sp-operator { + color: #088; +} diff --git a/gulliver/js/codemirror/css/xmlcolors.css b/gulliver/js/codemirror/css/xmlcolors.css new file mode 100755 index 000000000..65477a94b --- /dev/null +++ b/gulliver/js/codemirror/css/xmlcolors.css @@ -0,0 +1,55 @@ +html { + cursor: text; +} + +.editbox { + margin: .4em; + padding: 0; + font-family: monospace; + font-size: 10pt; + color: black; +} + +.editbox p { + margin: 0; +} + +span.xml-tagname { + color: #A0B; +} + +span.xml-attribute { + color: #281; +} + +span.xml-punctuation { + color: black; +} + +span.xml-attname { + color: #00F; +} + +span.xml-comment { + color: #A70; +} + +span.xml-cdata { + color: #48A; +} + +span.xml-processing { + color: #999; +} + +span.xml-entity { + color: #A22; +} + +span.xml-error { + color: #F00 !important; +} + +span.xml-text { + color: black; +} diff --git a/gulliver/js/codemirror/js/codemirror.js b/gulliver/js/codemirror/js/codemirror.js new file mode 100755 index 000000000..cdc77533a --- /dev/null +++ b/gulliver/js/codemirror/js/codemirror.js @@ -0,0 +1,582 @@ +/* CodeMirror main module (http://codemirror.net/) + * + * Implements the CodeMirror constructor and prototype, which take care + * of initializing the editor frame, and providing the outside interface. + */ + +// The CodeMirrorConfig object is used to specify a default +// configuration. If you specify such an object before loading this +// file, the values you put into it will override the defaults given +// below. You can also assign to it after loading. +var CodeMirrorConfig = window.CodeMirrorConfig || {}; + +var CodeMirror = (function(){ + function setDefaults(object, defaults) { + for (var option in defaults) { + if (!object.hasOwnProperty(option)) + object[option] = defaults[option]; + } + } + function forEach(array, action) { + for (var i = 0; i < array.length; i++) + action(array[i]); + } + function createHTMLElement(el) { + if (document.createElementNS && document.documentElement.namespaceURI !== null) + return document.createElementNS("http://www.w3.org/1999/xhtml", el) + else + return document.createElement(el) + } + + // These default options can be overridden by passing a set of + // options to a specific CodeMirror constructor. See manual.html for + // their meaning. + setDefaults(CodeMirrorConfig, { + stylesheet: [], + path: "", + parserfile: [], + basefiles: ["util.js", "stringstream.js", "select.js", "undo.js", "editor.js", "tokenize.js"], + iframeClass: null, + passDelay: 200, + passTime: 50, + lineNumberDelay: 200, + lineNumberTime: 50, + continuousScanning: false, + saveFunction: null, + onLoad: null, + onChange: null, + undoDepth: 50, + undoDelay: 800, + disableSpellcheck: true, + textWrapping: true, + readOnly: false, + width: "", + height: "300px", + minHeight: 100, + autoMatchParens: false, + markParen: null, + unmarkParen: null, + parserConfig: null, + tabMode: "indent", // or "spaces", "default", "shift" + enterMode: "indent", // or "keep", "flat" + electricChars: true, + reindentOnLoad: false, + activeTokens: null, + onCursorActivity: null, + lineNumbers: false, + firstLineNumber: 1, + onLineNumberClick: null, + indentUnit: 2, + domain: null, + noScriptCaching: false, + incrementalLoading: false + }); + + function addLineNumberDiv(container, firstNum) { + var nums = createHTMLElement("div"), + scroller = createHTMLElement("div"); + nums.style.position = "absolute"; + nums.style.height = "100%"; + if (nums.style.setExpression) { + try {nums.style.setExpression("height", "this.previousSibling.offsetHeight + 'px'");} + catch(e) {} // Seems to throw 'Not Implemented' on some IE8 versions + } + nums.style.top = "0px"; + nums.style.left = "0px"; + nums.style.overflow = "hidden"; + container.appendChild(nums); + scroller.className = "CodeMirror-line-numbers"; + nums.appendChild(scroller); + scroller.innerHTML = "
" + firstNum + "
"; + return nums; + } + + function frameHTML(options) { + if (typeof options.parserfile == "string") + options.parserfile = [options.parserfile]; + if (typeof options.basefiles == "string") + options.basefiles = [options.basefiles]; + if (typeof options.stylesheet == "string") + options.stylesheet = [options.stylesheet]; + + var html = [""]; + // Hack to work around a bunch of IE8-specific problems. + html.push(""); + var queryStr = options.noScriptCaching ? "?nocache=" + new Date().getTime().toString(16) : ""; + forEach(options.stylesheet, function(file) { + html.push(""); + }); + forEach(options.basefiles.concat(options.parserfile), function(file) { + if (!/^https?:/.test(file)) file = options.path + file; + html.push(" "; - } \ No newline at end of file + } diff --git a/workflow/engine/xmlform/dynaforms/dynaforms_XmlEditor.html b/workflow/engine/xmlform/dynaforms/dynaforms_XmlEditor.html new file mode 100755 index 000000000..506376219 --- /dev/null +++ b/workflow/engine/xmlform/dynaforms/dynaforms_XmlEditor.html @@ -0,0 +1,22 @@ +
+
+ + + + +
+ + + + + + +
{$form.XML}
+
+
+
+ +
+ diff --git a/workflow/engine/xmlform/dynaforms/dynaforms_XmlEditor.xml b/workflow/engine/xmlform/dynaforms/dynaforms_XmlEditor.xml index 440b6243e..abe89f60a 100644 --- a/workflow/engine/xmlform/dynaforms/dynaforms_XmlEditor.xml +++ b/workflow/engine/xmlform/dynaforms/dynaforms_XmlEditor.xml @@ -1,5 +1,5 @@ - + @@ -7,7 +7,7 @@ XML - \ No newline at end of file + diff --git a/workflow/public_html/skins/green/style.css b/workflow/public_html/skins/green/style.css index 3758baa0d..4d0c1fc74 100644 --- a/workflow/public_html/skins/green/style.css +++ b/workflow/public_html/skins/green/style.css @@ -3125,3 +3125,15 @@ button.x-btn-text:focus,.x-combo-selected{ outline:none; } +.CodeMirror-line-numbers { + width: 2.2em; + color: #aaa; + background-color: #eee; + text-align: right; + padding-right: .3em; + font-size: 10pt; + font-family: monospace; + padding-top: .4em; + line-height: normal; +} + diff --git a/workflow/public_html/sysGeneric.php b/workflow/public_html/sysGeneric.php index 313265bbe..90a66e9a4 100644 --- a/workflow/public_html/sysGeneric.php +++ b/workflow/public_html/sysGeneric.php @@ -137,7 +137,7 @@ $startingTime = array_sum(explode(' ',microtime())); $virtualURITable['/controls/(*)'] = PATH_GULLIVER_HOME . 'methods/controls/'; $virtualURITable['/html2ps_pdf/(*)'] = PATH_THIRDPARTY . 'html2ps_pdf/'; $virtualURITable['/Krumo/(*)'] = PATH_THIRDPARTY . 'krumo/'; - $virtualURITable['/codepress/(*)'] = PATH_THIRDPARTY . 'codepress/'; +// $virtualURITable['/codepress/(*)'] = PATH_THIRDPARTY . 'codepress/'; $virtualURITable['/images/'] = 'errorFile'; $virtualURITable['/skins/'] = 'errorFile'; $virtualURITable['/files/'] = 'errorFile';