#include "oohg.ch"
#include "dSign.ch"


MEMVAR oMain, TitleHeight, BorderHeight, BorderWidth

Procedure Save(oWin, lAs, lMsg)
Local cStr := "", nHandle, c, nSpace := 3 //, lNew := EMPTY(oWin:cFileName) //, lFmg 
DEFAULT lAs TO .F.
DEFAULT lMsg TO .T.

	If !HB_IsObject(oWin)
		Return
	Else
		ReleaseControls(oWin)
		c := oWin:cFileName
	Endif
	If EMPTY(c) .OR. lAs
		c := PutFile({{"*.fmg","*.fmg"},{"*.prg","*.prg"},{"*","*.*"}}, /*title*/, /*cIniFolder*/, /*nochangedir*/, /*cDefaultFileName*/, /*lForceExt*/.T. )
		If EMPTY(c)
			Return
		Endif

		c := hb_FNameExtSetDef(c, ".fmt")
		If hb_FileExists(c)
			If !MsgYesNo("Archivo "+c+" ya existe." +hb_eol() + "Desea reemplazar?", "dSign")
				Return
			Endif
		Endif
	Else
		c := oWin:cFileName
		c := hb_FNameExtSetDef(c, ".fmt")
	Endif

	If lMsg
		WaitWindow( "Guardando..."+c, 1 )
	Endif

	AEVAL(oWin:aControls, {|o| o:lDone := .F.} )
	cStr += "********** Editado por dSign el "+DTOC(DATE())+" "+TIME()+" ******************"+hb_eol()
	cStr += "********** Aporte de David Field al proyecto OOHG ******************"+hb_eol()+hb_eol()
	
	// Guardar lo anterior a la definicion del windows
	cStr += oWin:cBefore	//+hb_eol()
	
	// Guardar el windows
	cStr += SPACE(nSpace)+"DEFINE WINDOW "+LTRIM(oWin:aDatas[NAME,2])+" ;"+hb_eol()
	cStr += SPACE(nSpace+3)+"AT "+LTRIM(STR(oWin:Row))+", "+LTRIM(STR(oWin:Col))+";"+hb_eol()
	oWin:aDatas[wWIDTH,2] := oWin:Width + IF(oWin:aDatas[wCLIENTAREA,2], -16,0)
	oWin:aDatas[wHEIGHT,2] := oWin:Height + IF(oWin:aDatas[wCLIENTAREA,2], -39,0)
	cStr += SaveDatas(oWin, nSpace+3) +hb_eol()+hb_eol()
	
	// Guardar controles
	cStr += SaveControls(oWin:aControls, nSpace+3)
	
	// Guardar lo que hubiera antes del END WINDOW
	cStr += If(!EMPTY(oWin:cAfter), oWin:cAfter, "")
	cStr += SPACE(nSpace)+"END WINDOW"+hb_eol()
	
	// Guardar todo lo demás
	cStr += RestofFMG	//oWin:Cargo[5]

	nHandle := FCREATE(c)
	FWRITE(nHandle, cStr)	//+hb_eol())
	FCLOSE(nHandle)
	oWin:cFileName := c
	MODIFIED := .F.
	If lMsg
		CloseWait()
	Endif
	oWin:Title := Comillas(oWin:aDatas[wTITLE,2]) + "     ("+oWin:cFileName+")"

	
Return

Function SaveControls(aControls, nSpace)
Local cType, o, oChild, cStr := "", j, cDatas, lNode := .F.
Local lLong := .T. //(NetName() = "DAVID-I7")		// Prueba para escribir en formato largo  90 caracteres

	
	FOR EACH o IN aControls 
If o:Type == "MENU"; LOOP; ENDIF
If o:lDone; LOOP; ENDIF
		If !hb_IsArray(o:Cargo) //.OR. o:Type == "MENU" .OR. 
			LOOP
		Endif
		o:lDone := .T.
		cType := o:Cargo[cTYPE]
		If !EMPTY(o:cBefore) // <> NIL
			cStr += o:cBefore	//+HB_eol()
		Endif
