// pour désactiver nibble: nibble=0

var timer = false; // boolean flag

var nibble=0;

var source="";

var replic;



var lsrc;

var possrc;

var posout;

var posouthead;



var now;



tagstart="[";

tagend="]";

tagparam="/";

tagescape="\\";



function DEFMODE(tag,trig0,trig1,notrig){

  this.activ=false;

  this.reactiv=false;

  this.tag=tag;

  this.trig0=trig0;

  this.trig1=trig1;

  this.notrig=notrig;

  this.duration=0;



  this.func="";

  this.phase=0;

  this.nparams=0;

  this.params=new Array();

}



defmode=new Array();



defmode[0]=new DEFMODE("c","","","");

defmode[1]=new DEFMODE("p","","","");

defmode[2]=new DEFMODE("w",""," "," ");

defmode[3]=new DEFMODE("l","","\n","");

defmode[4]=new DEFMODE("b",".:?!","","");

defmode[5]=new DEFMODE("s",".:?!,;()","","");



var maxmode=defmode.length;



function FUNCS(tag,f){

  this.tag=tag;

  this.f=f;

}



var funcs=new Array();



funcs[0]=new FUNCS('S',  'if (defmode[funcmod].nparams>=3){\n'+

  '  s=Math.sin(2.0*Math.PI*now/defmode[funcmod].params[2]);\n'+

  '  defmode[funcmod].duration=s*defmode[funcmod].params[1]+defmode[funcmod].params[0];\n'+

  '}' );



funcs[1]=new FUNCS('R',   'if (defmode[funcmod].nparams>=2){\n'+

  '  r=Math.random()*2.0-1.0;\n'+

  '  defmode[funcmod].duration=r*defmode[funcmod].params[1]+defmode[funcmod].params[0];\n'+

  '}' );



funcs[2]=new FUNCS('E',   'if (defmode[funcmod].nparams>=2){\n'+

  '  r=Math.random()*2.0-1.0;\n'+

  '  defmode[funcmod].duration=defmode[funcmod].params[defmode[funcmod].phase++%defmode[funcmod].nparams];\n'+

  '}' );



var maxfunc=funcs.length;





function parsetag() {

  var modabout=-1;

  var funcabout=-1;

  var charnow;

  var strvalue="";

  var m,f;

  var newmod=0;





  for (m=0;m<maxmode;m++)

    defmode[m].reactiv=false;



  do{ 

    possrc++;

    charnow=source.charAt(possrc);

      if (charnow>="0" && charnow<="9")

        strvalue+=charnow;

      else{

        if (modabout>=0 && modabout<maxmode){

          if (funcabout>=0 && funcabout<maxfunc){

            if (strvalue.length){

              v=parseInt(strvalue);

              defmode[modabout].params[defmode[modabout].nparams]=v;

            }

            defmode[modabout].nparams++;

            strvalue="";

          }

          else{

            if (strvalue.length){

              v=parseInt(strvalue);

              defmode[modabout].duration=v;

              defmode[modabout].params[0]=v;

            }

            defmode[modabout].nparams=1;

            strvalue="";

          }

        }

        

        for (m=0;m<maxmode;m++)

          if (charnow==defmode[m].tag){

            modabout=m;

            defmode[m].reactiv=true;

            if (m!=1) newmod=1;

            funcabout=-1;

            defmode[m].nparams=0;

            defmode[m].func="";

            break;

          }



        for (f=0;f<maxfunc;f++)

          if (charnow==funcs[f].tag){

            funcabout=f;

            if (modabout>=0 && modabout<maxmode)

              defmode[modabout].func=funcs[f].f;

            break;

          }

      }

  } while( charnow!=tagend )





  for (m=0;m<maxmode;m++)

    defmode[m].activ = defmode[m].reactiv  ||  !newmod && defmode[m].activ ;





  possrc++;



}



function calc_mod_time(m){

  if (defmode[m].func.length){

    funcmod=m;

    eval(defmode[m].func);

  }

  return defmode[m].duration;

}



function condchar(chr,m,pat,nopat){



  nnotoken=nopat.length;

  if (nnotoken>0){

    for (t=0;t<nnotoken;t++){

      if (chr==nopat.charAt(t))

        return false;

    }

  }



  ntoken=pat.length;

  if (ntoken==0)

    return true;

  else{

    for (t=0;t<ntoken;t++){

      if (chr==pat.charAt(t))

        return true;

    }

  }



  return false;

}



