]> matita.cs.unibo.it Git - helm.git/blob - matitaB/matita/matitaweb.js
Matitaweb: Fixed a bug in matitaweb.js concerning disambiguation and escaping.
[helm.git] / matitaB / matita / matitaweb.js
1 var locked;
2 var unlocked;
3 var workarea;
4 var scriptcell;
5 var goalcell;
6 var goals;
7 var goalview;
8 var filename;
9 var logarea;
10 var advanceButton;
11 var retractButton;
12 var cursorButton;
13 var bottomButton;
14 var dialogBox;
15 var dialogTitle;
16 var dialogContent;
17 var metasenv = "";
18 var lockedbackup = "";
19 var matita;
20
21 function text_of_html(h)
22 {
23   if(document.all) {
24      return h.innerText;
25   } else {
26      return h.textContent;
27   }
28 }
29
30 function unescape_html(s)
31 {
32   u = document.getElementById("unescape");
33   u.innerHTML = s;
34   return text_of_html(u)
35 }
36
37 function filterByClass (elements,class){
38   var itemsfound = new Array;
39   for(var i=0;i<elements.length;i++){
40     if(elements[i].className == class){
41       itemsfound.push(elements[i]);
42     }
43   }
44   return itemsfound;
45 }
46
47 function initialize()
48 {
49   if (readCookie("session") == null) {
50     window.location = "/login.html"
51   } else {
52     body = document.body;
53     titlebar = document.getElementById("titlebar");
54     matitaTitle = document.getElementById("matitaTitle");
55     apparea = document.getElementById("matitaapparea");
56     locked = document.getElementById("locked");
57     unlocked = document.getElementById("unlocked");
58     toparea = document.getElementById("toparea");
59     workarea = document.getElementById("workarea");
60     scriptcell = document.getElementById("scriptcell");
61     sidearea = document.getElementById("sidearea");
62     disambcell = document.getElementById("disambcell");
63     goalcell = document.getElementById("goalcell");
64     goals = document.getElementById("goals");
65     goalview = document.getElementById("goalview");
66     filename = document.getElementById("filename");
67     logarea = document.getElementById("logarea");
68     advanceButton = document.getElementById("advance");
69     retractButton = document.getElementById("retract");
70     cursorButton = document.getElementById("cursor");
71     bottomButton = document.getElementById("bottom");
72     dialogBox = document.getElementById("dialogBox");
73     uploadBox = document.getElementById("uploadBox");
74     dialogTitle = document.getElementById("dialogTitle");
75     dialogContent = document.getElementById("dialogContent");
76
77     matita = new Object();
78     matita.disambMode = matita.proofMode = false;
79
80     // hide sequent view at start
81     initializeLayout();
82     updateSide();
83
84     changeFile("test.ma");
85
86     // initialize keyboard events in the unlocked script
87     init_keyboard(unlocked);
88   }
89 }
90
91 function changeFile(name) {
92     current_fname = name;
93     matitaTitle.innerHTML = "Matita - cic:/matita/" + name;
94 }
95
96 function init_keyboard(target)
97 {
98     if (target.addEventListener)
99     {
100 //       target.addEventListener("keydown",keydown,false);
101        target.addEventListener("keypress",keypress,false);
102 //       target.addEventListener("keyup",keyup,false);
103 //       target.addEventListener("textInput",textinput,false);
104     }
105     else if (target.attachEvent)
106     {
107 //       target.attachEvent("onkeydown", keydown);
108        target.attachEvent("onkeypress", keypress);
109 //       target.attachEvent("onkeyup", keyup);
110 //       target.attachEvent("ontextInput", textinput);
111     }
112     else
113     {
114 //       target.onkeydown= keydown;
115        target.onkeypress= keypress;
116 //       target.onkeyup= keyup;
117 //       target.ontextinput= textinput;   // probably doesn't work
118     }
119  
120 }
121
122 function keyval(n)
123 {
124     if (n == null) return 'undefined';
125     var s= '' + n;
126     if (n >= 32 && n < 127) s+= ' (' + String.fromCharCode(n) + ')';
127     while (s.length < 9) s+= ' ';
128     return s;
129 }
130  
131 function string_of_key(n)
132 {
133     if (n == null) return 'undefined';
134     return String.fromCharCode(n);
135 }
136
137 function pressmesg(w,e)
138 {
139    debug(w + '  keyCode=' + keyval(e.keyCode) +
140                  ' which=' + keyval(e.which) +
141                  ' charCode=' + keyval(e.charCode) +
142                  '\n          shiftKey='+e.shiftKey
143               + ' ctrlKey='+e.ctrlKey
144               + ' altKey='+e.altKey
145               + ' metaKey='+e.metaKey);
146 }
147  
148 function suppressdefault(e,flag)
149 {
150    if (flag)
151    {
152        if (e.preventDefault) e.preventDefault();
153        if (e.stopPropagation) e.stopPropagation();
154    }
155    return !flag;
156 }
157
158 function restoreSelection(r) {
159     unlocked.focus();
160     if (r != null) {
161         if (window.getSelection)//non IE and there is already a selection
162         {
163             var s = window.getSelection();
164             if (s.rangeCount > 0) 
165                 s.removeAllRanges();
166             s.addRange(r);
167         }
168         else 
169             if (document.createRange)//non IE and no selection
170             {
171                 window.getSelection().addRange(r);
172             }
173             else 
174                 if (document.selection)//IE
175                 {
176                     r.select();
177                 }
178     }
179 }
180
181 function lookup_tex(texmacro)
182 {
183   texmacro = texmacro.substring(1);
184   return unescape(macro2utf8[texmacro]);
185 }
186
187 function strip_errors() 
188 {
189     errors = filterByClass(unlocked.getElementsByTagName("span"),"error");
190     for (i = 0; i < errors.length; i++) {
191         children = errors[i].childNodes;
192         for (j = 0; j < children.length; j++) {
193             unlocked.insertBefore(children[j],errors[i]);
194         }
195         unlocked.removeChild(errors[i]);
196     }
197 }
198  
199 function keypress(e)
200 {
201    if (!e) e= event;
202    pressmesg('keypress',e);
203    var s = string_of_key(e.charCode);
204    strip_errors();
205    if (s == " ") {
206         j = getCursorPos();
207         i = unlocked.innerHTML.lastIndexOf('\\',j);
208         if (i >= 0) {
209           match = unlocked.innerHTML.substring(i,j);
210           sym = unescape_html(lookup_tex(match));
211           if (sym != "undefined") {
212              if (window.getSelection) { // non IE
213                 savedRange.setStart(savedsc,savedso - (j-i));
214                 savedRange.deleteContents();
215                 savedRange.insertNode(document.createTextNode(sym));
216                 savedsc.parentNode.normalize();
217                 if (savedRange.collapsed) { // Mozilla
218                   savedRange.setEnd(savedsc,savedRange.endOffset + sym.length);
219                 }
220                 savedRange.collapse(false);
221              } else {
222                 savedRange.moveStart(i-j);
223                 savedRange.text(sym);
224                 savedRange.collapse(false);
225              }
226              restoreSelection(savedRange); 
227              return suppressdefault(e,true);
228           }
229           else {
230              // restoreSelection(0); 
231              return suppressdefault(e,false);
232           }
233         }
234         else return suppressdefault(e,false);
235    } else {
236         return suppressdefault(e,false);
237    }
238 }
239  
240 var logtxt = "";
241
242 function debug(txt)
243 {
244         // internet explorer (v.9) doesn't work with innerHTML
245         // but google chrome's innerText is, in a sense, "write only"
246         // what should we do?
247         // logarea.innerText = txt + "\n" + logarea.innerText;
248         logtxt = /* logtxt + "\n" +*/ txt;
249 }
250
251 function showLog() {
252   logWin = window.open( "", "Matita Log",
253      "width=600,height=450,status,scrollbars,resizable,screenX=20,screenY=40,left=20,top=40");
254   logWin.document.write('<html><head><title>Matita Log' + '</title></head>');   
255   logWin.document.write('<body><textarea style="width:100%;height:100%;">' +
256     logtxt + '</textarea></body></html>');
257   logWin.document.close(); 
258 }
259
260 function listhd(l)
261 {
262         ar = l.split("#");
263         debug("hd of '" + l + "' = '" + ar[0] + "'");
264         return (ar[0]);
265 }
266
267 function listtl(l)
268 {
269         i = l.indexOf("#");
270         tl = l.substr(i+1);
271         debug("tl of '" + l + "' = '" + tl + "'");
272         return (tl);
273 }
274
275 function listcons(x,l)
276 {
277         debug("cons '" + x + "' on '" + l + "'");
278         return (x + "#" + l);
279 }
280
281 function listnil()
282 {
283         return ("");
284 }
285
286 function is_nil(l)
287 {
288         return (l == "");
289 }
290
291 function fold_left (f,acc,l)
292 {
293         if (is_nil(l))
294            { debug("'" + l + "' is fold end");
295            return (acc); }
296         else
297            { debug("'" + l + "' is fold cons");
298              return(fold_left (f,f(acc,(listhd(l))),listtl(l))); }
299 }
300
301 function listiter (f,l)
302 {
303         if (is_nil(l))
304         { debug("'" + l + "' is nil");
305            return;
306         }
307         else
308         {
309            debug("'" + l + "' is not nil");
310            f(listhd(l));
311            listiter(f,listtl(l));
312         }
313 }
314
315 function listmap (f,l)
316 {
317         debug("listmap on " + l);
318         if (is_nil(l)) 
319            { debug("returning listnil");
320              return(listnil());
321            }
322         else 
323            { debug("cons f(hd) map(f,tl)");
324              return(f(listhd(l)) + "#" + listmap(f,listtl(l)));
325            }
326 }
327
328 var statements = listnil();
329
330 var goalarray;
331 var metalist = listnil();
332
333 function pairmap (f,p)
334 {
335   debug("pairmap of '" + p + "'");
336   ar = p.split("|");
337   return (f(ar[0],ar[1])); 
338 }
339
340 function tripletmap (f,p)
341 {
342   debug("tripletmap of '" + p + "'");
343   ar = p.split("|");
344   return (f(ar[0],ar[1],ar[2])); 
345 }
346
347 function fst (p)
348 {
349   debug("fst");
350   return (pairmap (function (a,b) { return (a); }, p));
351 }
352
353 function p13 (p)
354 {
355   debug("p13");
356   return (tripletmap (function (a,b,c) { return (a); }, p));
357 }
358
359 function p23 (p)
360 {
361   debug("p23");
362   return (tripletmap (function (a,b,c) { return (b); }, p));
363 }
364
365 function p33 (p)
366 {
367   debug("f33");
368   return (tripletmap (function (a,b,c) { return (c); }, p));
369 }
370
371 function populate_goalarray(menv)
372 {
373   debug("metasenv.length = " + menv.length);
374   if (menv.length == 0) {
375       try {
376           hideSequent();
377       } catch (err) { };
378   } else {
379       showSequent();
380       goalarray = new Array();
381       metalist = listnil();
382       var tmp_goallist = "";
383       for (i = 0; i < menv.length; i++) {
384         metano = menv[i].getAttribute("number");
385         metaname = menv[i].childNodes[0].childNodes[0].data;
386         goal = menv[i].childNodes[1].childNodes[0].data;
387         debug ("found meta n. " + metano);
388         debug ("found goal\nBEGIN" + goal + "\nEND");
389         goalarray[metano] = goal;
390         tmp_goallist = " <A href=\"javascript:switch_goal(" + metano + ")\">" + metaname + "</A>" + tmp_goallist;
391         metalist = listcons(metano,metalist);
392         debug ("goalarray[\"" + metano + "\"] = " + goalarray[metano]); 
393       }
394       goals.innerHTML = tmp_goallist;
395       debug("new metalist is '" + metalist + "'");
396       if (is_nil(metalist)) {
397         switch_goal();
398       }
399       else {
400         switch_goal(listhd(metalist));
401       }
402   }
403 }
404
405 function switch_goal(meta)
406 {
407   if (typeof meta == "undefined") {
408     goalview.innerHTML = "";
409   }
410   else {
411     debug("switch_goal " + meta + "\n" + goalarray[meta]);
412     goalview.innerHTML = "<B>Goal ?" + meta + ":</B>\n\n" + goalarray[meta];
413   }
414 }
415
416 // the following is used to avoid escaping unicode, which results in 
417 // the server being unable to unescape the string
418 String.prototype.sescape = function() {
419         var patt1 = /%/gi;
420         var patt2 = /=/gi;
421         var patt3 = /&/gi;
422         var patt4 = /\+/gi;
423         var result = this;
424         result = result.replace(patt1,"%25");
425         result = result.replace(patt2,"%3D");
426         result = result.replace(patt3,"%26");
427         result = result.replace(patt4,"%2B");
428         return (result);
429 }
430
431 String.prototype.html_to_matita = function()
432 {
433         var patt1 = /<br(\/|)>/gi;
434         var patt2 = /</gi
435         var patt3 = />/gi
436         var patt4 = /&lt;/gi;
437         var patt5 = /&gt;/gi;
438         var patt6 = /&nbsp;/gi;
439         var result = this;
440         result = result.replace(patt1,"\n");
441         result = result.replace(patt2,"\005");
442         result = result.replace(patt3,"\006");
443         result = result.replace(patt4,"<");
444         result = result.replace(patt5,">");
445         result = result.replace(patt6," ");
446         return (unescape(result));
447 }
448
449 String.prototype.matita_to_html = function()
450 {
451         var patt1 = /</gi
452         var patt2 = />/gi
453         var patt3 = /\005/gi;
454         var patt4 = /\006/gi;
455         var result = this;
456         result = result.replace(patt1,"&lt;");
457         result = result.replace(patt2,"&gt;");
458         result = result.replace(patt3,"<");
459         result = result.replace(patt4,">");
460         return (unescape(result));
461 }
462
463 function pause()
464 {
465         advanceButton.disabled = true;
466         retractButton.disabled = true;
467         cursorButton.disabled = true;
468         bottomButton.disabled = true;
469 }
470
471 function resume()
472 {
473         advanceButton.disabled = false;
474         retractButton.disabled = false;
475         cursorButton.disabled = false;
476         bottomButton.disabled = false;
477 }
478
479 function is_defined(x)
480 {
481         return (typeof x != "undefined");
482 }
483
484 /* servicename: name of the service being called
485  * reqbody: text of the request
486  * processResponse: processes the server response
487  *     (takes the response text in input, undefined in case of error)
488  */
489 function callServer(servicename,processResponse,reqbody)
490 {
491         var req = null; 
492         // pause();
493         if (window.XMLHttpRequest)
494         {
495                 req = new XMLHttpRequest();
496         } 
497         else if (window.ActiveXObject) 
498         {
499                 try {
500                                 req = new ActiveXObject("Msxml2.XMLHTTP");
501                 } catch (e)
502                 {
503                         try {
504                                 req = new ActiveXObject("Microsoft.XMLHTTP");
505                                 } catch (e) {}
506                 }
507         }
508         req.onreadystatechange = function()
509         { 
510
511                 rs = req.readyState;
512
513                 if(rs == 4)
514                 {
515                         stat = req.status;
516                         stxt = req.statusText;
517                         if(stat == 200)
518                         {
519                           debug(req.responseText);
520                           if (window.DOMParser) {
521                             parser=new DOMParser();
522                             xmlDoc=parser.parseFromString(req.responseText,"text/xml");
523                           }
524                           else // Internet Explorer
525                           {
526                             xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
527                             xmlDoc.async="false";
528                             xmlDoc.loadXML(req.responseText);
529                           }     
530                           processResponse(xmlDoc);
531                         } else {
532                           processResponse();
533                         }
534                 } 
535         };
536         req.open("POST", servicename); // + escape(unlocked.innerHTML), true);
537         req.setRequestHeader("Content-type","application/x-www-form-urlencoded");       
538         if (reqbody) {
539                 req.send(reqbody); 
540         } else {
541                 req.send();
542         }
543   
544 }
545
546 function advanceForm1()
547 {
548         processor = function(xml) {
549                 if (is_defined(xml)) {
550                         var parsed = xml.getElementsByTagName("parsed")[0];
551                         var ambiguity = xml.getElementsByTagName("ambiguity")[0];
552                         if (is_defined(parsed)) {
553                         // debug("advance: received response\nBEGIN\n" + req.responseText + "\nEND");
554                             var len = parseInt(parsed.getAttribute("length"));
555                             // len0 = unlocked.innerHTML.length;
556                             var unescaped = unlocked.innerHTML.html_to_matita();
557                             var parsedtxt = parsed.childNodes[0].nodeValue;
558                             //parsedtxt = unescaped.substr(0,len); 
559                             var unparsedtxt = unescaped.substr(len);
560                             lockedbackup += parsedtxt;
561                             locked.innerHTML = lockedbackup;
562                             unlocked.innerHTML = unparsedtxt.matita_to_html();
563                             // len1 = unlocked.innerHTML.length;
564                             // len2 = len0 - len1;
565                             var len2 = parsedtxt.length;
566                             var metasenv = xml.getElementsByTagName("meta");
567                             populate_goalarray(metasenv);
568                             statements = listcons(len2,statements);
569                             unlocked.scrollIntoView(true);
570                         }
571                         else if (is_defined(ambiguity)) {
572                             var start = parseInt(ambiguity.getAttribute("start"));
573                             var stop = parseInt(ambiguity.getAttribute("stop"));
574                             var choices = xml.getElementsByTagName("choice");
575
576                             matita.ambiguityStart = start;
577                             matita.ambiguityStop = stop;
578                             matita.unlockedbackup = unlocked.innerHTML.html_to_matita();
579                             matita.interpretations = [];
580                         
581                             var unlockedtxt = unlocked.innerHTML.html_to_matita();
582                             var pre = unlockedtxt.substring(0,start).matita_to_html();
583                             var mid = unlockedtxt.substring(start,stop).matita_to_html();
584                             var post = unlockedtxt.substring(stop).matita_to_html();
585                             unlocked.innerHTML = pre + 
586                                     "<span class=\"error\" title=\"disambiguation error\">" +
587                                     mid + "</span>" + post;
588
589                             var title = "<H3>Ambiguous input</H3>";
590                             disambcell.innerHTML = title;
591                             for (i = 0;i < choices.length;i++) {
592                                 matita.interpretations[i] = new Object();
593
594                                 var href = choices[i].getAttribute("href");
595                                 var title = choices[i].getAttribute("title");
596                                 var desc = choices[i].childNodes[0].nodeValue;
597
598                                 matita.interpretations[i].href = href;
599                                 matita.interpretations[i].title = title;
600                                 matita.interpretations[i].desc = desc;
601                                 
602                                 var choice = document.createElement("input");
603                                 choice.setAttribute("type","radio");
604                                 choice.setAttribute("name","interpr");
605                                 choice.setAttribute("href",href);
606                                 choice.setAttribute("title",title);
607                                 if (i == 0) choice.setAttribute("checked","");
608                                 
609                                 disambcell.appendChild(choice);
610                                 disambcell.appendChild(document.createTextNode(desc));
611                                 disambcell.appendChild(document.createElement("br"));
612                             }
613
614                             var okbutton = document.createElement("input");
615                             okbutton.setAttribute("type","button");
616                             okbutton.setAttribute("value","OK");
617                             okbutton.setAttribute("onclick","do_disambiguate()");
618                             var cancelbutton = document.createElement("input");
619                             cancelbutton.setAttribute("type","button");
620                             cancelbutton.setAttribute("value","Cancel");
621                             cancelbutton.setAttribute("onclick","cancel_disambiguate()");
622
623                             disambcell.appendChild(okbutton);
624                             disambcell.appendChild(cancelbutton);
625
626                             matita.disambMode = true;
627                             updateSide();
628                         }
629                         else {
630                             var error = xml.getElementsByTagName("error")[0]; 
631                             unlocked.innerHTML = error.childNodes[0].nodeValue;
632                             // debug(xml.childNodes[0].nodeValue);
633                         }
634                 } else {
635                         debug("advance failed");
636                 }
637                 resume();
638         };
639         pause();
640         callServer("advance",processor,"body=" + (unlocked.innerHTML.html_to_matita()).sescape());
641   
642 }
643
644 function gotoBottom()
645 {
646         processor = function(xml) {
647                 if (is_defined(xml)) {
648                         // debug("goto bottom: received response\nBEGIN\n" + req.responseText + "\nEND");
649                         parsed = xml.getElementsByTagName("parsed")[0];
650                         len = parseInt(parsed.getAttribute("length"));
651                         if (len > 0) {
652                           // len0 = unlocked.innerHTML.length;
653                           unescaped = unlocked.innerHTML.html_to_matita();
654                           // not working in mozilla
655                           // parsedtxt = parsed.childNodes[0].nodeValue;
656                           parsedtxt = parsed.childNodes[0].wholeText;
657                           //parsedtxt = unescaped.substr(0,len); 
658                           unparsedtxt = unescaped.substr(len);
659                           lockedbackup += parsedtxt;
660                           locked.innerHTML = lockedbackup; //.matita_to_html();
661                           unlocked.innerHTML = unparsedtxt.matita_to_html();
662                           // len1 = unlocked.innerHTML.length;
663                           len2 = parsedtxt.length;
664                           metasenv = xml.getElementsByTagName("meta");
665                           populate_goalarray(metasenv);
666                           if (len2 > 0)
667                             statements = listcons(len2,statements);
668                           unlocked.scrollIntoView(true);
669                         }
670                 } else {
671                         debug("goto bottom failed");
672                 } 
673                 resume();
674         };
675         pause();
676         callServer("bottom",processor,"body=" + (unlocked.innerHTML.html_to_matita()).sescape());
677   
678 }
679
680
681 function gotoTop()
682 {
683         processor = function(xml) {
684                 if (is_defined(xml)) {
685                   if (xml.childNodes[0].textContent != "ok") {
686                      debug("goto top failed");
687                   }
688                   else
689                         statements = listnil();
690                         /*
691                         lockedlen = locked.innerHTML.length - statementlen;
692                         statement = locked.innerHTML.substr(lockedlen, statementlen);
693                         locked.innerHTML = locked.innerHTML.substr(0,lockedlen);
694                         unlocked.innerHTML = statement + unlocked.innerHTML;
695                         */
696                         unlocked.innerHTML = lockedbackup + unlocked.innerHTML;
697                         lockedbackup = "";
698                         locked.innerHTML = lockedbackup;
699                         hideSequent();
700                         unlocked.scrollIntoView(true);
701                 } else {
702                         debug("goto top failed");
703                 } 
704                 resume();
705         };
706         pause();
707         callServer("top",processor,"body=" + (unlocked.innerHTML.html_to_matita()).sescape());
708   
709 }
710 function gotoPos(offset)
711 {
712         if (!is_defined(offset)) {
713                 offset = getCursorPos();
714         }
715         processor = function(xml) {
716                 if (is_defined(xml)) {
717                         parsed = xml.getElementsByTagName("parsed")[0];
718                         len = parseInt(parsed.getAttribute("length"));
719                         // len0 = unlocked.innerHTML.length;
720                         unescaped = unlocked.innerHTML.html_to_matita();
721                         parsedtxt = parsed.childNodes[0].nodeValue;
722                         //parsedtxt = unescaped.substr(0,len); 
723                         unparsedtxt = unescaped.substr(len);
724                         lockedbackup += parsedtxt;
725                         locked.innerHTML = lockedbackup; //.matita_to_html();
726                         unlocked.innerHTML = unparsedtxt.matita_to_html();
727                         // len1 = unlocked.innerHTML.length;
728                         len2 = parsedtxt.length;
729                         metasenv = xml.getElementsByTagName("meta");
730                         // populate_goalarray(metasenv);
731                         statements = listcons(len2,statements);
732                         unlocked.scrollIntoView(true);
733                         // la populate non andrebbe fatta a ogni passo
734                         if (offset <= len) {
735                                 populate_goalarray(metasenv);
736                                 resume();
737                         } else {
738                                 gotoPos(offset - len);
739                         }
740                 } else {
741                         unlocked.scrollIntoView(true);
742                         populate_goalarray(metasenv);
743                         resume();
744                 }
745         }
746         pause();
747         callServer("advance",processor,"body=" + (unlocked.innerHTML.html_to_matita()).sescape());
748 }
749
750 function retract()
751 {
752         processor = function(xml) {
753                 if (typeof xml != "undefined") {
754                         // debug("advance: received response\nBEGIN\n" + req.responseText + "\nEND");
755                         statementlen = parseInt(listhd(statements));
756                         statements = listtl(statements);
757                         /*
758                         lockedlen = locked.innerHTML.length - statementlen;
759                         statement = locked.innerHTML.substr(lockedlen, statementlen);
760                         locked.innerHTML = locked.innerHTML.substr(0,lockedlen);
761                         unlocked.innerHTML = statement + unlocked.innerHTML;
762                         */
763                         lockedlen = lockedbackup.length - statementlen;
764                         statement = lockedbackup.substr(lockedlen, statementlen);
765                         lockedbackup = lockedbackup.substr(0,lockedlen);
766                         locked.innerHTML = lockedbackup;
767                         unlocked.innerHTML = statement + unlocked.innerHTML;
768                         metasenv = xml.getElementsByTagName("meta");
769                         populate_goalarray(metasenv);
770                         unlocked.scrollIntoView(true);
771                 } else {
772                         debug("retract failed");
773                 }
774                 resume();
775         };
776         debug("retract 1");
777         pause();
778         callServer("retract",processor);
779         debug("retract 2");
780 }
781
782 function openFile()
783
784         processor = function(xml)
785         {
786                 if (is_defined(xml)) {  
787                         lockedbackup = "";
788                         locked.innerHTML = lockedbackup;
789                         unlocked.innerHTML = xml.documentElement.wholeText;
790                 } else {
791                         debug("file open failed");
792                 }
793         };
794         callServer("open",processor,"file=" + escape(filename.value)); 
795 }
796
797 function retrieveFile(thefile)
798
799         processor = function(xml)
800         {
801                 if (is_defined(xml)) {  
802                         changeFile(thefile);
803                         lockedbackup = ""
804                         locked.innerHTML = lockedbackup;
805                         // code originally used in google chrome (problems with mozilla)
806                         // debug(xml.getElementsByTagName("file")[0].childNodes[0].nodeValue);
807                         // unlocked.innerHTML = xml.getElementsByTagName("file")[0].childNodes[0].nodeValue;
808                         debug(xml.childNodes[0].textContent);
809                         if (document.all) { // IE
810                           unlocked.innerHTML = xml.childNodes[0].text;
811                         } else {
812                           unlocked.innerHTML = xml.childNodes[0].textContent;
813                         }
814
815                 } else {
816                         debug("file open failed");
817                 }
818         };
819         dialogBox.style.display = "none";
820         callServer("open",processor,"file=" + escape(thefile)); 
821 }
822
823 function showLibrary(title,callback,reloadDialog)
824
825         var req = null;
826         dialogBox.reload = reloadDialog; 
827         // pause();
828         if (window.XMLHttpRequest)
829         {
830                 req = new XMLHttpRequest();
831         } 
832         else if (window.ActiveXObject) 
833         {
834                 try {
835                                 req = new ActiveXObject("Msxml2.XMLHTTP");
836                 } catch (e)
837                 {
838                         try {
839                                 req = new ActiveXObject("Microsoft.XMLHTTP");
840                                 } catch (e) {}
841                 }
842         }
843         req.onreadystatechange = function()
844         { 
845
846                 rs = req.readyState;
847
848                 if(rs == 4)
849                 {
850                         stat = req.status;
851                         stxt = req.statusText;
852                         if(stat == 200)
853                         {
854                           debug(req.responseText);
855                           showDialog("<H2>" + title + "</H2>",req.responseText, callback);
856                         } 
857                 } 
858         };
859         req.open("POST", "viewlib"); // + escape(unlocked.innerHTML), true);
860         req.setRequestHeader("Content-type","application/x-www-form-urlencoded");       
861         req.send();
862   
863 }
864
865 function uploadDialog()
866 {  
867         uploadBox.style.display = "block";
868 }
869
870 function uploadOK()
871 {   
872    var file = document.getElementById("uploadFilename").files[0];
873    if (file) { 
874        var filecontent = file.getAsText("UTF-8");
875        locked.innerHTML = lockedbackup;
876        unlocked.innerHTML = filecontent;
877        uploadBox.style.display = "none";
878    }
879 //   if (file) { 
880 //      var reader = new FileReader();
881 //      reader.readAsText(file, "UTF-8");
882 //       reader.onloadend = function (evt) {
883 //         lockedbackup = "";
884 //           locked.innerHTML = lockedbackup
885 //           unlocked.innerHTML = evt.target.result;
886 //           uploadBox.style.display = "none";
887 //       }
888 //       reader.onerror = function (evt) {
889 //         debug("file open failed");
890 //           uploadBox.style.display = "none";
891 //      }
892 //   }
893 }
894
895 function openDialog()
896 {  
897         callback = function (fname) { retrieveFile(fname); };
898         showLibrary("Open file", callback, openDialog);
899 }
900
901 function saveDialog()
902 {  
903         callback = function (fname) { 
904           dialogBox.style.display = "none";
905           saveFile(fname,
906                    (locked.innerHTML.html_to_matita()).sescape(),
907                    (unlocked.innerHTML.html_to_matita()).sescape(),
908                    false,saveDialog); 
909         };
910         showLibrary("Save file as", callback, saveDialog);
911 }
912
913 function newDialog()
914 {
915         callback = function (fname) { 
916           dialogBox.style.display = "none";
917           saveFile(fname,"","",false,newDialog,true);
918         };
919         showLibrary("Create new file", callback, newDialog);
920 }
921
922
923 function saveFile(fname,lockedtxt,unlockedtxt,force,reloadDialog,reloadFile)
924 {
925         if (!is_defined(reloadFile)) { reloadFile = true };
926         if (!is_defined(fname)) {
927             fname = current_fname;
928             lockedtxt = (locked.innerHTML.html_to_matita()).sescape();
929             unlockedtxt = (unlocked.innerHTML.html_to_matita()).sescape();
930             force = true;
931             // when force is true, reloadDialog is not needed 
932         }
933         processor = function(xml) {
934                 if (is_defined(xml)) {
935                   if (xml.childNodes[0].textContent != "ok") {
936                     if (confirm("File already exists. All existing data will be lost.\nDo you want to proceed anyway?")) {
937                        saveFile(fname,lockedtxt,unlockedtxt,true,reloadDialog,reloadFile);
938                     } else {
939                       reloadDialog();
940                     }
941                   } else {
942                     changeFile(fname);
943                     debug("file saved!");
944                     if (reloadFile) { retrieveFile(fname); }
945                   }
946                 } else {
947                         debug("save file failed");
948                 }
949                 resume();
950         };
951         if (is_defined(fname)) {
952           pause();
953           callServer("save",processor,"file=" + escape(fname) + 
954                                     "&locked=" + lockedtxt +
955                                     "&unlocked=" + unlockedtxt +
956                                     "&force=" + force);
957         }
958         else { debug("no file selected"); }
959 }
960
961 function createDir() {
962    abortDialog();
963    dirname = prompt("New directory name:\ncic:/matita/","newdir");
964    if (dirname != null) {
965         processor = function(xml) {
966                 if (is_defined(xml)) {
967                   if (xml.childNodes[0].textContent != "ok") {
968                       alert("An error occurred :-(");
969                   }
970                 } else {
971                       alert("An error occurred :-(");
972                 }
973                 dialogBox.reload();
974         };
975         pause();
976         callServer("save",processor,"file=" + escape(dirname) + 
977                                     "&locked=&unlocked=&force=false&dir=true");
978    } else {
979       dialogBox.reload();
980    }
981 }
982
983 function commitAll()
984 {
985         processor = function(xml) {
986                 if (is_defined(xml)) {
987                         debug(xml.getElementsByTagName("details")[0].textContent);
988                         alert("Commit executed: see details in the log.\n\n" +
989                               "NOTICE: this message does NOT imply (yet) that the commit was successful.");
990                 } else {
991                         alert("Commit failed!");
992                 }
993                 resume();
994         };
995         pause();
996         callServer("commit",processor);
997 }
998
999 function updateAll()
1000 {
1001         processor = function(xml) {
1002                 if (is_defined(xml)) {
1003                         alert("Update executed.\n\n" +
1004                               "Details:\n" +
1005                               xml.getElementsByTagName("details")[0].textContent);
1006                 } else {
1007                         alert("Update failed!");
1008                 }
1009                 resume();
1010         };
1011         pause();
1012         callServer("update",processor);
1013 }
1014
1015 var goalcell;
1016
1017 function hideSequent() {
1018         matita.proofMode = false;
1019         updateSide();
1020 }
1021
1022 function showSequent() {
1023         matita.proofMode = true;
1024         updateSide();
1025 }
1026
1027 function showDialog(title,content,callback) {
1028   dialogTitle.innerHTML = title;
1029   dialogContent.innerHTML = content;
1030   dialogBox.callback = callback;
1031   dialogBox.style.display = "block";
1032 }
1033
1034 function showDisamb(content) {
1035   disambContent.innerHTML = content;
1036   disambBox.style.display = "block";
1037 }
1038
1039 function abortDialog(dialog) {
1040   dialogBox.style.display = "none";
1041 }
1042
1043 function removeElement(id) {
1044   var element = document.getElementById(id);
1045   element.parentNode.removeChild(element);
1046
1047
1048 var savedsc;
1049 var savedso;
1050
1051 function getCursorPos() {
1052   var cursorPos;
1053   if (window.getSelection) {
1054     var selObj = window.getSelection();
1055     savedRange = selObj.getRangeAt(0);
1056     savedsc = savedRange.startContainer;
1057     savedso = savedRange.startOffset;
1058     //cursorPos =  findNode(selObj.anchorNode.parentNode.childNodes, selObj.anchorNode) + selObj.anchorOffset;
1059     cursorPos =  findNode(unlocked.childNodes, selObj.anchorNode,0) + selObj.anchorOffset;
1060     /* FIXME the following works wrong in Opera when the document is longer than 32767 chars */
1061     return(cursorPos);
1062   }
1063   else if (document.selection) {
1064     savedRange = document.selection.createRange();
1065     var bookmark = savedRange.getBookmark();
1066     /* FIXME the following works wrong when the document is longer than 65535 chars */
1067     cursorPos = bookmark.charCodeAt(2) - 11; /* Undocumented function [3] */
1068     return(cursorPos);
1069   }
1070 }
1071
1072 function findNode(list, node, acc) {
1073   for (var i = 0; i < list.length; i++) {
1074     if (list[i] == node) {
1075    //   debug("success " + i);
1076       return acc;
1077     }
1078     if (list[i].hasChildNodes()) {
1079        try {
1080    //      debug("recursion on node " + i);
1081          return (findNode(list[i].childNodes,node,acc))
1082        }
1083        catch (e) { /* debug("recursion failed"); */ }
1084     }
1085     sandbox = document.getElementById("sandbox");
1086     dup = list[i].cloneNode(true);
1087     sandbox.appendChild(dup);
1088 //    debug("fail " + i + ": " + sandbox.innerHTML);
1089     acc += sandbox.innerHTML.length;
1090     sandbox.removeChild(dup);
1091   }
1092   throw "not found";
1093 }
1094
1095 function test () {
1096   debug("cursor test: " + unlocked.innerHTML.substr(0,getCursorPos()));
1097 }
1098
1099 function get_checked_index(name) {
1100         var radios = document.getElementsByName(name);
1101         for (i = 0; i < radios.length; i++) {
1102             if (radios[i].checked) {
1103                     return i;
1104             }
1105         }
1106         return null;
1107 }
1108
1109 function cancel_disambiguate() {
1110         matita.disambMode = false;
1111         updateSide();
1112 }
1113
1114 function do_disambiguate() {
1115         var i = get_checked_index("interpr");
1116         if (i != null) {
1117             var pre = matita.unlockedbackup
1118                       .substring(0,matita.ambiguityStart).matita_to_html();
1119             var mid = matita.unlockedbackup
1120                       .substring(matita.ambiguityStart,matita.ambiguityStop)
1121                       .matita_to_html();
1122             var post = matita.unlockedbackup
1123                        .substring(matita.ambiguityStop).matita_to_html();
1124
1125             var href = matita.interpretations[i].href;
1126             var title = matita.interpretations[i].title;
1127
1128             if (is_defined(title)) {
1129                 mid = "<A href=\"" + href + "\" title=\"" + title + "\">" + mid + "</A>";
1130             } else {
1131                 mid = "<A href=\"" + href + "\">" + mid + "</A>";
1132             }
1133
1134             unlocked.innerHTML = pre + mid + post;
1135
1136             matita.disambMode = false;
1137             updateSide();
1138         }
1139 }
1140
1141 function readCookie(name) {
1142         var nameEQ = name + "=";
1143         var ca = document.cookie.split(';');
1144         for(var i=0;i < ca.length;i++) {
1145                 var c = ca[i];
1146                 while (c.charAt(0)==' ') c = c.substring(1,c.length);
1147                 if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
1148         }
1149         return null;
1150 }
1151
1152 function delete_cookie ( cookie_name )
1153 {
1154   var cookie_date = new Date();  // current date & time
1155   cookie_date.setTime ( cookie_date.getTime() - 1 );
1156   document.cookie = cookie_name += "=; expires=" + cookie_date.toGMTString();
1157 }
1158
1159 function delete_session()
1160 {
1161         delete_cookie("session");
1162 }