//db_Text(o:aDatas[NAME,2]+"  "+STR(o:Cargo[2],3))
		If cType $ "PAGE"		// Ignore
		ElseIf cType == "TAB"
			cStr += SPACE(nSpace)+"DEFINE TAB "+ALLTRIM(o:aDatas[NAME,2])+" ;"+hb_eol()
			nSpace += 3
			cStr += SPACE(nSpace)+"AT "+LTRIM(STR(o:nRow))+", "+LTRIM(STR(o:nCol))+" ;"+hb_eol()
			If o:nWidth <> 0
				cStr += SPACE(nSpace)+"WIDTH "+LTRIM(STR(o:nWidth))+" ;"+hb_eol()
			Endif
			If o:Height <> 0
				cStr += SPACE(nSpace)+"HEIGHT "+LTRIM(STR(o:Height))+" ;"+hb_eol()
			Endif
			cDatas := SaveDatas(o, nSpace)
			If EMPTY(cDatas)
				cStr := SUBSTR(cStr, 1, RAT(";", cStr)-1)	+hb_eol()+hb_eol()
			Else
				cStr += cDatas
			Endif
			
			// Save Each Page
			For each oChild in o:aPages
				If !EMPTY(oChild:cBefore)
					cStr += oChild:cBefore	//+hb_eol()
				Endif
				oChild:lDone := .T.
				cStr += SPACE(nSpace)+"DEFINE PAGE '"+oChild:Caption+"' ;"+hb_eol()
				cDatas := SaveDatas(oChild, nSpace)
				If EMPTY(cDatas)
					cStr := SUBSTR(cStr, 1, RAT(";", cStr)-1)	+hb_eol()+hb_eol()
				Else
					cStr += cDatas
				Endif

			// Save Each Control for this page
				ASORT(oChild:aControls,,, {|x, y| x:Cargo[2] < y:Cargo[2]} )		// Order by TABINDEX
				nSpace += 3
				cStr += SaveControls(oChild:aControls, nSpace)
				nSpace -= 3
				cStr += SPACE(nSpace)+"END PAGE "+hb_eol()+HB_eol()
			Next
			nSpace -= 3
			cStr += SPACE(nSpace)+"END TAB"+hb_eol()+hb_eol()
		
		ElseIf cType == "TIMER"
*			cStr += SPACE(nSpace)+"*****@ "+LTRIM(STR(o:nRow))+", "+LTRIM(STR(o:nCol))+" TIMER "+o:aDatas[NAME,2]+" ;"+hb_eol()
			cStr += SPACE(nSpace)+"DEFINE TIMER "+o:aDatas[NAME,2]+" ;"+hb_eol()
			nSpace += 3
			cStr += SaveDatas(o, nSpace)
