File manager - Edit - /home/newsbmcs.com/public_html/static/img/logo/edit.zip
Back
PK �\�Z�-� � global_events.jsnu �[��� import { onBlur } from "../display/focus.js" import { on } from "../util/event.js" // These must be handled carefully, because naively registering a // handler for each editor will cause the editors to never be // garbage collected. function forEachCodeMirror(f) { if (!document.getElementsByClassName) return let byClass = document.getElementsByClassName("CodeMirror"), editors = [] for (let i = 0; i < byClass.length; i++) { let cm = byClass[i].CodeMirror if (cm) editors.push(cm) } if (editors.length) editors[0].operation(() => { for (let i = 0; i < editors.length; i++) f(editors[i]) }) } let globalsRegistered = false export function ensureGlobalHandlers() { if (globalsRegistered) return registerGlobalHandlers() globalsRegistered = true } function registerGlobalHandlers() { // When the window resizes, we need to refresh active editors. let resizeTimer on(window, "resize", () => { if (resizeTimer == null) resizeTimer = setTimeout(() => { resizeTimer = null forEachCodeMirror(onResize) }, 100) }) // When the window loses focus, we want to show the editor as blurred on(window, "blur", () => forEachCodeMirror(onBlur)) } // Called when the window resizes function onResize(cm) { let d = cm.display // Might be a text scaling operation, clear size caches. d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null d.scrollbarsClipped = false cm.setSize() } PK �\�Zn��A A options.jsnu �[��� import { onBlur } from "../display/focus.js" import { getGutters, updateGutters } from "../display/gutters.js" import { loadMode, resetModeState } from "../display/mode_state.js" import { initScrollbars, updateScrollbars } from "../display/scrollbars.js" import { updateSelection } from "../display/selection.js" import { regChange } from "../display/view_tracking.js" import { getKeyMap } from "../input/keymap.js" import { defaultSpecialCharPlaceholder } from "../line/line_data.js" import { Pos } from "../line/pos.js" import { findMaxLine } from "../line/spans.js" import { clearCaches, compensateForHScroll, estimateLineHeights } from "../measurement/position_measurement.js" import { replaceRange } from "../model/changes.js" import { mobile, windows } from "../util/browser.js" import { addClass, rmClass } from "../util/dom.js" import { off, on } from "../util/event.js" import { themeChanged } from "./utils.js" export let Init = {toString: function(){return "CodeMirror.Init"}} export let defaults = {} export let optionHandlers = {} export function defineOptions(CodeMirror) { let optionHandlers = CodeMirror.optionHandlers function option(name, deflt, handle, notOnInit) { CodeMirror.defaults[name] = deflt if (handle) optionHandlers[name] = notOnInit ? (cm, val, old) => {if (old != Init) handle(cm, val, old)} : handle } CodeMirror.defineOption = option // Passed to option handlers when there is no old value. CodeMirror.Init = Init // These two are, on init, called from the constructor because they // have to be initialized before the editor can start at all. option("value", "", (cm, val) => cm.setValue(val), true) option("mode", null, (cm, val) => { cm.doc.modeOption = val loadMode(cm) }, true) option("indentUnit", 2, loadMode, true) option("indentWithTabs", false) option("smartIndent", true) option("tabSize", 4, cm => { resetModeState(cm) clearCaches(cm) regChange(cm) }, true) option("lineSeparator", null, (cm, val) => { cm.doc.lineSep = val if (!val) return let newBreaks = [], lineNo = cm.doc.first cm.doc.iter(line => { for (let pos = 0;;) { let found = line.text.indexOf(val, pos) if (found == -1) break pos = found + val.length newBreaks.push(Pos(lineNo, found)) } lineNo++ }) for (let i = newBreaks.length - 1; i >= 0; i--) replaceRange(cm.doc, val, newBreaks[i], Pos(newBreaks[i].line, newBreaks[i].ch + val.length)) }) option("specialChars", /[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b-\u200c\u200e\u200f\u2028\u2029\ufeff\ufff9-\ufffc]/g, (cm, val, old) => { cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g") if (old != Init) cm.refresh() }) option("specialCharPlaceholder", defaultSpecialCharPlaceholder, cm => cm.refresh(), true) option("electricChars", true) option("inputStyle", mobile ? "contenteditable" : "textarea", () => { throw new Error("inputStyle can not (yet) be changed in a running editor") // FIXME }, true) option("spellcheck", false, (cm, val) => cm.getInputField().spellcheck = val, true) option("autocorrect", false, (cm, val) => cm.getInputField().autocorrect = val, true) option("autocapitalize", false, (cm, val) => cm.getInputField().autocapitalize = val, true) option("rtlMoveVisually", !windows) option("wholeLineUpdateBefore", true) option("theme", "default", cm => { themeChanged(cm) updateGutters(cm) }, true) option("keyMap", "default", (cm, val, old) => { let next = getKeyMap(val) let prev = old != Init && getKeyMap(old) if (prev && prev.detach) prev.detach(cm, next) if (next.attach) next.attach(cm, prev || null) }) option("extraKeys", null) option("configureMouse", null) option("lineWrapping", false, wrappingChanged, true) option("gutters", [], (cm, val) => { cm.display.gutterSpecs = getGutters(val, cm.options.lineNumbers) updateGutters(cm) }, true) option("fixedGutter", true, (cm, val) => { cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0" cm.refresh() }, true) option("coverGutterNextToScrollbar", false, cm => updateScrollbars(cm), true) option("scrollbarStyle", "native", cm => { initScrollbars(cm) updateScrollbars(cm) cm.display.scrollbars.setScrollTop(cm.doc.scrollTop) cm.display.scrollbars.setScrollLeft(cm.doc.scrollLeft) }, true) option("lineNumbers", false, (cm, val) => { cm.display.gutterSpecs = getGutters(cm.options.gutters, val) updateGutters(cm) }, true) option("firstLineNumber", 1, updateGutters, true) option("lineNumberFormatter", integer => integer, updateGutters, true) option("showCursorWhenSelecting", false, updateSelection, true) option("resetSelectionOnContextMenu", true) option("lineWiseCopyCut", true) option("pasteLinesPerSelection", true) option("selectionsMayTouch", false) option("readOnly", false, (cm, val) => { if (val == "nocursor") { onBlur(cm) cm.display.input.blur() } cm.display.input.readOnlyChanged(val) }) option("screenReaderLabel", null, (cm, val) => { val = (val === '') ? null : val cm.display.input.screenReaderLabelChanged(val) }) option("disableInput", false, (cm, val) => {if (!val) cm.display.input.reset()}, true) option("dragDrop", true, dragDropChanged) option("allowDropFileTypes", null) option("cursorBlinkRate", 530) option("cursorScrollMargin", 0) option("cursorHeight", 1, updateSelection, true) option("singleCursorHeightPerLine", true, updateSelection, true) option("workTime", 100) option("workDelay", 100) option("flattenSpans", true, resetModeState, true) option("addModeClass", false, resetModeState, true) option("pollInterval", 100) option("undoDepth", 200, (cm, val) => cm.doc.history.undoDepth = val) option("historyEventDelay", 1250) option("viewportMargin", 10, cm => cm.refresh(), true) option("maxHighlightLength", 10000, resetModeState, true) option("moveInputWithCursor", true, (cm, val) => { if (!val) cm.display.input.resetPosition() }) option("tabindex", null, (cm, val) => cm.display.input.getField().tabIndex = val || "") option("autofocus", null) option("direction", "ltr", (cm, val) => cm.doc.setDirection(val), true) option("phrases", null) } function dragDropChanged(cm, value, old) { let wasOn = old && old != Init if (!value != !wasOn) { let funcs = cm.display.dragFunctions let toggle = value ? on : off toggle(cm.display.scroller, "dragstart", funcs.start) toggle(cm.display.scroller, "dragenter", funcs.enter) toggle(cm.display.scroller, "dragover", funcs.over) toggle(cm.display.scroller, "dragleave", funcs.leave) toggle(cm.display.scroller, "drop", funcs.drop) } } function wrappingChanged(cm) { if (cm.options.lineWrapping) { addClass(cm.display.wrapper, "CodeMirror-wrap") cm.display.sizer.style.minWidth = "" cm.display.sizerWidth = null } else { rmClass(cm.display.wrapper, "CodeMirror-wrap") findMaxLine(cm) } estimateLineHeights(cm) regChange(cm) clearCaches(cm) setTimeout(() => updateScrollbars(cm), 100) } PK �\�Z�����! �! CodeMirror.jsnu �[��� import { Display } from "../display/Display.js" import { onFocus, onBlur } from "../display/focus.js" import { maybeUpdateLineNumberWidth } from "../display/line_numbers.js" import { endOperation, operation, startOperation } from "../display/operations.js" import { initScrollbars } from "../display/scrollbars.js" import { onScrollWheel } from "../display/scroll_events.js" import { setScrollLeft, updateScrollTop } from "../display/scrolling.js" import { clipPos, Pos } from "../line/pos.js" import { posFromMouse } from "../measurement/position_measurement.js" import { eventInWidget } from "../measurement/widgets.js" import Doc from "../model/Doc.js" import { attachDoc } from "../model/document_data.js" import { Range } from "../model/selection.js" import { extendSelection } from "../model/selection_updates.js" import { ie, ie_version, mobile, webkit } from "../util/browser.js" import { e_preventDefault, e_stop, on, signal, signalDOMEvent } from "../util/event.js" import { copyObj, Delayed } from "../util/misc.js" import { clearDragCursor, onDragOver, onDragStart, onDrop } from "./drop_events.js" import { ensureGlobalHandlers } from "./global_events.js" import { onKeyDown, onKeyPress, onKeyUp } from "./key_events.js" import { clickInGutter, onContextMenu, onMouseDown } from "./mouse_events.js" import { themeChanged } from "./utils.js" import { defaults, optionHandlers, Init } from "./options.js" // A CodeMirror instance represents an editor. This is the object // that user code is usually dealing with. export function CodeMirror(place, options) { if (!(this instanceof CodeMirror)) return new CodeMirror(place, options) this.options = options = options ? copyObj(options) : {} // Determine effective options based on given values and defaults. copyObj(defaults, options, false) let doc = options.value if (typeof doc == "string") doc = new Doc(doc, options.mode, null, options.lineSeparator, options.direction) else if (options.mode) doc.modeOption = options.mode this.doc = doc let input = new CodeMirror.inputStyles[options.inputStyle](this) let display = this.display = new Display(place, doc, input, options) display.wrapper.CodeMirror = this themeChanged(this) if (options.lineWrapping) this.display.wrapper.className += " CodeMirror-wrap" initScrollbars(this) this.state = { keyMaps: [], // stores maps added by addKeyMap overlays: [], // highlighting overlays, as added by addOverlay modeGen: 0, // bumped when mode/overlay changes, used to invalidate highlighting info overwrite: false, delayingBlurEvent: false, focused: false, suppressEdits: false, // used to disable editing during key handlers when in readOnly mode pasteIncoming: -1, cutIncoming: -1, // help recognize paste/cut edits in input.poll selectingText: false, draggingText: false, highlight: new Delayed(), // stores highlight worker timeout keySeq: null, // Unfinished key sequence specialChars: null } if (options.autofocus && !mobile) display.input.focus() // Override magic textarea content restore that IE sometimes does // on our hidden textarea on reload if (ie && ie_version < 11) setTimeout(() => this.display.input.reset(true), 20) registerEventHandlers(this) ensureGlobalHandlers() startOperation(this) this.curOp.forceUpdate = true attachDoc(this, doc) if ((options.autofocus && !mobile) || this.hasFocus()) setTimeout(() => { if (this.hasFocus() && !this.state.focused) onFocus(this) }, 20) else onBlur(this) for (let opt in optionHandlers) if (optionHandlers.hasOwnProperty(opt)) optionHandlers[opt](this, options[opt], Init) maybeUpdateLineNumberWidth(this) if (options.finishInit) options.finishInit(this) for (let i = 0; i < initHooks.length; ++i) initHooks[i](this) endOperation(this) // Suppress optimizelegibility in Webkit, since it breaks text // measuring on line wrapping boundaries. if (webkit && options.lineWrapping && getComputedStyle(display.lineDiv).textRendering == "optimizelegibility") display.lineDiv.style.textRendering = "auto" } // The default configuration options. CodeMirror.defaults = defaults // Functions to run when options are changed. CodeMirror.optionHandlers = optionHandlers export default CodeMirror // Attach the necessary event handlers when initializing the editor function registerEventHandlers(cm) { let d = cm.display on(d.scroller, "mousedown", operation(cm, onMouseDown)) // Older IE's will not fire a second mousedown for a double click if (ie && ie_version < 11) on(d.scroller, "dblclick", operation(cm, e => { if (signalDOMEvent(cm, e)) return let pos = posFromMouse(cm, e) if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return e_preventDefault(e) let word = cm.findWordAt(pos) extendSelection(cm.doc, word.anchor, word.head) })) else on(d.scroller, "dblclick", e => signalDOMEvent(cm, e) || e_preventDefault(e)) // Some browsers fire contextmenu *after* opening the menu, at // which point we can't mess with it anymore. Context menu is // handled in onMouseDown for these browsers. on(d.scroller, "contextmenu", e => onContextMenu(cm, e)) on(d.input.getField(), "contextmenu", e => { if (!d.scroller.contains(e.target)) onContextMenu(cm, e) }) // Used to suppress mouse event handling when a touch happens let touchFinished, prevTouch = {end: 0} function finishTouch() { if (d.activeTouch) { touchFinished = setTimeout(() => d.activeTouch = null, 1000) prevTouch = d.activeTouch prevTouch.end = +new Date } } function isMouseLikeTouchEvent(e) { if (e.touches.length != 1) return false let touch = e.touches[0] return touch.radiusX <= 1 && touch.radiusY <= 1 } function farAway(touch, other) { if (other.left == null) return true let dx = other.left - touch.left, dy = other.top - touch.top return dx * dx + dy * dy > 20 * 20 } on(d.scroller, "touchstart", e => { if (!signalDOMEvent(cm, e) && !isMouseLikeTouchEvent(e) && !clickInGutter(cm, e)) { d.input.ensurePolled() clearTimeout(touchFinished) let now = +new Date d.activeTouch = {start: now, moved: false, prev: now - prevTouch.end <= 300 ? prevTouch : null} if (e.touches.length == 1) { d.activeTouch.left = e.touches[0].pageX d.activeTouch.top = e.touches[0].pageY } } }) on(d.scroller, "touchmove", () => { if (d.activeTouch) d.activeTouch.moved = true }) on(d.scroller, "touchend", e => { let touch = d.activeTouch if (touch && !eventInWidget(d, e) && touch.left != null && !touch.moved && new Date - touch.start < 300) { let pos = cm.coordsChar(d.activeTouch, "page"), range if (!touch.prev || farAway(touch, touch.prev)) // Single tap range = new Range(pos, pos) else if (!touch.prev.prev || farAway(touch, touch.prev.prev)) // Double tap range = cm.findWordAt(pos) else // Triple tap range = new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0))) cm.setSelection(range.anchor, range.head) cm.focus() e_preventDefault(e) } finishTouch() }) on(d.scroller, "touchcancel", finishTouch) // Sync scrolling between fake scrollbars and real scrollable // area, ensure viewport is updated when scrolling. on(d.scroller, "scroll", () => { if (d.scroller.clientHeight) { updateScrollTop(cm, d.scroller.scrollTop) setScrollLeft(cm, d.scroller.scrollLeft, true) signal(cm, "scroll", cm) } }) // Listen to wheel events in order to try and update the viewport on time. on(d.scroller, "mousewheel", e => onScrollWheel(cm, e)) on(d.scroller, "DOMMouseScroll", e => onScrollWheel(cm, e)) // Prevent wrapper from ever scrolling on(d.wrapper, "scroll", () => d.wrapper.scrollTop = d.wrapper.scrollLeft = 0) d.dragFunctions = { enter: e => {if (!signalDOMEvent(cm, e)) e_stop(e)}, over: e => {if (!signalDOMEvent(cm, e)) { onDragOver(cm, e); e_stop(e) }}, start: e => onDragStart(cm, e), drop: operation(cm, onDrop), leave: e => {if (!signalDOMEvent(cm, e)) { clearDragCursor(cm) }} } let inp = d.input.getField() on(inp, "keyup", e => onKeyUp.call(cm, e)) on(inp, "keydown", operation(cm, onKeyDown)) on(inp, "keypress", operation(cm, onKeyPress)) on(inp, "focus", e => onFocus(cm, e)) on(inp, "blur", e => onBlur(cm, e)) } let initHooks = [] CodeMirror.defineInitHook = f => initHooks.push(f) PK �\�Z�� � key_events.jsnu �[��� import { signalLater } from "../util/operation_group.js" import { restartBlink } from "../display/selection.js" import { isModifierKey, keyName, lookupKey } from "../input/keymap.js" import { eventInWidget } from "../measurement/widgets.js" import { ie, ie_version, mac, presto, gecko } from "../util/browser.js" import { activeElt, addClass, rmClass } from "../util/dom.js" import { e_preventDefault, off, on, signalDOMEvent } from "../util/event.js" import { hasCopyEvent } from "../util/feature_detection.js" import { Delayed, Pass } from "../util/misc.js" import { commands } from "./commands.js" // Run a handler that was bound to a key. function doHandleBinding(cm, bound, dropShift) { if (typeof bound == "string") { bound = commands[bound] if (!bound) return false } // Ensure previous input has been read, so that the handler sees a // consistent view of the document cm.display.input.ensurePolled() let prevShift = cm.display.shift, done = false try { if (cm.isReadOnly()) cm.state.suppressEdits = true if (dropShift) cm.display.shift = false done = bound(cm) != Pass } finally { cm.display.shift = prevShift cm.state.suppressEdits = false } return done } function lookupKeyForEditor(cm, name, handle) { for (let i = 0; i < cm.state.keyMaps.length; i++) { let result = lookupKey(name, cm.state.keyMaps[i], handle, cm) if (result) return result } return (cm.options.extraKeys && lookupKey(name, cm.options.extraKeys, handle, cm)) || lookupKey(name, cm.options.keyMap, handle, cm) } // Note that, despite the name, this function is also used to check // for bound mouse clicks. let stopSeq = new Delayed export function dispatchKey(cm, name, e, handle) { let seq = cm.state.keySeq if (seq) { if (isModifierKey(name)) return "handled" if (/\'$/.test(name)) cm.state.keySeq = null else stopSeq.set(50, () => { if (cm.state.keySeq == seq) { cm.state.keySeq = null cm.display.input.reset() } }) if (dispatchKeyInner(cm, seq + " " + name, e, handle)) return true } return dispatchKeyInner(cm, name, e, handle) } function dispatchKeyInner(cm, name, e, handle) { let result = lookupKeyForEditor(cm, name, handle) if (result == "multi") cm.state.keySeq = name if (result == "handled") signalLater(cm, "keyHandled", cm, name, e) if (result == "handled" || result == "multi") { e_preventDefault(e) restartBlink(cm) } return !!result } // Handle a key from the keydown event. function handleKeyBinding(cm, e) { let name = keyName(e, true) if (!name) return false if (e.shiftKey && !cm.state.keySeq) { // First try to resolve full name (including 'Shift-'). Failing // that, see if there is a cursor-motion command (starting with // 'go') bound to the keyname without 'Shift-'. return dispatchKey(cm, "Shift-" + name, e, b => doHandleBinding(cm, b, true)) || dispatchKey(cm, name, e, b => { if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion) return doHandleBinding(cm, b) }) } else { return dispatchKey(cm, name, e, b => doHandleBinding(cm, b)) } } // Handle a key from the keypress event function handleCharBinding(cm, e, ch) { return dispatchKey(cm, "'" + ch + "'", e, b => doHandleBinding(cm, b, true)) } let lastStoppedKey = null export function onKeyDown(e) { let cm = this if (e.target && e.target != cm.display.input.getField()) return cm.curOp.focus = activeElt() if (signalDOMEvent(cm, e)) return // IE does strange things with escape. if (ie && ie_version < 11 && e.keyCode == 27) e.returnValue = false let code = e.keyCode cm.display.shift = code == 16 || e.shiftKey let handled = handleKeyBinding(cm, e) if (presto) { lastStoppedKey = handled ? code : null // Opera has no cut event... we try to at least catch the key combo if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey)) cm.replaceSelection("", null, "cut") } if (gecko && !mac && !handled && code == 46 && e.shiftKey && !e.ctrlKey && document.execCommand) document.execCommand("cut") // Turn mouse into crosshair when Alt is held on Mac. if (code == 18 && !/\bCodeMirror-crosshair\b/.test(cm.display.lineDiv.className)) showCrossHair(cm) } function showCrossHair(cm) { let lineDiv = cm.display.lineDiv addClass(lineDiv, "CodeMirror-crosshair") function up(e) { if (e.keyCode == 18 || !e.altKey) { rmClass(lineDiv, "CodeMirror-crosshair") off(document, "keyup", up) off(document, "mouseover", up) } } on(document, "keyup", up) on(document, "mouseover", up) } export function onKeyUp(e) { if (e.keyCode == 16) this.doc.sel.shift = false signalDOMEvent(this, e) } export function onKeyPress(e) { let cm = this if (e.target && e.target != cm.display.input.getField()) return if (eventInWidget(cm.display, e) || signalDOMEvent(cm, e) || e.ctrlKey && !e.altKey || mac && e.metaKey) return let keyCode = e.keyCode, charCode = e.charCode if (presto && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return} if ((presto && (!e.which || e.which < 10)) && handleKeyBinding(cm, e)) return let ch = String.fromCharCode(charCode == null ? keyCode : charCode) // Some browsers fire keypress events for backspace if (ch == "\x08") return if (handleCharBinding(cm, e, ch)) return cm.display.input.onKeyPress(e) } PK �\�Z/�� � fromTextArea.jsnu �[��� import { CodeMirror } from "./CodeMirror.js" import { activeElt } from "../util/dom.js" import { off, on } from "../util/event.js" import { copyObj } from "../util/misc.js" export function fromTextArea(textarea, options) { options = options ? copyObj(options) : {} options.value = textarea.value if (!options.tabindex && textarea.tabIndex) options.tabindex = textarea.tabIndex if (!options.placeholder && textarea.placeholder) options.placeholder = textarea.placeholder // Set autofocus to true if this textarea is focused, or if it has // autofocus and no other element is focused. if (options.autofocus == null) { let hasFocus = activeElt() options.autofocus = hasFocus == textarea || textarea.getAttribute("autofocus") != null && hasFocus == document.body } function save() {textarea.value = cm.getValue()} let realSubmit if (textarea.form) { on(textarea.form, "submit", save) // Deplorable hack to make the submit method do the right thing. if (!options.leaveSubmitMethodAlone) { let form = textarea.form realSubmit = form.submit try { let wrappedSubmit = form.submit = () => { save() form.submit = realSubmit form.submit() form.submit = wrappedSubmit } } catch(e) {} } } options.finishInit = cm => { cm.save = save cm.getTextArea = () => textarea cm.toTextArea = () => { cm.toTextArea = isNaN // Prevent this from being ran twice save() textarea.parentNode.removeChild(cm.getWrapperElement()) textarea.style.display = "" if (textarea.form) { off(textarea.form, "submit", save) if (!options.leaveSubmitMethodAlone && typeof textarea.form.submit == "function") textarea.form.submit = realSubmit } } } textarea.style.display = "none" let cm = CodeMirror(node => textarea.parentNode.insertBefore(node, textarea.nextSibling), options) return cm } PK �\�Z� utils.jsnu �[��� import { clearCaches } from "../measurement/position_measurement.js" export function themeChanged(cm) { cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") + cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-") clearCaches(cm) } PK �\�Z��˻ legacy.jsnu �[��� import { scrollbarModel } from "../display/scrollbars.js" import { wheelEventPixels } from "../display/scroll_events.js" import { keyMap, keyName, isModifierKey, lookupKey, normalizeKeyMap } from "../input/keymap.js" import { keyNames } from "../input/keynames.js" import { Line } from "../line/line_data.js" import { cmp, Pos } from "../line/pos.js" import { changeEnd } from "../model/change_measurement.js" import Doc from "../model/Doc.js" import { LineWidget } from "../model/line_widget.js" import { SharedTextMarker, TextMarker } from "../model/mark_text.js" import { copyState, extendMode, getMode, innerMode, mimeModes, modeExtensions, modes, resolveMode, startState } from "../modes.js" import { addClass, contains, rmClass } from "../util/dom.js" import { e_preventDefault, e_stop, e_stopPropagation, off, on, signal } from "../util/event.js" import { splitLinesAuto } from "../util/feature_detection.js" import { countColumn, findColumn, isWordCharBasic, Pass } from "../util/misc.js" import StringStream from "../util/StringStream.js" import { commands } from "./commands.js" export function addLegacyProps(CodeMirror) { CodeMirror.off = off CodeMirror.on = on CodeMirror.wheelEventPixels = wheelEventPixels CodeMirror.Doc = Doc CodeMirror.splitLines = splitLinesAuto CodeMirror.countColumn = countColumn CodeMirror.findColumn = findColumn CodeMirror.isWordChar = isWordCharBasic CodeMirror.Pass = Pass CodeMirror.signal = signal CodeMirror.Line = Line CodeMirror.changeEnd = changeEnd CodeMirror.scrollbarModel = scrollbarModel CodeMirror.Pos = Pos CodeMirror.cmpPos = cmp CodeMirror.modes = modes CodeMirror.mimeModes = mimeModes CodeMirror.resolveMode = resolveMode CodeMirror.getMode = getMode CodeMirror.modeExtensions = modeExtensions CodeMirror.extendMode = extendMode CodeMirror.copyState = copyState CodeMirror.startState = startState CodeMirror.innerMode = innerMode CodeMirror.commands = commands CodeMirror.keyMap = keyMap CodeMirror.keyName = keyName CodeMirror.isModifierKey = isModifierKey CodeMirror.lookupKey = lookupKey CodeMirror.normalizeKeyMap = normalizeKeyMap CodeMirror.StringStream = StringStream CodeMirror.SharedTextMarker = SharedTextMarker CodeMirror.TextMarker = TextMarker CodeMirror.LineWidget = LineWidget CodeMirror.e_preventDefault = e_preventDefault CodeMirror.e_stopPropagation = e_stopPropagation CodeMirror.e_stop = e_stop CodeMirror.addClass = addClass CodeMirror.contains = contains CodeMirror.rmClass = rmClass CodeMirror.keyNames = keyNames } PK �\�Z��� drop_events.jsnu �[��� import { drawSelectionCursor } from "../display/selection.js" import { operation } from "../display/operations.js" import { clipPos } from "../line/pos.js" import { posFromMouse } from "../measurement/position_measurement.js" import { eventInWidget } from "../measurement/widgets.js" import { makeChange, replaceRange } from "../model/changes.js" import { changeEnd } from "../model/change_measurement.js" import { simpleSelection } from "../model/selection.js" import { setSelectionNoUndo, setSelectionReplaceHistory } from "../model/selection_updates.js" import { ie, presto, safari } from "../util/browser.js" import { elt, removeChildrenAndAdd } from "../util/dom.js" import { e_preventDefault, e_stop, signalDOMEvent } from "../util/event.js" import { indexOf } from "../util/misc.js" // Kludge to work around strange IE behavior where it'll sometimes // re-fire a series of drag-related events right after the drop (#1551) let lastDrop = 0 export function onDrop(e) { let cm = this clearDragCursor(cm) if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) return e_preventDefault(e) if (ie) lastDrop = +new Date let pos = posFromMouse(cm, e, true), files = e.dataTransfer.files if (!pos || cm.isReadOnly()) return // Might be a file drop, in which case we simply extract the text // and insert it. if (files && files.length && window.FileReader && window.File) { let n = files.length, text = Array(n), read = 0 const markAsReadAndPasteIfAllFilesAreRead = () => { if (++read == n) { operation(cm, () => { pos = clipPos(cm.doc, pos) let change = {from: pos, to: pos, text: cm.doc.splitLines( text.filter(t => t != null).join(cm.doc.lineSeparator())), origin: "paste"} makeChange(cm.doc, change) setSelectionReplaceHistory(cm.doc, simpleSelection(clipPos(cm.doc, pos), clipPos(cm.doc, changeEnd(change)))) })() } } const readTextFromFile = (file, i) => { if (cm.options.allowDropFileTypes && indexOf(cm.options.allowDropFileTypes, file.type) == -1) { markAsReadAndPasteIfAllFilesAreRead() return } let reader = new FileReader reader.onerror = () => markAsReadAndPasteIfAllFilesAreRead() reader.onload = () => { let content = reader.result if (/[\x00-\x08\x0e-\x1f]{2}/.test(content)) { markAsReadAndPasteIfAllFilesAreRead() return } text[i] = content markAsReadAndPasteIfAllFilesAreRead() } reader.readAsText(file) } for (let i = 0; i < files.length; i++) readTextFromFile(files[i], i) } else { // Normal drop // Don't do a replace if the drop happened inside of the selected text. if (cm.state.draggingText && cm.doc.sel.contains(pos) > -1) { cm.state.draggingText(e) // Ensure the editor is re-focused setTimeout(() => cm.display.input.focus(), 20) return } try { let text = e.dataTransfer.getData("Text") if (text) { let selected if (cm.state.draggingText && !cm.state.draggingText.copy) selected = cm.listSelections() setSelectionNoUndo(cm.doc, simpleSelection(pos, pos)) if (selected) for (let i = 0; i < selected.length; ++i) replaceRange(cm.doc, "", selected[i].anchor, selected[i].head, "drag") cm.replaceSelection(text, "around", "paste") cm.display.input.focus() } } catch(e){} } } export function onDragStart(cm, e) { if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return } if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) return e.dataTransfer.setData("Text", cm.getSelection()) e.dataTransfer.effectAllowed = "copyMove" // Use dummy image instead of default browsers image. // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there. if (e.dataTransfer.setDragImage && !safari) { let img = elt("img", null, null, "position: fixed; left: 0; top: 0;") img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" if (presto) { img.width = img.height = 1 cm.display.wrapper.appendChild(img) // Force a relayout, or Opera won't use our image for some obscure reason img._top = img.offsetTop } e.dataTransfer.setDragImage(img, 0, 0) if (presto) img.parentNode.removeChild(img) } } export function onDragOver(cm, e) { let pos = posFromMouse(cm, e) if (!pos) return let frag = document.createDocumentFragment() drawSelectionCursor(cm, pos, frag) if (!cm.display.dragCursor) { cm.display.dragCursor = elt("div", null, "CodeMirror-cursors CodeMirror-dragcursors") cm.display.lineSpace.insertBefore(cm.display.dragCursor, cm.display.cursorDiv) } removeChildrenAndAdd(cm.display.dragCursor, frag) } export function clearDragCursor(cm) { if (cm.display.dragCursor) { cm.display.lineSpace.removeChild(cm.display.dragCursor) cm.display.dragCursor = null } } PK �\�Z�� main.jsnu �[��� // EDITOR CONSTRUCTOR import { CodeMirror } from "./CodeMirror.js" export { CodeMirror } from "./CodeMirror.js" import { eventMixin } from "../util/event.js" import { indexOf } from "../util/misc.js" import { defineOptions } from "./options.js" defineOptions(CodeMirror) import addEditorMethods from "./methods.js" addEditorMethods(CodeMirror) import Doc from "../model/Doc.js" // Set up methods on CodeMirror's prototype to redirect to the editor's document. let dontDelegate = "iter insert remove copy getEditor constructor".split(" ") for (let prop in Doc.prototype) if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0) CodeMirror.prototype[prop] = (function(method) { return function() {return method.apply(this.doc, arguments)} })(Doc.prototype[prop]) eventMixin(Doc) // INPUT HANDLING import ContentEditableInput from "../input/ContentEditableInput.js" import TextareaInput from "../input/TextareaInput.js" CodeMirror.inputStyles = {"textarea": TextareaInput, "contenteditable": ContentEditableInput} // MODE DEFINITION AND QUERYING import { defineMIME, defineMode } from "../modes.js" // Extra arguments are stored as the mode's dependencies, which is // used by (legacy) mechanisms like loadmode.js to automatically // load a mode. (Preferred mechanism is the require/define calls.) CodeMirror.defineMode = function(name/*, mode, …*/) { if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name defineMode.apply(this, arguments) } CodeMirror.defineMIME = defineMIME // Minimal default mode. CodeMirror.defineMode("null", () => ({token: stream => stream.skipToEnd()})) CodeMirror.defineMIME("text/plain", "null") // EXTENSIONS CodeMirror.defineExtension = (name, func) => { CodeMirror.prototype[name] = func } CodeMirror.defineDocExtension = (name, func) => { Doc.prototype[name] = func } import { fromTextArea } from "./fromTextArea.js" CodeMirror.fromTextArea = fromTextArea import { addLegacyProps } from "./legacy.js" addLegacyProps(CodeMirror) CodeMirror.version = "5.58.1" PK �\�Z#K" " deleteNearSelection.jsnu �[��� import { runInOp } from "../display/operations.js" import { ensureCursorVisible } from "../display/scrolling.js" import { cmp } from "../line/pos.js" import { replaceRange } from "../model/changes.js" import { lst } from "../util/misc.js" // Helper for deleting text near the selection(s), used to implement // backspace, delete, and similar functionality. export function deleteNearSelection(cm, compute) { let ranges = cm.doc.sel.ranges, kill = [] // Build up a set of ranges to kill first, merging overlapping // ranges. for (let i = 0; i < ranges.length; i++) { let toKill = compute(ranges[i]) while (kill.length && cmp(toKill.from, lst(kill).to) <= 0) { let replaced = kill.pop() if (cmp(replaced.from, toKill.from) < 0) { toKill.from = replaced.from break } } kill.push(toKill) } // Next, remove those actual ranges. runInOp(cm, () => { for (let i = kill.length - 1; i >= 0; i--) replaceRange(cm.doc, "", kill[i].from, kill[i].to, "+delete") ensureCursorVisible(cm) }) } PK �\�Z��I�N N commands.jsnu �[��� import { deleteNearSelection } from "./deleteNearSelection.js" import { runInOp } from "../display/operations.js" import { ensureCursorVisible } from "../display/scrolling.js" import { endOfLine } from "../input/movement.js" import { clipPos, Pos } from "../line/pos.js" import { visualLine, visualLineEnd } from "../line/spans.js" import { getLine, lineNo } from "../line/utils_line.js" import { Range } from "../model/selection.js" import { selectAll } from "../model/selection_updates.js" import { countColumn, sel_dontScroll, sel_move, spaceStr } from "../util/misc.js" import { getOrder } from "../util/bidi.js" // Commands are parameter-less actions that can be performed on an // editor, mostly used for keybindings. export let commands = { selectAll: selectAll, singleSelection: cm => cm.setSelection(cm.getCursor("anchor"), cm.getCursor("head"), sel_dontScroll), killLine: cm => deleteNearSelection(cm, range => { if (range.empty()) { let len = getLine(cm.doc, range.head.line).text.length if (range.head.ch == len && range.head.line < cm.lastLine()) return {from: range.head, to: Pos(range.head.line + 1, 0)} else return {from: range.head, to: Pos(range.head.line, len)} } else { return {from: range.from(), to: range.to()} } }), deleteLine: cm => deleteNearSelection(cm, range => ({ from: Pos(range.from().line, 0), to: clipPos(cm.doc, Pos(range.to().line + 1, 0)) })), delLineLeft: cm => deleteNearSelection(cm, range => ({ from: Pos(range.from().line, 0), to: range.from() })), delWrappedLineLeft: cm => deleteNearSelection(cm, range => { let top = cm.charCoords(range.head, "div").top + 5 let leftPos = cm.coordsChar({left: 0, top: top}, "div") return {from: leftPos, to: range.from()} }), delWrappedLineRight: cm => deleteNearSelection(cm, range => { let top = cm.charCoords(range.head, "div").top + 5 let rightPos = cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div") return {from: range.from(), to: rightPos } }), undo: cm => cm.undo(), redo: cm => cm.redo(), undoSelection: cm => cm.undoSelection(), redoSelection: cm => cm.redoSelection(), goDocStart: cm => cm.extendSelection(Pos(cm.firstLine(), 0)), goDocEnd: cm => cm.extendSelection(Pos(cm.lastLine())), goLineStart: cm => cm.extendSelectionsBy(range => lineStart(cm, range.head.line), {origin: "+move", bias: 1} ), goLineStartSmart: cm => cm.extendSelectionsBy(range => lineStartSmart(cm, range.head), {origin: "+move", bias: 1} ), goLineEnd: cm => cm.extendSelectionsBy(range => lineEnd(cm, range.head.line), {origin: "+move", bias: -1} ), goLineRight: cm => cm.extendSelectionsBy(range => { let top = cm.cursorCoords(range.head, "div").top + 5 return cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div") }, sel_move), goLineLeft: cm => cm.extendSelectionsBy(range => { let top = cm.cursorCoords(range.head, "div").top + 5 return cm.coordsChar({left: 0, top: top}, "div") }, sel_move), goLineLeftSmart: cm => cm.extendSelectionsBy(range => { let top = cm.cursorCoords(range.head, "div").top + 5 let pos = cm.coordsChar({left: 0, top: top}, "div") if (pos.ch < cm.getLine(pos.line).search(/\S/)) return lineStartSmart(cm, range.head) return pos }, sel_move), goLineUp: cm => cm.moveV(-1, "line"), goLineDown: cm => cm.moveV(1, "line"), goPageUp: cm => cm.moveV(-1, "page"), goPageDown: cm => cm.moveV(1, "page"), goCharLeft: cm => cm.moveH(-1, "char"), goCharRight: cm => cm.moveH(1, "char"), goColumnLeft: cm => cm.moveH(-1, "column"), goColumnRight: cm => cm.moveH(1, "column"), goWordLeft: cm => cm.moveH(-1, "word"), goGroupRight: cm => cm.moveH(1, "group"), goGroupLeft: cm => cm.moveH(-1, "group"), goWordRight: cm => cm.moveH(1, "word"), delCharBefore: cm => cm.deleteH(-1, "codepoint"), delCharAfter: cm => cm.deleteH(1, "char"), delWordBefore: cm => cm.deleteH(-1, "word"), delWordAfter: cm => cm.deleteH(1, "word"), delGroupBefore: cm => cm.deleteH(-1, "group"), delGroupAfter: cm => cm.deleteH(1, "group"), indentAuto: cm => cm.indentSelection("smart"), indentMore: cm => cm.indentSelection("add"), indentLess: cm => cm.indentSelection("subtract"), insertTab: cm => cm.replaceSelection("\t"), insertSoftTab: cm => { let spaces = [], ranges = cm.listSelections(), tabSize = cm.options.tabSize for (let i = 0; i < ranges.length; i++) { let pos = ranges[i].from() let col = countColumn(cm.getLine(pos.line), pos.ch, tabSize) spaces.push(spaceStr(tabSize - col % tabSize)) } cm.replaceSelections(spaces) }, defaultTab: cm => { if (cm.somethingSelected()) cm.indentSelection("add") else cm.execCommand("insertTab") }, // Swap the two chars left and right of each selection's head. // Move cursor behind the two swapped characters afterwards. // // Doesn't consider line feeds a character. // Doesn't scan more than one line above to find a character. // Doesn't do anything on an empty line. // Doesn't do anything with non-empty selections. transposeChars: cm => runInOp(cm, () => { let ranges = cm.listSelections(), newSel = [] for (let i = 0; i < ranges.length; i++) { if (!ranges[i].empty()) continue let cur = ranges[i].head, line = getLine(cm.doc, cur.line).text if (line) { if (cur.ch == line.length) cur = new Pos(cur.line, cur.ch - 1) if (cur.ch > 0) { cur = new Pos(cur.line, cur.ch + 1) cm.replaceRange(line.charAt(cur.ch - 1) + line.charAt(cur.ch - 2), Pos(cur.line, cur.ch - 2), cur, "+transpose") } else if (cur.line > cm.doc.first) { let prev = getLine(cm.doc, cur.line - 1).text if (prev) { cur = new Pos(cur.line, 1) cm.replaceRange(line.charAt(0) + cm.doc.lineSeparator() + prev.charAt(prev.length - 1), Pos(cur.line - 1, prev.length - 1), cur, "+transpose") } } } newSel.push(new Range(cur, cur)) } cm.setSelections(newSel) }), newlineAndIndent: cm => runInOp(cm, () => { let sels = cm.listSelections() for (let i = sels.length - 1; i >= 0; i--) cm.replaceRange(cm.doc.lineSeparator(), sels[i].anchor, sels[i].head, "+input") sels = cm.listSelections() for (let i = 0; i < sels.length; i++) cm.indentLine(sels[i].from().line, null, true) ensureCursorVisible(cm) }), openLine: cm => cm.replaceSelection("\n", "start"), toggleOverwrite: cm => cm.toggleOverwrite() } function lineStart(cm, lineN) { let line = getLine(cm.doc, lineN) let visual = visualLine(line) if (visual != line) lineN = lineNo(visual) return endOfLine(true, cm, visual, lineN, 1) } function lineEnd(cm, lineN) { let line = getLine(cm.doc, lineN) let visual = visualLineEnd(line) if (visual != line) lineN = lineNo(visual) return endOfLine(true, cm, line, lineN, -1) } function lineStartSmart(cm, pos) { let start = lineStart(cm, pos.line) let line = getLine(cm.doc, start.line) let order = getOrder(line, cm.doc.direction) if (!order || order[0].level == 0) { let firstNonWS = Math.max(start.ch, line.text.search(/\S/)) let inWS = pos.line == start.line && pos.ch <= firstNonWS && pos.ch return Pos(start.line, inWS ? 0 : firstNonWS, start.sticky) } return start } PK �\�Zyp���V �V methods.jsnu �[��� import { deleteNearSelection } from "./deleteNearSelection.js" import { commands } from "./commands.js" import { attachDoc } from "../model/document_data.js" import { activeElt, addClass, rmClass } from "../util/dom.js" import { eventMixin, signal } from "../util/event.js" import { getLineStyles, getContextBefore, takeToken } from "../line/highlight.js" import { indentLine } from "../input/indent.js" import { triggerElectric } from "../input/input.js" import { onKeyDown, onKeyPress, onKeyUp } from "./key_events.js" import { onMouseDown } from "./mouse_events.js" import { getKeyMap } from "../input/keymap.js" import { endOfLine, moveLogically, moveVisually } from "../input/movement.js" import { endOperation, methodOp, operation, runInOp, startOperation } from "../display/operations.js" import { clipLine, clipPos, equalCursorPos, Pos } from "../line/pos.js" import { charCoords, charWidth, clearCaches, clearLineMeasurementCache, coordsChar, cursorCoords, displayHeight, displayWidth, estimateLineHeights, fromCoordSystem, intoCoordSystem, scrollGap, textHeight } from "../measurement/position_measurement.js" import { Range } from "../model/selection.js" import { replaceOneSelection, skipAtomic } from "../model/selection_updates.js" import { addToScrollTop, ensureCursorVisible, scrollIntoView, scrollToCoords, scrollToCoordsRange, scrollToRange } from "../display/scrolling.js" import { heightAtLine } from "../line/spans.js" import { updateGutterSpace } from "../display/update_display.js" import { indexOf, insertSorted, isWordChar, sel_dontScroll, sel_move } from "../util/misc.js" import { signalLater } from "../util/operation_group.js" import { getLine, isLine, lineAtHeight } from "../line/utils_line.js" import { regChange, regLineChange } from "../display/view_tracking.js" // The publicly visible API. Note that methodOp(f) means // 'wrap f in an operation, performed on its `this` parameter'. // This is not the complete set of editor methods. Most of the // methods defined on the Doc type are also injected into // CodeMirror.prototype, for backwards compatibility and // convenience. export default function(CodeMirror) { let optionHandlers = CodeMirror.optionHandlers let helpers = CodeMirror.helpers = {} CodeMirror.prototype = { constructor: CodeMirror, focus: function(){window.focus(); this.display.input.focus()}, setOption: function(option, value) { let options = this.options, old = options[option] if (options[option] == value && option != "mode") return options[option] = value if (optionHandlers.hasOwnProperty(option)) operation(this, optionHandlers[option])(this, value, old) signal(this, "optionChange", this, option) }, getOption: function(option) {return this.options[option]}, getDoc: function() {return this.doc}, addKeyMap: function(map, bottom) { this.state.keyMaps[bottom ? "push" : "unshift"](getKeyMap(map)) }, removeKeyMap: function(map) { let maps = this.state.keyMaps for (let i = 0; i < maps.length; ++i) if (maps[i] == map || maps[i].name == map) { maps.splice(i, 1) return true } }, addOverlay: methodOp(function(spec, options) { let mode = spec.token ? spec : CodeMirror.getMode(this.options, spec) if (mode.startState) throw new Error("Overlays may not be stateful.") insertSorted(this.state.overlays, {mode: mode, modeSpec: spec, opaque: options && options.opaque, priority: (options && options.priority) || 0}, overlay => overlay.priority) this.state.modeGen++ regChange(this) }), removeOverlay: methodOp(function(spec) { let overlays = this.state.overlays for (let i = 0; i < overlays.length; ++i) { let cur = overlays[i].modeSpec if (cur == spec || typeof spec == "string" && cur.name == spec) { overlays.splice(i, 1) this.state.modeGen++ regChange(this) return } } }), indentLine: methodOp(function(n, dir, aggressive) { if (typeof dir != "string" && typeof dir != "number") { if (dir == null) dir = this.options.smartIndent ? "smart" : "prev" else dir = dir ? "add" : "subtract" } if (isLine(this.doc, n)) indentLine(this, n, dir, aggressive) }), indentSelection: methodOp(function(how) { let ranges = this.doc.sel.ranges, end = -1 for (let i = 0; i < ranges.length; i++) { let range = ranges[i] if (!range.empty()) { let from = range.from(), to = range.to() let start = Math.max(end, from.line) end = Math.min(this.lastLine(), to.line - (to.ch ? 0 : 1)) + 1 for (let j = start; j < end; ++j) indentLine(this, j, how) let newRanges = this.doc.sel.ranges if (from.ch == 0 && ranges.length == newRanges.length && newRanges[i].from().ch > 0) replaceOneSelection(this.doc, i, new Range(from, newRanges[i].to()), sel_dontScroll) } else if (range.head.line > end) { indentLine(this, range.head.line, how, true) end = range.head.line if (i == this.doc.sel.primIndex) ensureCursorVisible(this) } } }), // Fetch the parser token for a given character. Useful for hacks // that want to inspect the mode state (say, for completion). getTokenAt: function(pos, precise) { return takeToken(this, pos, precise) }, getLineTokens: function(line, precise) { return takeToken(this, Pos(line), precise, true) }, getTokenTypeAt: function(pos) { pos = clipPos(this.doc, pos) let styles = getLineStyles(this, getLine(this.doc, pos.line)) let before = 0, after = (styles.length - 1) / 2, ch = pos.ch let type if (ch == 0) type = styles[2] else for (;;) { let mid = (before + after) >> 1 if ((mid ? styles[mid * 2 - 1] : 0) >= ch) after = mid else if (styles[mid * 2 + 1] < ch) before = mid + 1 else { type = styles[mid * 2 + 2]; break } } let cut = type ? type.indexOf("overlay ") : -1 return cut < 0 ? type : cut == 0 ? null : type.slice(0, cut - 1) }, getModeAt: function(pos) { let mode = this.doc.mode if (!mode.innerMode) return mode return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode }, getHelper: function(pos, type) { return this.getHelpers(pos, type)[0] }, getHelpers: function(pos, type) { let found = [] if (!helpers.hasOwnProperty(type)) return found let help = helpers[type], mode = this.getModeAt(pos) if (typeof mode[type] == "string") { if (help[mode[type]]) found.push(help[mode[type]]) } else if (mode[type]) { for (let i = 0; i < mode[type].length; i++) { let val = help[mode[type][i]] if (val) found.push(val) } } else if (mode.helperType && help[mode.helperType]) { found.push(help[mode.helperType]) } else if (help[mode.name]) { found.push(help[mode.name]) } for (let i = 0; i < help._global.length; i++) { let cur = help._global[i] if (cur.pred(mode, this) && indexOf(found, cur.val) == -1) found.push(cur.val) } return found }, getStateAfter: function(line, precise) { let doc = this.doc line = clipLine(doc, line == null ? doc.first + doc.size - 1: line) return getContextBefore(this, line + 1, precise).state }, cursorCoords: function(start, mode) { let pos, range = this.doc.sel.primary() if (start == null) pos = range.head else if (typeof start == "object") pos = clipPos(this.doc, start) else pos = start ? range.from() : range.to() return cursorCoords(this, pos, mode || "page") }, charCoords: function(pos, mode) { return charCoords(this, clipPos(this.doc, pos), mode || "page") }, coordsChar: function(coords, mode) { coords = fromCoordSystem(this, coords, mode || "page") return coordsChar(this, coords.left, coords.top) }, lineAtHeight: function(height, mode) { height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top return lineAtHeight(this.doc, height + this.display.viewOffset) }, heightAtLine: function(line, mode, includeWidgets) { let end = false, lineObj if (typeof line == "number") { let last = this.doc.first + this.doc.size - 1 if (line < this.doc.first) line = this.doc.first else if (line > last) { line = last; end = true } lineObj = getLine(this.doc, line) } else { lineObj = line } return intoCoordSystem(this, lineObj, {top: 0, left: 0}, mode || "page", includeWidgets || end).top + (end ? this.doc.height - heightAtLine(lineObj) : 0) }, defaultTextHeight: function() { return textHeight(this.display) }, defaultCharWidth: function() { return charWidth(this.display) }, getViewport: function() { return {from: this.display.viewFrom, to: this.display.viewTo}}, addWidget: function(pos, node, scroll, vert, horiz) { let display = this.display pos = cursorCoords(this, clipPos(this.doc, pos)) let top = pos.bottom, left = pos.left node.style.position = "absolute" node.setAttribute("cm-ignore-events", "true") this.display.input.setUneditable(node) display.sizer.appendChild(node) if (vert == "over") { top = pos.top } else if (vert == "above" || vert == "near") { let vspace = Math.max(display.wrapper.clientHeight, this.doc.height), hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth) // Default to positioning above (if specified and possible); otherwise default to positioning below if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight) top = pos.top - node.offsetHeight else if (pos.bottom + node.offsetHeight <= vspace) top = pos.bottom if (left + node.offsetWidth > hspace) left = hspace - node.offsetWidth } node.style.top = top + "px" node.style.left = node.style.right = "" if (horiz == "right") { left = display.sizer.clientWidth - node.offsetWidth node.style.right = "0px" } else { if (horiz == "left") left = 0 else if (horiz == "middle") left = (display.sizer.clientWidth - node.offsetWidth) / 2 node.style.left = left + "px" } if (scroll) scrollIntoView(this, {left, top, right: left + node.offsetWidth, bottom: top + node.offsetHeight}) }, triggerOnKeyDown: methodOp(onKeyDown), triggerOnKeyPress: methodOp(onKeyPress), triggerOnKeyUp: onKeyUp, triggerOnMouseDown: methodOp(onMouseDown), execCommand: function(cmd) { if (commands.hasOwnProperty(cmd)) return commands[cmd].call(null, this) }, triggerElectric: methodOp(function(text) { triggerElectric(this, text) }), findPosH: function(from, amount, unit, visually) { let dir = 1 if (amount < 0) { dir = -1; amount = -amount } let cur = clipPos(this.doc, from) for (let i = 0; i < amount; ++i) { cur = findPosH(this.doc, cur, dir, unit, visually) if (cur.hitSide) break } return cur }, moveH: methodOp(function(dir, unit) { this.extendSelectionsBy(range => { if (this.display.shift || this.doc.extend || range.empty()) return findPosH(this.doc, range.head, dir, unit, this.options.rtlMoveVisually) else return dir < 0 ? range.from() : range.to() }, sel_move) }), deleteH: methodOp(function(dir, unit) { let sel = this.doc.sel, doc = this.doc if (sel.somethingSelected()) doc.replaceSelection("", null, "+delete") else deleteNearSelection(this, range => { let other = findPosH(doc, range.head, dir, unit, false) return dir < 0 ? {from: other, to: range.head} : {from: range.head, to: other} }) }), findPosV: function(from, amount, unit, goalColumn) { let dir = 1, x = goalColumn if (amount < 0) { dir = -1; amount = -amount } let cur = clipPos(this.doc, from) for (let i = 0; i < amount; ++i) { let coords = cursorCoords(this, cur, "div") if (x == null) x = coords.left else coords.left = x cur = findPosV(this, coords, dir, unit) if (cur.hitSide) break } return cur }, moveV: methodOp(function(dir, unit) { let doc = this.doc, goals = [] let collapse = !this.display.shift && !doc.extend && doc.sel.somethingSelected() doc.extendSelectionsBy(range => { if (collapse) return dir < 0 ? range.from() : range.to() let headPos = cursorCoords(this, range.head, "div") if (range.goalColumn != null) headPos.left = range.goalColumn goals.push(headPos.left) let pos = findPosV(this, headPos, dir, unit) if (unit == "page" && range == doc.sel.primary()) addToScrollTop(this, charCoords(this, pos, "div").top - headPos.top) return pos }, sel_move) if (goals.length) for (let i = 0; i < doc.sel.ranges.length; i++) doc.sel.ranges[i].goalColumn = goals[i] }), // Find the word at the given position (as returned by coordsChar). findWordAt: function(pos) { let doc = this.doc, line = getLine(doc, pos.line).text let start = pos.ch, end = pos.ch if (line) { let helper = this.getHelper(pos, "wordChars") if ((pos.sticky == "before" || end == line.length) && start) --start; else ++end let startChar = line.charAt(start) let check = isWordChar(startChar, helper) ? ch => isWordChar(ch, helper) : /\s/.test(startChar) ? ch => /\s/.test(ch) : ch => (!/\s/.test(ch) && !isWordChar(ch)) while (start > 0 && check(line.charAt(start - 1))) --start while (end < line.length && check(line.charAt(end))) ++end } return new Range(Pos(pos.line, start), Pos(pos.line, end)) }, toggleOverwrite: function(value) { if (value != null && value == this.state.overwrite) return if (this.state.overwrite = !this.state.overwrite) addClass(this.display.cursorDiv, "CodeMirror-overwrite") else rmClass(this.display.cursorDiv, "CodeMirror-overwrite") signal(this, "overwriteToggle", this, this.state.overwrite) }, hasFocus: function() { return this.display.input.getField() == activeElt() }, isReadOnly: function() { return !!(this.options.readOnly || this.doc.cantEdit) }, scrollTo: methodOp(function (x, y) { scrollToCoords(this, x, y) }), getScrollInfo: function() { let scroller = this.display.scroller return {left: scroller.scrollLeft, top: scroller.scrollTop, height: scroller.scrollHeight - scrollGap(this) - this.display.barHeight, width: scroller.scrollWidth - scrollGap(this) - this.display.barWidth, clientHeight: displayHeight(this), clientWidth: displayWidth(this)} }, scrollIntoView: methodOp(function(range, margin) { if (range == null) { range = {from: this.doc.sel.primary().head, to: null} if (margin == null) margin = this.options.cursorScrollMargin } else if (typeof range == "number") { range = {from: Pos(range, 0), to: null} } else if (range.from == null) { range = {from: range, to: null} } if (!range.to) range.to = range.from range.margin = margin || 0 if (range.from.line != null) { scrollToRange(this, range) } else { scrollToCoordsRange(this, range.from, range.to, range.margin) } }), setSize: methodOp(function(width, height) { let interpret = val => typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val if (width != null) this.display.wrapper.style.width = interpret(width) if (height != null) this.display.wrapper.style.height = interpret(height) if (this.options.lineWrapping) clearLineMeasurementCache(this) let lineNo = this.display.viewFrom this.doc.iter(lineNo, this.display.viewTo, line => { if (line.widgets) for (let i = 0; i < line.widgets.length; i++) if (line.widgets[i].noHScroll) { regLineChange(this, lineNo, "widget"); break } ++lineNo }) this.curOp.forceUpdate = true signal(this, "refresh", this) }), operation: function(f){return runInOp(this, f)}, startOperation: function(){return startOperation(this)}, endOperation: function(){return endOperation(this)}, refresh: methodOp(function() { let oldHeight = this.display.cachedTextHeight regChange(this) this.curOp.forceUpdate = true clearCaches(this) scrollToCoords(this, this.doc.scrollLeft, this.doc.scrollTop) updateGutterSpace(this.display) if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5 || this.options.lineWrapping) estimateLineHeights(this) signal(this, "refresh", this) }), swapDoc: methodOp(function(doc) { let old = this.doc old.cm = null // Cancel the current text selection if any (#5821) if (this.state.selectingText) this.state.selectingText() attachDoc(this, doc) clearCaches(this) this.display.input.reset() scrollToCoords(this, doc.scrollLeft, doc.scrollTop) this.curOp.forceScroll = true signalLater(this, "swapDoc", this, old) return old }), phrase: function(phraseText) { let phrases = this.options.phrases return phrases && Object.prototype.hasOwnProperty.call(phrases, phraseText) ? phrases[phraseText] : phraseText }, getInputField: function(){return this.display.input.getField()}, getWrapperElement: function(){return this.display.wrapper}, getScrollerElement: function(){return this.display.scroller}, getGutterElement: function(){return this.display.gutters} } eventMixin(CodeMirror) CodeMirror.registerHelper = function(type, name, value) { if (!helpers.hasOwnProperty(type)) helpers[type] = CodeMirror[type] = {_global: []} helpers[type][name] = value } CodeMirror.registerGlobalHelper = function(type, name, predicate, value) { CodeMirror.registerHelper(type, name, value) helpers[type]._global.push({pred: predicate, val: value}) } } // Used for horizontal relative motion. Dir is -1 or 1 (left or // right), unit can be "codepoint", "char", "column" (like char, but // doesn't cross line boundaries), "word" (across next word), or // "group" (to the start of next group of word or // non-word-non-whitespace chars). The visually param controls // whether, in right-to-left text, direction 1 means to move towards // the next index in the string, or towards the character to the right // of the current position. The resulting position will have a // hitSide=true property if it reached the end of the document. function findPosH(doc, pos, dir, unit, visually) { let oldPos = pos let origDir = dir let lineObj = getLine(doc, pos.line) let lineDir = visually && doc.direction == "rtl" ? -dir : dir function findNextLine() { let l = pos.line + lineDir if (l < doc.first || l >= doc.first + doc.size) return false pos = new Pos(l, pos.ch, pos.sticky) return lineObj = getLine(doc, l) } function moveOnce(boundToLine) { let next if (unit == "codepoint") { let ch = lineObj.text.charCodeAt(pos.ch + (unit > 0 ? 0 : -1)) if (isNaN(ch)) next = null else next = new Pos(pos.line, Math.max(0, Math.min(lineObj.text.length, pos.ch + dir * (ch >= 0xD800 && ch < 0xDC00 ? 2 : 1))), -dir) } else if (visually) { next = moveVisually(doc.cm, lineObj, pos, dir) } else { next = moveLogically(lineObj, pos, dir) } if (next == null) { if (!boundToLine && findNextLine()) pos = endOfLine(visually, doc.cm, lineObj, pos.line, lineDir) else return false } else { pos = next } return true } if (unit == "char" || unit == "codepoint") { moveOnce() } else if (unit == "column") { moveOnce(true) } else if (unit == "word" || unit == "group") { let sawType = null, group = unit == "group" let helper = doc.cm && doc.cm.getHelper(pos, "wordChars") for (let first = true;; first = false) { if (dir < 0 && !moveOnce(!first)) break let cur = lineObj.text.charAt(pos.ch) || "\n" let type = isWordChar(cur, helper) ? "w" : group && cur == "\n" ? "n" : !group || /\s/.test(cur) ? null : "p" if (group && !first && !type) type = "s" if (sawType && sawType != type) { if (dir < 0) {dir = 1; moveOnce(); pos.sticky = "after"} break } if (type) sawType = type if (dir > 0 && !moveOnce(!first)) break } } let result = skipAtomic(doc, pos, oldPos, origDir, true) if (equalCursorPos(oldPos, result)) result.hitSide = true return result } // For relative vertical movement. Dir may be -1 or 1. Unit can be // "page" or "line". The resulting position will have a hitSide=true // property if it reached the end of the document. function findPosV(cm, pos, dir, unit) { let doc = cm.doc, x = pos.left, y if (unit == "page") { let pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight) let moveAmount = Math.max(pageSize - .5 * textHeight(cm.display), 3) y = (dir > 0 ? pos.bottom : pos.top) + dir * moveAmount } else if (unit == "line") { y = dir > 0 ? pos.bottom + 3 : pos.top - 3 } let target for (;;) { target = coordsChar(cm, x, y) if (!target.outside) break if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break } y += dir * 5 } return target } PK �\�Zs%Jɴ= �= mouse_events.jsnu �[��� import { delayBlurEvent, ensureFocus } from "../display/focus.js" import { operation } from "../display/operations.js" import { visibleLines } from "../display/update_lines.js" import { clipPos, cmp, maxPos, minPos, Pos } from "../line/pos.js" import { getLine, lineAtHeight } from "../line/utils_line.js" import { posFromMouse } from "../measurement/position_measurement.js" import { eventInWidget } from "../measurement/widgets.js" import { normalizeSelection, Range, Selection } from "../model/selection.js" import { extendRange, extendSelection, replaceOneSelection, setSelection } from "../model/selection_updates.js" import { captureRightClick, chromeOS, ie, ie_version, mac, webkit, safari } from "../util/browser.js" import { getOrder, getBidiPartAt } from "../util/bidi.js" import { activeElt } from "../util/dom.js" import { e_button, e_defaultPrevented, e_preventDefault, e_target, hasHandler, off, on, signal, signalDOMEvent } from "../util/event.js" import { dragAndDrop } from "../util/feature_detection.js" import { bind, countColumn, findColumn, sel_mouse } from "../util/misc.js" import { addModifierNames } from "../input/keymap.js" import { Pass } from "../util/misc.js" import { dispatchKey } from "./key_events.js" import { commands } from "./commands.js" const DOUBLECLICK_DELAY = 400 class PastClick { constructor(time, pos, button) { this.time = time this.pos = pos this.button = button } compare(time, pos, button) { return this.time + DOUBLECLICK_DELAY > time && cmp(pos, this.pos) == 0 && button == this.button } } let lastClick, lastDoubleClick function clickRepeat(pos, button) { let now = +new Date if (lastDoubleClick && lastDoubleClick.compare(now, pos, button)) { lastClick = lastDoubleClick = null return "triple" } else if (lastClick && lastClick.compare(now, pos, button)) { lastDoubleClick = new PastClick(now, pos, button) lastClick = null return "double" } else { lastClick = new PastClick(now, pos, button) lastDoubleClick = null return "single" } } // A mouse down can be a single click, double click, triple click, // start of selection drag, start of text drag, new cursor // (ctrl-click), rectangle drag (alt-drag), or xwin // middle-click-paste. Or it might be a click on something we should // not interfere with, such as a scrollbar or widget. export function onMouseDown(e) { let cm = this, display = cm.display if (signalDOMEvent(cm, e) || display.activeTouch && display.input.supportsTouch()) return display.input.ensurePolled() display.shift = e.shiftKey if (eventInWidget(display, e)) { if (!webkit) { // Briefly turn off draggability, to allow widgets to do // normal dragging things. display.scroller.draggable = false setTimeout(() => display.scroller.draggable = true, 100) } return } if (clickInGutter(cm, e)) return let pos = posFromMouse(cm, e), button = e_button(e), repeat = pos ? clickRepeat(pos, button) : "single" window.focus() // #3261: make sure, that we're not starting a second selection if (button == 1 && cm.state.selectingText) cm.state.selectingText(e) if (pos && handleMappedButton(cm, button, pos, repeat, e)) return if (button == 1) { if (pos) leftButtonDown(cm, pos, repeat, e) else if (e_target(e) == display.scroller) e_preventDefault(e) } else if (button == 2) { if (pos) extendSelection(cm.doc, pos) setTimeout(() => display.input.focus(), 20) } else if (button == 3) { if (captureRightClick) cm.display.input.onContextMenu(e) else delayBlurEvent(cm) } } function handleMappedButton(cm, button, pos, repeat, event) { let name = "Click" if (repeat == "double") name = "Double" + name else if (repeat == "triple") name = "Triple" + name name = (button == 1 ? "Left" : button == 2 ? "Middle" : "Right") + name return dispatchKey(cm, addModifierNames(name, event), event, bound => { if (typeof bound == "string") bound = commands[bound] if (!bound) return false let done = false try { if (cm.isReadOnly()) cm.state.suppressEdits = true done = bound(cm, pos) != Pass } finally { cm.state.suppressEdits = false } return done }) } function configureMouse(cm, repeat, event) { let option = cm.getOption("configureMouse") let value = option ? option(cm, repeat, event) : {} if (value.unit == null) { let rect = chromeOS ? event.shiftKey && event.metaKey : event.altKey value.unit = rect ? "rectangle" : repeat == "single" ? "char" : repeat == "double" ? "word" : "line" } if (value.extend == null || cm.doc.extend) value.extend = cm.doc.extend || event.shiftKey if (value.addNew == null) value.addNew = mac ? event.metaKey : event.ctrlKey if (value.moveOnDrag == null) value.moveOnDrag = !(mac ? event.altKey : event.ctrlKey) return value } function leftButtonDown(cm, pos, repeat, event) { if (ie) setTimeout(bind(ensureFocus, cm), 0) else cm.curOp.focus = activeElt() let behavior = configureMouse(cm, repeat, event) let sel = cm.doc.sel, contained if (cm.options.dragDrop && dragAndDrop && !cm.isReadOnly() && repeat == "single" && (contained = sel.contains(pos)) > -1 && (cmp((contained = sel.ranges[contained]).from(), pos) < 0 || pos.xRel > 0) && (cmp(contained.to(), pos) > 0 || pos.xRel < 0)) leftButtonStartDrag(cm, event, pos, behavior) else leftButtonSelect(cm, event, pos, behavior) } // Start a text drag. When it ends, see if any dragging actually // happen, and treat as a click if it didn't. function leftButtonStartDrag(cm, event, pos, behavior) { let display = cm.display, moved = false let dragEnd = operation(cm, e => { if (webkit) display.scroller.draggable = false cm.state.draggingText = false off(display.wrapper.ownerDocument, "mouseup", dragEnd) off(display.wrapper.ownerDocument, "mousemove", mouseMove) off(display.scroller, "dragstart", dragStart) off(display.scroller, "drop", dragEnd) if (!moved) { e_preventDefault(e) if (!behavior.addNew) extendSelection(cm.doc, pos, null, null, behavior.extend) // Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081) if ((webkit && !safari) || ie && ie_version == 9) setTimeout(() => {display.wrapper.ownerDocument.body.focus({preventScroll: true}); display.input.focus()}, 20) else display.input.focus() } }) let mouseMove = function(e2) { moved = moved || Math.abs(event.clientX - e2.clientX) + Math.abs(event.clientY - e2.clientY) >= 10 } let dragStart = () => moved = true // Let the drag handler handle this. if (webkit) display.scroller.draggable = true cm.state.draggingText = dragEnd dragEnd.copy = !behavior.moveOnDrag // IE's approach to draggable if (display.scroller.dragDrop) display.scroller.dragDrop() on(display.wrapper.ownerDocument, "mouseup", dragEnd) on(display.wrapper.ownerDocument, "mousemove", mouseMove) on(display.scroller, "dragstart", dragStart) on(display.scroller, "drop", dragEnd) delayBlurEvent(cm) setTimeout(() => display.input.focus(), 20) } function rangeForUnit(cm, pos, unit) { if (unit == "char") return new Range(pos, pos) if (unit == "word") return cm.findWordAt(pos) if (unit == "line") return new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0))) let result = unit(cm, pos) return new Range(result.from, result.to) } // Normal selection, as opposed to text dragging. function leftButtonSelect(cm, event, start, behavior) { let display = cm.display, doc = cm.doc e_preventDefault(event) let ourRange, ourIndex, startSel = doc.sel, ranges = startSel.ranges if (behavior.addNew && !behavior.extend) { ourIndex = doc.sel.contains(start) if (ourIndex > -1) ourRange = ranges[ourIndex] else ourRange = new Range(start, start) } else { ourRange = doc.sel.primary() ourIndex = doc.sel.primIndex } if (behavior.unit == "rectangle") { if (!behavior.addNew) ourRange = new Range(start, start) start = posFromMouse(cm, event, true, true) ourIndex = -1 } else { let range = rangeForUnit(cm, start, behavior.unit) if (behavior.extend) ourRange = extendRange(ourRange, range.anchor, range.head, behavior.extend) else ourRange = range } if (!behavior.addNew) { ourIndex = 0 setSelection(doc, new Selection([ourRange], 0), sel_mouse) startSel = doc.sel } else if (ourIndex == -1) { ourIndex = ranges.length setSelection(doc, normalizeSelection(cm, ranges.concat([ourRange]), ourIndex), {scroll: false, origin: "*mouse"}) } else if (ranges.length > 1 && ranges[ourIndex].empty() && behavior.unit == "char" && !behavior.extend) { setSelection(doc, normalizeSelection(cm, ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0), {scroll: false, origin: "*mouse"}) startSel = doc.sel } else { replaceOneSelection(doc, ourIndex, ourRange, sel_mouse) } let lastPos = start function extendTo(pos) { if (cmp(lastPos, pos) == 0) return lastPos = pos if (behavior.unit == "rectangle") { let ranges = [], tabSize = cm.options.tabSize let startCol = countColumn(getLine(doc, start.line).text, start.ch, tabSize) let posCol = countColumn(getLine(doc, pos.line).text, pos.ch, tabSize) let left = Math.min(startCol, posCol), right = Math.max(startCol, posCol) for (let line = Math.min(start.line, pos.line), end = Math.min(cm.lastLine(), Math.max(start.line, pos.line)); line <= end; line++) { let text = getLine(doc, line).text, leftPos = findColumn(text, left, tabSize) if (left == right) ranges.push(new Range(Pos(line, leftPos), Pos(line, leftPos))) else if (text.length > leftPos) ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize)))) } if (!ranges.length) ranges.push(new Range(start, start)) setSelection(doc, normalizeSelection(cm, startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex), {origin: "*mouse", scroll: false}) cm.scrollIntoView(pos) } else { let oldRange = ourRange let range = rangeForUnit(cm, pos, behavior.unit) let anchor = oldRange.anchor, head if (cmp(range.anchor, anchor) > 0) { head = range.head anchor = minPos(oldRange.from(), range.anchor) } else { head = range.anchor anchor = maxPos(oldRange.to(), range.head) } let ranges = startSel.ranges.slice(0) ranges[ourIndex] = bidiSimplify(cm, new Range(clipPos(doc, anchor), head)) setSelection(doc, normalizeSelection(cm, ranges, ourIndex), sel_mouse) } } let editorSize = display.wrapper.getBoundingClientRect() // Used to ensure timeout re-tries don't fire when another extend // happened in the meantime (clearTimeout isn't reliable -- at // least on Chrome, the timeouts still happen even when cleared, // if the clear happens after their scheduled firing time). let counter = 0 function extend(e) { let curCount = ++counter let cur = posFromMouse(cm, e, true, behavior.unit == "rectangle") if (!cur) return if (cmp(cur, lastPos) != 0) { cm.curOp.focus = activeElt() extendTo(cur) let visible = visibleLines(display, doc) if (cur.line >= visible.to || cur.line < visible.from) setTimeout(operation(cm, () => {if (counter == curCount) extend(e)}), 150) } else { let outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0 if (outside) setTimeout(operation(cm, () => { if (counter != curCount) return display.scroller.scrollTop += outside extend(e) }), 50) } } function done(e) { cm.state.selectingText = false counter = Infinity // If e is null or undefined we interpret this as someone trying // to explicitly cancel the selection rather than the user // letting go of the mouse button. if (e) { e_preventDefault(e) display.input.focus() } off(display.wrapper.ownerDocument, "mousemove", move) off(display.wrapper.ownerDocument, "mouseup", up) doc.history.lastSelOrigin = null } let move = operation(cm, e => { if (e.buttons === 0 || !e_button(e)) done(e) else extend(e) }) let up = operation(cm, done) cm.state.selectingText = up on(display.wrapper.ownerDocument, "mousemove", move) on(display.wrapper.ownerDocument, "mouseup", up) } // Used when mouse-selecting to adjust the anchor to the proper side // of a bidi jump depending on the visual position of the head. function bidiSimplify(cm, range) { let {anchor, head} = range, anchorLine = getLine(cm.doc, anchor.line) if (cmp(anchor, head) == 0 && anchor.sticky == head.sticky) return range let order = getOrder(anchorLine) if (!order) return range let index = getBidiPartAt(order, anchor.ch, anchor.sticky), part = order[index] if (part.from != anchor.ch && part.to != anchor.ch) return range let boundary = index + ((part.from == anchor.ch) == (part.level != 1) ? 0 : 1) if (boundary == 0 || boundary == order.length) return range // Compute the relative visual position of the head compared to the // anchor (<0 is to the left, >0 to the right) let leftSide if (head.line != anchor.line) { leftSide = (head.line - anchor.line) * (cm.doc.direction == "ltr" ? 1 : -1) > 0 } else { let headIndex = getBidiPartAt(order, head.ch, head.sticky) let dir = headIndex - index || (head.ch - anchor.ch) * (part.level == 1 ? -1 : 1) if (headIndex == boundary - 1 || headIndex == boundary) leftSide = dir < 0 else leftSide = dir > 0 } let usePart = order[boundary + (leftSide ? -1 : 0)] let from = leftSide == (usePart.level == 1) let ch = from ? usePart.from : usePart.to, sticky = from ? "after" : "before" return anchor.ch == ch && anchor.sticky == sticky ? range : new Range(new Pos(anchor.line, ch, sticky), head) } // Determines whether an event happened in the gutter, and fires the // handlers for the corresponding event. function gutterEvent(cm, e, type, prevent) { let mX, mY if (e.touches) { mX = e.touches[0].clientX mY = e.touches[0].clientY } else { try { mX = e.clientX; mY = e.clientY } catch(e) { return false } } if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) return false if (prevent) e_preventDefault(e) let display = cm.display let lineBox = display.lineDiv.getBoundingClientRect() if (mY > lineBox.bottom || !hasHandler(cm, type)) return e_defaultPrevented(e) mY -= lineBox.top - display.viewOffset for (let i = 0; i < cm.display.gutterSpecs.length; ++i) { let g = display.gutters.childNodes[i] if (g && g.getBoundingClientRect().right >= mX) { let line = lineAtHeight(cm.doc, mY) let gutter = cm.display.gutterSpecs[i] signal(cm, type, cm, line, gutter.className, e) return e_defaultPrevented(e) } } } export function clickInGutter(cm, e) { return gutterEvent(cm, e, "gutterClick", true) } // CONTEXT MENU HANDLING // To make the context menu work, we need to briefly unhide the // textarea (making it as unobtrusive as possible) to let the // right-click take effect on it. export function onContextMenu(cm, e) { if (eventInWidget(cm.display, e) || contextMenuInGutter(cm, e)) return if (signalDOMEvent(cm, e, "contextmenu")) return if (!captureRightClick) cm.display.input.onContextMenu(e) } function contextMenuInGutter(cm, e) { if (!hasHandler(cm, "gutterContextMenu")) return false return gutterEvent(cm, e, "gutterContextMenu", false) } PK �\�Z�-� � global_events.jsnu �[��� PK �\�Zn��A A � options.jsnu �[��� PK �\�Z�����! �! c"