#include "H\General.H"
#include "H\Disco.H"
#include "H\Prog.H"
#include "H\Gastos.H"

#define Inc		10

typedef struct DCnt {
	Int16 	id;
	Boolean s;	// Tiene subniveles ?
	Boolean a;	// Esta abierto ?
} Cnt;

typedef struct DGas {
	Char            tipo;	 		// 0=Gasto 1=Ingreso
	Cnt 			*cnt;	 		// Manejo en memoria del control
	UInt8 			*col;	 		// Colores
	MemHandle 		mcn;
	Int16       	cn;		 		// Cantidad de datos
	Int16       	lx;		 		// Longitud total en alloc
	Int16       	sel;	 		// Selección
	Boolean     	cmb;	 		// Bandera de cambios
	Boolean     	edt;	 		// Hay edición ?
	MOVGA       	niv;	 		// Info. de la cuenta de gastos
	Boolean     	n0;		 		// Nivel 0 ?
	OCalc       	oc;		 		// Calculadora y teclado
	UInt16      	frm;	 		// De donde proviene y tipo de acceso
	Char        	tpa;     		// 1=Solo_editar  2=Seleccionar
	ID          	*rid;	 		// Regreso del id seleccionado
	Boolean     	busc;	 		// Buscar nivel cuando inicia
	Int16       	nn;		 		// Nivel superior
	Boolean     	ayu;	 		// Ayuda abierta ?
	CPer			per;
	Char            tpx;	 		// Cuando se llama 1=fijo 2=var 0=abierto
	Char            oper;	 		// 0=Interno 1=Viene de otra parte
	Boolean         qt;		 		// Quitar periodo en edición de cuenta
	Boolean         slc;	 		// Hay selección de cuentas ?
	Periodo         po;		 		// Periodo original
	Char            str[1][120];	// Para manejo de strings
} GAS;
GAS 		*gas;
MemHandle 	mga;

void 	IniFormaGA	(FormType*)										ES4;
void 	PntLGA		(Int16,RectangleType*,char**,ListType*)			ES4;
void 	IniEdtGastos(FormType*,Boolean)								ES4;
Boolean SelListaGA	(FormType*,Int16)								ES4;
void 	SBListaGA	(Boolean,Int16,Int16)							ES4;
Int16 	InsListaGA	(Int16,Int16,Boolean)							ES4;
void 	InsBorEspGA	(FormType*,Boolean)								ES4;
Boolean AgMemGA		(Int16)											ES4;
void 	BorrGA		(Int16)											ES4;
void 	PonPerX		(FormType*)										ES4;
void 	SumResPer	(double,Periodo*,Periodo*)						ES4;
void 	CapGA		(FormType *f)									ES4;