//			cStr := SUBSTR(cStr, 1, RAT(";", cStr)-1)	+hb_eol()+hb_eol()
			nSpace -= 3
			
		ElseIf cType == "TREE"
			cStr += SPACE(nSpace)+"DEFINE TREE "+o:aDatas[NAME,2]+If(lLong, ""," ;"+hb_eol())
			nSpace += 3
			cStr += SPACE(nSpace)+"AT "+LTRIM(STR(o:nRow))+", "+LTRIM(STR(o:nCol))+" ;"+hb_eol()
			If o:nWidth <> 0
				cStr += SPACE(nSpace)+"WIDTH "+LTRIM(STR(o:nWidth))+" ;"+hb_eol()
			Endif
			If o:Height <> 0
				cStr += SPACE(nSpace)+"HEIGHT "+LTRIM(STR(o:Height))+" ;"+hb_eol()
			Endif
			cStr += SaveDatas(o, nSpace)
			cStr := SUBSTR(cStr, 1, RAT(";", cStr)-1)+hb_eol()+hb_eol()

			For j := 1 TO LEN(o:aEndNode)
				If !EMPTY(o:aBefore[j]);	cStr += o:aBefore[j]+hb_eol(); Endif
			If j <= LEN(o:aAsignId)
				If o:aNode[j]
					cStr += SPACE(nSpace)+"NODE "+o:aText[j]+" "
					nSpace +=3
				Else
					cStr += SPACE(nSpace)+"TREEITEM "+o:aText[j]+" "
				Endif
				If !EMPTY(o:aTreeIdMap[j]); cStr += "; "+hb_eol()+SPACE(nSpace)+" ID "+hb_cStr(o:aTreeIdMap[j])+" "; Endif
				If o:aTreeRO[j]; 				cStr += "; "+hb_eol()+SPACE(nSpace)+"READONLY "; Endif
				If !o:aTreeEnabled[j]; 		cStr += "; "+hb_eol()+SPACE(nSpace)+"DISABLED "; Endif
				If !EMPTY(o:aId[j]); 			cStr += "; "+hb_eol()+SPACE(nSpace)+"ID "+hb_cStr(o:aId[j])+" "; Endif
				If o:aTreeNoDrag[j]; 			cStr += "; "+hb_eol()+SPACE(nSpace)+"NODRAG "; Endif
				If !EMPTY(o:aBold[j]);		cStr += "; "+hb_eol()+SPACE(nSpace)+" BOLD "; Endif
				If !EMPTY(o:aAsignId[j]);	cStr += "; "+hb_eol()+SPACE(nSpace)+" AUTOID "; Endif
				cStr += hb_eol()
				If !EMPTY(o:aAfter[j]);		cStr += o:aAfter[j]+hb_Eol(); Endif
			Endif
				If o:aEndNode[j]
					nSpace -= 3
					cStr += SPACE(nSpace)+"END NODE "+hb_Eol()+hb_eol()
				Endif
			Next j
					
			If !EMPTY(o:cAfter);		cStr += o:cAfter+hb_Eol(); Endif
			nSpace := 3
			cStr += SPACE(nSpace)+"END TREE"+hb_eol()+hb_eol()
			o:cAfter := ""
			
		ElseIf cType == "TOOLBAR"
			cStr += SPACE(nSpace)+"DEFINE TOOLBAR "+o:aDatas[NAME,2]+" ;"+hb_eol()
			nSpace += 3
			cStr += SPACE(nSpace)+"BUTTONSIZE "+LTRIM(STR(o:nButtonWidth))+", "+LTRIM(STR(o:nButtonHeight))+" ;"+hb_eol()
			o:aDatas[tbBUTTONSIZE,2] := ''
			cStr += SaveDatas(o, nSpace)
			// Quitar último ;
			If SUBSTR(cStr, -3,1) = ";"
				cStr := LEFT(cStr, LEN(cStr)-3)+hb_eol()
			Endif
			
			For EACH oChild IN o:aControls
				If !EMPTY(oChild:cBefore)
					cStr += SPACE(nSpace)+ ALLTRIM(oChild:cBefore)	//+hb_eol()
				Endif
				oChild:lDone := .T.
				cStr += SPACE(nSpace)+"BUTTON "+oChild:aDatas[NAME,2]+" ;"+hb_eol()
				nSpace += 3
				cStr += SaveDatas(oChild, nSpace)
				// Quitar último ;
				If SUBSTR(cStr, -3,1) = ";"
					cStr := LEFT(cStr, LEN(cStr)-3)+hb_eol()
				Endif
				
				nSpace -= 3
			Next
			nSpace -= 3
			cStr += SPACE(nSpace)+"END TOOLBAR"+hb_eol()+hb_eol()
		
		ElseIf cType == "SPLITBOX"
			cStr += SPACE(nSpace)+"DEFINE SPLITBOX  ;"+hb_eol()
			nSpace += 3
			cStr += SaveDatas(o, nSpace)
//			cStr := SUBSTR(cStr, 1, Hb_RAT(";", cStr)-1)+hb_eol()+hb_eol()
		
			// Poner en orden los controles
			ASORT(o:MyItems,,, {|x, y| x:Cargo[TABINDEX] < y:Cargo[TABINDEX]})
			nSpace += 3
			cStr += SaveControls(o:aControls, nSpace)
			nSpace -= 3
