%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% giac/hevea interaction code definitions
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Use one of the environment \begin{giacjs}...\end{giacjs} or \begin{giacjsonline}...\end{giacjsonline}
%% to load the javascript code (from hard disk or Internet)
%% Commands \giacinput{} or \giacinputmath{} or \giacinputbigmath{} 
%% \giaccmd{} or \giaccmdmath{} or \giaccmdbigmath{} 
%% or \begin{giacprog}...\end{giacprog}
\usepackage{hevea} 
\usepackage{listings}
\usepackage{fancyvrb}
\ifhevea 
\newcommand\giacmathjax{
\usepackage[auto]{mathjax}
\renewcommand{\jax@meta}{\begin{rawhtml}<script language="javascript"> 
var ua = window.navigator.userAgent;  
var old_ie = ua.indexOf('MSIE ');  
var new_ie = ua.indexOf('Trident/');  
if ((old_ie > -1) || (new_ie > -1) || Boolean(window.chrome)){
 (function () {
  var script = document.createElement("script");
  script.type = "text/javascript";
  script.src  = "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-MML-AM_CHTML";
  document.getElementsByTagName("head")[0].appendChild(script);
})();
}
</script>
\end{rawhtml}}
}
\newenvironment{giacjs}[1]["max-height: 500px; overflow:auto"]
{\loadgiacmain{#1}
}
{\loadgiaccontrol
\loadgiacscriptstart
\loadgiacscript["file:///usr/share/giac/doc/"]
\loadgiacscriptend
} 
\newenvironment{giacjshere}[1]["max-height: 500px; overflow:auto"]
{\loadgiacmain{#1}
}
{\loadgiaccontrol
\loadgiacscriptstart
\loadgiacscript[""]
\loadgiacscriptend
} 
\newenvironment{giacparijs}[1]["max-height: 500px; overflow:auto"]
{\loadgiacmain{#1}
}
{
\loadgiaccontrol
\loadgiacscriptstart
\@print{
<script src="file:///usr/share/giac/doc/giacpari.js" async></script> 
}
\loadgiacscriptend
} 
\newenvironment{giacjsonline}[1]["max-height: 500px; overflow:auto"]
{\loadgiacmain{#1}
}
{
\loadgiaccontrol
\loadgiacscriptstart
\loadgiacscript["https://www-fourier.univ-grenoble-alpes.fr/~parisse/"]
\loadgiacscriptend
} 
\newenvironment{giacparijsonline}[1]["max-height: 500px; overflow:auto"]
{\loadgiacmain{#1}
}
{
\loadgiaccontrol
\loadgiacscriptstart
\@print{
<script src="https://www-fourier.univ-grenoble-alpes.fr/~parisse/giacpari.js" async></script> 
}
\loadgiacscriptend
} 
\else
\newcommand\giacmathjax{}
\newenvironment{giacjs}[1]["max-height: 500px; overflow:auto"]{}{}
\newenvironment{giacjshere}[1]["max-height: 500px; overflow:auto"]{}{}
\newenvironment{giacparijs}[1]["max-height: 500px; overflow:auto"]{}{}
\newenvironment{giacjsonline}[1]["max-height: 500px; overflow:auto"]{}{}
\newenvironment{giacparijsonline}[1]["max-height: 500px; overflow:auto"]{}{}
\fi
\newcommand{\loadgiacscript}[1][""]{
\ifhevea
\@print{
<script async>
  var UI={
   detectmob:function() { 
    if( navigator.userAgent.match(/Android/i)
	|| navigator.userAgent.match(/webOS/i)
	|| navigator.userAgent.match(/iPhone/i)
	|| navigator.userAgent.match(/iPad/i)
	|| navigator.userAgent.match(/iPod/i)
	|| navigator.userAgent.match(/BlackBerry/i)
	|| navigator.userAgent.match(/Windows Phone/i)
      ) return true;
    else 
      return false;
   },
   readCookie:function(name) {
    if (window.localStorage){
      var tmp=localStorage.getItem(name);
      if (tmp!=null) return tmp;
    }
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');
    for(var i=0;i < ca.length;i++) {
      var c = ca[i];
      while (c.charAt(0)==' ') c = c.substring(1,c.length);
      if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
    }
    return null;
   },
  }
  var script = document.createElement("script");
  script.type = "text/javascript";
  var webAssemblyAvailable = true;//false;
  if (Boolean(window.chrome)){
    if (!UI.detectmob()) webAssemblyAvailable =  window.location.href.substr(0,4)!='file';
  }
  else {
    var ua = window.navigator.userAgent;
    var old_ie = ua.indexOf('MSIE ');
    var new_ie = ua.indexOf('Trident/');
    if (!UI.detectmob() && old_ie<=-1 && new_ie<=-1)
      webAssemblyAvailable =!!window.WebAssembly;
  }
  if (webAssemblyAvailable){
    var ck=UI.readCookie('xcas_wasm');
    if (ck)
      webAssemblyAvailable=(ck=='1');
  }
  if (webAssemblyAvailable) // fixme: enable
    script.src =}#1\@print{+"giacwasm.js";
  else
    script.src  =}#1\@print{+"giac.js";
  document.getElementsByTagName("head")[0].appendChild(script);
</script>
}
\fi
}
\newcommand{\loadgiacscriptstart}{
\ifhevea
\@print{
<script language="javascript"> 
var Module = { 
        htmlcheck:true,
        htmlbuffer:'',
        ready:false,
        preRun: [],
        postRun: [],
        print: (function() {
          var element = document.getElementById('output');
          element.innerHTML='';// element.value = ''; // clear browser cache
          return function(text) {
            //console.log(text.charCodeAt(0));
            if (text.length==1 && text.charCodeAt(0)==12){ element.innerHTML=''; return; }
            if (text.length>=1 && text.charCodeAt(0)==2) {console.log('STX');Module.htmlcheck=false; htmlbuffer='';return;}
            if (text.length>=1 && text.charCodeAt(0)==3) {console.log('ETX');Module.htmlcheck=true; element.style.display='inherit'; element.innerHTML += htmlbuffer;htmlbuffer='';element.scrollTop = 99999; return;}
            if (Module.htmlcheck){
            // These replacements are necessary if you render to raw HTML 
             text = text.replace(/&/g, "&amp;");
             text = text.replace(/</g, "&lt;");
             text = text.replace(/>/g, "&gt;");
             text = text.replace('\n', '<br>', 'g');
             text += '<br>'
             element.style.display='inherit';
             element.innerHTML += text; // element.value += text + "\n";
             element.scrollTop = 99999; // focus on bottom
            } else htmlbuffer += text;
          };
        })(),
     canvas: document.getElementById('canvas'),};
Module['onRuntimeInitialized']=function(){ console.log('UI is ready'); Module.ready=true;}
</script>
}
\fi
}
\newcommand{\loadgiacmain}[1]{
\ifhevea
\@print{
<div>
<div id="maindiv" style=}#1\@print{>}
\fi
}
\newcommand{\loadgiaccontrol}{
\ifhevea
\@print{
</div>
<div id="controldiv" style="max-height: 400px; overflow:auto">
<span id="controlindex"></span>
<button title="Clone la derni&egrave;re commande ex&eacute;cut&eacute;ee vers Xcas pour Firefox" onclick="UI.clone()">Clone</button>
<button title="Efface la console" onclick="document.getElementById('output').innerHTML='';">Efface</button>
<button title="Increase console size" onclick="var field=document.getElementById('output'); var s=field.style.maxHeight; s=s.substr(0,s.length-2);s=eval(s)+20 ;if(s<innerHeight/2){s=s+'px';field.style.maxHeight=s; field=document.getElementById('maindiv'); s=field.style.maxHeight; s=s.substr(0,s.length-2);s=eval(s)-20; s=s+'px';field.style.maxHeight=s;}">+</button>
<button title="Decrease console size" onclick="var field=document.getElementById('output'); var s=field.style.maxHeight; s=s.substr(0,s.length-2);s=eval(s)-20 ; if(s>80){s=s+'px';field.style.maxHeight =s;field=document.getElementById('maindiv'); s=field.style.maxHeight; s=s.substr(0,s.length-2);s=eval(s)+20; s=s+'px';field.style.maxHeight=s;}">-</button>
<textarea title="Ligne de commande pour un calcul rapide" onkeypress="UI.ckenter(event,this,3)" style="width:400px;height:20px;font-size:large"></textarea><button  title="Evalue cellule precedente" onclick="UI.quick(this);">-></button><span></span>
&nbsp;&nbsp;<button onclick="var s=UI.caseval('restart;'); Module.print(s);" title="Reinitialise le moteur de calcul formel">Restart</button>
<button onclick="UI.exec(document.documentElement);" title='Cliquer ici pour executer toutes les commandes (attention cela peut etre long!)'>Exec. tout</button>
<canvas id='canvas' width=0 height=0   onmousedown="UI.canvas_pushed=true;UI.canvas_lastx=event.clientX; UI.canvas_lasty=event.clientY;"  onmouseup="UI.canvas_pushed=false;" onmousemove="UI.canvas_mousemove(event,'')"></canvas>
<div id="output" style="max-height: 80px; overflow:auto"></div>
</div>
</div>}
\fi
}
\ifhevea
\newcommand{\loadgiacscriptend}{
\@print{
<script language="javascript">
 var UI = {
  Datestart:Date.now(),
  n2d:0,
  python:0,
  histcount:0,
  usemathjax:false,
  lastcmd:'',
  clone:function(){
    if (UI.lastcmd.length){
       var tmp=UI.giaceval('VARS(-1)');
       tmp=encodeURIComponent(tmp);
       var url='https://www-fourier.univ-grenoble-alpes.fr/~parisse/xcasfr.html'+String.fromCharCode(35)+'+'+tmp+':;&+'+UI.lastcmd;
       console.log(url);
       window.open(url,'_blank');
    }
  },
  canvas_pushed:false,
  canvas_lastx:0,
  canvas_lasty:0,
  canvas_mousemove:function(event,no){
    if (UI.canvas_pushed){
      // Module.print(event.clientX);
      if (UI.canvas_lastx!=event.clientX){
        if (event.clientX>UI.canvas_lastx)
          giac3d('r'+no);
        else
          giac3d('l'+no);
        UI.canvas_lastx=event.clientX;
      }
      if (UI.canvas_lasty!=event.clientY){
        if (event.clientY>UI.canvas_lasty)
          giac3d('d'+no);
        else
          giac3d('u'+no);
        UI.canvas_lasty=event.clientY;
      }
    }
  },  
  count_newline:function(s){
    var ss=s.length,i,res=1;
    for (i=0;i<ss;i++){
      if (s[i]=='\n') res++;
    }
    return res;
  },
  ltgt:function(s){
    var ss=s.length,i,res='',c=0;
    for (i=0;i<ss-4;i++){
      if (s[i]=='\n') c++;
      if (s[i]!='&' || s[i+2]!='t' || s[i+3]!=';'){
        res += s[i];
        continue;
      }
      if (s[i+1]=='l'){
        res += '<';
        i +=3;
        continue;
      }
      if (s[i+1]=='g'){
        res += '>';
        i +=3;
        continue;
      }
      res += s[i];
    }
    for (;i<ss;i++) res+=s[i];
    return [res,c];
  },
  rmquote:function(tmp){
    var s=tmp.length;
    if (s>2 && tmp.charCodeAt(0)==34 && tmp.charCodeAt(s-1)==34)
      tmp=tmp.substr(1,s-2);
    return tmp;
  },
  renderhelp: function (s) {
    var pos0 = s.search("</b>");
    //console.log(s);
    var found = (s.substr(pos0 + 7, 20) != "Best match has score");
    var lh = s.substr(3, pos0 - 3);
    var unlocalized_cmd = lh;
    var sorig = s;
    pos1 = s.search("<br>");
    if (pos1 < 0) return sorig;
    var explication = s.substr(0, pos1);
    s = s.substr(pos1 + 4, s.length - pos1 - 4);
    pos1 = s.search("<br>");
    if (pos1 < 0) return sorig;
    var syntaxe = s.substr(0, pos1);
    s = s.substr(pos1 + 4, s.length - pos1 - 4);
    pos1 = s.search("<br>");
    if (pos1 < 0) return sorig;
    var voiraussi = s.substr(0, pos1);
    var examples = s.substr(pos1 + 4, s.length - pos1 - 4);
    s = '';//'<b>'+unlocalized_cmd+':</b> ';
    if (found)
      s += explication + '<br>Voir aussi: ' +voiraussi+'<br><b>Exemples : </b>'+examples;
    else
      s += explication.substr(0, pos0);
    return s;
  },   
  quick:function(field){
    var tmp1=field.previousSibling.value;
    var tmp=UI.caseval(tmp1);
    tmp=UI.rmquote(tmp); 
    tmp=UI.latexeval(tmp);
    Module.print(String.fromCharCode(2));
    Module.print("<tt>");
    Module.print(tmp1);
    Module.print("</tt><br>&nbsp;&nbsp;");
    if (tmp.length>3 && tmp.substr(0,3)=='<b>'){ 
       Module.print(UI.renderhelp(tmp)); tmp='';
    } else Module.print(tmp);
    Module.print("<br>");
    Module.print(String.fromCharCode(3));
    field.nextSibling.innerHTML='&nbsp;'+tmp;
   //UI.render_canvas(nextSibling);  
  },
  giaceval:function(text){
     if (UI.python) text='@@'+text;
     if (!Module.ready){ window.setTimeout(UI.giaceval,100,text); return " ... ";}
     var dogiaceval=Module.cwrap('caseval',  'string', ['string']);
     return dogiaceval(text);
  },
  caseval:function(text){
    UI.lastcmd=text;
    var s="non evalu&eacute;",err;
    try {
       s= UI.giaceval(text);
    } catch (err) { s=err.message;}
    var is_2d=s.length>4 && s.substr(0,4)=='gr2d';
    if (is_2d){
      s = '<canvas id="gr2d_'+UI.n2d+'" width=400 height=250>'+s+'</canvas>';
      //console.log(UI.n2d,s);
      UI.n2d++;
    }
    var is_3d=s.length>5 && s.substr(0,5)=='gl3d ';
    if (is_3d){
	var n3d=s.substr(5,s.length-5);
	s = '<canvas id="gl3d_'+n3d+'" onmousedown="UI.canvas_pushed=true;UI.canvas_lastx=event.clientX; UI.canvas_lasty=event.clientY;" onmouseup="UI.canvas_pushed=false;" onmousemove="UI.canvas_mousemove(event,'+n3d+')" width=400 height=250></canvas>';
    }
    return s;
  },
  pourcentmod:function(a,b){
    return a-Math.floor(a/b)*b;
  },
  color_list: ['black',
    'red',
    'green',
    'yellow',
    'blue',
    'magenta',
    'cyan',
    'white',
    'silver',
    'gray',
    'maroon',
    'purple',
    'fuchsia',
    'lime',
    'olive',
    'navy',
    'teal',
    'aqua',
    'antiquewhite',
    'aquamarine',
    'azure',
    'beige',
    'bisque',
    'blanchedalmond',
    'blueviolet',
    'brown',
    'burlywood',
    'cadetblue',
    'chartreuse',
    'chocolate',
    'coral',
    'cornflowerblue',
    'cornsilk',
    'crimson',
    'cyan',
    'darkblue',
    'darkcyan',
    'darkgoldenrod',
    'darkgray',
    'darkgreen',
    'darkgrey',
    'darkkhaki',
    'darkmagenta',
    'darkolivegreen',
    'darkorange',
    'darkorchid',
    'darkred',
    'darksalmon',
    'darkseagreen',
    'darkslateblue',
    'darkslategray',
    'darkslategrey',
    'darkturquoise',
    'darkviolet',
    'deeppink',
    'deepskyblue',
    'dimgray',
    'dimgrey',
    'dodgerblue',
    'firebrick',
    'floralwhite',
    'forestgreen',
    'gainsboro',
    'ghostwhite',
    'gold',
    'goldenrod',
    'greenyellow',
    'grey',
    'honeydew',
    'hotpink',
    'indianred',
    'indigo',
    'ivory',
    'khaki',
    'lavender',
    'lavenderblush',
    'lawngreen',
    'lemonchiffon',
    'lightblue',
    'lightcoral',
    'lightcyan',
    'lightgoldenrodyellow',
    'lightgray',
    'lightgreen',
    'lightgrey',
    'lightpink',
    'lightsalmon',
    'lightseagreen',
    'lightskyblue',
    'lightslategray',
    'lightslategrey',
    'lightsteelblue',
    'lightyellow',
    'limegreen',
    'linen',
    'mediumaquamarine',
    'mediumblue',
    'mediumorchid',
    'mediumpurple',
    'mediumseagreen',
    'mediumslateblue',
    'mediumspringgreen',
    'mediumturquoise',
    'mediumvioletred',
    'midnightblue',
    'mintcream',
    'mistyrose',
    'moccasin',
    'navajowhite',
    'oldlace',
    'olivedrab',
    'orangered',
    'orchid',
    'palegoldenrod',
    'palegreen',
    'paleturquoise',
    'palevioletred',
    'papayawhip',
    'peachpuff',
    'peru',
    'pink',
    'plum',
    'powderblue',
    'rosybrown',
    'royalblue',
    'saddlebrown',
    'salmon',
    'sandybrown',
    'seagreen',
    'seashell',
    'sienna',
    'skyblue',
    'slateblue',
    'slategray',
    'slategrey',
    'snow',
    'springgreen',
    'steelblue',
    'tan',
    'thistle',
    'tomato',
    'turquoise',
    'violet',
    'wheat',
    'whitesmoke',
    'yellowgreen'],
  arc_en_ciel: function (k) {
    var r, g, b;
    k += 21;
    k = pourcentmod(k,126);
    if (k < 0)
      k += 126;
    if (k < 21) {
      r = 251;
      g = 0;
      b = 12 * k;
    }
    if (k >= 21 && k < 42) {
      r = 251 - (12 * (k - 21));
      g = 0;
      b = 251;
    }
    if (k >= 42 && k < 63) {
      r = 0;
      g = (k - 42) * 12;
      b = 251;
    }
    if (k >= 63 && k < 84) {
      r = 0;
      g = 251;
      b = 251 - (k - 63) * 12;
    }
    if (k >= 84 && k < 105) {
      r = (k - 84) * 12;
      g = 251;
      b = 0;
    }
    if (k >= 105 && k < 126) {
      r = 251;
      g = 251 - (k - 105) * 12;
      b = 0;
    }
    return 'rgb(' + r + ',' + g + ',' + b + ')';
  },
  turtle_color: function (c) {
    if (c >= 0x100) {
      if (c < 0x17e)
        return UI.arc_en_ciel(c);
      var r=8*((c>>11) & 0x1f);
      var g=4*((c>>5) & 0x3f);
      var b=8*(c & 0x1f);
      return 'rgb(' + r + ',' + g + ',' + b + ')';
    }
    return UI.color_list[c];
  },
  pixon_draw: function (id, s) {
    var v = eval(s);
    if (!Array.isArray(v)) return;
    //console.log(v[0], v.length);
    var canvas = document.getElementById(id);
    var l = v.length, w = 0, h = 0;
    if (l < 2) return;
    var scale = v[0];
    for (var k = 1; k < l; k++) {
      var cur = v[k];
      var x = cur[0], y = cur[1];
      if (cur.length==3 && typeof cur[2]!="number"){
	x+=100;
	y+=16;
      }
      if (cur.length==4) {
        var tmp = cur[3];
	if (typeof tmp=="number"){
          if (tmp > 0) y += tmp; else x -= tmp;
	} else {
	  x+=100;
	  y+=16;
	}
      }
      //console.log(cur,x,y);
      if (x > w) w = x;
      if (y > h) h = y;
    }
    w = (w + 1) * scale;
    h = (h + 1) * scale;
    canvas.width = w;
    canvas.height = h;
    //console.log(h,w);
    if (canvas.getContext) {
      var ctx = canvas.getContext('2d');
      for (var k = 1; k < l; k++) {
        var cur = v[k], cl;
        //console.log(cur);
        if (!Array.isArray(cur) || (cl = cur.length) < 2) continue;
        // cur[0]=x, cur[1]=y, cur[2]=color, cur[3]=w if +, h if -
        var x = cur[0] * scale;
        var y = cur[1] * scale;
	if (cl>2 && typeof cur[2]=="string"){
	  console.log(cur[2]);
	  ctx.font = '16px serif';
	  ctx.fillStyle = 'black';
	  ctx.fillText(cur[2],x,y+16,100);
	  continue;
	}
        ctx.fillStyle = (cl > 2) ? UI.turtle_color(cur[2]) : 'black';
        if (cl < 4) {
          ctx.fillRect(x, y, scale, scale);
          continue;
        }
	if (typeof cur[3]=="string"){
	  ctx.font = '16px serif';
	  ctx.fillText(cur[3],x,y+16,100);
	  continue;
	}
        var h = cur[3] * scale, w = scale;
        if (h < 0) {
          w = -h;
          h = scale;
        }
        ctx.fillRect(x, y, w, h);
      }
    }
  },
  turtle_dx: 0, // shift frame
  turtle_dy: 0,
  turtle_z: 1,  // zoom factor
  turtle_maillage: 1,
  turtle_draw: function (id, s) {
    if (s.length < 7) return;
    s = s.substr(5, s.length - 6);
    if (s.length > 7 && s.substr(s, 6) == "pixon(") {
      UI.pixon_draw(id, s.substr(6, s.length - 7));
      return;
    }
    if (s.length < 6 || s.substr(s, 5) != "logo(")
      return;
    s = s.substr(5, s.length - 6);
    //console.log(s);
    var v = eval(s);
    if (!Array.isArray(v)) return;
    //console.log(v[0]);
    var canvas = document.getElementById(id);
    var w = canvas.width, h = canvas.height;
    if (canvas.getContext) {
      var ctx = canvas.getContext('2d');
      var turtlezoom = UI.turtle_z, turtlex = UI.turtle_dx, turtley = UI.turtle_dy;
      // maillage
      if (UI.turtle_maillage & 3) {
        ctx.fillStyle = 'black';
        var xdecal = Math.floor(turtlex / 10.0) * 10;
        var ydecal = Math.floor(turtley / 10.0) * 10;
        if ((UI.turtle_maillage & 0x3) == 1) {
          for (var i = xdecal; i < w + xdecal; i += 10) {
            for (var j = ydecal; j < h + ydecal; j += 10) {
              var X = Math.floor((i - turtlex) * turtlezoom + .5);
              var Y = Math.floor((j - turtley) * turtlezoom + .5);
              // console.log(X,Y);
              ctx.fillRect(X, h - Y, 1, 1);
            }
          }
        } else {
          var dj = Math.sqrt(3.0) * 10, i0 = xdecal;
          for (var j = ydecal; j < h + ydecal; j += dj) {
            var J = Math.floor(h - (j - turtley) * turtlezoom);
            for (var i = i0; i < w + xdecal; i += 10) {
              ctx.fillRect(Math.floor((i - turtlex) * turtlezoom + .5), J, 1, 1);
            }
            i0 += dj;
            while (i0 >= 10)
              i0 -= 10;
          }
        }
      }
      var l = v.length, i;
      // montre la position et le cap (v[l-1])
      var prec = v[l - 1];
      ctx.font = '16px serif';
      ctx.fillStyle = 'yellow';
      ctx.fillRect(w - 40, 0, 40, 50);
      ctx.fillStyle = 'black';
      ctx.fillText('x:' + prec[0], w - 40, 15);
      ctx.fillText('y:' + prec[1], w - 40, 31);
      ctx.fillText('t:' + prec[2], w - 40, 49);
      // v[i]=[x(0),y(1),cap(2),status(3),r(4),chaine(5)],
      // couleur=status >> 11
      // longueur_tortue= (status>>3)&0xff
      // direct=status&4 (vrai si angle dans le sens trigo)
      // visible=status&2
      // crayon baisse=status&1
      // si r>0 arc/disque rayon=r & 0x1ff, theta1=(r >> 9) & 0x1ff, theta2=(r >> 18) & 0x1ff
      //        rempli=(r>>27)&0x1
      // si r<0 ligne polygonale extremite v[i] origine v[i+r] (r<0)
      for (k = 1; k < l; k++) {
        prec = v[k - 1];
        var cur = v[k];
        var preccouleur = prec[3] >> 11; // -> FIXME colors
        var curcouleur = prec[3] >> 11; // -> FIXME colors
        if (cur[5].length) {
          ctx.font = cur[4] + 'px serif';
          ctx.strokeStyle = ctx.fillStyle = UI.turtle_color(curcouleur);
          ctx.fillText(cur[5], turtlezoom * (cur[0] - turtlex), h - turtlezoom * (cur[1] - turtley));
          continue;
        }
        var radius = cur[4], precradius = prec[4];
        var x1 = Math.floor(turtlezoom * (prec[0] - turtlex) + .5),
            y1 = Math.floor(turtlezoom * (prec[1] - turtley) + .5),
            x2 = Math.floor(turtlezoom * (cur[0] - turtlex) + .5),
            y2 = Math.floor(turtlezoom * (cur[1] - turtley) + .5);
        if (radius > 0) {
          var r = radius & 0x1ff, theta1, theta2, rempli, x, y, R, angle;
          theta1 = prec[2]+ ((radius >> 9) & 0x1ff);
          theta2 = prec[2] + ((radius >> 18) & 0x1ff);
          rempli = (radius >> 27) & 1;
	  var seg = (radius >> 28) & 1;
          R = Math.floor(turtlezoom * r + .5);
          angle1 = Math.PI / 180 * (theta1 - 90);
          angle2 = Math.PI / 180 * (theta2 - 90);
          x = Math.floor(turtlezoom * (cur[0] - turtlex - r * Math.cos(angle2)) + .5);
          y = Math.floor(turtlezoom * (cur[1] - turtley - r * Math.sin(angle2)) + .5);
          ctx.beginPath();
	  if (seg)
            ctx.moveTo(x2, h - y2);
	  else {
            ctx.moveTo(x, h - y);
            ctx.lineTo(x2, h - y2);
	  }
	  //console.log(x,y,x1,y1,angle1,angle2);
          ctx.arc(x, h - y, R, -angle2,-angle1);
          ctx.closePath();
          ctx.strokeStyle = ctx.fillStyle = UI.turtle_color(curcouleur);
          if (rempli)
            ctx.fill();
          else
            ctx.stroke();
          continue;
        }
        if (prec[3] & 1) {
          ctx.strokeStyle = ctx.fillStyle = UI.turtle_color(preccouleur);
          ctx.beginPath();
          ctx.moveTo(x1, h - y1);
          ctx.lineTo(x2, h - y2);
          ctx.closePath();
          ctx.stroke();
        }
        if (radius < -1 && k + radius >= 0) {
          ctx.strokeStyle = ctx.fillStyle = UI.turtle_color(curcouleur);
          ctx.beginPath();
          var x0 = Math.floor(turtlezoom * (cur[0] - turtlex) + .5), y0 = Math.floor(turtlezoom * (cur[1] - turtley) + .5);
          //console.log('begin',x0,y0);
          ctx.moveTo(x0, h - y0);
          for (var i = -1; i >= radius; i--) {
            prec = v[k + i];
            var x = Math.floor(turtlezoom * (prec[0] - turtlex) + .5);
            var y = Math.floor(turtlezoom * (prec[1] - turtley) + .5);
            //console.log(i,x,y);
            ctx.lineTo(x, h - y);
          }
          //console.log('end',x0,y0);
          //ctx.lineTo(x0,h-y0);
          ctx.closePath();
          ctx.fill(); // automatically close path
        }
      }
      var cur = v[l - 1];
      if (cur[3] & 2) {
        // dessin de la tortue
        var x = Math.floor(turtlezoom * (cur[0] - turtlex) + .5);
        var y = Math.floor(turtlezoom * (cur[1] - turtley) + .5);
        var cost = Math.cos(cur[2] * Math.PI / 180);
        var sint = Math.sin(cur[2] * Math.PI / 180);
        var turtle_length = (cur[3] >> 3) & 0xff;
        var Dx = Math.floor(turtlezoom * turtle_length * cost / 2 + .5);
        var Dy = Math.floor(turtlezoom * turtle_length * sint / 2 + .5);
        //console.log('tortue',cur,w,h,turtlezoom,x,y,Dx,Dy);
        ctx.strokeStyle = ctx.fillStyle = UI.turtle_color(curcouleur);
        ctx.beginPath();
        ctx.moveTo(x + Dy, h - (y - Dx));
        ctx.lineTo(x - Dy, h - (y + Dx));
        ctx.closePath();
        ctx.stroke();
        if (!(cur[3] & 1))
          ctx.strokeStyle = ctx.fillStyle = UI.turtle_color(curcouleur + 1);
        ctx.beginPath();
        ctx.moveTo(x + Dy, h - (y - Dx));
        ctx.lineTo(x + 3 * Dx, h - (y + 3 * Dy));
        ctx.closePath();
        ctx.stroke();
        ctx.beginPath();
        ctx.moveTo(x - Dy, h - (y + Dx));
        ctx.lineTo(x + 3 * Dx, h - (y + 3 * Dy));
        ctx.closePath();
        ctx.stroke();
      }
    }
  },
  render_canvas:function(field){
   var n=field.id;
   if (n && n.length>4 && n.substr(0,4)=='gr2d'){
     var s=field.innerHTML;
     //console.log(s);
     UI.turtle_draw(n, s);
   }
   if (n && n.length>5 && n.substr(0,5)=='gl3d_'){
    Module.print(n);
    var n3d=n.substr(5,n.length-5);
    giac3d(n3d);
    return;
   }
   var f=field.firstChild;
   for (;f;f=f.nextSibling){
     UI.render_canvas(f);
   }
  },
  eval_form: function(field){
    UI.giaceval('assume('+field.name.value+'=round('+field.valname.value+',12))');
    var s=UI.caseval(field.prog.value);
    var is_svg=s.substr(1,4)=='<svg';
    if (is_svg) field.parentNode.lastChild.innerHTML=s.substr(1,s.length-2);
    else field.parentNode.lastChild.innerHTML=s;
    UI.render_canvas(field.parentNode.lastChild);
  },
  latexeval:function(text){
    var tmp=text;
    if (tmp.length>5 && tmp.substr(0,5)=='gl3d_') return tmp;
    if (tmp.length>10 && tmp.substr(0,10)=='GIAC_ERROR') return '"'+tmp.substr(11,tmp.length-11)+'"';
    if (tmp.length>5 && tmp.substr(1,4)=='<svg') return tmp.substr(1,tmp.length-2);
    if (tmp.length>5 && tmp.substr(0,4)=='<svg') return tmp;
    if (tmp.length>3 && tmp.substr(0,3)=='<b>') return tmp;
     if (UI.usemathjax){
       tmp=UI.giaceval('latex(quote('+tmp+'))');
       var dollar=String.fromCharCode(36);
       tmp=dollar+dollar+tmp.substr(1,tmp.length-2)+dollar+dollar;
       return tmp;
     }
     tmp=UI.giaceval('mathml(quote('+tmp+',1))');
     tmp=tmp.substr(1,tmp.length-2);
    return tmp;   
  },
  ckenter:function(event,field,mode){
    var key = event.keyCode;
    if (key != 13 || event.shiftKey) return true;
   if (mode==3){ UI.quick(field.nextSibling); event.preventDefault(); field.select(); return true; }
    var tmp=field.value;
   Module.print(tmp);
    tmp=UI.caseval(tmp);
    if (mode==1){
      tmp=UI.rmquote(tmp); 
   }
   if (mode==2){
     tmp=UI.latexeval(tmp);
   }
   field.nextSibling.nextSibling.innerHTML=tmp;
   UI.render_canvas(field.nextSibling.nextSibling);
   if (UI.usemathjax) MathJax.Hub.Queue(["Typeset",MathJax.Hub,field.nextSibling.nextSibling]);
   if (event.preventDefault) event.preventDefault();
    return false;
  },
  exec: function(field){
     if (field.nodeName=="BUTTON" && field.innerHTML!='Clone' && field.innerHTML!='Restart' && field.innerHTML!='Exec. tout' ){
        field.click();
        return;
     }
     var f=field.firstChild;
     while (f){
       UI.exec(f);
       f=f.nextSibling;
     }
   },
  execonload: function(field){
     if (!Module.ready){ 
         //console.log('execonload ', field.innerHTML);
         window.setTimeout(UI.execonload, 100, field); 
     }
     var f=field.nextSibling;
     if (f && f.innerHTML=="onload" && field.nodeName=="BUTTON"){
        field.click();
        return;
     }
     f=field.firstChild;
     while (f){
       UI.execonload(f);
       f=f.nextSibling;
     }
   },
  textarealtgt: function(field){
     if (field.nodeName=="TEXTAREA"){
        var tmp=UI.ltgt(field.value);
        field.value=tmp[0];
        //field.style.height=20*(tmp[1]+1)+'px';
        field.rows=tmp[1]+1;
        //console.log(tmp,field.rows);
        return;
     }
     var f=field.firstChild;
     while (f){
       UI.textarealtgt(f);
       f=f.nextSibling;
     }
   }
 };
 window.onload = function(e){
   var isFirefox = typeof InstallTrigger !== 'undefined';   // Firefox 1.0+
   var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0;
  var ua = window.navigator.userAgent;
  var old_ie = ua.indexOf('MSIE ');
  var new_ie = ua.indexOf('Trident/');
  if ((!isFirefox && !isSafari) || (old_ie > -1) || (new_ie > -1) || window.chrome){
     UI.usemathjax=true;
     alert("Votre navigateur ne supporte MathML, on utilise MathJax pour l'affichage 2d.  Les calculs seraient plus rapides et les resultats seraient mieux affiches avec Firefox.");
  }
  if (UI.usemathjax){
    var script = document.createElement("script");
    script.type = "text/javascript";
    script.src  = "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS-MML_HTMLorMML";
    document.getElementsByTagName("head")[0].appendChild(script);
  }
  var elem= document.getElementById('controlindex');
  elem.innerHTML='<hr><a href="'+String.fromCharCode(35)+'sec1">Table</a>, <a href="'+String.fromCharCode(35)+'sec2">Index</a>'+elem.innerHTML;
  elem=document.getElementById('maindiv');
  if (elem.style.maxHeight=='500px')
    elem.style.maxHeight=(window.innerHeight-120)+'px';
  elem= document.getElementById('maindiv');
  elem.style.maxHeight=(window.innerHeight-150)+'px';
  giac3d = Module.cwrap('_ZN4giac13giac_rendererEPKc','number', ['string']);
  UI.giaceval('set_language(1);');
  //UI.giaceval('factor(x^4-1)');
  //UI.giaceval('sin(x+y)+f(t)');
  UI.textarealtgt(document.documentElement);
  window.setTimeout(UI.execonload, 1000, document.documentElement); // UI.execonload(document.documentElement);
  document.getElementById('output').innerHTML='';
 // if (confirm('Executer les commandes?')) UI.exec(document.documentElement);
 };
</script>
}
}
\else
\newcommand{\loadgiacscriptend}{}
\fi
\ifhevea
\newcommand{\giacpython}{
\@print{<button onclick="UI.python=1;" style="display:none"></button><span style="display:none">onload</span>}
}
\newenvironment{giacprog}{
\verbatim}
{\endverbatim 
\@print{<button onclick="var field=parentNode.previousSibling; var tmp=field.innerHTML;if(tmp.length==0) tmp=field.value;var t=createElement('TEXTAREA');t.style.fontSize=16;t.cols=60;t.rows=10;var tmp1=UI.ltgt(tmp);t.value=tmp1[0];tmp=UI.caseval(tmp);tmp=UI.rmquote(tmp);nextSibling.innerHTML=tmp; UI.render_canvas(nextSibling); field.parentNode.insertBefore(t,field);field.parentNode.removeChild(field);">exe</button><span></span><br>
}
}
\newenvironment{giaconload}{
\verbatim}
{\endverbatim 
\@print{<button onclick="var field=parentNode.previousSibling; var tmp=field.innerHTML;if(tmp.length==0) tmp=field.value;var t=createElement('TEXTAREA');t.style.fontSize=16;t.cols=60;t.rows=UI.count_newline(tmp);var tmp1=UI.ltgt(tmp)[0];t.value=tmp1;tmp=UI.caseval(tmp);tmp=UI.rmquote(tmp);nextSibling.innerHTML=tmp; UI.render_canvas(nextSibling); field.parentNode.insertBefore(t,field);field.parentNode.removeChild(field);">exe</button><span>onload</span><br>
}
}
\newenvironment{giaconloadhide}{
\verbatim}
{\endverbatim 
\@print{<button onclick="this.style.display='none';var field=parentNode.previousSibling; var tmp=field.innerHTML;if(tmp.length==0) tmp=field.value;var t=createElement('TEXTAREA');t.style.display='none';t.style.fontSize=16;t.cols=60;t.rows=UI.count_newline(tmp);var tmp1=UI.ltgt(tmp)[0];t.value=tmp1;tmp=UI.caseval(tmp);tmp=UI.rmquote(tmp);nextSibling.innerHTML=tmp; UI.render_canvas(nextSibling); field.parentNode.insertBefore(t,field);field.parentNode.removeChild(field);">exe</button><span>onload</span><br>
}
}
\else
\newcommand\giacpython{}
\newenvironment{giacprog}
{
\VerbatimEnvironment
\begin{Verbatim}
}
{
\end{Verbatim}
}
\newenvironment{giaconload}
{
\VerbatimEnvironment
\begin{Verbatim}
}
{
\end{Verbatim}
}
\newenvironment{giaconloadhide}
{
\VerbatimEnvironment
\begin{Verbatim}
}
{
\end{Verbatim}
}
\fi

% for example \giaccmd{factor}{x^4-1}
\newcommand{\giaccmd}[3][style="width:400px;font-size:large"]{
\ifhevea
\@print{<textarea}
\@getprint{#1>#3}
\@print{</textarea><button onclick="var tmp=UI.caseval(}
\@getprint{'#2('}
\@print{+previousSibling.value+')');tmp=UI.rmquote(tmp); nextSibling.innerHTML='&nbsp;'+tmp;UI.render_canvas(nextSibling);">}
\@getprint{#2}
\@print{</button><span></span><br>}
\else
\lstinline@#2(#3)@
\fi
}
\newcommand{\giacinput}[2][style="width:400px;font-size:large"]{
\ifhevea
\@print{<textarea onkeypress="UI.ckenter(event,this,1)" }
\@getprint{#1>#2}
\@print{</textarea><button onclick="previousSibling.style.display='inherit';var tmp=UI.caseval(previousSibling.value);tmp=UI.rmquote(tmp); nextSibling.innerHTML='&nbsp;'+tmp;UI.render_canvas(nextSibling);">exe</button><span></span><br>}
\else
\lstinline@#2@
\fi
}
\newcommand{\giachidden}[3][style="display:none;width:400px;font-size:large"]{
\ifhevea
\@print{<textarea onkeypress="UI.ckenter(event,this,1)" }
\@getprint{#1>#2}
\@print{</textarea><button onclick="previousSibling.style.display='inherit';var tmp=UI.caseval(previousSibling.value);tmp=UI.rmquote(tmp); nextSibling.innerHTML='&nbsp;'+tmp;UI.render_canvas(nextSibling);">}
\@getprint{#3}
\@print{</button><span></span><br>}
\else
\lstinline@#2@
\fi
}
\newcommand{\giacinputbig}[2][style="width:800px;font-size:large"]{
\ifhevea
\@print{<textarea onkeypress="UI.ckenter(event,this,1)" }
\@getprint{#1>#2}
\@print{</textarea><button onclick="previousSibling.style.display='inherit';var tmp=UI.caseval(previousSibling.value);tmp=UI.rmquote(tmp); nextSibling.innerHTML='&nbsp;'+tmp;UI.render_canvas(nextSibling);">exe</button><span></span><br>}
\else
\lstinline@#2@
\fi
}
\newcommand{\giaccmdmath}[3][style="width:400px;font-size:large"]{\ifhevea
\begin{rawhtml}<br><textarea \end{rawhtml}
\@getprint{#1>#3}
\begin{rawhtml}</textarea><button onclick="var tmp=UI.caseval(\end{rawhtml} 
\@getprint{'#2('+}
\begin{rawhtml}previousSibling.value+')');  tmp=UI.latexeval(tmp);nextSibling.innerHTML='&nbsp;'+tmp; if (UI.usemathjax) MathJax.Hub.Queue(['Typeset',MathJax.Hub,nextSibling]);
">\end{rawhtml}
\@getprint{#2}
\begin{rawhtml}</button><span></span><br>\end{rawhtml}
\else
\lstinline@#2(#3)@
\fi
}
\newcommand{\giacinputmath}[2][style="width:400px;font-size:large"]{\ifhevea
\begin{rawhtml}<br><textarea onkeypress="UI.ckenter(event,this,2)" \end{rawhtml}
\@getprint{#1>#2} 
\begin{rawhtml}</textarea><button onclick="previousSibling.style.display='inherit';var tmp=UI.caseval(previousSibling.value); tmp=UI.latexeval(tmp);nextSibling.innerHTML='&nbsp;'+tmp; if (UI.usemathjax) MathJax.Hub.Queue(['Typeset',MathJax.Hub,nextSibling])">exe</button><span></span><br>\end{rawhtml}
\else
\lstinline@#2@
\fi
}
\newcommand{\giachiddenmath}[3][style="display:none;width:400px;font-size:large"]{\ifhevea
\begin{rawhtml}<br><textarea onkeypress="UI.ckenter(event,this,2)" \end{rawhtml}
\@getprint{#1>#2} 
\begin{rawhtml}</textarea><button onclick="previousSibling.style.display='inherit';var tmp=UI.caseval(previousSibling.value); tmp=UI.latexeval(tmp);nextSibling.innerHTML='&nbsp;'+tmp; if (UI.usemathjax) MathJax.Hub.Queue(['Typeset',MathJax.Hub,nextSibling])">\end{rawhtml}
\@getprint{#3}
\begin{rawhtml}</button><span></span><br>\end{rawhtml}
\else
\lstinline@#2@
\fi
}
\newcommand{\giaccmdbigmath}[3][style="width:800px;font-size:large"]{\ifhevea
\begin{rawhtml}<br><textarea \end{rawhtml}
\@getprint{#1>#3} 
\begin{rawhtml}</textarea><button onclick="var tmp=UI.caseval(\end{rawhtml} 
\@getprint{'#2('+}
\begin{rawhtml}previousSibling.value+')');  tmp=UI.latexeval(tmp);nextSibling.innerHTML=tmp; if (UI.usemathjax) MathJax.Hub.Queue(['Typeset',MathJax.Hub,nextSibling])">\end{rawhtml}
\@getprint{#2}
\begin{rawhtml}</button><div style="width:800px;max-height:200px;overflow:auto;color:blue;text-align:center"></div><br>\end{rawhtml}
\else
\lstinline@#2(#3)@
\fi
}
\newcommand{\giacinputbigmath}[2][style="width:800px;font-size:large"]{\ifhevea
\begin{rawhtml}<div><textarea onkeypress="UI.ckenter(event,this,2)" \end{rawhtml}
\@getprint{#1>#2} 
\begin{rawhtml}</textarea><button onclick="previousSibling.style.display='inherit';var tmp=UI.caseval(previousSibling.value); tmp=UI.latexeval(tmp);nextSibling.innerHTML=tmp; if (UI.usemathjax) MathJax.Hub.Queue(['Typeset',MathJax.Hub,nextSibling])">exe</button><div style="width:800px;max-height:200px;overflow:auto;color:blue;text-align:center"></div></div>\end{rawhtml}
\else
\lstinline@#2@
\fi
}
\newcommand{\giaclink}[2][Tester en ligne]{\ifhevea
\begin{rawhtml}<a href=\end{rawhtml}\@getprint{"#2"}
\begin{rawhtml} target="_blank">\end{rawhtml}
\@getprint{#1}
\begin{rawhtml}</a>\end{rawhtml}
\else
\fi
}
% \giacslider{name}{mini}{maxi}{step}{value}{prog}
\newcommand{\giacslider}[6]{
\ifhevea
\begin{rawhtml}
<div><form onsubmit="setTimeout(function(){UI.eval_form(form);});return false;">
<input type="text" name="name" size="1" value=
\end{rawhtml}
\@getprint{"#1">}
\begin{rawhtml}
=<input type="number" name="valname" onchange="UI.eval_form(form);" value=
\end{rawhtml}
\@getprint{"#5">}
\begin{rawhtml}
<input type="button" value="-" onclick="valname.value -= stepname.value;UI.eval_form(form);">
<input type="button" value="+" onclick="valname.value -= -stepname.value;UI.eval_form(form);">
<input type="number" name="stepname" value=
\end{rawhtml}
\@getprint{"#4">}
\begin{rawhtml}
<input type="range" name="rangename"
onclick="valname.value=value;UI.eval_form(form);" value=
\end{rawhtml}
\@getprint{"#5" min="#2" max="#3" step="#4">}
\begin{rawhtml}
<textarea name="prog" onchange="UI.eval_form(form)" style="width:400px;vertical-align:bottom;font-size:large">
\end{rawhtml}\@getprint{#6}
\begin{rawhtml}
</textarea>
</form>
<span>Not evaled</span></div>
\end{rawhtml}
\else
\fi
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% giac/hevea end code definitions
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