// **********************************************************************
//
// Disco
//
// **********************************************************************
// Inicio de los registros
void  IniciaRegGA () {
GA  			*ApI;
MOVGA 			*ApM;
UInt16  		NReg;
        ApI = SacarApRM();
        ApI->TipoReg=3;
        ApI->ProxRef=13;
        InsReg((INF*)ApI);
        
        ApM = SacarApMM();
        ApM->RefSup=0;
        ApM->Ref=1;
        ApM->Nivel=1;
        ApM->did=false;
        ApM->tpc=1;
        ApM->tpp=0;
        IniPer(0,&(ApM->Per));
        StrCopy(ApM->Nom,"Casa");
        SacarNReg (3,0,&NReg);
        InsMov((MOV*)ApM,NReg);		
        
           ApM->RefSup=1;
           ApM->Ref=5;
           ApM->Nivel=2;
           StrCopy(ApM->Nom,"Renta");
           InsMov((MOV*)ApM,NReg);		

           ApM->RefSup=1;
           ApM->Ref=6;
           ApM->Nivel=2;
           StrCopy(ApM->Nom,"Luz");
           InsMov((MOV*)ApM,NReg);		
        
        ApM->RefSup=0;
        ApM->Ref=2;
        ApM->Nivel=1;
        StrCopy(ApM->Nom,"Automovil");
        InsMov((MOV*)ApM,NReg);		

           ApM->RefSup=2;
           ApM->Ref=7;
           ApM->Nivel=2;
           StrCopy(ApM->Nom,"Gasolina");
           InsMov((MOV*)ApM,NReg);		

             ApM->RefSup=7;
             ApM->Ref=9;
             ApM->Nivel=3;
             StrCopy(ApM->Nom,"Gas 1");
             InsMov((MOV*)ApM,NReg);		
             
             ApM->RefSup=7;
             ApM->Ref=10;
             ApM->Nivel=3;
             StrCopy(ApM->Nom,"Gas 2");
             InsMov((MOV*)ApM,NReg);		

           ApM->RefSup=2;
           ApM->Ref=8;
           ApM->Nivel=2;
           StrCopy(ApM->Nom,"Mtto");
           InsMov((MOV*)ApM,NReg);		

        
        ApM->RefSup=0;
        ApM->Ref=3;
        ApM->Nivel=1;
        ApM->Per.op=0;
        StrCopy(ApM->Nom,"Personal");
        InsMov((MOV*)ApM,NReg);		
        
           ApM->RefSup=3;
           ApM->Ref=11;
           ApM->Nivel=2;
           ApM->Per.op=0;
           StrCopy(ApM->Nom,"Ropa");
           InsMov((MOV*)ApM,NReg);		

           ApM->RefSup=3;
           ApM->Ref=12;
           ApM->Nivel=2;
           ApM->Per.op=0;
           StrCopy(ApM->Nom,"Aseo");
           InsMov((MOV*)ApM,NReg);		
           
        ApI->TipoReg=5;
        ApI->ProxRef=2;
        InsReg((INF*)ApI);
        ApM->RefSup=0;
        ApM->Ref=1;
        ApM->Nivel=1;
        ApM->Per.tpv=1;
        IniPer(1,&(ApM->Per));
        StrCopy(ApM->Nom,"Sueldo");
        SacarNReg (5,0,&NReg);
        InsMov((MOV*)ApM,NReg);		
           
        return;
}