*			i += LEN(o:MyItems)
			cStr += SPACE(nSpace)+"END SPLITBOX"+hb_eol()+hb_eol()


		ElseIf cType == "STATUSBAR"
			cStr += SPACE(nSpace)+"DEFINE STATUSBAR ;"+HB_eol()
			nSpace += 3
			cStr += SaveDatas(o, nSpace)
			cStr := SUBSTR(cStr, 1, RAT(";", cStr)-1)+hb_eol()
			
			// aItems array = {Caption, Width, action, ToolTip, icon, cstyl, cAlign, lDefault}			
			For j := 1 TO LEN(o:MyItems)
				cStr += SPACE(nSpace)
				if o:MyItems[j,1] $ "DATE KEYBOARD CLOCK"
					cStr += o:MyItems[j,1]+" ;"+hb_eol()
				Else
					cStr += "STATUSITEM "+o:MyItems[j,1]+" ;"+hb_eol()
				Endif
				If !EMPTY(o:MyItems[j,2])
					cStr += SPACE(nSpace+3)+"WIDTH "+STR(o:MyItems[j,2],4,0)+" ;"+hb_eol()
				Endif
				If !EMPTY(o:MyItems[j,3]) 
					cStr += SPACE(nSpace+3)+"ACTION "+o:MyItems[j,3]+" ;"+hb_eol()
				Endif
				If !EMPTY(o:MyItems[j,4]) 
					cStr += SPACE(nSpace+3)+"TOOLTIP '"+o:MyItems[j,4]+"' ;"+hb_eol()
				Endif
				If !EMPTY(o:MyItems[j,5]) 
					cStr += SPACE(nSpace+3)+"ICON "+o:MyItems[j,5]+" ;"+hb_eol()
				Endif
				If !EMPTY(o:MyItems[j,6]) //.AND. o:MyItems[j,6] <> "FLAT"
					cStr += SPACE(nSpace+3)+o:MyItems[j,6]+" ;"+hb_eol()
				Endif
				If !EMPTY(o:MyItems[j,7]) //.AND. o:MyItems[j,7] <> "LEFT"
					cStr += SPACE(nSpace+3)+o:MyItems[j,7]+" ;"+hb_eol()+hb_eol()
				Endif
				If o:MyItems[j,8] 
					cStr += SPACE(nSpace+3)+"DEFAULT "+" ;"+hb_eol()
				Endif
				cStr := SUBSTR(cStr, 1, RAT(";", cStr)-1)+hb_eol()
			Next
			
			nSpace -= 3
			cStr += SPACE(nSpace)+"END STATUSBAR"+hb_eol()+hb_eol()

		Else
			cStr += SPACE(nSpace)+"@ "+LTRIM(STR(o:Row))+", "+LTRIM(STR(o:Col))+" "+cType+" "+o:aDatas[NAME,2]+ If(lLong, ""," ;"+hb_eol())
			nSpace += 3
			// No especificar tamaños de ancho y alto en Label con autosize
			If cType == "LABEL" .and. GetaDatas("AUTOSIZE", o:aDatas) = .T.
			ElseIf cType == "COMBOBOX"
				If o:nWidth <> 0
					cStr += If(lLong, " ", SPACE(nSpace)) +"WIDTH "+LTRIM(STR(o:nWidth))+If(lLong, ""," ;"+hb_eol())
				Endif
				If EMPTY(o:aDatas[dHEIGHT,2]) 
					cStr += If(lLong, " ", SPACE(nSpace))+"HEIGHT "+LTRIM(STR(o:Height))+If(lLong, ""," ;"+hb_eol())
				Else
					cStr += If(lLong, " ", SPACE(nSpace))+"HEIGHT "+LTRIM(STR(o:aDatas[dHEIGHT,2]))+If(lLong, ""," ;"+hb_eol())
					o:aDatas[dHEIGHT,2] := ''
				Endif
			ElseIf cType == "MONTHCALENDAR"
				// Do not write WIDTH or HEIGHT in definition
			Else
				If o:nWidth <> 0
					cStr += If(lLong, " ", SPACE(nSpace)) +"WIDTH "+LTRIM(STR(o:nWidth))+If(lLong, ""," ;"+hb_eol())
				Endif
				If o:Height <> 0 .AND. !(cType $ "RADIOGROUP")
					cStr += If(lLong, " ", SPACE(nSpace))+"HEIGHT "+LTRIM(STR(o:Height))+If(lLong, ""," ;"+hb_eol())
				Endif
			Endif

			If cType $ "GRID XBROWSE BROWSE"
				// TODO Add ColumnControls
				// Add Items
				If VALTYPE(o:aDatas[dHEADERS,2]) == 'A'
					o:aDatas[dHEADERS,2] 		:= o:aHeaders		// Add Headers
					o:aDatas[dWIDTHS,2] 		:= o:aWidths		// Add Widths
					o:aDatas[dINPUTMASK,2] 	:= o:Picture		// Add inputmask
					o:aDatas[dJUSTIFY,2] 		:= o:aJust			// Add Justify
				Endif
