// Copyright (c) 2003, 2008 Four J's Development Tools.
// All Rights Reserved.
// Note that the modification of this file is not supported.
// For customizing with your own javascript and cascading style sheets
// please read the product documentation.
// 
// $Id: gwccore.js 40806 2008-08-12 09:56:52Z ff $
/////////////////////////////////////////////////////////////////////////////




gwc.sapi = {};

/////////////////////////////////////////////////////////////////////////////

//
gwc.tk = new function() {

	var _tk = this;
	var _win = window;


	_tk.platform = _win.navigator.platform.toLowerCase();

	_tk.isIe = parseFloat( _win.navigator.userAgent.substr( _win.navigator.userAgent.indexOf('MSIE') + 5 ) );

	_tk.isOpera = parseFloat( _win.navigator.userAgent.substr( _win.navigator.userAgent.indexOf('Opera') + 6 ) );
	_tk.isGecko = parseFloat( _win.navigator.userAgent.substr( _win.navigator.userAgent.indexOf('Gecko') + 6 ) );
	_tk.isKHTML = (_win.navigator.userAgent.indexOf('KHTML') != -1);


	_tk.Noop = function() {}
	
	_tk.Inherit = function(baseObj) { function tmp(){}; tmp.prototype = baseObj; return new tmp }

	_tk.AddObj = function(baseObj,obj) { for ( var p in obj ) baseObj[p] = obj[p] }
	
	_tk.HasProperty = function(obj) { if ( obj.__count__ ) return true; for ( var i in obj ) return true }
	
	_tk.FirstValue = function(c) { for ( var i in c ) return c[i] }
	
	_tk.FirstKey = function(c) { for ( var i in c ) return i }
	
	_tk.CompareArrays = function(a,b) { if ( a.length != b.length ) return false; for ( var i in a ) if ( a[i] != b[i] ) return false; return true }

	_tk.SetTimeout = function( fct, time ) { return _win.setTimeout(fct, time) }

	_tk.ClearTimeout = function( timeout ) { _win.clearTimeout(timeout) }

	_tk.SetInterval = function( fct, time ) { return _win.setInterval(fct, time) }

	_tk.ClearInterval = function( timeout ) { _win.clearInterval(timeout) }
	
	_tk.Defer = function( fct ) { _win.setTimeout(fct, 0) }
	
	_tk.DeferCall = function( fct, arg ) { var _this=this; _win.setTimeout( function(){ fct.apply(_this,arg) }, 0) }

	_tk.DeferCallObj = function( fct, obj, arg ) { _win.setTimeout( function(){ fct.apply(obj,arg) }, 0) }

	_tk.nbsp = String.fromCharCode(0xA0);

	_tk.MinMax = function( val, min, max ) { return val > max ? max : val < min ? min : val } 

	_tk.IsNumber = function( text ) {
	
		return /[+-]?\d*[\.,]?\d*/(text) != null;
	}

	_tk.FirstElement = function(e) {
		
		e = e.firstChild;
		while ( e && e.nodeType != 1 )
			e = e.nextSibling;
		return e;
	}

	_tk.LastElement = function(e) {

		e = e.lastChild;
		while ( e && e.nodeType != 1 )
			e = e.previousSibling;
		return e;
	}

	_tk.PreviousElement = function(e) {
	
		do { e = e.previousSibling } while ( e && e.nodeType != 1 );
		return e;
	}

	_tk.NextElement = function(e) {
		
		do { e = e.nextSibling } while ( e && e.nodeType != 1 );
		return e;
	}

	_tk.HasClass = function( elt, cl ) { return (' '+elt.className+' ').indexOf(' '+cl+' ') != -1 }

	_tk.AddClass = function( elt, cl ) { elt.className += ' '+cl+' ' }

	_tk.RemoveClass = function( elt, cl ) { 

		var eltcl = ' '+elt.className+' ';
		var cl = ' '+cl+' ';
		var pos = eltcl.lastIndexOf(cl);
		if ( pos != -1 )
			elt.className = eltcl.substr( 0, pos + 1 ) + eltcl.substr( pos + cl.length );
	}

	_tk.ToggleClass = function( elt, clList ) {
		
		var eltcl = ' '+elt.className+' ';
		for ( var i = 0; i < clList.length; i++ ) {
			
			var cl = ' '+clList[i]+' ';
			var pos = eltcl.lastIndexOf(cl);
			if ( pos != -1 ) {
				eltcl = eltcl.substr( 0, pos + 1 ) + clList[(i+1)%clList.length] + eltcl.substr( pos + cl.length );
				break;
			}
		}
		elt.className = eltcl;
	}
	
	_tk.SetClass = function( elt, polarity, cl ) {

		cl = ' '+cl+' ';
		var str = ' '+elt.className+' ';
		var pos = str.lastIndexOf(cl);
		if ( polarity != (pos != -1) )
			elt.className = polarity ? str + cl : str.substr( 0, pos + 1 ) + str.substr( pos + cl.length );
	}
	
	_tk.ClearClasses = function( elt, list ) {
		
		var _class = ' '+elt.className+' ';
		for ( var i in list ) {
			
			var cl = ' '+list[i]+' ';
			var pos = _class.lastIndexOf(cl);
			if ( pos != -1 )
				_class = _class.substr( 0, pos + 1 ) + _class.substr( pos + cl.length );
		}
		elt.className = _class;
	}


	if ( _tk.isIe )
		_tk.Contains = function( elt, innerElt ) { return elt && elt.contains(innerElt) }
	else
		_tk.Contains = function( elt, innerElt ) {
			for ( ; innerElt != document && innerElt != elt; innerElt = innerElt.parentNode );
			return innerElt == elt;
		}
	

	if ( _tk.isIe )
		_tk.SetHTMLElementAttribute = function( elt, name, value ) { 
			switch (name.toLowerCase()) {
				case 'style': elt.style.setAttribute('cssText', value); break;
				case 'class': name = 'className'; 
				default: elt.setAttribute( name, value, 0 );
			}
		}
	else
		_tk.SetHTMLElementAttribute = function( elt, name, value ) {
			if (name == 'value')
				elt.value = value;
			else
				elt.setAttribute( name, value );
		}


	if ( _tk.isIe )
		_tk.RemoveElementAttribute = function( elt, name ) { elt.removeAttribute( name.toLowerCase() == 'class' ? 'classname' : name, 0 ) }
	else
		_tk.RemoveElementAttribute = function( elt, name ) { elt.removeAttribute( name ) }


	_tk.RemoveElement = function(elt) { return elt.parentNode.removeChild(elt) }


	_tk.InsertBefore = function( element, reference ) { return reference.parentNode.insertBefore( element, reference ) }


	_tk.InsertAfter = function( element, reference ) { 
		var ns = reference.nextSibling;
		return ns ? reference.parentNode.insertBefore( element, ns ) : reference.parentNode.appendChild( element );
	}	



	if ( window.attachEvent ) 
		_tk.AddEvent = function ( elt, ev, fn ) { elt.attachEvent( 'on'+ev, fn ) }
	else
		_tk.AddEvent = function ( elt, ev, fn ) { elt.addEventListener( ev, fn, false ) }


	if ( window.detachEvent ) 
		_tk.RemoveEvent = function ( elt, ev, fn ) { elt.detachEvent( 'on'+ev, fn ) }
	else
		_tk.RemoveEvent = function ( elt, ev, fn ) { elt.removeEventListener( ev, fn, false ) }


	_tk.AddEventList = function(elt, evList, fn) { for ( var e in evList ) _tk.AddEvent(elt, evList[e], fn) }


	_tk.RemoveEventList = function(elt, evList, fn) { for ( var e in evList ) _tk.RemoveEvent(elt, evList[e], fn) }



	_tk.SetEvent = function(polarity, elt, evName, callback) {
		
		if ( polarity )
			_tk.AddEvent(elt, evName, callback);
		else
			_tk.RemoveEvent(elt, evName, callback);
	}


	_tk.SetEventEx = function( polarity, elt, evName, callback, arg ) {

		var eventInfo = elt.gEventInfo || (elt.gEventInfo={});
		var _this = this;
		
		if ( polarity ) {

			var inner = function(event) { callback.apply( _this, [event, elt].concat(arg) ) }
			eventInfo[evName] = inner;
			_tk.AddEvent( elt, evName, inner );
		} else {
			
			if ( eventInfo[evName] ) {
			
				_tk.RemoveEvent( elt, evName, eventInfo[evName] );
				delete eventInfo[evName];
			}




		}
	}
	

	if ( _tk.isIe || _tk.isOpera )
		_tk.EventKeyCode = function(ev) { return ev.type == 'keypress' ? 0 : ev.keyCode }
	else
		_tk.EventKeyCode = function(ev) { return ev.keyCode }


	if ( _tk.isIe || _tk.isOpera )
		_tk.EventChar = function(ev) { return String.fromCharCode(ev.type == 'keypress' ? ev.keyCode : 0) }
	else
		_tk.EventChar = function(ev) { return String.fromCharCode(ev.charCode) }


	if ( _tk.isIe )
		_tk.EventTarget = function(ev) { return ev.srcElement }
	else
		_tk.EventTarget = function(ev) { return ev.target }


	_tk.EventKeyModifiers = function(ev) { return (ev.shiftKey?1:0) + (ev.ctrlKey?2:0) + (ev.altKey?4:0) }


	if ( _tk.isIe )
		_tk.CancelEvent = function(event) {
			event.cancelBubble = true;
			event.returnValue = false;
			return false;
		}
  	else
		_tk.CancelEvent = function(event) {
			event.preventDefault();
			event.stopPropagation();
			return false;
		}


	if ( _tk.isIe )
		_tk.PreventDefault = function(event) {
			event.returnValue = true;
			return false;
		}
  	else
		_tk.PreventDefault = function(event) {
			event.preventDefault();
			return false;
		}


	if ( _tk.isIe )
		_tk.StopEventPropagation = function(event) { event.cancelBubble = true }
  	else
		_tk.StopEventPropagation = function(event) { event.stopPropagation() }


	_tk.acceleratorToKeycode = { RETURN:13, ENTER:13, SPACE:32, ESCAPE:27, TAB:9, BACKSPACE:8, UP:38, DOWN:40, LEFT:37, RIGHT:39, INSERT:45, DELETE:46, HOME:36, END:35, NEXT:34, PRIOR:33 }
	for ( var i = 0; i < 12; i++ ) 
		_tk.acceleratorToKeycode['F'+(i+1)] = 112 + i;


	_tk.SequenceStart = function(fct,timeout) {

		var timers = [];
		for ( var i=0; i<arguments.length; i+=2 ) timers.push(_win.setTimeout(arguments[i], arguments[i+1]));
		return timers;
	}


	 _tk.SequenceCancel = function(seq) {

		for ( var i in seq ) _win.clearTimeout(seq[i]);
		seq.splice(0); 
	}



	if ( _tk.isIe )
		_tk.PasteText = function( elt, text ) {

			
			var scrollPos = elt.scrollTop;
			var range = document.selection.createRange();
			range.text = text;
			range.select();
			if (scrollPos)
				elt.scrollTop = scrollPos;
		} 
	else
		_tk.PasteText = function( elt, text ) {

			var scrollPos = elt.scrollTop;
			var pos = elt.selectionStart + text.length;
			elt.value = elt.value.substring( 0, elt.selectionStart ) + text + elt.value.substring( elt.selectionEnd );
			elt.setSelectionRange(pos,pos);
			if (scrollPos)
				elt.scrollTop = scrollPos;
		}


	if ( _tk.isIe ) 
		_tk.GetCaret = function(elt) { 

			var range = document.selection.createRange();
			range.compareEndPoints('StartToEnd', range) != 0 && range.collapse(true);
			var bookmark = range.getBookmark();
			var start = bookmark.charCodeAt(2)-1-bookmark.charCodeAt(0);
			var range = document.selection.createRange();
			range.compareEndPoints('StartToEnd', range) != 0 && range.collapse(false);
			var bookmark = range.getBookmark();
			var end = bookmark.charCodeAt(2)-1-bookmark.charCodeAt(0);
			return { start:start, end:end };
		}
	else
		_tk.GetCaret = function(elt) {
			return { start:elt.selectionStart, end:elt.selectionEnd };
		}


	if ( _tk.isIe ) 
		_tk.SetCaret = function(elt, start, end) {
			var range = elt.createTextRange();
			range.collapse(true);
			range.moveStart('character', start);
			range.moveEnd('character', end - start);
			range.select();
		}
	else
		_tk.SetCaret = function(elt,start,end) {
			elt.setSelectionRange(start, end);
		}


	_tk.SafeSelect = function( elt ) { _win.setTimeout( function() { try { elt.select() } catch(ex) {} }, 0 ) }


	_tk.SafeFocus = function( elt ) { _win.setTimeout( function() { try { elt.focus() } catch(ex) {} }, 0 ) }


	_tk.SafeBlur = function( elt ) { try { elt.blur() } catch(ex) {} }


	_tk.UnselectField = function(elt) { var tmp = elt.value; elt.value=''; elt.value=tmp }
	

	_tk.AbsoluteX = function(o) { return o.offsetLeft + (o.offsetParent ? arguments.callee(o.offsetParent) : 0) } 


	_tk.AbsoluteY = function(o) { return o.offsetTop + (o.offsetParent ? arguments.callee(o.offsetParent) : 0) } 


	if ( _tk.isIe )
		_tk.OffsetX = function(o) { return o.offsetLeft + (o.offsetParent && o.parentNode && o.parentNode.currentStyle && o.parentNode.currentStyle.position != 'absolute' ? arguments.callee(o.offsetParent) : 0) }
	else
		_tk.OffsetX = function(o) { return o.offsetLeft }


	if ( _tk.isIe )
		_tk.OffsetY = function(o) { return o.offsetTop + (o.offsetParent && o.parentNode && o.parentNode.currentStyle && o.parentNode.currentStyle.position != 'absolute' ? arguments.callee(o.offsetParent) : 0) }
	else
		_tk.OffsetY = function(o) { return o.offsetTop }
	

	if ( _tk.isIe )
		_tk.DocumentHeight = function() { return document.documentElement.offsetHeight }
	else	
		_tk.DocumentHeight = function() { return document.documentElement.clientHeight }


	if ( _tk.isIe )
		_tk.DocumentWidth = function() { return document.documentElement.offsetWidth }
	else	
		_tk.DocumentWidth = function() { return document.documentElement.clientWidth }

	if ( document.body )
		_tk.GetBody = function() { return document.body }
	else
		_tk.GetBody = function() { return document.getElementsByTagName('body')[0] }
		

	if ( _tk.isIe ) 
		_tk.IdToElement = function(id) { var elt = window[id]; return elt && elt.id ? elt : document.getElementById(id) }
	else
		_tk.IdToElement = function(id) { return document.getElementById(id) }

	_tk.SetDOMAttributes = function( obj, attrList ) {

		for ( var name in attrList ) {

			var attr = attrList[name];
			attr instanceof Object ? _tk.SetDOMAttributes( obj[name], attr ) : obj[name] = attr;
		}
	}


	if ( _tk.isIe ) 
		_tk.CreateElement = function( eName, attrList ) {

			var elt = document.createElement( attrList && attrList['name'] ? '<'+eName+' name="'+attrList['name']+'">' : eName ); 
			attrList && _tk.SetDOMAttributes( elt, attrList );
			return elt;
		}
	else
		_tk.CreateElement = function( eName, attrList ) {

			var elt = document.createElement(eName);
			attrList && _tk.SetDOMAttributes( elt, attrList );
			return elt;
		}


	if ( _win.XMLHttpRequest ) 
		_tk.NewHttpRequest = function() { return new _win.XMLHttpRequest }
	else
		_tk.NewHttpRequest = function() { return new _win.ActiveXObject("Microsoft.XMLHTTP") } 

	if ( _tk.isIe ) { 

		_tk.HTMLToNodes = function(html) { 
		
			var tmpElt = document.createElement('div');
			switch ( html.substr(1,2).toLowerCase() ) {
				case 'tb': 
					tmpElt.innerHTML = '<table>'+html+'</table>';
					return tmpElt.firstChild;
				case 'tr':
					tmpElt.innerHTML = '<table><tbody>'+html+'</tbody></table>';
					return tmpElt.firstChild.firstChild;
				case 'td':
					tmpElt.innerHTML = '<table><tbody><tr>'+html+'</tr></tbody></table>';
					return tmpElt.firstChild.firstChild.firstChild;
				case 'op': 
					tmpElt.innerHTML = '<select>'+html+'</select>';
					return tmpElt.firstChild;
				default:
					tmpElt.innerHTML = html;
					return tmpElt;
			}		
		}
	} else {
	
		var htmlNamespaceInfo = '';
		var attr = document.documentElement.attributes;
		for ( var i = 0; i < attr.length; i++ )
			htmlNamespaceInfo += attr.item(i).nodeName+'="'+attr.item(i).nodeValue+'" ';
		
		var domParser = new DOMParser();
		function _CreateDoc(ml) {

			return domParser.parseFromString('<div '+htmlNamespaceInfo+'>' + ml + '</div>', 'application/xhtml+xml').documentElement; 
		}

		_tk.HTMLToNodes = function(html) { 

			var elt;		
			switch ( html.substr(1,2).toLowerCase() ) {
				case 'tb': 
					elt = _CreateDoc('<table>'+html+'</table>').firstChild;
					break;
				case 'tr':
					elt = _CreateDoc('<table><tbody>'+html+'</tbody></table>').firstChild.firstChild;
					break;
				case 'td':
					elt = _CreateDoc('<table><tbody><tr>'+html+'</tr></tbody></table>').firstChild.firstChild.firstChild;
					break;
				case 'op': 
					elt = _CreateDoc('<select>'+html+'</select>').firstChild;
					break;
				default:
					elt = _CreateDoc(html);
			}
			return document.importNode(elt, true);
		}
	}


	_tk.AppendContent = function( elt, html ) {

		var nodes = _tk.HTMLToNodes(html);
		while ( nodes.firstChild )
			elt.appendChild( nodes.firstChild );
	}


	_tk.InsertContent = function( elt, html ) {

		var nodes = _tk.HTMLToNodes(html);
		while ( nodes.firstChild )
			elt.parentNode.insertBefore( nodes.firstChild, elt );
	}


	_tk.InnerHTML = function( elt ) {

		if(_tk.isKHTML)
			return '<pre>'+
			       elt.innerHTML.replace(/[<>]/g,function(pStr,pP1,pOffset,pS){return(pStr=='<'?'&lt;':'&gt;')})+
			       '</pre>';
		return elt.innerHTML;
	}


	if ( _tk.isIe ) 
		_tk.Alpha = function(elt,a) { elt.style.filter = 'alpha(opacity='+(a*100)+')' }
	else
		_tk.Alpha = function(elt,a) { elt.style.opacity = a }




	if ( _tk.isIe ) 
		_tk.TextPast = function( elt, text ) {
			elt.focus(); 
			var range = document.selection.createRange();
			range.text = text;
			range.select(); 
		}
	else
		_tk.TextPast = function( elt, text ) {
			var pos = elt.selectionStart + text.length;
			elt.value = elt.value.substring( 0, elt.selectionStart ) + text + elt.value.substring( elt.selectionEnd );
			elt.setSelectionRange(pos,pos);
		}


	_tk.AppendTextNode = function( elt, text ) {

		return elt.appendChild(document.createTextNode(text)); 
	}


	if ( document.defaultView )
		_tk.GetStyle = function( elt, cssStyle ) {
		
			return document.defaultView.getComputedStyle(elt, null).getPropertyValue(cssStyle);
		}
	else
		_tk.GetStyle = function( elt, cssStyle ) {

			var sArray = cssStyle.split('-');
			var attrStyle = sArray[0];
			for( var i = 1, len = sArray.length; i < len; i++ ) {

			  var s = sArray[i];
			  attrStyle += s.charAt(0).toUpperCase() + s.substring(1);
			}
			return elt.currentStyle[attrStyle];
		}

	if ( _tk.isIe )		
		_tk.SetStyleElementText = function( elt, cssText ) {

			elt.styleSheet.cssText = cssText;
		}
	else if ( _tk.isKHTML )
		_tk.SetStyleElementText = function( elt, cssText ) {

			while(elt.firstChild) {
				elt.removeChild(elt.firstChild);
			}
			elt.appendChild(document.createTextNode(cssText));
		}
	else
		_tk.SetStyleElementText = function( elt, cssText ) {

			elt.innerHTML = cssText;
		}


	_tk.LocalDateStrings = function() {
		
		if ( gwc.cfg.localeDateStrings )
			return gwc.cfg.localeDateStrings;
		
		var splitter = /[, ]+/;
		stringDates:{
			
			if ( new Date().toLocaleDateString().indexOf(' ') == -1 ) 
				break stringDates;
			var mPos, dPos, list = { day:[], month:[] };
			var d1 = new Date(2006,1,3).toLocaleDateString().split(splitter), d2 = new Date(2006,2,3).toLocaleDateString().split(splitter);
			for ( var i in d1 )
				if( d1[i] != d2[i] )
					mPos = i;
				else if( d1[i] == d2[i] && isNaN(d1[i]) )
					dPos = i;
			if ( mPos == undefined || dPos == undefined )
				break stringDates;
			for ( var d=0; d<7; d++ )
				list.day.push(new Date(2006,9,d+1).toLocaleDateString().split(splitter)[dPos]);
			for ( var m=0; m<12; m++ )
				list.month.push(new Date(2006,m,1).toLocaleDateString().split(splitter)[mPos]);
			return list;
		}
		return { day:['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'], month:['January','February','March','April','May','June','July','August','September','October','November','December'] };
	}



	_tk.LocalFirstDayOfTheWeek = function() { 
		
		return ' fr fr-be fr-ca fr-ch fr-lu '.indexOf( ' '+navigator.userLanguage+' ' ) != -1 ? 1 : 0;
	}


	_tk.Movable = function( elt, onMove, gripper ) {

		var _ox, _oy;
		
		function Moving(event) {
			
			event = event||window.event;
			var pos = { x:event.clientX + _ox, y:event.clientY + _oy };
			onMove && onMove( pos );
			
			if ( pos.x != undefined )
				elt.style.left = pos.x + 'px';
			if ( pos.y != undefined )
				elt.style.top = pos.y + 'px';
		}

		function EndDrag(event) {

			_tk.RemoveEvent(document, 'mousemove', Moving);
			_tk.RemoveEvent(document, 'mouseup', EndDrag);
		}

		function StartDrag(event) {

			event = event||window.event;
			if ( !gripper || _tk.Contains( gripper, _tk.EventTarget(event) ) ) {

				_ox = elt.offsetLeft - event.clientX;
				_oy = elt.offsetTop - event.clientY;
				_tk.AddEvent(document, 'mousemove', Moving);
				_tk.AddEvent(document, 'mouseup', EndDrag);
				_tk.CancelEvent(event); 
			}
		}
		
		_tk.AddEvent(elt, 'mousedown', StartDrag);
		_tk.isIe && ( elt.onselectstart = function() { return false; } ); 
		return function() { _tk.RemoveEvent(elt, 'mousedown', StartDrag) }; 
	}
	
	_tk.Popup = function( _popup ) {
	
		var _visibility = false;
		_popup.style.display = 'none';
		_popup.style.position = 'absolute';
		'zIndex' in _tk.Popup ? _tk.Popup.zIndex++ : (_tk.Popup.zIndex = 2); 
		_popup.style.zIndex = _tk.Popup.zIndex;

		this.Align = function(x,y) {
			
			_popup.style.visibility = 'hidden';
			_visibility || (_popup.style.display='');
			
			switch (x) {
				case 'center':
					_popup.style.left = (_tk.DocumentWidth()/2 - _popup.clientWidth/2) + 'px';
					break;
				case 'left':
					_popup.style.left = 0 + 'px';
					break;
				case 'right':
					_popup.style.right = 0 + 'px';
					break;
			}

			switch (y) {
				case 'center':
					_popup.style.top = (_tk.DocumentHeight()/2-_popup.offsetHeight/2) + 'px';
					break;
				case 'top':
					_popup.style.top = 0 + 'px';
					break;
				case 'bottom':
					_popup.style.bottom = 0 + 'px';
					break;
			}

			_visibility || (_popup.style.display = 'none');
			_popup.style.visibility='';
			return this;
		}

		this.Resize = function(w,h) {

			w = w||_popup.clientWidth;
			h = h||_popup.clientHeight;
			var x = (_tk.DocumentWidth()/2-w/2);
			var y = (_tk.DocumentHeight()/2-h/2);
			_popup.style.left = x + 'px';
			_popup.style.top = y + 'px';
			_popup.style.width = w + 'px';
			_popup.style.height = h + 'px';
			return this;
		}
		
		this.Move = function(x,y) {
		
			_popup.style.left = x + 'px';
			_popup.style.top = y + 'px';
		}

		this.Visible = function(polarity) {
		
			if ( polarity != _visibility ) {

				_visibility = polarity;
				_popup.style.display = polarity ? '' : 'none';
			}
			return this;
		}
		
		this.Remove = function() {
			
			
		}
	}


	_tk.FrontLayer = function(elt) {
	
		var _visibility = false, _alpha, _layer;
		var _layer = _tk.CreateElement('span', { className:'gwcFrontLayer' } );
		
		function Resize() {
			
			_layer.style.left = elt.offsetLeft + 'px';
			_layer.style.top = elt.offsetTop + 'px';
			_layer.style.width = elt.offsetWidth + 'px'; 
			_layer.style.height = elt.offsetHeight + 'px'; 
		}

		function Alpha(alpha) {

			_alpha = alpha;
			_layer && _tk.Alpha(_layer,alpha);
		}

		this.elt = _layer;
		
		this.Alpha = function(a) { Alpha(a); return this }

		this.Fade = function(toAlpha, oncomplete) {

			var interval, steps = 16;
			clearInterval(interval);
			interval = setInterval( function() { Alpha(_alpha+(toAlpha-_alpha)/8); if (--steps<=0) { clearInterval(interval); oncomplete && oncomplete() } }, 50 );
		}

		this.Visible = function(polarity) { 
		
			if ( polarity != _visibility ) {

				_visibility = polarity;
				
				polarity ? _tk.GetBody().appendChild(_layer) : _tk.RemoveElement(_layer);
			}
			return this;
		}
		
		this.Remove = function() {

			
		}
	}
	
	
	_tk.ScrollBar = function(elt, wheelElt, onscroll) {

		var _sb, _size, _pageSize, _offset, _delay, _hasEvents;
		_sb = _tk.CreateElement( 'div', { style:{ visibility:'hidden', overflow:'scroll', overflowY:'scroll', overflowX:'hidden', width:'32px', height:'64px' } } ); 
		_sb.appendChild( _tk.CreateElement( 'div' ) );
		elt.appendChild(_sb);
		var sbWidth = _sb.offsetWidth - _sb.clientWidth + 0;
		_sb.style.width = sbWidth + 1 + 'px'; 
		_sb.style.height = elt.offsetHeight + (_tk.isOpera?sbWidth:0) + 'px'; 
		if ( !_tk.isOpera && !_tk.isIe )
			elt.style.marginRight = sbWidth + 'px';
		_sb.style.visibility = 'visible';

		var Update = this.Update = function() {
			
			if ( _size != undefined && _pageSize != undefined && _offset != undefined ) {

				if ( _pageSize >= _size && _offset > 0 ) {

					_sb.firstChild.style.height = (_sb.offsetHeight * (_pageSize+_offset) / _pageSize) + 'px';
					_sb.scrollTop = _sb.scrollHeight - _sb.offsetHeight;
				} else {

					_sb.firstChild.style.height = (_sb.offsetHeight * _size / _pageSize) + 'px';
					_sb.scrollTop = (_sb.scrollHeight - _sb.offsetHeight) * _offset / (_size - _pageSize);
				}
			}

		}

		this.Size = function(size) { _size = size }
		this.PageSize = function(pageSize) { _pageSize = pageSize }
		this.Offset = function(offset) { _offset = offset }
		this.Disable = function(polarity) {
			
			SetScrollbarEvents(!polarity);
			if ( polarity )
				_sb.firstChild.style.height = '0px';
			else
				Update();
		}
		
		function ProcessEvent(event,newOffset) {

			_tk.CancelEvent(event); 
			if ( newOffset == _offset || newOffset < 0 || (newOffset > _size - _pageSize && newOffset > _offset) )
				return;

			_offset = newOffset;
			Update();
			_win.clearTimeout(_delay);
			_delay = _win.setTimeout( function() { onscroll(_offset) }, 200 );
		}
		
		function OnScroll(ev) {

			if ( _sb.scrollHeight == _sb.offsetHeight ) 
				return;
			ProcessEvent(ev, Math.round(_sb.scrollTop * (_size - _pageSize) / (_sb.scrollHeight - _sb.offsetHeight)));
		}
		
		function OnWheel(ev) {
			
			var way = ev.detail ? ev.detail > 0 : ev.wheelDelta < 0;
			ProcessEvent(ev, _offset + (way ? 1: -1));
		}
		
		function SetScrollbarEvents(polarity) {
		
			if ( _hasEvents != polarity ) {
				
				_tk.SetEvent( polarity, _sb, 'scroll', OnScroll );
				_tk.SetEvent( polarity, wheelElt, _tk.isGecko ? 'DOMMouseScroll' : 'mousewheel', OnWheel );
				_tk.isOpera && _tk.SetEvent( polarity, _sb, 'mousewheel', OnWheel ); 
				_hasEvents = polarity;
			}
		}
		
		SetScrollbarEvents(true);
		
		this.Remove = function() {

			SetScrollbarEvents(false);
			_tk.RemoveElement( _sb );
		}
	}


	_tk.DateToFglFormat = function(date, format) {

		 return format.replace(/ddd|dd|mmm|mm|yyyy|yy/g, function(id) {

			switch(id) {
				case 'ddd' : return date.toUTCString().substr(0,3);
				case 'mmm' : return date.toUTCString().substr(8,3);
				case 'dd'  : return (date.getDate()<10?'0':'')+(date.getDate());
				case 'mm'  : return (date.getMonth()<9?'0':'')+(date.getMonth()+1);
				case 'yyyy': return date.getFullYear();
				case 'yy'  : return String(''+date.getFullYear()).substr(2);
			}
		 });
	}


	_tk.FglFormatToDate = function(text, format) {

		var date = new Date;
		var reg = /ddd|dd|mmm|mm|yyyy|yy/g;
		for (;;) {

			var res = reg.exec(format);
			if (!res)
				break;
			var last = reg.lastIndex;
			var id = res[0];
			var data = text.substring(last - id.length, last);
			if (!data)
				continue;
			switch (id) {
				case "dd":
					date.setDate(data);
					break;
				case "mmm":
					date.setMonth({Jan:0, Feb:1, Mar:2, Apr:3, May:4, Jun:5, Jul:6, Aug:7, Sep:8, Oct:9, Nov:10, Dec:11}[data]);
					break;
				case "mm":
					date.setMonth(data - 1);
					break;
				case "yyyy":
					date.setFullYear(data);
					break;
				case "yy":
					date.setFullYear("20" + data);
					break;
			}
		 }
		 return date;
	}


	_tk.DateToFglDbdate = function( date, dbdate ) {

		var sep = dbdate.charAt(dbdate.length-1), dateStr = '';
		for ( var i=0; i < dbdate.length-1; i++ ) {

			dateStr += i ? sep : '';
			switch ( dbdate.charAt(i) ) {
			case 'Y':
				dateStr += (dbdate.charAt(++i)=='4')?date.getFullYear():date.getFullYear()%100;
				break;
			case 'M':
				dateStr += date.getMonth() + 1;
				break;
			case 'D':
				dateStr += date.getDate();
				break;
			}
		}
		return dateStr;
   }


	_tk.FglDbdateToDate = function( dateStr, dbdate ) {

		var res = dateStr.match( /([0-9]*).([0-9]*).([0-9]*)/ );
		var date = new Date();
		if ( res && res.length == 4 && res[1] && res[2] && res[3] ) {

			for ( var i=0, j=1; i < dbdate.length-1; i++ )
				switch ( dbdate.charAt(i) ) {
				case 'Y':
					date.setFullYear( Number(res[j++]) + (dbdate.charAt(++i) == '4' ? 0 : 2000) );
					break;
				case 'M':
					date.setMonth( Number(res[j++]) -1 );
					break;
				case 'D':
					date.setDate( Number(res[j++]) );
					break;
			}
		}
		return date;
	}


	_tk.Calendar = function(container, dateString, firstDayOfWeek) { 
		
		var _this = this;
		var _date;
		var _cal = this.elt = _tk.CreateElement( 'table', { className:'gCalendar', style:{ visibility:'hidden' } } );
		
		container && container.appendChild(_cal);

		for ( var r = 0; r < 7; r++ )
			for ( var c = 0, row = _cal.insertRow(-1); c < 8; c++ ) {
				var td = row.insertCell(-1);
				_tk.AppendTextNode(td, '');
				c > 0 && r == 0 && (td.className = 'gDayName');
				r > 0 && c == 0 && (td.className = 'gWeek');
			}

		var thtd = _cal.createTHead().insertRow(-1).insertCell(-1);
		thtd.colSpan = 8;
		_tk.AppendTextNode(thtd, '');

		function Cell(x,y) { return _cal.rows[y].cells[x] }
		
		var header = Cell(0,0);
		
		var a = header.appendChild( _tk.CreateElement('a', {href:'#'}) );
		_tk.AppendTextNode( a, ' '+String.fromCharCode(171)+' ' );
		a.onmousedown = function() { _date.setYear(_date.getFullYear()-1); _this.Paint() }

		var yearText = _tk.AppendTextNode( header, '' );

		var a = header.appendChild( _tk.CreateElement('a', {href:'#'}) );
		_tk.AppendTextNode( a, ' '+String.fromCharCode(187)+' ' );
		a.onmousedown = function() { _date.setYear(_date.getFullYear()+1); _this.Paint() }

		_tk.AppendTextNode( header, _tk.nbsp + _tk.nbsp + _tk.nbsp );

		var a = header.appendChild( _tk.CreateElement('a', {href:'#'} ) );
		_tk.AppendTextNode( a, ' '+String.fromCharCode(171)+' ' );
		a.onmousedown = function() { _date.setMonth(_date.getMonth()-1); _this.Paint() }

		var monthText = _tk.AppendTextNode( header, '' );

		var a = header.appendChild( _tk.CreateElement('a', {href:'#'}) );
		_tk.AppendTextNode( a, ' '+String.fromCharCode(187)+' ' );
		a.onmousedown = function() { _date.setMonth(_date.getMonth()+1); _this.Paint() }

		_cal.style.visibility = 'visible';

      var tmp = new Date(), _today = new Date(tmp.getFullYear(), tmp.getMonth(), tmp.getDate() );

		_cal.onmousedown = _cal.onmouseup = _cal.ondblclick = function(event) {
			
			var event = event||window.event;
			target = _tk.EventTarget(event);
			if ( target.nodeName.toLowerCase() == 'td' && target.parentNode.parentNode.nodeName.toLowerCase() != 'thead' && target.firstChild ) {
				
				var data = Number(target.firstChild.data); 
				if ( data >= 1 && data <= 31 ) {

					_date.setDate( target.firstChild.data );
					_this.onEvent && _this.onEvent(_date, event.type);
				}
			}
		};

		this.Paint = function() {

			var year = _date.getFullYear(), month = _date.getMonth(), d = new Date(year,month,1);
			yearText.data = year;
			monthText.data = dateString.month[month].substr(0,3);
			d.setDate( 1 - d.getDay() + firstDayOfWeek );
			if ( d.getMonth() == month && d.getDate() > 1 ) d.setDate(d.getDate()-7); 
			for ( var r = 0; r < 6; r++ )
				for ( var c = 0; c < 7; c++ ) {
					
					var isCurrentMonth = d.getMonth() == month && d.getFullYear() == year;
					var cell = Cell(1+c, 2+r);
					_tk.SetClass(cell, d.getTime() == _date.getTime(), 'gSelectedDate');
					_tk.SetClass(cell, isCurrentMonth, 'gCurrentMonth');
					_tk.SetClass(cell, d.getTime() == _today.getTime(), 'gToday');
					_tk.SetClass(cell, (d.getDay()+1)%7 <= 1, 'gWeekEnd');

					cell.firstChild.data = isCurrentMonth ? d.getDate() : '';
					if ( c == 0 ) Cell(0, 2+r).firstChild.data = Math.floor(((d - new Date(year,0,1))/86400000 - d.getDay()+4)/7); 
					if ( r == 0 ) Cell(1+ c,1).firstChild.data = dateString.day[d.getDay()].substr(0,3);
					d.setDate(d.getDate()+1);
			}
		}
		
		this.SetDate = function(date) {

	      _date = new Date(date.getFullYear(), date.getMonth(), date.getDate());
	      if ( isNaN(_date.valueOf()) )
	      	_date = new Date();
			_this.Paint();
		}
		
		this.Remove = function() {
			
			_tk.RemoveElement(_cal);
		}
	}

	
	_tk.fglPicture = function( elt, picture, onEnd ) {
		
		
		var _pic = picture.split('');
		
		function MatchPicture(c,pos) {

			switch( _pic[pos] ) {
				case 'A': return c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z';
				case '#': return c >= '0' && c <= '9'; 
				case 'X': return true;
				default: return _pic[pos] == c;
			}
		}
		
		function IsStatic(pos) {
		
			if ( pos < 0 || pos >= picture.length ) return undefined;
			return '#AX'.indexOf(_pic[pos]) == -1;
		}
		
		function keydown(event) {

			var keycode = _tk.EventKeyCode(event);

			if ( keycode == 8 ) { //Backspace
				
				var pos = _tk.GetCaret(elt).start;
				var endpos = _tk.GetCaret(elt).end;
				var val = elt.value.split('');

				if(endpos-pos<2) { //Selection range of 0 or 1 char

				  while ( pos > 0 && IsStatic(--pos) );
				  val[pos] = ' ';
				}
				else { //Selection range of 2 or more chars

				  for(var i=pos; i<endpos; i++) {

				    if(!IsStatic(i))
				      val[i]=' ';
				  }
				}

				elt.value = val.join('');
				_tk.SetCaret(elt,pos,pos+1);

				_tk.CancelEvent(event);
			}
			
			else if ( keycode == 46 ) { //Delete
			
				var pos = _tk.GetCaret(elt).start;
				var endpos = _tk.GetCaret(elt).end;
				var val = elt.value.split('');

				if(pos!=endpos) {

				  for(var i=pos; i<endpos; i++) {

				    if(!IsStatic(i))
				      val[i] = ' ';
				  }

				  elt.value = val.join('');
				}

				_tk.SetCaret(elt,pos,pos+1);				
				_tk.CancelEvent(event);
			}

			else if ( keycode == 37 ) { //left arrow

				var pos = _tk.GetCaret(elt).start;

				if(event.shiftKey) {

					var endpos = _tk.GetCaret(elt).end;
					_tk.SetCaret(elt,pos-1,endpos);
				}
				else {

					if(pos>0)
						pos--;
					while(pos>0 && IsStatic(pos))
						pos--;

					_tk.SetCaret(elt,pos,pos+1);
				}

				_tk.CancelEvent(event);
			}

			else if ( keycode == 39 ) { //right arrow

				var pos = _tk.GetCaret(elt).start;

				if(event.shiftKey) {

					var endpos = _tk.GetCaret(elt).end;
					_tk.SetCaret(elt,pos,endpos+1);
				}
				else {

					if(pos<elt.value.length)
						pos++;
					while(pos<elt.value.length && IsStatic(pos))
						pos++;

					_tk.SetCaret(elt,pos,pos+1);
				}

				_tk.CancelEvent(event);
			}
		}
		
		function typing(event) {

			_tk.CancelEvent(event);

			var c = _tk.EventChar(event);
			if ( c == '\0' )
				return;
			var pos = _tk.GetCaret(elt).start;
			

			var p = _pic[pos];
			var val = elt.value.split('');


				
			if ( MatchPicture(c,pos) ) {
				
				val[pos] = c;
				pos++;
				while(IsStatic(pos)) {
					val[pos] = _pic[pos];
					pos++;
				}
			}
			


				
			elt.value = val.join('');
			_tk.SetCaret(elt,pos,pos+1);
			pos == picture.length && onEnd && onEnd();
		}
		
		_tk.AddEvent( elt, 'keypress', typing );
		_tk.AddEvent( elt, 'keydown', keydown );
		
		return function() {

			_tk.RemoveEvent( elt, 'keypress', typing );
			_tk.RemoveEvent( elt, 'keydown', keydown );
		}
	}
	
	_tk.Freezer = function(elt) {
		
		this.FreezeKeyboard = function(polarity) {
		
			if (polarity)
				_tk.AddEventList(elt, ['keydown','keyup','keypress'], _tk.CancelEvent );
			else
				_tk.RemoveEventList(elt, ['keydown','keyup','keypress'], _tk.CancelEvent );
		}

		
		if ( _tk.isIe ) {

			var _interval, _events = ['losecapture','click','focus','selectstart']; 
			function Capture(ev) { _tk.CancelEvent(ev); _tk.Defer( function() { elt.setCapture(false) } ) }

			this.FreezeMouse = function(polarity) {

				if (polarity) {
				
					elt.setCapture(false);
					_tk.AddEventList(elt, _events, Capture );
				} else {
					
					_tk.RemoveEventList(elt, _events, Capture );

					elt.releaseCapture();
				}
			}
		} else {
		
			this.FreezeMouse = function(polarity) {

				if (polarity) {
				
					elt.addEventListener( 'mousedown', _tk.CancelEvent, true );
					elt.addEventListener( 'mouseup', _tk.CancelEvent, true );
					elt.addEventListener( 'click', _tk.CancelEvent, true );
					_tk.isOpera && elt.addEventListener( 'scroll', _tk.CancelEvent, true ); 
					elt.addEventListener( _tk.isGecko?'DOMMouseScroll':'mousewheel', _tk.CancelEvent, true );
				} else {		
				
					elt.removeEventListener( 'mousedown', _tk.CancelEvent, true );
					elt.removeEventListener( 'mouseup', _tk.CancelEvent, true );
					elt.removeEventListener( 'click', _tk.CancelEvent, true );
					_tk.isOpera && elt.removeEventListener( 'scroll', _tk.CancelEvent, true );
					elt.removeEventListener( _tk.isGecko?'DOMMouseScroll':'mousewheel', _tk.CancelEvent, true );
				}
			}		
		}
	}


	_tk.HttpConnection = function() {
		
		var _this = this;
		var _httpRequest = _tk.NewHttpRequest();
		var _rexp_keyval = /(.*?): ?(.*?)\r?\n/g;
		var _attemp = 0;
		
		function headersToObject( allHeaders ) {
		
			var res, hdrObj = {};
			for ( _rexp_keyval.lastIndex = 0; res = _rexp_keyval.exec(allHeaders); hdrObj[res[1].toLowerCase()] = res[2]);
			return hdrObj;
		} 

		this.IsPending = function() {

			return _httpRequest.readyState != 4 && _httpRequest.readyState != 0;
		}
		
		this.Send = function(url, data, headerList, responseHandler) { 
			
			
			_httpRequest.open( data ? 'POST' : 'GET', url, true ); 
			
			for ( var name in headerList ) 
				_httpRequest.setRequestHeader(name, headerList[name]); 
			
			_httpRequest.onreadystatechange = function() {
			
//alert( _httpRequest.status + ' - ' + _httpRequest.responseText );

				if ( _httpRequest.readyState != 4 ) 
					return;

				var response, status, error, responseHeaders; 
				try {
				
					response = _httpRequest.responseText;
					status = _httpRequest.status;
					if (status < 100 || status >= 600 ) { 

						error = status;
						status = undefined;
					}
					responseHeaders = headersToObject(_httpRequest.getAllResponseHeaders());
				} catch (ex) {
					
					error = ex.result;
				}
				
				if ( status == 408 && _attemp <= 3 ) { 
					
					_this.Send( url, data, headerList, responseHandler );
					return;
				} else {
					
					_tk.Defer( function() { 

						responseHandler( response, responseHeaders, error, status );
					});
				}
				_attemp = 0;
			}
			
			_attemp++;
			_httpRequest.send( data == undefined ? null : data );
			
			_this.Cancel = function() {
				
				_this.Cancel = _tk.Noop;
				_httpRequest.onreadystatechange = _tk.Noop;
				_httpRequest.abort();
				_httpRequest = _tk.NewHttpRequest(); 
			}
		}
	}


	_tk.EventDispatcher = function(forward) { 
		
		var _dispatcher = this;
		var _dispatchList = [];
		var _eventQueue = [];
		var _processing = 0;

		this.AddListener = function( object ) {

			_dispatchList.push(object);
		}

		function ProcessEventQueue() {

			nextEvent:while ( _eventQueue.length && _processing == 0 ) { 

				var event = _eventQueue.shift();
				nextListener:for ( var i in _dispatchList ) {

					var item = _dispatchList[i];
					var id = event[0];
					if (!(id in item)) continue nextListener;
					
					_processing++;
					var status = item[id].apply( _dispatcher, event );
					if ( status == _dispatcher.FREEZE ) return;
					_processing--;
					if ( status == _dispatcher.CANCEL ) continue nextEvent;
				}
				forward && forward.apply(this,event);
			}
		}

		this.ForwardEvent = function(event) { forward.apply( this, event ) }
		this.Forward = function() { forward.apply( this, arguments ) }

		this.InsertEvent = function() {
			
			_eventQueue.unshift(arguments);
		}

		this.UnFreeze = function() {
		
			_processing--;
			_processing || ProcessEventQueue();
		}

		this.Dispatch = function() { 

			_eventQueue.push(arguments);
			_processing || ProcessEventQueue();
		}
	}
	
	_tk.EventDispatcher.prototype = { CANCEL:1, FREEZE:2 }


	_tk.CallDispatcher = function() { 

		var _dispatchList = {};
		var _count = 0;
		this.AddListener = function( object ) {
			
			_dispatchList[_count++] = object;
		}

		this.RemoveListener = function( object ) {
			
			for ( var i in _dispatchList )
				if ( _dispatchList[i] == object ) {
					delete _dispatchList[i];
					return;
				}
		}
		
		this.Dispatch = function( name ) {

			for ( var i in _dispatchList ) {

				var item = _dispatchList[i];
				name in item && item[name].apply(this,arguments);
			}
		}
	}


	_tk.DeferedCallDispatcher = function( dispatch ) {

		var _eventList = {};
		var _count = 0;
		this.Dispatch = function() {
			
			_eventList[_count++] = arguments;
		}
		
		this.Flush = function() {
		
			if ( _count > 0 ) {
		
				for ( var i in _eventList )
					dispatch.apply( this, _eventList[i] );
				_eventList = {};
				_count = 0;
			}
		}
	}


	_tk.KeyManager = function( elt ) {
	
		var _keyHandlers = {};
		var _charHandlers = {};
		
		function keyEventHandler(ev) {
		
			var keyModifiers = _tk.EventKeyModifiers(ev);
			if ( ev.type == 'keydown' ) {

				var key = _tk.EventKeyCode(ev);
				var list = _keyHandlers[key];
			} else {

				var key = _tk.EventChar(ev);
				var list = _charHandlers[key];
				keyModifiers = keyModifiers & 1 ? keyModifiers - 1 : keyModifiers;
			}

			for ( var i in list )
				if ( list[i].keyModifiers == keyModifiers ) {
				
					list[i].handler.apply( this, [key, keyModifiers].concat(list[i].arg) );
					_tk.CancelEvent(ev);
				}
		}
		
		this.HasListener = function( key, keyModifiers ) {
			
			var list = (typeof(key) == 'string') ? _charHandlers[key] : _keyHandlers[key];
			if ( list )
				for ( i in list )
					if ( list[i].keyModifiers == keyModifiers )
						return true;
		}

		this.AddListener = function( key, keyModifiers, handler, userArguments ) {

			var list = (typeof(key) == 'string') ? (_charHandlers[key] || ( _charHandlers[key] = [] )) : (_keyHandlers[key] || ( _keyHandlers[key] = [] ));
			list.push( { keyModifiers:keyModifiers, handler:handler, arg:userArguments } );
		}

		this.RemoveListener = function( key, keyModifiers, handler ) {

			var list = (typeof(key) == 'string') ? _charHandlers[key] : _keyHandlers[key];
			for ( var i in list )
				if ( list[i].keyModifiers == keyModifiers )
					list.splice(i,1);
		}

		_tk.AddEvent( elt, 'keydown', keyEventHandler );
		_tk.AddEvent( elt, 'keypress', keyEventHandler );
	}
}



