2023-01-31 08:47:50 +04:00
require = ( function e ( t , n , r ) { function s ( o , u ) { if ( ! n [ o ] ) { if ( ! t [ o ] ) { var a = typeof require == "function" && require ; if ( ! u && a ) return a ( o , ! 0 ) ; if ( i ) return i ( o , ! 0 ) ; var f = new Error ( "Cannot find module '" + o + "'" ) ; throw f . code = "MODULE_NOT_FOUND" , f } var l = n [ o ] = { exports : { } } ; t [ o ] [ 0 ] . call ( l . exports , function ( e ) { var n = t [ o ] [ 1 ] [ e ] ; return s ( n ? n : e ) } , l , l . exports , e , t , n , r ) } return n [ o ] . exports } var i = typeof require == "function" && require ; for ( var o = 0 ; o < r . length ; o ++ ) s ( r [ o ] ) ; return s } ) ( { 1 : [ function ( require , module , exports ) {
//download.js v3.1, by dandavis; 2008-2014. [CCBY2] see http://danml.com/download.html for tests/usage
// v1 landed a FF+Chrome compat way of downloading strings to local un-named files, upgraded to use a hidden frame and optional mime
// v2 added named files via a[download], msSaveBlob, IE (10+) support, and window.URL support for larger+faster saves than dataURLs
// v3 added dataURL and Blob Input, bind-toggle arity, and legacy dataURL fallback was improved with force-download mime and base64 support. 3.1 improved safari handling.
// https://github.com/rndme/download
// data can be a string, Blob, File, or dataURL
function download ( data , strFileName , strMimeType ) {
var self = window , // this script is only for browsers anyway...
u = "application/octet-stream" , // this default mime also triggers iframe downloads
m = strMimeType || u ,
x = data ,
D = document ,
a = D . createElement ( "a" ) ,
z = function ( a ) { return String ( a ) ; } ,
B = ( self . Blob || self . MozBlob || self . WebKitBlob || z ) ;
B = B . call ? B . bind ( self ) : Blob ;
var fn = strFileName || "download" ,
blob ,
fr ;
if ( String ( this ) === "true" ) { //reverse arguments, allowing download.bind(true, "text/xml", "export.xml") to act as a callback
x = [ x , m ] ;
m = x [ 0 ] ;
x = x [ 1 ] ;
}
//go ahead and download dataURLs right away
if ( String ( x ) . match ( /^data\:[\w+\-]+\/[\w+\-]+[,;]/ ) ) {
return navigator . msSaveBlob ? // IE10 can't do a[download], only Blobs:
navigator . msSaveBlob ( d2b ( x ) , fn ) :
saver ( x ) ; // everyone else can save dataURLs un-processed
} //end if dataURL passed?
blob = x instanceof B ?
x :
new B ( [ x ] , { type : m } ) ;
function d2b ( u ) {
var p = u . split ( /[:;,]/ ) ,
t = p [ 1 ] ,
dec = p [ 2 ] == "base64" ? atob : decodeURIComponent ,
bin = dec ( p . pop ( ) ) ,
mx = bin . length ,
i = 0 ,
uia = new Uint8Array ( mx ) ;
for ( i ; i < mx ; ++ i ) uia [ i ] = bin . charCodeAt ( i ) ;
return new B ( [ uia ] , { type : t } ) ;
}
function saver ( url , winMode ) {
if ( 'download' in a ) { //html5 A[download]
a . href = url ;
a . setAttribute ( "download" , fn ) ;
a . innerHTML = "downloading..." ;
D . body . appendChild ( a ) ;
setTimeout ( function ( ) {
a . click ( ) ;
D . body . removeChild ( a ) ;
if ( winMode === true ) { setTimeout ( function ( ) { self . URL . revokeObjectURL ( a . href ) ; } , 250 ) ; }
} , 66 ) ;
return true ;
}
if ( typeof safari !== "undefined" ) { // handle non-a[download] safari as best we can:
url = "data:" + url . replace ( /^data:([\w\/\-\+]+)/ , u ) ;
if ( ! window . open ( url ) ) { // popup blocked, offer direct download:
if ( confirm ( "Displaying New Document\n\nUse Save As... to download, then click back to return to this page." ) ) { location . href = url ; }
}
return true ;
}
//do iframe dataURL download (old ch+FF):
var f = D . createElement ( "iframe" ) ;
D . body . appendChild ( f ) ;
if ( ! winMode ) { // force a mime that will download:
url = "data:" + url . replace ( /^data:([\w\/\-\+]+)/ , u ) ;
}
f . src = url ;
setTimeout ( function ( ) { D . body . removeChild ( f ) ; } , 333 ) ;
} //end saver
if ( navigator . msSaveBlob ) { // IE10+ : (has Blob, but not a[download] or URL)
return navigator . msSaveBlob ( blob , fn ) ;
}
if ( self . URL ) { // simple fast and modern way using Blob and URL:
saver ( self . URL . createObjectURL ( blob ) , true ) ;
} else {
// handle non-Blob()+non-URL browsers:
if ( typeof blob === "string" || blob . constructor === z ) {
try {
return saver ( "data:" + m + ";base64," + self . btoa ( blob ) ) ;
} catch ( y ) {
return saver ( "data:" + m + "," + encodeURIComponent ( blob ) ) ;
}
}
// Blob but not URL:
fr = new FileReader ( ) ;
fr . onload = function ( e ) {
saver ( this . result ) ;
} ;
fr . readAsDataURL ( blob ) ;
}
return true ;
} /* end download() */
module . exports = download ;
} , { } ] , 2 : [ function ( require , module , exports ) {
// -------------------------------------------------
// ------------------ UTF8 Helpers -----------------
// -------------------------------------------------
// http://en.wikipedia.org/wiki/UTF-8
"use strict" ;
function UTF8StreamToUnicode ( ) {
this . stream = new Uint8Array ( 5 ) ;
this . ofs = 0 ;
this . Put = function ( key ) {
this . stream [ this . ofs ] = key ;
this . ofs ++ ;
switch ( this . ofs ) {
case 1 :
if ( this . stream [ 0 ] < 0x80 ) {
this . ofs = 0 ;
return this . stream [ 0 ] ;
}
break ;
case 2 :
if ( ( this . stream [ 0 ] & 0xE0 ) == 0xC0 )
if ( ( this . stream [ 1 ] & 0xC0 ) == 0x80 ) {
this . ofs = 0 ;
return ( ( this . stream [ 0 ] & 0x1F ) << 6 ) |
( ( this . stream [ 1 ] & 0x3F ) << 0 ) ;
}
break ;
case 3 :
if ( ( this . stream [ 0 ] & 0xF0 ) == 0xE0 )
if ( ( this . stream [ 1 ] & 0xC0 ) == 0x80 )
if ( ( this . stream [ 2 ] & 0xC0 ) == 0x80 ) {
this . ofs = 0 ;
return ( ( this . stream [ 0 ] & 0xF ) << 12 ) |
( ( this . stream [ 1 ] & 0x3F ) << 6 ) |
( ( this . stream [ 2 ] & 0x3F ) << 0 ) ;
}
break ;
case 4 :
if ( ( this . stream [ 0 ] & 0xF8 ) == 0xF0 )
if ( ( this . stream [ 1 ] & 0xC0 ) == 0x80 )
if ( ( this . stream [ 2 ] & 0xC0 ) == 0x80 )
if ( ( this . stream [ 3 ] & 0xC0 ) == 0x80 ) {
this . ofs = 0 ;
return ( ( this . stream [ 0 ] & 0x7 ) << 18 ) |
( ( this . stream [ 1 ] & 0x3F ) << 12 ) |
( ( this . stream [ 2 ] & 0x3F ) << 6 ) |
( ( this . stream [ 3 ] & 0x3F ) << 0 ) ;
}
this . ofs = 0 ;
return - 1 ; //obviously illegal character, so reset
break ;
default :
this . ofs = 0 ;
return - 1 ;
break ;
}
return - 1 ;
}
}
function UnicodeToUTF8Stream ( key ) {
key = key | 0 ;
if ( key < 0x80 ) {
return [ key ] ;
} else
if ( key <= 0x7FF ) {
return [
( key >> 6 ) | 0xC0 ,
( key & 0x3F ) | 0x80
] ;
} else
if ( key <= 0xFFFF ) {
return [
( key >> 12 ) | 0xE0 ,
( ( key >> 6 ) & 0x3F ) | 0x80 ,
( key & 0x3F ) | 0x80
] ;
} else
if ( key <= 0x10FFFF ) {
return [
( key >> 18 ) | 0xF0 ,
( ( key >> 12 ) & 0x3F ) | 0x80 ,
( ( key >> 6 ) & 0x3F ) | 0x80 ,
( key & 0x3F ) | 0x80
] ;
} else {
//message.Debug("Error in utf-8 encoding: Invalid key");
}
return [ ] ;
}
function UTF8Length ( s )
{
var length = 0 ;
for ( var i = 0 ; i < s . length ; i ++ ) {
var key = s . charCodeAt ( i ) ;
if ( key < 0x80 ) {
length += 1 ;
} else
if ( key <= 0x7FF ) {
length += 2 ;
} else
if ( key <= 0xFFFF ) {
length += 3 ;
} else
if ( key <= 0x10FFFF ) {
length += 4 ;
} else {
}
}
return length ;
}
module . exports . UTF8StreamToUnicode = UTF8StreamToUnicode ;
module . exports . UTF8Length = UTF8Length ;
module . exports . UnicodeToUTF8Stream = UnicodeToUTF8Stream ;
} , { } ] , 3 : [ function ( require , module , exports ) {
// manages the websocket connection for the ethmac peripheral
var message = require ( '../messagehandler' ) ;
"use strict" ;
function Ethernet ( relayURL ) {
this . url = relayURL ;
this . onmessage = function ( e ) { } ;
this . ntries = 0 ;
this . OpenSocket ( ) ;
}
function EthernetMessageHandler ( e ) {
// if we recv binary data, call the onmessage handler
// which was assigned to this Ethernet object
if ( e . data instanceof ArrayBuffer ) {
this . onmessage ( e ) ;
} else
// otherwise, this might be a textual "ping" message to keep
// the connection alive
if ( e . data . toString ( ) . indexOf ( 'ping:' ) == 0 ) {
this . socket . send ( 'pong:' + e . data . toString ( ) . substring ( 5 ) ) ;
}
}
function EthernetOpenHandler ( e ) {
this . ntries = 0 ;
}
function EthernetCloseHandler ( e ) {
// reopen websocket if it closes
if ( this . ntries > 3 ) {
message . Debug ( "Websocket error: Connection failed" ) ;
return ;
}
this . ntries ++ ;
message . Debug ( "Websocket closed. Reopening." ) ;
this . OpenSocket ( ) ;
}
function EthernetErrorHandler ( e ) {
// just report the error to console, close event
// will handle reopening if possible
message . Debug ( "Websocket error:" ) ;
message . Debug ( e ) ;
}
Ethernet . prototype . OpenSocket = function ( ) {
try {
this . socket = new WebSocket ( this . url ) ;
} catch ( err ) {
delete this . socket ;
EthernetErrorHandler ( err ) ;
return ;
}
this . socket . binaryType = 'arraybuffer' ;
this . socket . onmessage = EthernetMessageHandler . bind ( this ) ;
this . socket . onclose = EthernetCloseHandler . bind ( this ) ;
this . socket . onopen = EthernetOpenHandler . bind ( this ) ;
this . socket . onerror = EthernetErrorHandler . bind ( this ) ;
}
Ethernet . prototype . SendFrame = function ( data ) {
if ( typeof this . socket == "undefined" ) return ;
try {
this . socket . send ( data ) ;
} catch ( err ) {
// this is unusual error, object exists, but send does not work
EthernetErrorHandler ( err ) ;
}
}
Ethernet . prototype . Close = function ( ) {
this . socket . onclose = undefined ;
this . socket . close ( ) ;
}
module . exports = Ethernet ;
} , { "../messagehandler" : 9 } ] , 4 : [ function ( require , module , exports ) {
var message = require ( '../messagehandler' ) ;
var download = require ( '../../lib/download' ) ;
var utils = require ( '../utils' ) ;
"use strict" ;
function Filesystem ( syncURL , userid ) {
this . syncURL = syncURL ;
this . userid = userid ;
}
Filesystem . prototype . TAR = function ( path ) {
message . Register ( "tar" , function ( d ) { download ( d , "user.tar" , "application/x-tar" ) ; } ) ;
message . Send ( "tar" , path ) ;
}
Filesystem . prototype . Sync = function ( path ) {
message . Register ( "sync" , this . OnSync . bind ( this ) ) ;
message . Send ( "sync" , path ) ;
}
Filesystem . prototype . OnSync = function ( d ) {
utils . UploadBinaryResource ( this . syncURL , this . userid + ".tar" , d ,
function ( response ) {
alert (
"Message from Server:" + response + "\n" +
"The home folder '/home/alice' has been synced with the server\n" +
"In order to access the data at a later date,\n" +
"start the next session with the current url with the user id\n" +
"The folder size is currently limited to 1MB. Note that the feature is experimental.\n" +
"The content can be downloaded under http://jor1k.com/sync/tarballs/" + this . userid + ".tar.bz2"
) ;
} . bind ( this ) ,
function ( msg ) { alert ( msg ) ; }
) ;
}
Filesystem . prototype . UploadExternalFile = function ( f ) {
var reader = new FileReader ( ) ;
reader . onload = function ( e ) {
message . Send ( "MergeFile" ,
{ name : "home/alice/" + f . name , data : new Uint8Array ( reader . result ) } ) ;
} . bind ( this ) ;
reader . readAsArrayBuffer ( f ) ;
}
Filesystem . prototype . MergeFile = function ( fileName , data ) {
function stringToUint ( string ) {
var charList = string . split ( '' ) ,
uintArray = [ ] ;
for ( var i = 0 ; i < charList . length ; i ++ ) {
uintArray . push ( charList [ i ] . charCodeAt ( 0 ) ) ;
}
return new Uint8Array ( uintArray ) ;
}
message . Send ( "MergeFile" , { name : fileName , data : stringToUint ( data ) } ) ;
}
Filesystem . prototype . MergeBinaryFile = function ( fileName , data ) {
message . Send ( "MergeFile" , { name : fileName , data : data } ) ;
}
Filesystem . prototype . CreateDirectory = function ( dirctoryName ) {
message . Send ( "CreateDirectory" , dirctoryName ) ;
}
Filesystem . prototype . ReadFile = function ( fileName , callback ) {
message . Register ( "ReadFile" , callback ) ;
message . Send ( "ReadFile" , { name : fileName } ) ;
}
//deletes contents of specified directory.
Filesystem . prototype . DeleteDirContents = function ( dirPath ) {
message . Send ( "DeleteDirContents" , dirPath ) ;
}
//deletes file, recursively deletes dir
Filesystem . prototype . DeleteNode = function ( nodeName ) {
message . Send ( "DeleteNode" , nodeName ) ;
}
Filesystem . prototype . Rename = function ( oldPath , newPath ) {
message . Send ( "Rename" , { oldPath : oldPath , newPath : newPath } ) ;
}
Filesystem . prototype . WatchFile = function ( fileName , callback ) {
message . Register ( "WatchFileEvent" , callback ) ;
message . Send ( "WatchFile" , { name : fileName } ) ;
}
Filesystem . prototype . WatchDirectory = function ( directoryPath , callback ) {
message . Register ( "WatchDirectoryEvent" , callback ) ;
message . Send ( "WatchDirectory" , { name : directoryPath } ) ;
}
module . exports = Filesystem ;
} , { "../../lib/download" : 1 , "../messagehandler" : 9 , "../utils" : 11 } ] , 5 : [ function ( require , module , exports ) {
var message = require ( '../messagehandler' ) ;
"use strict" ;
function Framebuffer ( fbid , fps ) {
this . fbid = fbid ;
this . Init ( fbid ) ;
this . SetFPS ( fps ) ;
}
// Init Framebuffer if it exists
Framebuffer . prototype . Init = function ( fbid ) {
this . fbcanvas = document . getElementById ( fbid ) ;
if ( ! this . fbcanvas ) return ;
this . fbctx = this . fbcanvas . getContext ( "2d" ) ;
this . fbctx . fillStyle = "rgba(0, 0, 0, 255)" ;
this . fbctx . fillRect ( 0 , 0 , this . fbcanvas . width , this . fbcanvas . height ) ;
this . fbimageData = this . fbctx . createImageData ( this . fbcanvas . width , this . fbcanvas . height ) ;
this . fbcanvas . onmousedown = function ( event ) {
this . fbcanvas . style . border = "2px solid #FF0000" ;
var rect = this . fbcanvas . getBoundingClientRect ( ) ;
var x = ( event . clientX - rect . left ) * 640 / rect . width ;
var y = ( event . clientY - rect . top ) * 400 / rect . height ;
message . Send ( "tsmousedown" , { x : x , y : y } ) ;
} . bind ( this ) ;
this . fbcanvas . onmouseup = function ( event ) {
var rect = this . fbcanvas . getBoundingClientRect ( ) ;
var x = ( event . clientX - rect . left ) * 640 / rect . width ;
var y = ( event . clientY - rect . top ) * 400 / rect . height ;
message . Send ( "tsmouseup" , { x : x , y : y } ) ;
} . bind ( this ) ;
this . fbcanvas . onmousemove = function ( event ) {
var rect = this . fbcanvas . getBoundingClientRect ( ) ;
var x = ( event . clientX - rect . left ) * 640 / rect . width ;
var y = ( event . clientY - rect . top ) * 400 / rect . height ;
message . Send ( "tsmousemove" , { x : x , y : y } ) ;
} . bind ( this ) ;
}
// receive interval of the contents of the framebuffer
Framebuffer . prototype . SetFPS = function ( fps ) {
this . fps = fps ;
if ( ! this . fbcanvas ) return ;
if ( this . fbinterval ) {
window . clearInterval ( this . fbinterval ) ;
}
if ( fps != 0 ) {
this . fbinterval = window . setInterval ( function ( ) { message . Send ( "GetFB" , 0 ) } . bind ( this ) , 1000 / this . fps ) ;
}
}
Framebuffer . prototype . Update = function ( buffer ) {
if ( ! this . fbcanvas ) return ;
//if(this.userpaused) return;
var i = 0 , n = buffer . length ;
var data = this . fbimageData . data ;
var offset = 0x0 ;
for ( i = 0 ; i < n ; i ++ ) {
var x = buffer [ i ] ;
data [ offset ++ ] = ( x >> 24 ) & 0xF8 ;
data [ offset ++ ] = ( x >> 19 ) & 0xFC ;
data [ offset ++ ] = ( x >> 13 ) & 0xF8 ;
data [ offset ++ ] = 0xFF ;
data [ offset ++ ] = ( x >> 8 ) & 0xF8 ;
data [ offset ++ ] = ( x >> 3 ) & 0xFC ;
data [ offset ++ ] = ( x << 3 ) & 0xF8 ;
data [ offset ++ ] = 0xFF ;
}
//data.set(buffer);
this . fbctx . putImageData ( this . fbimageData , 0 , 0 ) ; // at coords 0,0
}
module . exports = Framebuffer ;
} , { "../messagehandler" : 9 } ] , 6 : [ function ( require , module , exports ) {
// Provides a loop sound buffer.
var message = require ( '../messagehandler' ) ;
"use strict" ;
function LoopSoundBuffer ( samplerate ) {
this . enabled = false ;
this . nperiods = 8 ; // number of periods
this . source = new Array ( this . nperiods ) ;
this . soundbuffer = new Array ( this . nperiods ) ;
this . period = 0 ;
this . periodsize = 0 ;
this . bufferpos = 0 ;
if ( typeof AudioContext == "undefined" ) return ;
this . context = new AudioContext ( ) ;
this . SetRate ( samplerate ) ;
}
LoopSoundBuffer . prototype . SetRate = function ( rate ) {
if ( this . samplerate == rate ) return ;
this . samplerate = rate ;
this . periodsize = Math . floor ( this . samplerate / 4 ) ; // 250ms
this . sampleslen = this . periodsize * this . nperiods ;
this . buffer = new Float32Array ( this . sampleslen ) ;
for ( var i = 0 ; i < this . nperiods ; i ++ ) {
this . soundbuffer [ i ] = this . context . createBuffer ( 1 , this . periodsize , this . samplerate ) ;
}
}
LoopSoundBuffer . prototype . OnEnded = function ( )
{
if ( ! this . enabled ) return ;
this . PlayBuffer ( this . period ) ;
this . period ++ ;
}
LoopSoundBuffer . prototype . Enabled = function ( e )
{
this . enabled = e ;
if ( ! e ) return ;
this . period = 0 ;
this . basetime = this . context . currentTime ;
this . PlayBuffer ( 0 ) ;
this . PlayBuffer ( 1 ) ;
this . period = 2 ;
this . bufferpos = this . periodsize * ( this . period + 4 ) ;
}
LoopSoundBuffer . prototype . PlayBuffer = function ( period )
{
if ( ! this . enabled ) return ;
var idx = period % this . nperiods ;
var buffer = this . soundbuffer [ idx ] . getChannelData ( 0 ) ;
var offset = idx * this . periodsize ;
for ( var i = 0 ; i < this . periodsize ; i ++ ) {
buffer [ i ] = this . buffer [ i + offset ] ;
this . buffer [ i + offset ] = 0 ;
}
var source = this . context . createBufferSource ( ) ; // creates a sound source
source . buffer = this . soundbuffer [ idx ] ;
source . connect ( this . context . destination ) ;
source . onended = this . OnEnded . bind ( this ) ;
source . start ( this . basetime + period * ( this . periodsize ) / this . samplerate ) ;
// save the source. Otherwise the garbage collector might take them and the function OnEnded is not executed
this . source [ idx ] = source ;
}
LoopSoundBuffer . prototype . AddBuffer = function ( addbuffer )
{
if ( ! this . enabled ) return ;
var currentperiod = ( this . bufferpos / this . periodsize ) ;
if ( ( currentperiod ) < ( this . period + 2 ) ) {
this . bufferpos = this . periodsize * ( this . period + 4 ) ;
//message.Debug("Warning: Sound buffer underrun, resetting");
}
if ( currentperiod > ( this . period + 5 ) ) {
this . bufferpos = this . periodsize * ( this . period + 4 ) ;
//message.Debug("Warning: Sound buffer overrun, resetting");
}
for ( var i = 0 ; i < addbuffer . length ; i ++ ) {
this . buffer [ this . bufferpos % this . sampleslen ] = addbuffer [ i ] / 128. ;
this . bufferpos ++ ;
}
}
module . exports = LoopSoundBuffer ;
} , { "../messagehandler" : 9 } ] , 7 : [ function ( require , module , exports ) {
// -------------------------------------------------
// -------------- Terminal Input -------------------
// -------------------------------------------------
// for the special keys look at
// http://www2.gar.no/glinkj/help/cmds/ansm.htm
// http://www.comptechdoc.org/os/linux/howlinuxworks/linux_hlkeycodes.html
"use strict" ;
var UTF8 = require ( '../../lib/utf8' ) ;
function TerminalInput ( SendChars )
{
this . CTRLpressed = false ;
this . ALTpressed = false ;
this . SHIFTpressed = false ;
this . SendChars = SendChars ;
this . enabled = true ;
}
TerminalInput . prototype . OnKeyPress = function ( e ) {
if ( ! this . enabled ) {
return ;
}
var key = 0 ;
key = e . charCode ;
if ( key == 0 ) {
return false ;
}
// Define that the control key has this effect only if special keys have been pressed A..Z a..z. Otherwise some foreign keyboards will not work
if ( ( this . CTRLpressed ) && ( ( ( key >= 0x41 ) && ( key <= 0x5A ) ) || ( ( key >= 0x61 ) && ( key <= 0x7A ) ) ) ) {
key &= 0x1F ;
}
this . SendChars ( UTF8 . UnicodeToUTF8Stream ( key ) ) ;
return false ;
} ;
TerminalInput . prototype . OnKeyUp = function ( e )
{
if ( ! this . enabled ) {
return ;
}
var keycode = e . keyCode ;
var unicode = e . charCode ;
var ie = document . all ? true : false ;
if ( keycode == 17 )
{
this . CTRLpressed = false ;
if ( document . getElementById ( 'ctrl' ) )
{
if ( ie )
document . getElementById ( 'ctrl' ) . innerText = '' ;
else
document . getElementById ( 'ctrl' ) . innerHTML = '' ;
}
}
else if ( keycode == 18 )
{
this . ALTpressed = false ;
if ( document . getElementById ( 'alt' ) )
{
if ( ie )
document . getElementById ( 'alt' ) . innerText = '' ;
else
document . getElementById ( 'alt' ) . innerHTML = '' ;
}
}
else if ( keycode == 16 )
{
this . SHIFTpressed = false ;
if ( document . getElementById ( 'shift' ) )
{
if ( ie )
document . getElementById ( 'shift' ) . innerText = '' ;
else
document . getElementById ( 'shift' ) . innerHTML = '' ;
}
}
return false ;
} ;
TerminalInput . prototype . OnKeyDown = function ( e )
{
if ( ! this . enabled )
{
return ;
}
var keycode = e . keyCode ;
var unicode = e . charCode ;
var ie = document . all ? true : false ;
// alert ('oscpu : ' + navigator.oscpu );
// alert ('platform : ' + navigator.platform );
var os = navigator . platform . indexOf ( 'MacIntel' ) ;
var ua = navigator . userAgent ;
var safari = ua . indexOf ( "Safari" ) != - 1 ;
// alert('Safari :' + safari);
// alert ('os = ' + os);
// var os = navigator.oscpu;
// CTRL + x key handling for chrome
if ( ( this . CTRLpressed ) && ( ! this . ALTpressed ) && ( ! this . SHIFTpressed ) && ( keycode >= 65 ) && ( keycode <= 90 ) )
{
this . SendChars ( [ ( keycode - 32 ) & 0x1F ] ) ;
e . preventDefault ( ) ;
return false ;
}
// alert ( 'UserAgent = ' + ua + ' alt = ' + this.ALTpressed + ' shift = ' + this.SHIFTpressed + ' touche = ' + keycode + '(old=' + this.lastChar + ') OSX = ' + os);
if ( document . getElementById ( 'shift' ) )
{
var txt = ( this . SHIFTpressed ) ? 'shift' : '' ;
if ( ie )
document . getElementById ( 'shift' ) . innerText = txt ;
else
document . getElementById ( 'shift' ) . innerHTML = txt ;
}
if ( document . getElementById ( 'alt' ) )
{
var txt = ( this . ALTpressed ) ? 'alt' : '' ;
if ( ie )
document . getElementById ( 'alt' ) . innerText = txt ;
else
document . getElementById ( 'alt' ) . innerHTML = txt ;
}
if ( document . getElementById ( 'ctrl' ) )
{
var txt = ( this . CTRLpressed ) ? 'ctrl' : '' ;
if ( ie )
document . getElementById ( 'ctrl' ) . innerText = txt ;
else
document . getElementById ( 'ctrl' ) . innerHTML = txt ;
}
if ( document . getElementById ( 'key' ) )
{
if ( ie )
document . getElementById ( 'key' ) . innerText = keycode ;
else
document . getElementById ( 'key' ) . innerHTML = keycode ;
}
// TODO tab?
var oldk = this . lastChar ;
this . lastChar = false ; // auto-nettoyage
2023-01-31 09:52:15 +04:00
// 0x1b : CTRL (Escape)
// 0x31 : 1
// 0x35 : 5
// 0x3b : ;
// 0x44 : D
// 0x5b : [
if ( this . ALTpressed )
{
// https://askcodez.com/iterm-2-comment-definir-des-raccourcis-clavier-pour-aller-au-debut-a-la-fin-de-la-ligne.html
if ( keycode == 66 ) // B
{
// console.log('Traite le ALT+B');
this . SendChars ( [ 0x1b , 0x62 ] ) ; // Send backword
e . preventDefault ( ) ;
return false ;
}
else if ( keycode == 68 ) // D
{
// console.log('Traite le ALT+D');
this . SendChars ( [ 0x1b , 0x64 ] ) ; // Send delete Forward-Word
e . preventDefault ( ) ;
return false ;
}
else if ( keycode == 70 ) // F
{
// console.log('Traite le ALT+F');
this . SendChars ( [ 0x1b , 0x66 ] ) ; // Send Forward-Word
e . preventDefault ( ) ;
return false ;
}
else if ( keycode == 90 ) // Z
{
// console.log('Traite le ALT+Z');
this . SendChars ( [ 0x1f ] ) ; // Send Cancel
e . preventDefault ( ) ;
return false ;
}
}
2023-01-31 08:47:50 +04:00
switch ( keycode )
{
case 8 :
// del
this . SendChars ( [ 0x7F ] ) ;
e . preventDefault ( ) ;
return false ;
break ;
case 9 :
//tab
break ;
case 16 :
this . SHIFTpressed = true ;
if ( document . getElementById ( 'shift' ) )
{
if ( ie )
document . getElementById ( 'shift' ) . innerText = 'shift' ;
else
document . getElementById ( 'shift' ) . innerHTML = 'shift' ;
}
return ;
break ;
case 17 :
// CTRL
this . CTRLpressed = true ;
if ( document . getElementById ( 'ctrl' ) )
{
if ( ie )
document . getElementById ( 'ctrl' ) . innerText = 'ctrl' ;
else
document . getElementById ( 'ctrl' ) . innerHTML = 'ctrl' ;
}
//e.preventDefault();
//return false;
return ;
break ;
case 18 :
// Alt
this . ALTpressed = true ;
if ( document . getElementById ( 'alt' ) )
{
if ( ie )
document . getElementById ( 'alt' ) . innerText = 'alt' ;
else
document . getElementById ( 'alt' ) . innerHTML = 'alt' ;
}
return ;
break ;
case 32 :
// french mac keyboard
// add ˆ
if ( oldk == 160 )
{
this . SendChars ( [ 0x5e ] ) ; // ^
e . preventDefault ( ) ;
return false ;
}
else if ( oldk == 170 )
{
this . SendChars ( [ 0xc2 , 0xa8 ] ) ; // ¨
e . preventDefault ( ) ;
return false ;
}
break ;
case 38 :
// up
this . SendChars ( [ 0x1B , 0x5B , 0x41 ] ) ;
e . preventDefault ( ) ;
return false ;
break ;
case 37 :
// left
this . SendChars ( [ 0x1B , 0x5B , 0x44 ] ) ;
e . preventDefault ( ) ;
return false ;
break ;
case 39 :
// right
this . SendChars ( [ 0x1B , 0x5B , 0x43 ] ) ;
e . preventDefault ( ) ;
return false ;
break ;
case 40 :
// down
this . SendChars ( [ 0x1B , 0x5B , 0x42 ] ) ;
e . preventDefault ( ) ;
return false ;
break ;
case 65 :
// french mac keyboard
if ( oldk == 160 )
{
// add â
this . SendChars ( UTF8 . UnicodeToUTF8Stream ( 226 ) ) ; // â
e . preventDefault ( ) ;
return false ;
}
break ;
case 69 :
// french mac keyboard
if ( oldk == 160 )
{
// add ê
this . SendChars ( UTF8 . UnicodeToUTF8Stream ( 234 ) ) ; // ê
e . preventDefault ( ) ;
return false ;
}
else if ( oldk == 170 )
{
// add ë
this . SendChars ( UTF8 . UnicodeToUTF8Stream ( 235 ) ) ; // ë
e . preventDefault ( ) ;
return false ;
}
break ;
case 73 :
// french mac keyboard
if ( oldk == 160 )
{
// add î
this . SendChars ( UTF8 . UnicodeToUTF8Stream ( 238 ) ) ; // î
e . preventDefault ( ) ;
return false ;
}
else if ( oldk == 170 )
{
// add ï
this . SendChars ( UTF8 . UnicodeToUTF8Stream ( 239 ) ) ; // ï
e . preventDefault ( ) ;
return false ;
}
break ;
// french mac keyboard
case 76 :
if ( ( this . CTRLpressed ) && ( this . SHIFTpressed ) && ( os != - 1 ) )
{
// Add pipe char on Mac
this . SendChars ( [ 0x7C ] ) ;
e . preventDefault ( ) ;
return false ;
}
break ;
// french mac keyboard
case 78 :
if ( ( this . ALTpressed ) && ( ! this . CTRLpressed ) && ( ! this . SHIFTpressed ) && ( os != - 1 ) )
{
// Add tilde char on Mac
this . SendChars ( [ 0x7E ] ) ;
e . preventDefault ( ) ;
return false ;
}
break ;
case 79 :
// french mac keyboard
// add ô
if ( oldk == 160 )
{
this . SendChars ( UTF8 . UnicodeToUTF8Stream ( 244 ) ) ; // ô
e . preventDefault ( ) ;
return false ;
}
else if ( oldk == 170 )
{
this . SendChars ( UTF8 . UnicodeToUTF8Stream ( 246 ) ) ; // ö
e . preventDefault ( ) ;
return false ;
}
break ;
case 85 :
// french mac keyboard
if ( oldk == 160 )
{
// add û
this . SendChars ( UTF8 . UnicodeToUTF8Stream ( 251 ) ) ; // û
e . preventDefault ( ) ;
return false ;
}
else if ( oldk == 170 )
{
// add ü
this . SendChars ( UTF8 . UnicodeToUTF8Stream ( 252 ) ) ; // ü
e . preventDefault ( ) ;
return false ;
}
break ;
case 112 :
case 113 :
case 114 :
case 115 :
case 116 :
// F1 - F5
this . SendChars ( [ 0x1B , 0x5B , 0x5B , keycode - 112 + 0x41 ] ) ;
e . preventDefault ( ) ;
return false ;
break ;
case 117 :
case 118 :
case 119 :
// F6 - F8
this . SendChars ( [ 0x1B , 0x5B , 0x31 , keycode - 117 + 0x37 , 0x7E ] ) ;
e . preventDefault ( ) ;
return false ;
break ;
case 120 :
case 121 :
// F9 - F10
this . SendChars ( [ 0x1B , 0x5B , 0x32 , keycode - 120 + 0x30 , 0x7E ] ) ;
e . preventDefault ( ) ;
return false ;
break ;
2023-01-31 09:52:15 +04:00
case 20 :
// Caps Lock
// e.preventDefault();
return false ;
break ;
2023-01-31 08:47:50 +04:00
case 36 :
// pos1
2023-01-31 09:52:15 +04:00
this . SendChars ( [ 0x1b , 0x5b , 0x48 ] ) ; // CTRL + [ + H
2023-01-31 08:47:50 +04:00
e . preventDefault ( ) ;
return false ;
break ;
case 35 :
// end
2023-01-31 09:52:15 +04:00
this . SendChars ( [ 0x1b , 0x5b , 0x46 ] ) ; // CTRL + [ + F
2023-01-31 08:47:50 +04:00
e . preventDefault ( ) ;
return false ;
break ;
case 33 :
// Page up
2023-01-31 09:52:15 +04:00
this . SendChars ( [ 0x1b , 0x5b , 0x35 , 0x7e ] ) ; // CTRL + [ + 5 + ~
2023-01-31 08:47:50 +04:00
e . preventDefault ( ) ;
return false ;
break ;
case 34 :
// Page down
2023-01-31 09:52:15 +04:00
this . SendChars ( [ 0x1b , 0x5b , 0x36 , 0x7e ] ) ; // CTRL + [ + 6 + ~
2023-01-31 08:47:50 +04:00
e . preventDefault ( ) ;
return false ;
break ;
case 45 :
// ins
this . SendChars ( [ 0x1b , 0x5b , 0x32 , 0x7e ] ) ;
e . preventDefault ( ) ;
return false ;
break ;
case 46 :
// del
2023-01-31 09:52:15 +04:00
this . SendChars ( [ 0x1b , 0x5b , 0x33 , 0x7e ] ) ; // CTRL + [ + 3 + ~
2023-01-31 08:47:50 +04:00
e . preventDefault ( ) ;
return false ;
break ;
// french mac keyboard
case 160 :
// detecte l'usage de la touche ^ (uniquement pour mac & Firefox)
if ( ( os != - 1 ) && ( ua . indexOf ( "Firefox" ) != - 1 ) )
{
// ^ ou ¨
this . lastChar = 160 ;
if ( this . SHIFTpressed )
this . lastChar = 170 ;
return false ;
}
break ;
// french mac keyboard
case 192 :
// ` ..... (only for mac && Firefox)
if ( ( os != - 1 ) && ( ua . indexOf ( "Firefox" ) != - 1 ) )
{
if ( this . SHIFTpressed )
this . SendChars ( [ 0xc2 , 0xa3 ] ) ; // pound £
else
this . SendChars ( [ 0x60 ] ) ; // backquote `
e . preventDefault ( ) ;
return false ;
}
break ;
// french mac keyboard
case 219 :
// detecte l'usage de la touche ^ (pour tous les autres navigateurs -- exception:Firefox --)
// Sur Safari -> c'est aussi le code de la touche (
// alert ('os = ' + os + ' ctrl = ' + this.CTRLpressed + ' alt = ' + this.ALTpressed );
if ( ( os == - 1 ) && ( ua . indexOf ( "Firefox" ) == - 1 ) && ( this . CTRLpressed ) && ( this . ALTpressed ) )
{
// Chrome sur PC => ]
this . SendChars ( [ 0x5D ] ) ; // ]
e . preventDefault ( ) ;
return false ;
}
else if ( ( os != - 1 ) && ( ua . indexOf ( "Firefox" ) == - 1 ) && ( ! this . SHIFTpressed ) && ( ! this . ALTpressed ) )
{
// Sur mac ( Chrome.... )
// ^ ou ¨
this . lastChar = 160 ;
if ( this . SHIFTpressed )
this . lastChar = 170 ;
return false ;
}
else if ( ( safari ) && ( this . ALTpressed ) && ( ! this . SHIFTpressed ) )
{
this . SendChars ( [ 0x7B ] ) ; // {
e . preventDefault ( ) ;
return false ;
}
else if ( ( safari ) && ( this . ALTpressed ) && ( this . SHIFTpressed ) )
{
this . SendChars ( [ 0x5B ] ) ; // [
e . preventDefault ( ) ;
return false ;
}
break ;
// french mac keyboard
case 220 :
// ` ..... (only for mac && !Firefox)
// interference entre les touches ALT+SHIFT+/ et ALT+SHIFT+l et ` (même keycode)
if ( ( os != - 1 ) && ( ua . indexOf ( "Firefox" ) == - 1 ) )
{
if ( this . SHIFTpressed && this . ALTpressed )
this . SendChars ( [ 0x5c ] ) ; // \
else if ( this . SHIFTpressed && this . CTRLpressed )
this . SendChars ( [ 0x7C ] ) ; // |
else if ( this . SHIFTpressed )
this . SendChars ( [ 0xc2 , 0xa3 ] ) ; // `
else
this . SendChars ( [ 0x60 ] ) ; // £
e . preventDefault ( ) ;
return false ;
}
break ;
}
if ( ( keycode != 0 ) && ( keycode <= 0x1F ) ) {
this . SendChars ( [ keycode ] ) ;
e . preventDefault ( ) ;
return false ;
}
return ;
} ;
module . exports = TerminalInput ;
} , { "../../lib/utf8" : 2 } ] , 8 : [ function ( require , module , exports ) {
// -------------------------------------------------
// --------------- Terminal Emulator ---------------
// -------------------------------------------------
// http://lxr.free-electrons.com/source/drivers/tty/vt/vt.c
"use strict" ;
var UTF8 = require ( '../../lib/utf8' ) ;
var message = require ( '../messagehandler' ) ;
var Colors = new Array (
// standard colors
"#000000" , "#BB0000" , "#00BB00" , "#BBBB00" ,
"#0000BB" , "#BB00BB" , "#00BBBB" , "#BBBBBB" ,
// brighter colors
"#555555" , "#FF5555" , "#55FF55" , "#FFFF55" ,
"#5555FF" , "#FF55FF" , "#55FFFF" , "#FFFFFF" ,
// dimmed colors
"#000000" , "#770000" , "#007700" , "#777700" ,
"#000077" , "#770077" , "#007777" , "#777777"
) ;
// constructor
function Terminal ( nrows , ncolumns , elemId ) {
this . nrows = nrows ;
this . ncolumns = ncolumns ;
var ele = document . getElementById ( elemId ) ;
if ( ele . tagName == "CANVAS" ) {
this . canvas = ele ;
this . context = this . canvas . getContext ( "2d" ) ;
this . context . font = "13px courier,fixed,swiss,monospace,sans-serif" ;
} else {
this . Table = ele ;
this . rowelements = new Array ( this . nrows ) ;
for ( var i = 0 ; i < nrows ; i ++ ) {
var TR = this . Table . insertRow ( 0 ) ;
var TD = document . createElement ( "td" ) ;
this . rowelements [ i ] = TD ;
TR . appendChild ( TD ) ;
}
}
this . cursorvisible = false ;
this . escapetype = 0 ;
this . escapestring = "" ;
this . cursorx = 0 ;
this . cursory = 0 ;
this . scrolltop = 0 ;
this . cursortype = 1 ;
this . scrollbottom = this . nrows - 1 ;
this . attr _color = 0x7 ;
this . attr _reverse = false ;
this . attr _italic = false ;
this . attr _intensity = 0x1 ;
this . pauseblink = false ;
this . OnCharReceived = function ( ) { } ;
this . framerequested = false ;
this . timeout = 30 ; // the time in ms when the next frame is drawn
this . updaterow = new Uint8Array ( this . nrows ) ;
this . utf8converter = new UTF8 . UTF8StreamToUnicode ( ) ;
this . trows = 40 ;
this . brows = this . trows - this . nrows ;
this . bufferp = 0 ;
this . screen = new Array ( this . trows ) ;
this . color = new Array ( this . trows ) ;
for ( var i = 0 ; i < this . trows ; i ++ ) {
this . updaterow [ i ] = 1 ;
this . screen [ i ] = new Uint16Array ( this . ncolumns ) ;
this . color [ i ] = new Uint16Array ( this . ncolumns ) ;
for ( var j = 0 ; j < this . ncolumns ; j ++ ) {
this . screen [ i ] [ j ] = 0x20 ;
this . color [ i ] [ j ] = this . attr _color ;
}
}
this . deletedScreenRow = this . screen [ 0 ] ;
this . deletedColorRow = this . color [ 0 ] ;
//message.Debug("Inside constructor");
this . UpdateScreen ( ) ;
this . Blink ( ) ;
//if (!this.canvas) this.Table.addEventListener("wheel", this.UpdateScreenForScroll.bind(this));
}
// Stop blinking cursor when the VM is paused
Terminal . prototype . PauseBlink = function ( pause ) {
pause = ! ! pause ;
this . pauseblink = pause ;
if ( this . cursortype ) {
this . cursorvisible = ! pause ;
}
this . PrepareUpdateRow ( this . cursory , this . cursorx ) ;
}
Terminal . prototype . GetColor = function ( ) {
var c = this . attr _color ;
if ( this . attr _reverse ) {
c = ( ( c & 0x7 ) << 8 ) | ( ( c >> 8 ) ) & 0x7 ;
}
if ( this . attr _intensity == 2 ) {
c = c | 0x8 ;
} else
if ( this . attr _intensity == 0 ) {
c = c | 0x10 ;
}
return c ;
}
Terminal . prototype . Blink = function ( ) {
this . cursorvisible = ! this . cursorvisible ;
if ( ! this . pauseblink ) this . PrepareUpdateRow ( this . cursory , this . cursorx ) ;
window . setTimeout ( this . Blink . bind ( this ) , 500 ) ; // update every half second
} ;
Terminal . prototype . deepCopy = function ( oldObj ) {
var newObj = oldObj ;
if ( oldObj && typeof oldObj === 'object' ) {
newObj = Object . prototype . toString . call ( oldObj ) === "[object Array]" ? [ ] : { } ;
for ( var i in oldObj ) {
newObj [ i ] = this . deepCopy ( oldObj [ i ] ) ;
}
}
return newObj ;
}
Terminal . prototype . DeleteRow = function ( row ) {
var deletedScreenRow = this . deepCopy ( this . screen [ this . brows + row ] ) ;
var deletedColorRow = this . deepCopy ( this . color [ this . brows + row ] ) ;
if ( row == 23 ) {
for ( var i = 0 ; i < this . brows - 1 ; i ++ ) {
this . screen [ i ] = this . screen [ i + 1 ] ;
this . color [ i ] = this . color [ i + 1 ] ;
}
this . screen [ this . brows - 1 ] = deletedScreenRow ;
this . color [ this . brows - 1 ] = deletedColorRow ;
}
for ( var j = 0 ; j < this . ncolumns ; j ++ ) {
this . screen [ this . brows + row ] [ j ] = 0x20 ;
this . color [ this . brows + row ] [ j ] = this . attr _color ;
}
this . PrepareUpdateRow ( row ) ;
} ;
Terminal . prototype . DeleteArea = function ( row , column , row2 , column2 ) {
for ( var i = row ; i <= row2 ; i ++ ) {
for ( var j = column ; j <= column2 ; j ++ ) {
this . screen [ this . brows + i ] [ j ] = 0x20 ;
this . color [ this . brows + i ] [ j ] = this . attr _color ;
}
this . PrepareUpdateRow ( i ) ;
}
} ;
Terminal . prototype . UpdateRowCanvas = function ( row ) {
var y = row << 4 ;
var line = this . screen [ this . brows + row ] ;
var c = this . color [ this . brows + row ] [ 0 ] | 0 ;
var n = 0 ;
for ( var column = 0 ; column < this . ncolumns ; column ++ ) {
var cnew = this . color [ this . brows + row ] [ column ] | 0 ;
if ( this . cursorvisible )
if ( row == this . cursory )
if ( column == this . cursorx ) {
cnew |= 0x600 ;
}
if ( c != cnew ) {
var x = ( column - n ) << 3 ;
this . context . fillStyle = Colors [ ( c >>> 8 ) & 0x1F ] ;
this . context . fillRect ( x , y , n * 8 , 16 ) ;
this . context . fillStyle = Colors [ c & 0x1F ] ;
for ( var i = 0 ; i < n ; i ++ ) {
this . context . fillText ( String . fromCharCode ( line [ column - n + i ] ) , x + ( i << 3 ) , y + 12 ) ;
}
c = cnew ;
n = 0 ;
}
n ++ ;
}
var x = ( column - n ) << 3 ;
this . context . fillStyle = Colors [ ( c >>> 8 ) & 0x1F ] ;
this . context . fillRect ( x , y , n * 8 , 16 ) ;
this . context . fillStyle = Colors [ c & 0x1F ] ;
for ( var i = 0 ; i < n ; i ++ ) {
this . context . fillText ( String . fromCharCode ( line [ column - n + i ] ) , x + ( i << 3 ) , y + 12 ) ;
}
} ;
Terminal . prototype . GetSpan = function ( c , line , idx , n ) {
var html = "<span style=\"color:" + Colors [ c & 0x1F ] + ";background-color:" + Colors [ ( c >> 8 ) & 0x1F ] + "\">" ;
for ( var i = 0 ; i < n ; i ++ ) {
switch ( line [ idx + i ] )
{
case 0x20 :
html += " " ;
break ;
case 0x26 : // '&'
html += "&" ;
break ;
case 0x3C : // '<'
html += "<" ;
break ;
case 0x3E : // '>'
html += ">" ;
break ;
default :
html += String . fromCharCode ( line [ idx + i ] ) ;
break ;
}
}
html += "</span>" ;
return html ;
}
Terminal . prototype . UpdateRowTable = function ( row ) {
var y = row << 4 ;
var line = this . screen [ this . brows + row ] ;
var c = this . color [ this . brows + row ] [ 0 ] | 0 ;
var n = 0 ;
var html = "" ;
for ( var column = 0 ; column < this . ncolumns ; column ++ ) {
var cnew = this . color [ this . brows + row ] [ column ] | 0 ;
if ( this . cursorvisible )
if ( row == this . cursory )
if ( column == this . cursorx ) {
cnew |= 0x600 ;
}
if ( c != cnew ) {
html += this . GetSpan ( c , line , column - n , n ) ;
c = cnew ;
n = 0 ;
}
n ++ ;
}
html += this . GetSpan ( c , line , column - n , n ) ;
this . rowelements [ this . nrows - row - 1 ] . innerHTML = html ;
} ;
Terminal . prototype . UpdateRowTableForScroll = function ( row ) {
var y = row << 4 ;
var line = this . screen [ this . brows + row - this . bufferp ] ;
var c = this . color [ this . brows + row - this . bufferp ] [ 0 ] | 0 ;
var n = 0 ;
var html = "" ;
for ( var column = 0 ; column < this . ncolumns ; column ++ ) {
var cnew = this . color [ this . brows + row - this . bufferp ] [ column ] | 0 ;
if ( this . cursorvisible )
if ( row == this . cursory )
if ( column == this . cursorx ) {
cnew |= 0x600 ;
}
if ( c != cnew ) {
html += this . GetSpan ( c , line , column - n , n ) ;
c = cnew ;
n = 0 ;
}
n ++ ;
}
html += this . GetSpan ( c , line , column - n , n ) ;
this . rowelements [ this . nrows - row - 1 ] . innerHTML = html ;
} ;
Terminal . prototype . UpdateScreen = function ( ) {
var nupdated = 0 , i = 0 ;
for ( i = 0 ; i < this . nrows ; i ++ ) {
if ( ! this . updaterow [ i ] ) continue ;
if ( this . canvas ) {
this . UpdateRowCanvas ( i ) ;
} else {
this . UpdateRowTable ( i ) ;
}
nupdated ++ ;
this . updaterow [ i ] = 0 ;
}
this . framerequested = false ;
if ( nupdated >= ( this . nrows - 1 ) ) {
this . timeout = 100 ;
} else {
this . timeout = 30 ;
}
}
Terminal . prototype . UpdateScreenForScroll = function ( ) {
var i ;
if ( this . bufferp < this . brows ) this . bufferp ++ ;
else this . bufferp = 0 ; //show the original state before the scrolling started
for ( i = this . nrows - 1 ; i >= 0 ; i -- ) {
this . UpdateRowTableForScroll ( i ) ;
}
}
Terminal . prototype . PrepareUpdateRow = function ( row ) {
this . updaterow [ row ] = 1 ;
if ( this . framerequested ) return ;
window . setTimeout ( this . UpdateScreen . bind ( this ) , this . timeout ) ;
this . framerequested = true ;
}
Terminal . prototype . ScrollDown = function ( draw ) {
var tempscreen = this . screen [ this . brows + this . scrollbottom ] ;
var tempcolor = this . color [ this . brows + this . scrollbottom ] ;
for ( var i = this . scrollbottom - 1 ; i >= this . scrolltop ; i -- ) {
if ( i == this . nrows - 1 ) continue ;
this . screen [ this . brows + i + 1 ] = this . screen [ this . brows + i ] ;
this . color [ this . brows + i + 1 ] = this . color [ this . brows + i ] ;
if ( draw ) this . PrepareUpdateRow ( i + 1 ) ;
}
this . screen [ this . brows + this . scrolltop ] = tempscreen ;
this . color [ this . brows + this . scrolltop ] = tempcolor ;
this . DeleteRow ( this . scrolltop ) ;
if ( draw ) this . PrepareUpdateRow ( this . scrolltop ) ;
}
Terminal . prototype . ScrollUp = function ( draw ) {
var tempscreen = this . screen [ this . brows + this . scrolltop ] ;
var tempcolor = this . color [ this . brows + this . scrolltop ] ;
for ( var i = this . scrolltop + 1 ; i <= this . scrollbottom ; i ++ ) {
if ( i == 0 ) continue ;
this . screen [ this . brows + i - 1 ] = this . screen [ this . brows + i ] ;
this . color [ this . brows + i - 1 ] = this . color [ this . brows + i ] ;
if ( draw ) this . PrepareUpdateRow ( i - 1 ) ;
}
this . screen [ this . brows + this . scrollbottom ] = tempscreen ;
this . color [ this . brows + this . scrollbottom ] = tempcolor ;
this . DeleteRow ( this . scrollbottom ) ;
if ( draw ) this . PrepareUpdateRow ( this . scrollbottom ) ;
} ;
Terminal . prototype . LineFeed = function ( ) {
if ( this . cursory != this . scrollbottom ) {
this . cursory ++ ;
if ( this . cursorvisible ) {
this . PrepareUpdateRow ( this . cursory - 1 ) ; // delete old cursor position
this . PrepareUpdateRow ( this . cursory ) ; // show new cursor position
}
return ;
}
this . ScrollUp ( true ) ;
} ;
Terminal . prototype . ChangeCursor = function ( Numbers ) {
switch ( Numbers . length ) {
case 0 :
this . cursorx = 0 ;
this . cursory = 0 ;
break ;
case 1 :
this . cursory = Numbers [ 0 ] ;
if ( this . cursory ) this . cursory -- ;
break ;
case 2 :
default :
// TODO check for boundaries
this . cursory = Numbers [ 0 ] ;
this . cursorx = Numbers [ 1 ] ;
if ( this . cursorx ) this . cursorx -- ;
if ( this . cursory ) this . cursory -- ;
break ;
}
if ( this . cursorx >= this . ncolumns ) this . cursorx = this . ncolumns - 1 ;
if ( this . cursory >= this . nrows ) this . cursory = this . nrows - 1 ;
} ;
Terminal . prototype . ChangeColor = function ( Numbers ) {
if ( Numbers . length == 0 ) { // reset;
this . attr _color = 0x7 ;
this . attr _reverse = false ;
this . attr _italic = false ;
this . attr _intensity = 1 ;
return ;
}
var c = this . attr _color ;
for ( var i = 0 ; i < Numbers . length ; i ++ ) {
switch ( Number ( Numbers [ i ] ) ) {
case 0 : // reset
c = 0x7 ;
this . attr _reverse = false ;
this . attr _italic = false ;
this . attr _intensity = 1 ;
break ;
case 1 : // brighter foreground color
this . attr _intensity = 2 ;
break ;
case 2 : // dimmed foreground color
this . attr _intensity = 0 ;
break ;
case 3 : // italic
this . attr _italic = true ;
break ;
case 4 : // underline ignored
break ;
case 5 : // extended colors or blink ignored
//i++;
break ;
case 7 : // reversed
this . attr _reverse = true ;
break ;
case 8 : // hidden ignored
break ;
case 10 : // reset mapping ?
break ;
case 21 :
case 22 :
this . attr _intensity = 1 ;
break ;
case 23 :
this . attr _italic = false ;
break ;
case 27 : // no reverse
this . attr _reverse = false ;
break ;
case 30 : case 31 : case 32 : case 33 : case 34 : case 35 : case 36 : case 37 :
c = c & ( 0xFFF8 ) | ( Numbers [ i ] - 30 ) & 0x7 ;
break ;
case 40 : case 41 : case 42 : case 43 : case 44 : case 45 : case 46 : case 47 :
c = c & ( 0x00FF ) | ( ( ( Numbers [ i ] - 40 ) & 0x7 ) << 8 ) ;
break ;
case 39 :
c = c & ( 0xFF00 ) | 0x7 ; // set standard foreground color
break ;
case 49 :
c = c & 0x00FF ; // set standard background color
break ;
default :
message . Warning ( "Color " + Numbers [ i ] + " not found" ) ;
break ;
}
}
this . attr _color = c | 0 ;
} ;
Terminal . prototype . ChangeMode = function ( numbers , question , onoff ) {
for ( var i = 0 ; i < numbers . length ; i ++ ) {
switch ( numbers [ i ] ) {
case 4 : // insert mode
break ;
case 7 : // auto wrap on off
break ;
case 25 : // cursor on/off
this . cursortype = onoff ;
break ;
case 1000 : //
break ;
case 1006 : //
break ;
case 1005 : //
break ;
default :
message . Warning ( "Mode term parameter " + this . escapestring + " unknown" ) ;
break ;
}
}
}
Terminal . prototype . ChangeCursorType = function ( numbers , question ) {
if ( ! question ) {
message . Warning ( "cursor parameter unknown" ) ;
return ;
}
for ( var i = 0 ; i < numbers . length ; i ++ ) {
switch ( numbers [ i ] ) {
case 0 :
//this.cursorvisible = false;
//this.cursortype = 0;
break ;
case 1 :
//this.cursortype = 1;
break ;
default :
message . Warning ( "Term parameter " + this . escapestring + " unknown" ) ;
break ;
}
}
}
Terminal . prototype . HandleEscapeSequence = function ( ) {
//message.Debug("Escape sequence:'" + this.escapestring+"'");
var i = 0 ;
if ( this . escapestring == "[J" ) {
this . DeleteArea ( this . cursory , this . cursorx , this . cursory , this . ncolumns - 1 ) ;
this . DeleteArea ( this . cursory + 1 , 0. , this . nrows - 1 , this . ncolumns - 1 ) ;
return ;
} else
if ( this . escapestring == "M" ) {
this . ScrollDown ( true ) ;
return ;
}
// Testing for [x;y;z
var s = this . escapestring ;
if ( s . charAt ( 0 ) != "[" ) {
message . Warning ( "Short escape sequence unknown:'" + this . escapestring + "'" ) ;
return ; // the short escape sequences must be handled earlier
}
s = s . substr ( 1 ) ; // delete first sign
var lastsign = s . substr ( s . length - 1 ) ; // extract command
s = s . substr ( 0 , s . length - 1 ) ; // remove command
var question = false ;
if ( s . charAt ( 0 ) == '?' ) {
question = true ;
s = s . substr ( 1 ) ; // delete question mark
}
var numbers = s . split ( ";" ) ; // if there are multiple numbers, split them
if ( numbers [ 0 ] . length == 0 ) {
numbers = [ ] ;
}
// the array must contain of numbers and not strings. Make this sure
for ( i = 0 ; i < numbers . length ; i ++ ) {
numbers [ i ] = Number ( numbers [ i ] ) ;
}
var oldcursory = this . cursory ; // save current cursor position
var count = 0 ;
switch ( lastsign ) {
case 'l' :
this . ChangeMode ( numbers , question , true ) ;
return ;
case 'h' :
this . ChangeMode ( numbers , question , false ) ;
return ;
case 'c' :
this . ChangeCursorType ( numbers , question ) ;
return ;
}
if ( question ) {
message . Warning ( "Escape sequence unknown:'" + this . escapestring + "'" ) ;
return ;
}
switch ( lastsign ) {
case 'm' : // colors
this . ChangeColor ( numbers ) ;
return ;
case 'A' : // move cursor up
count = numbers . length ? numbers [ 0 ] : 1 ;
if ( count == 0 ) count = 1 ;
this . cursory -= count ;
break ;
case 'B' : // move cursor down
count = numbers . length ? numbers [ 0 ] : 1 ;
if ( count == 0 ) count = 1 ;
this . cursory += count ;
break ;
case 'C' : // move cursor right
count = numbers . length ? numbers [ 0 ] : 1 ;
if ( count == 0 ) count = 1 ;
this . cursorx += count ;
break ;
case 'D' : // move cursor left
count = numbers . length ? numbers [ 0 ] : 1 ;
if ( count == 0 ) count = 1 ;
this . cursorx -= count ;
if ( this . cursorx < 0 ) this . cursorx = 0 ;
break ;
case 'E' : // move cursor down
count = numbers . length ? numbers [ 0 ] : 1 ;
this . cursory += count ;
this . cursorx = 0 ;
break ;
case 'F' : // move cursor up
count = numbers . length ? numbers [ 0 ] : 1 ;
this . cursory -= count ;
if ( this . cursory < 0 ) this . cursory = 0 ;
this . cursorx = 0 ;
break ;
case 'G' : // change cursor column
count = numbers . length ? numbers [ 0 ] : 1 ;
this . cursorx = count ;
if ( this . cursorx ) this . cursorx -- ;
break ;
case 'H' : // cursor position
case 'd' :
case 'f' :
this . ChangeCursor ( numbers ) ;
break ;
case 'K' : // erase
count = numbers . length ? numbers [ 0 ] : 1 ;
if ( ! numbers . length ) {
this . DeleteArea ( this . cursory , this . cursorx , this . cursory , this . ncolumns - 1 ) ;
} else
if ( numbers [ 0 ] == 1 ) {
this . DeleteArea ( this . cursory , 0. , this . cursory , this . cursorx ) ;
} else
if ( numbers [ 0 ] == 2 ) {
this . DeleteRow ( this . cursory ) ;
}
break ;
case 'L' : // scroll down
count = numbers . length ? numbers [ 0 ] : 1 ;
if ( count == 0 ) count = 1 ;
var top = this . scrolltop ;
this . scrolltop = this . cursory ;
if ( count == 1 ) {
this . ScrollDown ( true ) ;
} else {
for ( var j = 0 ; j < count - 1 ; j ++ ) {
this . ScrollDown ( false ) ;
}
this . ScrollDown ( true ) ;
}
this . scrolltop = top ;
break ;
case 'M' : // scroll up
count = numbers . length ? numbers [ 0 ] : 1 ;
if ( count == 0 ) count = 1 ;
var top = this . scrolltop ;
this . scrolltop = this . cursory ;
if ( count == 1 ) {
this . ScrollUp ( true ) ;
} else {
for ( var j = 0 ; j < count - 1 ; j ++ ) {
this . ScrollUp ( false ) ;
}
this . ScrollUp ( true ) ;
}
this . scrolltop = top ;
break ;
case 'P' : /* shift left from cursor and fill with zero */
count = numbers . length ? numbers [ 0 ] : 1 ;
if ( count == 0 ) count = 1 ;
var n = 0 ; n
for ( var j = this . cursorx + count ; j < this . ncolumns ; j ++ ) {
this . screen [ this . brows + this . cursory ] [ this . cursorx + n ] = this . screen [ this . brows + this . cursory ] [ j ] ;
this . color [ this . brows + this . cursory ] [ this . cursorx + n ] = this . color [ this . brows + this . cursory ] [ j ] ;
n ++ ;
}
this . DeleteArea ( this . cursory , this . ncolumns - count , this . cursory , this . ncolumns - 1 ) ;
this . PrepareUpdateRow ( this . cursory ) ;
break ;
case 'r' : // set scrolling region
if ( numbers . length == 0 ) {
this . scrolltop = 0 ;
this . scrollbottom = this . nrows - 1 ;
} else {
this . scrolltop = numbers [ 0 ] ;
this . scrollbottom = numbers [ 1 ] ;
if ( this . scrolltop ) this . scrolltop -- ;
if ( this . scrollbottom ) this . scrollbottom -- ;
}
return ;
case 'X' : // erase only number of characters in current line
count = numbers . length ? numbers [ 0 ] : 1 ;
if ( count == 0 ) count = 1 ;
for ( var j = 0 ; j < count ; j ++ ) {
this . screen [ this . brows + this . cursory ] [ this . cursorx + j ] = 0x20 ;
this . color [ this . brows + this . cursory ] [ this . cursorx + j ] = this . GetColor ( ) ;
}
this . PrepareUpdateRow ( this . cursory ) ;
break ;
default :
message . Warning ( "Escape sequence unknown:'" + this . escapestring + "'" ) ;
break ;
}
if ( this . cursorvisible ) {
this . PrepareUpdateRow ( this . cursory ) ;
if ( this . cursory != oldcursory ) {
this . PrepareUpdateRow ( oldcursory ) ;
}
}
} ;
Terminal . prototype . PutChar = function ( c ) {
var i = 0 ;
//message.Debug("Char:" + c + " " + String.fromCharCode(c));
// escape sequence (CS)
if ( this . escapetype == 2 ) {
this . escapestring += String . fromCharCode ( c ) ;
if ( ( c >= 64 ) && ( c <= 126 ) ) {
this . HandleEscapeSequence ( ) ;
this . escapetype = 0 ;
}
return ;
}
// escape sequence
if ( ( this . escapetype == 0 ) && ( c == 0x1B ) ) {
this . escapetype = 1 ;
this . escapestring = "" ;
return ;
}
// starting escape sequence
if ( this . escapetype == 1 ) {
this . escapestring += String . fromCharCode ( c ) ;
// Control Sequence Introducer ([)
if ( c == 0x5B ) {
this . escapetype = 2 ;
return ;
}
this . HandleEscapeSequence ( ) ;
this . escapetype = 0 ;
return ;
}
switch ( c ) {
case 0xA :
// line feed
this . LineFeed ( ) ;
this . OnCharReceived ( "\n" ) ;
return ;
case 0xD :
// carriage return
this . cursorx = 0 ;
this . PrepareUpdateRow ( this . cursory ) ;
return ;
case 0x7 :
// beep
return ;
case 0x8 :
// back space
this . cursorx -- ;
if ( this . cursorx < 0 ) {
this . cursorx = 0 ;
}
this . PrepareUpdateRow ( this . cursory ) ;
return ;
case 0x9 :
// horizontal tab
var spaces = 8 - ( this . cursorx & 7 ) ;
do
{
if ( this . cursorx >= this . ncolumns ) {
this . PrepareUpdateRow ( this . cursory ) ;
this . LineFeed ( ) ;
this . cursorx = 0 ;
}
this . screen [ this . brows + this . cursory ] [ this . cursorx ] = 0x20 ;
this . color [ this . brows + this . cursory ] [ this . cursorx ] = this . attr _color ;
this . cursorx ++ ;
} while ( spaces -- ) ;
this . PrepareUpdateRow ( this . cursory ) ;
return ;
case 0x00 : case 0x01 : case 0x02 : case 0x03 :
case 0x04 : case 0x05 : case 0x06 : case 0x0B :
case 0x0C : case 0x0E : case 0x0F :
case 0x10 : case 0x11 : case 0x12 : case 0x13 :
case 0x14 : case 0x15 : case 0x16 : case 0x17 :
case 0x18 : case 0x19 : case 0x1A : case 0x1B :
case 0x1C : case 0x1D : case 0x1E : case 0x1F :
case 0x7F :
message . Warning ( "unknown character " + c ) ;
return ;
}
if ( this . cursorx >= this . ncolumns ) {
this . LineFeed ( ) ;
this . cursorx = 0 ;
}
c = this . utf8converter . Put ( c ) ;
if ( c == - 1 ) return ;
var cx = this . cursorx ;
var cy = this . cursory ;
this . screen [ this . brows + cy ] [ cx ] = c ;
this . color [ this . brows + cy ] [ cx ] = this . GetColor ( ) ;
this . cursorx ++ ;
//message.Debug("Write: " + String.fromCharCode(c));
this . PrepareUpdateRow ( cy ) ;
this . OnCharReceived ( String . fromCharCode ( c ) ) ;
} ;
module . exports = Terminal ;
} , { "../../lib/utf8" : 2 , "../messagehandler" : 9 } ] , 9 : [ function ( require , module , exports ) {
// -------------------------------------------------
// ------------- MessageHandler --------------------
// -------------------------------------------------
"use strict" ;
var worker ;
var run = true ;
function Send ( command , data ) {
worker . postMessage (
{
"command" : command ,
"data" : data
}
) ;
}
function Debug ( message ) {
console . log ( message ) ;
}
function Abort ( ) {
Debug ( "Master: Abort execution." ) ;
run = false ;
Send ( "Abort" , { } ) ;
throw new Error ( 'Kill master' ) ;
}
function DoError ( message ) {
Send ( "Debug" , "Error: " + message ) ;
Abort ( ) ;
}
function Warning ( message ) {
Send ( "Debug" , "Warning: " + message ) ;
}
var messagemap = new Object ( ) ;
function Register ( message , OnReceive ) {
messagemap [ message ] = OnReceive ;
}
// this is a global object of the worker
function OnMessage ( e ) {
var command = e . data . command ;
// Debug Messages are always allowed
if ( command == "Debug" ) {
messagemap [ command ] ( e . data . data ) ;
return ;
}
if ( ! run ) return ;
if ( typeof messagemap [ command ] == 'function' ) {
try {
messagemap [ command ] ( e . data . data ) ;
} catch ( error ) {
Debug ( "Master: Unhandled exception in command \"" + command + "\": " + error . message ) ;
run = false ;
}
}
}
function SetWorker ( _worker ) {
worker = _worker ;
worker . onmessage = OnMessage ;
worker . onerror = function ( e ) {
Debug ( "Error at " + e . filename + ":" + e . lineno + ": " + e . message ) ;
Abort ( ) ;
}
Register ( "Abort" , function ( ) { Debug ( "Master: Received abort signal from worker" ) ; run = false ; } ) ;
Register ( "Debug" , function ( d ) { Debug ( d ) ; } ) ;
}
module . exports . SetWorker = SetWorker ;
module . exports . Register = Register ;
module . exports . Debug = Debug ;
module . exports . Warning = Warning ;
module . exports . Error = DoError ;
module . exports . Abort = Abort ;
module . exports . Send = Send ;
} , { } ] , 10 : [ function ( require , module , exports ) {
// -------------------------------------------------
// -------------------- Master ---------------------
// -------------------------------------------------
var Terminal = require ( './dev/terminal' ) ;
var TerminalInput = require ( './dev/terminal-input' ) ;
var Framebuffer = require ( './dev/framebuffer' ) ;
var Ethernet = require ( './dev/ethernet' ) ;
var LoopSoundBuffer = require ( './dev/sound' ) ;
var Filesystem = require ( './dev/filesystem' ) ;
var utils = require ( './utils' ) ;
var message = require ( './messagehandler' ) ;
var TERMINAL = 0xDEADBEEF ;
"use strict" ;
function jor1kGUI ( parameters )
{
this . params = parameters ;
this . message = message ;
// --- parameters parsing ---
this . params . system = this . params . system || { } ;
this . params . path = this . params . path || "" ;
this . params . system . kernelURL = this . params . system . kernelURL || "vmlinux.bin.bz2" ;
this . params . system . memorysize = this . params . system . memorysize || 32 ;
this . params . system . arch = this . params . system . arch || "or1k" ;
this . params . system . cpu = this . params . system . cpu || "asm" ;
this . params . system . ncores = this . params . system . ncores || 1 ;
this . params . syncURL = this . params . syncURL || "" ;
this . params . fs = this . params . fs || { } ;
this . params . fs . basefsURL = this . params . fs . basefsURL || "basefs.json" ;
this . params . fs . earlyload = this . params . fs . earlyload || [ ] ;
this . params . fs . lazyloadimages = this . params . fs . lazyloadimages || [ ] ;
// add path to every URL
this . params . system . kernelURL = this . params . path + this . params . system . kernelURL ;
this . params . fs . basefsURL = this . params . path + this . params . fs . basefsURL ;
if ( this . params . fs . extendedfsURL ) {
this . params . fs . extendedfsURL = this . params . path + this . params . fs . extendedfsURL ;
}
this . params . userid = this . params . userid || "" ;
// ----------------------
this . worker = ( this . params . worker instanceof Worker ) ?
this . params . worker : new Worker ( "jor1k-worker-min.js" ) ;
message . SetWorker ( this . worker ) ;
// ----
if ( this . params . clipboardid ) {
this . clipboard = document . getElementById ( this . params . clipboardid ) ;
}
if ( this . params . statsid ) {
this . stats = document . getElementById ( this . params . statsid ) ;
}
if ( this . params . fbid ) {
this . framebuffer = new Framebuffer ( this . params . fbid , this . params . fps ) ;
message . Register ( "GetFB" , this . framebuffer . Update . bind ( this . framebuffer ) ) ;
}
this . terms = [ ] ;
if ( this . params . term ) {
this . terms = [ this . params . term ] ;
} else if ( this . params . terms ) {
this . terms = this . params . terms . slice ( 0 , 2 ) ; // support up to 2 terminals
}
for ( var i = 0 ; i < this . terms . length ; i ++ ) {
this . terms [ i ] . Init ( this , "tty" + i ) ;
}
this . activeTTY = "tty0" ;
this . terminput = new TerminalInput ( this . SendChars . bind ( this ) ) ;
this . fs = new Filesystem ( this . params . syncURL , this . params . userid ) ;
this . sound = new LoopSoundBuffer ( 22050 ) ;
message . Register ( "sound" , this . sound . AddBuffer . bind ( this . sound ) ) ;
message . Register ( "sound.rate" , this . sound . SetRate . bind ( this . sound ) ) ;
if ( this . clipboard ) {
this . clipboard . onpaste = function ( event ) {
this . clipboard . value = "" ;
setTimeout ( this . SendClipboard . bind ( this ) , 4 ) ;
} . bind ( this ) ;
this . SendClipboard = function ( ) {
var chars = [ ] ;
var v = this . clipboard . value ;
for ( var i = 0 ; i < v . length ; i ++ ) {
chars . push ( v . charCodeAt ( i ) ) ;
}
this . SendChars ( chars ) ;
this . clipboard . value = "" ;
} . bind ( this ) ;
}
this . IgnoreKeys = function ( ) {
return (
( this . lastMouseDownTarget != TERMINAL ) &&
( this . framebuffer ? this . lastMouseDownTarget != this . framebuffer . fbcanvas : true ) &&
( this . lastMouseDownTarget != this . clipboard )
) ;
}
var recordTarget = function ( event ) {
var termHitByEvent = false ;
for ( var i = 0 ; i < this . terms . length ; i ++ ) {
if ( this . terms [ i ] . WasHitByEvent ( event ) ) {
termHitByEvent = true ;
this . activeTTY = "tty" + i ;
break ;
}
}
if ( termHitByEvent )
this . lastMouseDownTarget = TERMINAL ;
else
this . lastMouseDownTarget = event . target ;
} . bind ( this ) ;
if ( document . addEventListener )
document . addEventListener ( 'mousedown' , recordTarget , false ) ;
else
Window . onmousedown = recordTarget ; // IE 10 support (untested)
document . onkeypress = function ( event ) {
if ( this . IgnoreKeys ( ) ) return true ;
if ( ( this . lastMouseDownTarget == TERMINAL ) || ( this . lastMouseDownTarget == this . clipboard ) ) {
return this . terminput . OnKeyPress ( event ) ;
}
message . Send ( "keypress" , { keyCode : event . keyCode , charCode : event . charCode } ) ;
return false ;
} . bind ( this ) ;
document . onkeydown = function ( event ) {
if ( this . IgnoreKeys ( ) ) return true ;
if ( ( this . lastMouseDownTarget == TERMINAL ) || ( this . lastMouseDownTarget == this . clipboard ) ) {
return this . terminput . OnKeyDown ( event ) ;
}
message . Send ( "keydown" , { keyCode : event . keyCode , charCode : event . charCode } ) ;
return false ;
} . bind ( this ) ;
document . onkeyup = function ( event ) {
if ( this . IgnoreKeys ( ) ) return true ;
if ( ( this . lastMouseDownTarget == TERMINAL ) || ( this . lastMouseDownTarget == this . clipboard ) ) {
return this . terminput . OnKeyUp ( event ) ;
}
message . Send ( "keyup" , { keyCode : event . keyCode , charCode : event . charCode } ) ;
return false ;
} . bind ( this ) ;
if ( this . params . relayURL ) {
this . ethernet = new Ethernet ( this . params . relayURL ) ;
this . ethernet . onmessage = function ( e ) {
message . Send ( "ethmac" , e . data ) ;
} . bind ( this ) ;
message . Register ( "ethmac" , this . ethernet . SendFrame . bind ( this . ethernet ) ) ;
}
message . Register ( "GetIPS" , this . ShowIPS . bind ( this ) ) ;
message . Register ( "execute" , this . Execute . bind ( this ) ) ;
message . Register ( "WorkerReady" , this . OnWorkerReady . bind ( this ) ) ;
}
jor1kGUI . prototype . OnWorkerReady = function ( ) {
this . Reset ( ) ;
window . setInterval ( function ( ) {
message . Send ( "GetIPS" , 0 ) ;
} , 1000 ) ;
} ;
// this command is send back and forth to be responsive
jor1kGUI . prototype . Execute = function ( ) {
if ( this . stop ) return ;
if ( this . userpaused ) {
this . executepending = true ;
} else {
this . executepending = false ;
message . Send ( "execute" , 0 ) ;
}
} ;
jor1kGUI . prototype . ShowIPS = function ( ips ) {
if ( ! this . stats ) return ;
if ( this . userpaused ) {
this . stats . innerHTML = "Paused" ;
} else {
this . stats . innerHTML = ips < 1000000 ?
Math . floor ( ips / 1000 ) + " KIPS"
:
( Math . floor ( ips / 100000 ) / 10. ) + " MIPS" ;
}
} ;
jor1kGUI . prototype . ChangeCore = function ( core ) {
message . Send ( "ChangeCore" , core ) ;
} ;
jor1kGUI . prototype . Reset = function ( ) {
this . stop = false ; // VM Stopped/Aborted
this . userpaused = false ;
this . executepending = false ; // if we rec an execute message while paused
message . Send ( "Init" , this . params . system ) ;
message . Send ( "Reset" ) ;
message . Send ( "LoadAndStart" , this . params . system . kernelURL ) ;
message . Send ( "LoadFilesystem" , this . params . fs ) ;
if ( this . terms . length > 0 ) {
this . terms . forEach ( function ( term ) {
term . PauseBlink ( false ) ;
} ) ;
this . lastMouseDownTarget = TERMINAL ;
// activeTTY remains the same, so the user can start typing into the terminal last used
// or the default terminal initialized in the constructor
}
}
jor1kGUI . prototype . Pause = function ( pause ) {
pause = ! ! pause ; // coerce to boolean
if ( pause == this . userpaused ) return ;
this . userpaused = pause ;
if ( ! this . userpaused && this . executepending ) {
this . executepending = false ;
message . Send ( "execute" , 0 ) ;
}
this . terms . forEach ( function ( term ) {
term . PauseBlink ( pause ) ;
} ) ;
}
// sends the input characters for the terminal
jor1kGUI . prototype . SendChars = function ( chars ) {
if ( this . lastMouseDownTarget == this . fbcanvas ) return ;
message . Send ( this . activeTTY , chars ) ;
message . Send ( "htif.term0.Transfer" , chars ) ;
}
// Returns the terminal attached to tty
// tty is the tty string, for example, tty0
jor1kGUI . prototype . GetTerm = function ( tty ) {
var index = parseInt ( tty . slice ( 3 ) ) ;
return this . terms [ index ] ;
}
jor1kGUI . prototype . FocusTerm = function ( tty ) {
this . activeTTY = tty ;
this . lastMouseDownTarget = TERMINAL ;
}
module . exports = jor1kGUI ;
} , { "./dev/ethernet" : 3 , "./dev/filesystem" : 4 , "./dev/framebuffer" : 5 , "./dev/sound" : 6 , "./dev/terminal" : 8 , "./dev/terminal-input" : 7 , "./messagehandler" : 9 , "./utils" : 11 } ] , 11 : [ function ( require , module , exports ) {
// -------------------------------------------------
// --------------------- Utils ---------------------
// -------------------------------------------------
"use strict" ;
function UploadBinaryResource ( url , filename , data , OnSuccess , OnError ) {
var boundary = "xxxxxxxxx" ;
var xhr = new XMLHttpRequest ( ) ;
xhr . open ( 'post' , url , true ) ;
xhr . setRequestHeader ( "Content-Type" , "multipart/form-data, boundary=" + boundary ) ;
xhr . setRequestHeader ( "Content-Length" , data . length ) ;
xhr . onreadystatechange = function ( ) {
if ( xhr . readyState != 4 ) {
return ;
}
if ( ( xhr . status != 200 ) && ( xhr . status != 0 ) ) {
OnError ( "Error: Could not upload file " + filename ) ;
return ;
}
OnSuccess ( this . responseText ) ;
} ;
var bodyheader = "--" + boundary + "\r\n" ;
bodyheader += 'Content-Disposition: form-data; name="uploaded"; filename="' + filename + '"\r\n' ;
bodyheader += "Content-Type: application/octet-stream\r\n\r\n" ;
var bodyfooter = "\r\n" ;
bodyfooter += "--" + boundary + "--" ;
var newdata = new Uint8Array ( data . length + bodyheader . length + bodyfooter . length ) ;
var offset = 0 ;
for ( var i = 0 ; i < bodyheader . length ; i ++ )
newdata [ offset ++ ] = bodyheader . charCodeAt ( i ) ;
for ( var i = 0 ; i < data . length ; i ++ )
newdata [ offset ++ ] = data [ i ] ;
for ( var i = 0 ; i < bodyfooter . length ; i ++ )
newdata [ offset ++ ] = bodyfooter . charCodeAt ( i ) ;
xhr . send ( newdata . buffer ) ;
}
module . exports . UploadBinaryResource = UploadBinaryResource ;
} , { } ] , "Jor1k" : [ function ( require , module , exports ) {
var Jor1k = require ( './system' ) ;
module . exports = Jor1k ;
} , { "./system" : 10 } ] , "LinuxTerm" : [ function ( require , module , exports ) {
var Terminal = require ( "../master/dev/terminal" ) ;
function LinuxTerm ( termElementId ) {
this . termElementId = termElementId ;
}
LinuxTerm . prototype . Init = function ( jor1kGUI , tty ) {
this . term = new Terminal ( 26 , 90 , this . termElementId ) ;
// this.term = new Terminal(26, 90, this.termElementId);
// this.term = new Terminal(22, 75, this.termElementId);
jor1kGUI . message . Register ( tty , function ( d ) {
d . forEach ( function ( c ) {
this . term . PutChar ( c & 0xFF ) ;
} . bind ( this ) ) ;
} . bind ( this ) ) ;
this . terminalcanvas = document . getElementById ( this . termElementId ) ;
this . terminalcanvas . onmousedown = function ( event ) {
if ( ! jor1kGUI . framebuffer ) return ;
jor1kGUI . framebuffer . fbcanvas . style . border = "2px solid #000000" ;
} . bind ( this ) ;
}
LinuxTerm . prototype . WasHitByEvent = function ( evt ) {
return this . terminalcanvas . contains ( evt . target ) ;
}
LinuxTerm . prototype . PauseBlink = function ( pause ) {
this . term . PauseBlink ( pause ) ;
}
LinuxTerm . prototype . SetCharReceiveListener = function ( callback ) {
this . term . OnCharReceived = callback ;
}
LinuxTerm . prototype . RemoveCharReceiveListener = function ( ) {
this . term . OnCharReceived = function ( ) { } ;
}
module . exports = LinuxTerm ;
} , { "../master/dev/terminal" : 8 } ] } , { } , [ ] ) ;