*				o:aDatas[dVALID,2] 		:= o:caValid			// Add Valid
				If EMPTY(o:aDatas[dWHEN,2])
					o:aDatas[dWHEN,2] 		:= o:caWhen			// Add When
				Endif
				If ArrayHasData(o:caValid)
					o:aDatas[dVALID,2] 		:= o:caValid		// Add Valid
				Endif
				If ArrayHasData(o:caOnHeadClick)
					o:aDatas[dONHEADCLICK,2] := o:caOnHeadClick
				Endif
				If ArrayHasData(o:caOnHeadDblClick)
					o:aDatas[dONHEADDBLCLICK,2] := o:caOnHeadDblClick
				Endif
				If ArrayHasData(o:caHeaderImage)
					o:aDatas[dHEADERIMAGES,2] := o:caHeaderImage
				Endif
				If ArrayHasData(o:caHeaderImageAlign)
					o:aDatas[dHEADERIMAGESGALIGN,2] := o:caHeaderImageAlign
				Endif
				If ArrayHasData(o:caDynamicBackColor)
					o:aDatas[dDYNAMICBACKCOLOR,2] := o:caDynamicBackColor
				Endif
				If ArrayHasData(o:caDynamicForeColor)
					o:aDatas[dDYNAMICFORECOLOR,2] :=  o:caDynamicForeColor
				Endif
				If ArrayHasData(o:caColumnBlocks)
					o:aDatas[dCOLUMNCONTROLS,2] := o:caColumnBlocks
				Endif
				If ArrayHasData(o:caDefaultValues)
					o:aDatas[dDEFAULTVALUES,2] := o:caDefaultValues
				Endif
				If ArrayHasData(o:caFields)
					o:aDatas[dFIELDS,2] := o:caFields
				Endif
				If ArrayHasData(o:caReplaceField)
					o:aDatas[dREPLACEFIELD,2] := o:caReplaceField
				Endif
				If ArrayHasData(o:caWhen)
					o:aDatas[dWHEN,2] := o:caWhen
				Endif
				If ArrayHasData(o:caOnHeadClick)
					o:aDatas[dONHEADCLICK,2] := o:caOnHeadClick
				Endif
				If ArrayHasData(o:caOnHeadDblClick)
					o:aDatas[dONHEADDBLCLICK,2] := o:caOnHeadDblClick
				Endif
				If o:aDatas[dEDIT,2]
					o:aDatas[dREADONLY,2] 	:= o:ReadOnly		// Add ReadOnly
*				ELSE
*					o:aDatas[dREADONLY,2] := {}
				Endif

				If lLong
					lLong := .F.
					cStr += " ;"+hb_eol()
				Endif
			Endif
			
			cDatas := SaveDatas(o, nSpace, lLong)
// db_Text(cStr)
//db_Text(cDatas)
			If EMPTY(cDatas)
*				cStr := SUBSTR(cStr, 1, RAT(";", cStr)-1)//+hb_eol()+hb_eol()
			ElseIf lLong
				cStr += " ;"+hb_eol() + cDatas
			Else
				cStr += cDatas
			Endif
			nSpace -= 3
			cStr += hb_eol()	//+hb_eol()
*			lLong := (NetName() = "DAVID-I7")	
lLong := .T.		
		Endif

		// Add cAfter to cStr
		If LEN(o:cAfter) > 0
			For Each cDatas IN Hb_ATokens(o:cAfter, hb_eol())
				If !EMPTY(ALLTRIM(cDatas))
					If ( "VISIBLE" $ cDatas ) .OR. ("TABSTOP" $ cDatas)
					Else
						cStr += SPACE(nSpace)+cDatas+hb_eol()
					Endif
				Endif
			Next
		Endif

	Next

Return cStr