function calc_tot_time(chr0,chr1){

  var p=0;



  for (m=0;m<maxmode;m++){

    if (defmode[m].activ 

         && condchar(chr0,m,defmode[m].trig0,defmode[m].notrig) 

         && condchar(chr1,m,defmode[m].trig1,"") ){

      p+=calc_mod_time(m);

    }

  }



  if (defmode[1].activ)

    defmode[1].activ=false;



  if (p<0)

    p=0;

  return p;

}



var charlast;

var charnow;



function play() {

  var pausetotal;



  do {



    replic+=charnow;

    posout++;



    charlast=charnow;

    

    while (true){

      charnow=source.charAt(possrc);

      if (charnow!=tagstart)

        break;

      parsetag();

    }

    

    pausetotal=calc_tot_time(charlast,charnow);



    possrc++;

  }

  while (pausetotal==0 && possrc<=lsrc);
    
  document.interf.txtout.value=replic.substring(posouthead,posout);

  scrollTextarea();

/*
    if (navigator.appName == 'Microsoft Internet Explorer' && navigator.appVersion.indexOf('Mac') == -1){

        var the_text = document.interf.txtout.createTextRange();

        the_text.scrollIntoView(false); 

    }


    if (navigator.appName == 'Netscape'){

      //document.interf.txtout.select();
 
      //document.interf.txtout.value = document.interf.txtout.value;

      //document.interf.txtout.blur();

    }
*/


  if(possrc<=lsrc){

    now+=pausetotal;

    lasttimeout=setTimeout("play()", pausetotal);  //faire une pause

  }


  //BOUCLER ICI

  if (possrc>lsrc)

    //alert('ok');
    ended();

}



function reset(){

  replic="";

  lsrc=source.length;;

  possrc=0;

  posout=0;

  posouthead=0;

  now=0;

  charlast="";

  charnow="";

  document.interf.txtout.value="";


}



// API (Application Programming Interface)



function ended(){

  clearTimeout(lasttimeout);
  starttimeout=setTimeout("start()",1000);

}



function stop(){
 
  if(timer==true){

    clearTimeout(lasttimeout);

    clearTimeout(starttimeout);

  }

  reset();

}



function start(){

  reset();

  play();

  timer = true;

}



function restart(){

  play();

}


function recorder(){
  var i=0;
  tempo = document.code.personnal.value;

    while(i<tempo.length) {
      if(i==0) { source += '[c2000]'+tempo.charAt(i); }
      else { source += '[c'+timer[i]+']'+tempo.charAt(i); }
      i++;
    }

  start();
}

function ressource(){

  document.code.personnal.value=source;

}



  /**************************************
    Record keyboard typing velocity
  **************************************/

  var tempo = "";
  var t = 0;
  var now = new Date();
  var timer= new Array();
  var starttime = now.getTime();

  function record(){
    now2 = new Date();
    totaltime = now2.getTime() - starttime;
    starttime = starttime+totaltime;
    timer[t] = Math.floor(totaltime/1.5);
    t++;
  }

function ressource(){
  document.code.personnal.value=source;
}

  /************************************
   add tag to code textarea
  ************************************/

function addtxt(tag) {
        var newmessage;
        var lastmsg = document.code.personnal.value;
        newmessage = lastmsg+tag;
        document.code.personnal.value=newmessage;
        return;
        }


function editor(){

  source=document.code.personnal.value;

  start();

}

function clean(){

    document.code.personnal.value="";

}



  /************************************************
    SCROLL TEXTAREA CROSS-BROWSER 
  ************************************************/

function scrollTextarea(){

var obj=document.forms.interf.elements.txtout; 

var gradual=false; // true to scroll slowly, false to jump 

obj.focus(); 

  if (document.layers){

    obj.select(); 

    obj.blur(); 
  }
 
  else if (gradual){

    var top=-1 

  while (top<obj.scrollTop){

    top=obj.scrollTop++;} 
  } 
  else {

    obj.scrollTop=obj.scrollHeight-obj.offsetHeight;
  } 
} 

