1 	JXG.GeogebraReader = new function() {
  2 /**
  3  * @param {String} type the type of expression
  4  * @param {String} m first input value
  5  * @param {String} n second input value
  6  * @return {String} return the object, string or calculated value
  7  */
  8 this.ggbAct = function(type, m, n) {
  9   var v1 = m, v2 = n, s1, s2, a;
 10   switch(type.toLowerCase()) {
 11     case 'end':
 12       // JXG.debug("<b>end: </b>"+ v1);
 13       return v1;
 14     break;
 15     case 'coord':
 16       s1 = (JXG.GeogebraReader.board.ggbElements[v1]) ? 'JXG.getReference(JXG.GeogebraReader.board, "'+ v1 +'")' : v1;
 17       s2 = (JXG.GeogebraReader.board.ggbElements[v2]) ? 'JXG.getReference(JXG.GeogebraReader.board, "'+ v2 +'")' : v2;
 18       return [s1, s2];
 19     break;
 20     case 'le': // smaller then
 21       return '( ('+ v1 +') <= ('+ v2 +') )';
 22     break;
 23     case 'ge': // greater then
 24       return '( ('+ v1 +') >= ('+ v2 +') )';
 25     break;
 26     case 'eq': // equal
 27       return '( ('+ v1 +') == ('+ v2 +') )';
 28     break;
 29     case 'neq': // not equal
 30       return '( ('+ v1 +') != ('+ v2 +') )';
 31     break;
 32     case 'lt': // smaller
 33       return '( ('+ v1 +') < ('+ v2 +') )';
 34     break;
 35     case 'gt': // greater
 36       return '( ('+ v1 +') > ('+ v2 +') )';
 37     break;
 38     case 'add':
 39     	if (JXG.GeogebraReader.isGGBVector(v1) && JXG.GeogebraReader.isGGBVector(v2)){ //Add: Vector + Vector
 40     		return [1, v1[1] + '+' + v2[1], v1[2] + '+' + v2[2]];
 41     	}
 42       if( JXG.isString(v1) && !v1.match(/JXG\.getReference\(JXG\.GeogebraReader\.board, "(.+?)"\)\./) && v1.match(/JXG\.getReference/) ) {
 43         s1 = [v1+'.X()', v1+'.Y()'];
 44       } else {
 45         s1 = v1;
 46       }
 47 
 48       if( JXG.isString(v2) && !v2.match(/JXG\.getReference\(JXG\.GeogebraReader\.board, "(.+?)"\)\./) && v2.match(/JXG\.getReference/) ) {
 49         s2 = [v2+'.X()', v2+'.Y()'];
 50       } else {
 51         s2 = v2;
 52       }
 53 
 54       if (JXG.GeogebraReader.isGGBVector(s1) && JXG.isArray(s2)){ //Add: Vector + Point
 55     	  return [s1[1] + '+' + s2[0], s1[2] + '+' + s2[1]];
 56   		}
 57 
 58       if (JXG.GeogebraReader.isGGBVector(s2) && JXG.isArray(s1)){ //Add: Vector + Point
 59     	  return [s2[1] + '+' + s1[0], s2[2] + '+' + s1[1]];
 60   		}
 61 
 62       if( JXG.isArray(s1) && JXG.isArray(s2) ) {
 63         return [ s1[0] +' + '+ s2[0], s1[1] +' + '+ s2[1] ];
 64       }
 65       else if( (JXG.isNumber(s1) || JXG.isString(s1)) && (JXG.isNumber(s2) || JXG.isString(s2)) ) {
 66         return s1 +' + '+ s2;
 67       }
 68       else if( (JXG.isNumber(s1) || JXG.isString(s1)) && JXG.isArray(s2) ) {
 69         return [ s1 +' + '+ s2[0], s1 +' + '+ s2[1] ];
 70       }
 71       else if( JXG.isArray(s1) && (JXG.isNumber(s2) || JXG.isString(s2)) ) {
 72         return [ s1[0] +' + '+ s2, s1[1] +' + '+ s2 ];
 73       }
 74       else {
 75         return s1 +' + '+ s2;
 76       }
 77     break;
 78     case 'sub':
 79     	if (JXG.GeogebraReader.isGGBVector(v1) && JXG.GeogebraReader.isGGBVector(v2)){ //Sub: Vector - Vector
 80     		return [1, v1[1] + '-' + v2[1], v1[2] + '-' + v2[2]];
 81     	}
 82 
 83       if( JXG.isString(v1) && !v1.match(/JXG\.getReference\(JXG\.GeogebraReader\.board, "(.+?)"\)\./) && v1.match(/JXG\.getReference/) ) {
 84         s1 = [v1+'.X()', v1+'.Y()'];
 85       } else {
 86         s1 = v1;
 87       }
 88 
 89       if( JXG.isString(v2) && !v2.match(/JXG\.getReference\(JXG\.GeogebraReader\.board, "(.+?)"\)\./) && v2.match(/JXG\.getReference/) ) {
 90         s2 = [v2+'.X()', v2+'.Y()'];
 91       } else {
 92         s2 = v2;
 93       }
 94 
 95       if (JXG.GeogebraReader.isGGBVector(s1) && JXG.isArray(s2)){ //Add: Vector - Point
 96     	  return [s1[1] + '-' + s2[0], s1[2] + '-' + s2[1]];
 97   		}
 98 
 99       if (JXG.isArray(s1) && JXG.GeogebraReader.isGGBVector(s2)){ //Add: Punkt - Vector
100     	  return [s1[0] + '-(' + s2[1] + ')', s1[1] + '-(' + s2[2] +')'];
101   		}
102 
103       if( JXG.isArray(s1) && JXG.isArray(s2) ) {
104         return [ s1[0] +' - '+ s2[0], s1[1] +' - '+ s2[1] ];
105       }
106       else if( (JXG.isNumber(s1) || JXG.isString(s1)) && (JXG.isNumber(s2) || JXG.isString(s2)) ) {
107         return s1 +' - '+ s2;
108       }
109       else if( (JXG.isNumber(s1) || JXG.isString(s1)) && JXG.isArray(s2) ) {
110         return [ s1 +' - '+ s2[0], s1 +' - '+ s2[1] ];
111       }
112       else if( JXG.isArray(s1) && (JXG.isNumber(s2) || JXG.isString(s2)) ) {
113         return [ s1[0] +' - '+ s2, s1[1] +' - '+ s2 ];
114       }
115       else {
116         return s1 +' - '+ s2;
117       }
118     break;
119     case 'neg':
120       return '!('+ v1 +')';
121     break;
122     case 'pow':
123       return 'Math.pow('+ v1 +', '+ v2 +')';
124     break;
125     case 'or':
126       return '('+ v1 +'||'+ v2 +')';
127     break;
128     case 'and':
129       return '('+ v1 +'&&'+ v2 +')';
130     break;
131     case 'mul':
132     	if (JXG.GeogebraReader.isGGBVector(v1) && !JXG.isArray(v2)){ // Mult: Vector * Skalar
133     		return [1,'(' + v1[1] + ')*'+v2,'(' + v1[2] + ')*'+v2];
134     	} else if (!JXG.isArray(v1) && JXG.GeogebraReader.isGGBVector(v2)){ // Mult: Skalar * Vector
135     		return new Array(1,'(' + v2[1] + ')*'+v1,'(' + v2[2] + ')*'+v1);
136     	} else if (JXG.GeogebraReader.isGGBVector(v1) && JXG.GeogebraReader.isGGBVector(v2)){ //Mult: Vector * Vector
137     		return '((' + v1[1] + ')*('+v2[1]+')+('+ v1[2] + ')*('+v2[2]+'))';
138     	} else { // Rest
139       if( JXG.isString(v1) && !v1.match(/JXG\.getReference\(JXG\.GeogebraReader\.board, "(.+?)"\)\./) && v1.match(/JXG\.getReference/) ) {
140 		        s1 = [v1+'.X()', v1+'.Y()'];
141 		      } else {
142 		    	s1 = v1;
143 		      }
144 
145       		if( JXG.isString(v2) && !v2.match(/JXG\.getReference\(JXG\.GeogebraReader\.board, "(.+?)"\)\./) && v2.match(/JXG\.getReference/) ) {
146 		        s2 = [v2+'.X()', v2+'.Y()'];
147 		      } else {
148 		        s2 = v2;
149 		      }
150 
151 		      if( JXG.isArray(s1) && JXG.isArray(s2) ) {
152 		        return [ s1[0] +' * '+ s2[0], s1[1] +' * '+ s2[1] ];
153 		      }
154 		      else if( (JXG.isNumber(s1) || JXG.isString(s1)) && (JXG.isNumber(s2) || JXG.isString(s2)) ) {
155 		        return s1 +' * '+ s2;
156 		      }
157 		      else if( (JXG.isNumber(s1) || JXG.isString(s1)) && JXG.isArray(s2) ) {
158 		        return [ s1 +' * '+ s2[0], s1 +' * '+ s2[1] ];
159 		      }
160 		      else if( JXG.isArray(s1) && (JXG.isNumber(s2) || JXG.isString(s2)) ) {
161 		        return [ s1[0] +' * '+ s2, s1[1] +' * '+ s2 ];
162 		      }
163 		      else {
164 		        return s1 +' * '+ s2;
165 		      }
166     	}
167     break;
168     case 'div':
169       if( JXG.isString(v1) && !v1.match(/JXG\.getReference\(JXG\.GeogebraReader\.board, "(.+?)"\)\./) && v1.match(/JXG\.getReference/) ) {
170         s1 = [v1+'.X()', v1+'.Y()'];
171       } else {
172         s1 = v1;
173       }
174 
175       if( JXG.isString(v2) && !v2.match(/JXG\.getReference\(JXG\.GeogebraReader\.board, "(.+?)"\)\./) && v2.match(/JXG\.getReference/) ) {
176         s2 = [v2+'.X()', v2+'.Y()'];
177       } else {
178         s2 = v2;
179       }
180 
181       if( JXG.isArray(s1) && JXG.isArray(s2) ) {
182         return [ s1[0] +' / '+ s2[0], s1[1] +' / '+ s2[1] ];
183       }
184       else if( (JXG.isNumber(s1) || JXG.isString(s1)) && (JXG.isNumber(s2) || JXG.isString(s2)) ) {
185         return s1 +' / '+ s2;
186       }
187       else if( (JXG.isNumber(s1) || JXG.isString(s1)) && JXG.isArray(s2) ) {
188         return [ s1 +' / '+ s2[0], s1 +' / '+ s2[1] ];
189       }
190       else if( JXG.isArray(s1) && (JXG.isNumber(s2) || JXG.isString(s2)) ) {
191         return [ s1[0] +' / '+ s2, s1[1] +' / '+ s2 ];
192       }
193       else {
194         return s1 +' / '+ s2;
195       }
196     break;
197     case 'negmult':
198     	if (JXG.GeogebraReader.isGGBVector(v1))
199     		return new Array(1, -1 + '*' + v1[1],-1 + '*' + v1[2]);
200       return -1 +'*'+ v1;
201     break;
202     case 'bra':
203     	if (JXG.GeogebraReader.isGGBVector(v1))
204     		return new Array(1,'(' + v1[1] + ')','(' + v1[2] + ')');
205       return '('+ v1 +')';
206     break;
207     case 'int':
208       return parseInt(v1);
209     break;
210     case 'float':
211       return parseFloat(v1);
212     break;
213     case 'param':
214       return v1;
215     break;
216     case 'html':
217       return v1;
218     break;
219     case 'string':
220       if(v2) return [v1, v2];
221       else   return v1;
222     break;
223     case 'command':
224       v2 = v1.split('[');
225       s1 = v2[0];
226       s2 = (v2[1].split(']'))[0];
227       switch(s1.toLowerCase()) {
228         case 'name':
229           return 'JXG.getReference(JXG.GeogebraReader.board, "'+ s2 +'").getName()'; //TODO korrigiere getName()
230         break;
231       }
232     break;
233     case 'var':
234       if(v2) {
235         switch(v1.toLowerCase()) {
236             case 'x':
237                 return v2 +'.X()';
238             break;
239             case 'y':
240                 return v2 +'.Y()';
241             break;
242             case 'abs':
243 			case 'acos':
244 			case 'asin':
245 			case 'atan':
246 			case 'ceil':
247 			case 'cos':
248 			case 'exp':
249 			case 'floor':
250 			case 'log':
251 			case 'max':
252 			case 'min':
253 			case 'pow':
254 			case 'random':
255 			case 'round':
256 			case 'sin':
257 			case 'sqrt':
258 			case 'tan':
259               return 'Math.'+v1.toLowerCase()+'('+ v2 +')';
260             break;
261             default:
262                 return v1.toLowerCase()+'*('+ v2 +')';
263             break;
264         }
265       } else {
266 
267         if(v1 == 'PI') {
268           return 'Math.PI';
269         } else {
270           a = JXG.GeogebraReader.checkElement(v1);
271           if(typeof JXG.GeogebraReader.board.ggb[v1] != 'undefined') {
272             return 'JXG.GeogebraReader.board.ggb["'+ v1 +'"]()';
273           } else if(typeof a.Value != 'undefined') {
274             return 'JXG.getReference(JXG.GeogebraReader.board, "'+ v1 +'").Value()';
275           } else if(typeof a.Area != 'undefined') {
276             return 'JXG.getReference(JXG.GeogebraReader.board, "'+ v1 +'").Area()';
277           } else if(typeof a.plaintextStr != 'undefined') {
278             return '1.0*JXG.getReference(JXG.GeogebraReader.board, "'+ v1 +'").plaintextStr';
279           } else if (a.type == JXG.OBJECT_TYPE_VECTOR){
280             return new Array(1, 'JXG.getReference(JXG.GeogebraReader.board, "'+ v1 +'").point2.X()-JXG.getReference(JXG.GeogebraReader.board, "'+ v1 +'").point1.X()','JXG.getReference(JXG.GeogebraReader.board, "'+ v1 +'").point2.Y()-JXG.getReference(JXG.GeogebraReader.board, "'+ v1 +'").point1.Y()');
281           }else if(a.elementClass == JXG.OBJECT_CLASS_LINE) {
282             return 'JXG.getReference(JXG.GeogebraReader.board, "'+ v1 +'").point1.Dist(JXG.getReference(JXG.GeogebraReader.board, "'+ v1 +'").point2)';
283           } else {
284             return 'JXG.getReference(JXG.GeogebraReader.board, "'+ v1 +'")';
285           }
286         }
287       }
288     break;
289   }
290 };
291 
292 /**
293  * JS/CC parser to convert the input expression to a working javascript function.
294  * @param {Object} board object
295  * @param {Object} element Element that needs to be updated
296  * @param {String} exp String which contains the function, expression or information
297  */
298 this.ggbParse = function(exp, element) {
299   var element = (element) ? JXG.getReference(JXG.GeogebraReader.board, JXG.GeogebraReader.board.ggbElements[element].id) : false;
300   if(element) JXG.debug("Zu aktualisierendes Element: "+ element.name + "("+ element.id +")");
301 
302 /*
303     This parser was generated with: The LALR(1) parser and lexical analyzer generator for JavaScript, written in JavaScript
304     In the version 0.30 on http://jscc.jmksf.com/
305 
306     It is based on the default template driver for JS/CC generated parsers running as
307     browser-based JavaScript/ECMAScript applications and was strongly modified.
308 
309     The parser was written 2007, 2008 by Jan Max Meyer, J.M.K S.F. Software Technologies
310     This is in the public domain.
311 */
312 
313 /***** begin replace *****/
314 	var _dbg_withtrace		= false;
315 	var _dbg_string			= new String();
316 
317 	function __dbg_print( text ) {
318 		_dbg_string += text + "\n";
319 	}
320 
321 	function __lex( info ) {
322 		var state		= 0;
323 		var match		= -1;
324 		var match_pos	= 0;
325 		var start		= 0;
326 		var pos			= info.offset + 1;
327 
328 		do
329 		{
330 			pos--;
331 			state = 0;
332 			match = -2;
333 			start = pos;
334 
335 			if( info.src.length <= start )
336 				return 28;
337 
338 			do
339 			{
340 
341 	switch( state )
342 	{
343 		case 0:
344 			if( info.src.charCodeAt( pos ) == 9 || info.src.charCodeAt( pos ) == 32 ) state = 1;
345 			else if( info.src.charCodeAt( pos ) == 33 ) state = 2;
346 			else if( info.src.charCodeAt( pos ) == 40 ) state = 3;
347 			else if( info.src.charCodeAt( pos ) == 41 ) state = 4;
348 			else if( info.src.charCodeAt( pos ) == 42 ) state = 5;
349 			else if( info.src.charCodeAt( pos ) == 43 ) state = 6;
350 			else if( info.src.charCodeAt( pos ) == 44 ) state = 7;
351 			else if( info.src.charCodeAt( pos ) == 45 ) state = 8;
352 			else if( info.src.charCodeAt( pos ) == 47 ) state = 9;
353 			else if( ( info.src.charCodeAt( pos ) >= 48 && info.src.charCodeAt( pos ) <= 57 ) ) state = 10;
354 			else if( info.src.charCodeAt( pos ) == 60 ) state = 11;
355 			else if( info.src.charCodeAt( pos ) == 62 ) state = 12;
356 			else if( ( info.src.charCodeAt( pos ) >= 65 && info.src.charCodeAt( pos ) <= 90 ) || ( info.src.charCodeAt( pos ) >= 97 && info.src.charCodeAt( pos ) <= 122 ) ) state = 13;
357 			else if( info.src.charCodeAt( pos ) == 94 ) state = 14;
358 			else if( info.src.charCodeAt( pos ) == 34 ) state = 26;
359 			else if( info.src.charCodeAt( pos ) == 38 ) state = 28;
360 			else if( info.src.charCodeAt( pos ) == 46 ) state = 29;
361 			else if( info.src.charCodeAt( pos ) == 61 ) state = 30;
362 			else if( info.src.charCodeAt( pos ) == 95 ) state = 31;
363 			else if( info.src.charCodeAt( pos ) == 124 ) state = 32;
364 			else state = -1;
365 			break;
366 
367 		case 1:
368 			state = -1;
369 			match = 1;
370 			match_pos = pos;
371 			break;
372 
373 		case 2:
374 			if( info.src.charCodeAt( pos ) == 61 ) state = 15;
375 			else state = -1;
376 			match = 23;
377 			match_pos = pos;
378 			break;
379 
380 		case 3:
381 			state = -1;
382 			match = 2;
383 			match_pos = pos;
384 			break;
385 
386 		case 4:
387 			state = -1;
388 			match = 3;
389 			match_pos = pos;
390 			break;
391 
392 		case 5:
393 			state = -1;
394 			match = 13;
395 			match_pos = pos;
396 			break;
397 
398 		case 6:
399 			state = -1;
400 			match = 11;
401 			match_pos = pos;
402 			break;
403 
404 		case 7:
405 			state = -1;
406 			match = 16;
407 			match_pos = pos;
408 			break;
409 
410 		case 8:
411 			state = -1;
412 			match = 12;
413 			match_pos = pos;
414 			break;
415 
416 		case 9:
417 			state = -1;
418 			match = 14;
419 			match_pos = pos;
420 			break;
421 
422 		case 10:
423 			if( ( info.src.charCodeAt( pos ) >= 48 && info.src.charCodeAt( pos ) <= 57 ) ) state = 10;
424 			else if( info.src.charCodeAt( pos ) == 46 ) state = 18;
425 			else state = -1;
426 			match = 4;
427 			match_pos = pos;
428 			break;
429 
430 		case 11:
431 			if( info.src.charCodeAt( pos ) == 61 ) state = 19;
432 			else state = -1;
433 			match = 21;
434 			match_pos = pos;
435 			break;
436 
437 		case 12:
438 			if( info.src.charCodeAt( pos ) == 61 ) state = 21;
439 			else state = -1;
440 			match = 22;
441 			match_pos = pos;
442 			break;
443 
444 		case 13:
445 			if( ( info.src.charCodeAt( pos ) >= 65 && info.src.charCodeAt( pos ) <= 90 ) || ( info.src.charCodeAt( pos ) >= 97 && info.src.charCodeAt( pos ) <= 122 ) ) state = 13;
446 			else if( ( info.src.charCodeAt( pos ) >= 48 && info.src.charCodeAt( pos ) <= 57 ) ) state = 27;
447 			else if( info.src.charCodeAt( pos ) == 91 ) state = 34;
448 			else if( info.src.charCodeAt( pos ) == 95 ) state = 35;
449 			else state = -1;
450 			match = 7;
451 			match_pos = pos;
452 			break;
453 
454 		case 14:
455 			state = -1;
456 			match = 15;
457 			match_pos = pos;
458 			break;
459 
460 		case 15:
461 			state = -1;
462 			match = 20;
463 			match_pos = pos;
464 			break;
465 
466 		case 16:
467 			state = -1;
468 			match = 9;
469 			match_pos = pos;
470 			break;
471 
472 		case 17:
473 			state = -1;
474 			match = 25;
475 			match_pos = pos;
476 			break;
477 
478 		case 18:
479 			if( ( info.src.charCodeAt( pos ) >= 48 && info.src.charCodeAt( pos ) <= 57 ) ) state = 18;
480 			else state = -1;
481 			match = 5;
482 			match_pos = pos;
483 			break;
484 
485 		case 19:
486 			state = -1;
487 			match = 17;
488 			match_pos = pos;
489 			break;
490 
491 		case 20:
492 			state = -1;
493 			match = 19;
494 			match_pos = pos;
495 			break;
496 
497 		case 21:
498 			state = -1;
499 			match = 18;
500 			match_pos = pos;
501 			break;
502 
503 		case 22:
504 			state = -1;
505 			match = 24;
506 			match_pos = pos;
507 			break;
508 
509 		case 23:
510 			state = -1;
511 			match = 8;
512 			match_pos = pos;
513 			break;
514 
515 		case 24:
516 			if( ( info.src.charCodeAt( pos ) >= 48 && info.src.charCodeAt( pos ) <= 57 ) || ( info.src.charCodeAt( pos ) >= 65 && info.src.charCodeAt( pos ) <= 90 ) || ( info.src.charCodeAt( pos ) >= 97 && info.src.charCodeAt( pos ) <= 122 ) ) state = 24;
517 			else state = -1;
518 			match = 6;
519 			match_pos = pos;
520 			break;
521 
522 		case 25:
523 			state = -1;
524 			match = 10;
525 			match_pos = pos;
526 			break;
527 
528 		case 26:
529 			if( info.src.charCodeAt( pos ) == 34 ) state = 16;
530 			else if( info.src.charCodeAt( pos ) == 32 || info.src.charCodeAt( pos ) == 46 || ( info.src.charCodeAt( pos ) >= 48 && info.src.charCodeAt( pos ) <= 57 ) || info.src.charCodeAt( pos ) == 61 || ( info.src.charCodeAt( pos ) >= 65 && info.src.charCodeAt( pos ) <= 90 ) || ( info.src.charCodeAt( pos ) >= 97 && info.src.charCodeAt( pos ) <= 122 ) || info.src.charCodeAt( pos ) == 223 || info.src.charCodeAt( pos ) == 228 || info.src.charCodeAt( pos ) == 246 || info.src.charCodeAt( pos ) == 252 ) state = 26;
531 			else state = -1;
532 			break;
533 
534 		case 27:
535 			if( ( info.src.charCodeAt( pos ) >= 48 && info.src.charCodeAt( pos ) <= 57 ) || ( info.src.charCodeAt( pos ) >= 65 && info.src.charCodeAt( pos ) <= 90 ) || ( info.src.charCodeAt( pos ) >= 97 && info.src.charCodeAt( pos ) <= 122 ) ) state = 27;
536 			else if( info.src.charCodeAt( pos ) == 95 ) state = 35;
537 			else state = -1;
538 			match = 7;
539 			match_pos = pos;
540 			break;
541 
542 		case 28:
543 			if( info.src.charCodeAt( pos ) == 38 ) state = 17;
544 			else if( ( info.src.charCodeAt( pos ) >= 65 && info.src.charCodeAt( pos ) <= 90 ) || ( info.src.charCodeAt( pos ) >= 97 && info.src.charCodeAt( pos ) <= 122 ) ) state = 33;
545 			else state = -1;
546 			break;
547 
548 		case 29:
549 			if( ( info.src.charCodeAt( pos ) >= 48 && info.src.charCodeAt( pos ) <= 57 ) ) state = 18;
550 			else state = -1;
551 			break;
552 
553 		case 30:
554 			if( info.src.charCodeAt( pos ) == 61 ) state = 20;
555 			else state = -1;
556 			break;
557 
558 		case 31:
559 			if( info.src.charCodeAt( pos ) == 95 ) state = 36;
560 			else state = -1;
561 			break;
562 
563 		case 32:
564 			if( info.src.charCodeAt( pos ) == 124 ) state = 22;
565 			else state = -1;
566 			break;
567 
568 		case 33:
569 			if( info.src.charCodeAt( pos ) == 59 ) state = 23;
570 			else if( ( info.src.charCodeAt( pos ) >= 65 && info.src.charCodeAt( pos ) <= 90 ) || ( info.src.charCodeAt( pos ) >= 97 && info.src.charCodeAt( pos ) <= 122 ) ) state = 33;
571 			else state = -1;
572 			break;
573 
574 		case 34:
575 			if( ( info.src.charCodeAt( pos ) >= 65 && info.src.charCodeAt( pos ) <= 90 ) || ( info.src.charCodeAt( pos ) >= 97 && info.src.charCodeAt( pos ) <= 122 ) ) state = 37;
576 			else state = -1;
577 			break;
578 
579 		case 35:
580 			if( ( info.src.charCodeAt( pos ) >= 48 && info.src.charCodeAt( pos ) <= 57 ) || ( info.src.charCodeAt( pos ) >= 65 && info.src.charCodeAt( pos ) <= 90 ) || ( info.src.charCodeAt( pos ) >= 97 && info.src.charCodeAt( pos ) <= 122 ) ) state = 27;
581 			else if( info.src.charCodeAt( pos ) == 95 ) state = 35;
582 			else state = -1;
583 			break;
584 
585 		case 36:
586 			if( ( info.src.charCodeAt( pos ) >= 48 && info.src.charCodeAt( pos ) <= 57 ) || ( info.src.charCodeAt( pos ) >= 65 && info.src.charCodeAt( pos ) <= 90 ) || ( info.src.charCodeAt( pos ) >= 97 && info.src.charCodeAt( pos ) <= 122 ) ) state = 24;
587 			else state = -1;
588 			break;
589 
590 		case 37:
591 			if( info.src.charCodeAt( pos ) == 93 ) state = 25;
592 			else if( ( info.src.charCodeAt( pos ) >= 65 && info.src.charCodeAt( pos ) <= 90 ) || ( info.src.charCodeAt( pos ) >= 97 && info.src.charCodeAt( pos ) <= 122 ) ) state = 37;
593 			else state = -1;
594 			break;
595 
596 	}
597 
598 
599 				pos++;
600 
601 			}
602 			while( state > -1 );
603 
604 		}
605 		while( 1 > -1 && match == 1 );
606 
607 		if( match > -1 )
608 		{
609 			info.att = info.src.substr( start, match_pos - start );
610 			info.offset = match_pos;
611 
612 
613 		}
614 		else
615 		{
616 			info.att = new String();
617 			match = -1;
618 		}
619 
620 		return match;
621 	}
622 
623 
624 	function __parse( src, err_off, err_la ) {
625 		var		sstack			= new Array();
626 		var		vstack			= new Array();
627 		var 	err_cnt			= 0;
628 		var		act;
629 		var		go;
630 		var		la;
631 		var		rval;
632 		var 	parseinfo		= new Function( "", "var offset; var src; var att;" );
633 		var		info			= new parseinfo();
634 
635 	/* Pop-Table */
636 	var pop_tab = new Array(
637 		new Array( 0/* p' */, 1 ),
638 		new Array( 27/* p */, 1 ),
639 		new Array( 26/* e */, 5 ),
640 		new Array( 26/* e */, 3 ),
641 		new Array( 26/* e */, 3 ),
642 		new Array( 26/* e */, 3 ),
643 		new Array( 26/* e */, 3 ),
644 		new Array( 26/* e */, 3 ),
645 		new Array( 26/* e */, 3 ),
646 		new Array( 26/* e */, 3 ),
647 		new Array( 26/* e */, 3 ),
648 		new Array( 26/* e */, 2 ),
649 		new Array( 26/* e */, 3 ),
650 		new Array( 26/* e */, 3 ),
651 		new Array( 26/* e */, 3 ),
652 		new Array( 26/* e */, 3 ),
653 		new Array( 26/* e */, 3 ),
654 		new Array( 26/* e */, 2 ),
655 		new Array( 26/* e */, 3 ),
656 		new Array( 26/* e */, 3 ),
657 		new Array( 26/* e */, 1 ),
658 		new Array( 26/* e */, 1 ),
659 		new Array( 26/* e */, 1 ),
660 		new Array( 26/* e */, 1 ),
661 		new Array( 26/* e */, 1 ),
662 		new Array( 26/* e */, 1 ),
663 		new Array( 26/* e */, 4 ),
664 		new Array( 26/* e */, 1 )
665 	);
666 
667 	/* Action-Table */
668 	var act_tab = new Array(
669 		/* State 0 */ new Array( 2/* "(" */,3 , 23/* "!" */,4 , 12/* "-" */,5 , 9/* "STRING" */,6 , 4/* "INT" */,7 , 5/* "FLOAT" */,8 , 6/* "PARAM" */,9 , 8/* "HTML" */,10 , 10/* "COMMAND" */,11 , 7/* "VAR" */,12 ),
670 		/* State 1 */ new Array( 28/* "$" */,0 ),
671 		/* State 2 */ new Array( 14/* "/" */,13 , 13/* "*" */,14 , 25/* "&&" */,15 , 24/* "||" */,16 , 15/* "^" */,17 , 12/* "-" */,18 , 11/* "+" */,19 , 22/* ">" */,20 , 21/* "<" */,21 , 20/* "!=" */,22 , 19/* "==" */,23 , 18/* ">=" */,24 , 17/* "<=" */,25 , 28/* "$" */,-1 ),
672 		/* State 3 */ new Array( 2/* "(" */,3 , 23/* "!" */,4 , 12/* "-" */,5 , 9/* "STRING" */,6 , 4/* "INT" */,7 , 5/* "FLOAT" */,8 , 6/* "PARAM" */,9 , 8/* "HTML" */,10 , 10/* "COMMAND" */,11 , 7/* "VAR" */,12 ),
673 		/* State 4 */ new Array( 2/* "(" */,3 , 23/* "!" */,4 , 12/* "-" */,5 , 9/* "STRING" */,6 , 4/* "INT" */,7 , 5/* "FLOAT" */,8 , 6/* "PARAM" */,9 , 8/* "HTML" */,10 , 10/* "COMMAND" */,11 , 7/* "VAR" */,12 ),
674 		/* State 5 */ new Array( 2/* "(" */,3 , 23/* "!" */,4 , 12/* "-" */,5 , 9/* "STRING" */,6 , 4/* "INT" */,7 , 5/* "FLOAT" */,8 , 6/* "PARAM" */,9 , 8/* "HTML" */,10 , 10/* "COMMAND" */,11 , 7/* "VAR" */,12 ),
675 		/* State 6 */ new Array( 11/* "+" */,29 , 28/* "$" */,-24 , 17/* "<=" */,-24 , 18/* ">=" */,-24 , 19/* "==" */,-24 , 20/* "!=" */,-24 , 21/* "<" */,-24 , 22/* ">" */,-24 , 12/* "-" */,-24 , 15/* "^" */,-24 , 24/* "||" */,-24 , 25/* "&&" */,-24 , 13/* "*" */,-24 , 14/* "/" */,-24 , 16/* "," */,-24 , 3/* ")" */,-24 ),
676 		/* State 7 */ new Array( 28/* "$" */,-20 , 17/* "<=" */,-20 , 18/* ">=" */,-20 , 19/* "==" */,-20 , 20/* "!=" */,-20 , 21/* "<" */,-20 , 22/* ">" */,-20 , 11/* "+" */,-20 , 12/* "-" */,-20 , 15/* "^" */,-20 , 24/* "||" */,-20 , 25/* "&&" */,-20 , 13/* "*" */,-20 , 14/* "/" */,-20 , 16/* "," */,-20 , 3/* ")" */,-20 ),
677 		/* State 8 */ new Array( 28/* "$" */,-21 , 17/* "<=" */,-21 , 18/* ">=" */,-21 , 19/* "==" */,-21 , 20/* "!=" */,-21 , 21/* "<" */,-21 , 22/* ">" */,-21 , 11/* "+" */,-21 , 12/* "-" */,-21 , 15/* "^" */,-21 , 24/* "||" */,-21 , 25/* "&&" */,-21 , 13/* "*" */,-21 , 14/* "/" */,-21 , 16/* "," */,-21 , 3/* ")" */,-21 ),
678 		/* State 9 */ new Array( 28/* "$" */,-22 , 17/* "<=" */,-22 , 18/* ">=" */,-22 , 19/* "==" */,-22 , 20/* "!=" */,-22 , 21/* "<" */,-22 , 22/* ">" */,-22 , 11/* "+" */,-22 , 12/* "-" */,-22 , 15/* "^" */,-22 , 24/* "||" */,-22 , 25/* "&&" */,-22 , 13/* "*" */,-22 , 14/* "/" */,-22 , 16/* "," */,-22 , 3/* ")" */,-22 ),
679 		/* State 10 */ new Array( 28/* "$" */,-23 , 17/* "<=" */,-23 , 18/* ">=" */,-23 , 19/* "==" */,-23 , 20/* "!=" */,-23 , 21/* "<" */,-23 , 22/* ">" */,-23 , 11/* "+" */,-23 , 12/* "-" */,-23 , 15/* "^" */,-23 , 24/* "||" */,-23 , 25/* "&&" */,-23 , 13/* "*" */,-23 , 14/* "/" */,-23 , 16/* "," */,-23 , 3/* ")" */,-23 ),
680 		/* State 11 */ new Array( 28/* "$" */,-25 , 17/* "<=" */,-25 , 18/* ">=" */,-25 , 19/* "==" */,-25 , 20/* "!=" */,-25 , 21/* "<" */,-25 , 22/* ">" */,-25 , 11/* "+" */,-25 , 12/* "-" */,-25 , 15/* "^" */,-25 , 24/* "||" */,-25 , 25/* "&&" */,-25 , 13/* "*" */,-25 , 14/* "/" */,-25 , 16/* "," */,-25 , 3/* ")" */,-25 ),
681 		/* State 12 */ new Array( 2/* "(" */,30 , 28/* "$" */,-27 , 17/* "<=" */,-27 , 18/* ">=" */,-27 , 19/* "==" */,-27 , 20/* "!=" */,-27 , 21/* "<" */,-27 , 22/* ">" */,-27 , 11/* "+" */,-27 , 12/* "-" */,-27 , 15/* "^" */,-27 , 24/* "||" */,-27 , 25/* "&&" */,-27 , 13/* "*" */,-27 , 14/* "/" */,-27 , 16/* "," */,-27 , 3/* ")" */,-27 ),
682 		/* State 13 */ new Array( 2/* "(" */,3 , 23/* "!" */,4 , 12/* "-" */,5 , 9/* "STRING" */,6 , 4/* "INT" */,7 , 5/* "FLOAT" */,8 , 6/* "PARAM" */,9 , 8/* "HTML" */,10 , 10/* "COMMAND" */,11 , 7/* "VAR" */,12 ),
683 		/* State 14 */ new Array( 2/* "(" */,3 , 23/* "!" */,4 , 12/* "-" */,5 , 9/* "STRING" */,6 , 4/* "INT" */,7 , 5/* "FLOAT" */,8 , 6/* "PARAM" */,9 , 8/* "HTML" */,10 , 10/* "COMMAND" */,11 , 7/* "VAR" */,12 ),
684 		/* State 15 */ new Array( 2/* "(" */,3 , 23/* "!" */,4 , 12/* "-" */,5 , 9/* "STRING" */,6 , 4/* "INT" */,7 , 5/* "FLOAT" */,8 , 6/* "PARAM" */,9 , 8/* "HTML" */,10 , 10/* "COMMAND" */,11 , 7/* "VAR" */,12 ),
685 		/* State 16 */ new Array( 2/* "(" */,3 , 23/* "!" */,4 , 12/* "-" */,5 , 9/* "STRING" */,6 , 4/* "INT" */,7 , 5/* "FLOAT" */,8 , 6/* "PARAM" */,9 , 8/* "HTML" */,10 , 10/* "COMMAND" */,11 , 7/* "VAR" */,12 ),
686 		/* State 17 */ new Array( 2/* "(" */,3 , 23/* "!" */,4 , 12/* "-" */,5 , 9/* "STRING" */,6 , 4/* "INT" */,7 , 5/* "FLOAT" */,8 , 6/* "PARAM" */,9 , 8/* "HTML" */,10 , 10/* "COMMAND" */,11 , 7/* "VAR" */,12 ),
687 		/* State 18 */ new Array( 2/* "(" */,3 , 23/* "!" */,4 , 12/* "-" */,5 , 9/* "STRING" */,6 , 4/* "INT" */,7 , 5/* "FLOAT" */,8 , 6/* "PARAM" */,9 , 8/* "HTML" */,10 , 10/* "COMMAND" */,11 , 7/* "VAR" */,12 ),
688 		/* State 19 */ new Array( 2/* "(" */,3 , 23/* "!" */,4 , 12/* "-" */,5 , 9/* "STRING" */,6 , 4/* "INT" */,7 , 5/* "FLOAT" */,8 , 6/* "PARAM" */,9 , 8/* "HTML" */,10 , 10/* "COMMAND" */,11 , 7/* "VAR" */,12 ),
689 		/* State 20 */ new Array( 2/* "(" */,3 , 23/* "!" */,4 , 12/* "-" */,5 , 9/* "STRING" */,6 , 4/* "INT" */,7 , 5/* "FLOAT" */,8 , 6/* "PARAM" */,9 , 8/* "HTML" */,10 , 10/* "COMMAND" */,11 , 7/* "VAR" */,12 ),
690 		/* State 21 */ new Array( 2/* "(" */,3 , 23/* "!" */,4 , 12/* "-" */,5 , 9/* "STRING" */,6 , 4/* "INT" */,7 , 5/* "FLOAT" */,8 , 6/* "PARAM" */,9 , 8/* "HTML" */,10 , 10/* "COMMAND" */,11 , 7/* "VAR" */,12 ),
691 		/* State 22 */ new Array( 2/* "(" */,3 , 23/* "!" */,4 , 12/* "-" */,5 , 9/* "STRING" */,6 , 4/* "INT" */,7 , 5/* "FLOAT" */,8 , 6/* "PARAM" */,9 , 8/* "HTML" */,10 , 10/* "COMMAND" */,11 , 7/* "VAR" */,12 ),
692 		/* State 23 */ new Array( 2/* "(" */,3 , 23/* "!" */,4 , 12/* "-" */,5 , 9/* "STRING" */,6 , 4/* "INT" */,7 , 5/* "FLOAT" */,8 , 6/* "PARAM" */,9 , 8/* "HTML" */,10 , 10/* "COMMAND" */,11 , 7/* "VAR" */,12 ),
693 		/* State 24 */ new Array( 2/* "(" */,3 , 23/* "!" */,4 , 12/* "-" */,5 , 9/* "STRING" */,6 , 4/* "INT" */,7 , 5/* "FLOAT" */,8 , 6/* "PARAM" */,9 , 8/* "HTML" */,10 , 10/* "COMMAND" */,11 , 7/* "VAR" */,12 ),
694 		/* State 25 */ new Array( 2/* "(" */,3 , 23/* "!" */,4 , 12/* "-" */,5 , 9/* "STRING" */,6 , 4/* "INT" */,7 , 5/* "FLOAT" */,8 , 6/* "PARAM" */,9 , 8/* "HTML" */,10 , 10/* "COMMAND" */,11 , 7/* "VAR" */,12 ),
695 		/* State 26 */ new Array( 14/* "/" */,13 , 13/* "*" */,14 , 25/* "&&" */,15 , 24/* "||" */,16 , 15/* "^" */,17 , 12/* "-" */,18 , 11/* "+" */,19 , 22/* ">" */,20 , 21/* "<" */,21 , 20/* "!=" */,22 , 19/* "==" */,23 , 18/* ">=" */,24 , 17/* "<=" */,25 , 16/* "," */,44 , 3/* ")" */,45 ),
696 		/* State 27 */ new Array( 14/* "/" */,-11 , 13/* "*" */,-11 , 25/* "&&" */,15 , 24/* "||" */,16 , 15/* "^" */,-11 , 12/* "-" */,-11 , 11/* "+" */,-11 , 22/* ">" */,-11 , 21/* "<" */,-11 , 20/* "!=" */,-11 , 19/* "==" */,-11 , 18/* ">=" */,-11 , 17/* "<=" */,-11 , 28/* "$" */,-11 , 16/* "," */,-11 , 3/* ")" */,-11 ),
697 		/* State 28 */ new Array( 14/* "/" */,-17 , 13/* "*" */,-17 , 25/* "&&" */,15 , 24/* "||" */,16 , 15/* "^" */,17 , 12/* "-" */,-17 , 11/* "+" */,-17 , 22/* ">" */,20 , 21/* "<" */,21 , 20/* "!=" */,22 , 19/* "==" */,23 , 18/* ">=" */,24 , 17/* "<=" */,25 , 28/* "$" */,-17 , 16/* "," */,-17 , 3/* ")" */,-17 ),
698 		/* State 29 */ new Array( 2/* "(" */,3 , 23/* "!" */,4 , 12/* "-" */,5 , 9/* "STRING" */,6 , 4/* "INT" */,7 , 5/* "FLOAT" */,8 , 6/* "PARAM" */,9 , 8/* "HTML" */,10 , 10/* "COMMAND" */,11 , 7/* "VAR" */,12 ),
699 		/* State 30 */ new Array( 2/* "(" */,3 , 23/* "!" */,4 , 12/* "-" */,5 , 9/* "STRING" */,6 , 4/* "INT" */,7 , 5/* "FLOAT" */,8 , 6/* "PARAM" */,9 , 8/* "HTML" */,10 , 10/* "COMMAND" */,11 , 7/* "VAR" */,12 ),
700 		/* State 31 */ new Array( 14/* "/" */,-16 , 13/* "*" */,-16 , 25/* "&&" */,15 , 24/* "||" */,16 , 15/* "^" */,17 , 12/* "-" */,-16 , 11/* "+" */,-16 , 22/* ">" */,20 , 21/* "<" */,21 , 20/* "!=" */,22 , 19/* "==" */,23 , 18/* ">=" */,24 , 17/* "<=" */,25 , 28/* "$" */,-16 , 16/* "," */,-16 , 3/* ")" */,-16 ),
701 		/* State 32 */ new Array( 14/* "/" */,-15 , 13/* "*" */,-15 , 25/* "&&" */,15 , 24/* "||" */,16 , 15/* "^" */,17 , 12/* "-" */,-15 , 11/* "+" */,-15 , 22/* ">" */,20 , 21/* "<" */,21 , 20/* "!=" */,22 , 19/* "==" */,23 , 18/* ">=" */,24 , 17/* "<=" */,25 , 28/* "$" */,-15 , 16/* "," */,-15 , 3/* ")" */,-15 ),
702 		/* State 33 */ new Array( 14/* "/" */,-14 , 13/* "*" */,-14 , 25/* "&&" */,-14 , 24/* "||" */,-14 , 15/* "^" */,-14 , 12/* "-" */,-14 , 11/* "+" */,-14 , 22/* ">" */,-14 , 21/* "<" */,-14 , 20/* "!=" */,-14 , 19/* "==" */,-14 , 18/* ">=" */,-14 , 17/* "<=" */,-14 , 28/* "$" */,-14 , 16/* "," */,-14 , 3/* ")" */,-14 ),
703 		/* State 34 */ new Array( 14/* "/" */,-13 , 13/* "*" */,-13 , 25/* "&&" */,-13 , 24/* "||" */,-13 , 15/* "^" */,-13 , 12/* "-" */,-13 , 11/* "+" */,-13 , 22/* ">" */,-13 , 21/* "<" */,-13 , 20/* "!=" */,-13 , 19/* "==" */,-13 , 18/* ">=" */,-13 , 17/* "<=" */,-13 , 28/* "$" */,-13 , 16/* "," */,-13 , 3/* ")" */,-13 ),
704 		/* State 35 */ new Array( 14/* "/" */,-12 , 13/* "*" */,-12 , 25/* "&&" */,15 , 24/* "||" */,16 , 15/* "^" */,-12 , 12/* "-" */,-12 , 11/* "+" */,-12 , 22/* ">" */,20 , 21/* "<" */,21 , 20/* "!=" */,22 , 19/* "==" */,23 , 18/* ">=" */,24 , 17/* "<=" */,25 , 28/* "$" */,-12 , 16/* "," */,-12 , 3/* ")" */,-12 ),
705 		/* State 36 */ new Array( 14/* "/" */,13 , 13/* "*" */,14 , 25/* "&&" */,15 , 24/* "||" */,16 , 15/* "^" */,17 , 12/* "-" */,-10 , 11/* "+" */,-10 , 22/* ">" */,20 , 21/* "<" */,21 , 20/* "!=" */,22 , 19/* "==" */,23 , 18/* ">=" */,24 , 17/* "<=" */,25 , 28/* "$" */,-10 , 16/* "," */,-10 , 3/* ")" */,-10 ),
706 		/* State 37 */ new Array( 14/* "/" */,13 , 13/* "*" */,14 , 25/* "&&" */,15 , 24/* "||" */,16 , 15/* "^" */,17 , 12/* "-" */,-9 , 11/* "+" */,-9 , 22/* ">" */,20 , 21/* "<" */,21 , 20/* "!=" */,22 , 19/* "==" */,23 , 18/* ">=" */,24 , 17/* "<=" */,25 , 28/* "$" */,-9 , 16/* "," */,-9 , 3/* ")" */,-9 ),
707 		/* State 38 */ new Array( 14/* "/" */,-8 , 13/* "*" */,-8 , 25/* "&&" */,15 , 24/* "||" */,16 , 15/* "^" */,-8 , 12/* "-" */,-8 , 11/* "+" */,-8 , 22/* ">" */,-8 , 21/* "<" */,-8 , 20/* "!=" */,-8 , 19/* "==" */,-8 , 18/* ">=" */,-8 , 17/* "<=" */,-8 , 28/* "$" */,-8 , 16/* "," */,-8 , 3/* ")" */,-8 ),
708 		/* State 39 */ new Array( 14/* "/" */,-7 , 13/* "*" */,-7 , 25/* "&&" */,15 , 24/* "||" */,16 , 15/* "^" */,-7 , 12/* "-" */,-7 , 11/* "+" */,-7 , 22/* ">" */,-7 , 21/* "<" */,-7 , 20/* "!=" */,-7 , 19/* "==" */,-7 , 18/* ">=" */,-7 , 17/* "<=" */,-7 , 28/* "$" */,-7 , 16/* "," */,-7 , 3/* ")" */,-7 ),
709 		/* State 40 */ new Array( 14/* "/" */,-6 , 13/* "*" */,-6 , 25/* "&&" */,15 , 24/* "||" */,16 , 15/* "^" */,-6 , 12/* "-" */,-6 , 11/* "+" */,-6 , 22/* ">" */,-6 , 21/* "<" */,-6 , 20/* "!=" */,-6 , 19/* "==" */,-6 , 18/* ">=" */,-6 , 17/* "<=" */,-6 , 28/* "$" */,-6 , 16/* "," */,-6 , 3/* ")" */,-6 ),
710 		/* State 41 */ new Array( 14/* "/" */,-5 , 13/* "*" */,-5 , 25/* "&&" */,15 , 24/* "||" */,16 , 15/* "^" */,-5 , 12/* "-" */,-5 , 11/* "+" */,-5 , 22/* ">" */,-5 , 21/* "<" */,-5 , 20/* "!=" */,-5 , 19/* "==" */,-5 , 18/* ">=" */,-5 , 17/* "<=" */,-5 , 28/* "$" */,-5 , 16/* "," */,-5 , 3/* ")" */,-5 ),
711 		/* State 42 */ new Array( 14/* "/" */,-4 , 13/* "*" */,-4 , 25/* "&&" */,15 , 24/* "||" */,16 , 15/* "^" */,-4 , 12/* "-" */,-4 , 11/* "+" */,-4 , 22/* ">" */,-4 , 21/* "<" */,-4 , 20/* "!=" */,-4 , 19/* "==" */,-4 , 18/* ">=" */,-4 , 17/* "<=" */,-4 , 28/* "$" */,-4 , 16/* "," */,-4 , 3/* ")" */,-4 ),
712 		/* State 43 */ new Array( 14/* "/" */,-3 , 13/* "*" */,-3 , 25/* "&&" */,15 , 24/* "||" */,16 , 15/* "^" */,-3 , 12/* "-" */,-3 , 11/* "+" */,-3 , 22/* ">" */,-3 , 21/* "<" */,-3 , 20/* "!=" */,-3 , 19/* "==" */,-3 , 18/* ">=" */,-3 , 17/* "<=" */,-3 , 28/* "$" */,-3 , 16/* "," */,-3 , 3/* ")" */,-3 ),
713 		/* State 44 */ new Array( 2/* "(" */,3 , 23/* "!" */,4 , 12/* "-" */,5 , 9/* "STRING" */,6 , 4/* "INT" */,7 , 5/* "FLOAT" */,8 , 6/* "PARAM" */,9 , 8/* "HTML" */,10 , 10/* "COMMAND" */,11 , 7/* "VAR" */,12 ),
714 		/* State 45 */ new Array( 28/* "$" */,-18 , 17/* "<=" */,-18 , 18/* ">=" */,-18 , 19/* "==" */,-18 , 20/* "!=" */,-18 , 21/* "<" */,-18 , 22/* ">" */,-18 , 11/* "+" */,-18 , 12/* "-" */,-18 , 15/* "^" */,-18 , 24/* "||" */,-18 , 25/* "&&" */,-18 , 13/* "*" */,-18 , 14/* "/" */,-18 , 16/* "," */,-18 , 3/* ")" */,-18 ),
715 		/* State 46 */ new Array( 14/* "/" */,13 , 13/* "*" */,14 , 25/* "&&" */,15 , 24/* "||" */,16 , 15/* "^" */,17 , 12/* "-" */,-19 , 11/* "+" */,-19 , 22/* ">" */,20 , 21/* "<" */,21 , 20/* "!=" */,22 , 19/* "==" */,23 , 18/* ">=" */,24 , 17/* "<=" */,25 , 28/* "$" */,-19 , 16/* "," */,-19 , 3/* ")" */,-19 ),
716 		/* State 47 */ new Array( 14/* "/" */,13 , 13/* "*" */,14 , 25/* "&&" */,15 , 24/* "||" */,16 , 15/* "^" */,17 , 12/* "-" */,18 , 11/* "+" */,19 , 22/* ">" */,20 , 21/* "<" */,21 , 20/* "!=" */,22 , 19/* "==" */,23 , 18/* ">=" */,24 , 17/* "<=" */,25 , 3/* ")" */,49 ),
717 		/* State 48 */ new Array( 14/* "/" */,13 , 13/* "*" */,14 , 25/* "&&" */,15 , 24/* "||" */,16 , 15/* "^" */,17 , 12/* "-" */,18 , 11/* "+" */,19 , 22/* ">" */,20 , 21/* "<" */,21 , 20/* "!=" */,22 , 19/* "==" */,23 , 18/* ">=" */,24 , 17/* "<=" */,25 , 3/* ")" */,50 ),
718 		/* State 49 */ new Array( 28/* "$" */,-26 , 17/* "<=" */,-26 , 18/* ">=" */,-26 , 19/* "==" */,-26 , 20/* "!=" */,-26 , 21/* "<" */,-26 , 22/* ">" */,-26 , 11/* "+" */,-26 , 12/* "-" */,-26 , 15/* "^" */,-26 , 24/* "||" */,-26 , 25/* "&&" */,-26 , 13/* "*" */,-26 , 14/* "/" */,-26 , 16/* "," */,-26 , 3/* ")" */,-26 ),
719 		/* State 50 */ new Array( 28/* "$" */,-2 , 17/* "<=" */,-2 , 18/* ">=" */,-2 , 19/* "==" */,-2 , 20/* "!=" */,-2 , 21/* "<" */,-2 , 22/* ">" */,-2 , 11/* "+" */,-2 , 12/* "-" */,-2 , 15/* "^" */,-2 , 24/* "||" */,-2 , 25/* "&&" */,-2 , 13/* "*" */,-2 , 14/* "/" */,-2 , 16/* "," */,-2 , 3/* ")" */,-2 )
720 	);
721 
722 	/* Goto-Table */
723 	var goto_tab = new Array(
724 		/* State 0 */ new Array( 27/* p */,1 , 26/* e */,2 ),
725 		/* State 1 */ new Array(  ),
726 		/* State 2 */ new Array(  ),
727 		/* State 3 */ new Array( 26/* e */,26 ),
728 		/* State 4 */ new Array( 26/* e */,27 ),
729 		/* State 5 */ new Array( 26/* e */,28 ),
730 		/* State 6 */ new Array(  ),
731 		/* State 7 */ new Array(  ),
732 		/* State 8 */ new Array(  ),
733 		/* State 9 */ new Array(  ),
734 		/* State 10 */ new Array(  ),
735 		/* State 11 */ new Array(  ),
736 		/* State 12 */ new Array(  ),
737 		/* State 13 */ new Array( 26/* e */,31 ),
738 		/* State 14 */ new Array( 26/* e */,32 ),
739 		/* State 15 */ new Array( 26/* e */,33 ),
740 		/* State 16 */ new Array( 26/* e */,34 ),
741 		/* State 17 */ new Array( 26/* e */,35 ),
742 		/* State 18 */ new Array( 26/* e */,36 ),
743 		/* State 19 */ new Array( 26/* e */,37 ),
744 		/* State 20 */ new Array( 26/* e */,38 ),
745 		/* State 21 */ new Array( 26/* e */,39 ),
746 		/* State 22 */ new Array( 26/* e */,40 ),
747 		/* State 23 */ new Array( 26/* e */,41 ),
748 		/* State 24 */ new Array( 26/* e */,42 ),
749 		/* State 25 */ new Array( 26/* e */,43 ),
750 		/* State 26 */ new Array(  ),
751 		/* State 27 */ new Array(  ),
752 		/* State 28 */ new Array(  ),
753 		/* State 29 */ new Array( 26/* e */,46 ),
754 		/* State 30 */ new Array( 26/* e */,47 ),
755 		/* State 31 */ new Array(  ),
756 		/* State 32 */ new Array(  ),
757 		/* State 33 */ new Array(  ),
758 		/* State 34 */ new Array(  ),
759 		/* State 35 */ new Array(  ),
760 		/* State 36 */ new Array(  ),
761 		/* State 37 */ new Array(  ),
762 		/* State 38 */ new Array(  ),
763 		/* State 39 */ new Array(  ),
764 		/* State 40 */ new Array(  ),
765 		/* State 41 */ new Array(  ),
766 		/* State 42 */ new Array(  ),
767 		/* State 43 */ new Array(  ),
768 		/* State 44 */ new Array( 26/* e */,48 ),
769 		/* State 45 */ new Array(  ),
770 		/* State 46 */ new Array(  ),
771 		/* State 47 */ new Array(  ),
772 		/* State 48 */ new Array(  ),
773 		/* State 49 */ new Array(  ),
774 		/* State 50 */ new Array(  )
775 	);
776 
777 
778 
779 	/* Symbol labels */
780 	var labels = new Array(
781 		"p'" /* Non-terminal symbol */,
782 		"WHITESPACE" /* Terminal symbol */,
783 		"(" /* Terminal symbol */,
784 		")" /* Terminal symbol */,
785 		"INT" /* Terminal symbol */,
786 		"FLOAT" /* Terminal symbol */,
787 		"PARAM" /* Terminal symbol */,
788 		"VAR" /* Terminal symbol */,
789 		"HTML" /* Terminal symbol */,
790 		"STRING" /* Terminal symbol */,
791 		"COMMAND" /* Terminal symbol */,
792 		"+" /* Terminal symbol */,
793 		"-" /* Terminal symbol */,
794 		"*" /* Terminal symbol */,
795 		"/" /* Terminal symbol */,
796 		"^" /* Terminal symbol */,
797 		"," /* Terminal symbol */,
798 		"<=" /* Terminal symbol */,
799 		">=" /* Terminal symbol */,
800 		"==" /* Terminal symbol */,
801 		"!=" /* Terminal symbol */,
802 		"<" /* Terminal symbol */,
803 		">" /* Terminal symbol */,
804 		"!" /* Terminal symbol */,
805 		"||" /* Terminal symbol */,
806 		"&&" /* Terminal symbol */,
807 		"e" /* Non-terminal symbol */,
808 		"p" /* Non-terminal symbol */,
809 		"$" /* Terminal symbol */
810 	);
811 
812 
813 
814 		info.offset = 0;
815 		info.src = src;
816 		info.att = new String();
817 
818 		if( !err_off )
819 			err_off	= new Array();
820 		if( !err_la )
821 		err_la = new Array();
822 
823 		sstack.push( 0 );
824 		vstack.push( 0 );
825 
826 		la = __lex( info );
827 
828 		while( true )
829 		{
830 			act = 52;
831 			for( var i = 0; i < act_tab[sstack[sstack.length-1]].length; i+=2 )
832 			{
833 				if( act_tab[sstack[sstack.length-1]][i] == la )
834 				{
835 					act = act_tab[sstack[sstack.length-1]][i+1];
836 					break;
837 				}
838 			}
839 
840 			if( _dbg_withtrace && sstack.length > 0 )
841 			{
842 				__dbg_print( "\nState " + sstack[sstack.length-1] + "\n" +
843 								"\tLookahead: " + labels[la] + " (\"" + info.att + "\")\n" +
844 								"\tAction: " + act + "\n" + 
845 								"\tSource: \"" + info.src.substr( info.offset, 30 ) + ( ( info.offset + 30 < info.src.length ) ?
846 										"..." : "" ) + "\"\n" +
847 								"\tStack: " + sstack.join() + "\n" +
848 								"\tValue stack: " + vstack.join() + "\n" );
849 			}
850 
851 
852 			//Panic-mode: Try recovery when parse-error occurs!
853 			if( act == 52 )
854 			{
855 				if( _dbg_withtrace )
856 					__dbg_print( "Error detected: There is no reduce or shift on the symbol " + labels[la] );
857 
858 				err_cnt++;
859 				err_off.push( info.offset - info.att.length );			
860 				err_la.push( new Array() );
861 				for( var i = 0; i < act_tab[sstack[sstack.length-1]].length; i+=2 )
862 					err_la[err_la.length-1].push( labels[act_tab[sstack[sstack.length-1]][i]] );
863 
864 				//Remember the original stack!
865 				var rsstack = new Array();
866 				var rvstack = new Array();
867 				for( var i = 0; i < sstack.length; i++ )
868 				{
869 					rsstack[i] = sstack[i];
870 					rvstack[i] = vstack[i];
871 				}
872 
873 				while( act == 52 && la != 28 )
874 				{
875 					if( _dbg_withtrace )
876 						__dbg_print( "\tError recovery\n" +
877 										"Current lookahead: " + labels[la] + " (" + info.att + ")\n" +
878 										"Action: " + act + "\n\n" );
879 					if( la == -1 )
880 						info.offset++;
881 
882 					while( act == 52 && sstack.length > 0 )
883 					{
884 						sstack.pop();
885 						vstack.pop();
886 
887 						if( sstack.length == 0 )
888 							break;
889 
890 						act = 52;
891 						for( var i = 0; i < act_tab[sstack[sstack.length-1]].length; i+=2 )
892 						{
893 							if( act_tab[sstack[sstack.length-1]][i] == la )
894 							{
895 								act = act_tab[sstack[sstack.length-1]][i+1];
896 								break;
897 							}
898 						}
899 					}
900 
901 					if( act != 52 )
902 						break;
903 
904 					for( var i = 0; i < rsstack.length; i++ )
905 					{
906 						sstack.push( rsstack[i] );
907 						vstack.push( rvstack[i] );
908 					}
909 
910 					la = __lex( info );
911 				}
912 
913 				if( act == 52 )
914 				{
915 					if( _dbg_withtrace )
916 						__dbg_print( "\tError recovery failed, terminating parse process..." );
917 					break;
918 				}
919 
920 
921 				if( _dbg_withtrace )
922 					__dbg_print( "\tError recovery succeeded, continuing" );
923 			}
924 
925 			/*
926 			if( act == 52 )
927 				break;
928 			*/
929 
930 
931 			//Shift
932 			if( act > 0 )
933 			{			
934 				if( _dbg_withtrace )
935 					__dbg_print( "Shifting symbol: " + labels[la] + " (" + info.att + ")" );
936 
937 				sstack.push( act );
938 				vstack.push( info.att );
939 
940 				la = __lex( info );
941 
942 				if( _dbg_withtrace )
943 					__dbg_print( "\tNew lookahead symbol: " + labels[la] + " (" + info.att + ")" );
944 			}
945 			//Reduce
946 			else
947 			{		
948 				act *= -1;
949 
950 				if( _dbg_withtrace )
951 					__dbg_print( "Reducing by producution: " + act );
952 
953 				rval = void(0);
954 
955 				if( _dbg_withtrace )
956 					__dbg_print( "\tPerforming semantic action..." );
957 
958 	switch( act )
959 	{
960 		case 0:
961 		{
962 			rval = vstack[ vstack.length - 1 ];
963 		}
964 		break;
965 		case 1:
966 		{
967 			 rval = JXG.GeogebraReader.ggbAct('end', vstack[ vstack.length - 1 ]); 
968 		}
969 		break;
970 		case 2:
971 		{
972 			 rval = JXG.GeogebraReader.ggbAct('coord', vstack[ vstack.length - 4 ], vstack[ vstack.length - 2 ], element); 
973 		}
974 		break;
975 		case 3:
976 		{
977 			 rval = JXG.GeogebraReader.ggbAct('le', vstack[ vstack.length - 3 ], vstack[ vstack.length - 1 ]); 
978 		}
979 		break;
980 		case 4:
981 		{
982 			 rval = JXG.GeogebraReader.ggbAct('ge', vstack[ vstack.length - 3 ], vstack[ vstack.length - 1 ]); 
983 		}
984 		break;
985 		case 5:
986 		{
987 			 rval = JXG.GeogebraReader.ggbAct('eq', vstack[ vstack.length - 3 ], vstack[ vstack.length - 1 ]); 
988 		}
989 		break;
990 		case 6:
991 		{
992 			 rval = JXG.GeogebraReader.ggbAct('neq', vstack[ vstack.length - 3 ], vstack[ vstack.length - 1 ]); 
993 		}
994 		break;
995 		case 7:
996 		{
997 			 rval = JXG.GeogebraReader.ggbAct('lt', vstack[ vstack.length - 3 ], vstack[ vstack.length - 1 ]); 
998 		}
999 		break;
1000 		case 8:
1001 		{
1002 			 rval = JXG.GeogebraReader.ggbAct('gt', vstack[ vstack.length - 3 ], vstack[ vstack.length - 1 ]); 
1003 		}
1004 		break;
1005 		case 9:
1006 		{
1007 			 rval = JXG.GeogebraReader.ggbAct('add', vstack[ vstack.length - 3 ], vstack[ vstack.length - 1 ]); 
1008 		}
1009 		break;
1010 		case 10:
1011 		{
1012 			 rval = JXG.GeogebraReader.ggbAct('sub', vstack[ vstack.length - 3 ], vstack[ vstack.length - 1 ]); 
1013 		}
1014 		break;
1015 		case 11:
1016 		{
1017 			 rval = JXG.GeogebraReader.ggbAct('neg', vstack[ vstack.length - 1 ]); 
1018 		}
1019 		break;
1020 		case 12:
1021 		{
1022 			 rval = JXG.GeogebraReader.ggbAct('pow', vstack[ vstack.length - 3 ], vstack[ vstack.length - 1 ]); 
1023 		}
1024 		break;
1025 		case 13:
1026 		{
1027 			 rval = JXG.GeogebraReader.ggbAct('or', vstack[ vstack.length - 3 ], vstack[ vstack.length - 1 ]); 
1028 		}
1029 		break;
1030 		case 14:
1031 		{
1032 			 rval = JXG.GeogebraReader.ggbAct('and', vstack[ vstack.length - 3 ], vstack[ vstack.length - 1 ]); 
1033 		}
1034 		break;
1035 		case 15:
1036 		{
1037 			 rval = JXG.GeogebraReader.ggbAct('mul', vstack[ vstack.length - 3 ], vstack[ vstack.length - 1 ]); 
1038 		}
1039 		break;
1040 		case 16:
1041 		{
1042 			 rval = JXG.GeogebraReader.ggbAct('div', vstack[ vstack.length - 3 ], vstack[ vstack.length - 1 ]); 
1043 		}
1044 		break;
1045 		case 17:
1046 		{
1047 			 rval = JXG.GeogebraReader.ggbAct('negmult', vstack[ vstack.length - 1 ]); 
1048 		}
1049 		break;
1050 		case 18:
1051 		{
1052 			 rval = JXG.GeogebraReader.ggbAct('bra', vstack[ vstack.length - 2 ]); 
1053 		}
1054 		break;
1055 		case 19:
1056 		{
1057 			 rval = JXG.GeogebraReader.ggbAct('string', vstack[ vstack.length - 3 ], vstack[ vstack.length - 1 ]); 
1058 		}
1059 		break;
1060 		case 20:
1061 		{
1062 			 rval = JXG.GeogebraReader.ggbAct('int', vstack[ vstack.length - 1 ]); 
1063 		}
1064 		break;
1065 		case 21:
1066 		{
1067 			 rval = JXG.GeogebraReader.ggbAct('float', vstack[ vstack.length - 1 ]); 
1068 		}
1069 		break;
1070 		case 22:
1071 		{
1072 			 rval = JXG.GeogebraReader.ggbAct('param', vstack[ vstack.length - 1 ]); 
1073 		}
1074 		break;
1075 		case 23:
1076 		{
1077 			 rval = JXG.GeogebraReader.ggbAct('html', vstack[ vstack.length - 1 ]); 
1078 		}
1079 		break;
1080 		case 24:
1081 		{
1082 			 rval = JXG.GeogebraReader.ggbAct('string', vstack[ vstack.length - 1 ]); 
1083 		}
1084 		break;
1085 		case 25:
1086 		{
1087 			 rval = JXG.GeogebraReader.ggbAct('command', vstack[ vstack.length - 1 ]); 
1088 		}
1089 		break;
1090 		case 26:
1091 		{
1092 			 rval = JXG.GeogebraReader.ggbAct('var', vstack[ vstack.length - 4 ], vstack[ vstack.length - 2 ]); 
1093 		}
1094 		break;
1095 		case 27:
1096 		{
1097 			 rval = JXG.GeogebraReader.ggbAct('var', vstack[ vstack.length - 1 ]); 
1098 		}
1099 		break;
1100 	}
1101 
1102 
1103 
1104 				if( _dbg_withtrace )
1105 					__dbg_print( "\tPopping " + pop_tab[act][1] + " off the stack..." );
1106 
1107 				for( var i = 0; i < pop_tab[act][1]; i++ )
1108 				{
1109 					sstack.pop();
1110 					str = vstack.pop();
1111 				}
1112 
1113 				go = -1;
1114 				for( var i = 0; i < goto_tab[sstack[sstack.length-1]].length; i+=2 )
1115 				{
1116 					if( goto_tab[sstack[sstack.length-1]][i] == pop_tab[act][0] )
1117 					{
1118 						go = goto_tab[sstack[sstack.length-1]][i+1];
1119 						break;
1120 					}
1121 				}
1122 
1123 				if( act == 0 )
1124 					break;
1125 
1126 				if( _dbg_withtrace )
1127 					__dbg_print( "\tPushing non-terminal " + labels[ pop_tab[act][0] ] );
1128 
1129 				sstack.push( go );
1130 				vstack.push( rval );			
1131 			}
1132 
1133 			if( _dbg_withtrace )
1134 			{		
1135 				JXG.debug( _dbg_string );
1136 				_dbg_string = new String();
1137 			}
1138 		}
1139 
1140 		if( _dbg_withtrace )
1141 		{
1142 			__dbg_print( "\nParse complete." );
1143 			JXG.debug( _dbg_string );
1144 		}
1145 
1146 		return err_cnt;
1147 	}
1148 /***** end replace *****/
1149 
1150   var error_offsets = new Array();
1151   var error_lookaheads = new Array();
1152   var error_count = 0;
1153   var str = exp;
1154   if( ( error_count = __parse( str, error_offsets, error_lookaheads ) ) > 0 ) {
1155     var errstr = new String();
1156     for( var i = 0; i < error_count; i++ )
1157       errstr += "Parse error in line " + ( str.substr( 0, error_offsets[i] ).match( /\n/g ) ?
1158                   str.substr( 0, error_offsets[i] ).match( /\n/g ).length : 1 )
1159                 + " near \"" + str.substr( error_offsets[i] ) + "\", expecting \"" + error_lookaheads[i].join() + "\"\n" ;
1160     JXG.debug( errstr );
1161   }
1162 
1163   return str;
1164 }; //end: ggbParse()
1165 
1166 
1167 /**
1168  * Override JSxGraph defaults with Geogebra settings
1169  * @param {Object} board object
1170  * @return {Object} board oject
1171  */
1172 this.setDefaultOptions = function(board){
1173   board.options.elements.strokeWidth = '1px'; // TODO: board.options.line.strokeWidth
1174   board.options.elements.withLabel = true;
1175 
1176   board.options.point.face = 'circle';
1177   board.options.point.size = 3;
1178   board.options.point.fillColor = 'blue';
1179   board.options.point.fillOpacity = 1;
1180   board.options.point.highlightFillOpacity = 1;
1181   board.options.point.strokeColor = 'black';
1182   board.options.point.highlightStrokeColor = 'black';
1183   board.options.point.strokeWidth = '2px';
1184 
1185   board.options.line.strokeWidth = '1px';
1186   board.options.line.highlightStrokeColor = '#000000';
1187   board.options.line.strokeColor = '#000000';
1188 
1189   board.options.polygon.fillColor = JXG.rgb2hex(153, 51, 0);
1190   board.options.polygon.fillOpacity = 0.1;
1191   board.options.polygon.highlightFillColor = board.options.polygon.fillColor;
1192   board.options.polygon.highlightFillOpacity = 0.1;
1193 
1194   board.options.sector.fillColor = JXG.rgb2hex(153, 51, 0);
1195   board.options.sector.fillOpacity = 0.1;
1196   board.options.sector.highlightFillColor = board.options.sector.fillColor;
1197   board.options.sector.highlightFillOpacity = 0.1;
1198 
1199   board.options.angle.fillColor = JXG.rgb2hex(0, 100, 0);
1200   board.options.angle.fillOpacity = 0.1;
1201   //board.options.angle.highlightFillColor = board.options.angle.fillColor;
1202   board.options.angle.highlightFillOpacity = 0.1;
1203 
1204   return board;
1205 };
1206 
1207 /**
1208  * Set color properties of a geogebra element.
1209  * Set stroke, fill, lighting, label and draft color attributes.
1210  * @param {Object} gxtEl element of which attributes are to set
1211  * @param {Object} attr object carrying all necessary attribute values
1212  * @return {Object} returning the updated attr-attributes object
1213  */
1214 this.colorProperties = function(Data, attr) {
1215   var a,r,g,b;
1216   a = (Data.getElementsByTagName("objColor").length > 0 && Data.getElementsByTagName("objColor")[0].getAttribute("alpha")) ? parseFloat(Data.getElementsByTagName("objColor")[0].getAttribute("alpha")) : 0;
1217   r = (Data.getElementsByTagName("objColor").length > 0 && Data.getElementsByTagName("objColor")[0].getAttribute("r")) ? parseInt(Data.getElementsByTagName("objColor")[0].getAttribute("r")).toString(16) : 0;
1218   g = (Data.getElementsByTagName("objColor").length > 0 && Data.getElementsByTagName("objColor")[0].getAttribute("g")) ? parseInt(Data.getElementsByTagName("objColor")[0].getAttribute("g")).toString(16) : 0;
1219   b = (Data.getElementsByTagName("objColor").length > 0 && Data.getElementsByTagName("objColor")[0].getAttribute("b")) ? parseInt(Data.getElementsByTagName("objColor")[0].getAttribute("b")).toString(16) : 0;
1220   if (r.length == 1) r = '0' + r;
1221   if (g.length == 1) g = '0' + g;
1222   if (b.length == 1) b = '0' + b;
1223 
1224   attr.fillColor = '#'+ r + g + b;
1225   attr.strokeColor = attr.fillColor;
1226   attr.highlightFillColor = attr.fillColor;
1227   attr.highlightStrokeColor = attr.strokeColor;
1228   attr.fillOpacity = a;
1229   attr.highlightFillOpacity = a;
1230   attr.labelColor = attr.fillColor;
1231 
1232   return attr;
1233 };
1234 
1235 /**
1236  * Set the board properties.
1237  * Set active, area, dash, draft and showinfo attributes.
1238  * @param {Object} gxtEl element of which attributes are to set
1239  * @param {Object} Data element of which attributes are to set
1240  * @param {Object} attr object containing the necessary attribute values
1241  */
1242 this.boardProperties = function(gxtEl, Data, attr) {
1243   return attr;
1244 };
1245 
1246 /**
1247  * @param {Object} gxtEl element of which attributes are to set
1248  * @param {Object} Data element of which attributes are to set
1249  * @return {Object} updated element
1250  */
1251 this.coordinates = function(gxtEl, Data) {
1252   var labelOffset = {}, tmp;
1253   labelOffset.x = 0; labelOffset.y = 0; labelOffset.z = 0;
1254 
1255   if(Data.getElementsByTagName('labelOffset')[0]) {
1256     // tmp = new JXG.Coords(JXG.COORDS_BY_SCREEN, [,
1257     //                                             parseFloat(Data.getElementsByTagName("labelOffset")[0].attributes["y"].value)], JXG.GeogebraReader.board);
1258     labelOffset.x = parseFloat(Data.getElementsByTagName("labelOffset")[0].getAttribute("x"))/JXG.GeogebraReader.board.stretchX;
1259     labelOffset.y = parseFloat(Data.getElementsByTagName("labelOffset")[0].getAttribute("y"))/JXG.GeogebraReader.board.stretchY;
1260   }
1261 
1262   if(Data.getElementsByTagName("coords")[0]) {
1263     gxtEl.x = parseFloat(Data.getElementsByTagName("coords")[0].getAttribute("x"));
1264     gxtEl.y = parseFloat(Data.getElementsByTagName("coords")[0].getAttribute("y"));
1265     gxtEl.z = parseFloat(Data.getElementsByTagName("coords")[0].getAttribute("z"));
1266   } else if(Data.getElementsByTagName("startPoint")[0]) {
1267     if(Data.getElementsByTagName("startPoint")[0].getAttribute('exp')) {
1268       var a = JXG.getReference(JXG.GeogebraReader.board, Data.getElementsByTagName("startPoint")[0].getAttribute('exp'));
1269       gxtEl.x = function() {return a.X()+labelOffset.x;};
1270       gxtEl.y = function() {return a.Y()-labelOffset.y;}; // minus because geogebra starts on the other side
1271       gxtEl.z = false;
1272     } else {
1273       gxtEl.x = parseFloat(Data.getElementsByTagName("startPoint")[0].getAttribute("x"));
1274       gxtEl.y = parseFloat(Data.getElementsByTagName("startPoint")[0].getAttribute("y"));
1275       gxtEl.z = parseFloat(Data.getElementsByTagName("startPoint")[0].getAttribute("z"));
1276     }
1277   } else if(Data.getElementsByTagName("absoluteScreenLocation")[0]) {
1278     var tmp = new JXG.Coords(JXG.COORDS_BY_SCREEN, [parseFloat(Data.getElementsByTagName("absoluteScreenLocation")[0].getAttribute("x")),
1279                                                     parseFloat(Data.getElementsByTagName("absoluteScreenLocation")[0].getAttribute("y"))], JXG.GeogebraReader.board);
1280     gxtEl.x = tmp.usrCoords[1]+labelOffset.x;
1281     gxtEl.y = tmp.usrCoords[2]+labelOffset.y;
1282     gxtEl.z = false;
1283   } else {
1284     return false;
1285   }
1286 
1287   return gxtEl;
1288 };
1289 
1290 /**
1291  * Writing element attributes to the given object
1292  * @param {XMLNode} Data expects the content of the current element
1293  * @return {Object} object with according attributes
1294  */
1295 this.visualProperties = function(Data, attr) {
1296   (Data.getElementsByTagName("show").length != 0 && Data.getElementsByTagName("show")[0].getAttribute("object")) ? attr.visible = Data.getElementsByTagName("show")[0].getAttribute("object") : false;
1297   (Data.getElementsByTagName("show").length != 0 && Data.getElementsByTagName("show")[0].getAttribute("label")) ? attr.withLabel = Data.getElementsByTagName("show")[0].getAttribute("label") : true;
1298   if(attr.withLabel == 'true') {
1299      attr.withLabel = true;
1300   }
1301   else if(attr.withLabel == 'false') {
1302      attr.withLabel = false;
1303   }
1304   (Data.getElementsByTagName('pointSize')[0]) ? attr.size = Data.getElementsByTagName('pointSize')[0].getAttribute("val") : false;
1305   (Data.getElementsByTagName('pointStyle')[0]) ? attr.styleGGB = Data.getElementsByTagName('pointStyle')[0].getAttribute("val") : false;
1306    if(attr.styleGGB == 0 || attr.styleGGB == 2) {
1307       attr.face = 'circle';
1308       if(attr.styleGGB == 0) {
1309         attr.fillColor = attr.strokeColor;
1310         attr.fillOpacity = 1;
1311         attr.highlightFillColor = attr.strokeColor;
1312         attr.highlightFillOpacity = 1;
1313         attr.strokeColor = 'black';
1314         attr.strokeWidth = '1px';
1315       }
1316       else if(attr.styleGGB == 2) {
1317         attr.fillColor = 'none';
1318       }
1319    }
1320    else if(attr.styleGGB == 1) {
1321       attr.face = 'x';
1322    }
1323    else if(attr.styleGGB == 3) {
1324       attr.face = '+';
1325       attr.strokeOpacity = 1;
1326    }
1327    else if(attr.styleGGB == 4 || attr.styleGGB == 5) {
1328       attr.face = 'diamond';
1329       if(attr.styleGGB == 4) {
1330          attr.fillColor = attr.strokeColor;
1331          attr.fillOpacity = 1;
1332       }
1333       else if(attr.styleGGB == 5) {
1334         attr.fillColor = 'none';
1335       }
1336    }
1337    else if(attr.styleGGB == 6) {
1338       attr.face = 'triangleUp';
1339       attr.fillColor = attr.strokeColor;
1340       attr.fillOpacity = 1;
1341    }
1342    else if(attr.styleGGB == 7) {
1343       attr.face = 'triangleDown';
1344       attr.fillColor = attr.strokeColor;
1345       attr.fillOpacity = 1;
1346    }
1347    else if(attr.styleGGB == 8) {
1348       attr.face = 'triangleRight';
1349       attr.fillColor = attr.strokeColor;
1350       attr.fillOpacity = 1;
1351    }
1352    else if(attr.styleGGB == 9) {
1353       attr.face = 'triangleLeft';
1354       attr.fillColor = attr.strokeColor;
1355       attr.fillOpacity = 1;
1356    }
1357   (Data.getElementsByTagName('slopeTriangleSize')[0]) ? attr.slopeWidth = Data.getElementsByTagName('slopeTriangleSize')[0].getAttribute("val") : false;
1358   (Data.getElementsByTagName('lineStyle')[0]) ? attr.strokeWidth = (Data.getElementsByTagName('lineStyle')[0].getAttribute("thickness")/2.0)+'px' : false;
1359   if(attr.strokeWidth) {
1360     attr.highlightStrokeWidth = (1*attr.strokeWidth.substr(0,attr.strokeWidth.length-2)+1)+'px';
1361   }
1362   (Data.getElementsByTagName('lineStyle')[0]) ? attr.dashGGB = Data.getElementsByTagName('lineStyle')[0].getAttribute("type") : false;
1363 
1364    if(attr.dashGGB == 0) {
1365       attr.dash = 0;
1366    }
1367    else if(attr.dashGGB == 10) {
1368       attr.dash = 2;
1369    }
1370    else if(attr.dashGGB == 15) {
1371       attr.dash = 3;
1372    }
1373    else if(attr.dashGGB == 20) {
1374       attr.dash = 1;
1375    }
1376    else if(attr.dashGGB == 30) {
1377       attr.dash = 6;
1378    }
1379   (Data.getElementsByTagName("labelOffset")[0]) ? attr.labelX = 1*Data.getElementsByTagName("labelOffset")[0].getAttribute("x") : false;
1380   (Data.getElementsByTagName("labelOffset")[0]) ? attr.labelY = 1*Data.getElementsByTagName("labelOffset")[0].getAttribute("y") : false;
1381   (Data.getElementsByTagName("trace")[0]) ? attr.trace = Data.getElementsByTagName("trace")[0].getAttribute("val") : false;
1382   (Data.getElementsByTagName('fix')[0]) ? attr.fixed = Data.getElementsByTagName('fix')[0].getAttribute("val") : false;
1383   return attr;
1384 };
1385 
1386 /**
1387  * Searching for an element in the geogebra tree
1388  * @param {String} the name of the element to search for
1389  * @param {Boolean} whether it is search for an expression or not
1390  * @return {Object} object with according label
1391  */
1392 this.getElement = function(name, expr) {
1393   var Data, i, j;
1394   expr = expr || false;
1395   for(i=0; i<JXG.GeogebraReader.tree.getElementsByTagName("construction").length; i++)
1396     if(expr == false) {
1397       for(j=0; j<JXG.GeogebraReader.tree.getElementsByTagName("construction")[i].getElementsByTagName("element").length; j++) {
1398         Data = JXG.GeogebraReader.tree.getElementsByTagName("construction")[i].getElementsByTagName("element")[j];
1399         if(name == Data.getAttribute("label")) {
1400           return Data;
1401         }
1402       };
1403     } else {
1404       for(j=0; j<JXG.GeogebraReader.tree.getElementsByTagName("construction")[i].getElementsByTagName("expression").length; j++) {
1405         Data = JXG.GeogebraReader.tree.getElementsByTagName("construction")[i].getElementsByTagName("expression")[j];
1406         if(name == Data.getAttribute("label")) {
1407           return Data;
1408         }
1409       };
1410     }
1411   return false;
1412 };
1413 
1414 /**
1415  * Check if an element is already registered in the temporary ggbElements register. If not, create and register the element.
1416  * @param {String} the name of the element to check
1417  * @return {Object} newly created element
1418  */
1419 this.checkElement = function(name) {
1420 // Segment[A, B] nur bis Version 2.4 ? In 2.5 schon (x(A), x(B)) und durch Parser loesbar
1421   // if(name.match(/[a-zA-Z]+\[[a-zA-Z0-9]+[a-zA-Z0-9,\ ]*\]/)) {
1422   //   var tmp, type, input, output, i;
1423   //   tmp = name.split('[');
1424   //   type = tmp[0];
1425   //   input = tmp[1].split(']');
1426   //   input = input[0].split(', ');
1427   //   for(i=0; i<input.length; i++) {
1428   //     input[i] = JXG.GeogebraReader.checkElement(input[i]);
1429   //   }
1430   //   output = {
1431   //     'attributes' : []
1432   //   };
1433   //   output.attributes['type'] = {value: type };
1434   //   output.attributes['label'] = {value: name};
1435   //
1436   //   JXG.GeogebraReader.board.ggbElements[name] = JXG.GeogebraReader.writeElement(JXG.GeogebraReader.board, name, input, type);
1437   // } else
1438   if(typeof JXG.GeogebraReader.board.ggbElements[name] == 'undefined' || JXG.GeogebraReader.board.ggbElements[name] == '') {
1439     var input = JXG.GeogebraReader.getElement(name);
1440     JXG.GeogebraReader.board.ggbElements[name] = JXG.GeogebraReader.writeElement(JXG.GeogebraReader.board, input);
1441   }
1442   return JXG.GeogebraReader.board.ggbElements[name];
1443 };
1444 
1445 /**
1446  * Prepare expression for this.ggbParse with solving multiplications and replacing mathematical functions.
1447  * @param {String} exp Expression to parse and correct
1448  * @return {String} correct expression with fixed function and multiplication
1449  */
1450 this.functionParse = function(type, exp) {
1451  var input, vars, expr, output, i, s, o;
1452  switch(type) {
1453   case 'c':
1454     // search for function params
1455     if(exp.match(/[a-zA-Z0-9\']+\([a-zA-Z0-9]+[a-zA-Z0-9,\ ]*\)[\ ]*[=][\ ]*[a-zA-Z0-9\+\-\*\/ \( \) \u005E]+/)) {
1456       input = exp.split('(')[1].split(')')[0];
1457       vars = input.split(', ');
1458 
1459       output = [];
1460       for(i=0; i<vars.length; i++)
1461         output.push("__"+vars[i]);
1462 
1463       expr = exp.split('=')[1];
1464 
1465       // separate and replace function parameters
1466       for(i=0; i<vars.length; i++) {
1467         if(vars[i] == 'x') {
1468           expr = expr.replace(/(?![e])x(?!\()(?![p])/g, '__'+vars[i]);
1469         } else if(vars[i] == 'y') {
1470           expr = expr.replace(/(?![e])y(?!\()(?![p])/g, '__'+vars[i]);
1471         } else {
1472           expr = expr.replace( eval('/'+vars[i]+'/g'), '__'+vars[i] );
1473         }
1474       }
1475 
1476       // replace -__x to -1*__x
1477       expr = expr.replace(/-__/g, '-1*__');
1478 
1479 	  if(JXG.GeogebraReader.format <= 3.01) {
1480 	    // prepare string: "solve" multiplications 'a b' to 'a*b'
1481 	    s = expr.split(' ');
1482 	    o = '';
1483 	    for(var i=0; i<s.length; i++) {
1484 	      if(s.length != i+1)
1485 	        if(s[i].search(/\)$/) > -1 || s[i].search(/[0-9]+$/) > -1 || s[i].search(/[a-zA-Z]+(\_*[a-zA-Z0-9]+)*$/) > -1)
1486 	          if(s[i+1].search(/^\(/) > -1 ||
1487                  s[i+1].search(/^[0-9]+/) > -1 ||
1488                  s[i+1].search(/^[a-zA-Z]+(\_*[a-zA-Z0-9]+)*/) > -1 ||
1489                  s[i+1].search(/\_\_[a-zA-Z0-9]+/) > -1) {
1490 	               s[i] = s[i] + "*";
1491                  }
1492 	      o += s[i];
1493 	    };
1494 	    expr = o;
1495 	  }
1496 
1497       output.push(expr);
1498       return output;
1499     } else {
1500       return exp;
1501     }
1502   break;
1503   case 's':
1504     exp = exp.replace(/(?![e])x(?!\()(?![p])/g, '__x');
1505     return ['__x', exp];
1506   break;
1507   default:
1508     if(JXG.GeogebraReader.format <= 3.01) {
1509 	  // prepare string: "solve" multiplications 'a b' to 'a*b'
1510 	  s = exp.split(' ');
1511 	  o = '';
1512       for(i=0; i<s.length; i++) {
1513         if(s.length != i+1)
1514           if(s[i].search(/\)$/) > -1 || s[i].search(/[0-9]+$/) > -1 || s[i].search(/[a-zA-Z]+(\_*[a-zA-Z0-9]+)*$/) > -1)
1515             if(s[i+1].search(/^\(/) > -1 ||
1516               s[i+1].search(/^[0-9]+/) > -1 ||
1517               s[i+1].search(/^[a-zA-Z]+(\_*[a-zA-Z0-9]+)*/) > -1 ||
1518               s[i+1].search(/\_\_[a-zA-Z0-9]+/) > -1) {
1519                 s[i] = s[i] + "*";
1520             }
1521 	    o += s[i];
1522 	  };
1523 	  exp = o;
1524 	}
1525     return exp;
1526   break;
1527  }
1528 };
1529 
1530 /**
1531  * Searching for an element in the geogebra tree
1532  * @param {Object} board object
1533  */
1534 this.writeBoard = function(board) {
1535   var boardData = JXG.GeogebraReader.tree.getElementsByTagName("euclidianView")[0];
1536 
1537   board.origin = {};
1538   board.origin.usrCoords = [1, 0, 0];
1539   board.origin.scrCoords = [1, 1*boardData.getElementsByTagName("coordSystem")[0].getAttribute("xZero"), 1*boardData.getElementsByTagName("coordSystem")[0].getAttribute("yZero")];
1540   board.unitX = (boardData.getElementsByTagName("coordSystem")[0].getAttribute("scale")) ? 1*boardData.getElementsByTagName("coordSystem")[0].getAttribute("scale") : 1;
1541   board.unitY = (boardData.getElementsByTagName("coordSystem")[0].getAttribute("yscale")) ? 1*boardData.getElementsByTagName("coordSystem")[0].getAttribute("yscale") : board.unitX;
1542   board.updateStretch();
1543 
1544   board.fontSize = (JXG.GeogebraReader.tree.getElementsByTagName("gui")[0] && JXG.GeogebraReader.tree.getElementsByTagName("gui")[0].getElementsByTagName("font")[0]) ? 1*JXG.GeogebraReader.tree.getElementsByTagName("gui")[0].getElementsByTagName("font")[0].getAttribute("size") : '12px';
1545 
1546   JXG.JSXGraph.boards[board.id] = board;
1547 
1548   // Update of properties during update() is not necessary in GEONExT files
1549   board.renderer.enhancedRendering = true;
1550 
1551   // snap to point
1552   var snapToPoint = (boardData.getElementsByTagName('evSettings')[0].getAttribute("pointCapturing") == "true");
1553 
1554   var grid = (boardData.getElementsByTagName('evSettings')[0].getAttribute("grid") == "true") ? board.renderer.drawGrid(board) : null;
1555 
1556   if(boardData.getElementsByTagName('evSettings')[0].getAttribute("axes") && boardData.getElementsByTagName('evSettings')[0].getAttribute("axes") == "true") {
1557       board.ggbElements["xAxis"] = board.create('axis', [[0, 0], [1, 0]], {strokeColor:'black', minorTicks: 0});
1558       board.ggbElements["yAxis"] = board.create('axis', [[0, 0], [0, 1]], {strokeColor:'black', minorTicks: 0});
1559   }
1560 };
1561 
1562 /**
1563  * Searching for an element in the geogebra tree
1564  * @param {Object} board object
1565  * @param {Object} ggb element whose attributes are to parse
1566  * @param {Array} input list of all input elements
1567  * @param {String} typeName output construction method
1568  * @return {Object} return newly created element or false
1569  */
1570 this.writeElement = function(board, output, input, cmd) {
1571   var element, gxtEl, attr, p, exp, coord, type, points, border, length, m, s, e, sx, sy, ex, ey, func, range;
1572   element = (JXG.isArray(output)) ? output[0] : output;
1573 
1574   gxtEl = {}; // geometric element
1575   attr = {}; // Attributes of geometric elements
1576 
1577   JXG.debug(element);
1578 
1579   gxtEl.type = (element && element.attributes && typeof cmd === 'undefined') ? element.getAttribute('type').toLowerCase() : cmd;
1580   gxtEl.label = element.getAttribute('label');
1581   attr.name  = gxtEl.label;
1582 
1583   JXG.debug("<br><b>Konstruiere</b> "+ attr.name +"("+ gxtEl.type +"):");
1584 
1585   switch(gxtEl.type) {
1586     case 'point':
1587       attr = JXG.GeogebraReader.boardProperties(gxtEl, element, attr);
1588       attr = JXG.GeogebraReader.colorProperties(element, attr);
1589       attr = JXG.GeogebraReader.visualProperties(element, attr);
1590 
1591       if(JXG.GeogebraReader.getElement(attr.name, true)) {
1592         exp = JXG.GeogebraReader.getElement(attr.name, true).getAttribute('exp');
1593         coord = JXG.GeogebraReader.ggbParse(exp);
1594         gxtEl.x = new Function('return '+ coord[0] +';');
1595         gxtEl.y = new Function('return '+ coord[1] +';');
1596       } else {
1597         gxtEl = JXG.GeogebraReader.coordinates(gxtEl, element);
1598       }
1599       if(!JXG.exists(attr.styleGGB)) {
1600          attr.face = 'circle';
1601          attr.fillColor = attr.strokeColor;
1602          attr.fillOpacity = 1;
1603          attr.highlightFillColor = attr.strokeColor;
1604          attr.highlightFillOpacity = 1;
1605          attr.strokeColor = 'black';
1606          attr.strokeWidth = '1px';
1607       }
1608 
1609       JXG.debug(gxtEl);
1610       JXG.debug(input);
1611 
1612       try {
1613         var ma = /Circle\[\s*(\w+)\s*,\s*([\d\.]+)\s*\]/.exec(input);
1614         if(typeof input != 'undefined') {
1615           if (ma!=null && ma.length==3) {
1616             // from Circle[A, 5] take "A" and "5", stored in ma[1] and ma[2]
1617             var q = JXG.GeogebraReader.checkElement(ma[1])
1618             var c = board.create('circle', [q, parseFloat(ma[2])], {fillColor:'none',visible:false,name:''});
1619             p = board.create('glider', [gxtEl.x, gxtEl.y, c], attr);
1620           } else if(JXG.isArray(input)) {
1621             p = board.create('glider', [gxtEl.x, gxtEl.y, input[0]], attr);
1622           } else {
1623             p = board.create('glider', [gxtEl.x, gxtEl.y, input], attr);
1624           }
1625         } else {
1626           p = board.create('point', [gxtEl.x, gxtEl.y], attr);
1627         }
1628         return p;
1629       } catch(e) {
1630           JXG.debug("* <b>Err:</b> Point " + attr.name +"<br>\n");
1631           return false;
1632       }
1633     break;
1634     case 'segment':
1635       attr = JXG.GeogebraReader.boardProperties(gxtEl, element, attr);
1636       attr = JXG.GeogebraReader.colorProperties(element, attr);
1637       gxtEl = JXG.GeogebraReader.coordinates(gxtEl, element);
1638       attr = JXG.GeogebraReader.visualProperties(element, attr);
1639 
1640       try {
1641         JXG.debug("* <b>Segment:</b> ("+ attr.name +") First: " + input[0].name + ", Last: " + input[1].name + "<br>\n");
1642         attr.straightFirst = false;
1643         attr.straightLast =  false;
1644         p = board.create('line', input, attr);
1645         return p;
1646       } catch(e) {
1647         JXG.debug("* <b>Err:</b> Segment " + attr.name +" First: " + input[0].name + ", Last: " + input[1].name + "<br>\n");
1648         return false;
1649       }
1650     break;
1651     case 'line':
1652       attr = JXG.GeogebraReader.boardProperties(gxtEl, element, attr);
1653       attr = JXG.GeogebraReader.colorProperties(element, attr);
1654       gxtEl = JXG.GeogebraReader.coordinates(gxtEl, element);
1655       attr = JXG.GeogebraReader.visualProperties(element, attr);
1656 
1657       type = 'line';
1658       if(!input) {
1659         input = [ parseFloat(element.getElementsByTagName('coords')[0].getAttribute('z')),
1660                       parseFloat(element.getElementsByTagName('coords')[0].getAttribute('x')),
1661                       parseFloat(element.getElementsByTagName('coords')[0].getAttribute('y'))
1662                     ];
1663       } else if(JXG.getReference(board, input[1].id).type == 1330924622) {
1664          type = 'parallel'; // Parallele durch Punkt
1665       }
1666 
1667       try {
1668         p = board.create(type, input, attr);
1669         return p;
1670       } catch(e) {
1671         JXG.debug("* <b>Err:</b> Line " + attr.label +"<br>\n");
1672         return false;
1673       }
1674     break;
1675     case "orthogonalline":
1676       attr = JXG.GeogebraReader.boardProperties(gxtEl, element, attr);
1677       attr = JXG.GeogebraReader.colorProperties(element, attr);
1678       gxtEl = JXG.GeogebraReader.coordinates(gxtEl, element);
1679       attr = JXG.GeogebraReader.visualProperties(element, attr);
1680 
1681       try {
1682         JXG.debug("* <b>Orthogonalline:</b> First: " + input[0].id + ", Last: " + input[1].id + "<br>\n");
1683         p = board.create('normal', input, attr);
1684         return p;
1685       } catch(e) {
1686         JXG.debug("* <b>Err:</b> Orthogonalline " + attr.label +"<br>\n");
1687         return false;
1688       }
1689     break;
1690     case "polygon":
1691       attr = JXG.GeogebraReader.boardProperties(gxtEl, element, attr);
1692       attr = JXG.GeogebraReader.colorProperties(element, attr);
1693       gxtEl = JXG.GeogebraReader.coordinates(gxtEl, element);
1694       attr = JXG.GeogebraReader.visualProperties(element, attr);
1695 
1696       // test if polygon is regular
1697       if(input.length == 3 && output.length != 4) {
1698         input[2] = parseInt(input[2]);
1699         type = 'regular';
1700       }
1701 
1702       try {
1703         JXG.debug("* <b>Polygon:</b> First: " + input[0].name + ", Second: " + input[1].name + ", Third: " + input[2] + "<br>\n");
1704 
1705         var borders = [];
1706         var borderatts = [];
1707         length = (type == 'regular') ? output.length-input[2]+2 : output.length;
1708 
1709         for(var i=1; i<length; i++) {
1710           borders[i-1] = {};
1711           borderatts[i-1] = {};
1712           borders[i-1].id = '';
1713           borders[i-1].name = output[i].getAttribute('label');
1714           borderatts[i-1] = JXG.GeogebraReader.colorProperties(output[i], borderatts[i-1]);
1715           borderatts[i-1] = JXG.GeogebraReader.visualProperties(output[i], borderatts[i-1]);
1716           // JXG.debug("border["+ typeof borders[i-1] +"]: "+ borders[i-1].name);
1717         }
1718         attr.borders = borders;
1719 
1720         points = [];
1721         if(type == 'regular') {
1722           points.push(input[0]);
1723           points.push(input[1]);
1724 
1725           for(i=input[2]+1; i<output.length; i++){
1726             if(output[i].attributes)
1727               points.push(JXG.GeogebraReader.checkElement(output[i].getAttribute('label')));
1728             else
1729               points.push(output[i]);
1730           }
1731         } else {
1732           for(i=0; i<input.length; i++) {
1733             if(typeof input[i] === 'object') {
1734               points.push(input[i]);
1735               // JXG.debug("input-queue: added "+ input[i].name);
1736             }
1737           }
1738         }
1739 
1740         if(type == 'regular') {
1741           p = board.create('regularpolygon', points, attr);
1742         }
1743         else {
1744           p = board.create('polygon', points, attr);
1745         }
1746         for(i=0; i<p.borders.length; i++) {
1747             if(borderatts[i].withLabel) {
1748                 p.borders[i].addLabelToElement();
1749             }
1750             p.borders[i].setProperty(borderatts[i]);
1751         }
1752         return p;
1753       } catch(e) {
1754         JXG.debug("* <b>Err:</b> Polygon " + attr.name +"<br>\n");
1755         return false;
1756       }
1757     break;
1758     case 'intersect':
1759       attr = JXG.GeogebraReader.boardProperties(gxtEl, element, attr);
1760       attr = JXG.GeogebraReader.colorProperties(element, attr);
1761       gxtEl = JXG.GeogebraReader.coordinates(gxtEl, element);
1762       attr = JXG.GeogebraReader.visualProperties(element, attr);
1763 
1764       try {
1765         JXG.debug("* <b>Intersection:</b> First: " + input[0].name + ", Second: " + input[1].name + "<br>\n");
1766         if(!JXG.exists(attr.styleGGB)) {
1767            attr.face = 'circle';
1768            attr.fillColor = attr.strokeColor;
1769            attr.fillOpacity = 1;
1770            attr.highlightFillColor = attr.strokeColor;
1771            attr.highlightFillOpacity = 1;
1772            attr.strokeColor = 'black';
1773            attr.strokeWidth = '1px';
1774         }
1775         if(output.length == 1) {
1776            p = board.create('intersection', [input[0], input[1], 0], attr);
1777         }
1778         else {
1779            p = board.create('intersection', [input[0], input[1], 1], attr);
1780            var attr2 = {};
1781            attr2 = JXG.GeogebraReader.colorProperties(output[1], attr2);
1782            attr2 = JXG.GeogebraReader.visualProperties(output[1], attr2);
1783            attr2.name = output[1].getAttribute('label');
1784            var p2 = board.create('otherintersection', [input[0], input[1], p], attr2);
1785            board.ggbElements[attr2.name] = p2;
1786         }
1787 
1788         return p;
1789       } catch(e) {
1790         JXG.debug("* <b>Err:</b> Intersection " + attr.name +"<br>\n");
1791         return false;
1792       }
1793     break;
1794     case 'distance':
1795       attr = JXG.GeogebraReader.boardProperties(gxtEl, element, attr);
1796       attr = JXG.GeogebraReader.colorProperties(element, attr);
1797       gxtEl = JXG.GeogebraReader.coordinates(gxtEl, element);
1798       attr = JXG.GeogebraReader.visualProperties(element, attr);
1799 
1800 
1801       try {
1802         JXG.debug("* <b>Distance:</b> First: " + input[0].name + ", Second: " + input[1].name + "<br>\n");
1803 
1804         if(false && output[0].getAtribute('type') && output[0].getAttribute('type') == 'numeric') {
1805           input[1].Value = function(){ return this.X(); }
1806           p = input[1];
1807           board.elementsByName[attr.name] = p;
1808         } else {
1809           m = board.create('midpoint', input, {visible: 'false'});
1810           attr.visible = 'true';
1811           p = board.create('text', [function(){return m.X();}, function(){return m.Y();}, function(){
1812               return "<span style='text-decoration: overline'>"+ input[0].name + input[1].name +"</span> = "
1813                      + JXG.trimNumber(JXG.getReference(board, input[0].id).Dist(JXG.getReference(board, input[1].id)).toFixed(JXG.GeogebraReader.decimals));
1814                 }], attr);
1815           p.Value = function () {
1816             return (JXG.getReference(board, input[0].id).Dist(JXG.getReference(board, input[1].id)));
1817           }
1818         }
1819         return p;
1820       } catch(e) {
1821         JXG.debug("* <b>Err:</b> Distance " + attr.name +"<br>\n");
1822         return false;
1823       }
1824     break;
1825     case 'vector':
1826       attr = JXG.GeogebraReader.boardProperties(gxtEl, element, attr);
1827       attr = JXG.GeogebraReader.colorProperties(element, attr);
1828       gxtEl = JXG.GeogebraReader.coordinates(gxtEl, element);
1829       attr = JXG.GeogebraReader.visualProperties(element, attr);
1830 
1831       if(element.getElementsByTagName("startPoint")[0]) {
1832 
1833         if(input && input.length == 2) {
1834             e = JXG.GeogebraReader.checkElement(input[1].name);
1835         } else {
1836             e = [parseFloat(element.getElementsByTagName("coords")[0].getAttribute("x")), parseFloat(element.getElementsByTagName("coords")[0].getAttribute("y"))];
1837         }
1838         if(element.getElementsByTagName("startPoint")[0].getAttribute("x") && element.getElementsByTagName("startPoint")[0].getAttribute("y")) {
1839             s = [parseFloat(element.getElementsByTagName("startPoint")[0].getAttribute("x")), parseFloat(element.getElementsByTagName("startPoint")[0].getAttribute("y"))];
1840         } else if(element.getElementsByTagName("startPoint")[0].getAttribute("exp")) {
1841             var startpoint = element.getElementsByTagName("startPoint")[0].getAttribute("exp");
1842             s = JXG.GeogebraReader.checkElement(startpoint);
1843         }
1844       } else if(input && input.length != 0) {
1845         s = input[0];
1846         e = input[1];
1847       } else {
1848         exp = JXG.GeogebraReader.getElement(element.getAttribute('label'), true);
1849         if(exp) {// experimental
1850             exp = exp.getAttribute('exp');
1851             // exp = JXG.GeogebraReader.functionParse('', exp);
1852             exp = JXG.GeogebraReader.ggbParse(exp);
1853             if (JXG.isArray(exp))
1854             	exp = new Array(new Function('return '+ exp[1] +';'), new Function('return '+ exp[2] +';'));
1855             else
1856             	exp = new Function('return '+ exp +';');
1857             JXG.debug('exp: '+ exp);
1858             p = board.create('arrow', [[0,0], [exp[0], exp[1]]], attr);
1859             return p;
1860             //t = JXG.getReference(board, 'a');
1861             //s = t.point1;
1862             // var e = [-1*vector.point2.X(), -1*vector.point2.Y()];
1863             // attr.type = 'rotate';
1864             // var angle;
1865             // if(exp < 0) {
1866             //   angle = Math.PI;
1867             // } else if(exp == 0) {
1868             //   angle = 0;
1869             // } else {
1870             //   angle = Math.PI/exp;
1871             // }
1872             // needed: a clean rotating based on factor 'exp'
1873 
1874             // priorization of expression like 't*a' --> a := startPoint
1875         }
1876       }
1877 
1878       try {
1879         JXG.debug("* <b>Vector:</b> First: " + attr.name);
1880         p = board.create('arrow', [s, e], attr);
1881         return p;
1882       } catch(e) {
1883         JXG.debug("* <b>Err:</b> Vector " + attr.name + e +"<br>\n");
1884         return false;
1885       }
1886     break;
1887     case 'rotate':
1888       attr = JXG.GeogebraReader.boardProperties(gxtEl, element, attr);
1889       attr = JXG.GeogebraReader.colorProperties(element, attr);
1890       gxtEl = JXG.GeogebraReader.coordinates(gxtEl, element);
1891       attr = JXG.GeogebraReader.visualProperties(element, attr);
1892 
1893       try {
1894         JXG.debug("* <b>Rotate:</b> First: " + input[0].name + ", Second: " + input[1] + "<br>\n");
1895         attr.type = 'rotate';
1896 
1897         if(!JXG.exists(attr.styleGGB)) {
1898            attr.face = 'circle';
1899            attr.fillColor = attr.strokeColor;
1900            attr.fillOpacity = 1;
1901            attr.highlightFillColor = attr.strokeColor;
1902            attr.highlightFillOpacity = 1;
1903            attr.strokeColor = 'black';
1904            attr.strokeWidth = '1px';
1905         }
1906 
1907         t = board.create('transform', [parseInt(input[1])*Math.PI/180, input[2]], {type:'rotate'});
1908         p = board.create('point', [input[0], t], attr);
1909         return p;
1910       } catch(e) {
1911         JXG.debug("* <b>Err:</b> Rotate " + attr.name +"<br>\n");
1912         return false;
1913       }
1914     break;
1915     case 'dilate':
1916       attr = JXG.GeogebraReader.boardProperties(gxtEl, element, attr);
1917       attr = JXG.GeogebraReader.colorProperties(element, attr);
1918       gxtEl = JXG.GeogebraReader.coordinates(gxtEl, element);
1919       attr = JXG.GeogebraReader.visualProperties(element, attr);
1920 
1921       try {
1922         JXG.debug("* <b>Dilate:</b> First: " + input[0].name + ", Second: " + input[1] + "<br>\n");
1923         attr.type = 'rotate';
1924         var d = parseInt(input[1]);
1925         var d1 = board.create('transform', [d, d], {type:'scale'});
1926         var d2 = board.create('transform', [function() { return (1-d) * input[2].X(); },
1927                                                function() { return (1-d) * input[2].Y(); }], {type:'translate'});
1928 
1929         if(!JXG.exists(attr.styleGGB)) {
1930            attr.face = 'circle';
1931            attr.fillColor = attr.strokeColor;
1932            attr.fillOpacity = 1;
1933            attr.highlightFillColor = attr.strokeColor;
1934            attr.highlightFillOpacity = 1;
1935            attr.strokeColor = 'black';
1936            attr.strokeWidth = '1px';
1937         }
1938         p = board.create('point', [input[0], [d1, d2]], attr);
1939 
1940         return p;
1941       } catch(e) {
1942         JXG.debug("* <b>Err:</b> Dilate " + attr.name +"<br>\n");
1943         return false;
1944       }
1945     break;
1946     case 'translate':
1947       attr = JXG.GeogebraReader.boardProperties(gxtEl, element, attr);
1948       attr = JXG.GeogebraReader.colorProperties(element, attr);
1949       gxtEl = JXG.GeogebraReader.coordinates(gxtEl, element);
1950       attr = JXG.GeogebraReader.visualProperties(element, attr);
1951 
1952       try {
1953           t = board.create('transform', [function() { return input[1].point2.X()-input[1].point1.X(); },
1954                                          function() { return input[1].point2.Y()-input[1].point1.Y(); }], {type:'translate'});
1955           if(!JXG.exists(attr.styleGGB)) {
1956              attr.face = 'circle';
1957              attr.fillColor = attr.strokeColor;
1958              attr.fillOpacity = 1;
1959              attr.highlightFillColor = attr.strokeColor;
1960              attr.highlightFillOpacity = 1;
1961              attr.strokeColor = 'black';
1962              attr.strokeWidth = '1px';
1963           }
1964           p = board.create('point', [input[0], t], attr);
1965           return p;
1966       } catch(e) {
1967         JXG.debug("* <b>Err:</b> Translate " + attr.name +"<br>\n");
1968         return false;
1969       }
1970     break;
1971     case 'mirror':
1972       attr = JXG.GeogebraReader.boardProperties(gxtEl, element, attr);
1973       attr = JXG.GeogebraReader.colorProperties(element, attr);
1974       gxtEl = JXG.GeogebraReader.coordinates(gxtEl, element);
1975       attr = JXG.GeogebraReader.visualProperties(element, attr);
1976 
1977       if(JXG.getReference(board, input[1].id).type == 1330925652) var type = 'mirrorpoint'; // Punktspiegelung
1978       else if(JXG.getReference(board, input[1].id).type == 1330924622) var type = 'reflection'; // Geradenspiegelung
1979 
1980       try {
1981         JXG.debug("* <b>Mirror:</b> First: " + input[0].name + ", Second: " + input[1].name + "<br>\n");
1982         p = board.create(type, [input[1], input[0]], attr);
1983         return p;
1984       } catch(e) {
1985         JXG.debug("* <b>Err:</b> Mirror " + attr.name +"<br>\n");
1986         return false;
1987       }
1988     break;
1989     case 'circle':
1990       attr = JXG.GeogebraReader.boardProperties(gxtEl, element, attr);
1991       attr = JXG.GeogebraReader.colorProperties(element, attr);
1992       gxtEl = JXG.GeogebraReader.coordinates(gxtEl, element);
1993       attr = JXG.GeogebraReader.visualProperties(element, attr);
1994 
1995       try {
1996         JXG.debug("* <b>Circle:</b> First: " + input[0].name + ", Second: " + input[1] + "<br>\n");
1997         p = board.create('circle', input, attr);
1998         return p;
1999       } catch(e) {
2000         JXG.debug("* <b>Err:</b> Circle " + attr.name +"<br>\n");
2001         return false;
2002       }
2003     break;
2004     case 'circlearc':
2005       attr = JXG.GeogebraReader.boardProperties(gxtEl, element, attr);
2006       attr = JXG.GeogebraReader.colorProperties(element, attr);
2007       gxtEl = JXG.GeogebraReader.coordinates(gxtEl, element);
2008       attr = JXG.GeogebraReader.visualProperties(element, attr);
2009 
2010       try {
2011         JXG.debug("* <b>CircleArc:</b> First: " + input[0].name + ", Second: " + input[1].name + "<br>\n");
2012         p = board.create('arc', input, attr);
2013         return p;
2014       } catch(e) {
2015         JXG.debug("* <b>Err:</b> CircleArc " + attr.name +"<br>\n");
2016         return false;
2017       }
2018     break;
2019     case 'ellipse':
2020       attr = JXG.GeogebraReader.boardProperties(gxtEl, element, attr);
2021       attr = JXG.GeogebraReader.colorProperties(element, attr);
2022       gxtEl = JXG.GeogebraReader.coordinates(gxtEl, element);
2023       attr = JXG.GeogebraReader.visualProperties(element, attr);
2024 
2025       try {
2026         JXG.debug("* <b>Ellipse:</b> First: " + input[0].name + ", Second: " + input[1].name + ", Third: "+ input[2] +"<br>\n");
2027         // if third parameters is the major axis, else the third parameter is a point
2028         if(parseInt(input[2]) == input[2])
2029           input[2] = parseInt(input[2]*2); // Geogebra delivers the half major axis
2030 
2031         p = board.create('ellipse', input, attr);
2032         return p;
2033       } catch(e) {
2034         JXG.debug("* <b>Err:</b> Ellipse " + attr.name +"<br>\n");
2035         return false;
2036       }
2037     break;
2038     case 'conic':
2039       attr = JXG.GeogebraReader.boardProperties(gxtEl, element, attr);
2040       attr = JXG.GeogebraReader.colorProperties(element, attr);
2041       gxtEl = JXG.GeogebraReader.coordinates(gxtEl, element);
2042       attr = JXG.GeogebraReader.visualProperties(element, attr);
2043 
2044 //      try {
2045 	/*
2046         // is there an expression named like the conic?
2047         var exp = JXG.GeogebraReader.getElement(attr.name, true);
2048 
2049         // then get the function parameteres
2050         if(exp.attributes['exp']){
2051           // exp = JXG.GeogebraReader.functionParse(exp.attributes['exp'].value);
2052           // exp = JXG.GeogebraReader.ggbParse(exp.attributes['exp'].value);
2053 
2054 
2055 
2056           // (exp.getElementsByTagName('value')) ? exp = parseFloat(exp.getElementsByTagName('value')[0].attributes['val'].value) : false;
2057 
2058         } else */ if(input && input.length == 5) {
2059           p = board.create('conic', input, attr);
2060         } else if(element.getElementsByTagName('matrix')) {
2061           m = [];
2062           for(var i=0; i<element.getElementsByTagName('matrix')[0].attributes.length; i++) {
2063             m[i] = parseFloat(element.getElementsByTagName('matrix')[0].attributes[i].value);
2064           }
2065           p = board.create('conic', m, attr);
2066         }
2067 
2068         return p;
2069 //      } catch(e) {
2070 //        JXG.debug("* <b>Err:</b> Conic " + attr.name +"<br>\n");
2071 //        return false;
2072 //      }
2073     break;
2074     case 'circlesector':
2075       attr = JXG.GeogebraReader.boardProperties(gxtEl, element, attr);
2076       attr = JXG.GeogebraReader.colorProperties(element, attr);
2077       gxtEl = JXG.GeogebraReader.coordinates(gxtEl, element);
2078       attr = JXG.GeogebraReader.visualProperties(element, attr);
2079       //attr.names = [attr.name,'','',''];
2080       //attr2 = {};
2081       //attr2.names = attr.names;
2082       try {
2083         JXG.debug("* <b>CircleSector:</b> First: " + input[0].name + ", Second: " + input[1].name + ", Third: " + input[2].name + "<br>\n");
2084         p = board.create('sector', [input[0],input[1],input[2]], attr);
2085         /*
2086         p.point4.hideElement();
2087         p.arc.setProperty(attr);
2088         p.arc.visProp['highlightStrokeWidth'] = (1*p.arc.visProp['strokeWidth'].substr(0,p.arc.visProp['strokeWidth'].length-2)+1)+'px';
2089         p.lines[0].setProperty(attr);
2090         p.lines[1].setProperty(attr);
2091         p.lines[0].visProp['highlightStrokeWidth'] = (1*p.lines[0].visProp['strokeWidth'].substr(0,p.lines[0].visProp['strokeWidth'].length-2)+1)+'px';
2092         p.lines[1].visProp['highlightStrokeWidth'] = (1*p.lines[1].visProp['strokeWidth'].substr(0,p.lines[1].visProp['strokeWidth'].length-2)+1)+'px';
2093         p.arc.hasPoint = p.arc.hasPointSector;
2094         p.arc.highlight = (function(el){ return function() {
2095             this.board.renderer.highlight(this);
2096             this.board.renderer.highlight(el.lines[0]);
2097             this.board.renderer.highlight(el.lines[1]);
2098         };})(p);
2099         p.arc.noHighlight = (function(el){ return function() {
2100             this.board.renderer.noHighlight(this);
2101             this.board.renderer.noHighlight(el.lines[0]);
2102             this.board.renderer.noHighlight(el.lines[1]);
2103         };})(p);
2104         p.lines[0].highlight = (function(el){ return function() {
2105             this.board.renderer.highlight(this);
2106             this.board.renderer.highlight(el.arc);
2107             this.board.renderer.highlight(el.lines[1]);
2108         };})(p);
2109         p.lines[1].highlight = (function(el){ return function() {
2110             this.board.renderer.highlight(this);
2111             this.board.renderer.highlight(el.arc);
2112             this.board.renderer.highlight(el.lines[0]);
2113         };})(p);
2114         p.lines[0].noHighlight = (function(el){ return function() {
2115             this.board.renderer.noHighlight(this);
2116             this.board.renderer.noHighlight(el.arc);
2117             this.board.renderer.noHighlight(el.lines[1]);
2118         };})(p);
2119         p.lines[1].noHighlight = (function(el){ return function() {
2120             this.board.renderer.noHighlight(this);
2121             this.board.renderer.noHighlight(el.arc);
2122             this.board.renderer.noHighlight(el.lines[0]);
2123         };})(p);
2124         */
2125         return p;
2126       } catch(e) {
2127         JXG.debug("* <b>Err:</b> CircleSector " + attr.name +"<br>\n");
2128         return false;
2129       }
2130     break;
2131     case 'linebisector':
2132       attr = JXG.GeogebraReader.boardProperties(gxtEl, element, attr);
2133       attr = JXG.GeogebraReader.colorProperties(element, attr);
2134       gxtEl = JXG.GeogebraReader.coordinates(gxtEl, element);
2135       attr = JXG.GeogebraReader.visualProperties(element, attr);
2136 
2137       try {
2138         JXG.debug("* <b>LineBiSector (Mittelsenkrechte):</b> First: " + input[0].name + "<br>\n");
2139         attr.straightFirst = true;
2140         attr.straightLast =  true;
2141 
2142         m = board.create('midpoint', input, {visible: false});
2143         if(JXG.getReference(board, input[0].id).type == 1330925652 && JXG.getReference(board, input[1].id).type == 1330925652) {
2144           t = board.create('line', input, {visible: 'false'});
2145           p = board.create('perpendicular', [m, t], attr);
2146           p.point.setProperty('visible:false');
2147         } else {
2148           p = board.create('perpendicular', [m, input[0]], attr);
2149           p.point.setProperty('visible:false');
2150         }
2151         return p[0];
2152       } catch(e) {
2153         JXG.debug("* <b>Err:</b> LineBiSector (Mittelsenkrechte) " + attr.name +"<br>\n");
2154         return false;
2155       }
2156     break;
2157     case 'ray':
2158       attr = JXG.GeogebraReader.boardProperties(gxtEl, element, attr);
2159       attr = JXG.GeogebraReader.colorProperties(element, attr);
2160       gxtEl = JXG.GeogebraReader.coordinates(gxtEl, element);
2161       attr = JXG.GeogebraReader.visualProperties(element, attr);
2162 
2163       try {
2164         JXG.debug("* <b>Ray:</b> First: " + input[0].name + "<br>\n");
2165         attr.straightFirst = true;
2166         attr.straightLast =  false;
2167         p = board.create('line', [input[1], input[0]], attr);
2168         return p;
2169       } catch(e) {
2170         JXG.debug("* <b>Err:</b> Ray " + attr.name +"<br>\n");
2171         return false;
2172       }
2173     break;
2174     case 'tangent':
2175       attr = JXG.GeogebraReader.boardProperties(gxtEl, element, attr);
2176       attr = JXG.GeogebraReader.colorProperties(element, attr);
2177       gxtEl = JXG.GeogebraReader.coordinates(gxtEl, element);
2178       attr = JXG.GeogebraReader.visualProperties(element, attr);
2179 
2180       try {
2181         JXG.debug("* <b>Tangent:</b> First: " + input[0].name + ", Sec.: "+ input[1].name +"("+ input[1].type +")<br>\n");
2182         switch(input[1].type) {
2183           case 1330923344: // graph
2184             input[0].makeGlider(input[1]);
2185             p = board.create('tangent', [input[0]], attr);
2186             return p;
2187           break;
2188           case 1330922316: // circle 0x4F54434C
2189           case 1330922319: // conic 0x4F54434F
2190             /*
2191             m = function(circ) {
2192 	        return [[circ.midpoint.X()*circ.midpoint.X()+circ.midpoint.Y()*circ.midpoint.Y()-circ.Radius()*circ.Radius(),
2193 	                     -circ.midpoint.X(),-circ.midpoint.Y()],
2194 	                    [-circ.midpoint.X(),1,0],
2195 	                    [-circ.midpoint.Y(),0,1]
2196 	                   ];
2197 	            };
2198 
2199 	        t = board.create('line', [
2200 	                    function(){ return JXG.Math.matVecMult(m(input[1]), input[0].coords.usrCoords)[0]; },
2201 	                    function(){ return JXG.Math.matVecMult(m(input[1]), input[0].coords.usrCoords)[1]; },
2202 	                    function(){ return JXG.Math.matVecMult(m(input[1]), input[0].coords.usrCoords)[2]; }
2203 	                ], {visible: false});
2204                      */
2205             // input[0]: point
2206             // input[1]: circle or conic
2207             var pol = board.create('polar',[input[1],input[0]],{visible:false});
2208 	        var i1 = board.create('intersection', [input[1], pol, 0], {visible: false});
2209 	        var i2 = board.create('intersection', [input[1], pol, 1], {visible: false});
2210 	        var t1 = board.create('line', [input[0], i1], attr);
2211             var attr2 = {}
2212             attr2 = JXG.GeogebraReader.colorProperties(output[1], attr2);
2213             attr2 = JXG.GeogebraReader.visualProperties(output[1], attr2);
2214             attr2.name = output[1].getAttribute('label');
2215             var t2 = board.create('line', [input[0], i2], attr2);
2216             board.ggbElements[attr2.name] = t2;
2217             return [t1, t2];
2218           break;
2219         }
2220       } catch(e) {
2221         JXG.debug("* <b>Err:</b> Tangent " + attr.name +" "+ attr2.name + "<br>\n");
2222         return false;
2223       }
2224     break;
2225     case 'circumcirclearc':
2226       attr = JXG.GeogebraReader.boardProperties(gxtEl, element, attr);
2227       attr = JXG.GeogebraReader.colorProperties(element, attr);
2228       gxtEl = JXG.GeogebraReader.coordinates(gxtEl, element);
2229       attr = JXG.GeogebraReader.visualProperties(element, attr);
2230 
2231       try {
2232         JXG.debug("* <b>CircumcircleArc:</b> First: " + input[0].name + "<br>\n");
2233         p = board.create('circumcirclearc', input, attr);
2234         return p;
2235       } catch(e) {
2236         JXG.debug("* <b>Err:</b> CircumcircleArc " + attr.name +"<br>\n");
2237         return false;
2238       }
2239     break;
2240     case 'circumcirclesector':
2241       attr = JXG.GeogebraReader.boardProperties(gxtEl, element, attr);
2242       attr = JXG.GeogebraReader.colorProperties(element, attr);
2243       gxtEl = JXG.GeogebraReader.coordinates(gxtEl, element);
2244       attr = JXG.GeogebraReader.visualProperties(element, attr);
2245 
2246       try {
2247         JXG.debug("* <b>CircumcircleSector:</b> First: " + input[0].name + "<br>\n");
2248         p = board.create('circumcirclesector', [input[0], input[1], input[2]], attr); //{name:attr['name']});
2249         /*
2250         p.arc.setProperty(attr);
2251         p.lines[0].setProperty(attr);
2252         p.lines[1].setProperty(attr);
2253         p.arc.visProp['highlightStrokeWidth'] = (1*p.arc.visProp['strokeWidth'].substr(0,p.arc.visProp['strokeWidth'].length-2)+1)+'px';
2254         p.lines[0].visProp['highlightStrokeWidth'] = (1*p.lines[0].visProp['strokeWidth'].substr(0,p.lines[0].visProp['strokeWidth'].length-2)+1)+'px';
2255         p.lines[1].visProp['highlightStrokeWidth'] = (1*p.lines[1].visProp['strokeWidth'].substr(0,p.lines[1].visProp['strokeWidth'].length-2)+1)+'px';
2256         p.arc.hasPoint = p.arc.hasPointSector;
2257         p.arc.highlight = (function(el){ return function() {
2258             this.board.renderer.highlight(this);
2259             this.board.renderer.highlight(el.lines[0]);
2260             this.board.renderer.highlight(el.lines[1]);
2261         };})(p);
2262         p.arc.noHighlight = (function(el){ return function() {
2263             this.board.renderer.noHighlight(this);
2264             this.board.renderer.noHighlight(el.lines[0]);
2265             this.board.renderer.noHighlight(el.lines[1]);
2266         };})(p);
2267         p.lines[0].highlight = (function(el){ return function() {
2268             this.board.renderer.highlight(this);
2269             this.board.renderer.highlight(el.arc);
2270             this.board.renderer.highlight(el.lines[1]);
2271         };})(p);
2272         p.lines[1].highlight = (function(el){ return function() {
2273             this.board.renderer.highlight(this);
2274             this.board.renderer.highlight(el.arc);
2275             this.board.renderer.highlight(el.lines[0]);
2276         };})(p);
2277         p.lines[0].noHighlight = (function(el){ return function() {
2278             this.board.renderer.noHighlight(this);
2279             this.board.renderer.noHighlight(el.arc);
2280             this.board.renderer.noHighlight(el.lines[1]);
2281         };})(p);
2282         p.lines[1].noHighlight = (function(el){ return function() {
2283             this.board.renderer.noHighlight(this);
2284             this.board.renderer.noHighlight(el.arc);
2285             this.board.renderer.noHighlight(el.lines[0]);
2286         };})(p);
2287         */
2288         return p;
2289       } catch(e) {
2290         JXG.debug("* <b>Err:</b> CircumcircleSector " + attr.name +"<br>\n");
2291         return false;
2292       }
2293     break;
2294     case 'semicircle':
2295       attr = JXG.GeogebraReader.boardProperties(gxtEl, element, attr);
2296       attr = JXG.GeogebraReader.colorProperties(element, attr);
2297       gxtEl = JXG.GeogebraReader.coordinates(gxtEl, element);
2298       attr = JXG.GeogebraReader.visualProperties(element, attr);
2299 
2300       try {
2301         JXG.debug("* <b>Semicircle:</b> First: " + input[0].name + "<br>\n");
2302         p = board.create('semicircle', [input[0], input[1]], attr);
2303         return p;
2304       } catch(e) {
2305         JXG.debug("* <b>Err:</b> Semicircle " + attr.name +"<br>\n");
2306         return false;
2307       }
2308     break;
2309     case 'angle':
2310       attr = JXG.GeogebraReader.boardProperties(gxtEl, element, attr);
2311       attr = JXG.GeogebraReader.colorProperties(element, attr);
2312       gxtEl = JXG.GeogebraReader.coordinates(gxtEl, element);
2313       attr = JXG.GeogebraReader.visualProperties(element, attr);
2314 
2315       try {
2316         JXG.debug("* <b>Angle:</b> First: " + input[0].name + "<br>\n");
2317         p = board.create('angle', input, attr);
2318         return p;
2319       } catch(e) {
2320         JXG.debug("* <b>Err:</b> Angle " + attr.name +"<br>\n");
2321         return false;
2322       }
2323     break;
2324     case 'angularbisector':
2325       attr = JXG.GeogebraReader.boardProperties(gxtEl, element, attr);
2326       attr = JXG.GeogebraReader.colorProperties(element, attr);
2327       gxtEl = JXG.GeogebraReader.coordinates(gxtEl, element);
2328       attr = JXG.GeogebraReader.visualProperties(element, attr);
2329       attr.straightFirst = true;
2330       attr.straightLast = true;
2331 
2332       try {
2333         JXG.debug("* <b>Angularbisector:</b> First: " + input[0].name + "<br>\n");
2334         p = board.create('bisector', input, attr);
2335         return p;
2336       } catch(e) {
2337         JXG.debug("* <b>Err:</b> Angularbisector " + attr.name +"<br>\n");
2338         return false;
2339       }
2340     break;
2341     case 'numeric':
2342     if(element.getElementsByTagName('slider').length == 0) {
2343       // auxiliary doesn't exist in every numeric
2344       //element.getElementsByTagName('auxiliary').length != 0 && element.getElementsByTagName('auxiliary')[0].attributes['val'].value == 'true') {
2345       exp = JXG.GeogebraReader.getElement(element.getAttribute('label'), true);
2346       if(exp) {
2347     	  exp = exp.getAttribute('exp');
2348     	  exp = JXG.GeogebraReader.functionParse('', exp);
2349     	  exp = JXG.GeogebraReader.ggbParse(exp);
2350       }
2351       board.ggb[attr.name] = new Function('return '+ exp +';');
2352       JXG.debug('value: '+ board.ggb[attr.name]());
2353       return board.ggb[attr.name];
2354 	} else {
2355       attr = JXG.GeogebraReader.boardProperties(gxtEl, element, attr);
2356       attr = JXG.GeogebraReader.colorProperties(element, attr);
2357       // gxtEl = JXG.GeogebraReader.coordinates(gxtEl, element);
2358       attr = JXG.GeogebraReader.visualProperties(element, attr);
2359       if(element.getElementsByTagName('slider').length == 1) { // it's a slider
2360         sx = parseFloat(element.getElementsByTagName('slider')[0].getAttribute('x'));
2361         sy = parseFloat(element.getElementsByTagName('slider')[0].getAttribute('y'));
2362         length = parseFloat(element.getElementsByTagName('slider')[0].getAttribute('width'));
2363         // are coordinates absolut?
2364         if(element.getElementsByTagName('slider')[0].getAttribute('absoluteScreenLocation') && element.getElementsByTagName('slider')[0].getAttribute('absoluteScreenLocation') == 'true') {
2365           var tmp = new JXG.Coords(JXG.COORDS_BY_SCREEN, [sx, sy], board);
2366           sx = tmp.usrCoords[1];
2367           sy = tmp.usrCoords[2];
2368         }
2369 
2370         if(element.getElementsByTagName('slider')[0].getAttribute('horizontal') == 'true') {
2371           if(element.getElementsByTagName('slider')[0].getAttribute('absoluteScreenLocation') && element.getElementsByTagName('slider')[0].getAttribute('absoluteScreenLocation') == 'true')
2372           length /= (board.unitX*board.zoomX);
2373           ex = sx + length;
2374           ey = sy;
2375         } else {
2376           if(element.getElementsByTagName('slider')[0].getAttribute('absoluteScreenLocation') && element.getElementsByTagName('slider')[0].getAttribute('absoluteScreenLocation') == 'true')
2377           length /= (board.unitY*board.zoomY);
2378           ex = sx;
2379           ey = sy + length;
2380         }
2381 
2382         (element.getElementsByTagName('animation')[0]) ? attr.snapWidth = parseFloat(element.getElementsByTagName('animation')[0].getAttribute('step')) : false;
2383 
2384         try {
2385           JXG.debug("* <b>Numeric:</b> First: " + attr.name + "<br>\n");
2386           attr['withTicks'] = false;
2387           p = board.create('slider', [[sx,sy], [ex,ey], [parseFloat(element.getElementsByTagName('slider')[0].getAttribute('min')),
2388                                                          parseFloat(element.getElementsByTagName('value')[0].getAttribute('val')),
2389                                                          parseFloat(element.getElementsByTagName('slider')[0].getAttribute('max'))]], attr);
2390           p.setProperty({withLabel:false});
2391           return p;
2392         } catch(e) {
2393           JXG.debug("* <b>Err:</b> Numeric " + attr.name +"<br>\n");
2394           return false;
2395         }
2396       }
2397     }
2398     break;
2399     case 'midpoint':
2400       attr = JXG.GeogebraReader.boardProperties(gxtEl, element, attr);
2401       attr = JXG.GeogebraReader.colorProperties(element, attr);
2402       gxtEl = JXG.GeogebraReader.coordinates(gxtEl, element);
2403       attr = JXG.GeogebraReader.visualProperties(element, attr);
2404 
2405       try {
2406           if(!JXG.exists(attr.styleGGB)) {
2407              attr.face = 'circle';
2408              attr.fillColor = attr.strokeColor;
2409              attr.fillOpacity = 1;
2410              attr.highlightFillColor = attr.strokeColor;
2411              attr.highlightFillOpacity = 1;
2412              attr.strokeColor = 'black';
2413              attr.strokeWidth = '1px';
2414           }
2415           p = board.create('midpoint', input, attr);
2416           JXG.debug("* <b>Midpoint ("+ p.id +"):</b> "+ attr.name + "("+ gxtEl.x +", "+ gxtEl.y +")<br>\n");
2417           return p;
2418       } catch(e) {
2419           JXG.debug("* <b>Err:</b> Midpoint " + attr.name +"<br>\n");
2420           return false;
2421       }
2422     break;
2423     case 'center':
2424       attr = JXG.GeogebraReader.boardProperties(gxtEl, element, attr);
2425       attr = JXG.GeogebraReader.colorProperties(element, attr);
2426       gxtEl = JXG.GeogebraReader.coordinates(gxtEl, element);
2427       attr = JXG.GeogebraReader.visualProperties(element, attr);
2428       try {
2429           if(!JXG.exists(attr.styleGGB)) {
2430              attr.face = 'circle';
2431              attr.fillColor = attr.strokeColor;
2432              attr.fillOpacity = 1;
2433              attr.highlightFillColor = attr.strokeColor;
2434              attr.highlightFillOpacity = 1;
2435              attr.strokeColor = 'black';
2436              attr.strokeWidth = '1px';
2437           }
2438           p = board.create('point', [function() { return JXG.getReference(board, input[0].id).midpoint.X(); },
2439                                      function() { return JXG.getReference(board, input[0].id).midpoint.Y(); }], attr);
2440           JXG.debug("* <b>Center ("+ p.id +"):</b> "+ attr.name + "("+ gxtEl.x +", "+ gxtEl.y +")<br>\n");
2441           return p;
2442       } catch(e) {
2443           JXG.debug("* <b>Err:</b> Center " + attr.name +"<br>\n");
2444           return false;
2445       }
2446     break;
2447     case 'function':
2448       attr = JXG.GeogebraReader.boardProperties(gxtEl, element, attr);
2449       attr = JXG.GeogebraReader.colorProperties(element, attr);
2450       gxtEl = JXG.GeogebraReader.coordinates(gxtEl, element);
2451       attr = JXG.GeogebraReader.visualProperties(element, attr);
2452 
2453       if(JXG.GeogebraReader.getElement(attr.name, true)) {
2454         func = JXG.GeogebraReader.getElement(attr.name, true).getAttribute('exp');
2455         func = JXG.GeogebraReader.functionParse('c', func);
2456       } else {
2457         func = input[0];
2458         func = JXG.GeogebraReader.functionParse('s', func);
2459       }
2460 
2461       JXG.debug(func);
2462 
2463       length = func.length;
2464       func[func.length-1] = 'return '+ JXG.GeogebraReader.ggbParse(func[func.length-1]) +';';
2465 
2466       JXG.debug(func);
2467 
2468       range = [(input && input[1]) ? input[1] : null, (input && input[2]) ? input[2] : null];
2469 
2470       try {
2471         if(length == 1)
2472           p = board.create('functiongraph', [new Function(func[0]), range[0], range[1]], attr);
2473         else if(length==2)
2474           p = board.create('functiongraph', [new Function(func[0], func[1]), range[0], range[1]], attr);
2475         else if(length==3)
2476           p = board.create('functiongraph', [new Function(func[0], func[1], func[2]), range[0], range[1]], attr);
2477         else if(length==4)
2478           p = board.create('functiongraph', [new Function(func[0], func[1], func[2], func[3]), range[0], range[1]], attr);
2479         else if(length==5)
2480           p = board.create('functiongraph', [new Function(func[0], func[1], func[2], func[3], func[4]), range[0], range[1]], attr);
2481         return p;
2482       } catch(e) {
2483         JXG.debug("* <b>Err:</b> Functiongraph " + attr.name +"<br>\n");
2484         return false;
2485       }
2486 
2487      break;
2488      case 'polar':
2489       attr = JXG.GeogebraReader.boardProperties(gxtEl, element, attr);
2490       attr = JXG.GeogebraReader.colorProperties(element, attr);
2491       gxtEl = JXG.GeogebraReader.coordinates(gxtEl, element);
2492       attr = JXG.GeogebraReader.visualProperties(element, attr);
2493 
2494       try {
2495         JXG.debug("* <b>Polar:</b> First: " + input[0].name + ", Sec.: "+ input[1].name +"<br>\n");
2496         p = board.create('polar', input, attr);
2497         return p;
2498       } catch(e) {
2499         JXG.debug("* <b>Err:</b> Polar " + attr.name +"<br>\n");
2500         return false;
2501       }
2502     break;
2503     case 'slope':
2504      attr = JXG.GeogebraReader.boardProperties(gxtEl, element, attr);
2505      attr = JXG.GeogebraReader.colorProperties(element, attr);
2506      gxtEl = JXG.GeogebraReader.coordinates(gxtEl, element);
2507      attr = JXG.GeogebraReader.visualProperties(element, attr);
2508 
2509      try {
2510        JXG.debug("* <b>Slope ("+ attr.name +"):</b> First: " + input[0].name +"<br>\n");
2511        var slopeWidth = parseInt(attr.slopeWidth) || 1.0;
2512        var p1 = input[0].glider || input[0].point1;
2513        var p2 = board.create('point',[function(){return (slopeWidth+p1.X());}, function(){return p1.Y();}], {visible: false});
2514        var l1 = board.create('segment', [p1, p2], {visible: false}); // visible: attr.visible
2515        var l2 = board.create('normal', [l1, l1.point2], {visible: false}); // visible attr.visible
2516        var i  = board.create('intersection', [input[0], l2, 0], {visible: false});
2517        var m  = board.create('midpoint', [l1.point2, i], {visible: false});
2518 
2519        var t = board.create('text', [function(){return m.X();}, function(){return m.Y();},
2520                       function(){ return "  " + (slopeWidth > 1 ? slopeWidth.toString() : "") + " " + this.name + " = " + JXG.trimNumber((slopeWidth * input[0].getSlope()).toFixed(JXG.GeogebraReader.decimals)); }], attr);
2521        attr.name = "";
2522        var t2 = board.create('text', [function(){return (p1.X() + p2.X())/2.;}, function(){return p1.Y();},
2523                                      function(){ return "<br/>" + slopeWidth; }], attr);
2524        t.Value = (function() { return function(){ return input[0].getSlope(); }; })();
2525        var poly = board.create('polygon',[p1,p2,i], attr);
2526 
2527        poly.borders[2].setProperty({visible: false});
2528        poly.borders[0].setProperty({strokeColor: attr.fillColor, strokeWidth: attr.strokeWidth, highlightStrokeColor: attr.fillColor, dash:attr.dash});
2529        poly.borders[1].setProperty({strokeColor: attr.fillColor, strokeWidth: attr.strokeWidth, highlightStrokeColor: attr.fillColor, dash:attr.dash});       
2530        return t;
2531      } catch(e) {
2532        JXG.debug("* <b>Err:</b> Slope " + attr.name +"<br>\n");
2533        return false;
2534      }
2535     break;
2536     case 'text':
2537      attr = JXG.GeogebraReader.boardProperties(gxtEl, element, attr);
2538      attr = JXG.GeogebraReader.colorProperties(element, attr);
2539      gxtEl = JXG.GeogebraReader.coordinates(gxtEl, element);
2540      attr = JXG.GeogebraReader.visualProperties(element, attr);
2541      var rx, res = '';
2542 
2543      try {
2544        if(element.getElementsByTagName('isLaTeX')[0] && element.getElementsByTagName('isLaTeX')[0].getAttribute('val') == 'true') {
2545          JXG.GeogebraReader.board.options.text.useASCIIMathML = true;
2546          t = JXG.GeogebraReader.getElement(attr.name, true).getAttribute('exp');
2547 
2548          // here we're searching for patterns like
2549          //    " + ... + "
2550          // ... will be sent to the ggbParser and a calculated text element is built from this.
2551          while(rx = t.match(/(.*?)" \+ (.+) \+ "(.*)/)) {
2552              var re2 = JXG.GeogebraReader.ggbParse(RegExp.$2);
2553              if (typeof re2 == 'string') {
2554                res = res + RegExp.$1 + re2;
2555              } else {
2556                res = res + RegExp.$1 + '" + JXG.trimNumber((' + re2 + ').toFixed(JXG.GeogebraReader.decimals)) + "';
2557              }
2558              t = RegExp.$3;
2559          }
2560          // we have to look, if the string's ending with a string-part or a formula part:
2561          if(rx = t.match(/(.*?)" \+ (.+)/)) {
2562              res = res + RegExp.$1 + '" + JXG.trimNumber((' + JXG.GeogebraReader.ggbParse(RegExp.$2) + ').toFixed(JXG.GeogebraReader.decimals))';
2563          } else
2564              res = res + t;
2565 
2566          JXG.debug("Text: "+res);
2567 
2568          p = board.create('text', [gxtEl.x, gxtEl.y, new Function('return ' + res + ';')], attr);
2569        } else {
2570          JXG.debug(JXG.GeogebraReader.getElement(attr.name, true).getAttribute('exp'));
2571          t = JXG.GeogebraReader.ggbParse(JXG.GeogebraReader.functionParse(false, JXG.GeogebraReader.getElement(attr.name, true).getAttribute('exp')));
2572          JXG.debug(t[1]);
2573          p = board.create('text', [gxtEl.x, gxtEl.y, new Function('return '+t[0]+' + " " + JXG.trimNumber(parseFloat(' + t[1] +').toFixed(JXG.GeogebraReader.decimals));') ], attr);
2574        }
2575        JXG.debug("* <b>Text:</b> " + t  +"<br>\n");
2576        return p;
2577      } catch(e) {
2578       JXG.debug("* <b>Err:</b> Text: " + t +"<br>\n");
2579       return false;
2580      }
2581     break;
2582     case 'root':
2583         attr = JXG.GeogebraReader.boardProperties(gxtEl, element, attr);
2584         attr = JXG.GeogebraReader.colorProperties(element, attr);
2585         gxtEl = JXG.GeogebraReader.coordinates(gxtEl, element);
2586         attr = JXG.GeogebraReader.visualProperties(element, attr);
2587         //JXG.debug(JXG.getReference(board, gxtEl.id));
2588 
2589         for(var i=0; i<output.length; i++) {
2590           output[i] = JXG.GeogebraReader.checkElement(output[i].getAttribute('label'));
2591         }
2592         
2593         var inp;
2594         if(JXG.isArray(input)) {
2595             inp = input[0];
2596         } else {
2597             inp = input;
2598         }
2599 
2600         // At this point, the output points already exist. 
2601         // Bind the root function to all output elements.
2602         // The start values for all output elements are the x-coordinates as given
2603         // in the ggb file.
2604         for(i=0; i<output.length; i++) {
2605             output[i].addConstraint([
2606                     (function(x){ return function(){ return board.root(inp.Y,x,inp);}; })(output[i].X()), 
2607                     function(){ return 0;}
2608                 ]);
2609         }
2610         //var p = board.create('point', [function(){ return board.root(output);}, function(){ return 1;}], attr);
2611         return output; // What to return here????
2612     break;
2613   case 'integral':
2614       attr = JXG.GeogebraReader.boardProperties(gxtEl, element, attr);
2615       attr = JXG.GeogebraReader.colorProperties(element, attr);
2616       gxtEl = JXG.GeogebraReader.coordinates(gxtEl, element);
2617       attr = JXG.GeogebraReader.visualProperties(element, attr);
2618 
2619       try {
2620         JXG.debug("* <b>Integral:</b> First: " + input[0].name + ", Sec.: "+ input[1].name +", Thir.: "+ input[2].name +"<br>\n");
2621         JXG.debug([input[1](), input[2]()]);
2622         var p = board.create('integral', [JXG.getRef(board, input[0]), [input[1], input[2]]], attr);
2623         return p;
2624       } catch(e) {
2625         JXG.debug("* <b>Err:</b> Integral " + attr.name + e + "<br>\n");
2626         return false;
2627       }
2628     break;
2629 
2630 // case 'transform':
2631 // break;
2632 //    case 'radius':
2633 //    break;
2634 //    case 'derivative':
2635 //    break;
2636 //    case 'root':
2637 //    break;
2638 //    case 'corner':
2639 //    break;
2640 //    case 'unitvector':
2641 //    break;
2642 //    case 'extremum':
2643 //    break;
2644 //    case 'turningpoint':
2645 //    break;
2646 //    case 'arc':
2647 //    break;
2648 //    case 'circlepart':
2649 //    break;
2650 //    case 'uppersum':
2651 //    break;
2652 //    case 'lowersum':
2653 //    break;
2654 //    case 'image':
2655 //    break;
2656     default:
2657       return false;
2658     break;
2659   }
2660 };
2661 
2662 /**
2663  * Reading the elements of a geogebra file
2664  * @param {Object} board board object
2665  */
2666 this.readGeogebra = function(tree, board) {
2667   var el, Data, i, els = [], expr;
2668 
2669   board.ggbElements = [];
2670   board.ggb = {};
2671   JXG.GeogebraReader.tree = tree;
2672   JXG.GeogebraReader.board = board;
2673   JXG.GeogebraReader.format = parseFloat(JXG.GeogebraReader.tree.getElementsByTagName('geogebra')[0].getAttribute('format'));
2674   JXG.GeogebraReader.decimals = parseInt(JXG.GeogebraReader.tree.getElementsByTagName('geogebra')[0].getElementsByTagName('kernel')[0].getElementsByTagName('decimals')[0].getAttribute('val'));
2675   JXG.GeogebraReader.writeBoard(board);
2676   board = JXG.GeogebraReader.setDefaultOptions(board);
2677 
2678   // speeding up the drawing process
2679   //board.suspendUpdate();
2680 
2681   var constructions = JXG.GeogebraReader.tree.getElementsByTagName("construction");
2682   for (var t=0; t<constructions.length; t++) {
2683 
2684     var cmds = constructions[t].getElementsByTagName("command");
2685     for (var s=0; s<cmds.length; s++) {
2686       Data = cmds[s];
2687 
2688       // JXG.debug('now i\'ll parse the command:');
2689       // JXG.debug(Data);
2690 
2691       var input = [];
2692       for (i=0; i<Data.getElementsByTagName("input")[0].attributes.length; i++) {
2693         el = Data.getElementsByTagName("input")[0].attributes[i].value;
2694         if(el.match(/\u00B0/) || !el.match(/\D/) || el.match(/Circle/) || Data.getAttribute('name') == 'Function' || el == parseFloat(el) ) {
2695           input[i] = el;
2696         // } else if(el.match(/[a-zA-Z]+\[[a-zA-Z0-9]+[a-zA-Z0-9,\ ]*\]/)) {
2697         //   input[i] = JXG.GeogebraReader.writeElement(board, )
2698         } else if(el == 'xAxis' || el == 'yAxis') {
2699           input[i] = board.ggbElements[el];
2700         } else {
2701           input[i] = JXG.GeogebraReader.checkElement(el);
2702         }
2703       };
2704 
2705       var output = [], elname = Data.getElementsByTagName("output")[0].attributes[0].value;
2706       for (i=0; i<Data.getElementsByTagName("output")[0].attributes.length; i++) {
2707         el = Data.getElementsByTagName("output")[0].attributes[i].value;
2708         output[i] = JXG.GeogebraReader.getElement(el);
2709       };
2710       if(typeof board.ggbElements[elname] == 'undefined' || board.ggbElements[elname] == '') {
2711         board.ggbElements[elname] = JXG.GeogebraReader.writeElement(board, output, input, Data.getAttribute('name').toLowerCase());
2712         // JXG.debug("regged: "+board.ggbElements[elname].id+"<br/>");
2713 
2714         /* register borders to according "parent" */
2715         if(board.ggbElements[elname].borders)
2716           for(var i=0; i<board.ggbElements[elname].borders.length; i++) {
2717             board.ggbElements[board.ggbElements[elname].borders[i].name] = board.ggbElements[elname].borders[i];
2718             // JXG.debug(i+") regged: "+board.ggbElements[elname].borders[i].name+"("+ board.ggbElements[board.ggbElements[elname].borders[i].name].id +")<br/>");
2719           };
2720       }
2721     };
2722 
2723     JXG.debug('Restesammler: ');
2724     // create "single" elements which do not depend on any other
2725     var elements = constructions[t].getElementsByTagName("element");
2726     for (var s=0; s<elements.length; s++) {
2727       var Data = elements[s];
2728       var el = Data.getAttribute('label');
2729 
2730       if(typeof board.ggbElements[el] == 'undefined' || board.ggbElements[el] == '') {
2731         board.ggbElements[el] = JXG.GeogebraReader.writeElement(board, Data);
2732 
2733         if(expr = JXG.GeogebraReader.getElement(el, true)) {
2734           var type = Data.getAttribute('type');
2735           switch(type) {
2736             case 'text':
2737             case 'function':
2738               // board.ggbElements[el] = JXG.GeogebraReader.writeElement(board.ggbElements, board, expr, false, type);
2739             break;
2740             default:
2741               JXG.GeogebraReader.ggbParse(expr.getAttribute('exp'), el);
2742             break;
2743           }
2744         }
2745 
2746       }
2747     };
2748 
2749   }; // end: for construction
2750 
2751   // speeding up the drawing process
2752   board.unsuspendUpdate();
2753 
2754   board.fullUpdate();
2755  // delete(board.ggbElements);
2756 };
2757 
2758 /**
2759  * Clean the utf8-symbols in a Geogebra expression in JavaScript syntax
2760  * @param {String} string to clean
2761  * @return {String} replaced string
2762  */
2763 this.utf8replace = function(exp) {
2764   exp = (exp.match(/\u03C0/)) ? exp.replace(/\u03C0/g, 'PI') : exp;
2765   exp = (exp.match(/\u00B2/)) ? exp.replace(/\u00B2/g, '^2') : exp;
2766   exp = (exp.match(/\u00B3/)) ? exp.replace(/\u00B3/g, '^3') : exp;
2767   exp = (exp.match(/\u225F/)) ? exp.replace(/\u225F/g, '==') : exp;
2768   exp = (exp.match(/\u2260/)) ? exp.replace(/\u2260/g, '!=') : exp;
2769   exp = (exp.match(/\u2264/)) ? exp.replace(/\u2264/g, '<=') : exp;
2770   exp = (exp.match(/\u2265/)) ? exp.replace(/\u2265/g, '>=') : exp;
2771   exp = (exp.match(/\u2227/)) ? exp.replace(/\u2227/g, '&&') : exp;
2772   exp = (exp.match(/\u2228/)) ? exp.replace(/\u2228/g, '//') : exp;
2773   return exp;
2774 };
2775 
2776 /**
2777  * Extracting the packed geogebra file in order to return the "blank" xml-tree for further parsing.
2778  * @param {String} archive containing geogebra.xml-file or raw input string (eg. xml-tree)
2779  * @return {String} content of geogebra.xml-file if archive was passed in
2780  */
2781 this.prepareString = function(fileStr, isString) {
2782     var i, bA, len, fstr;
2783 
2784     // here we have to deal with two different base64 encoded streams
2785     // first one: base64 encoded xml (geogebra's web export)
2786     // second one: base64 encoded ggb file, this is our recommendation for an IE & Opera
2787     // workaround, which can't deal with binary data transferred via AJAX.
2788 
2789     // first try to decode assuming we got a base64 encoded ggb file
2790     if(isString) {
2791         fstr = JXG.Util.Base64.decode(fileStr);
2792         if(fstr.slice(0,2)!=="PK") {
2793             // ooops, that was no ggb file. try again with utf8 parameter set.
2794             fstr = JXG.Util.Base64.decode(fileStr, true);
2795         }
2796         fileStr = fstr;
2797     }
2798 
2799     if (fileStr.indexOf('<') != 0) {
2800         bA = [];
2801         len = fileStr.length;
2802         for (i=0;i<len;i++)
2803             bA[i]=JXG.Util.asciiCharCodeAt(fileStr,i);
2804         // Unzip
2805         fileStr = (new JXG.Util.Unzip(bA)).unzipFile("geogebra.xml");
2806     }
2807     fileStr = JXG.Util.utf8Decode(fileStr);
2808     fileStr = JXG.GeogebraReader.utf8replace(fileStr);
2809     return fileStr;
2810 };
2811 
2812 /**
2813  * Checking if a parameter is a Geogebra vector (array with length 3)
2814  * @param {Object} possible Geogebra vector
2815  * @return {boolean}
2816  */
2817 this.isGGBVector = function(v){
2818 	return JXG.isArray(v) && v.length == 3 && v[0] == 1;	
2819 };
2820 }; // end: GeogebraReader()
2821