
// ----------------------------- GfA-Bibliothek -----------------------------

/* 'Lib-GfA2JS 191203' (c) by cybaer@binon.net
   -------------------
 Inhalt    : GfA-Basic-Befehle fuer JavaScript
 Aufruf    : - (Bibliothek)
 Parameter : -
 Sprache   : JavaScript 1.1 (ungesichert), JavaScript 1.2 (gesichert)
 Quelle    : http://Coding.binon.net/JSGfALib (cybaer@binon.net)
             Die kostenlose Nutzung der Quelltexte in eigenen Projekten ist
             bei nicht-kommerziellen Projekten (und deren unentgeltlicher
             Herstellung) bei Nennung der Quelle ausdruecklich gestattet.
 InternFunc: wrongJS (wird aufgerufen, falls der Browser fuer eine Funktion zu alt ist)
             parseGfA (wandelt GfA-Zahlensystem um in Dezimalzahl, z.B. 10->10, $0A->10, %1111->15)
 InlineFunc: diverse Bibliotheksfunktionen
 Konstante : isCHR$, isASC, isSTRING$, isPRED, isSUCC (true, wenn Funktion vorhanden, sonst false)
 Variable  : -
 SystemVar : -
 ExternVar : -
 Rueckgabe : -
 Anmerkung : Der TIMER()-Aufruf entspricht dem TIMER-Aufruf in GfA (also 1/200stel Sekunden).
             Die Befehle der GFA2JS-Bibliothek wandeln intern alle GfA-Zahlensysteme in Dezimalzahlen
             um (Nicht-Dezimalzahlen muessen den Befehlen als Strings uebergeben werden).
             ROUND() und FRAC() arbeiten ohne die JavaScript-typischen Rundungsabweichungen.
 Beispiele : S. http://Coding.binon.net/JSGfALib
*/

// Interne Funktionen
gfaInteger=4294967295; gfaIntegerSigned=2147483647;
function wrongJS(gfa,version) { alert("Dieser Browser ist leider zu alt!\n"+gfa+" braucht mindestens JavaScript "+version+"."); }
function parseGfA(data,isInt) { var result; data=""+data; if(data=="true") { result=-1; } else if(data!="false") { result=0; data=data.toLowerCase(); if(data.substring(0,1)=="&") { if(data.substring(0,2)=="&h") { result=parseInt(data.substring(2,data.length),16); result=(result<0)?0:result; } else if(data.substring(0,2)=="&x") { result=parseInt(data.substring(2,data.length),2); result=(result<0)?0:result; } else if(data.substring(0,2)=="&o") { result=parseInt(data.substring(2,data.length),8); result=(result<0)?0:result; } else { result=parseInt(data.substring(1,data.length),16); result=(result<0)?0:result; } } else if(data.substring(0,1)=="$") { result=parseInt(data.substring(1,data.length),16); result=(result<0)?0:result; } else if(data.substring(0,1)=="%") { result=parseInt(data.substring(1,data.length),2); result=(result<0)?0:result; } else { if(data.indexOf("e+")>1) { data=""+Math.pow(10,parseInt(data.substring(data.indexOf("e+")+2,data.length)))*parseFloat(data); } else if(data.indexOf("e-")>1) { data=""+Math.pow(10,parseInt(data.substring(data.indexOf("e-")+1,data.length)))*parseFloat(data); } data=(data.substring(0,1)=="-")?data:"0"+data; result=(isInt)?parseInt(data.substring(0,data.length),10):parseFloat(data.substring(0,data.length)); } } return (result>=0 || result<0)?result:0; }

