| 
						
						
							
								
							
						
						
					 | 
					 | 
					@ -82,16 +82,12 @@ window.TermScreen = class TermScreen { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    this.cursor = { | 
					 | 
					 | 
					 | 
					    this.cursor = { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      x: 0, | 
					 | 
					 | 
					 | 
					      x: 0, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      y: 0, | 
					 | 
					 | 
					 | 
					      y: 0, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      fg: 7, | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      bg: 0, | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      attrs: 0, | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      blinkOn: false, | 
					 | 
					 | 
					 | 
					      blinkOn: false, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      blinking: true, | 
					 | 
					 | 
					 | 
					      blinking: true, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      visible: true, | 
					 | 
					 | 
					 | 
					      visible: true, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      hanging: false, | 
					 | 
					 | 
					 | 
					      hanging: false, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      style: 'block', | 
					 | 
					 | 
					 | 
					      style: 'block', | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      blinkEnable: true, | 
					 | 
					 | 
					 | 
					      blinkInterval: null | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      blinkInterval: 0 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    this._palette = null | 
					 | 
					 | 
					 | 
					    this._palette = null | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -131,15 +127,18 @@ window.TermScreen = class TermScreen { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      // though alt can be held to override it
 | 
					 | 
					 | 
					 | 
					      // though alt can be held to override it
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      selectable: true, | 
					 | 
					 | 
					 | 
					      selectable: true, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      // selection start and end (x, y) tuples
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      start: [0, 0], | 
					 | 
					 | 
					 | 
					      start: [0, 0], | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      end: [0, 0] | 
					 | 
					 | 
					 | 
					      end: [0, 0] | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    // mouse features
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    this.mouseMode = { clicks: false, movement: false } | 
					 | 
					 | 
					 | 
					    this.mouseMode = { clicks: false, movement: false } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    // event listeners
 | 
					 | 
					 | 
					 | 
					    // event listeners
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    this._listeners = {} | 
					 | 
					 | 
					 | 
					    this._listeners = {} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    // make writing to window update size and draw
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    const self = this | 
					 | 
					 | 
					 | 
					    const self = this | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    this.window = new Proxy(this._window, { | 
					 | 
					 | 
					 | 
					    this.window = new Proxy(this._window, { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      set (target, key, value, receiver) { | 
					 | 
					 | 
					 | 
					      set (target, key, value, receiver) { | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -157,13 +156,15 @@ window.TermScreen = class TermScreen { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    this.screenBG = [] | 
					 | 
					 | 
					 | 
					    this.screenBG = [] | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    this.screenAttrs = [] | 
					 | 
					 | 
					 | 
					    this.screenAttrs = [] | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    // used to determine if a cell should be redrawn
 | 
					 | 
					 | 
					 | 
					    // used to determine if a cell should be redrawn; storing the current state
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    // as it is on screen
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    this.drawnScreen = [] | 
					 | 
					 | 
					 | 
					    this.drawnScreen = [] | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    this.drawnScreenFG = [] | 
					 | 
					 | 
					 | 
					    this.drawnScreenFG = [] | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    this.drawnScreenBG = [] | 
					 | 
					 | 
					 | 
					    this.drawnScreenBG = [] | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    this.drawnScreenAttrs = [] | 
					 | 
					 | 
					 | 
					    this.drawnScreenAttrs = [] | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    this.drawnCursor = [-1, -1, ''] | 
					 | 
					 | 
					 | 
					    this.drawnCursor = [-1, -1, ''] | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    // start blink timers
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    this.resetBlink() | 
					 | 
					 | 
					 | 
					    this.resetBlink() | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    this.resetCursorBlink() | 
					 | 
					 | 
					 | 
					    this.resetCursorBlink() | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -190,6 +191,8 @@ window.TermScreen = class TermScreen { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      Object.assign(this.selection, this.getNormalizedSelection()) | 
					 | 
					 | 
					 | 
					      Object.assign(this.selection, this.getNormalizedSelection()) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    // bind event listeners
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    this.canvas.addEventListener('mousedown', e => { | 
					 | 
					 | 
					 | 
					    this.canvas.addEventListener('mousedown', e => { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      if ((this.selection.selectable || e.altKey) && e.button === 0) { | 
					 | 
					 | 
					 | 
					      if ((this.selection.selectable || e.altKey) && e.button === 0) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        selectStart(e.offsetX, e.offsetY) | 
					 | 
					 | 
					 | 
					        selectStart(e.offsetX, e.offsetY) | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -207,6 +210,8 @@ window.TermScreen = class TermScreen { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      selectEnd(e.offsetX, e.offsetY) | 
					 | 
					 | 
					 | 
					      selectEnd(e.offsetX, e.offsetY) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }) | 
					 | 
					 | 
					 | 
					    }) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    // touch event listeners
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let touchPosition = null | 
					 | 
					 | 
					 | 
					    let touchPosition = null | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let touchDownTime = 0 | 
					 | 
					 | 
					 | 
					    let touchDownTime = 0 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let touchSelectMinTime = 500 | 
					 | 
					 | 
					 | 
					    let touchSelectMinTime = 500 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -247,6 +252,7 @@ window.TermScreen = class TermScreen { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        e.preventDefault() | 
					 | 
					 | 
					 | 
					        e.preventDefault() | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        selectEnd(...touchPosition) | 
					 | 
					 | 
					 | 
					        selectEnd(...touchPosition) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        // selection ended; show touch select menu
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let touchSelectMenu = qs('#touch-select-menu') | 
					 | 
					 | 
					 | 
					        let touchSelectMenu = qs('#touch-select-menu') | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        touchSelectMenu.classList.add('open') | 
					 | 
					 | 
					 | 
					        touchSelectMenu.classList.add('open') | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let rect = touchSelectMenu.getBoundingClientRect() | 
					 | 
					 | 
					 | 
					        let rect = touchSelectMenu.getBoundingClientRect() | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -333,16 +339,31 @@ window.TermScreen = class TermScreen { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }) | 
					 | 
					 | 
					 | 
					    }) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  /** | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * Bind an event listener to an event | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {string} event - the event name | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {Function} listener - the event listener | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  on (event, listener) { | 
					 | 
					 | 
					 | 
					  on (event, listener) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (!this._listeners[event]) this._listeners[event] = [] | 
					 | 
					 | 
					 | 
					    if (!this._listeners[event]) this._listeners[event] = [] | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    this._listeners[event].push({ listener }) | 
					 | 
					 | 
					 | 
					    this._listeners[event].push({ listener }) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  /** | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * Bind an event listener to be run only once the next time the event fires | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {string} event - the event name | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {Function} listener - the event listener | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  once (event, listener) { | 
					 | 
					 | 
					 | 
					  once (event, listener) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (!this._listeners[event]) this._listeners[event] = [] | 
					 | 
					 | 
					 | 
					    if (!this._listeners[event]) this._listeners[event] = [] | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    this._listeners[event].push({ listener, once: true }) | 
					 | 
					 | 
					 | 
					    this._listeners[event].push({ listener, once: true }) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  /** | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * Remove an event listener | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {string} event - the event name | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {Function} listener - the event listener | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  off (event, listener) { | 
					 | 
					 | 
					 | 
					  off (event, listener) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let listeners = this._listeners[event] | 
					 | 
					 | 
					 | 
					    let listeners = this._listeners[event] | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (listeners) { | 
					 | 
					 | 
					 | 
					    if (listeners) { | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -355,6 +376,11 @@ window.TermScreen = class TermScreen { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  /** | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * Emits an event | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {string} event - the event name | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {...any} args - arguments passed to all listeners | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  emit (event, ...args) { | 
					 | 
					 | 
					 | 
					  emit (event, ...args) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let listeners = this._listeners[event] | 
					 | 
					 | 
					 | 
					    let listeners = this._listeners[event] | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (listeners) { | 
					 | 
					 | 
					 | 
					    if (listeners) { | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -376,6 +402,10 @@ window.TermScreen = class TermScreen { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  /** | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * The color palette. Should define 16 colors in an array. | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @type {number[]} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  get palette () { | 
					 | 
					 | 
					 | 
					  get palette () { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    return this._palette || themes[0] | 
					 | 
					 | 
					 | 
					    return this._palette || themes[0] | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -387,6 +417,14 @@ window.TermScreen = class TermScreen { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  /** | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * Returns the specified color. If `i` is in the palette, it will return the | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * palette color. If `i` is between 16 and 255, it will return the 256color | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * value. If `i` is larger than 255, it will return an RGB color value. If `i` | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * is -1 (foreground) or -2 (background), it will return the selection colors. | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {number} i - the color | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @returns {string} the CSS color | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  getColor (i) { | 
					 | 
					 | 
					 | 
					  getColor (i) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    // return palette color if it exists
 | 
					 | 
					 | 
					 | 
					    // return palette color if it exists
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (this.palette[i]) return this.palette[i] | 
					 | 
					 | 
					 | 
					    if (this.palette[i]) return this.palette[i] | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -411,24 +449,44 @@ window.TermScreen = class TermScreen { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    return 'rgba(0, 0, 0, 0)' | 
					 | 
					 | 
					 | 
					    return 'rgba(0, 0, 0, 0)' | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  // schedule a size update in the next tick
 | 
					 | 
					 | 
					 | 
					  /** | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * Schedule a size update in the next millisecond | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  scheduleSizeUpdate () { | 
					 | 
					 | 
					 | 
					  scheduleSizeUpdate () { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    clearTimeout(this._scheduledSizeUpdate) | 
					 | 
					 | 
					 | 
					    clearTimeout(this._scheduledSizeUpdate) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    this._scheduledSizeUpdate = setTimeout(() => this.updateSize(), 1) | 
					 | 
					 | 
					 | 
					    this._scheduledSizeUpdate = setTimeout(() => this.updateSize(), 1) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  // schedule a draw in the next tick
 | 
					 | 
					 | 
					 | 
					  /** | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * Schedule a draw in the next millisecond | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {string} why - the reason why the draw occured (for debugging) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {number} [aggregateTime] - time to wait for more scheduleDraw calls | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   *   to occur. 1 ms by default. | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  scheduleDraw (why, aggregateTime = 1) { | 
					 | 
					 | 
					 | 
					  scheduleDraw (why, aggregateTime = 1) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    clearTimeout(this._scheduledDraw) | 
					 | 
					 | 
					 | 
					    clearTimeout(this._scheduledDraw) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    this._scheduledDraw = setTimeout(() => this.draw(why), aggregateTime) | 
					 | 
					 | 
					 | 
					    this._scheduledDraw = setTimeout(() => this.draw(why), aggregateTime) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  /** | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * Returns a CSS font string with this TermScreen's font settings and the | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * font modifiers. | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {Object} modifiers | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {string} [modifiers.style] - the font style | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {string} [modifiers.weight] - the font weight | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @returns {string} a CSS font string | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  getFont (modifiers = {}) { | 
					 | 
					 | 
					 | 
					  getFont (modifiers = {}) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let fontStyle = modifiers.style || 'normal' | 
					 | 
					 | 
					 | 
					    let fontStyle = modifiers.style || 'normal' | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let fontWeight = modifiers.weight || 'normal' | 
					 | 
					 | 
					 | 
					    let fontWeight = modifiers.weight || 'normal' | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    return `${fontStyle} normal ${fontWeight} ${this.window.fontSize}px ${this.window.fontFamily}` | 
					 | 
					 | 
					 | 
					    return `${fontStyle} normal ${fontWeight} ${this.window.fontSize}px ${this.window.fontFamily}` | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  /** | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * The character size, used for calculating the cell size. The space character | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * is used for measuring. | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @returns {Object} the character size with `width` and `height` in pixels | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  getCharSize () { | 
					 | 
					 | 
					 | 
					  getCharSize () { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    this.ctx.font = this.getFont() | 
					 | 
					 | 
					 | 
					    this.ctx.font = this.getFont() | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -438,6 +496,10 @@ window.TermScreen = class TermScreen { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  /** | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * The cell size, which is the character size multiplied by the grid scale. | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @returns {Object} the cell size with `width` and `height` in pixels | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  getCellSize () { | 
					 | 
					 | 
					 | 
					  getCellSize () { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let charSize = this.getCharSize() | 
					 | 
					 | 
					 | 
					    let charSize = this.getCharSize() | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -447,6 +509,9 @@ window.TermScreen = class TermScreen { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  /** | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * Updates the canvas size if it changed | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  updateSize () { | 
					 | 
					 | 
					 | 
					  updateSize () { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    this._window.devicePixelRatio = window.devicePixelRatio || 1 | 
					 | 
					 | 
					 | 
					    this._window.devicePixelRatio = window.devicePixelRatio || 1 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -513,6 +578,9 @@ window.TermScreen = class TermScreen { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  /** | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * Resets the cursor blink to on and restarts the timer | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  resetCursorBlink () { | 
					 | 
					 | 
					 | 
					  resetCursorBlink () { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    this.cursor.blinkOn = true | 
					 | 
					 | 
					 | 
					    this.cursor.blinkOn = true | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    clearInterval(this.cursor.blinkInterval) | 
					 | 
					 | 
					 | 
					    clearInterval(this.cursor.blinkInterval) | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -524,6 +592,9 @@ window.TermScreen = class TermScreen { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }, 500) | 
					 | 
					 | 
					 | 
					    }, 500) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  /** | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * Resets the blink style to on and restarts the timer | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  resetBlink () { | 
					 | 
					 | 
					 | 
					  resetBlink () { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    this.window.blinkStyleOn = true | 
					 | 
					 | 
					 | 
					    this.window.blinkStyleOn = true | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    clearInterval(this.window.blinkInterval) | 
					 | 
					 | 
					 | 
					    clearInterval(this.window.blinkInterval) | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -542,6 +613,11 @@ window.TermScreen = class TermScreen { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }, 200) | 
					 | 
					 | 
					 | 
					    }, 200) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  /** | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * Returns a normalized version of the current selection, such that `start` | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * is always before `end`. | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @returns {Object} the normalized selection, with `start` and `end` | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  getNormalizedSelection () { | 
					 | 
					 | 
					 | 
					  getNormalizedSelection () { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let { start, end } = this.selection | 
					 | 
					 | 
					 | 
					    let { start, end } = this.selection | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    // if the start line is after the end line, or if they're both on the same
 | 
					 | 
					 | 
					 | 
					    // if the start line is after the end line, or if they're both on the same
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -552,6 +628,12 @@ window.TermScreen = class TermScreen { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    return { start, end } | 
					 | 
					 | 
					 | 
					    return { start, end } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  /** | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * Returns whether or not a given cell is in the current selection. | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {number} col - the column (x) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {number} line - the line (y) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @returns {boolean} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  isInSelection (col, line) { | 
					 | 
					 | 
					 | 
					  isInSelection (col, line) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let { start, end } = this.getNormalizedSelection() | 
					 | 
					 | 
					 | 
					    let { start, end } = this.getNormalizedSelection() | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let colAfterStart = start[0] <= col | 
					 | 
					 | 
					 | 
					    let colAfterStart = start[0] <= col | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -565,6 +647,10 @@ window.TermScreen = class TermScreen { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    else return start[1] < line && line < end[1] | 
					 | 
					 | 
					 | 
					    else return start[1] < line && line < end[1] | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  /** | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * Sweeps for selected cells and joins them in a multiline string. | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @returns {string} the selection | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  getSelectedText () { | 
					 | 
					 | 
					 | 
					  getSelectedText () { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    const screenLength = this.window.width * this.window.height | 
					 | 
					 | 
					 | 
					    const screenLength = this.window.width * this.window.height | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let lines = [] | 
					 | 
					 | 
					 | 
					    let lines = [] | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -586,6 +672,9 @@ window.TermScreen = class TermScreen { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    return lines.join('\n') | 
					 | 
					 | 
					 | 
					    return lines.join('\n') | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  /** | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * Copies the selection to clipboard and creates a notification balloon. | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  copySelectionToClipboard () { | 
					 | 
					 | 
					 | 
					  copySelectionToClipboard () { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let selectedText = this.getSelectedText() | 
					 | 
					 | 
					 | 
					    let selectedText = this.getSelectedText() | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    // don't copy anything if nothing is selected
 | 
					 | 
					 | 
					 | 
					    // don't copy anything if nothing is selected
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -602,6 +691,12 @@ window.TermScreen = class TermScreen { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    document.body.removeChild(textarea) | 
					 | 
					 | 
					 | 
					    document.body.removeChild(textarea) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  /** | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * Converts screen coordinates to grid coordinates. | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {number} x - x in pixels | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {number} y - y in pixels | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @returns {number[]} a tuple of (x, y) in cells | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  screenToGrid (x, y) { | 
					 | 
					 | 
					 | 
					  screenToGrid (x, y) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let cellSize = this.getCellSize() | 
					 | 
					 | 
					 | 
					    let cellSize = this.getCellSize() | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -611,12 +706,27 @@ window.TermScreen = class TermScreen { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    ] | 
					 | 
					 | 
					 | 
					    ] | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  /** | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * Converts grid coordinates to screen coordinates. | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {number} x - x in cells | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {number} y - y in cells | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @returns {number[]} a tuple of (x, y) in pixels | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  gridToScreen (x, y) { | 
					 | 
					 | 
					 | 
					  gridToScreen (x, y) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let cellSize = this.getCellSize() | 
					 | 
					 | 
					 | 
					    let cellSize = this.getCellSize() | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    return [ x * cellSize.width, y * cellSize.height ] | 
					 | 
					 | 
					 | 
					    return [x * cellSize.width, y * cellSize.height] | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  /** | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * Draws a cell's background with the given parameters. | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {Object} options | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {number} options.x - x in cells | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {number} options.y - y in cells | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {number} options.cellWidth - cell width in pixels | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {number} options.cellHeight - cell height in pixels | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {number} options.bg - the background color | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  drawCellBackground ({ x, y, cellWidth, cellHeight, bg }) { | 
					 | 
					 | 
					 | 
					  drawCellBackground ({ x, y, cellWidth, cellHeight, bg }) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    const ctx = this.ctx | 
					 | 
					 | 
					 | 
					    const ctx = this.ctx | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    ctx.fillStyle = this.getColor(bg) | 
					 | 
					 | 
					 | 
					    ctx.fillStyle = this.getColor(bg) | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -624,6 +734,20 @@ window.TermScreen = class TermScreen { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    ctx.fillRect(x * cellWidth, y * cellHeight, Math.ceil(cellWidth), Math.ceil(cellHeight)) | 
					 | 
					 | 
					 | 
					    ctx.fillRect(x * cellWidth, y * cellHeight, Math.ceil(cellWidth), Math.ceil(cellHeight)) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  /** | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * Draws a cell's character with the given parameters. Won't do anything if | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * text is an empty string. | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {Object} options | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {number} options.x - x in cells | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {number} options.y - y in cells | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {Object} options.charSize - the character size, an object with | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   *   `width` and `height` in pixels | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {number} options.cellWidth - cell width in pixels | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {number} options.cellHeight - cell height in pixels | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {string} options.text - the cell content | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {number} options.fg - the foreground color | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {number} options.attrs - the cell's attributes | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  drawCell ({ x, y, charSize, cellWidth, cellHeight, text, fg, attrs }) { | 
					 | 
					 | 
					 | 
					  drawCell ({ x, y, charSize, cellWidth, cellHeight, text, fg, attrs }) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (!text) return | 
					 | 
					 | 
					 | 
					    if (!text) return | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -671,6 +795,12 @@ window.TermScreen = class TermScreen { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    ctx.globalAlpha = 1 | 
					 | 
					 | 
					 | 
					    ctx.globalAlpha = 1 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  /** | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * Returns all adjacent cell indices given a radius. | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {number} cell - the center cell index | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {number} [radius] - the radius. 1 by default | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @returns {number[]} an array of cell indices | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  getAdjacentCells (cell, radius = 1) { | 
					 | 
					 | 
					 | 
					  getAdjacentCells (cell, radius = 1) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    const { width, height } = this.window | 
					 | 
					 | 
					 | 
					    const { width, height } = this.window | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    const screenLength = width * height | 
					 | 
					 | 
					 | 
					    const screenLength = width * height | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -687,6 +817,10 @@ window.TermScreen = class TermScreen { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    return cells.filter(cell => cell >= 0 && cell < screenLength) | 
					 | 
					 | 
					 | 
					    return cells.filter(cell => cell >= 0 && cell < screenLength) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  /** | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * Updates the screen. | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {string} why - the draw reason (for debugging) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  draw (why) { | 
					 | 
					 | 
					 | 
					  draw (why) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    const ctx = this.ctx | 
					 | 
					 | 
					 | 
					    const ctx = this.ctx | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    const { | 
					 | 
					 | 
					 | 
					    const { | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -726,7 +860,8 @@ window.TermScreen = class TermScreen { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      let isCursor = !this.cursor.hanging && | 
					 | 
					 | 
					 | 
					      let isCursor = !this.cursor.hanging && | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        this.cursor.x === x && | 
					 | 
					 | 
					 | 
					        this.cursor.x === x && | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        this.cursor.y === y && | 
					 | 
					 | 
					 | 
					        this.cursor.y === y && | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        this.cursor.blinkOn | 
					 | 
					 | 
					 | 
					        this.cursor.blinkOn && | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        this.cursor.visible | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      let wasCursor = x === this.drawnCursor[0] && y === this.drawnCursor[1] | 
					 | 
					 | 
					 | 
					      let wasCursor = x === this.drawnCursor[0] && y === this.drawnCursor[1] | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -899,6 +1034,10 @@ window.TermScreen = class TermScreen { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (this.window.debug && this._debug) this._debug.drawEnd() | 
					 | 
					 | 
					 | 
					    if (this.window.debug && this._debug) this._debug.drawEnd() | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  /** | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * Parses the content of an `S` message and schedules a draw | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {string} str - the message content | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  loadContent (str) { | 
					 | 
					 | 
					 | 
					  loadContent (str) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    // current index
 | 
					 | 
					 | 
					 | 
					    // current index
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let i = 0 | 
					 | 
					 | 
					 | 
					    let i = 0 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -1075,7 +1214,11 @@ window.TermScreen = class TermScreen { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    this.emit('load') | 
					 | 
					 | 
					 | 
					    this.emit('load') | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  /** Apply labels to buttons and screen title (leading T removed already) */ | 
					 | 
					 | 
					 | 
					  /** | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * Parses the content of a `T` message and updates the screen title and button | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * labels. | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {string} str - the message content | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  loadLabels (str) { | 
					 | 
					 | 
					 | 
					  loadLabels (str) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let pieces = str.split('\x01') | 
					 | 
					 | 
					 | 
					    let pieces = str.split('\x01') | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    qs('h1').textContent = pieces[0] | 
					 | 
					 | 
					 | 
					    qs('h1').textContent = pieces[0] | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -1088,6 +1231,10 @@ window.TermScreen = class TermScreen { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }) | 
					 | 
					 | 
					 | 
					    }) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  /** | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * Shows an actual notification (if possible) or a notification balloon. | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {string} text - the notification content | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  showNotification (text) { | 
					 | 
					 | 
					 | 
					  showNotification (text) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    console.info(`Notification: ${text}`) | 
					 | 
					 | 
					 | 
					    console.info(`Notification: ${text}`) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (Notification && Notification.permission === 'granted') { | 
					 | 
					 | 
					 | 
					    if (Notification && Notification.permission === 'granted') { | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -1105,6 +1252,11 @@ window.TermScreen = class TermScreen { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  /** | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * Loads a message from the server, and optionally a theme. | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {string} str - the message | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {number} [theme] - the new theme index | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  load (str, theme = -1) { | 
					 | 
					 | 
					 | 
					  load (str, theme = -1) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    const content = str.substr(1) | 
					 | 
					 | 
					 | 
					    const content = str.substr(1) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (theme >= 0 && theme < themes.length) { | 
					 | 
					 | 
					 | 
					    if (theme >= 0 && theme < themes.length) { | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -1133,6 +1285,9 @@ window.TermScreen = class TermScreen { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  /** | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * Creates a beep sound. | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  beep () { | 
					 | 
					 | 
					 | 
					  beep () { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    const audioCtx = this.audioCtx | 
					 | 
					 | 
					 | 
					    const audioCtx = this.audioCtx | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (!audioCtx) return | 
					 | 
					 | 
					 | 
					    if (!audioCtx) return | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -1166,6 +1321,11 @@ window.TermScreen = class TermScreen { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    osc.stop(audioCtx.currentTime + 0.08) | 
					 | 
					 | 
					 | 
					    osc.stop(audioCtx.currentTime + 0.08) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  /** | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * Converts an alphabetic character to its fraktur variant. | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @param {string} character - the character | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   * @returns {string} the converted character | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					   */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  static alphaToFraktur (character) { | 
					 | 
					 | 
					 | 
					  static alphaToFraktur (character) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (character >= 'a' && character <= 'z') { | 
					 | 
					 | 
					 | 
					    if (character >= 'a' && character <= 'z') { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      character = String.fromCodePoint(0x1d51e - 0x61 + character.charCodeAt(0)) | 
					 | 
					 | 
					 | 
					      character = String.fromCodePoint(0x1d51e - 0x61 + character.charCodeAt(0)) | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
					 | 
					
  |