gwc.Event = function() {
	
	this.value = {};
	this.sessionVar = {};
	
	this.SessionVar = function(varName, value) {
		
		this.sessionVar[varName] = value;
	}
	
	this.Action = function(did) {
		
		this.action = did;
	}

	this.Key = function(idref) {
		
		this.key = idref;
	}

	this.Focus = function(idref) {
		
		this.focus = idref;
	}

	this.Offset = function(idref, offset) {
		
		this.offset = [idref, offset];
	}

	this.Row = function(idref, row) {
		
		this.row = [idref, row];
	}
	
	this.Value = function(idref, value) {

		this.value[idref] = value;
	}
	
	this.Rest = function() {

		this.rest = true;
	}
	
	this.Clear = function() {

		this.value = {};
		this.sessionVar = {};
		delete this.rest;
		delete this.action;
		delete this.focus;
		delete this.key;
		delete this.row;
		delete this.offset;
	}
	
	this.InsertEvent = function(event) {
		
		for ( var idref in event.value )
			if ( !(idref in this.value) )
				this.value[idref] = event.value[idref];

		for ( var name in event.sessionVar )
			if ( !(name in this.sessionVar) )
				this.sessionVar[name] = event.sessionVar[name];

		if ( !this.focus && event.focus  ) this.focus = event.focus;
		if ( !this.row && event.row ) this.row = event.row;
		if ( !this.offset && event.offset ) this.offset = event.offset;
	}

	this.AppendEvent = function(event) {
	
		for ( var idref in event.value )
			this.value[idref] = event.value[idref];

		for ( var name in event.sessionVar )
			this.sessionVar[name] = event.sessionVar[name];

		if ( event.focus ) this.focus = event.focus;
		if ( event.row ) this.row = event.row;
		if ( event.offset ) this.offset = event.offset;
		if ( event.key ) this.key = event.key;
	}

	this.Serialize = function() { 
		
		var ev = '';
		this.rest && ( ev += '&t=' );
		this.action && ( ev += '&'+this.action );
		this.focus && ( ev += '&f=v'+this.focus );
		this.key && ( ev += '&k='+this.key );
		this.row && ( ev += '&r'+this.row[0]+'='+this.row[1] );
		this.offset && ( ev += '&o'+this.offset[0]+'/'+this.offset[1] );
		for ( var idref in this.value )
			ev += '&v'+idref+'='+encodeURIComponent(this.value[idref]);
		for ( var name in this.sessionVar )
			ev += '&u'+name+'='+encodeURIComponent(this.sessionVar[name]);
		return ev.substr(1);
	}
}

