diff --git a/cfg/root-riscv64.cfg b/cfg/root-riscv64.cfg deleted file mode 100644 index e1349e2..0000000 --- a/cfg/root-riscv64.cfg +++ /dev/null @@ -1,11 +0,0 @@ -/* VM configuration file */ -{ - version: 1, - machine: "riscv64", - memory_size: 128, - bios: "bbl64.bin", - kernel: "kernel-riscv64.bin", - cmdline: "console=hvc0 root=/dev/vda rw", - drive0: { file: "root-riscv64/blk.txt" }, - eth0: { driver: "user" }, -} diff --git a/cfg/root-x86.cfg b/cfg/root-x86.cfg deleted file mode 100644 index 31f2afa..0000000 --- a/cfg/root-x86.cfg +++ /dev/null @@ -1,10 +0,0 @@ -/* VM configuration file */ -{ - version: 1, - machine: "pc", - memory_size: 128, - kernel: "kernel-x86.bin", - cmdline: "loglevel=3 console=hvc0 root=/dev/vda rw", - drive0: { file: "root-x86/blk.txt" }, - eth0: { driver: "user" }, -} diff --git a/web/index.html b/web/index.html deleted file mode 100644 index 8cde18f..0000000 --- a/web/index.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - JSLinux - - - - -
-
-
-
- - - - -
-
- - - - - diff --git a/web/jslinux.js b/web/jslinux.js deleted file mode 100644 index d656c75..0000000 --- a/web/jslinux.js +++ /dev/null @@ -1,646 +0,0 @@ -/* - * JS Linux main - * - * Copyright (c) 2017 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -"use strict"; - -var term, console_write1; -var graphic_display, display_key_event, display_mouse_event; -var net_state, net_write_packet, net_set_carrier; -var display_wheel_event; -var fs_import_file; -var Module = {}; -var downloading_timer_pending = false; -var downloading_timer; - -function on_update_file(f) -{ - var f, reader; - reader = new FileReader(); - reader.onload = function (ev) { - var buf, buf_addr, buf_len; - buf = new Uint8Array(reader.result); - buf_len = buf.length; - buf_addr = _malloc(buf_len); - HEAPU8.set(buf, buf_addr); - /* the buffer is freed by the function */ - fs_import_file(f.name, buf_addr, buf_len); - }; - reader.readAsArrayBuffer(f); -} - -function on_update_files(files) -{ - var i, n; - n = files.length; - for(i = 0; i < n; i++) { - on_update_file(files[i]); - } -} - -function term_handler(str) -{ - var i; - for(i = 0; i < str.length; i++) { - console_write1(str.charCodeAt(i)); - } -} - -function downloading_timer_cb() -{ - var el = document.getElementById("net_progress"); - el.style.visibility = "hidden"; - downloading_timer_pending = false; -} - -function update_downloading(flag) -{ - var el; - if (flag) { - if (downloading_timer_pending) { - clearTimeout(downloading_timer); - downloading_timer_pending = false; - } else { - el = document.getElementById("net_progress"); - el.style.visibility = "visible"; - } - } else { - downloading_timer_pending = true; - downloading_timer = setTimeout(downloading_timer_cb, 500); - } -} - -function get_params() -{ - var url, query_str, p, tab, i, params, tab2; - query_str = window.location.href; - p = query_str.indexOf("?"); - if (p < 0) - return {}; - query_str = query_str.substr(p + 1); - tab = query_str.split("&"); - params = {}; - for(i = 0; i < tab.length; i++) { - tab2 = tab[i].split("="); - params[decodeURIComponent(tab2[0])] = decodeURIComponent(tab2[1]); - } - return params; -} - -function get_absolute_url(fname) -{ - var path, p; - - if (fname.indexOf(":") >= 0) - return fname; - path = window.location.pathname; - p = path.lastIndexOf("/"); - if (p < 0) - return fname; - return window.location.origin + path.slice(0, p + 1) + fname; -} - -function GraphicDisplay(parent_el, width, height) -{ - this.width = width; - this.height = height; - - this.canvas_el = document.createElement("canvas"); - this.canvas_el.width = width; /* logical width */ - this.canvas_el.height = height; /* logical width */ - /* displayed size */ - this.canvas_el.style.width = width + "px"; - this.canvas_el.style.height = height + "px"; - this.canvas_el.style.cursor = "none"; - - parent_el.appendChild(this.canvas_el); - - this.ctx = this.canvas_el.getContext("2d"); - /* clear the display */ - this.ctx.fillStyle = "#000000"; - this.ctx.fillRect(0, 0, width, height); - - this.image = this.ctx.createImageData(width, height); - - this.key_pressed = new Uint8Array(128); - - document.addEventListener("keydown", - this.keyDownHandler.bind(this), false); - document.addEventListener("keyup", - this.keyUpHandler.bind(this), false); - document.addEventListener("blur", - this.blurHandler.bind(this), false); - - this.canvas_el.onmousedown = this.mouseMoveHandler.bind(this); - this.canvas_el.onmouseup = this.mouseMoveHandler.bind(this); - this.canvas_el.onmousemove = this.mouseMoveHandler.bind(this); - this.canvas_el.oncontextmenu = this.onContextMenuHandler.bind(this); - this.canvas_el.onwheel = this.wheelHandler.bind(this); -} - -GraphicDisplay.code_to_input_map = { - "Escape": 0x01, - "Digit1": 0x02, - "Digit2": 0x03, - "Digit3": 0x04, - "Digit4": 0x05, - "Digit5": 0x06, - "Digit6": 0x07, - "Digit7": 0x08, - "Digit8": 0x09, - "Digit9": 0x0a, - "Digit0": 0x0b, - "Minus": 0x0c, - "Equal": 0x0d, - "Backspace": 0x0e, - "Tab": 0x0f, - "KeyQ": 0x10, - "KeyW": 0x11, - "KeyE": 0x12, - "KeyR": 0x13, - "KeyT": 0x14, - "KeyY": 0x15, - "KeyU": 0x16, - "KeyI": 0x17, - "KeyO": 0x18, - "KeyP": 0x19, - "BracketLeft": 0x1a, - "BracketRight": 0x1b, - "Enter": 0x1c, - "ControlLeft": 0x1d, - "KeyA": 0x1e, - "KeyS": 0x1f, - "KeyD": 0x20, - "KeyF": 0x21, - "KeyG": 0x22, - "KeyH": 0x23, - "KeyJ": 0x24, - "KeyK": 0x25, - "KeyL": 0x26, - "Semicolon": 0x27, - "Quote": 0x28, - "Backquote": 0x29, - "ShiftLeft": 0x2a, - "Backslash": 0x2b, - "KeyZ": 0x2c, - "KeyX": 0x2d, - "KeyC": 0x2e, - "KeyV": 0x2f, - "KeyB": 0x30, - "KeyN": 0x31, - "KeyM": 0x32, - "Comma": 0x33, - "Period": 0x34, - "Slash": 0x35, - "ShiftRight": 0x36, - "NumpadMultiply": 0x37, - "AltLeft": 0x38, - "Space": 0x39, - "CapsLock": 0x3a, - "F1": 0x3b, - "F2": 0x3c, - "F3": 0x3d, - "F4": 0x3e, - "F5": 0x3f, - "F6": 0x40, - "F7": 0x41, - "F8": 0x42, - "F9": 0x43, - "F10": 0x44, - "NumLock": 0x45, - "ScrollLock": 0x46, - "Numpad7": 0x47, - "Numpad8": 0x48, - "Numpad9": 0x49, - "NumpadSubtract": 0x4a, - "Numpad4": 0x4b, - "Numpad5": 0x4c, - "Numpad6": 0x4d, - "NumpadAdd": 0x4e, - "Numpad1": 0x4f, - "Numpad2": 0x50, - "Numpad3": 0x51, - "Numpad0": 0x52, - "NumpadDecimal": 0x53, - "IntlBackslash": 0x56, - "F11": 0x57, - "F12": 0x58, - - "NumpadEnter": 96, - "ControlRight": 97, - "NumpadDivide": 98, - "AltRight": 100, - "Home": 102, - "ArrowUp": 103, - "PageUp": 104, - "ArrowLeft": 105, - "ArrowRight": 106, - "End": 107, - "ArrowDown": 108, - "PageDown": 109, - "Insert": 110, - "Delete": 111, - "OSLeft": 125, - "OSRight": 126, - "ContextMenu": 127, -}; - -GraphicDisplay.key_code_to_input_map = new Uint8Array([ - 0, 0, 0, 0, 0, 0, 0, 0, - 0x0E, 0x0F, 0, 0, 0, 0x1C, 0, 0, - 0x2A, 0x1D, 0x38, 0, 0x3A, 0, 0, 0, /* 0x10 */ - 0, 0, 0, 0x01, 0, 0, 0, 0, - 0x39, 104, 109, 107, 102, 105, 103, 106, /* 0x20 */ - 0x50, 0, 0, 0, 0, 0x52, 0x53, 0, - 0x0B, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, /* 0x30 */ - 0x09, 0x0A, 0, 0x27, 0, 0x0D, 0, 0, - 0, 0x1E, 0x30, 0x2E, 0x20, 0x12, 0x21, 0x22, /* 0x40 */ - 0x23, 0x17, 0x24, 0x25, 0x26, 0x32, 0x31, 0x18, - 0x19, 0x10, 0x13, 0x1F, 0x14, 0x16, 0x2F, 0x11, /* 0x50 */ - 0x2D, 0x15, 0x2C, 125, 126, 127, 0, 0, - 0x52, 0x4F, 0x50, 0x51, 0x4B, 0x4C, 0x4D, 0x47, /* 0x60 */ - 0x48, 0x49, 0x37, 0x4e, 0, 0x4a, 0x53, 98, - 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, /* 0x70 */ - 0x43, 0x44, 0x57, 0x58, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0x45, 0, 0, 0, 0, 0, 0, 0, /* 0x90 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 */ - 0, 0, 0, 0, 0, 0x0C, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 */ - 0, 0, 0x27, 0x0D, 0x33, 0x0C, 0x34, 0x35, - 0x29, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 */ - 0, 0, 0, 0x1A, 0x2B, 0x1B, 0x28, 0, - 125, 100, 0, 0, 0, 0, 0, 0, /* 0xe0 */ - 0, 0, 0, 0, 0, 0, 0, 0, -]); - -GraphicDisplay.prototype.keyHandler = function keyHandler(ev, isDown) -{ - var code, input_key_code; - - /* At least avoid exiting the navigator if Ctrl-Q or Ctrl-W are - * pressed */ - if (ev.ctrlKey) { - window.onbeforeunload = function() { - window.onbeforeunload = null; - return "CTRL-W or Ctrl-Q cannot be sent to the emulator."; - }; - } else { - window.onbeforeunload = null; - } - - if (typeof ev.code != "undefined") { - code = ev.code; - input_key_code = GraphicDisplay.code_to_input_map[code]; - if (typeof input_key_code != "undefined") { -// console.log("code=" + code + " isDown=" + isDown + " input_key_code=" + input_key_code); - this.key_pressed[input_key_code] = isDown; - display_key_event(isDown, input_key_code); - - if (ev.stopPropagation) - ev.stopPropagation(); - if (ev.preventDefault) - ev.preventDefault(); - return false; - } - } else { - /* fallback using keyCodes. Works only with an US keyboard */ - code = ev.keyCode; - if (code < 256) { - input_key_code = GraphicDisplay.key_code_to_input_map[code]; -// console.log("keyCode=" + code + " isDown=" + isDown + " input_key_code=" + input_key_code); - if (input_key_code) { - this.key_pressed[input_key_code] = isDown; - display_key_event(isDown, input_key_code); - - if (ev.stopPropagation) - ev.stopPropagation(); - if (ev.preventDefault) - ev.preventDefault(); - return false; - } - } - } - return true; -} - -GraphicDisplay.prototype.keyDownHandler = function keyDownHandler(ev) -{ - return this.keyHandler(ev, 1); -} - -GraphicDisplay.prototype.keyUpHandler = function keyUpHandler(ev) -{ - return this.keyHandler(ev, 0); -} - -GraphicDisplay.prototype.blurHandler = function blurHandler(ev, isDown) -{ - var i, n, key_pressed; - /* allow unloading the page */ - window.onbeforeunload = null; - /* release all keys */ - key_pressed = this.key_pressed; - for(i = 0; i < key_pressed.length; i++) { - if (key_pressed[i]) { - display_key_event(0, i); - key_pressed[i] = 0; - } - } -} - -GraphicDisplay.prototype.mouseMoveHandler = function (ev) -{ - var x, y, rect, buttons; - rect = this.canvas_el.getBoundingClientRect(); - x = ev.clientX - rect.left; - y = ev.clientY - rect.top; - buttons = ev.buttons & 7; -// console.log("mouse: x=" + x + " y=" + y + " buttons=" + buttons); - display_mouse_event(x, y, buttons); - if (ev.stopPropagation) - ev.stopPropagation(); - if (ev.preventDefault) - ev.preventDefault(); - return false; -} - -GraphicDisplay.prototype.wheelHandler = function (ev) -{ - if (ev.deltaY < 0) { - display_wheel_event(1); - } else if (ev.deltaY > 0) { - display_wheel_event(-1); - } - if (ev.stopPropagation) - ev.stopPropagation(); - if (ev.preventDefault) - ev.preventDefault(); -} - -/* disable contextual menu */ -GraphicDisplay.prototype.onContextMenuHandler = function (ev) -{ - if (ev.stopPropagation) - ev.stopPropagation(); - if (ev.preventDefault) - ev.preventDefault(); - return false; -} - -/* Network support */ - -function Ethernet(url) -{ - try { - this.socket = new WebSocket(url); - } catch(err) { - this.socket = null; - console.log("Could not open websocket url=" + url); - return; - } - this.socket.binaryType = 'arraybuffer'; - this.socket.onmessage = this.messageHandler.bind(this); - this.socket.onclose = this.closeHandler.bind(this); - this.socket.onopen = this.openHandler.bind(this); - this.socket.onerror = this.errorHandler.bind(this); -} - -Ethernet.prototype.openHandler = function(e) -{ - net_set_carrier(1); -} - -Ethernet.prototype.closeHandler = function(e) -{ - net_set_carrier(0); -} - -Ethernet.prototype.errorHandler = function(e) -{ - console.log("Websocket error=" + e); -} - -Ethernet.prototype.messageHandler = function(e) -{ - var str, buf_len, buf_addr, buf; - if (e.data instanceof ArrayBuffer) { - buf_len = e.data.byteLength; - buf = new Uint8Array(e.data); - buf_addr = _malloc(buf_len); - HEAPU8.set(buf, buf_addr); - net_write_packet(buf_addr, buf_len); - _free(buf_addr); - } else { - str = e.data.toString(); - if (str.substring(0, 5) == "ping:") { - try { - this.socket.send('pong:' + str.substring(5)); - } catch (err) { - } - } - } -} - -Ethernet.prototype.recv_packet = function(buf) -{ - if (this.socket) { - try { - this.socket.send(buf); - } catch (err) { - } - } -} - -function start_vm(user, pwd) -{ - var url, mem_size, cpu, params, vm_url, cmdline, cols, rows, guest_url; - var font_size, graphic_enable, width, height, net_url, alloc_size; - var drive_url, vm_file; - - function loadScript(src, f) { - var head = document.getElementsByTagName("head")[0]; - var script = document.createElement("script"); - script.src = src; - var done = false; - script.onload = script.onreadystatechange = function() { - // attach to both events for cross browser finish detection: - if ( !done && (!this.readyState || - this.readyState == "loaded" || this.readyState == "complete") ) { - done = true; - if (f) { - f(); - } - script.onload = script.onreadystatechange = null; - head.removeChild(script); - } - }; - head.appendChild(script); - } - - function start() - { - /* C functions called from javascript */ - console_write1 = Module.cwrap('console_queue_char', null, ['number']); - fs_import_file = Module.cwrap('fs_import_file', null, ['string', 'number', 'number']); - display_key_event = Module.cwrap('display_key_event', null, ['number', 'number']); - display_mouse_event = Module.cwrap('display_mouse_event', null, ['number', 'number', 'number']); - display_wheel_event = Module.cwrap('display_wheel_event', null, ['number']); - net_write_packet = Module.cwrap('net_write_packet', null, ['number', 'number']); - net_set_carrier = Module.cwrap('net_set_carrier', null, ['number']); - - net_state = null; - if (net_url != "") { - net_state = new Ethernet(net_url); - } - - Module.ccall("vm_start", null, ["string", "number", "string", "string", "number", "number", "number", "string"], [url, mem_size, cmdline, pwd, width, height, (net_state != null) | 0, drive_url]); - pwd = null; - } - - /* read the parameters */ - - params = get_params(); - cpu = params["cpu"] || "riscv64"; - url = params["url"]; - if (!url) { - if (cpu == "x86") - url = "root-x86.cfg"; - else - url = "root-riscv64.cfg"; - } - url = get_absolute_url(url); - mem_size = (params["mem"] | 0) || 128; /* in mb */ - cmdline = params["cmdline"] || ""; - cols = (params["cols"] | 0) || 80; - rows = (params["rows"] | 0) || 30; - font_size = (params["font_size"] | 0) || 15; - guest_url = params["guest_url"] || ""; - width = (params["w"] | 0) || 1024; - height = (params["h"] | 0) || 640; - graphic_enable = params["graphic"] | 0; - net_url = params["net_url"] || ""; /* empty string means no network */ - if (typeof net_url == "undefined") - net_url = "wss://relay.widgetry.org/"; - drive_url = params["drive_url"] || ""; - - if (user) { - cmdline += " LOGIN_USER=" + user; - } else if (guest_url) { - cmdline += " GUEST_URL=" + guest_url; - } - - if (graphic_enable) { - graphic_display = new GraphicDisplay(document.getElementById("term_container"), width, height); - } else { - width = 0; - height = 0; - /* start the terminal */ - term = new Term(cols, rows, term_handler, 10000); - term.open(document.getElementById("term_container"), - document.getElementById("term_paste")); - term.term_el.style.fontSize = font_size + "px"; - term.write("Loading...\r\n"); - } - -// console.log("cpu=" + cpu + " url=" + url + " mem=" + mem_size); - - switch(cpu) { - case "x86": - vm_file = "x86emu"; - break; - case "riscv64": - case "riscv": - vm_file = "riscvemu64"; - break; - case "riscv32": - vm_file = "riscvemu32"; - break; - default: - term.writeln("Unknown cpu=" + cpu); - return; - } - - if (typeof WebAssembly === "object") { - /* wasm support : the memory grows automatically */ - vm_url = vm_file + "-wasm.js"; - } else { - /* set the total memory */ - alloc_size = mem_size; - if (cpu == "x86") - alloc_size += 16; - if (graphic_enable) { - /* frame buffer memory */ - alloc_size += (width * height * 4 + 1048576 - 1) >> 20; - } - alloc_size += 32; /* extra space (XXX: reduce it ?) */ - alloc_size = (alloc_size + 15) & -16; /* align to 16 MB */ - Module.TOTAL_MEMORY = alloc_size << 20; - vm_url = vm_file + ".js"; - } - Module.preRun = start; - - loadScript(vm_url, null); -} - -function on_login() -{ - var login_wrap_el = document.getElementById("wrap"); - var term_wrap_el = document.getElementById("term_wrap"); - var form = document.getElementById("form"); - var status = document.getElementById("status"); - var user = form.user.value; - var pwd = form.password.value; - - if (user.length <= 1) { - status.innerHTML = "User name must be provided"; - return false; - } - - login_wrap_el.style.display = "none"; - term_wrap_el.style.display = "block"; - form.password.value = ""; - form.user.value = ""; - - start_vm(user, pwd); - - return false; -} - -(function() { - var login, params; - - params = get_params(); - login = params["login"] || 0; - if (login) { - var login_wrap_el = document.getElementById("wrap"); - login_wrap_el.style.display = "block"; - } else { - var term_wrap_el = document.getElementById("term_wrap"); - term_wrap_el.style.display = "block"; - start_vm(null, null); - } -})(); diff --git a/web/style.css b/web/style.css deleted file mode 100644 index 9d39504..0000000 --- a/web/style.css +++ /dev/null @@ -1,41 +0,0 @@ -.term { - font-family: courier,fixed,swiss,monospace,sans-serif; - font-size: 15px; - color: #f0f0f0; - background: #000000; -} - -.term_content a { - color: #ffff00; -} - -.term_cursor { - color: #000000; - background: #00ff00; -} - -.term_scrollbar { background: transparent url(images/bg-scrollbar-track-y.png) no-repeat 0 0; position: relative; background-position: 0 0; float: right; width: 15px; height: 100%; } -.term_track { background: transparent url(images/bg-scrollbar-trackend-y.png) no-repeat 0 100%; height: 100%; width:13px; position: relative; padding: 0 1px; } -.term_thumb { background: transparent url(images/bg-scrollbar-thumb-y.png) no-repeat 50% 100%; height: 20px; width: 25px; cursor: pointer; overflow: hidden; position: absolute; top: 0; left: -5px; } -.term_thumb .term_end { background: transparent url(images/bg-scrollbar-thumb-y.png) no-repeat 50% 0; overflow: hidden; height: 5px; width: 25px; } -.noSelect { user-select: none; -o-user-select: none; -moz-user-select: none; -khtml-user-select: none; -webkit-user-select: none; } -#term_paste { - border: 1px solid; - height: 19px; -} - -/* file import */ -#files { - visibility: hidden; - width:1px; - height:1px; - padding: 0px; - margin: 0px; - bordex: 0px; -} - -label { - cursor: pointer; - margin-left: 5px; - margin-right: 5px; -} diff --git a/web/term.js b/web/term.js deleted file mode 100644 index 1a9ca6c..0000000 --- a/web/term.js +++ /dev/null @@ -1,1251 +0,0 @@ -/* - * Javascript terminal - * - * Copyright (c) 2011-2017 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -"use strict"; - -function Term(width, height, handler, tot_height) -{ - this.w = width; - this.h = height; - - this.cur_h = height; /* current height of the scroll back buffer */ - if (!tot_height || tot_height < height) - tot_height = height; - this.tot_h = tot_height; /* maximum height of the scroll back buffer */ - this.y_base = 0; /* position of the current top screen line in the - * scroll back buffer */ - this.y_disp = 0; /* position of the top displayed line in the - * scroll back buffer */ - /* cursor position */ - this.x = 0; - this.y = 0; - this.scroll_top = 0; - this.scroll_bottom = this.h; - this.cursorstate = 0; - this.handler = handler; - this.state = 0; - this.output_queue = ""; - this.colors = [ - /* normal */ - "#000000", - "#aa0000", - "#00aa00", - "#aa5500", - "#0000aa", - "#aa00aa", - "#00aaaa", - "#aaaaaa", - /* bright */ - "#555555", - "#ff5555", - "#55ff55", - "#ffff55", - "#5555ff", - "#ff55ff", - "#55ffff", - "#ffffff" - ]; - /* attributes bits: - 0-3: bg - 4-7: fg - 8: bold - 9: inverse - */ - this.def_attr = (7 << 4) | 0; - this.cur_attr = this.def_attr; - this.is_mac = (navigator.userAgent.indexOf("Mac") >=0 ) ? true : false; - this.key_rep_state = 0; - this.key_rep_str = ""; - - this.utf8 = true; - this.utf8_state = 0; - this.utf8_val = 0; - - this.application_cursor = false; - this.application_keypad = false; - /* if true, emulate some behaviors of the Linux console */ - this.linux_console = true; -} - -Term.prototype.open = function(parent_el, textarea_el) -{ - var y, line, i, term, c, row_el; - - /* set initial content */ - this.lines = new Array(); - c = 32 | (this.def_attr << 16); - for(y = 0; y < this.cur_h;y++) { - line = new Array(); - for(i=0;i= 0; - } - - function right_trim(str, a) - { - var i, n; - n = a.length; - i = str.length; - while (i >= n && str.substr(i - n, n) == a) - i -= n; - return str.substr(0, i); - } - - for(y = ymin; y <= ymax; y++) { - /* convert to HTML string */ - y1 = y + this.y_disp; - if (y1 >= this.cur_h) - y1 -= this.cur_h; - line = this.lines[y1]; - outline = ""; - w = this.w; - if (y == this.y && this.cursor_state && - this.y_disp == this.y_base) { - cx = this.x; - } else { - cx = -1; - } - last_attr = this.def_attr; - http_link_len = 0; - for(i = 0; i < w; i++) { - c = line[i]; - attr = c >> 16; - c &= 0xffff; - /* test for http link */ - if (c == 0x68 && (w - i) >= 8 && http_link_len == 0) { - /* test http:// or https:// */ - if ((line[i + 1] & 0xffff) == 0x74 && - (line[i + 2] & 0xffff) == 0x74 && - (line[i + 3] & 0xffff) == 0x70 && - (((line[i + 4] & 0xffff) == 0x3a && - (line[i + 5] & 0xffff) == 0x2f && - (line[i + 6] & 0xffff) == 0x2f) || - ((line[i + 4] & 0xffff) == 0x73 && - (line[i + 5] & 0xffff) == 0x3a && - (line[i + 6] & 0xffff) == 0x2f && - (line[i + 7] & 0xffff) == 0x2f))) { - http_link_str = ""; - j = 0; - while ((i + j) < w && - is_http_link_char(line[i + j] & 0xffff)) { - http_link_str += String.fromCharCode(line[i + j] & 0xffff); - j++; - } - http_link_len = j; - if (last_attr != this.def_attr) { - outline += ''; - last_attr = this.def_attr; - } - outline += ""; - } - } - if (i == cx) { - attr = -1; /* cursor */ - } - if (attr != last_attr) { - if (last_attr != this.def_attr) - outline += ''; - if (attr != this.def_attr) { - if (attr == -1) { - /* cursor */ - outline += ''; - } else { - outline += ''; - } - } - } - switch(c) { - case 32: - outline += " "; - break; - case 38: // '&' - outline += "&"; - break; - case 60: // '<' - outline += "<"; - break; - case 62: // '>' - outline += ">"; - break; - default: - if (c < 32) { - outline += " "; - } else { - outline += String.fromCharCode(c); - } - break; - } - last_attr = attr; - if (http_link_len != 0) { - http_link_len--; - if (http_link_len == 0) { - if (last_attr != this.def_attr) { - outline += ''; - last_attr = this.def_attr; - } - outline += ""; - } - } - } - if (last_attr != this.def_attr) { - outline += ''; - } - - /* trim trailing spaces for copy/paste */ - outline = right_trim(outline, " "); - if (outline == "") - outline = " "; - - this.rows_el[y].innerHTML = outline; - } - - this.refresh_scrollbar(); -}; - -Term.prototype.cursor_timer_cb = function() -{ - this.cursor_state ^= 1; - this.refresh(this.y, this.y); -}; - -Term.prototype.show_cursor = function() -{ - if (!this.cursor_state) { - this.cursor_state = 1; - this.refresh(this.y, this.y); - } -}; - -/* scroll down or up in the scroll back buffer by n lines */ -Term.prototype.scroll_disp = function(n) -{ - var i, y1; - /* slow but it does not really matters */ - if (n >= 0) { - for(i = 0; i < n; i++) { - if (this.y_disp == this.y_base) - break; - if (++this.y_disp == this.cur_h) - this.y_disp = 0; - } - } else { - n = -n; - y1 = this.y_base + this.h; - if (y1 >= this.cur_h) - y1 -= this.cur_h; - for(i = 0; i < n; i++) { - if (this.y_disp == y1) - break; - if (--this.y_disp < 0) - this.y_disp = this.cur_h - 1; - } - } - this.refresh(0, this.h - 1); -}; - -Term.prototype.write = function(str) -{ - var s, ymin, ymax; - - function update(y) - { - ymin = Math.min(ymin, y); - ymax = Math.max(ymax, y); - } - - function get_erase_char() - { - var bg_mask, attr; - bg_mask = 0xf; - attr = (s.def_attr & ~bg_mask) | (s.cur_attr & bg_mask); - return 32 | (attr << 16); - } - - function erase_chars(x1, x2, y) { - var l, i, c, y1; - y1 = s.y_base + y; - if (y1 >= s.cur_h) - y1 -= s.cur_h; - l = s.lines[y1]; - c = get_erase_char(); - for(i = x1; i < x2; i++) - l[i] = c; - update(y); - } - - function erase_to_eol(x, y) { - erase_chars(x, s.w, y); - } - - function erase_in_line(n) { - switch(n) { - case 0: - erase_to_eol(s.x, s.y); - break; - case 1: - erase_chars(0, s.x + 1, s.y); - break; - case 2: - erase_chars(0, s.w, s.y); - break; - } - } - - function erase_in_display(n) { - var y; - switch(n) { - case 0: - erase_to_eol(s.x, s.y); - for(y = s.y + 1; y < s.h; y++) - erase_to_eol(0, y); - break; - case 1: - erase_chars(0, s.x + 1, s.y); - for(y = 0; y < s.y; y++) { - erase_to_eol(0, y); - } - break; - case 2: - for(y = 0; y < s.h; y++) { - erase_to_eol(0, y); - } - break; - } - } - - - function delete_chars(n) - { - var l, i, c, y1, j; - y1 = s.y + s.y_base; - if (y1 >= s.cur_h) - y1 -= s.cur_h; - l = s.lines[y1]; - if (n < 1) - n = 1; - c = get_erase_char(); - j = s.x + n; - for(i = s.x; i < s.w; i++) { - if (j < s.w) - l[i] = l[j]; - else - l[i] = c; - j++; - } - update(s.y); - } - - function insert_chars(n) - { - var l, i, c, y1, x1; - if (n < 1) - n = 1; - if (n > s.w - s.x) - n = s.w - s.x; - y1 = s.y + s.y_base; - if (y1 >= s.cur_h) - y1 -= s.cur_h; - l = s.lines[y1]; - x1 = s.x + n; - for(i = s.w - 1; i >= x1; i--) - l[i] = l[i - n]; - c = get_erase_char(); - for(i = s.x; i < x1; i++) - l[i] = c; - update(s.y); - } - - function csi_colors(esc_params) - { - var j, n, fg, bg, mask; - - if (esc_params.length == 0) { - s.cur_attr= s.def_attr; - } else { - for(j = 0; j < esc_params.length; j++) { - n = esc_params[j]; - if (n >= 30 && n <= 37) { - /* foreground */ - fg = n - 30; - s.cur_attr = (s.cur_attr & ~(0xf << 4)) | (fg << 4); - } else if (n >= 40 && n <= 47) { - /* background */ - bg = n - 40; - s.cur_attr = (s.cur_attr & ~0xf) | bg; - } else if (n >= 90 && n <= 97) { - /* bright foreground */ - fg = n - 90 + 8; - s.cur_attr = (s.cur_attr & ~(0xf << 4)) | (fg << 4); - } else if (n >= 100 && n <= 107) { - /* bright background */ - bg = n - 100 + 8; - s.cur_attr = (s.cur_attr & ~0xf) | bg; - } else if (n == 1) { - /* bold + bright */ - s.cur_attr |= (1 << 8); - } else if (n == 0) { - /* default attr */ - s.cur_attr = s.def_attr; - } else if (n == 7) { - /* inverse */ - s.cur_attr |= (1 << 9); - } else if (n == 27) { - /* not inverse */ - s.cur_attr &= ~(1 << 9); - } else if (n == 39) { - /* reset fg */ - mask = 0x0f << 4; - s.cur_attr = (s.cur_attr & ~mask) | (s.def_attr & mask); - } else if (n == 49) { - /* reset bg */ - mask = 0x0f; - s.cur_attr = (s.cur_attr & ~mask) | (s.def_attr & mask); - } - } - } - } - - function empty_line(y, use_erase_char) { - var line, c, y1, x; - if (use_erase_char) - c = get_erase_char(); - else - c = 32 | (s.def_attr << 16); - line = new Array(); - for(x=0;x= s.cur_h) - y1 -= s.cur_h; - s.lines[y1] = line; - } - - function scroll_down(top, bottom, use_erase_char) - { - var y, line, y1, y2; - - if (top == 0 && bottom == s.h) { - /* increase height of buffer if possible */ - if (s.cur_h < s.tot_h) { - s.cur_h++; - } - /* move down one line */ - if (++s.y_base == s.cur_h) - s.y_base = 0; - s.y_disp = s.y_base; - } else { - /* partial scroll */ - for(y = top; y < bottom - 1; y++) { - y1 = s.y_base + y; - if (y1 >= s.cur_h) - y1 -= s.cur_h; - y2 = y1 + 1; - if (y2 >= s.cur_h) - y2 -= s.cur_h; - s.lines[y1] = s.lines[y2]; - } - } - empty_line(bottom - 1, use_erase_char); - update(top); - update(bottom - 1); - } - - function scroll_up(top, bottom, use_erase_char) { - var y, y1, y2; - /* XXX: could scroll in the history */ - for(y = bottom - 1; y > top; y--) { - y1 = s.y_base + y; - if (y1 >= s.cur_h) - y1 -= s.cur_h; - y2 = y1 - 1; - if (y2 >= s.cur_h) - y2 -= s.cur_h; - s.lines[y1] = s.lines[y2]; - } - empty_line(top, use_erase_char); - update(top); - update(bottom - 1); - } - - function down_with_scroll() { - s.y++; - if (s.y == s.scroll_bottom) { - s.y--; - scroll_down(s.scroll_top, s.scroll_bottom, false); - } else if (s.y >= s.h) { - s.y--; - scroll_down(0, s.h, false); - } - } - - function up_with_scroll() { - if (s.y == s.scroll_top) { - scroll_up(s.scroll_top, s.scroll_bottom, true); - } else if (s.y == 0) { - scroll_up(0, s.h, true); - } else { - s.y--; - } - } - - function insert_lines(n) { - var y2; - if (n < 1) - n = 1; - if (s.y < s.scroll_bottom) - y2 = s.scroll_bottom; - else - y2 = s.h; - while (n != 0) { - scroll_up(s.y, y2, true); - n--; - } - } - - function delete_lines(n) { - var y2; - if (n < 1) - n = 1; - if (s.y < s.scroll_bottom) - y2 = s.scroll_bottom; - else - y2 = s.h; - while (n != 0) { - scroll_down(s.y, y2, true); - n--; - } - } - - var TTY_STATE_NORM = 0; - var TTY_STATE_ESC = 1; - var TTY_STATE_CSI = 2; - var TTY_STATE_CHARSET = 3; - - function handle_char(c) { - var i, l, n, j, y1, y2, x1; - - switch(s.state) { - case TTY_STATE_NORM: - switch(c) { - case 10: - down_with_scroll(); - break; - case 13: - s.x = 0; - break; - case 8: - if (s.x > 0) { - s.x--; - } - break; - case 9: /* tab */ - n = (s.x + 8) & ~7; - if (n <= s.w) { - s.x = n; - } - break; - case 27: - s.state = TTY_STATE_ESC; - break; - default: - if (c >= 32) { - if (s.x >= s.w) { - s.x = 0; - down_with_scroll(); - } - y1 = s.y + s.y_base; - if (y1 >= s.cur_h) - y1 -= s.cur_h; - s.lines[y1][s.x] = (c & 0xffff) | - (s.cur_attr << 16); - s.x++; - update(s.y); - } - break; - } - break; - case TTY_STATE_ESC: - switch(c) { - case 91: // '[' - s.esc_params = new Array(); - s.cur_param = 0; - s.esc_prefix = 0; - s.state = TTY_STATE_CSI; - break; - case 40: // '(' - case 41: // ')' - s.state = TTY_STATE_CHARSET; - break; - case 61: // '=' - s.application_keypad = true; - s.state = TTY_STATE_NORM; - break; - case 62: // '>' - s.application_keypad = false; - s.state = TTY_STATE_NORM; - break; - case 77: // 'M' - up_with_scroll(); - s.state = TTY_STATE_NORM; - break; - default: - s.state = TTY_STATE_NORM; - break; - } - break; - case TTY_STATE_CSI: - if (c >= 48 && c <= 57) { // '0' '9' - /* numeric */ - s.cur_param = s.cur_param * 10 + c - 48; - } else { - if (c == 63) { // '?' - s.esc_prefix = c; - break; - } - /* add parsed parameter */ - s.esc_params[s.esc_params.length] = s.cur_param; - s.cur_param = 0; - if (c == 59) // ; - break; - s.state = TTY_STATE_NORM; - - // console.log("term: csi=" + s.esc_params + " cmd="+c); - switch(c) { - case 64: // '@' insert chars - insert_chars(s.esc_params[0]); - break; - case 65: // 'A' up - n = s.esc_params[0]; - if (n < 1) - n = 1; - s.y -= n; - if (s.y < 0) - s.y = 0; - break; - case 66: // 'B' down - n = s.esc_params[0]; - if (n < 1) - n = 1; - s.y += n; - if (s.y >= s.h) - s.y = s.h - 1; - break; - case 67: // 'C' right - n = s.esc_params[0]; - if (n < 1) - n = 1; - s.x += n; - if (s.x >= s.w - 1) - s.x = s.w - 1; - break; - case 68: // 'D' left - n = s.esc_params[0]; - if (n < 1) - n = 1; - s.x -= n; - if (s.x < 0) - s.x = 0; - break; - case 71: /* 'G' cursor character absolute */ - x1 = s.esc_params[0] - 1; - if (x1 < 0) - x1 = 0; - else if (x1 >= s.w) - x1 = s.w - 1; - s.x = x1; - break; - case 72: // 'H' goto xy - y1 = s.esc_params[0] - 1; - if (s.esc_params.length >= 2) - x1 = s.esc_params[1] - 1; - else - x1 = 0; - if (y1 < 0) - y1 = 0; - else if (y1 >= s.h) - y1 = s.h - 1; - if (x1 < 0) - x1 = 0; - else if (x1 >= s.w) - x1 = s.w - 1; - s.x = x1; - s.y = y1; - break; - case 74: // 'J' erase in display - erase_in_display(s.esc_params[0]); - break; - case 75: // 'K' erase in line - erase_in_line(s.esc_params[0]); - break; - case 76: // 'L' insert lines - insert_lines(s.esc_params[0]); - break; - case 77: // 'M' insert lines - delete_lines(s.esc_params[0]); - break; - case 80: // 'P' - delete_chars(s.esc_params[0]); - break; - case 100: // 'd' line position absolute - { - y1 = s.esc_params[0] - 1; - if (y1 < 0) - y1 = 0; - else if (y1 >= s.h) - y1 = s.h - 1; - s.y = y1; - } - break; - case 104: // 'h': set mode - if (s.esc_prefix == 63 && s.esc_params[0] == 1) { - s.application_cursor = true; - } - break; - case 108: // 'l': reset mode - if (s.esc_prefix == 63 && s.esc_params[0] == 1) { - s.application_cursor = false; - } - break; - case 109: // 'm': set color - csi_colors(s.esc_params); - break; - case 110: // 'n' return the cursor position - s.queue_chars("\x1b[" + (s.y + 1) + ";" + (s.x + 1) + "R"); - break; - case 114: // 'r' set scroll region - y1 = s.esc_params[0] - 1; - if (y1 < 0) - y1 = 0; - else if (y1 >= s.h) - y1 = s.h - 1; - if (s.esc_params.length >= 2) - y2 = s.esc_params[1]; - else - y2 = s.h; - if (y2 >= s.h || y2 <= y1) - y2 = s.h; - s.scroll_top = y1; - s.scroll_bottom = y2; - s.x = 0; - s.y = 0; - break; - default: - break; - } - } - break; - case TTY_STATE_CHARSET: - /* just ignore */ - s.state = TTY_STATE_NORM; - break; - } - } - - function handle_utf8(c) { - if (s.utf8_state !== 0 && (c >= 0x80 && c < 0xc0)) { - s.utf8_val = (s.utf8_val << 6) | (c & 0x3F); - s.utf8_state--; - if (s.utf8_state === 0) { - handle_char(s.utf8_val); - } - } else if (c >= 0xc0 && c < 0xf8) { - s.utf8_state = 1 + (c >= 0xe0) + (c >= 0xf0); - s.utf8_val = c & ((1 << (6 - s.utf8_state)) - 1); - } else { - s.utf8_state = 0; - handle_char(c); - } - } - - var i, c, utf8; - - /* update region is in ymin ymax */ - s = this; - ymin = s.h; - ymax = -1; - update(s.y); // remove the cursor - /* reset top of displayed screen to top of real screen */ - if (s.y_base != s.y_disp) { - s.y_disp = s.y_base; - /* force redraw */ - ymin = 0; - ymax = s.h - 1; - } - utf8 = s.utf8; - for(i = 0; i < str.length; i++) { - c = str.charCodeAt(i); - if (utf8) - handle_utf8(c); - else - handle_char(c); - } - update(s.y); // show the cursor - - if (ymax >= ymin) - s.refresh(ymin, ymax); -}; - -Term.prototype.writeln = function (str) -{ - this.write(str + '\r\n'); -}; - -Term.prototype.interceptBrowserExit = function (ev) -{ - /* At least avoid exiting the navigator if Ctrl-Q or Ctrl-W are - * pressed */ - if (ev.ctrlKey) { - window.onbeforeunload = function() { - window.onbeforeunload = null; - return "CTRL-W or Ctrl-Q cannot be sent to the emulator."; - }; - } else { - window.onbeforeunload = null; - } -} - -Term.prototype.keyDownHandler = function (ev) -{ - var str; - - this.interceptBrowserExit(ev); - - str=""; - switch(ev.keyCode) { - case 8: /* backspace */ - str = "\x7f"; - break; - case 9: /* tab */ - str = "\x09"; - break; - case 13: /* enter */ - str = "\x0d"; - break; - case 27: /* escape */ - str = "\x1b"; - break; - case 37: /* left */ - if (ev.ctrlKey) { - str = "\x1b[1;5D"; - } else if (this.application_cursor) { - str = "\x1bOD"; - } else { - str = "\x1b[D"; - } - break; - case 39: /* right */ - if (ev.ctrlKey) { - str = "\x1b[1;5C"; - } else if (this.application_cursor) { - str = "\x1bOC"; - } else { - str = "\x1b[C"; - } - break; - case 38: /* up */ - if (ev.ctrlKey) { - this.scroll_disp(-1); - } else if (this.application_cursor) { - str = "\x1bOA"; - } else { - str = "\x1b[A"; - } - break; - case 40: /* down */ - if (ev.ctrlKey) { - this.scroll_disp(1); - } else if (this.application_cursor) { - str = "\x1bOB"; - } else { - str = "\x1b[B"; - } - break; - case 46: /* delete */ - str = "\x1b[3~"; - break; - case 45: /* insert */ - str = "\x1b[2~"; - break; - case 36: /* home */ - if (this.linux_console) - str = "\x1b[1~"; - else if (this.application_keypad) - str = "\x1bOH"; - else - str = "\x1b[H"; - break; - case 35: /* end */ - if (this.linux_console) - str = "\x1b[4~"; - else if (this.application_keypad) - str = "\x1bOF"; - else - str = "\x1b[F"; - break; - case 33: /* page up */ - if (ev.ctrlKey) { - this.scroll_disp(-(this.h - 1)); - } else { - str = "\x1b[5~"; - } - break; - case 34: /* page down */ - if (ev.ctrlKey) { - this.scroll_disp(this.h - 1); - } else { - str = "\x1b[6~"; - } - break; - default: - if (ev.ctrlKey) { - /* ctrl + key */ - if (ev.keyCode >= 65 && ev.keyCode <= 90) { - str = String.fromCharCode(ev.keyCode - 64); - } else if (ev.keyCode == 32) { - str = String.fromCharCode(0); - } - } else if ((!this.is_mac && ev.altKey) || - (this.is_mac && ev.metaKey)) { - /* meta + key (Note: we only send lower case) */ - if (ev.keyCode >= 65 && ev.keyCode <= 90) { - str = "\x1b" + String.fromCharCode(ev.keyCode + 32); - } - } - break; - } - // console.log("keydown: keycode=" + ev.keyCode + " charcode=" + ev.charCode + " str=" + str + " ctrl=" + ev.ctrlKey + " alt=" + ev.altKey + " meta=" + ev.metaKey); - if (str) { - if (ev.stopPropagation) - ev.stopPropagation(); - if (ev.preventDefault) - ev.preventDefault(); - - this.show_cursor(); - this.key_rep_state = 1; - this.key_rep_str = str; - this.handler(str); - return false; - } else { - this.key_rep_state = 0; - return true; - } -}; - -Term.prototype.keyUpHandler = function (ev) -{ - this.interceptBrowserExit(ev); -}; - -Term.prototype.to_utf8 = function(s) -{ - var i, n = s.length, r, c; - r = ""; - for(i = 0; i < n; i++) { - c = s.charCodeAt(i); - if (c < 0x80) { - r += String.fromCharCode(c); - } else if (c < 0x800) { - r += String.fromCharCode((c >> 6) | 0xc0, (c & 0x3f) | 0x80); - } else if (c < 0x10000) { - r += String.fromCharCode((c >> 12) | 0xe0, - ((c >> 6) & 0x3f) | 0x80, - (c & 0x3f) | 0x80); - } else { - r += String.fromCharCode((c >> 18) | 0xf0, - ((c >> 12) & 0x3f) | 0x80, - ((c >> 6) & 0x3f) | 0x80, - (c & 0x3f) | 0x80); - } - } - return r; -} - -Term.prototype.keyPressHandler = function (ev) -{ - var str, char_code; - - if (ev.stopPropagation) - ev.stopPropagation(); - if (ev.preventDefault) - ev.preventDefault(); - - str=""; - if (!("charCode" in ev)) { - /* on Opera charCode is not defined and keypress is sent for - system keys. Moreover, only keupress is repeated which is a - problem for system keys. */ - char_code = ev.keyCode; - if (this.key_rep_state == 1) { - this.key_rep_state = 2; - return false; - } else if (this.key_rep_state == 2) { - /* repetition */ - this.show_cursor(); - this.handler(this.key_rep_str); - return false; - } - } else { - char_code = ev.charCode; - } - if (char_code != 0) { - if (!ev.ctrlKey && - ((!this.is_mac && !ev.altKey) || - (this.is_mac && !ev.metaKey))) { - str = String.fromCharCode(char_code); - } - } - // console.log("keypress: keycode=" + ev.keyCode + " charcode=" + ev.charCode + " str=" + str + " ctrl=" + ev.ctrlKey + " alt=" + ev.altKey + " meta=" + ev.metaKey); - if (str) { - this.show_cursor(); - if (this.utf8) - str = this.to_utf8(str); - this.handler(str); - return false; - } else { - return true; - } -}; - -Term.prototype.blurHandler = function (ev) -{ - /* allow unloading the page */ - window.onbeforeunload = null; -}; - -Term.prototype.wheelHandler = function (ev) -{ - if (ev.deltaY < 0) - this.scroll_disp(-3); - else if (ev.deltaY > 0) - this.scroll_disp(3); - ev.stopPropagation(); -} - -Term.prototype.mouseDownHandler = function (ev) -{ - this.thumb_el.onmouseup = this.mouseUpHandler.bind(this); - document.onmousemove = this.mouseMoveHandler.bind(this); - document.onmouseup = this.mouseUpHandler.bind(this); - - /* disable potential selection */ - document.body.className += " noSelect"; - - this.mouseMoveHandler(ev); -} - -Term.prototype.mouseMoveHandler = function (ev) -{ - var total_size, pos, new_y_disp, y, y0; - total_size = this.term_el.clientHeight; - y = ev.clientY - this.track_el.getBoundingClientRect().top; - pos = Math.floor((y - (this.thumb_size / 2)) * this.cur_h / total_size); - new_y_disp = Math.min(Math.max(pos, 0), this.cur_h - this.h); - /* position of the first line of the scroll back buffer */ - y0 = (this.y_base + this.h) % this.cur_h; - new_y_disp += y0; - if (new_y_disp >= this.cur_h) - new_y_disp -= this.cur_h; - if (new_y_disp != this.y_disp) { - this.y_disp = new_y_disp; - this.refresh(0, this.h - 1); - } -} - -Term.prototype.mouseUpHandler = function (ev) -{ - this.thumb_el.onmouseup = null; - document.onmouseup = null; - document.onmousemove = null; - document.body.className = document.body.className.replace(" noSelect", ""); -} - -Term.prototype.pasteHandler = function (ev) -{ - var c = ev.clipboardData, str; - if (c) { - str = c.getData("text/plain"); - if (this.utf8) - str = this.to_utf8(str); - this.queue_chars(str); - setTimeout(this.textAreaReset.bind(this), 10); - return false; - } -} - -Term.prototype.textAreaReset = function(ev) -{ - /* reset text */ - this.textarea_el.value = "Paste Here"; -} - -/* output queue to send back asynchronous responses */ -Term.prototype.queue_chars = function (str) -{ - this.output_queue += str; - if (this.output_queue) - setTimeout(this.outputHandler.bind(this), 0); -}; - -Term.prototype.outputHandler = function () -{ - if (this.output_queue) { - this.handler(this.output_queue); - this.output_queue = ""; - } -}; - -Term.prototype.getSize = function () -{ - return [this.w, this.h]; -};