Function SaveDatas(o, nSpace, lLong)
Local i, aDatas := o:aDatas, aEvents := o:aEvents, cStr := "", nLongSpace, cTxt := ""
DEFAULT lLong TO .F.

	If lLong
		cStr += SPACE(nSpace-1)
		nLongSpace := nSpace
		nSpace := 1
	Endif

	For i := 1 TO LEN(aDatas)
	
		If aDatas[i,1] $ "NAME " .OR. EMPTY(aDatas[i,2])
			LOOP
		ElseIf aDatas[i,1] $ "STRETCH" .AND. !(o:Type $ "IMAGE PICTURE")
			LOOP
		ElseIf hb_IsString(aDatas[i,2]) .AND. aDatas[i,2] = "NIL"
			LOOP
		Endif
		// For Combobox special treatment to DISPLAYEDIT must go with MAXLENGTH and NOHSCROLL
		If o:Cargo[cTYPE] == "COMBOBOX"
			If aDatas[i,1] == "DISPLAYEDIT" .AND. aDatas[i,2]
				cTxt += SPACE(nSpace)+aDatas[i,1]	//+" ;"+HB_Eol()
				If !EMPTY(aDatas[dMAXLENGTH,2])
					cTxt += " MAXLENGTH "+STR(aDatas[dMAXLENGTH,2],3,0)
				Endif
				If !EMPTY(aDatas[dNOHSCROLL,2]) .AND. aDatas[dNOHSCROLL,2]
					cTxt += " NOHSCROLL "
				Endif
				LOOP
			Endif
			If aDatas[i,1] == "MAXLENGTH" .OR. aDatas[i,1] == "NOHSCROLL"
				LOOP
			Endif
		Endif
			
				
		
		If aDatas[i,1] $ "ALIGN STYLE"
			If aDatas[i,1] == "ALIGN" .AND. aDatas[i,2] <> "LEFT"
				cTxt += SPACE(nSpace)+aDatas[i,2]	//+" ;"+HB_Eol()
			Endif
			If aDatas[i,1] == "STYLE" .AND. aDatas[i,2] <> "FLAT"
				cTxt += SPACE(nSpace)+aDatas[i,2]	//+" ;"+HB_Eol()
			Endif
		
		ElseIf o:Cargo[1] $ "PAGE " 
			// Do nothing

		ElseIf aDatas[i,1] == "BACKIMAGE"
			cTxt += SPACE(nSpace)+aDatas[i,1]+" "+aDatas[i,2]+" "	//+" ;"+HB_Eol()
			If aDatas[wSTRETCH,2]
				cTxt += SPACE(nSpace)+"STRETCH "	//+HB_Eol()
			Endif
			
		ElseIf aDatas[i,1] == "FONT"
			cTxt += SPACE(nSpace)+aDatas[i,1]+' '+Comillas(aDatas[i,2], .T.)	//+' ;'+HB_Eol()

		ElseIf aDatas[i,1] == "FIELD"		// para mi
			If o:Cargo[6]
				cTxt += SPACE(nSpace)+"GET "+aDatas[i,2]	//+" ;"+HB_eol()
			Else
				cTxt += SPACE(nSpace)+"FIELD "+aDatas[i,2]	//+" ;"+HB_eol()
			Endif
			
// Quité esto ya que es responsabilidad del creador decidir si lleva comillas o no			
*		ElseIf aDatas[i,1] $ "CAPTION OBJ FIELD PARENT TITLE VALID VALUE WORKAREA RANGE LISTWIDTH IMAGEALIGN INTERACTIVECLOSE" ; // All datas that should not be enclosed in cuotes
*				.AND. !hb_IsArray(aDatas[i,2])	// VALID may be array of Grid, xbrowse or browse so do not include here			
*			// Do not enclose these in quotes
*			If !hb_IsString(aDatas[i,2])
*				cTxt += SPACE(nSpace)+aDatas[i,1]+" "+hb_cTxt(aDatas[i,2])+" ;"+HB_Eol()
*			Else
*				cTxt += SPACE(nSpace)+aDatas[i,1]+" "+aDatas[i,2]+" ;"+HB_Eol()
*			Endif

		ElseIf HB_ISLOGICAL(aDatas[i,2]) .AND. aDatas[i,2]				// Logical datas
			cTxt += SPACE(nSpace)+aDatas[i,1]	//+" ;"+HB_Eol()

		ElseIf hb_IsNumeric(aDatas[i,2]) .AND. aDatas[i,2] > 0		// numeric datas
*If o:Cargo[1] == "WINDOW" .and. aDatas[i,1] = "WIDTH"
*tone(2000,3)
*Endif
			cTxt += SPACE(nSpace)+aDatas[i,1]+" "+LTRIM(STR(aDatas[i,2]))	//+" ;"+HB_Eol()

		ElseIf hb_IsArray(aDatas[i,2]) //.AND. !EMPTY(aDatas[i,2])		// array datas
			If ASCAN(aDatas[i,2], {|a| a <> NIL}) > 0
				If aDatas[i,1] $ "HEADERS ITEMS OPTIONS INPUTMASK WIDTHS"
//					cTxt += SPACE(nSpace)+aDatas[i,1]+" "+(aDatas[i,2] := ArrayToString(aDatas[i,2], .T.))	//+" ;"+HB_Eol()
					cTxt += SPACE(nSpace)+aDatas[i,1]+" "+ ArrayToString(aDatas[i,2], .T.)	//+" ;"+HB_Eol()
				Else
					cTxt += SPACE(nSpace)+aDatas[i,1]+" "+(aDatas[i,2] := ArrayToString(aDatas[i,2]))	//+" ;"+HB_Eol()