gwc.INTERNAL = {};
gwc.EXTERNAL = {};


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//
gwc.core = new function() {

	var FIELD = 'FIELD', ROW = 'ROW', CELL = 'CELL', TABLE = 'TABLE'; 

	var _core = this;

	var _tk = gwc.tk;
	
	function CoreException() {}
	function UndefinedComponent(cid) {
		
	}
	UndefinedComponent.prototype = new CoreException();
	function UndefinedMark(cid, markName) {
		
	}
	UndefinedMark.prototype = new CoreException();
	function UndefinedIdref(idref) {
		
	}
	UndefinedIdref.prototype = new CoreException();

	function StateHandler() {

		
		var _markTree = this.markTree = [0,{},[]]; 
		var _markEidIndex = this.markEidIndex = { 0:this.markTree }; 
		var _markCidIndex = this.markCidIndex = {}; 
		
		var _componentList = this.componentList = {}; 
		var _componentIdrefIndex = this.componentIdrefIndex = {};
		
		var _dialog = this.dialog = {}; 
		var _dialogIdrefIndex = this.dialogIdrefIndex = {};

		
		this.Init = function( markTree, componentList, newDialog, dispatch, source) {

			this.AddComponentSet( componentList, dispatch, source );
			this.AddElementMarks( _markTree, 0, markTree, dispatch, source);
			this.AddDialog( newDialog, dispatch, source );
		}

		this.AddElementMarks = function(node, index, nodeList, dispatch, source ) { 

			function _inner(n, parent) {

				var eid = n[0], n1 = n[1], n2 = n[2];
				_markEidIndex[eid] = n;
				n.parent = parent;
				
				for ( var markName in n1 ) {
					
					if ( markName.charAt(0) == '_' ) {

					
					} else {
				
						var data = n1[markName], cid = data[0], markTable = _markCidIndex[cid] || (_markCidIndex[cid]={});
						(markTable[markName] || (markTable[markName]={}))[eid] = data; 
						dispatch( 'AddMark', eid, markName, cid, data, source ); 
					}
				}

				if ( n2 == undefined ) 
					return

				if ( isNaN(n2) ) {

					for ( var c in n2 )
						_inner(n2[c], n);
				} else {

					n[2] = parent.splice(index,n2);
					for ( var i in n[2] )
						n[2][i].parent = n;
					
				}
			}
			
			while ( nodeList.length ) {

				var c = nodeList.pop();
				if ( !node[2] ) 
					node[2] = [];
				node[2].splice( index, 0, c ); 
				_inner(c, node); 
			}
		}


		this.RemoveElementMarkTrees = function(eidList, dispatch, source ) {

			
			function _innerDispatch(n) { 
				
				var eid = n[0], n1 = n[1], n2 = n[2];
				for ( var markName in n1 ) {
					
					if ( markName.charAt(0) == '_' ) {

						
					} else {

						var data = n1[markName];
						dispatch( 'RemoveMark', eid, markName, data[0], data, source ); 
					}
				}
				
				for ( var c in n2 )
					_innerDispatch( n2[c] );
			}
			
			for ( var i in eidList )
				_innerDispatch(_markEidIndex[eidList[i]]);

			function _inner(n) { 
				
				var eid = n[0], n1 = n[1], n2 = n[2];
				for ( var markName in n1 ) {

					if ( markName.charAt(0) == '_' ) {
					} else {
					
						var cid = n1[markName][0], markTable = _markCidIndex[cid];
						delete markTable[markName][eid];
						if ( !_tk.HasProperty(markTable[markName]) ) {

							delete markTable[markName]; 
							_tk.HasProperty(markTable) || delete _markCidIndex[cid]; 
						}
					}
				}
				
				delete _markEidIndex[eid]; 
				for ( var c in n2 ) 
					_inner( n2[c] );
			}
			
			for ( var i in eidList ) {
			
				var node = _markEidIndex[eidList[i]]; 
				_inner(node); 
				
				var p = node.parent[2]; 
				for ( var j in p )
					if ( p[j] == node ) { 

						delete p[j]; 
						break; 
					}
			}
		}


		this.RemoveElementMarks = function(list, dispatch, source ) { 

			for ( var idx in list ) {
				
				var markName = list[idx][1];
				if ( markName.charAt(0) == '_' ) {

					
				} else {

					var eid = list[idx][0], node = _markEidIndex[eid], markMap = node[1], data = markMap[markName];
					dispatch( 'RemoveMark', eid, markName, data[0], data, source ); 
				}
			}

			for ( var idx in list ) {
				
				var markName = list[idx][1], eid = list[idx][0], node = _markEidIndex[eid], markMap = node[1];

				if ( markName.charAt(0) == '_' ) {
				} else {

					var cid = markMap[markName][0];
					delete _markCidIndex[cid][markName][eid];
					_tk.HasProperty(_markCidIndex[cid][markName]) || delete _markCidIndex[cid][markName];
					_tk.HasProperty(_markCidIndex[cid]) || delete _markCidIndex[cid];
				}

				delete markMap[markName];
				
				if ( !_tk.HasProperty(markMap) ) { 

					delete _markEidIndex[eid];
					var parent = node.parent;
					parent[2] = node[2];
					node.parent = parent;
				}
			}
		}


		this.SetElementMarks_Remove = function( elementMarks, dispatch, source ) {  
		
			for ( var i in elementMarks ) {
			
				var item = elementMarks[i], eid = item[0], markName = item[1], markMap = _markEidIndex[eid][1];
				if ( !(markName in markMap) ) 
					continue;
				if ( markName.charAt(0) == '_' ) {

					
				} else {

					var data = markMap[markName], cid = data[0];
					dispatch( 'RemoveMark', eid, markName, cid, data, source );

					if ( item[2][0] != cid ) { 

						var eidMap = _markCidIndex[cid][markName];
						delete eidMap[eid];
						_tk.HasProperty(eidMap) || delete _markCidIndex[cid][markName];
						_tk.HasProperty(_markCidIndex[cid]) || delete _markCidIndex[cid];
						delete markMap[markName];
					}
				}
			}
		}


		this.SetElementMarks_Add = function( elementMarks, dispatch, source ) {  
		
			for ( var i in elementMarks ) {
			
				var item = elementMarks[i], eid = item[0], markName = item[1], newData = item[2], markMap = _markEidIndex[eid][1];

				if ( markName.charAt(0) == '_' ) {

					
				} else {
					
					var newCid = newData[0];
					if ( !(markName in markMap) ) { 
				
						var markTable = _markCidIndex[newCid] || (_markCidIndex[newCid]={});
						(markTable[markName] || (markTable[markName]={}))[eid] = newData;
					} else {
					
						_markCidIndex[newCid][markName][eid] = newData; 
					}
					dispatch( 'AddMark', eid, markName, newCid, newData, source );
				}

				markMap[markName] = newData;
			}
		}
		
		this.AddComponentSet = function( componentList, dispatch, source ) {
			
			for ( var cid in componentList ) {
			
				var component = componentList[cid];
				component.cid = cid;
				_componentList[cid] = component;
				var idref = component[1];
				
				(_componentIdrefIndex[idref] || (_componentIdrefIndex[idref]={}))[cid] = component;
				dispatch( 'AddComponent', cid, component, source );
			}
		}

		this.RemoveComponent = function( cid, dispatch, source ) {

			var component = _componentList[cid];
			dispatch( 'RemoveComponent', cid, component, source );
			
			var idref = component[1];
			delete _componentList[cid];
			_componentIdrefIndex[idref][cid] && delete _componentIdrefIndex[idref][cid];
			_tk.HasProperty(_componentIdrefIndex[idref]) || delete _componentIdrefIndex[idref];
		}

		this.RemoveDialog = function( dispatch, source ) {
		
			dispatch( 'RemoveDialog', _dialog, source );
			for ( var idref in _dialog )
				delete _dialog[idref];
			for ( var idref in _dialogIdrefIndex )
				delete _dialogIdrefIndex[idref];
		}


		this.AddDialog = function( newDialog, dispatch, source ) {

			for ( var idref in newDialog ) {
				
				var info = newDialog[idref];
				_dialog[idref] = info;
				if ( isNaN(idref) ) 
					continue;
				info.idref = idref;
				if ( 'VC' in info )
					for ( var i in info.VC ) {

						var idref = info.VC[i];
						function Tmp(){}
						Tmp.prototype = info;
						var newInfo = new Tmp;
						_dialogIdrefIndex[idref] = newInfo;
						newInfo.rowIndex = i;

						newInfo.parentIdref = newInfo.idref; 
						newInfo.idref = idref; 
						
						if ( info.VC.length > 1 ) {
							
							var colCount = info.table ? newDialog[info.table].columnCount : newInfo.columnCount;
							newInfo.tabindex += colCount * i;
						}
					}
			}
			dispatch( 'AddDialog', _dialog, source );
		}

		this.SetDialogProperties = function( attrList, dispatch, source ) {
			
			for ( var i in attrList ) {

				var attr = attrList[i], idref = attr[0], key = attr[1], value = attr[2];
				var oldValue = (idref ? _dialog[idref] : _dialog)[key];
				dispatch( 'SetDialogProperty', idref, key, value, oldValue, _dialog, source );
				(idref ? _dialog[idref] : _dialog)[key] = value;
			}
		}

		this.UnsetDialogProperty = function( attr, dispatch, source ) {

			var idref = attr[0], key = attr[1];

			if ( idref ) { 

				var currentVal = _dialog[idref][key];
				dispatch( 'UnsetDialogProperty', idref, key, currentVal, _dialog, source );
				delete _dialog[idref][key];
			} else {

				var currentVal = _dialog[key];
				dispatch( 'UnsetDialogProperty', idref, key, currentVal, _dialog, source );
				delete _dialog[key];
			}
		} 
	

		
		this.ForeachMarkByMarkName = function( markName, fct, callWhenLeaving ) {
			
			function inner( node ) {
				
				var markMap = node[1], nodeList = node[2];
				!callWhenLeaving && markMap[markName] && fct( node[0], markMap[markName] );
				for ( var i in nodeList )
					inner( nodeList[i] );
				callWhenLeaving && markMap[markName] && fct( node[0], markMap[markName] );
			}
			inner( _markTree );
		}
		
		this.HasComponent = function( cid, markName, eid ) {
			
			return cid in _markCidIndex;
		}

		this.HasMark = function( cid, markName, eid ) {
			
			return cid in _markCidIndex && markName in _markCidIndex[cid];
		}

		this.MarkData = function( cid, markName, eid ) {

			if ( !(cid in _markCidIndex) ) throw new UndefinedComponent(cid);
			if ( !(markName in _markCidIndex[cid]) ) throw new UndefinedMark(cid, markName);
			return _markCidIndex[cid][markName][eid];
		}

		this.FirstMarkData = function( cid, markName ) {

			if ( !(cid in _markCidIndex) ) throw new UndefinedComponent(cid);
			if ( !(markName in _markCidIndex[cid]) ) throw new UndefinedMark(cid, markName);
			return _tk.FirstValue( _markCidIndex[cid][markName] );
		}

		this.FirstMarkEid = function( cid, markName ) { 

			if ( !(cid in _markCidIndex) ) throw new UndefinedComponent(cid);
			if ( !(markName in _markCidIndex[cid]) ) throw new UndefinedMark(cid, markName);
			return _tk.FirstKey( _markCidIndex[cid][markName] );
		}
		
		this.ForeachMarkEid = function( cid, markName, fct ) {
		
			if ( !(cid in _markCidIndex) ) throw new UndefinedComponent(cid);
			for ( var eid in _markCidIndex[cid][markName] )
				if ( (ret = fct(eid, _markCidIndex[cid][markName][eid])) != undefined )
					return ret;
		}
		
		this.ActionDidByName = function( actionName ) {
			
			for ( var idref in _dialog ) {
			
				var item = _dialog[idref];
				if ( item.type == 'action' && item.name == actionName )
					return item.DID;
			}
		}

		this.ActionNameByDid = function( actionDid ) {
			
			for ( var idref in _dialog ) {
			
				var item = _dialog[idref];
				if ( item.type == 'action' && item.DID == actionDid )
					return item.name;
			}
		}

		this.ActionActiveByDid = function( actionDid ) {
			
			for ( var idref in _dialog ) {
			
				var item = _dialog[idref];
				if ( item.type == 'action' && item.DID == actionDid )
					return !!item.active;
			}
		}
		
		this.IdrefByCid = function( cid ) {

			if ( !(cid in _componentList) ) throw new UndefinedComponent(cid);
			return _componentList[cid][1];
		}
		
		this.ComponentByCid = function( cid ) {
			
			if ( !(cid in _componentList) ) throw new UndefinedComponent(cid);
			return _componentList[cid];
		}
		
		this.ComponentsByIdref = function( idref ) {
			
			if ( !(idref in _componentIdrefIndex) ) throw new UndefinedIdref(idref);
			return _componentIdrefIndex[idref];
		}

		this.DialogInfoByCid = function( cid ) {
			
			if ( !(cid in _componentList) ) throw new UndefinedComponent(cid);
			var idref = _componentList[cid][1];
			return _dialogIdrefIndex[idref] || _dialog[idref]; //(TBD) fix it?
		}

		this.DialogInfoByIdref = function( idref ) {
			
			return _dialogIdrefIndex[idref];
		}		
		
		this.HasError = function() {
			
			return _dialog.error;
		}
		
		this.ForcedFieldMode = function() {
			
			return _dialog.forcedFieldMode;
		}

		this.CurrentItem = function() { 
			
			if ( _dialog.focus ) {

				var focus = _dialog[_dialog.focus]; 

				if ( focus.type == 'field' && ('currentrow' in focus) && !focus.active ) 
					return { type:CELL, item:_dialogIdrefIndex[focus.VC[focus.currentrow]] };

				if ( focus.type == 'table' && ('currentrow' in focus) && !('currentcolumn' in focus) ) 
					return { type:ROW, item:focus, index:focus.currentrow, container:focus, trigger:_dialog };

				if ( focus.type == 'button' ) 
					return { type:FIELD, item:focus };

				if ( focus.type == 'table' && ('currentrow' in focus) && ('currentcolumn' in focus) )
					return { type:FIELD, item:_dialogIdrefIndex[_dialog[focus.currentcolumn].VC[focus.currentrow]], container:{ type:ROW, index:focus.currentrow, item:focus } };

				if ( focus.type == 'field' && focus.active )
					return { type:FIELD, item:_dialogIdrefIndex[focus.VC[focus.currentrow||0]] };
			}
		}
		
		this.SetFocus = function(field) { 
			
			var s = {};
			
			if ( field.VC && 'rowIndex' in field ) { 

				if ( 'table' in field ) {
					
					s.focus = field.table;
					s.currentcolumn = field.parentIdref;
					s.currentrow = field.rowIndex;
				} else {
				
					s.currentrow = field.rowIndex;
					s.focus = field.parentIdref;
				}
			} else {			

				s.focus = field.idref;
			}
			
			this.SetCurrentState(s);
		}
		
		this.SetCurrentRowIndex = function(table, row) {
		
			var s = {};
			s.focus = table.idref;
			s.currentrow = row;
			this.SetCurrentState(s);
		}
		
		this.GetCurrentState = function() {
			
			var s = {}; 
			if ( 'focus' in _dialog ) {

				s.focus = _dialog.focus;
				var focusedItem = _dialog[_dialog.focus];
				if ( 'currentcolumn' in focusedItem )
					s.currentcolumn = focusedItem.currentcolumn;
				if ( 'currentrow' in focusedItem )
					s.currentrow = focusedItem.currentrow;
			}			
			return s;
		}

		this.SetCurrentState = function(s) {
			
			var dialogUpdate = [];
			if ( 'focus' in s ) {

				dialogUpdate.push( [ 0, 'focus', s.focus ] );
				
				if ( 'currentcolumn' in s && 'currentrow' in s ) {
					
					dialogUpdate.push( [ s.focus, 'currentcolumn', s.currentcolumn ] );
					dialogUpdate.push( [ s.focus, 'currentrow', s.currentrow ] );
				} else
					if ( 'currentrow' in s ) {

						dialogUpdate.push( [ s.focus, 'currentrow', s.currentrow ] );
					}
				_core.dispatcher.Dispatch('BeforeStateUpdate', _state, gwc.INTERNAL );
				_state.SetDialogProperties( dialogUpdate , _core.dispatcher.Dispatch, gwc.INTERNAL );
				_core.dispatcher.Dispatch('AfterStateUpdate', _state, gwc.INTERNAL );				
			}
		}
		
		this.FieldByTabindex = function( tabindex ) {
			
			for ( var idref in _dialogIdrefIndex )
				if ( _dialogIdrefIndex[idref].tabindex == tabindex )
					return _dialogIdrefIndex[idref];
		}		

		this.NextField = function( field ) {
			
			if ( field.tabindex )
				for ( var idref in _dialogIdrefIndex )
					if ( _dialogIdrefIndex[idref].tabindex == field.tabindex + 1 )
						return _dialogIdrefIndex[idref];
		}
		
		this.ComponentHasFocus = function(cid) {
			
			var current = this.CurrentItem();
			if ( current && current.item == this.DialogInfoByCid(cid) )
				return true;
		}
	}


	function Connection() {
		
		
		var _url, _defaultHeaders = { 'Accept':'application/javascript', 'Pragma':'no-cache', 'Cache-Control':'no-store, no-cache, must-revalidate', 'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8' };
		
		if ( _tk.isIe )
			_defaultHeaders['Accept'] += ', text/html'


		var _httpConnection = new _tk.HttpConnection();
		
		var _this = this;
		
		_this.CancelCurrentRequest = _tk.Noop;

		this.RequestToEngine = function( thisFctName, data) {

			var _dispatcher = this;

			_this.CancelCurrentRequest = function() {
				
				_this.CancelCurrentRequest = _tk.Noop;
				if ( !_httpConnection.IsPending() )
					return;
				_httpConnection.Cancel();
				_dispatcher.Forward('ResponseFromEngine',0,0,'canceled',0,0);
				_dispatcher.UnFreeze(); 
			}


			_httpConnection.Send( _url, data, _defaultHeaders, function(response, headers, error, httpStatus) { 
				
				_core.EventSink('ResetKeepAlive');
				_dispatcher.Forward('ResponseFromEngine',_url,httpStatus,error,response,headers); 
				_dispatcher.UnFreeze(); 
			});

			return this.FREEZE;
		}

		this.UpdateConnectionUrl = function(id,url) {
			
			_url = url;
		}
	}


	function ResponseParser() {
		

		this.ResponseFromEngine = function( fctName ,url, httpStatus, error, response, headers) {
			
			if ( error == 'canceled' )
				return;

			if ( httpStatus >= 500 ) {
			
				document.body.innerHTML = '<h1>500 Internal Server Error</h1>';
				throw(0);
				return;
			}

			if ( httpStatus == 406 ) {

				location.replace( url );
				return;
			}

			if ( httpStatus != 200 || headers['content-type'].indexOf('application/javascript') != 0 ) {

				_core.dispatcher.Dispatch('StopKeepAlive');
				_core.dispatcher.Dispatch('DocumentUnloading');
				headers && document.open(headers['content-type'], 'replace');
				document.write( response );
				document.close();
				return;
			}

			var update = eval(response); 
			this.InsertEvent( 'ProcessIncrementalUpdate', update );
		} 
	} 



	function StateUpdater() {


		this.ProcessIncrementalUpdate = function( thisFctName, update ) {

			_core.dispatcher.Dispatch( 'BeforeStateUpdate', _state, gwc.EXTERNAL ); 

			var coreDispatch = _core.dispatcher.Dispatch;
			var deferedDispatcher = new _tk.DeferedCallDispatcher( coreDispatch );
			

		
			if (update.setElementMarks) {
			
				_state.SetElementMarks_Remove( update.setElementMarks, deferedDispatcher.Dispatch );
				deferedDispatcher.Flush();
			}
			
			if (update.removedElementMarkTrees) {
				
				_state.RemoveElementMarkTrees( update.removedElementMarkTrees, coreDispatch ); 
			}
			
			if (update.removedElementMarks) {
			
				_state.RemoveElementMarks( update.removedElementMarks, coreDispatch ); 
			}

			if (update.removedDialogProperties) {

				for ( i in update.removedDialogProperties )
					_state.UnsetDialogProperty( update.removedDialogProperties[i], deferedDispatcher.Dispatch );
				
				deferedDispatcher.Flush();
			}
			
			if (update.dialog) {
				
				_state.RemoveDialog(coreDispatch);
			}
			
			if (update.removedComponents) {
				
				for ( var i in update.removedComponents )
					_state.RemoveComponent( update.removedComponents[i], deferedDispatcher.Dispatch );
				deferedDispatcher.Flush();
			}
				
			if (update.removedPreviousTextsBeforeRemovingElements) {
			
				for ( var i in update.removedPreviousTextsBeforeRemovingElements ) {

					var elt = _tk.IdToElement(update.removedPreviousTextsBeforeRemovingElements[i]);
					while ( elt.previousSibling && elt.previousSibling.nodeType != 1 )
						elt.parentNode.removeChild(elt.previousSibling);
				}
			}
			
			if (update.removedLastTextsBeforeRemovingElements) {
			
				for ( var i in update.removedLastTextsBeforeRemovingElements ) {

					var elt = _tk.IdToElement(update.removedLastTextsBeforeRemovingElements[i]);
					while ( elt.lastChild && elt.lastChild.nodeType != 1 )
						elt.removeChild(elt.lastChild);
				}
			}

			if (update.removedElementAttributes) {
				
				for ( var i in update.removedElementAttributes ) {

					var arg = update.removedElementAttributes[i];
					_tk.RemoveElementAttribute(_tk.IdToElement(arg[0]), arg[1]);
				}
			}

			if (update.removedElements) { 
			
				for ( var i in update.removedElements )
					_tk.RemoveElement(_tk.IdToElement(update.removedElements[i]));
			}
				
			if (update.removedPreviousTextsBeforeAddingContent) {
			
				for ( var i in update.removedPreviousTextsBeforeAddingContent ) {

					var elt = _tk.IdToElement(update.removedPreviousTextsBeforeAddingContent[i]);
					while ( elt.previousSibling && elt.previousSibling.nodeType != 1 )
						elt.parentNode.removeChild(elt.previousSibling);
				}
			}
			
			if (update.removedLastTextsBeforeAddingContent) {
			
				for ( var i in update.removedLastTextsBeforeAddingContent ) {

					var elt = _tk.IdToElement(update.removedLastTextsBeforeAddingContent[i]);
					while ( elt.lastChild && elt.lastChild.nodeType != 1 )
						elt.removeChild(elt.lastChild);
				}
			}

			/////////////////////////////////////////////////////////////////

			if (update.insertedElementContents) {
			
				for ( var i in update.insertedElementContents ) {

					var arg = update.insertedElementContents[i];
					_tk.InsertContent( _tk.IdToElement(arg[0]), arg[1] );
				}
			}

			if (update.appendedElementContents) {
			
				for ( var i in update.appendedElementContents ) {

					var arg = update.appendedElementContents[i];
					_tk.AppendContent( _tk.IdToElement(arg[0]), arg[1] );
				}
			}

			if (update.setElementAttributes) {
			
				for ( var i in update.setElementAttributes ) {

					var arg = update.setElementAttributes[i];
					_tk.SetHTMLElementAttribute( _tk.IdToElement(arg[0]), arg[1], arg[2] );
				}
			}
			
			if (update.addedComponents) {
				
				_state.AddComponentSet( update.addedComponents, deferedDispatcher.Dispatch );
				deferedDispatcher.Flush();
			}

			if (update.dialog) {
				
				_state.AddDialog(update.dialog, deferedDispatcher.Dispatch );
				deferedDispatcher.Flush();
			}
			
			if (update.setDialogProperties) {
			
				_state.SetDialogProperties( update.setDialogProperties, deferedDispatcher.Dispatch );
				deferedDispatcher.Flush();
			}

			if (update.addedElementMarks) {
			
				for ( var i in update.addedElementMarks ) { 

					var arg = update.addedElementMarks[i];
					_state.AddElementMarks( _state.markEidIndex[arg[0]||0], arg[1], arg[2], deferedDispatcher.Dispatch ); 
				}
				deferedDispatcher.Flush();
			}

			if (update.setElementMarks) {
			
				_state.SetElementMarks_Add( update.setElementMarks, deferedDispatcher.Dispatch );
				deferedDispatcher.Flush();
			}
			
			_core.dispatcher.Dispatch('AfterStateUpdate', _state, gwc.EXTERNAL );		
		}

		this.AfterStateUpdate = function( fctName ) {

			var url = _tk.IdToElement('gSuaURL').value;
			_core.dispatcher.Dispatch('UpdateConnectionUrl',url);
		}

	} 

	
	
	function FieldMode(state) {
		
		
		var _this = this;
		
		function Current( polarity ) {
			
			var current = state.CurrentItem();
			if ( !current )
				return;
			try {
				var components = state.ComponentsByIdref(current.item.idref);
				for ( var cid in components ) {
	
					var component = components[cid];
					var componentClass = gwc.ComponentSelector(component);
					switch ( current.type ) {
						case CELL:
							componentClass['currentCell'] && componentClass['currentCell'].call( componentClass, polarity, component );
							break;
						case ROW:
							componentClass['currentRow'] && componentClass['currentRow'].call( componentClass, polarity, component, current.index );
							componentClass['currentTable'] && componentClass['currentTable'].call( componentClass, polarity, component );
							break;
						case FIELD:
							componentClass['currentField'] && componentClass['currentField'].call( componentClass, polarity, component );
							break;
					}
				}
			} catch(ex) {
  				
  				if ( !(ex instanceof CoreException) )
  					throw ex;
			}
		}
		

		this.HideCurrentField = function() { Current(false) }


		this.BeforeStateUpdate = function(thisFctName, state) { Current(false) }
		this.AfterStateUpdate = function(thisFctName, state) { Current(true) }


		function QueryFieldData(idref) {
			
			var components = _state.ComponentsByIdref( idref );
			for ( var cid in components ) { 

				var component = components[cid];
				var componentClass = gwc.ComponentSelector(component);
				try {
					if ( componentClass && 'GetValue' in componentClass )
						return componentClass.GetValue.call( componentClass, component );
				} catch(ex) {
					if ( !(ex instanceof CoreException) ) throw ex;
				}
			}
		}

		function AddCurrentFieldData(gwcEvent) {
			
			var current = _state.CurrentItem();
			if ( current && current.type == FIELD ) {
				
				var data = QueryFieldData(current.item.idref);
				if ( data != undefined )
					gwcEvent.Value(current.item.idref, data);
			}
		}
	
		this.Typing = function(thisFctName, event) {

			var dialogInfo = _state.DialogInfoByIdref( event.idref );
			if ( dialogInfo && dialogInfo.autonext ) { 
				
				var valueLength = QueryFieldData(event.idref).length; 
				if ( valueLength >= dialogInfo.maxlength )
					gwc.capi.NextField();
			}
		}

		this.Commit = function(thisFctName, gwcEvent) {

			AddCurrentFieldData(gwcEvent);
		}

		this.Action = function(thisFctName, gwcEvent) {

			AddCurrentFieldData(gwcEvent);
		}

		this.Focus = function(thisFctName, gwcEvent) {

			AddCurrentFieldData(gwcEvent);
		}

		this.SelectMatrixItem = function(_, gwcEvent) {
		}

		this.SelectTableRow = function(_, gwcEvent) {
		}

		this.Offset = function(thisFctName, gwcEvent) { 

			AddCurrentFieldData(gwcEvent);
		}

		this.Key = function(thisFctName, gwcEvent) {
			
			AddCurrentFieldData(gwcEvent);
		}

		this.Rest = function(thisFctName, gwcEvent) {
			
			gwcEvent.Rest();
		}
	} 



	function SmartMode() {

		var _this = this;
		var _pendingEvent = new gwc.Event()
		var _previousEngineState = _state.GetCurrentState();
		
		this.AfterStateUpdate = function(thisFctName, state, source) {

			if ( source == gwc.INTERNAL )
				return;
			_previousEngineState = _state.GetCurrentState();
		}

		function HasInTrigger( field ) {
		
			return field.beforeField;
		}

		function HasOutTrigger( field ) {

			return field.afterField || field.include || field.onChange || field.verify; 
		}
		
		function TypeCheck(dataType, value) {

			if ( !dataType.indexOf('CHAR') || !dataType.indexOf('VARCHAR') || !dataType.indexOf('STRING') || !dataType.indexOf('TEXT') )
				return true;
			
			if ( !dataType.indexOf('DATE') )
				return !!/^$|^\d{1,4}([\./\-:])\d{1,2}\1\d{1,4}$/.exec(value);

			if ( !dataType.indexOf('DATETIME') )
				return !!/^$|^\d{1,4}([\./\-:])\d{1,2}\1\d{1,4} \d{1,2}:\d{1,2}(?::\d{1,2}(?:\.\d{1,4})?)?$/.exec(value); 

			if ( !dataType.indexOf('INTEGER') || !dataType.indexOf('SMALLINT') )
				return !!/^$|^[+-]?\d+$/.exec(value);

			if ( !dataType.indexOf('DECIMAL') || !dataType.indexOf('FLOAT') || !dataType.indexOf('SMALLFLOAT') ) 
				return !!/^$|^[+-]?\d*(?:[\.,]\d+)?([eE][+-]\d+)?$/.exec(value);

			return false;
		}

		this.Commit =
		this.SelectMatrixItem =
		this.Offset = function(thisFctName, gwcEvent) {

			gwcEvent.InsertEvent(_pendingEvent);
			_pendingEvent.Clear();
			_state.SetCurrentState(_previousEngineState);
			_core.dispatcher.Dispatch( 'HideCurrentField' );
		}


		this.Action = function(thisFctName, gwcEvent) {

			var actionName = gwc.core.state.ActionNameByDid(gwcEvent.action);

			smart:{
			
				if ( _state.HasError() || _state.ForcedFieldMode() )
					break smart;
				var current = _state.CurrentItem();
				if ( !current )
					break smart;
				switch ( current.type ) {
					case FIELD:
						
						var value = gwcEvent.value[current.item.idref];
						var dataType = current.item.dataType;
						if ( actionName != 'nextfield' || HasOutTrigger(current.item) || ( dataType && !TypeCheck(dataType, value) ) ) 
							break smart;

						var cf = current.item;
						do { 
							cf = _state.NextField(cf);
						} while ( cf && !cf.active );
						if ( !cf || HasInTrigger(cf) )
							break smart;

						_state.SetFocus(cf);
						
						current = _state.CurrentItem(); 
						if ( current.container && current.container.type == ROW && current.container.index >= current.container.item.rowCount )
							break smart;

						_pendingEvent.Focus(cf.idref); 
						break;

					case ROW:
						if ( current.index == undefined )
							break smart;
						if ( current.trigger.beforeRow || current.trigger.afterRow )
							break smart;
						var nextRow;
						switch ( actionName ) {
							case 'prevpage':
								if ( current.index > 0 )
									nextRow = 0;
								else
									break smart;
								break;
							case 'nextpage':
								if ( current.index < current.item.rowCount-1 )
									nextRow = current.item.rowCount-1;
								else
									break smart;
								break;
							case 'nextrow':
							case 'nextfield':
								nextRow = current.index + 1;
								break;
							case 'prevrow':
							case 'prevfield':
								nextRow = current.index - 1;
								break;
							default:
								break smart;
						}

						if ( nextRow < 0 || nextRow > current.item.rowCount - 1 )
							break smart;

						_pendingEvent.Row(current.item.idref, nextRow);
						_state.SetCurrentRowIndex(current.item, nextRow);
					break;
					case CELL:
						break smart; 
				}

				_pendingEvent.AppendEvent(gwcEvent);
				delete _pendingEvent.action;
				return this.CANCEL;
			}
			
			gwcEvent.InsertEvent(_pendingEvent);
			_pendingEvent.Clear();
			_state.SetCurrentState(_previousEngineState);
			_core.dispatcher.Dispatch( 'HideCurrentField' );
		}


		this.SelectTableRow = function(thisFctName, gwcEvent) {
		
			smart:{

				if ( _state.HasError() || _state.ForcedFieldMode() )
					break smart;
				var current = _state.CurrentItem();
				if ( !current || current.type != ROW || current.index == undefined || current.trigger.beforeRow || current.trigger.afterRow )
					break smart;
				_pendingEvent.AppendEvent(gwcEvent);
				_state.SetCurrentRowIndex(current.item, gwcEvent.row[1]);
				return this.CANCEL;
			}				
		
			gwcEvent.InsertEvent(_pendingEvent);
			_pendingEvent.Clear();
			_state.SetCurrentState(_previousEngineState);
			_core.dispatcher.Dispatch( 'HideCurrentField' );
		}

		
		this.Focus = function(thisFctName, gwcEvent) {
		
			smart:{
				
				if ( _state.HasError() || _state.ForcedFieldMode() )
					break smart;
				var current = _state.CurrentItem();
				if ( !current || current.type != FIELD )
					break smart;
				var field = current.item;
				for(;;) {

					if ( !field || HasOutTrigger(field) )
						break smart;

					field = _state.NextField(field);

					if ( !field || HasInTrigger(field) )
						break smart;

					if ( field.idref == gwcEvent.focus ) {

						_pendingEvent.AppendEvent(gwcEvent);
						_state.SetFocus(field);
						return this.CANCEL;
					}
				}
			}

			gwcEvent.InsertEvent(_pendingEvent);
			_pendingEvent.Clear();
			_state.SetCurrentState(_previousEngineState);
			_core.dispatcher.Dispatch( 'HideCurrentField' );
		}

	} 
	

	function EventFilter() {

		var _lockEvents = 0;
		this.Action = function(thisFctName, gwcEvent) {
			
			if ( _lockEvents && gwc.core.state.ActionNameByDid( gwcEvent.action ) != 'interrupt' )
				return this.CANCEL;
		}

		this.RequestToEngine = function() {
			
			_lockEvents++;
		}
		
		this.ResponseFromEngine = function() {

			_lockEvents--;
		}

	} 


	function EventTranslator() {


		this.Commit =
		this.SessionVar =
		this.Action =
		this.Focus =
		this.SelectMatrixItem =
		this.SelectTableRow =
		this.Offset =
		this.Key =
		this.Rest = function(thisFctName, gwcEvent) {
		

			_core.EventSink('RequestToEngine', gwcEvent.Serialize());
		}
	} 


	function UiUpdater() {

		
		_core.dispatcher.AddListener( this );
		
		this.RemoveMark = function( name, eid, mark, cid, data ) {
			
			var component = _state.ComponentByCid(cid);
			var componentClass = gwc.ComponentSelector(component);
			if ( !componentClass ) return;
			try {
				var markFunction = componentClass[mark];
				markFunction && markFunction.call( componentClass, false, eid, cid, component, data );
			} catch(ex) {
				if ( !(ex instanceof CoreException) ) throw ex;
			}
		}

		this.AddMark = function( name, eid, mark, cid, data ) {

			var component = _state.ComponentByCid(cid);
			var componentClass = gwc.ComponentSelector(component);
			if ( !componentClass )
				return;
			try {
				var markFunction = componentClass[mark];
				markFunction && markFunction.call( componentClass, true, eid, cid, component, data );
			} catch(ex) {
				if ( !(ex instanceof CoreException) ) throw ex;
			}
		}

		this.Defer = function( name, cid, functionName, argArray ) {

			var component = _state.ComponentByCid(cid);
			var componentClass = gwc.ComponentSelector(component);
			componentClass[functionName].apply( componentClass, [cid].concat(argArray) );
		}
	} 



	function InterruptManager( connection ) {
	
		this.Action = function(thisFctName, gwcEvent) {

			if ( gwc.core.state.ActionNameByDid( gwcEvent.action ) == 'interrupt' ) {
			
				_core.dispatcher.Dispatch('Interrupt');
				connection.CancelCurrentRequest();
			}
		}
	} 


	var uiFreezer = new function() {

		
		var _this = this, _layer, _freeze, _popup, _seq;

		this.DocumentLoaded = function() {

			//Work arround for safari 3.0.4 in XHTML (will be fixed in a future safari)
			if(!document.body)
			{
				document.body = document.getElementsByTagName("body")[0];
			}

			_layer = new _tk.FrontLayer(_tk.GetBody());
			_freeze = new _tk.Freezer(_tk.GetBody());

			var popupElt = _tk.GetBody().appendChild(_tk.CreateElement('div', { className:'gwcHourglass' } ));
			gwc.cfg.hourglassText && _tk.AppendTextNode( popupElt, gwc.cfg.hourglassText );
			_popup = new _tk.Popup(popupElt);
			delete _this.DocumentLoaded; 
		}

		this.DocumentUnloading = function() {
			
			_tk.SequenceCancel(_seq);
			_layer.Remove();
			_popup.Remove();
		}
		
		this.RequestToEngine = function() {
		
			
			_freeze.FreezeKeyboard(true);

			
			_seq && _tk.SequenceCancel(_seq);
			_seq = _tk.SequenceStart(
				function() {
					
					_layer.Alpha(0).Visible(true);
				}, 200, 
				function() {

					_popup.Align('center','center').Visible(true);
				}, gwc.cfg.hourglassDelay,
				function() {
				
					_layer.Fade(gwc.cfg.backgroundLayerFadingLevel);

				}, gwc.cfg.backgroundLayerFadingDelay
			);
		}
	
		this.ResponseFromEngine = function() {

			_tk.SequenceCancel(_seq);
			_layer.Visible(false);
			_popup.Visible(false);
			_freeze.FreezeKeyboard(false);

		}
	} 


	var idleManager = new function() {
	
		var _idleTimeout;
		var _delay;
		var _actionDid;
		var _isIdle;
		
		function OnIdle() {
			
			gwc.capi.Action(_actionDid);
		}
		
		function Stop() {
			
			if ( _idleTimeout ) {
				
				_tk.ClearTimeout( _idleTimeout );
				_idleTimeout = undefined;
			}
		}	
		
		function Start() {
			 
			Stop();
			_idleTimeout = _tk.SetTimeout( OnIdle, _delay * 1000 );
		}

		this.AfterStateUpdate = function( thisFctName, state, source ) {
			
			if ( state.dialog.idle ) {
			
				_actionDid = state.dialog.idle.DID;
				_delay = state.dialog.idle.timeout;
			}
			
			if ( !state.dialog.idle && _isIdle || state.dialog.idle && _delay == 0 ) {
			
				Stop();
				_tk.RemoveEvent( window.document.documentElement, 'mousemove', Start );
				_isIdle = false;
				return;
			}

			if ( state.dialog.idle && !_isIdle ) {
			
				Start();
				_tk.AddEvent( window.document.documentElement, 'mousemove', Start );
				_isIdle = true;
				return;
			}
		}
	} 



	var acceleratorManager = new function() {
		
		function acceleratorHandler( keyCode, keyModifier, did ) {
		
			var gwcEvent = new gwc.Event();
			gwcEvent.Action(did);
			gwc.core.EventSink( 'Action', gwcEvent );
		}
		
		function AcceleratorParser( accelerator ) {
			
			if ( accelerator ) {

				var shift = accelerator.indexOf('ft-') != -1; 
				var ctrl = accelerator.indexOf('ol-') != -1;	 
				var alt = accelerator.indexOf('lt-') != -1;	 
				var keyName = accelerator.substr(accelerator.lastIndexOf('-')+1);
				
				var key = _tk.acceleratorToKeycode[keyName.toUpperCase()];
				if ( !key ) {
					
					key = shift ? keyName.toUpperCase() : keyName;
					shift = false;
				}

				var keyModifiers = (shift ? 1 : 0) + (ctrl ? 2 : 0) + (alt ? 4 : 0);
				return { key:key, keyModifiers:keyModifiers };
			}
		}
		
		this.AddDialog = function( thisFctName, dialog ) {
		
			for ( var idref in dialog ) {
				
				if ( dialog[idref].type == 'action' && dialog[idref].acceleratorName && dialog[idref].active ) {
	
					var info = AcceleratorParser( dialog[idref].acceleratorName );
					_core.keyManager.AddListener( info.key, info.keyModifiers, acceleratorHandler, dialog[idref].DID );
				}
			}
		}

		this.RemoveDialog = function( thisFctName, dialog) {
			
			for ( var idref in dialog ) {

				if ( dialog[idref].type == 'action' && dialog[idref].acceleratorName && dialog[idref].active  ) {
					
					var info = AcceleratorParser( dialog[idref].acceleratorName );
					_core.keyManager.RemoveListener( info.key, info.keyModifiers, acceleratorHandler );
				}
			}
		}

		this.SetDialogProperty = function( thisFctName, idref, prop, newVal, oldVal, dialog ) {
			
			if ( !dialog[idref] || dialog[idref].type != 'action' )
				return;
			
			if ( prop == 'acceleratorName' ) {
			
				if ( oldVal ) {
					
					var info = AcceleratorParser( oldVal );
					_core.keyManager.RemoveListener( info.key, info.keyModifiers, acceleratorHandler );
				}
				
				var info = AcceleratorParser( newVal );
				_core.keyManager.AddListener( info.key, info.keyModifiers, acceleratorHandler, dialog[idref].DID );
			} else
			if ( prop == 'active') {

				var info = AcceleratorParser( dialog[idref].acceleratorName );
				if ( info )
					if ( !newVal )
						_core.keyManager.RemoveListener( info.key, info.keyModifiers, acceleratorHandler );
					else
						_core.keyManager.AddListener( info.key, info.keyModifiers, acceleratorHandler, dialog[idref].DID );
			}
		}
	
		this.UnsetDialogProperty = function( thisFctName, idref, prop, currentVal, dialog ) {

			if ( !dialog[idref] || dialog[idref].type != 'action' )
				return;

			if ( prop == 'acceleratorName' ) {
			
				var info = AcceleratorParser( currentVal );
				_core.keyManager.RemoveListener( info.key, info.keyModifiers, acceleratorHandler );
			} else
			if ( prop == 'active' ) {
			
				var info = AcceleratorParser( dialog[idref].acceleratorName );
				if ( info )
					_core.keyManager.RemoveListener( info.key, info.keyModifiers, acceleratorHandler );
			}
		}
		
	} 


	function KeepAlive() {
		
		
		var _timer, _timeout, _url;
		var _url, _defaultHeaders = { 'Pragma':'no-cache', 'Cache-Control':'no-store, no-cache, must-revalidate' };
		var _keepAliveConnection = new _tk.HttpConnection();

		function DoKeepAlive() {

			_keepAliveConnection.Send( _url, undefined, _defaultHeaders, _tk.Noop );
			KeepAlive();
		}

		function KeepAlive(thisFctName, timeoutValue, url) {
		
			_tk.ClearTimeout(_timer);
			_timer = _tk.SetTimeout( DoKeepAlive, _timeout );
		}

		this.StartKeepAlive = function(thisFctName, url, timeout, pageLoadTime) {

			_url = url;
			timeout = timeout > 60 ? timeout - 15 : timeout * 0.75;
			_timeout = timeout * 1000;
			_timer = _tk.SetTimeout( DoKeepAlive, _timeout - pageLoadTime );
		}
		
		this.ResetKeepAlive = KeepAlive;
		this.StopKeepAlive = function(_) {

			_tk.ClearTimeout(_timer);
			_timer = undefined;
		}
	} 





	this.keyManager = new _tk.KeyManager( window.document ); 

	this.dispatcher = new _tk.CallDispatcher();

	var _state = this.state = new StateHandler( this.dispatcher.Dispatch );
	
	var connection = new Connection();
	var uiUpdater = new UiUpdater();
	var fieldMode = new FieldMode(this.state);
	var smartMode = new SmartMode(this.state);
	var stateUpdater = new StateUpdater();
	var keepAlive = new KeepAlive();
	var eventFilter = new EventFilter();

	this.dispatcher.AddListener(smartMode);
	this.dispatcher.AddListener(fieldMode);
	this.dispatcher.AddListener(acceleratorManager);
	this.dispatcher.AddListener(stateUpdater);
	this.dispatcher.AddListener(connection);
	this.dispatcher.AddListener(idleManager);
	this.dispatcher.AddListener(uiFreezer);
	this.dispatcher.AddListener(keepAlive);
	
	this.output = new _tk.EventDispatcher(_tk.Noop);
	this.connect = new _tk.EventDispatcher(this.output.Dispatch);
	this.input = new _tk.EventDispatcher(this.connect.Dispatch);
	this.EventSink = this.input.Dispatch;

	this.input.AddListener(eventFilter);
	this.input.AddListener(keepAlive);
	this.input.AddListener(new InterruptManager(connection));
	this.input.AddListener(fieldMode);
	this.input.AddListener(smartMode);
	this.input.AddListener(new EventTranslator());
	this.input.AddListener(uiFreezer);
	


	this.connect.AddListener(connection);

	this.output.AddListener(uiFreezer);	
	this.output.AddListener(new ResponseParser());
	this.output.AddListener(stateUpdater);
	this.output.AddListener(uiUpdater);
	this.output.AddListener(eventFilter);





//
	this.DocumentLoaded = function() {

		if ( _tk.isIe )
			window.offscreenBuffering = true; 
	
		gwc.loadTime = (new Date()).getTime()-gwc.initTime;
		
		_core.EventSink('DocumentLoaded');

		_core.EventSink('StartKeepAlive', gwc.cfg.keepaliveURL, gwc.cfg.keepaliveInterval, gwc.loadTime); 

		var deferedDispatcher = new _tk.DeferedCallDispatcher( gwc.core.dispatcher.Dispatch );
		_state.Init( gElementMarkTree, gComponentList, gDialog, deferedDispatcher.Dispatch );
		deferedDispatcher.Flush();

		gwc.core.dispatcher.Dispatch( 'AfterStateUpdate', _state, gwc.EXTERNAL );
		




		
		_core.EventSink('InitializationDone');
	}

	this.Init = function() {
		
		function loadHandler() { 
			
			gwc.core.DocumentLoaded();
			_tk.RemoveEvent( window, 'load', loadHandler );
		}
		
		_tk.AddEvent( window, 'load', loadHandler );
	}
}