// Ein-/Ausgabebefehle
function INPUT(text) { text=(text)?text:""; return prompt(text,""); }
function PRINT(data,channel) { if(typeof(channel)!="undefined") { channel=parseGfA(channel); } if(channel>=0 && top.frames[channel]) { top.frames[channel].document.write(data); } else { document.write(data); } }
function PRINTLN(data,channel) { if(typeof(channel)!="undefined") { channel=parseGfA(channel); } if(channel>=0 && top.frames[channel]) { top.frames[channel].document.write(data); } else { document.write(data); } }
function SPC(size) { return STRING$(size,"&#160;",true); }
// Soundbefehle
// Textoperationen
function INSTR(text,string,pos) { if(string) { pos=(!pos)?1:parseGfA(pos); return text.indexOf(string,Math.max(0,pos-1))+1; } else { return 0; } }
function LEFT$(text,num) { num=(num)?parseGfA(num):1; return text.substring(0,num); }
function LEN(text) { return text.length; }
function MID$(text,pos,num) { pos=parseGfA(pos)-1; if(typeof(num)=="undefined") { num=text.length-pos; } else { num=parseGfA(num); } return text.substring(pos,pos+num); } // JS 1.1
function RIGHT$(text,num) { num=(num)?parseGfA(num):1; return text.substring(text.length-num,text.length); }
function RINSTR(text,string,pos) { if(string) { pos=(!pos)?text.length:parseGfA(pos); return text.lastIndexOf(string,pos-1)+1; } else { return 0; } }
function SPACE$(size,isHTML) { size=parseGfA(size); var result=""; var string=(isHTML)?"&#160;":" "; for(var i=0;i<size;i++) { result+=string; } return result; }
function STRING$(size,data,isNumber) { size=parseGfA(size); var string="",result=""; if(isNumber) { if(String.fromCharCode) { string=String.fromCharCode(parseGfA(data)); } else { wrongJS("STRING$(size,num)",1.2); } } else { string=data; } for(var i=1;i<=size;i++) { result+=string; } return result; } // JS 1.2
function TRIM$(text) { while(text.charAt(0)==" ") { text=text.substring(1,text.length); } while(text.charAt(text.length-1)==" ") { text=text.substring(0,text.length-1); } return text; }
function UPPER$(text) { return text.toUpperCase(); }
// Mathematische Operationen
function ADD(num1,num2) { return parseGfA(num1,true)+parseGfA(num2,true); }
function DIV(num1,num2) { return parseGfA(num1,true)/parseGfA(num2,true); }
function MOD(num1,num2) { return parseGfA(num1,true)%parseGfA(num2,true); }
function MUL(num1,num2) { return parseGfA(num1,true)*parseGfA(num2,true); }
function SUB(num1,num2) { return parseGfA(num1,true)-parseGfA(num2,true); }
// Numerische Funktionen
function ABS(num) { return Math.abs(parseGfA(num)); }
function EVEN(num) { num=parseGfA(num,true); return (num%2)?0:-1; }
function FIX(num) { return parseGfA(num,true); }
function FRAC(num) { num=parseGfA(num); return parseFloat("0."+num.substring(num.length-((num.indexOf(".")>=0)?num.length-num.indexOf(".")-1:0),num.length)); }
function INT(num) { return Math.floor(parseGfA(num)); }
function ODD(num) { num=parseGfA(num,true); return (num%2)?-1:0; }
function PRED(data,isString) { if(!isString) { return parseGfA(data,true)-1; } else if(String.fromCharCode) { return String.fromCharCode(data.charCodeAt(0)-1); } else { wrongJS("PRED(string$)",1.2); return ""; } }
function ROUND(num,pos) { num=parseGfA(num); pos=parseGfA(pos); if(pos<0) { pos=Math.pow(10,Math.abs(pos)); return Math.round(num/pos)*pos; } else if(pos>0) { pos=Math.pow(10,pos); return Math.round(num*pos)/pos; } else { return Math.round(num); } }
function SGN(num) { num=parseGfA(num); return (num>0)?1:(num<0)?-1:0; }
function SQR(num) { return Math.sqr(parseGfA(num)); }
function SUCC(data,isString) { if(!isString) { return parseGfA(data,true)+1; } else if(String.fromCharCode) { return String.fromCharCode(data.charCodeAt(0)+1); } else { wrongJS("SUCC(string$)",1.2); return ""; } }
function TRUNC(num) { return parseGfA(num,true); }
// Kombinatorische Funktionen
function COMBIN(n,k) { n=parseGfA(n,true); k=parseGfA(k,true); if(n>=0 && k>=0 && n>=k) { return FACT(n)/(FACT(n-k)*FACT(k)); } else { return "undefined"; } }
function FACT(num) { num=parseGfA(num,true); var result=1; if(num>0) { while(num) { result*=num; num--; } } else if(num==0) { result=1; } else { result="undefined"; } return result; }
function VARIAT(n,k) { n=parseGfA(n,true); k=parseGfA(k,true); if(n>=0 && k>=0 && n>=k) { return FACT(n)/FACT(n-k); } else { return "undefined"; } }
// Matrizen-Funktionen
// Trigonometrische Funktionen
function ACOS(radian) { return Math.acos(parseGfA(radian)); }
function ASIN(radian) { return Math.asin(parseGfA(radian)); }
function ATN(radian) { return Math.atan(parseGfA(radian)); }
function COS(radian) { return Math.cos(parseGfA(radian)); }
function COSQ(degree) { return Math.cos(parseGfA(degree)*Math.PI/180); }
function DEG(radian) { return parseGfA(radian)*180/Math.PI; }
function RAD(degree) { return parseGfA(degree)*Math.PI/180; }
function SIN(radian) { return Math.sin(parseGfA(radian)); }
function SINQ(degree) { return Math.sin(parseGfA(degree)*Math.PI/180); }
function TAN(radian) { return Math.tan(parseGfA(radian)); }
// Vergleichsoperationen
function MAX(data) { var i=MAX.arguments.length, result; result=parseGfA(data); while(i>1) { i--; result=Math.max(result,parseGfA(MAX.arguments[i])); } return result; } // Momentan keine Zeichenketten.
function MIN(data) { var i=MIN.arguments.length, result; result=parseGfA(data); while(i>1) { i--; result=Math.min(result,parseGfA(MIN.arguments[i])); } return result; } // Momentan keine Zeichenketten.
// Bit-Operationen
// Zufallswert-Erzeugung
function RAND(num) { num=parseGfA(num); num=(num>65535)?num%65535:num; return RANDOM(num); }
function RANDOM(num) { num=parseGfA(num); if(Math.random) { if(num>1) { return Math.ceil(Math.max(1,num)*Math.random())-1; } else if(num<-1) { return -Math.ceil(Math.max(1,Math.abs(num))*Math.random())+1; } else { return 0; } } else { return num; } }
function RND() { if(Math.random) { return Math.random(); } else { return 0; } }
// Grafik-Definitionen
// Objektgrafikbefehle
// Line-A-Grafikbefehle
// Datenumwandlung
function ASC(text) { var result=""; if(String.fromCharCode) { result=(text.length)?(text.charCodeAt(0)):0; } else { wrongJS("ASC()",1.2); } return result; }
function BIN$(num,size) { var q, result=""; num=parseGfA(num,true); if(num<0) { num=gfaInteger+num; } while(true) { q=num/2; result=((FRAC(q))?"1":"0")+result; num=parseInt(q); if(num==0) { break; } } if(typeof(size)!="undefined") { size=(size<0 || size>32)?32:size; result="00000000000000000000000000000000"+result; result=result.substring(result.length-size,result.length); } return result; }
function CFLOAT(num) { return parseGfA(num); }
function CINT(num) { return Math.round(parseGfA(num)); }
function CHR$(num) { num=parseGfA(num,true); num=(256+num)%256; var result=""; if(String.fromCharCode) { result=String.fromCharCode(num); } else { wrongJS("CHR$()",1.2); } return result; } // JS 1.2
function HEX$(num,size) { var q, baseTable="0123456789ABCDEF", result=""; num=parseGfA(num,true); if(num<0) { num=gfaInteger+1+num; } while(true) { q=num/16; result=baseTable.charAt(parseInt(FRAC(q)*16))+result; num=parseInt(q); if(num==0) { break; } } if(typeof(size)!="undefined") { size=(size<0 || size>8)?8:size; result="00000000"+result; result=result.substring(result.length-size,result.length); } return result; }
function OCT$(num,size) { var q, result=""; num=parseGfA(num,true); if(num<0) { num=gfaInteger+num; } while(true) { q=num/8; result=""+parseInt(FRAC(q)*8)+result; num=parseInt(q); if(num==0) { break; } } if(typeof(size)!="undefined") { size=(size<0 || size>11)?11:size; result="00000000000"+result; result=result.substring(result.length-size,result.length); } return result; }
function STR$(num,size,real) { var i, q, strInt, strFrac, result=""; num=parseGfA(num); if(typeof(real)=="undefined") { strFrac=""+FRAC(Math.abs(num)); if(strFrac) { strFrac=strFrac.substring(2,strFrac.length); } strInt=""+parseInt(num); } else { real=parseGfA(real); if(real==0) { strFrac=""; strInt=Math.round(num); } else { strFrac=""+FRAC(Math.abs(ROUND(num,real))); if(strFrac) { strFrac=strFrac.substring(2,strFrac.length); } q=real-strFrac.length; for(i=1;i<=q;i++) { strFrac+="0"; } strInt=""+parseInt(num); } } strFrac=(strFrac)?"."+strFrac:strFrac; result=strInt+strFrac; if(typeof(size)!="undefined") { size=parseGfA(size); if(result.length>size) { if(strFrac.length)  { if(typeof(real)=="undefined") { result=result.substring(0,size); } else { result=result.substring(result.length-size,result.length); } } else { result=""+ROUND(result,-(result.length-size)); result=result.substr(0,result.length-(result.length-size)); } } result=SPACE$(size-result.length)+result; } return result; }
function VAL(text) { var result=0; text=""+text.toLowerCase(); if(text.substring(0,2)=="&h") { result=parseInt(text.substring(2,text.length),16); result=(result<0)?0:result; } else if(text.substring(0,2)=="&x") { result=parseInt(text.substring(2,text.length),2); result=(result<0)?0:result; } else if(text.substring(0,2)=="&o") { result=parseInt(text.substring(2,text.length),8); result=(result<0)?0:result; } else if(text.substring(0,1)=="$" || text.substring(0,1)=="&") { result=parseInt(text.substring(1,text.length),16); result=(result<0)?0:result; } else if(text.substring(0,1)=="%") { result=parseInt(text.substring(1,text.length),2); result=(result<0)?0:result; } else { text=(text.substring(0,1)=="-")?text:"0"+text; result=parseFloat(text.substring(0,text.length),10); } return (result>=0 || result<0)?result:0; }
// Feldoperationen
// Speicheroperationen
// Programmkontrolle
function TIMER() { var actual=new Date(); return parseInt(actual.getTime()/5); }
// Interaktion
function ALERT(icon,text,button,buttontext) { text=rc(text,"|","\n"); if(buttontext.indexOf("|")>=0) { return -confirm(text)+2; } else { alert(text); return 1; } }
// Konstante
FALSE=0;
PI=Math.PI;
TRUE=-1;
// Funktion vorhanden?
isASC=(String.fromCharCode)?true:false;
isCHR$=(String.fromCharCode)?true:false;
isSTRING$=(String.fromCharCode)?true:false;  // Nur von Bedeutung, falls Hauptparameter Zahl
isPRED=(String.fromCharCode)?true:false;     // Nur von Bedeutung, falls Hauptparameter Text
isSUCC=(String.fromCharCode)?true:false;     // Nur von Bedeutung, falls Hauptparameter Text

// --------------------------------------------------------------------------