// Total de subniveles de un nivel (n=0 --> nivel principal)
Int16 TotGA(Char EsGI, Int16 NAct) {
UInt16     NReg;
Int16      NMov,nm;
Int16      t;
Int32      RefBuscar;
MOVGA      G;
Boolean    IB,Cont=true;
	//   Poner referencia a buscar	
  	if(!SacarNReg ((EsGI==0)?3:5,0,&NReg)) return 0;		
	NMov=NAct-1;
	if(NAct == 0) RefBuscar=0;
	else {
		if(!LeerMov((void*)&G,NReg,NMov,&IB)) return 0;
		RefBuscar=G.Ref;
	}
	//   Contar	los de esa referencia
	t=0;
	nm=-1;
	while (Cont) {
		if(!SacarProxRef(NReg,RefBuscar,&nm,true)) return 0;
		if(nm==-1) Cont=false;
		else t++;
	}
	return t;
}
// Sacar ID's del nivel id
Int16 IdGA(Char EsGI, Int16 NSup, Int16 pos) {
UInt16     NReg;
Int16      NMov,nm;
Int32      RefBuscar;
MOVGA      G;
Boolean    IB,Cont=true;
	//   Poner referencia a buscar	
  	if(!SacarNReg ((EsGI==0)?3:5,0,&NReg)) return 0;		
	NMov=NSup-1;
	if(NSup == 0) RefBuscar=0;
	else {
		if(!LeerMov((void*)&G,NReg,NMov,&IB)) return 0;
		RefBuscar=G.Ref;
	}
	//   Buscar la referencia contando
	nm=-1;
	while (Cont) {
		if(!SacarProxRef(NReg,RefBuscar,&nm,true)) return 0;
		if(pos == 0 && nm != -1 ) return nm+1;
		if(nm==-1) Cont=false;
		else pos--;
	}
	return -1;
}
// Leer(0), Guardar(1) o borrar(2) info del id
// dp=Id del cual depende 0=No depende de ninguno 
//						 -1=Solo guardar (edición)
//    cuendo no es -1 debe regresar el id nuevo en dp
Boolean CBG_GA(Char EsGI, Char op, Int16 id, void *g, Int16 *dp) {
GA         c;
UInt16     NReg;
Int16      NMov;
Boolean    IB;
MOVGA      d;
MOVGA	   *G;

	G=g; if(!SacarNReg((EsGI==0)?3:5,0,&NReg)) return 0;		
	switch(op) {
	case 0: // Leer
	        NMov=id-1;
	        if(!LeerMov((void*)G,NReg,NMov,&IB)) return false;
	        return true;
	case 1: // Guardar
	        if((*dp)==-1) {
	           NMov=id-1;
   	           if(!ModMov((void*)G,NReg,NMov)) return false;
   	           return true;
	        }
         	if(!LeerReg((void*)&c,NReg)) return false;
	        if((*dp)==0) { G->RefSup=0; G->Nivel=1;  }
	        else {
	        	  NMov = (*dp)-1;
	        	  if(!LeerMov((void*)&d,NReg,NMov,&IB)) return false;
	        	  G->RefSup=d.Ref;
	        	  G->Nivel=d.Nivel+1;
	        }
   	       	(*dp)=SacarTotMov(NReg)+1;
	       	G->Ref=c.ProxRef;
	       	c.ProxRef++;
            if(!ModReg((void*)&c,NReg)) return false;
            if(!InsMov((void*)G,NReg)) return false;
            return true;
		case 2: // Borrar
            NMov=id-1;
            if(!BorMov(NReg,NMov,true)) return false;
	    	return true;
	}
	return false;
}
//      Forma el vector *v* de *nv* elementos, 
//      con los *id* de el gasto *ID*. En *nv*
//      tiene al inicio el maximo.
Boolean FormaVecId (ID *ApID, Int16 *nv, Int16 *v) {
MOVGA      g;
UInt16     NReg;
Int16      NMov;
Boolean    IB;
Int16      tv=0;
Int32      RefBuscar;
Boolean    Cont=true;
        if(!SacarNRegNMov(ApID,&NReg,&NMov,false)) return false;
        while (Cont) {
          if(!LeerMov((void*)&g,NReg,NMov,&IB)) return false;
          if((tv+1)>=(*nv)) return false;
          v[tv]=NMov+1;
          tv++;
      	  if(g.RefSup==0){Cont=false;break;}
      	  RefBuscar=g.RefSup;
      	  NMov=-1;
     	  if(!SacarProxRef(NReg,RefBuscar,&NMov,false)) return false;
      	  if(NMov == -1 ) return false;
	}
	(*nv)=tv;
	return true;
}
// **********************************************************************
//
// Manejo de la lista en memoria
//
// **********************************************************************
// Subir / Bajar la lista a partir de p n posiciones
void SBListaGA(Boolean subir, Int16 p, Int16 n) {
Int16 i;
	if (subir) {
		for (i=p+n+1;i<gas->cn;i++) MemMove(&(gas->cnt[i-n]),&(gas->cnt[i]),sizeof(Cnt));
		gas->cn-=n;
	}
	else for (i=gas->cn-1;i>p;i--) MemMove(&(gas->cnt[i+n]),&(gas->cnt[i]),sizeof(Cnt));
}
// Insertar los niveles de id en pos p
Int16 InsListaGA(Int16 p, Int16 id, Boolean mover) {
int t,j;
	t=TotGA(gas->tipo,id); AgMemGA(t);
	if (mover) { SBListaGA(false,p,t); p++; }
	for (j=0;j<t;j++,p++) {
   		gas->cnt[p].id=IdGA(gas->tipo,id,j);
   		gas->cnt[p].a=false;
   		gas->cnt[p].s=(TotGA(gas->tipo,gas->cnt[p].id)>0);
	}
	gas->cn+=t;	return t;
}
// Analizar la selección
Boolean SelListaGA(FormType *f, Int16 s) {
Int16 n,i,d;
MOVGA niv;
GAS   *g;
    if (s==noListSelection) return false;  gas->sel=s;
    if (s==0) { 
    	gas->n0=true; 
    	FrmHideObject(f,FrmGetObjectIndex(f,BEdi)); 
    	if (gas->oper==2) FrmHideObject(f,FrmGetObjectIndex(f,BAce));
    	return true; 
    }
    FrmShowObject(f,FrmGetObjectIndex(f,BEdi)); 
    if (gas->cnt[s-1].s) {
    	if (gas->oper==2) FrmHideObject(f,FrmGetObjectIndex(f,BAce));
    	gas->cnt[s-1].a=!gas->cnt[s-1].a;
    	if (gas->cnt[s-1].a) InsListaGA(s-1,gas->cnt[s-1].id,true);
    	else {
    		g=gas; CBG_GA(gas->tipo,0,gas->cnt[s-1].id,&(gas->niv),&d);
    		for (n=0,i=s;i<gas->cn;i++) {
    			CBG_GA(gas->tipo,0,gas->cnt[i].id,&niv,&d);
    			if (niv.Nivel>gas->niv.Nivel) n++; else break;
    		}
    		SBListaGA(true,s-1,n);
    	}
    	return true;
    }
//    else if (gas->oper==2) FrmShowObject(f,FrmGetObjectIndex(f,BAce));
//    return false;
	else if (gas->oper==2) {
	   	if (gas->cnt[gas->sel-1].s) FrmHideObject(f,FrmGetObjectIndex(f,BAce));
		else FrmShowObject(f,FrmGetObjectIndex(f,BAce));
	}
	return true;
}
// Insertar un nuevo registro, borrar un registro
void BorrGA(Int16 id) {
Int16 t,i;
    t=TotGA(gas->tipo,id);
	while(t>0) { BorrGA(IdGA(gas->tipo,id,t-1)); t--; }
	CBG_GA(gas->tipo,2,id,NULL,NULL);
	for (i=0;i<gas->cn;i++) if (gas->cnt[i].id>id) gas->cnt[i].id--;
}
// Sumar o restar el valor de lperiodo tantantes veces se repita
// a la fecha de hoy (sg==-1-> restar ==1->sumar)
void SumResPer(double sg, Periodo *per, Periodo *po) {
PROG   pro;
Fecha  h,p,q;
double v,vt;
   if (per->op==0) return;	
   if (sg>0) {
   	ProxFPPer(&(per->f),per,1);
   	if (gas->edt) do { 
   		if (Comp2Fec(&(per->f),&(po->f))==-1) ProxFPPer(&(per->f),per,4);
   	    else break;
   	} while(1==1);
   }
   CG_PR(0,(void*)&pro);
   FecHoy(&h); h.d=1; SumarMeses(1,&h);
   CopFec(&q,&(per->f)); v=0; vt=per->v;
   do { CopFec(&p,&q); ProxFPPer(&p,per,2);
    	if (Comp2Fec(&h,&p)==1) 
    	{ v+=vt; ProxFPPer(&q,per,3); } else break;
   } while(1==1);
   v*=sg;
   switch(per->tpv) {
	   case 0: switch(per->op) { case 1: pro.sfe+=v; break;
	   	       			    	 case 2: pro.sve+=v; break;  } break;
	   case 1: switch(per->op) { case 1: pro.sfi+=v; break;
	   	       					 case 2: pro.svi+=v; break;  } break;
   }
   CG_PR(1,(void*)&pro);
}
void InsBorEspGA(FormType *f, Boolean borrar) {
Int16 	q,d,i,j,id;
MOVGA   n;
Char    s[120];
   SumResPer(-1,&(gas->po),NULL);
   if (!borrar) {
   	   Texto(gas->niv.Nom,GetObjPtr(f,100),false);
   	   if (!gas->qt) {
   	   	 if (gas->niv.Per.op!=0) {
   	   	 	Texto(s,GetObjPtr(f,113),false); gas->niv.Per.v=AdblX(s);
   	   	    SumResPer(1,&(gas->niv.Per),&(gas->po));
   	   	 }
   	   	 else { gas->niv.Per.v=0; }
   	   }
   	   if (gas->oper==1) GuardarConID(gas->rid,&(gas->niv));
   	   else {
   	   	AgMemGA(1);
	   	if (gas->edt) { d=-1; CBG_GA(gas->tipo,1,gas->cnt[gas->sel-1].id,&(gas->niv),&d); }
	   	else {
		   if (gas->sel==0) d=0; else d=gas->cnt[gas->sel-1].id; 
	       CBG_GA(gas->tipo,1,0,&(gas->niv),&d);
	       if (gas->sel!=0) if (!gas->cnt[gas->sel-1].s) gas->cnt[gas->sel-1].s=true;
	       if (gas->sel==0) {
	       	  gas->cnt[gas->cn].s=gas->cnt[gas->cn].a=false;
	       	  gas->cnt[gas->cn].id=d; gas->cn++;
	       }
	       else if (gas->cnt[gas->sel-1].a) {
	       	  i=gas->sel; do {
	       	  	CBG_GA(gas->tipo,0,gas->cnt[i].id,&n,&q);
	       	  	if (gas->nn>=n.Nivel) break; i++;
	       	  } while (i<gas->cn);
			  SBListaGA(false,i-1,1);
	       	  gas->cnt[i].s=gas->cnt[i].a=false;
	       	  gas->cnt[i].id=d; 
	       	  gas->cn++;
	       }
	   	}
   	   }
   } else {
   	   if (gas->cnt[gas->sel-1].a) {
    	 for (j=1,i=gas->sel;i<gas->cn;i++) {
    		CBG_GA(gas->tipo,0,gas->cnt[i].id,&n,&q);
    		if (n.Nivel>gas->niv.Nivel) j++; else break;
    	 }
   	   } else j=1;
   	   id=gas->cnt[gas->sel-1].id;
	   for (i=gas->sel-1+j;i<gas->cn;i++) MemMove(&(gas->cnt[i-j]),&(gas->cnt[i]),sizeof(Cnt));
	   gas->cn-=j;
	   BorrGA(id);
   }
}
// **********************************************************************
//
// Inicio, termino, pintar formas y control borrar y home
//
// **********************************************************************
// Inicio y término de EFECTIVO
Boolean FinalizaGA() {
Boolean cmb;
	if (gas->ayu) FinAyuda();
	if (gas->slc) FinalizaCuentas();
	MemHandleUnlock(gas->mcn); MemHandleFree(gas->mcn); gas->cnt=NULL;
	cmb=gas->cmb;
	MemHandleUnlock(mga); MemHandleFree(mga); gas=NULL;
	return cmb;
}
Char IniciaGastos(Char tipo, Char op, UInt16 f, ID *id, Boolean busc, UInt8 *c, Char tpx) { 
	mga=MemHandleNew(sizeof(GAS));
	gas=(GAS *)MemHandleLock(mga);
	gas->lx=Inc;
	gas->mcn=MemHandleNew(sizeof(MOVGA)*gas->lx);
	gas->cnt=MemHandleLock(gas->mcn);
	gas->cn=0;
	gas->col=c;	gas->frm=f;	gas->tpa=op; gas->rid=id; gas->busc=busc;
	gas->edt=false;	gas->cmb=false; gas->ayu=false;
	gas->tipo=tipo;
	gas->tpx=tpx;
 	gas->slc=false;
	switch(op) {
	case 1: gas->oper=0; FrmPopupForm(FGastos); break;
	case 2: gas->oper=0; FrmPopupForm(FGastosM); break;
	case 3: gas->edt=true; gas->oper=1; FrmPopupForm(FEdtGastos); break;
	case 4: gas->oper=2; FrmPopupForm(FGastosM); break;
	}
	return 3; 
}
Boolean AgMemGA(Int16 t) {
	if (gas->lx-gas->cn<t) {
		do gas->lx+=Inc; while (gas->lx-gas->cn<t);
		MemHandleUnlock(gas->mcn);
		MemHandleResize(gas->mcn,sizeof(MOVGA)*gas->lx);
		gas->cnt=MemHandleLock(gas->mcn);
	} 
	return true;
}
// **********************************************************************
//
// GASTOS
//
// **********************************************************************
// Editar / Nueva cuenta de gastos
void PonPerX(FormType *f) {
Char s[120];
	if (gas->niv.Per.op==0) {
		FrmHideObject(f,FrmGetObjectIndex(f,202));
		FrmHideObject(f,FrmGetObjectIndex(f,203));
		FrmHideObject(f,FrmGetObjectIndex(f,113));
		if (gas->per.act) PonPerCamp(&(gas->per),true);
    	gas->per.act=false; gas->per.tp=1;
	}
	else {
    	gas->per.act=true;
		FrmShowObject(f,FrmGetObjectIndex(f,202));
		FrmShowObject(f,FrmGetObjectIndex(f,203));
		FrmShowObject(f,FrmGetObjectIndex(f,113));
		gas->per.r.topLeft.x=57; gas->per.r.topLeft.y=111;
		PonPerCamp(&(gas->per),false);
		AstrX(gas->niv.Per.v,s,false,false); Texto(s,GetObjPtr(f,113),true);
	}
	CtlSetValue(GetObjPtr(f,110),((gas->niv.Per.op==0)?1:0));
	CtlSetValue(GetObjPtr(f,111),((gas->niv.Per.op==1)?1:0));
	CtlSetValue(GetObjPtr(f,112),((gas->niv.Per.op==2)?1:0));
}
void IniEdtGastos(FormType *f, Boolean ini) {
Char  			s[120];
Int16 			d,cl;
	if (ini) {
		if (gas->oper==1) {
			gas->edt=true; LeerConID(gas->rid,&(gas->niv),false); gas->qt=false;
		}
		else {
			gas->qt=(gas->cnt[gas->sel-1].s);
			if (gas->sel!=0) {
				CBG_GA(gas->tipo,0,gas->cnt[gas->sel-1].id,&(gas->niv),&d);
				if (gas->oper==2) SacarID(gas->rid);
			}
			else gas->niv.Nivel=0; 
			if (gas->oper==2) gas->niv.Per.op=gas->tpx;
		}
	}
	if (gas->qt) {
		FrmHideObject(f,FrmGetObjectIndex(f,201));
		FrmHideObject(f,FrmGetObjectIndex(f,202));
		FrmHideObject(f,FrmGetObjectIndex(f,203));
		FrmHideObject(f,FrmGetObjectIndex(f,204));
		FrmHideObject(f,FrmGetObjectIndex(f,110));
		FrmHideObject(f,FrmGetObjectIndex(f,111));
		FrmHideObject(f,FrmGetObjectIndex(f,112));
		FrmHideObject(f,FrmGetObjectIndex(f,113));
		FrmHideObject(f,FrmGetObjectIndex(f,115));
	}
	if (ini) FrmDrawForm(f);
	switch(gas->tipo) {
	case 0: SacaTexto(s,2300,(!gas->edt)?2:1,120); FrmCopyTitle(f,s);
			if (!(gas->qt)) {
				SacaTexto(s,2300, 8,120); FrmCopyLabel(f,201,s);
				SacaTexto(s,2300,10,120); FrmCopyLabel(f,204,s);
			}
			break;
	case 1: SacaTexto(s,2300,(!gas->edt)?6:5,120); FrmCopyTitle(f,s);
			if (!(gas->qt)) {
				SacaTexto(s,2300, 9,120); FrmCopyLabel(f,201,s);
				SacaTexto(s,2300,11,120); FrmCopyLabel(f,204,s);
			}
			break;
	}
	cl=WinSetForeColor(gas->col[0]); WinSetForeColor(cl);
	if (ini) {
		gas->nn=gas->niv.Nivel;
		if (!gas->edt) { 
			IniPer(gas->tipo,&(gas->niv.Per));
			StrCopy(gas->niv.Nom," ");	gas->niv.Nivel++; 
			gas->niv.did=false; gas->niv.tpc=1;
			FrmHideObject(f,FrmGetObjectIndex(f,BBor));
		} else {
			if (gas->oper==1) FrmHideObject(f,FrmGetObjectIndex(f,BBor));
			else FrmShowObject(f,FrmGetObjectIndex(f,BBor));
	    }
	    gas->per.p=&(gas->niv.Per); gas->per.f=FEdtGastos; 
	    gas->per.ayu=&(gas->ayu);  gas->per.col=gas->col;
	}
	Texto(gas->niv.Nom,GetObjPtr(f,100),true);
    if (!(gas->qt)) {
    	PonPerX(f);
    	if (gas->niv.tpc==2 && !gas->niv.did) gas->niv.tpc=1;
    	switch(gas->niv.tpc) {
    		case 0: 
    		case 1: Lista(GetObjPtr(f,115),GetObjPtr(f,116),gas->niv.tpc,true,0,NULL); break;
    		case 2: PonValorCuenta(f,115,&(gas->niv.id),gas->niv.did,gas->str[0]); break;
    	}
    }
    if (gas->oc.op) RefBotonCT(&(gas->oc));
}
void CapGA(FormType *f) {
Char s[120];
   Texto(gas->niv.Nom,GetObjPtr(f,100),false);
   if (!gas->qt)
   if (gas->niv.Per.op!=0) 
   	{ Texto(s,GetObjPtr(f,113),false); gas->niv.Per.v=AdblX(s); }
}
Boolean EdtGastos(EventType* pEvent) {
Int16 v;
	switch (pEvent->eType) {
		case frmUpdateEvent:
			switch(pEvent->data.frmUpdate.updateCode) {
			case 70: break;
			case 90: gas->ayu=false; break;
			case 92: gas->slc=false; break;
			case 93: gas->slc=false; gas->niv.did=true; break;
			case 98: break;
			default: return false;
			}
			IniEdtGastos(FrmGetActiveForm(),false);
			return true;
		case frmOpenEvent:
			PonBotonCT(&(gas->oc),2,100,NULL,gas->niv.Nom,FrmGetActiveForm(),sizeof(gas->niv.Nom),2300,3);
			IniEdtGastos(FrmGetActiveForm(),true);
			MemMove(&(gas->po),&(gas->niv.Per),sizeof(Periodo));
			return true;
		case ctlSelectEvent:
		    switch(pEvent->data.ctlSelect.controlID) {
		    case BCal: CapGA(FrmGetActiveForm());
		               OpBotonCT(&(gas->oc)); return true;
		   	case BAce: InsBorEspGA(FrmGetActiveForm(),false);
			case BCan: if (gas->oper!=2) FrmUpdateForm(((gas->oper==0)?FGastos:FConfirmarPR),99); 
	   				   else if (gas->edt) FrmUpdateForm(FGastos,89); 
	   				        else FrmUpdateForm(FGastos,99);  
			           if (gas->oper==1) FinalizaGA();
	   				   FrmReturnToForm(0);
		   	           return true;
		   	case BBor: if (FrmAlert(104)==1) {
		   			   	  InsBorEspGA(FrmGetActiveForm(),true);
		   				  FrmUpdateForm(FGastos,98);
		   				  FrmReturnToForm(0);
		   			   }
					   return true;
		   	case BAyu: CapGA(FrmGetActiveForm());
		               gas->ayu=Ayuda(((gas->tipo==0)?2304:2314),1,gas->col,FEdtGastos); return true;
		   	case  110: if (gas->niv.Per.op!=0) gas->niv.Per.op=0; PonPerX(FrmGetActiveForm()); break;
		   	case  111: if (gas->niv.Per.op!=1) gas->niv.Per.op=1; PonPerX(FrmGetActiveForm()); break;
		   	case  112: if (gas->niv.Per.op!=2) gas->niv.Per.op=2; PonPerX(FrmGetActiveForm()); break;
		    }
        case ctlEnterEvent:
            switch(pEvent->data.ctlEnter.controlID) {
   		    case  115: CapGA(FrmGetActiveForm());
   		               v=LstPopupList(GetObjPtr(FrmGetActiveForm(),116));
   		               if (v==-1) return true;
   		               gas->niv.tpc=(Char)v;
   		               switch(gas->niv.tpc) {
   		               case 0: 
   		               case 1: Lista(GetObjPtr(FrmGetActiveForm(),115),GetObjPtr(FrmGetActiveForm(),116),gas->niv.tpc,true,0,NULL); break;
   		               case 2: gas->slc=IniciaCuentas(FEdtGastos,NULL,&(gas->niv.id),gas->niv.did,gas->col); break;
   		               }
   		               return true;
            }
            break;
	    case fldEnterEvent:
            switch(pEvent->data.fldEnter.fieldID) {
   		    case  100: PonBotonCT(&(gas->oc),2,100,NULL,gas->niv.Nom,FrmGetActiveForm(),sizeof(gas->niv.Nom),2300,3); return false;
   		    case  113: PonBotonCT(&(gas->oc),1,113,&(gas->niv.Per.v),NULL,FrmGetActiveForm(),0,2300,0); return false;
           	default  : PonBotonCT(&(gas->oc),0,0,NULL,NULL,FrmGetActiveForm(),0,2300,0); return false;
            }
		    break;
        case penDownEvent:
            if (EnPeriodo(pEvent->screenX,pEvent->screenY,&(gas->per))) {
            	CapGA(FrmGetActiveForm());
            	PonPerCamp(&(gas->per),true);
		        SelecPeriodo(&(gas->per),false);
                return true;
            }
            break;
		default: break;
	}
	return false;
}
// Pintar lista resumen (desde SO)
void PntLGA(Int16 it, RectangleType *r,char **u, ListType *p) {
Int16    		x,x1,y,w,d;
Int8            a,n;
RectangleType   e;
Char            s[50];
    x=r->topLeft.x; y=r->topLeft.y; w=150;
    if (it==0) { 
    	SacaTexto(s,2300,((gas->tipo==0)?0:4),50); PonTexto(s,x,y,N,I,w,false,-1,-1,&a); 
    }
    else {
	    CBG_GA(gas->tipo,0,gas->cnt[it-1].id,&(gas->niv),&d);
	    x1=x+2; n=1;
	    while (n<gas->niv.Nivel) { 	n++; x1+=8; w-=8;  }
	   	e.topLeft.x=x1+1; e.topLeft.y=y+1+((r->extent.y-2)/2); 
	   	e.extent.x=2;  e.extent.y=2;
	   	if (gas->cnt[it-1].s && !gas->cnt[it-1].a)	
	   	{ e.topLeft.x-=1; e.extent.x+=2; e.extent.y+=2; WinDrawRectangle(&e,0); }
		else WinDrawRectangleFrame(simpleFrame,&e);
	    PonTexto(gas->niv.Nom,e.topLeft.x+9,y,N,I,w,false,-1,-1,&a);
    }
}
// Iniciar y pintar forma
void IniFormaGA(FormType *f) {
Int16       t,n,i,j,v[25];
Char        s[120];
	SacaTexto(s,2300,((gas->tipo==0)?0:4),120); FrmCopyTitle(f,s);
	FrmDrawForm(f); 
    gas->cn=0; gas->sel=0; t=InsListaGA(0,0,false);
    if (gas->tpa==2 && gas->busc) {
    	for (i=0;i<25;i++) v[i]=0;
		n=25; FormaVecId(gas->rid,&n,v); j=n-1; i=0;
		do { if (v[j]==gas->cnt[i].id) {
				if (j==0) { gas->sel=i+1; break; }
				t+=InsListaGA(i,gas->cnt[i].id,true); j--;
			 } i++;
		} while(1==1);
    }
	if (gas->oper==2) FrmHideObject(f,FrmGetObjectIndex(f,BAce));
	if (gas->sel==0) FrmHideObject(f,FrmGetObjectIndex(f,BEdi));
	EliminaMarco(f,100,(ListDrawDataFuncPtr)PntLGA,gas->cn+1,true,gas->sel);
}
// Principal
Boolean Gastos(EventType* pEvent) {
UInt16 f;
Char   t;
Int16  d;
	switch (pEvent->eType) {
		case frmUpdateEvent:
			switch(pEvent->data.frmUpdate.updateCode) {
			case 89: f=gas->frm; FrmUpdateForm(f,95);
		   	         FinalizaGA(); FrmReturnToForm(0); return true;
			case 90: gas->ayu=false; break;
			case 98:
			case 99: EliminaMarco(FrmGetActiveForm(),100,(ListDrawDataFuncPtr)PntLGA,
			                      gas->cn+1,false,gas->sel); break;
			default: return false;
			}
			return true;
		case frmOpenEvent:
			IniFormaGA(FrmGetActiveForm()); gas->n0=true;
			return true;
		case ctlSelectEvent:
		    switch(pEvent->data.ctlSelect.controlID) {
	    	case BAyu: gas->ayu=Ayuda(((gas->tipo==0)?((gas->tpa==1)?2302:2306):
	    							  ((gas->tpa==1)?2312:2316)),1,gas->col,FGastos); 
	    			   return true;
		   	case BAce: if (gas->oper==2) {
							if (gas->sel!=0) 
							{ gas->edt=true; FrmPopupForm(FEdtGastos); }
		   			   }
		   			   else {
			   	           f=gas->frm; t=gas->tpa;
			   			   if (t==2) {
			   				 if (gas->cnt[gas->sel-1].s) { Ayuda(((gas->tipo==0)?2300:2310),3,gas->col,FGastos); return true; }
			   				 CBG_GA(gas->tipo,0,gas->cnt[gas->sel-1].id,&(gas->niv),&d);
			   				 SacarID(gas->rid);
			   			   }
			   	           FinalizaGA(); 
			   	           if (t==2) FrmUpdateForm(f,95);
			   	           else      FrmUpdateForm(f,99);
			   	           FrmReturnToForm(0); 
		   			   }
		   	           return true;
		   	case BNue: gas->edt=false; FrmPopupForm(FEdtGastos); return true;
		   	case BEdi: if (gas->sel==0) return true;
		   	           gas->edt=true; FrmPopupForm(FEdtGastos); return true;
		   	case BCan: f=gas->frm; t=gas->tpa;
		   	           FinalizaGA(); 
		   	           if (t==2 || t==4) FrmUpdateForm(f,94);
		   	           FrmReturnToForm(0); return true;
		    }
		    break;
        case lstSelectEvent:
          	if (SelListaGA(FrmGetActiveForm(),pEvent->data.lstSelect.selection))
          	    EliminaMarco(FrmGetActiveForm(),100,(ListDrawDataFuncPtr)PntLGA,gas->cn+1,false,gas->sel);
            return true;
		default: break;
	}
	return false;
}