/////////////////////////////////////////////////////////////////////////////

//

//

gwc.capi = {

	Commit:function(did) {
		
		var gwcEvent = new gwc.Event();
		gwc.core.EventSink('Commit',gwcEvent );
	},

	SessionVar:function(varName, value) {
		
		var gwcEvent = new gwc.Event();
		gwcEvent.SessionVar(varName, value);
		gwc.core.EventSink('SessionVar',gwcEvent );
	},

	Action:function(did) {
		
		var gwcEvent = new gwc.Event();
		gwcEvent.Action(did);
		gwc.core.EventSink('Action',gwcEvent );
	},

	SortColumn:function(did) {

		var gwcEvent = new gwc.Event();
		gwcEvent.Action(did);
		gwc.core.EventSink('Action',gwcEvent );
	},

	Key:function(key) {

		var gwcEvent = new gwc.Event();
		gwcEvent.Key(key);
		gwc.core.EventSink('Key',gwcEvent );
	},
	
	NextField:function() {





		var gwcEvent = new gwc.Event();
		gwcEvent.Action(gwc.core.state.ActionDidByName('nextfield'));
		gwc.core.EventSink('Action', gwcEvent);
	},
	
	Focus:function(cid) {

		if ( gwc.core.state.ComponentHasFocus(cid) ) 
			return;
		var gwcEvent = new gwc.Event();
		gwcEvent.Focus(gwc.core.state.IdrefByCid(cid));
		gwc.core.EventSink('Focus',gwcEvent);
	},

	Typing:function(cid) {

		gwc.core.EventSink('Typing', { idref:gwc.core.state.IdrefByCid(cid) });
	},

	Offset:function( idref, offset ) {

		var gwcEvent = new gwc.Event();
		gwcEvent.Offset(idref, offset);
		gwc.core.EventSink('Offset',gwcEvent );
	},

	SelectTableRow:function( tableIdref, rowIndex ) {
	



		var gwcEvent = new gwc.Event();
		gwcEvent.Row(tableIdref, rowIndex);
		gwc.core.EventSink('SelectTableRow',gwcEvent );
	},
	
	SelectMatrixItem:function( cid, rowIndex ) {
	
		var gwcEvent = new gwc.Event();
		gwcEvent.Row(gwc.core.state.DialogInfoByCid(cid).parentIdref, rowIndex);
		gwc.core.EventSink('SelectMatrixItem',gwcEvent );
	},

	Rest:function() {
	
		var gwcEvent = new gwc.Event();
		gwcEvent.Rest();
		gwc.core.EventSink('Rest', gwcEvent );
	},

	Defer:function(cid, functionName, argArray) {

		gwc.core.EventSink('Defer', cid, functionName, argArray);
	}
}
/////////////////////////////////////////////////////////////////////////////

gwc.core.Init();


//var gAction = gwc.capi.Action;
//var gFocus = gwc.capi.Focus;
//var gTyping = gwc.capi.Typing;


