function IGrid(
 thecontainer,	// container
 theclass,	// classname
 thebodystr,	// grid body
 theheadstr,	// grid header Col1~..~ColN
 tabind,	// tabindex
 theW,		// initial width  -4 :)
 theH,		// initial height -4 :)
 thecolhdr,	// column attributes (COLGROUP) col1~..~colN
 thebordertype,	// border type : r,c,rc
 dummy,		// not used ( was - cellspacing )
 thepadding,	// cellpadding
 theleftcolno,	// left column number or 0
 theselmode	// selection mode (0,1,2)
) {
 var me  = this ;
// passed properties
 me.holder	= thecontainer;
 me.classname	= theclass;
 me.bodystr	= thebodystr;
 me.headstr	= theheadstr;
 me.tabstop	= parseInt(tabind,10) ;
 me.W		= parseInt(theW,10)+4;
 me.H		= parseInt(theH,10)+4;
 me.colhdr	= thecolhdr?thecolhdr:"";
 me.border	= thebordertype;
 me.cellpadd	= parseInt(thepadding,10) ;  //    Cellpadding = ?
 me.leftcolno	= parseInt(theleftcolno,10) ;
 me.selmode	= parseInt(theselmode,10) ;
/*=====  Public Methods  ============
init		([Row],[Col])
makesel 	( Row ,[Col])
setsize 	(Width-4,Height-4)
refreshHDR 	()
multisel	(Row,[Col],[true/false])
multiclear	()
updateHTML	(Row,Col,HTML)
getRC		([SrcElement],[SelMode])
print		([Doc Title],[Hidden frame window])
focus 		()
blur		()
srt 		(Sort Index,Sort value=ADad)
updown          (+1:down; -1:up)
rile            (-1:left; +1:right)
=====  Public Events  ============
		onready()
bool 		onbeforechange(newR,newC)
		onchange()
bool 		onbeforemultichange(newR,newC)
		onmultichange('R:C')
		onsortchange()
		onhscroll(scrollLeft)
		onmouseclicked()
		onclick()
		ondblclick()
sPopup		onbeforepopup()
		onpopupcmd(sPopup command)
keyCode		onkeydown(keyCode)
		postformat(this)
*/
//
// runtime properties
//
me.AssignRuntimeProps = function() {

 me.doc				= me.holder.document;
 me.win				= me.doc.parentWindow;
 me.win.attachEvent('onunload',function(){me.Kill()});

 // multiselection colors
 me.Multibackgroundcolor	= 'khaki';
 me.Multiforegroundcolor	= 'blue';
 me.Multibackgroundselected	= 'darkgoldenrod';
 me.Multiforegroundselected	= 'white';

 // 3D button colors
 me.BtnBackground		= 'threedface';
 me.BtnBorderColor		= 'threeddarkshadow'; // new
 me.BtnBorderColorLight		= 'threedhighlight';  // new
 me.BtnBorderColorDark		= 'threedshadow';     // new

 // text colors
 me.bordercolor			= 'threedshadow' ;
 me.backgroundcolor		= 'window';
 me.foregroundcolor		= 'windowtext';
 me.backgroundselected		= 'highlight';
 me.foregroundselected		= 'highlighttext';
 var blackFace			= 0;
 try{blackFace=me.doc.body.currentStyle.scrollbarFaceColor=='#000000'}catch(e){};
 me.backgroundblured		= blackFace?me.backgroundselected:'threedlightshadow';
 me.foregroundblured		= blackFace?me.foregroundselected:'windowtext';

 // extended attributes
 me.lsclassname			= me.classname; // class name for left column
 me.wrapcells			= 0; 		// new - allow wrap cells
 me.cbxExtraText		= "";		// extra text for checkboxes
 me.imgpath			= "/img/"+(me.doc.location.protocol.search(/http/i)?'':'');
 me.EnableMultiselect		= false;	// enable multiselect
 me.HdrSortState		= [];		// sort state array
 me.Multiselected		= [];		// selected items array

 // local(private) properties
 me.frm	=  me.frmc		= 0;
 me.ach				= [];
 me.MakeStyle(1);

 me.maintab			= me.doc.all[me.holder.id+"_main"];
 me.focusto			= me.doc.all[me.holder.id+"_main"] ;// me.holder ;
}

me.Kill = function() {
 if (me.gs) {
   me.gs.onclick	=null;
   me.gs.ondblclick	=null;
   me.gs.onscroll	=null;
   me.gs.onmouseup	=null;
 }
 if (me.focusto) {
   me.focusto.onkeydown =null;
   me.focusto.onblur	=null;
   me.focusto.onfocus	=null;
 }
 me.holder.innerHTML='';
 for (var key in me) delete me[key];
}

me.focus = function()  {
  try {me.focusto.focus();} catch (e) {};
}

me.blur	   = function()  {
 me.SetColors(true);
 me.savescrTop  = me.gs.scrollTop ;
 me.savescrLeft = me.gs.scrollLeft ;
}

me.MakeStyle = function(first) {
 me.aBtnBorderColor		= [me.BtnBorderColorLight,me.BtnBorderColorDark ,me.BtnBorderColorDark ,me.BtnBorderColorLight];
 me.aBtnBorderColorPressed	= [me.BtnBorderColorDark ,me.BtnBorderColorLight,me.BtnBorderColorLight,me.BtnBorderColorDark ];
 me.sm			= me.selmode;
 if (!me.nodataHTML)   me.nodataHTML = '<SPAN class="'+me.classname+'" style="font-weight:bold;color:navy">No data available</SPAN>';
 switch(me.border){
  case 'rc': me.borderrules="ALL" ;break;
  case 'r' : me.borderrules="ROWS";break;
  case 'c' : me.borderrules="COLS";break;
  default  : me.borderrules="NONE";
 }
 me.ahead=[];
 if (me.headstr) me.ahead=(me.headstr.constructor==String)?[me.headstr]:me.headstr;
 me.ach=me.colhdr.split('~');
 if (me.ahead.length) me.MakeAch();
 me.colgroup = me.ach.length? ("<COLGROUP><COL " + me.ach.join("><COL ")+"><TBODY>"):"";

 if (first) {
   me.holder.innerHTML	=
    "<TABLE CELLPADDING=0 CELLSPACING=0 id='"+me.holder.id+"_main'"+
     " TABINDEX="+me.tabstop+ " class="+me.classname+" BGCOLOR="+me.backgroundcolor+
     " style='border:1px solid;border-color:"+[me.BtnBorderColorDark,me.BtnBorderColorLight,me.BtnBorderColorLight,me.BtnBorderColorDark].join(' ') +"'" +
     " WIDTH="+me.W+" HEIGHT="+me.H+">" +
     "<TR HEIGHT=100% style='vertical-align:middle;' VALIGN=MIDDLE>"+
     "<TD WIDTH=100% ALIGN=CENTER"+
     " style='color:navy;border:1px solid;border-color:"+[me.BtnBorderColor,me.BtnBackground,me.BtnBackground,me.BtnBorderColor].join(' ')+ "'>" +
     " Loading, please wait ..." +
    "</TABLE>" ;
  }
}
//  extend ach(colhdr),if need
me.MakeAch = function() {
  var newh,i,COLS=0;
  String("~"+me.ahead[0]).
    replace(/~\#\d+,(\d+)/g,function($0,$1){COLS+=parseInt($1,10);return ""}).
    replace(/~\^(\d+)/g    ,function($0,$1){COLS+=parseInt($1,10);return ""}).
    replace(/~/g	   ,function($0)   {COLS+=1;return "~"});
  me.ach[COLS-1]=me.ach[COLS-1]?me.ach[COLS-1]:"";
  while (me.ach.length > COLS++) me.ahead[0]+='~';
}

me.MakeCrossText = function() {
 var txt;
 if (me.headstr && me.leftcolno!=0)
   txt=me.getColName(me.leftcolno).pop();
 if (txt) return  "&nbsp;"+txt+"&nbsp;";
 return "&nbsp;";
}

me.init = function(il,ic) {
 me.initLine = (il)?il:0;
 me.initCol  = (ic)?ic:0;
 me.Multiselected	= []; // array of selected strings [row 1] = (1~2~5) (1-based)) or "1" ( selmode=1 )
 me.ColorPool		= [];
 me.MakeStyle();
 me.crosstext		= me.MakeCrossText();
 me.CreateHtml();
 me.maintab		= me.doc.all[me.holder.id+"_main"];
 me.focusto		= me.doc.all[me.holder.id+"_main"] ; // new contents of _main=> reassign
 if (me.headstr)
   me.hs		= me.doc.all[me.holder.id+"_head"] ;
 if (me.leftcolno!=0)
   me.ls		= me.doc.all[me.holder.id+"_lcol"] ;
 if (me.headstr && me.leftcolno!=0)
   me.crosstd		= me.doc.all[me.holder.id+"_cross"] ;
 me.gs			= me.doc.all[me.holder.id+"_grid"] ;
 me.grid		= me.doc.all[me.holder.id+"_tbl" ] ;
 me.lines		= me.nodata?0:(me.grid.rows.length - me.ahead.length);
 me.hsheight            = 0 ;
 me.MakeHeader();
 me.lsprefwidth		= 0 ; // preffered width of leftspan
 me.lsactwidth		= 0 ; // actual width of leftspan
 me.MakeLeftCol();
 me.refreshHDR();
 me.W			= me.lsactwidth + me.gs.offsetWidth + me.lbpx ;
 me.H			= me.hsheight   + me.gs.offsetHeight+ me.tbpx;
 me.selectedLine	= 0 ;
 me.selectedCol		= 0 ;
 me.cs			= null;
 me.cr			= null;
 me.savescrTop		= 0 ;
 me.savescrLeft		= 0 ;
 me.holder.onselectstart= me.GRID_retfalse;
 me.holder.onselectstart= me.GRID_retfalse;
 me.gs.me		= me;
 me.gs.onscroll		= me.GS_onscroll;
 if (me.sm>0) {
   me.gs.onclick	= me.GS_onclick;
   me.gs.ondblclick	= me.GS_ondblclick;
   me.gs.oncontextmenu	= me.GS_onmousedown;
 }
 me.focusto.me		= me;
 me.focusto.onkeydown	= me.GRID_onkeydown;
 me.focusto.onfocus	= me.GRID_onfocus;
 me.focusto.onblur	= me.GRID_onblur;
 //-- Initialization code ----------------------------
 me.focusto.tabIndex	= me.tabstop;
 me.makesel(me.initLine,me.initCol);
 me.ready = true;
 if (me.onready)  me.onready();
}

me.srt = function(ind,setval) {
 for (var key in me.HdrSortState) {
   me.HdrSortState[key]=(ind!=key) ? me.HdrSortState[key].toLowerCase():setval;
 }
 me.RefSortState();
}

me.CreateHtml = function() {
 if (me.bodystr.replace(/ /g,"") =='') {
   me.nodata = true;
   var  i,hidcols=0,totcols=me.ach.length;
   for (i=0;i<totcols;i++) {
     if (me.ach[i].search(/[=;'" ]display[:=]none/i)<0) break;
     hidcols++;
   }
   me.tb = "<TR style='height:100%;vertical-align:middle;'>";
   if (hidcols) me.tb+="<TD COLSPAN="+hidcols+">";
   me.tb+= "<TD COLSPAN="+(totcols-hidcols)+" ALIGN=CENTER style='vertical-align:middle;border-bottom:none'>"+me.nodataHTML;
   me.sm=0;
 } else {
   me.nodata = false;
   me.MakeBody(); // => me.tb
   if (me.postformat) me.postformat(me);  // => me.tb updated
 }
 var mainstyle			= [
   'cursor:default',
   'border-top   :1px solid '+me.BtnBorderColorDark,
   'border-left  :1px solid '+me.BtnBorderColorDark,
   'border-right :2px inset '+me.BtnBorderColorLight,
   'border-bottom:2px inset '+me.BtnBorderColorLight,
   ''
 ].join(';');

 var as = [];
 as[as.length]= "<table id='"+me.holder.id+"_main'"+
 		" TABINDEX="+me.tabstop+" cellpadding=0 cellspacing=0 border=0"+
		" style='" + mainstyle + "' class='"+me.classname+"'>" ;
 var lborder=(!me.leftcolno)?"style='border-left:1px solid "+me.BtnBorderColor+"'":'';
 me.lbpx = lborder?4:3;
 var tborder=(!me.headstr  )?"style='border-top :1px solid "+me.BtnBorderColor+"'":'';
 me.tbpx = tborder?4:3;
 if (me.headstr) {
   as[as.length]="<tr>" ;
   if (me.leftcolno != 0)  {
      as[as.length]="<td height=100% id='"+me.holder.id+"_cross' nowrap "+
      "style='background-color:"+me.BtnBackground+";border:1px solid "+me.BtnBorderColor+";'>"+
      "<TABLE class='"+me.classname+"' width=100% height=100% cellspacing=0 cellpadding=0"+
      " style='table-layout:fixed;border:1px solid;border-color:"+me.aBtnBorderColor.join(' ')+';'+"'>"+
      "<TR><TD align=center>"+me.crosstext+
      "</TABLE>"+
      "</TD>";
   }
   as[as.length]= "<td nowrap  align=left valign=top "+lborder+">"+
		  "<span id='"+me.holder.id+"_head' style='width:"+(me.W-me.lbpx)+"px;overflow:hidden;background-color:"+me.BtnBackground+"'></span>" ;
 }
 as[as.length]="<tr>" ;
 if (me.leftcolno != 0 ){
   as[as.length]= "<td nowrap align=left "+tborder+">" +
	   	  "<span id='"+me.holder.id+"_lcol' style='height:"+(me.H-me.tbpx)+"px;overflow=hidden;background-color:"+me.BtnBackground+"'></span>" ;
 }
 as[as.length] = "<td nowrap align=left valign=top "+lborder+" "+tborder+">" +
	"<span id='"+me.holder.id+"_grid'"+
	" style='width:"+(me.W-me.lbpx)+"px;height:"+(me.H-me.tbpx)+"px;overflow:auto;background-color:"+me.backgroundcolor+"'>" +
	"<TABLE WIDTH=100% "+((me.nodata)?"HEIGHT=100%":"")+
	" ID='"+me.holder.id+"_tbl' CLASS='"+me.classname+"' CELLSPACING=0 CELLPADDING="+me.cellpadd+
	" FRAME="+(me.headstr || me.border.indexOf("r")<0?"VOID":"BELOW")+
	" RULES="+me.borderrules+
	" style='border-collapse:collapse;border:none;position:relative;left:-1;'"+
	" BORDER=1 BORDERCOLOR="+me.bordercolor+" BGCOLOR="+me.backgroundcolor+">";

 as[as.length]=me.colgroup;
 as[as.length]=me.tb;
 //me.tb=null;
 if (me.headstr) {
   var hb=me.GetHdrBody("style='border:none;padding:0 0 0 5'","style='visibility:hidden;'");
   hb = hb.replace(/\x7B[ADad]\x7D/g,"<IMG align=absmiddle WIDTH=8 HEIGHT=7 SRC='"+me.imgpath+"sort_emp.gif' style='visibility:hidden'>")
   as[as.length]=hb;
   hb=null;
 }
 as[as.length]= "</table></span></tr></table>" ;
 me.holder.innerHTML = as.join('') ;
 as=null;
}

me.getColName = function (colNum) {
 var MAXCOL=-1,HNAM=[],ret=[],ahl=me.ahead.length,str,row,col,cols,i,j;
 for (row=0;row<ahl;row++) HNAM[row]=[];
 for (row=0;row<ahl;row++) {
   me.ahead[row].replace(/\{[ADad]\}/g,"").replace(/&nbsp[;]?/gi," ").
   replace(/(?:^|~)(\^\d+|\%\d+|\#\d+,\d+)?([^~$]*)/g,
     function($0,$1,$2){
       var csp=1,rsp=1;
       if ($1) {
         var a=$1.substr(1).split(','),a0=parseInt(a[0],10);
         switch ($1.substr(0,1)) {
         case '^': csp=a0;break;
         case '#': csp=parseInt(a[1],10);
         case '%': rsp=a0;break;
       } }
       if (rsp>ahl-row) rsp=ahl-row;
       var col=HNAM[row].length;
       for (j=0;j<col;j++) if (HNAM[row][j]==null){col=j;break;}
       if (colNum<0 && col+csp>MAXCOL) MAXCOL=col+csp;
       str=$2.replace(/(^\s*)|(\s*$)/g, "");
       for (i=0;i<rsp;i++) {
         for (j=0;j<csp;j++) HNAM[row+i][col+j]=str;
         str="";
 } } ); }
 for (row=0;row<ahl;row++) if(str=HNAM[row][colNum+MAXCOL]) ret.push(str);
 return ret;
}

me.GetHdrBody =  function(tdins,trins,tr0pfx,tr0sfx) {
 var hh,i,atr=[],tdpfx="<TD "+tdins+" NOWRAP ";
 if (!tr0pfx) tr0pfx="";
 if (!tr0sfx) tr0sfx="";
 for (i=0;i<me.ahead.length;i++) {
   hh = ('~'+me.ahead[i]).
     replace(/~\#(\d+),(\d+)/g,	tdpfx+"ROWSPAN=$1 COLSPAN=$2>&nbsp;").
     replace(/~\%(\d+)/g,	tdpfx+"ROWSPAN=$1>&nbsp;").
     replace(/~\^(\d+)/g,	tdpfx+"COLSPAN=$1>&nbsp;").
     replace(/~/g,		tdpfx+">&nbsp;");
   hh = '<'+hh.substr(1).replace(/<TD /g,"&nbsp;<TD ") + "&nbsp;";
   atr[atr.length]= "<TR "+trins+">" + tr0pfx + hh + tr0sfx + "</TR>";
   tr0pfx="";
   tr0sfx="";
 }
 return atr.join("");
}

me.MakeHeader = function() {
 if (!me.headstr) return ;
 var tdins=" align=center class='"+me.classname+"' style='"+
  "padding:1;background-color:"+me.BtnBackground+";border:1px solid;"+
  "border-color:"+me.aBtnBorderColor.join(' ')+";'";
 var hb=me.GetHdrBody(tdins,"",
   "<td ROWSPAN="+me.ahead.length+" style=width:0>",
   "<td ROWSPAN="+me.ahead.length+" style=width:2000 "+tdins+">&nbsp;"
 );
 var aLetters=[];
 hb=hb.replace(/(\{[ADad]\})/g,function($0,$1) {
   var dsp1=dsp2=dsp3='none';
   var char=$1.substr(1,1);
   aLetters[aLetters.length]=char;
   switch (char) {
   case 'A': dsp1 = 'inline' ;  break;
   case 'D': dsp2 = 'inline' ;  break;
   default : dsp3 = 'inline' ;  break;
   }
   var impfx="<IMG WIDTH=8 HEIGHT=7 align=absmiddle SRC='"+me.imgpath;
   return ""+
    impfx+"sort_asc.gif'  style=display:"+dsp1+">"+
    impfx+"sort_desc.gif' style=display:"+dsp2+">"+
    impfx+"sort_emp.gif'  style=display:"+dsp3+">";
 });
 var i,ow,aCols=[],cols = me.grid.getElementsByTagName('COLGROUP')[0].children;
 for  (i=0;i<cols.length;i++) {
   ow = cols(i).offsetWidth-1;
   aCols[aCols.length]= "<col "+(ow<1?"style=display:none":"width="+ow)+">";
 }
 ss =
  "<table ID='"+me.holder.id+"_hdrtbl' style='table-layout:fixed;position:relative;left:-1'"+
  " border=0 cellspacing=1 cellpadding=0 height=100% bgcolor="+me.BtnBorderColor+">"+
  "<colgroup><col>"+aCols.join("")+"<col width=2000></colgroup>"+
  hb+
  "</table>" ;
 me.hs.innerHTML = ss;
 me.hstab      = me.doc.all[me.holder.id+"_hdrtbl"] ;
 me.hsheight   = me.hstab.offsetHeight ;
 var newh = me.gs.offsetHeight-me.hsheight;
 if (newh<40) newh = 40 ;
 me.gs.style.height    = newh ;
 if (me.ls&&me.leftcolno!=0) me.ls.style.height = newh;
 // prepare handlers + HdrSortState
 me.HdrSortState=[];
 var i,j,tds,tdl,td,iLet=0,offset=0;
 for (i=0;i<me.hstab.rows.length;i++) {
   tds=me.hstab.rows(i).cells;
   tdl=tds.length-(i==0?1:0);
   for (j=0;j<tdl;j++) {
     td=tds(j);
     if (td.getElementsByTagName('IMG').length) {
       me.HdrSortState[offset]=aLetters[iLet++];
       td.me		= me;
       td.ssoffset	= offset;
       td.onclick 	= me.BTN_onclick;
       td.onmousedown	= me.BTN_ondown;
       td.onmouseup	= me.BTN_onup;
       td.onmouseout	= me.BTN_onup;
     }
     offset++;
   }
 }
}

me.BTN_ondown = function() {
 var me=this.me;
 var td=this;
 td.style.borderColor	= me.aBtnBorderColorPressed.join(' ');
 td.style.padding	= '2 0 0 2';
}

me.BTN_onup   = function() {
 var me=this.me;
 var td=this;
 td.style.borderColor   = me.aBtnBorderColor.join(' ');
 td.style.padding=1;
}

me.BTN_onclick  = function() {
 var me=this.me;
 var td=this;
 var key,val;
 for (key in me.HdrSortState) {
   val  = me.HdrSortState[key];
   if (td.ssoffset != key)  val = val.toLowerCase();
   else  val = (val=='a'||val=='d')?val.toUpperCase():(val=='A')?'D':'A';
   me.HdrSortState[key]=val;
 }
 me.RefSortState();
 if (me.onsortchange)  me.onsortchange();
}

me.refreshHDR = function() {
 if (!me.headstr) return ;
 var i,ow,gcols,hcols;
 gcols = me.grid .getElementsByTagName('COLGROUP')[0].children;
 hcols = me.hstab.getElementsByTagName('COLGROUP')[0].children;
 for (i=0;i<gcols.length;i++) {
   ow = gcols(i).offsetWidth-1;
   hcols(i+1).style.display=ow>0?'':'none';
   if (ow>0) hcols(i+1).width=ow;
 }
 me.ScrollHdr();
}

me.MakeBody = function() {
 var tdpfx = me.wrapcells?'<TD ':'<TD NOWRAP ';
 var tb = '|' + me.bodystr + "</TR>";
 me.tb = tb.
  replace(/(\x7C)({)([a-z]*)(,)([a-z]*)(})/gi,			"</TR><TR style='color:$3;background-color:$5;'>~"). // |{fore,back}
  replace(/(\x7C)({#)([a-z]*)(#})/gi,				"</TR><TR class=$3>~").// |{#classname#}
  replace(/\x7C/g,						"</TR><TR>~").                                                                   // |
  substr(5).					// skip first </TR>
  replace(/~[ ]*~/g,"~&nbsp;~").replace(/~[ ]*~/g,"~&nbsp;~").
  replace(/~[ ]*<\/TR\>/g,"~&nbsp;</TR>").	// ~</TR>
  replace(/(~\x23)(\d+),(\d+)/g,                 		tdpfx+"rowspan=$2 colspan=$3>"). 				// ~#nnn,ddd     = > ROWSPAN=nnn COLSPAN=ddd
  replace(/(~\x25)(\d+)/g,                       		tdpfx+"rowspan=$2>"). 						// ~%nnn = > ROWSPAN=nnn
  replace(/(~\x5E)(\d+)/g,                       		tdpfx+"colspan=$2>"). 		  				// ~^nnn = > COLSPAN=nnn
  replace(/(~)({)([a-z0-9#]*)(,)([a-z0-9#]*)(})(\x25)(\d+)/gi,	tdpfx+"rowspan=$8 style='color:$3;background-color:$5;'>"). 	// ~%nnn   = > ROWSPAN=nnn
  replace(/(~)({)([a-z0-9#]*)(,)([a-z0-9#]*)(})/gi,		tdpfx+"style='color:$3;background-color:$5;'>").		// ~^nnn   = > COLSPAN=nnn
  replace(/(~)({#)([a-z]*)(#}\x25)(\d+)/gi,      		tdpfx+"rowspan=$5 class=$3>"). 		// ~{#classname#}%nnn    = > ROWSPAN=nnn+Class
  replace(/(~)({#)([a-z]*)(#}\x5E)(\d+)/gi,      		tdpfx+"colspan=$5 class=$3>").		// ~{#classname#}^nnn    = > COLSPAN=nnn+Class
  replace(/(~)({#)([a-z]*)(#})/gi,               		tdpfx+"class=$3>").
  replace(/~/g,                                  		tdpfx+">").
  replace(/\x7B\x5ECB\x2B\x7D/g,"<INPUT "+me.cbxExtraText+" TYPE=CHECKBOX CHECKED>").                               // {^CB+}
  replace(/\x7B\x5ECB\x2D\x7D/g,"<INPUT "+me.cbxExtraText+" TYPE=CHECKBOX>");                                       // {^CB-}
}

me.RefSortState = function() {
 var i,offset,img,ri,ci,ahd,td,tds=me.hstab.getElementsByTagName('TD');
 for (i=0;i<tds.length;i++) {
   td=tds(i);
   if (!(offset=td.ssoffset)) continue;
   img=td.getElementsByTagName('IMG');
   var dsp1 = dsp2 = dsp3 = 'none' ;
   switch (me.HdrSortState[offset]) {
     case 'A' : dsp1 = '' ; break ;
     case 'D' : dsp2 = '' ; break ;
     default  : dsp3 = '' ; break ;
   }
   img[0].style.display = dsp1 ;
   img[1].style.display = dsp2 ;
   img[2].style.display = dsp3 ;
   ri = td.parentElement.rowIndex;
   ci = td.cellIndex;
   if (ri==0) ci--;
   ahd=me.ahead[ri].split('~');
   ahd[ci]=ahd[ci].replace(/\{[ADad]\}/g,'{'+ me.HdrSortState[offset]+'}');
   me.ahead[ri]=ahd.join('~');
 }
 me.headstr=(me.headstr.constructor==String)?me.ahead[0]:me.ahead;
}

me.MakeLeftCol = function() {
 if (me.leftcolno==0) return ;
 var as=[];
 as[as.length] =
   "<table ID='"+me.holder.id+"_lcoltbl' cellpadding=0 border=0 cellspacing=1 bgcolor="+me.BtnBorderColor+
   " style='visibility:hidden;position:relative;top:-1;'" +
   "><tr><td height=1px>" ;
 var tdborder = '1px solid;border-color:'+me.aBtnBorderColor.join(' ')+';';
 if (!me.nodata) {
   var dh=0;
   for (var j=0; j< me.lines ; j++)  {
     var tr = me.grid.rows(j);
     var she="height:"+(tr.offsetHeight+dh)+"px;";
     as[as.length] =
	"<tr style='"+she+"'>"+
	"<td nowrap class='"+me.lsclassname+"' style='"+
	"border:"	    +tdborder + she+
	"background-color:" +me.BtnBackground+";"+
	"'>";
     var cellno = (me.leftcolno>0)?(me.leftcolno-1):(tr.cells.length+me.leftcolno);
     if (cellno>=0 && cellno<tr.cells.length) {
       as[as.length]=String('&nbsp;'+tr.cells(cellno).innerHTML+'&nbsp;').replace(/&shy;/gi,' ');
     }
     as[as.length] = "</td></tr>";
     dh=-1;
   }
 }
 as[as.length] =
   "<tr><td nowrap valign=bottom height=2000 style='"+
   "border:2px solid "+me.BtnBackground+";"+
   "background-color:"+me.BtnBackground+";"+
   "'>"+me.crosstext+"</tr></table>" ;
 me.ls.innerHTML= as.join('');
 as = null;
 var lstab      = me.doc.all[me.holder.id+'_lcoltbl']   ;
 me.lsprefwidth = lstab.offsetWidth ;

 lstab.style.tableLayout	= 'fixed' ;
 lstab.width			= me.lsprefwidth ;
 lstab.rows(0).style.display	= 'none' ;
 lstab.rows(lstab.rows.length-1).height = 2000 ;

 // justifying
 var newgsw             = me.CalcGsWidth(me.gs.offsetWidth-me.lsprefwidth) ;
 lstab.width            = me.lsactwidth;
 me.ls.style.width      = me.lsactwidth;
 if (me.crosstd)
   me.crosstd.width	= me.lsactwidth; //-4 ;
 me.gs.style.width	= newgsw;
 if (me.hs)
   me.hs.style.width	= newgsw;
 lstab.style.visibility = 'inherit';//'visible' ;
}

me.setsize = function(theW,theH) {
 if (!me.ready) return ;
 var newW=theW+4,newH=theH+4;
 try {
   for (var attempts=0;attempts<2;attempts++) {
     if (me.hstab) me.hsheight = me.hstab.offsetHeight;

     var newgsh = newH - me.hsheight-me.tbpx ;
     if (newgsh < 40) newgsh = 40 ;
     me.gs.style.height = newgsh ;
     me.gs.scrollTop+=0; // Do not touch !! invalid (+- scrollbars) size workaround
     if (me.ls&&me.leftcolno!=0) me.ls.style.height = newgsh ;

     var newgsw  = me.CalcGsWidth(newW-me.lsprefwidth-me.lbpx) ;
     if (me.lsactwidth>0) {
       me.doc.all[me.holder.id+'_lcoltbl'].width= me.lsactwidth ;
       me.ls.style.width = me.lsactwidth ;
       if (me.crosstd) me.crosstd.width = me.lsactwidth;
     }
     me.gs.style.width              = newgsw;
     if (me.hs)  me.hs.style.width  = newgsw;

     me.W  = me.lsactwidth + me.gs.offsetWidth + me.lbpx;
     me.H  = me.hsheight   + me.gs.offsetHeight+ me.tbpx;

     me.refreshHDR();
     if (!me.hstab || me.hsheight==me.hstab.offsetHeight) break;
   }
   me.Justify();
 } catch(e) {}
}

me.CalcGsWidth = function(newgsw) {
 me.lsactwidth= me.lsprefwidth ;
 if (newgsw<40) {
  if (!me.ls||me.leftcolno==0)
    newgsw = 40 ;
  else {
    me.lsactwidth = me.lsprefwidth + newgsw - 40 ;
    newgsw = 40 ;
    if (me.lsactwidth < 10) me.lsactwidth = 10 ;
 }}
 return newgsw ;
}

me.showsel = function(SnewR,SnewC) {
 var snapSm=me.sm;  
 if (typeof(SnewR)=='undefined') {
   if (me.cs) {
     me.sm = (me.cs.tagName=='TD')?2:1;
     me.StandardColor();
     me.selectedLine= 0;
     me.selectedCol = 0;
     me.cr          = null;
     me.cs          = null;
   }  
 } else {
   me.sm = (typeof(SnewC)=='undefined') ? 1:2;
   me.makesel(SnewR,SnewC);
 }
 me.sm = snapSm;
}  

//// newR       newC = 1..nnn or 0/-1 : set first/last visible row/cell
me.makesel = function(SnewR,SnewC,jopmouse) {
 if (me.sm      == 0)  return ;
 var newR = parseInt(SnewR,10);
 var newC = parseInt(SnewC,10);
 if (newR<1) {
   if (newR == 0) {
     for (newR=1;newR<=me.lines;newR++) if (me.IsRowEnabled(newR)) break ;
   } else {
     for (newR=me.lines;newR>0 ;newR--) if (me.IsRowEnabled(newR)) break ;
 } }
 if (newR>me.lines) newR = me.lines ;
 if (newR<1    ) newR = 1     ;

 var aRow = me.grid.rows(newR-1) ;
 if (me.sm==2) {
   var cols = aRow.cells.length ;
   if (newC == 0) {
     for (newC=1;newC<=cols;newC++) if (me.IsColEnabled(aRow,newC)) break ;
   } else if (newC== -1) {
     for (newC=cols;newC >0;newC--) if (me.IsColEnabled(aRow,newC)) break ;
   } else if (newC==me.selectedCol && newR != me.selectedLine && !jopmouse) {
     var offneed = me.grid.rows(me.selectedLine-1).cells(me.selectedCol-1).offsetLeft;
     for (newC=cols; newC>0 ;newC--) {
       if (me.IsColEnabled(aRow,newC) && aRow.cells(newC-1).offsetLeft<=offneed)  {
	 break;
     } }
     if (newC<1) newC=1;
 } }
 if (me.onbeforechange && me.onbeforechange(newR,newC)==false) return;

 if (me.win.event && (me.win.event.ctrlKey || me.win.event.shiftKey || me.win.event.keyCode==32)) {
   if (me.onbeforemultichange && me.onbeforemultichange(newR,newC)==false) {} else {
      me.InvertSelection(newR,newC);
   }
 }
 if (me.selectedLine > 0 && (me.selectedLine!=newR || me.selectedCol!=newC)) {
   if (me.Multiselected[me.selectedLine + ':' + ((me.sm == 1)?'0':me.selectedCol)]) {
     me.SpecificColor(me.Multibackgroundcolor,me.Multiforegroundcolor);
   } else {
     me.StandardColor();
   }
 }
 var NewSelFlag =  (me.selectedLine != newR  || (me.selmode==2 && me.selectedCol != newC)) ? true : false ;
 me.selectedLine= newR ;
 me.selectedCol = newC ;
 me.cr          = me.grid.rows(newR-1) ;
 me.cs          = (me.sm == 1) ? me.cr : me.cr.cells(newC-1);
 me.SetColors();
 me.Justify() ;
 if (me.doc.recalc) { me.doc.recalc();}
 if (NewSelFlag && me.onchange) {
   me.onchange();
 }
}

me.InvertSelection = function(newR,newC) {
 if (!me.EnableMultiselect) return;
 if (me.sm == 0) return ;
 var ind = newR + ':' + ((me.sm == 1)?'0':newC);
 me.Multiselected[ind]=(me.Multiselected[ind])?false:true;
 if (me.onmultichange) me.onmultichange(ind);
}

me.multiclear = function() {
 var cnt = 0;
 for (var key in me.Multiselected) {
   if (me.Multiselected[key]) {
     cnt+=1;
     var rc = key.split(':');
     me.multisel(rc[0],rc[1],false);
 } }
 me.Multiselected = []; // array of selected strings [row 1] = (1~2~5) (1-based)) or "1" ( selmode=1 )
 return cnt;
}

me.multisel = function(SnewR,SnewC,Sbsel) {
 if (me.sm==0) return;
 var bsel = (Sbsel)?true:false;
 var newR=parseInt(SnewR,10); if (isNaN(newR)) newR=0;
 var newC=parseInt(SnewC,10); if (isNaN(newC)) newC=0;
 var ind =newR+':'+newC;
 me.Multiselected[ind]=bsel;
 if (!bsel) {
   if (me.selectedLine==newR  && (me.sm!=2 || me.selectedCol==newC))
     if (me.holder.contains(me.doc.activeElement))
       me.SpecificColorRC(newR,newC,me.backgroundselected,me.foregroundselected)
     else
       me.SpecificColorRC(newR,newC,me.backgroundblured,me.foregroundblured)
   else
     me.StandardColorRC(newR,newC)
 } else {
   if (me.selectedLine==newR  && (me.sm!=2 || me.selectedCol==newC))
     me.SpecificColorRC(newR,newC,me.Multibackgroundselected,me.Multiforegroundselected)
   else
     me.SpecificColorRC(newR,newC,me.Multibackgroundcolor,me.Multiforegroundcolor)
 }
}

me.SetColors = function(forceblur) {
 if (me.sm==0 || !me.cs )  return;
 var c;
 if (me.Multiselected[me.GetIndex(me.cs)])
   c=[me.Multibackgroundselected,me.Multiforegroundselected];
 else if (forceblur || !me.holder.contains(me.doc.activeElement))
   c=[me.backgroundblured,me.foregroundblured];
 else
   c=[me.backgroundselected,me.foregroundselected];
 me.SpecificColor(c[0],c[1]);
}

me.SpecificColor = function(cback,cfore) {
  var RC = String(me.GetIndex(me.cs)).split(':');
  me.SpecificColorRC(RC[0],RC[1],cback,cfore);
}

me.SpecificColorRC = function(newR,newC,cback,cfore) {
 var skipelements ={
   select:1,option:1,input:1,button:1,callout:1,extrusion:1,fill:1,formulas:1,
   handles:1,imagedata:1,locks:1,path:1,shadow:1,skew:1,stroke:1,textbox:1,
   textpath:1,group:1,shape:1,shapetype:1,vmlframe:1,rect:1,roundrect:1,line:1,
   polyline:1,oval:1,image:1,curve:1,arc:1
 };
 var thecs,ind = newR+':'+newC;
 if (me.sm==1)  thecs = me.grid.rows(newR-1)
 else           thecs = me.grid.rows(newR-1).cells(newC-1);
 if  (me.ColorPool[ind]) ind = null;
 else           me.ColorPool[ind] = [];
 for (var i=-1;i < thecs.all.length ; i++) {
   var chi = (i<0)?thecs : thecs.all(i);
   if (!(chi.tagName.toLowerCase() in skipelements)) {
     if (ind)  me.ColorPool[ind][i] = chi.style.backgroundColor + '~'+ chi.style.color ;
     chi.style.backgroundColor = cback;
     chi.style.color           = cfore;
   }
 }
}

me.StandardColor = function() {
 var RC = String(me.GetIndex(me.cs)).split(':');
 me.StandardColorRC(RC[0],RC[1])
}

me.StandardColorRC = function(newR,newC) {
 var thecs,ind = newR+':'+newC;
 if (me.sm==1)	thecs = me.grid.rows(newR-1)
 else		thecs = me.grid.rows(newR-1).cells(newC-1)
 if (!me.ColorPool[ind]) {
   thecs.style.backgroundColor	= me.backgroundcolor;
   thecs.style.color		= me.foregroundcolor;
   return;
 }
 for (var key in me.ColorPool[ind]) {
   var i = parseInt(key,10);
   var chi = (i<0)? thecs : thecs.all(i);
   if (!chi) break;
   var colarr = me.ColorPool[ind][i].split('~');
   chi.style.backgroundColor	= colarr[0] ;
   chi.style.color		= colarr[1] ;
} }

me.updateHTML = function(R,C,HTML) {
 R = parseInt(R,10);
 C = parseInt(C,10);
 if (me.grid.rows &&
     me.grid.rows(R-1) &&
     me.grid.rows(R-1).cells &&
     me.grid.rows(R-1).cells(C-1))
   var cs = me.grid.rows(R-1).cells(C-1);
 else return ;
 var ind   = me.GetIndex(cs);
 var cback = cs.style.backgroundColor;
 var cfore = cs.style.color;
 me.StandardColorRC(R,C);
 if (me.ColorPool[ind])  me.ColorPool[ind]=null;
 if (HTML.replace(/ /g,'') == '') HTML='&nbsp;';
 cs.innerHTML = HTML;
 me.SpecificColorRC(R,C,cback,cfore);
 me.refreshHDR();
}

me.GetIndex =  function(cs) {
 if (cs.tagName == 'TR')  return (cs.rowIndex+1) + ':0' ;
 return  (cs.parentElement.rowIndex+1) + ':' + (cs.cellIndex+1)
}

me.ScrollHdr = function() {
 if (me.hs){
   if(me.hs.scrollLeft != me.gs.scrollLeft){
      me.hs.scrollLeft = me.gs.scrollLeft;
      if (me.onhscroll)  me.onhscroll(me.hs.scrollLeft);
   }
 }
 if (me.ls&&me.leftcolno!=0) {
   me.ls.scrollTop = me.gs.scrollTop;
 }
}

me.Justify = function() {
 if (me.sm      == 0)  return ;
 if (!me.cs) return ; // iav
 var newsTop  = me.gs.scrollTop  ;
 var newsLeft = me.gs.scrollLeft ;
 // row just
 if (me.cr.offsetTop+me.cr.offsetHeight >= newsTop + me.gs.clientHeight)
   newsTop = me.cr.offsetTop-me.gs.clientHeight+me.cr.offsetHeight ;
 else if (me.cr.offsetTop < newsTop)
   newsTop = me.cr.offsetTop ;
 // col just
 if (me.sm      == 2) {
   if ((me.cs.offsetWidth > me.gs.clientWidth) || (me.cs.offsetLeft < newsLeft))
	newsLeft = me.cs.offsetLeft;
   else if (me.cs.offsetLeft+me.cs.offsetWidth > newsLeft + me.gs.clientWidth)
	newsLeft = me.cs.offsetLeft+me.cs.offsetWidth-me.gs.clientWidth ;
 }
 me.gs.scrollTop  = newsTop ;
 me.gs.scrollLeft = newsLeft ;
}

me.getRC = function(src,sm) {
 if (!sm) sm = me.sm;
 if (!src) src = me.win.event.srcElement;
 var reta = [];
 if (sm == 1) {
   for (var se = src ; se      ; se = se.parentElement) {
     if (se.tagName=='TR' && se.parentElement.parentElement == me.grid) {
       var indR =      se.rowIndex+1 ;
       if (indR>1 && indR == me.grid.length && me.hs) indR-=1 ;
       reta["R"] = indR;
       reta["C"] = 1;
       break;
   } }
 } else if (sm == 2) { // selmode = 2
   for (var se = src ; se      ; se = se.parentElement) {
     if (se.tagName=='TD' && se.parentElement.parentElement.parentElement == me.grid) {
       var indR =      se.parentElement.rowIndex+1 ;
       if (indR>1 && indR == me.grid.length && me.hs) indR-=1 ;
       var indC = se.cellIndex+1;
       reta["R"] = indR;
       reta["C"] = indC;
       break ;
 } } }
 return reta ;
}
//
// GS events
//
me.GS_onscroll = function() {
 var me=this.me;
 me.ScrollHdr();
}

me.GS_onclick = function() {
 var me=this.me;
 me.win.event.returnValue = true;
 if (me.onmouseclicked)  me.onmouseclicked();
 if (me.win.event.returnValue==false) return ;
 me.doc.selection.empty();
 var ns = me.getRC();
 if (ns["R"]) {
   me.frm=0;
   me.frmc=0;
   me.makesel(ns["R"],ns["C"],1);   //  me.makesel(ns["R"],ns["C"]);
   if (me.onclick)  me.onclick();
} }

me.GS_ondblclick = function() {
 var me=this.me;
 if (me.ondblclick)  me.ondblclick();
}

me.GS_onmousedown = function() {
 var me=this.me;
 if (me.win.event.button==1 || !me.onbeforepopup || !me.win.top.showPopup)
   return true;
 var ns = me.getRC();
 var showed = false;
 if ((ns["R"]) && (!me.onbeforechange || me.onbeforechange(ns["R"],ns["C"]))) {
   me.makesel(ns["R"],ns["C"]);
   var pstr = me.onbeforepopup();
   if (pstr !='') {
     me.win.top.showPopup(me.win.event.screenX,me.win.event.screenY,pstr,me.onpopupcmd,me.doc.body);
     showed = true;
 } }
 me.win.event.cancelBubble = true;
 me.win.event.returnValue = false;
 return false;
}
//
// focusto events
//
me.GRID_onfocus = function() {
 var me=this.me;
 me.SetColors();
 me.gs.scrollTop  = me.savescrTop ;
 me.gs.scrollLeft = me.savescrLeft ;
 me.Justify() ;
}

me.GRID_onblur = function() {
 var me=this.me;
 me.SetColors(true);
 me.savescrTop  = me.gs.scrollTop ;
 me.savescrLeft = me.gs.scrollLeft ;
}

me.GRID_onkeydown = function() {
 var me=this.me;
 if (!me.ready) return true;
 if (me.sm      == 0 ) return true;
 var src = me.win.event.srcElement;
 var canc = true;
 var kk = me.win.event.keyCode;
 if (me.onkeydown) {kk=me.onkeydown(kk)}
 switch (kk) {
 case 38 : // up
   me.frm=0;
   me.updown(-1);
   break;
 case 40 : // down
   me.frm=0;
   me.updown(1);
   break;
 case 33 : // PG up
   me.ScrollPage(-1);
   break;
 case 34 : // PG down
   me.ScrollPage(1);
   break;
 case 36 : // Home
   me.makesel(0,me.selectedCol);
   break;
 case 35 : // End
   me.makesel(-1,me.selectedCol);
   break;
 case 37 : // <--
   me.frmc=0;
   if (me.sm != 2)      return true;
   me.rile(-1);
   break ;
 case 39 : // -->
   me.frmc=0;
   if (me.sm != 2)      return true;
   me.rile(+1);
   break ;
 case 32 : // SpaceKey
   if ((me.sm == 0) || (!me.EnableMultiselect)) return;
   me.makesel(me.selectedLine,me.selectedCol);
   break;
 default:
   canc = false ;
 }
 if (!canc) return true;
 me.win.event.returnValue= false;
 me.win.event.cancelBubble=true;
 return false;
}

me.updown = function(step) {
 var nsel = me.selectedLine+step;
 if ( nsel<=0 || nsel> me.lines) return;

 if(!me.grid.rows(me.selectedLine-1)) return;
 var aRow = me.grid.rows(me.selectedLine-1)
 var NXT,NOW;
 if (me.sm==2 &&
    (NXT = me.grid.rows(nsel-1).cells(me.selectedCol-1)) &&
    (NOW = me.grid.rows(me.selectedLine-1).cells(me.selectedCol-1)) &&
    (NXT.colSpan>1 || NOW.colSpan>1)) {
   var csel = me.selectedCol;
   var nnc=nsel;
   if (step>0)     {
     while(true){
       aRow = me.grid.rows(nsel-1) ;
       if (csel+2>aRow.cells.length) break;
       if (NXT.offsetLeft>NOW.offsetLeft) {if (csel>1) {csel=csel-1;} NXT = me.grid.rows(nsel-1).cells(csel-1);}
       if (NOW.offsetLeft>=NXT.offsetLeft+NXT.offsetWidth) {csel=csel+1; NXT = me.grid.rows(nsel-1).cells(csel-1);}
       if (NXT.offsetTop-4>NOW.offsetTop+NOW.offsetHeight) {nsel=nsel-1; NXT = me.grid.rows(nsel-1).cells(csel-1);}
       if (NOW.offsetTop+NOW.offsetHeight>=NXT.offsetTop+NXT.offsetHeight) {nsel=nsel+1; NXT = me.grid.rows(nsel-1).cells(csel-1);}
       if (NXT.offsetLeft<=NOW.offsetLeft && NOW.offsetLeft<NXT.offsetLeft+NXT.offsetWidth && NXT.offsetTop-4<=NOW.offsetTop+NOW.offsetHeight && NOW.offsetTop+NOW.offsetHeight<NXT.offsetTop+NXT.offsetHeight) { break;}
     }
   }
   if (step<0)     {
     while(true){
       aRow = me.grid.rows(nsel-1);
       if (csel+2>aRow.cells.length) break;
       if (NXT.offsetLeft>NOW.offsetLeft) {if (csel>1) {csel=csel-1;} NXT = me.grid.rows(nsel-1).cells(csel-1);}
       if (NOW.offsetLeft>=NXT.offsetLeft+NXT.offsetWidth) {csel=csel+1; NXT = me.grid.rows(nsel-1).cells(csel-1);}
       if (NXT.offsetLeft>NOW.offsetLeft) {if (csel>1) {csel=csel-1;} NXT = me.grid.rows(nsel-1).cells(csel-1);}
       if (NOW.offsetLeft>=NXT.offsetLeft+NXT.offsetWidth) {csel=csel+1; NXT = me.grid.rows(nsel-1).cells(csel-1);}
       if (NXT.offsetLeft<=NOW.offsetLeft && NOW.offsetLeft<NXT.offsetLeft+NXT.offsetWidth && NXT.offsetTop+NXT.offsetHeight+4>=NOW.offsetTop && NOW.offsetTop>NXT.offsetTop) { break;}
       nsel=nsel-1;
     }
   }
   if (NXT.colSpan>1) { me.frmc=1; from_csel=me.selectedCol; }
   if (me.onbeforechange && me.onbeforechange(nsel,csel)==false){}
   if (me.frmc==1 && NOW.colSpan>1) {  csel=from_csel;  }
   if (me.onbeforechange && me.onbeforechange(nsel,csel)==false){nsel=nsel+step;}
   me.makesel(nsel,csel);
 } else {
   for (var nsel = me.selectedLine+step ; nsel>0 && nsel<= me.lines ; nsel+= step) {
     if (me.IsRowEnabled(nsel)) {
       me.makesel(nsel,me.selectedCol);
       break;
     }
   }
 }
}

me.ScrollPage = function(step) {
 var nsel = me.selectedLine;
 while (nsel < me.lines && nsel>1)  {
   var aRow =           me.grid.rows(nsel-1);
   if (aRow.offsetHeight > 0) {
     if ((step == 1) && (aRow.offsetTop >= me.gs.scrollTop + me.gs.clientHeight-aRow.offsetHeight)) break ;
     if ((step ==-1) && (aRow.offsetTop <= me.gs.scrollTop)) break ;
   }
   nsel += step ;
 }
 if (nsel == me.selectedLine) {
   var topass = me.gs.clientHeight;
   for (var newsel = nsel+step ; newsel>0 && newsel<=me.lines ; newsel+=step) {
     var aH = me.grid.rows(newsel-1).offsetHeight ;
     if (aH>0) {
       topass-= aH ;
       if (topass<=0) break ;
       if (me.IsRowEnabled(newsel))  nsel = newsel ;
 } } }
 if (nsel != me.selectedLine) {
   me.makesel(nsel,me.selectedCol);
 }
}

me.rile = function(step) {
 var mg=me.grid;
 var aRow = mg.rows(me.selectedLine-1) ;
 var NXT,NXTR,NOW,NOWR,NOWi,c1,c2,c3,FROM,from_nsel; // iav
 var csel = me.selectedCol+step;
 if (csel <=0 || csel > aRow.cells.length) return;
 var nsel = me.selectedLine;
 NXT = mg.rows(nsel-1).cells(csel-1);
 //if Column is invisible [GIO]
 while(NXT.offsetWidth==0) {
   csel+=step;
   if (csel <=0 || csel > aRow.cells.length) return;
   NXT = mg.rows(nsel-1).cells(csel-1);
 }
 NXTR = NXT.offsetLeft+NXT.offsetWidth;
 NOW = mg.rows(me.selectedLine-1).cells(me.selectedCol-1);
 NOWR = NOW.offsetLeft+NOW.offsetWidth;
 if (step==1) {
   while(NOWR+4<NXT.offsetLeft){
     nsel--;
     NXT = mg.rows(nsel-1).cells(csel-1);
   }
   while(NOW.offsetLeft>=NXT.offsetLeft){
     csel++;
     NXT = mg.rows(nsel-1).cells(csel-1);
   }
 }
 if (step==-1 && NOW.offsetLeft-4>NXTR) {
   nsel--;
   NXT = mg.rows(nsel-1).cells(csel-1);
   NXTR = NXT.offsetLeft+NXT.offsetWidth;
   while(true) {
     c1=csel;
     if (NOW.offsetLeft-4>NXTR) {
       csel++;
       NXT = mg.rows(nsel-1).cells(csel-1);
       NXTR = NXT.offsetLeft+NXT.offsetWidth;
     }
     c2=csel;
     if (NOW.offsetLeft<=NXT.offsetLeft) {
       csel--;
       NXT = mg.rows(nsel-1).cells(csel-1);
       NXTR = NXT.offsetLeft+NXT.offsetWidth;
     }
     c3=csel;
     if(c1==c2 && c2 == c3) break; else nsel--;
     if(NOW.offsetLeft-4<=NXTR && NOW.offsetLeft>=NXTR &&
	NXT.offsetTop<=NOW.offsetTop+4 &&
	NXT.offsetTop+NXT.offsetHeight>=NOW.offsetTop+4) break;
   }
   NXT = mg.rows(nsel-1).cells(csel-1);
   while(NXT.offsetTop>NOW.offsetTop+4 || NXT.offsetTop+NXT.offsetHeight<NOW.offsetTop+4) {
     nsel++;
     NXT = mg.rows(nsel-1).cells(csel-1);
   }
 }
 NXT = mg.rows(nsel-1).cells(csel-1);
 NOWi=NOW;
 if(me.frm==0 && NXT.rowSpan>1) {
   from_nsel=me.selectedLine;
   FROM=NOW;
   me.frm=1;
 }
 if (me.onbeforechange && me.onbeforechange(nsel,csel)==false) {
   csel=csel+step;
   if (csel+2>aRow.cells.length)
     csel-=step;
 }
 me.makesel(nsel,csel,1);
 if(NOW.rowSpan>1 && me.frm==1) {
   while(mg.rows(me.selectedLine-1).cells(me.selectedCol-1).offsetTop<FROM.offsetTop){
     me.updown(1);
   }
 }
 if (step==1 && NOWi.rowSpan>1 && me.frm==1){
   while(mg.rows(me.selectedLine-1).cells(me.selectedCol-1).offsetTop>FROM.offsetTop) {
     me.updown(-1);
   }
   while(true) {
     if(mg.rows(me.selectedLine-1).cells(me.selectedCol-1).offsetLeft+mg.rows(me.selectedLine-1).cells(me.selectedCol-1).offsetWidth<=NOWi.offsetLeft+4) {
       me.makesel(me.selectedLine-1,me.selectedCol+1);
     }
     if(mg.rows(me.selectedLine-1).cells(me.selectedCol-1).offsetLeft>=NOWi.offsetLeft+NOWi.offsetWidth+4 ) {
       me.makesel(me.selectedLine,me.selectedCol-1);
     }
     if(mg.rows(me.selectedLine-1).cells(me.selectedCol-1).offsetLeft+mg.rows(me.selectedLine-1).cells(me.selectedCol-1).offsetWidth>NOWi.offsetLeft+4 && mg.rows(me.selectedLine-1).cells(me.selectedCol-1).offsetLeft<=NOWi.offsetLeft+NOWi.offsetWidth+4)
	break;
   }
 }
 if (step==-1 && NOWi.rowSpan>1 && me.frm==1){
   while(mg.rows(me.selectedLine-1).cells(me.selectedCol-1).offsetTop>FROM.offsetTop){
     me.updown(-1);
   }
   while(true) {
     if(mg.rows(me.selectedLine-1).cells(me.selectedCol-1).offsetLeft>=NOWi.offsetLeft+NOWi.offsetWidth-4) {
       me.makesel(me.selectedLine-1,me.selectedCol-1);
     }
     if(mg.rows(me.selectedLine-1).cells(me.selectedCol-1).offsetLeft+mg.rows(me.selectedLine-1).cells(me.selectedCol-1).offsetWidth<=NOWi.offsetLeft-4 ){
       me.makesel(me.selectedLine,me.selectedCol+1);
     }
     if(mg.rows(me.selectedLine-1).cells(me.selectedCol-1).offsetLeft<NOWi.offsetLeft+NOWi.offsetWidth-4 && mg.rows(me.selectedLine-1).cells(me.selectedCol-1).offsetLeft+mg.rows(me.selectedLine-1).cells(me.selectedCol-1).offsetWidth>=NOWi.offsetLeft-4)
	break;
   }
 }
}

me.IsRowEnabled = function(tri){
 var tr=me.grid.rows(tri-1);
 if (tr.clientHeight<1) return false;
 return !me.onbeforechange || me.onbeforechange(tr.rowIndex+1,1);
}

me.IsColEnabled = function(tr,tdi) {
 var td=tr.cells(tdi-1);
 if (td.clientWidth<1 ) return false;
 return !me.onbeforechange || me.onbeforechange(td.parentElement.rowIndex+1,td.cellIndex+1);
}

me.print = function(gtitle,inwin) {
 if (gtitle && typeof(gtitle)!='object') gtitle=[gtitle,gtitle];
 var aCSS =["<!--"];
 for (var is=0; is<me.doc.styleSheets.length; is++) {
   var sts = me.doc.styleSheets[is];
   if ( sts.media &&  sts.media!='ALL' && sts.media !='PRINT' ) continue;
   for (var ir=0; ir<sts.rules.length; ir++) {
     var selector=sts.rules[ir].selectorText;
     aCSS[aCSS.length]= (selector=="" ? "*" : selector) +' {'+sts.rules[ir].style.cssText+'}';
   }  
 }
 aCSS[aCSS.length]= "-->";

 var toclose  = '';
 var dest;
 if (inwin) {
   dest = inwin ;
 } else {
   dest = window.open("/suite/empty.php",'',"top=0px,left=0px,height=1px,width=1px,toolbar=no,location=no,directories=no,menubar=no,status=no,scrollbars=no,resizable=no,center=no");
   toclose   = 'window.close();';
 }
 var a=[];
 a[a.length]='<HTML><HEAD><TITLE>'+(gtitle?gtitle[0]:'')+'</TITLE>';
 a[a.length]='<style type="text/css" MEDIA=ALL>'+aCSS.join('\r\n')+'</style>';
 a[a.length]='<SCRIPT language="JScript">';
 a[a.length]='function onload() {';
 a[a.length]=  'try{var axn=top.getkey("PRINTAXNAME");if(!axn)axn.raise();axo=new ActiveXObject(axn)}catch(e){axo=null};';
 a[a.length]=  'if (axo){if(axo.PageSetup("Print","Print","",""))axo.PrintFrame(window)}';
 a[a.length]=  'else    {try{window.focus()}catch(e){};window.print()}';
 a[a.length]='}';
 a[a.length]='<\/SCRIPT>';
 a[a.length]='</HEAD>';
 a[a.length]="<BODY style='background-color:white;margin:0' onload=onload()>";
 if (gtitle && gtitle[1]) a[a.length]='<H4>'+gtitle[1]+'</H4>';
 a[a.length]="<TABLE WIDTH=100% CLASS='"+me.classname+"' CELLPADDING="+me.cellpadd +" CELLSPACING=0 BORDER=1 RULES="+me.borderrules+" BGCOLOR=WHITE BORDERCOLOR=GRAY style=border-collapse:collapse>";
 a[a.length]=me.colgroup+me.MakePrintHead()+'<TBODY>'+me.tb;
 a[a.length]='</TABLE></BODY></HTML>';
 dest.focus();
 var dd = dest.document;
 dd.open("text/html","replace");
 dd.write(a.join("\r\n"));
 dd.close();
 return '';
}

me.MakePrintHead = function() {
 var ph=me.GetHdrBody(" ALIGN=CENTER style='font-weight:bold;border:1px solid black'","");
 ph = ph.replace(/\x7B[ADad]\x7D/g,"");
 return "<THEAD BGCOLOR=SILVER style=display:table-header-group>"+ph+"</THEAD>";
}

 me.AssignRuntimeProps();
 me.GRID_retfalse = function(){ return true; }
 me.GRID_onSelectEnd = function(){ return true; }
}
window.newGrid = function(thecontainer,theclass,thebodystr,theheadstr,tabind,theW,theH,thecolhdr,thebord,thespac,thepadd,theleftcol,theselmode) {
 return new IGrid(thecontainer,theclass,thebodystr,theheadstr,tabind,theW,theH,thecolhdr,thebord,thespac,thepadd,theleftcol,theselmode);
}
var GridEndSemaphore=true;