//					cTxt += SPACE(nSpace)+aDatas[i,1]+" "+ ArrayToString(aDatas[i,2])	//+" ;"+HB_Eol()
				Endif
			
			Endif

		Elseif !EMPTY(aDatas[i,2]) .AND. aDatas[i,2] <> "NIL"		// string datas
			If LEFT(aDatas[i,1],2) == "ON" 								// EVENTS 
				cTxt += SPACE(nSpace)+LEFT(aDatas[i,1],2)+" "+SUBSTR(aDatas[i,1],3)+" "+aDatas[i,2]	//+" ;"+HB_Eol()

			ElseIf aDatas[i,1] = "ACTION" .OR. RIGHT(aDatas[i,1],5)	== "COLOR" 		// COLORS
				cTxt += SPACE(nSpace)+aDatas[i,1]+" "+aDatas[i,2]	//+" ;"+HB_Eol()

			ElseIf /*o:Cargo[1] == "COMBOBOX" .and. */ aDatas[i,1] $ "ITEMS VALUESOURCE OPTIONS"		// comobox exceptions
// posible caso de asignar variable a datos de array
				cTxt += SPACE(nSpace)+aDatas[i,1]+" "
				If aDatas[i,1] == "VALUESOURCE" .AND. LEFT(aDatas[i,2],1) = "{"
					// Exclusivo para ValueSource que debe ir entre parentesis cuando es array
					cTxt += "( "+aDatas[i,2]+" ) "	//;"+HB_Eol()
				Else
					cTxt += aDatas[i,2]	//+" ;"+HB_Eol()
				Endif

*			ElseIf aDatas[i,1] == "OPTIONS" // posible caso de asignar variable a OPTIONS
*				cTxt += SPACE(nSpace)+aDatas[i,1]+" "+aDatas[i,2]	//+" ;"+HB_Eol()

			Else
// comento la linea de abajo para que no ponga comillas
*				cTxt += SPACE(nSpace)+aDatas[i,1]+" '"+aDatas[i,2]+"' ;"+HB_Eol()
				cTxt += SPACE(nSpace)+aDatas[i,1]+" "+aDatas[i,2]	//+" ;"+HB_Eol()
			Endif
		ENDIF
		If !EMPTY(cTxt)
			If !lLong 
				cStr += cTxt + " ;"+hb_eol()
				cTxt := ""
			Else
				If LEN(cTxt) > 85
					cStr += cTxt + " ;"+hb_eol()
					cTxt := Space(nLongSpace-1)
				Endif
			Endif
		Endif
	Next

	If lLong .AND. !EMPTY(cTxt)
		cStr += cTxt
		If RIGHT(cStr,3) $ ";"
		Else
			cStr += " ;"+hb_eol()	// separar eventos de datas
		Endif
		nSpace := nLongSpace
	Endif
	
	// Save Events
	For i := 1 TO LEN(aEvents)
		If !EMPTY(aEvents[i,2]) .AND. UPPER(aEvents[i,2]) <> "NIL"
			If LEFT(aEvents[i,1],2) == "ON" .AND. o:Cargo[1] == "WINDOW"			// EVENTS 
				cStr += SPACE(nSpace)+LEFT(aEvents[i,1],2)+" "+SUBSTR(aEvents[i,1],3)+" "+aEvents[i,2]+" ;"+HB_Eol()
			Else
				cStr += SPACE(nSpace)+aEvents[i,1]+" "+aEvents[i,2]+" ;"+hb_eol()
			Endif
		Endif
	Next
	
	// Quitar último ;
*	msgbox( substr(cStr, -3,1) )
	If SUBSTR(cStr, -3,1) = ";"
		cStr := LEFT(cStr, LEN(cStr)-3)
	Endif
	IF !EMPTY(cStr) .AND. SUBSTR(cStr, -2,2) <> hb_eol()
		cStr +=hb_eol()
	Endif

Return cStr

Function ArrayToString(aArray, lComillas)
Local cStr, a
DEFAULT lComillas TO .F.
	cStr := "{ "
	For EACH a In aArray
		If HB_IsArray(a)
			cStr += ArrayToString(a, lComillas)+","
		ElseIf hb_IsNumeric(a)
			cStr += LTRIM(STR(a))+","
		ElseIf hb_IsDate(a)
			cSTR += DTOC(a)+","
		ElseIf hb_IsLogical(a)
			cStr += If(a, ".T.", ".F.")+","
		ElseIf hb_IsNil(a)
			cStr += ","
		ElseIf Type(a) == "B"	// For Blocks
			cStr += a+","
		Else
			If lComillas
				cStr += "'"+a+"',"
			Else
				cStr += a+","
			Endif
		Endif
	Next
	cStr := LEFT(cStr, LEN(cStr)-1) +" }"
Return cStr

Function xToString(a)
Local cStr
	cStr := ""
	If HB_IsArray(a)
		cStr := "{ "
		AEVAL(a, {|x| cStr += xToString(x)+","} )
		cStr := LEFT(cStr, LEN(cStr)-1) +" }"
	ElseIf hb_IsNumeric(a)
		cStr += LTRIM(STR(a))
	ElseIf hb_IsDate(a)
		cSTR += DTOC(a)
	ElseIf hb_IsLogical(a)
		cStr += If(a, ".T.", ".F.")
	ElseIf a = NIL
*			cStr += 'NIL'
		cStr += ''
	Else
*			cStr += "'"+a+"'"
		cStr += a
	Endif
Return cStr

Function ArrayHasData(aArray)
Return (ASCAN(aArray, {|a| !EMPTY(a) }) <> 0)
/*	
Procedure RMClick(o)
Local x := _oohg_MouseCol, y := _oohg_MouseRow
	IF o:ClassName = "TFORM"
		FormMenu(o, x, y)
	ELSE
		ControlMenu(o, x, y)
	ENDIF
Return

Procedure FormMenu( o, x, y )
Local oMenu
	DEFINE MENU DYNAMIC OF (o:Name) OBJ oMenu
		POPUP "Agregar Control" 
			ITEM "LABEL" 	ACTION AddControl("LABEL", 	x, y)
			ITEM "TEXTBOX" ACTION AddControl("TEXTBOX", 	x, y)
			ITEM "BUTTON" 	ACTION AddControl("BUTTON", 	x, y)
		END POPUP
		ITEM "Properties" ACTION msgbox("Row = "+str(o:Row)+" Col = "+str(o:Col))
	END MENU
	oMenu:Activate()
Return

Procedure ControlMenu( o )
Local oMenu
	DEFINE MENU DYNAMIC OF (o:Parent:Name) OBJ oMenu
*		ITEM "Move" ACTION MoveControl(o)
*		ITEM "Size" ACTION SizeControl(o)
		ITEM "Properties" ACTION msgbox("Row = "+str(o:Row)+" Col = "+str(o:Col))
	END MENU
	oMenu:Activate()
Return
*/
/*--------------------------------------------------------------------------------------------------------------------------------*/
FUNCTION IsValidColorArray( cColor )
/*--------------------------------------------------------------------------------------------------------------------------------*/
LOCAL aColor, uRet

	If Hb_IsArray(cColor)
      uRet := Len( cColor ) == 3 .AND. ;
              HB_ISNUMERIC( cColor[1] ) .AND. cColor[1] >= 0 .AND. cColor[1] <= 255 .AND. ;
              HB_ISNUMERIC( cColor[2] ) .AND. cColor[2] >= 0 .AND. cColor[2] <= 255 .AND. ;
              HB_ISNUMERIC( cColor[3] ) .AND. cColor[3] >= 0 .AND. cColor[3] <= 255
   ElseIF !hb_IsNil(cColor) .AND. "A" == Type( cColor )
      aColor := &( cColor )
		uRet := Len( aColor ) == 3 .AND. ;
				  HB_ISNUMERIC( aColor[1] ) .AND. aColor[1] >= 0 .AND. aColor[1] <= 255 .AND. ;
				  HB_ISNUMERIC( aColor[2] ) .AND. aColor[2] >= 0 .AND. aColor[2] <= 255 .AND. ;
				  HB_ISNUMERIC( aColor[3] ) .AND. aColor[3] >= 0 .AND. aColor[3] <= 255
		If uRet
			cColor := aColor
		Endif
   ELSE
      uRet := .F.
   ENDIF
RETURN uRet

/*--------------------------------------------------------------------------------------------------------------------------------*/
Function StrToColor( cColor ) 
/*--------------------------------------------------------------------------------------------------------------------------------*/
LOCAL uRet, nPos
   IF IsValidColorArray( @cColor )
      uRet := cColor 
	ELSEIF hb_IsNIL(cColor) .OR. EMPTY( cColor )
   ELSEIF Type( cColor ) == "N"
      uRet := Val( cColor )
   ELSE
      IF ( nPos := AScan( dSign_COLORS, {|cd| cd[1] == cColor } ) )  > 0
         uRet := dSign_COLORS[nPos, 2]
      ELSE
         uRet := NIL
      ENDIF
   ENDIF

RETURN uRet

Function ISNULL(xVar, xRet)
Return IF( HB_ISNIL(xVar), xRet, xVar)
