#include "H\General.H"
#include "H\Credito.H"
#include "H\Efectivo.H"
#include "H\Inst.H"
#include "H\Disco.H"
#include "H\Calc.H"
#include "H\Teclado.H"
#include "H\Bancos.H"

void 	 	RegMov		 		(Char,void*,void*,ID*)			ES5; // Si se cambia aquí se debe cambiar en Prog.c
Int16 		CantidadCuentas		(ID*)                      		ES3;
Boolean 	AfectarCuenta		(Int16,Int8,ID*,void*)          ES3;
void		PintaListaCuentas	(FormType*,Boolean)    			ES3;
void 		CopiaValCta			(Char,Char,void*,ID*) 			ES3;

/***********************************************************************
 *
 * Rutinas de apoyo
 *
 **********************************************************************/
// ---------------------------------------------------------------------
// 								Ajustar String
// ---------------------------------------------------------------------
void AjustaSTR(Char *d, Char *f, Int16 l) {
Int16 i,j,w;
	StrCopy(d,f); if (d==NULL) return;
	j=StrLen(f)+1; if (j==1) return;
	do { for (i=0,w=0;i<StrLen(d);i++) w+=(UInt16)FntCharWidth(d[i]);
		 if (w<=l) break;
		 j--; for (i=0;i<j;i++) d[i]=f[i]; d[i]=0; StrCat(d,"...");
	} while (j!=0);
}
// ---------------------------------------------------------------------
// 								Calculadora y teclado
// ---------------------------------------------------------------------
void PonBotonCT(OCalc *o, Char opc, Int16 id, double *v, Char *s, FormType *f, 
                Int16 mx, Int16 nt, Int16 it) {
ControlType *c;
	c=GetObjPtr(f,BCal); 
	o->calv=v; o->cals=s; o->tcc=opc; o->mtc=mx; o->txt=it; 
	o->calid=id; o->f=f; o->op=false; o->nt=nt;
	switch(opc) {
	case 0: CtlSetUsable(c,false);
	        CtlSetGraphics(GetObjPtr(f,BCal),107,NULL);  break;
	case 1: CtlSetUsable(c,true);
	        CtlSetGraphics(GetObjPtr(f,BCal),5053,NULL); break;
	case 2: CtlSetUsable(c,true);
            CtlSetGraphics(GetObjPtr(f,BCal),5100,NULL); break;
	}
}
void RefBotonCT(OCalc *o) {
ControlType *c;
	c=GetObjPtr(o->f,BCal); 
	switch(o->tcc) {
	case 0: CtlSetUsable(c,false);
	        CtlSetGraphics(GetObjPtr(o->f,BCal),107,NULL);  break;
	case 1: CtlSetUsable(c,true);
	        CtlSetGraphics(GetObjPtr(o->f,BCal),5053,NULL); break;
	case 2: CtlSetUsable(c,true);
            CtlSetGraphics(GetObjPtr(o->f,BCal),5100,NULL); break;
	}
//	FrmSetFocus(o->f,FrmGetObjectIndex(o->f,o->calid));	
	o->op=false;
}
void OpBotonCT(OCalc *o) {
Char  t[151];
	switch(o->tcc) {
	case 1: o->op=true;
	        Texto(t,GetObjPtr(o->f,o->calid),false); *(o->calv)=AdblX(t);
	        IniciaCalc(0,o->f,o->calv); break;
	case 2: o->op=true;
	        SacaTexto(t,o->nt,o->txt,sizeof(t));
	        Texto(o->cals,GetObjPtr(o->f,o->calid),false);
			IniTecladoX(o->f,o->cals,o->mtc,t); break;
	}
}
// ---------------------------------------------------------------------
// 								    Cuentas
//  Manejo de selección de cuentas
// ---------------------------------------------------------------------
typedef struct DCue {
	ID 		  *id,*rg;		// ID fuente y regreso
	Int16 	  f;			// Forma de llamada
	Int8      *col;			// Colores
	Boolean   def;			// rg contiene valor inicial ?
	Boolean   sel;			// Hay seleccionado ?
	Boolean   cre;
	Boolean   efe;
	Boolean   ba;
} CUE;
MemHandle mcu;
CUE       *cue;
// Sacar cantidad de registro tipo credito, efectivo y bancos
// Si id !=NULL revisa no sea cuenta con id
Int16 CantidadCuentas(ID * id) {
Int16 t=0,i,tr,str;
ID    idl;
        for(i=0;i<SacarTotReg();i++) {
	        	if(!LeerTyST(i,&tr,&str)) return 0;
            	if(!(tr == 1 || tr == 2 || tr == 7 )) continue;
            	SacarID(&idl);
                if(id != NULL) if(id->r == idl.r) continue;
             	t++;
        }
        return t;
}
// Cargar(0) y guardar(1) registro general de tipo credito, efectivo, ...
// Si id !=NULL revisa no sea cuenta con id
Boolean AfectarCuenta(Int16 it, Int8 op, ID *id, void *inf) {
Int16     i,tr,str;
ID        idl;
         for(i=0;i<SacarTotReg();i++) {
	        	if(!LeerTyST(i,&tr,&str)) return false;
            	if(!(tr == 1 || tr == 2 || tr == 7 )) continue;
            	SacarID(&idl);
                if(id != NULL) if(id->r == idl.r) continue;
	        	if(it==0) break;
             	it--;
        }
        if(it!=0) return false;
        switch(op) {
	    case 0: // Cargar
        	if(!LeerReg(inf,i)) return false;
			return true;
        case 1: // Guardar 
            if(!ModReg(inf,i)) return false;
            return true;
        default:
            return false;            
        }
}
// Iniciar y liberar memoria
Boolean IniciaCuentas(Int16 f, ID *id, ID *rg, Boolean def, Int8 *col) {
	mcu=MemHandleNew(sizeof(CUE));
	cue=(CUE *)MemHandleLock(mcu);
	cue->f=f; cue->id=id; cue->rg=rg; cue->col=col;	cue->def=def; 
	cue->sel=false; 
	cue->cre=false;
	cue->efe=false;
	cue->ba=false;	
	FrmPopupForm(FSelecCuenta);
	return true;
}
void FinalizaCuentas() {
	if (cue->cre) FinalizaCR(false);
	if (cue->efe) FinalizaEF();
	if (cue->ba)  FinalizaBA(false);	
	MemHandleUnlock(mcu); MemHandleFree(mcu);
}
// Sacar tipo de registro
void TpRegCuenta(void *d, UInt8 *tc, UInt8 *sb) {
NADA *n;
CRE  *cre;
	n=(NADA*)d; *tc=n->TipoReg;
	switch(*tc) {
	case 1: cre=(CRE*)d; *sb=cre->tp; break;
	case 2: *sb=0; break;
	}
}
// Pintar la lista
void PntCUE(Int16 it, RectangleType *r,char **u, ListType *p) {
Boolean  		pn;
Int16    		i,j,bc,x,y;
RectangleType 	q;
void            *rg;
CRE   		    *cre;
EFE				*efe;
MOVIN			inst;
REGBA           *rb;
Char            s[51];
Int8            a;
UInt8           tc,ts;
	pn=SelecLst(cue->col[0]);
    q.topLeft.x=r->topLeft.x; q.topLeft.y=r->topLeft.y; 
    q.extent.y=r->extent.y; q.extent.x=150;
    if (pn) {
		bc=WinSetBackColor((((it&0x01)>0)?cue->col[6]:cue->col[2])); 
		WinEraseRectangle(&q,0);
    }
    x=r->topLeft.x; y=r->topLeft.y;
    rg=SacarApRM(); AfectarCuenta(it,0,cue->id,rg);
    TpRegCuenta(rg,&tc,&ts);
    switch(tc) {
    case 1: cre=rg;
            PintaImagen(2110+cre->tp,x,y+1);  x+=16;
    	    PonTexto(cre->ctc,x,y,N,I,20,false,-1,-1,&a); x+=22;
    	    for (i=StrLen(cre->num)-4,j=0;j<4;i++,j++) s[j]=cre->num[i]; s[j]=0;
    	    PonTexto(s,x,y,N,I,25,false,-1,-1,&a); x+=30;
    	    if (cre->DInst) {
    	    	LeerConID(&(cre->Inst_ID),&inst,false);
    	    	PonTexto(inst.Nom,x,y,N,I,84,false,-1,-1,&a);
    	    }
    		break;
    case 2: efe=rg;
            PintaImagen(153,x,y+1);  x+=16;
    	    PonTexto("Efectivo",x,y,N,I,34,false,-1,-1,&a);
    		break;
    case 7: rb=rg;
            TextoLinBA(rb,x,y,r->extent.x);
            break;
    }
	if (pn) WinSetBackColor(bc);
}
void PintaListaCuentas(FormType *f, Boolean ini) {
Int16    i,c;
void     *rg;
ID       id;
    c=CantidadCuentas(cue->id);
    EliminaMarco(f,100,(ListDrawDataFuncPtr)PntCUE,c,ini,-1);
    if (cue->def) {
    	rg=SacarApRM();
    	for (i=0;i<c;i++) {
    	   AfectarCuenta(i,0,cue->id,rg); SacarID(&id);
    	   if (MemCmp(&id,cue->rg,sizeof(ID))==0) { 
    	   	 LstSetSelection((ListType*)GetObjPtr(FrmGetActiveForm(),100),i); 
    	   	 cue->sel=true;break; 
    	   }
    	}
    }
}
UInt8 TextoCuenta(Char *s, ID *id, Boolean largo) {
CRE   		    *cre;
EFE				*efe;
REGBA           *rb;
MOVIN			inst;
Char            t[5];
Int16           i,j;
UInt8			tp;
	cre=SacarApRM(); LeerConID(id,cre,true); tp=SacarTpApRM();
    switch(tp) {
    case 1: cre=SacarApRM();
    		StrCopy(s,cre->ctc); StrCat(s," ");
    	    for (i=StrLen(cre->num)-4,j=0;j<4;i++,j++) t[j]=cre->num[i]; t[j]=0;
    	    StrCat(s,t); StrCat(s," ");
    	    if (cre->DInst) { LeerConID(&(cre->Inst_ID),&inst,false); 
    	    	i=StrLen(s); j=0;
    	    	do { s[i++]=inst.Nom[j++]; } while (i<17 && j<StrLen(inst.Nom));
    	    	s[i]=0; if (i>=17) StrCat(s,"..");
    	    }
    		break;
    case 2: efe=SacarApRM(); SacaTexto(s,1000,4,120);    		
            break;
    case 7: rb=SacarApRM(); TextoCtlBA(rb,s);
            break;        
    }
    return tp;
}
// Poner valor en forma de llamada
UInt8 PonValorCuenta(FormType *f, Int16 it, ID *id, Boolean def, Char *s) {
UInt8 tp;
	if (!def) return 0;
	tp=TextoCuenta(s,id,false);
   	CtlSetLabel(GetObjPtr(f,it),s);	
   	return tp;
}
// Forma principal
Boolean SelecCuenta(EventType* pEvent) {
Int16 v;
void  *rg;
	switch (pEvent->eType) {
		case frmUpdateEvent:
			switch(pEvent->data.frmUpdate.updateCode) {
			case 60: cue->ba=false;					
			case 86: 
			case 87: cue->cre=false; break;
			case 98:
			case 99: cue->efe=false; break;
			default: return false;
			}
			PintaListaCuentas(FrmGetActiveForm(),false);
			return true;
		case frmOpenEvent:
			FrmDrawForm(FrmGetActiveForm());
		    PintaListaCuentas(FrmGetActiveForm(),true);
			return true;
		case ctlSelectEvent:
		    switch(pEvent->data.ctlSelect.controlID) {
		   	case BAce: if (cue->sel==false) break;
		   	           FrmUpdateForm(cue->f,93);
		   			   FinalizaCuentas(); FrmReturnToForm(0);		   			   
		   	           return true;
		   	case BCan: FrmUpdateForm(cue->f,92);
		   			   FinalizaCuentas(); FrmReturnToForm(0);		   			   
		   	           return true;
		   	case BAyu: return true;
		   	case BNue: v=LstPopupList((ListType*)GetObjPtr(FrmGetActiveForm(),105));
		   			   switch(v) {
		   			   	// Crédito
		   			   	case 0: case 1: case 2: case 3: 
		   			   	case 4: cue->cre=true; IniciaCR(cue->col,2+v,FrmGetActiveForm(),NULL); return true;
			   	        case 5: case 6: case 7: cue->ba=true;IniciaBA(cue->col,v-3,NULL); return true;		   			   	
		   			   }
    				   break;
    		case BEdi: if (cue->sel==false) break;
					   rg=SacarApRM(); LeerConID(cue->rg,rg,true);
					   switch(SacarTpApRM()) {
					   case 1: cue->cre=true; IniciaCR(cue->col,7,FrmGetActiveForm(),cue->rg); break;	
					   case 2: cue->efe=true; IniciaEF(cue->col,2,FrmGetActiveForm()); break;
					   case 7: cue->ba=true;  IniciaBA(cue->col,5,cue->rg);					   
					   }
    				   return true;
		    }
		    break;
        case lstSelectEvent:
		    v=pEvent->data.lstSelect.selection;
		    if (v==noListSelection) break;
		    cue->sel=true;
    	    rg=SacarApRM(); AfectarCuenta(v,0,cue->id,rg); SacarID(cue->rg);
            return true;
		default: break;
	}
	return false;
}
//    Inicia cuenta en confirmar programado  
void IniCuenta(FormType *f, Boolean hid, ID *id, Char *tp, Boolean gto, double *chq, Boolean *mod) {
INF   	*inf;
REGBA  	*rb;
	if (hid) {
		inf=SacarApRM(); LeerConID(id,inf,true);
		switch(inf->TReg) {
		case 1: FrmHideObject(f,FrmGetObjectIndex(f,116));
				FrmShowObject(f,FrmGetObjectIndex(f,115));
				FrmShowObject(f,FrmGetObjectIndex(f,205));
				if(tp[0] < 0 || tp[0] > 1 ) tp[0]=0;
				break;
		case 2: FrmHideObject(f,FrmGetObjectIndex(f,115));
				FrmHideObject(f,FrmGetObjectIndex(f,116));
				FrmHideObject(f,FrmGetObjectIndex(f,205));
				break;
    	case 7: *chq=0; *mod=false;
   				if (tp[0]<0 || tp[0]>2) tp[0]=0;			    
			    if (gto) {
			        rb=SacarApRM(); if (rb->TipoCDI==1 && tp[0]==0) *chq=rb->UNumCh+1;
		            FrmShowObject(f,FrmGetObjectIndex(f,116));
			    } else FrmHideObject(f,FrmGetObjectIndex(f,116));
		        FrmShowObject(f,FrmGetObjectIndex(f,115));
				FrmShowObject(f,FrmGetObjectIndex(f,205));
				break;  
		}
	}
	else {
		FrmHideObject(f,FrmGetObjectIndex(f,116));
		FrmHideObject(f,FrmGetObjectIndex(f,115));
		FrmHideObject(f,FrmGetObjectIndex(f,205));
	}
}
// ---------------------------------------------------------------------
//
// Actualizar la cuenta secundaria
//
// op   1 = Editar/Nueva  2 (otro) = Borrar el original
// inf  apuntador al movimiento principal nuevo, en borrar puede 
//      ser original o modificado. NO debe ser ApMM
// fte  De donde viene 1=TX 2=Efe 7=CHQ
// idf  id de la cuenta-movimiento principal
// idd  id original de la cuenta-movimiento secundario,
//      en caso de cambio se van a afectar las dos cuentas
// edt  true  Si viene de edición/borrar 
//      false Si es nueva (ignora idd) o bien antes NO tenia secundaria
//
//    Para usar esta funcion para editar se debe:
//    1) NO usar ApRM o ApMM, se usan en esta funcion
//    2) Al inicio de la edicion/borrar salvar ID del movimiento 
//       secundario original, si no lo hay se llama como edt=false
//    3) Insertar/modificar el movimiento principal, sacar su ID
//    4) llamar a esta funcion
//
//
//    Para usar esta funcion para borrar se debe:
//    1) NO usar ApRM o ApMM, se usan en esta funcion
//    2) Al inicio de la edicion/borrar salvar ID del movimiento 
//       secundario original, si no hay no se llama a esta funcion
//    3) llamar a esta funcion
//

// Revisar si el movimiento está para afectar el saldo al corte de TC
Boolean RvC(Int8 tp, Fecha *f, UInt8 dc) {
Fecha fc;
	ProximoPago(0,&fc,dc,3); 
	switch(tp) {
	case 1: // Saldo al corte
	        SumarMeses(-1,&fc);	return (Comp2Fec(f,&fc)!=1);
	case 2: // Saldo
			if (Futura(f)) return false;
			return (Comp2Fec(f,&fc)==-1);
	}
	return false;
}

//    Afectar la cuenta del movimiento secundario
//    tp    1=cr 2=ef 
//    cta   cuenta a modificar
//    mov   movimiento de la cuenta
//    idd   id de la cuenta-movimiento principal en tp=1 o null
void RegMov(Char tp, void *cta, void *mov, ID *idd) {
CRE 	*cre;
MOVC 	*mcre;
EFE 	*efe;
MOVEF 	*mefe;
	switch(tp) {
	case 1: cre=cta; mcre=mov;
			switch(cre->tp) {
			case 0: case 1: case 2: case 3:
			case 4: switch(mcre->tp) {
		    		case 1: if (!Futura(&(mcre->f))) {
		    					ValCrePag(2,idd,0,mcre->v);
			      				cre->sa+=mcre->v; cre->sc+=mcre->v; mcre->un.mvc.rev=1; 
							} break;
					case 2:
		    		case 3: if (RvC(2,&(mcre->f),cre->un.tc.dc)) {
								cre->sa-=mcre->v; mcre->un.mvc.rev=1;
			 					if (RvC(1,&(mcre->f),cre->un.tc.dc)) {
			   						cre->sc-=mcre->v;
			   						ProximoPago(0,&(mcre->un.mvc.fr),cre->un.tc.dc,3);
			   						mcre->un.mvc.rev=2;
			 					}
			 					else FecHoy(&(mcre->un.mvc.fr));
		    				} break;
					} break;
			} break;
    case 2: efe=cta; mefe=mov;
            mefe->rev=!(Futura(&(mefe->f)));
			if (mefe->rev) switch(mefe->tp) {
			case 3:
	        case 0: efe->sa+=mefe->v; break;
	        case 1:
	        case 2: efe->sa-=mefe->v; break;
	        } break;
    }
}
//  Llenar estructura movimiento secundario en ApMM

//  f    Fuente 1=credito 2=efectivo 7=bancos
//  d    Destino 1=credito 2=efectivo 7=bancos
//  inf  movimiento principal
//  idc  ID cuenta-movimiento principal

void CopiaValCta(Char f, Char d, void *inf, ID *idc) {
MOVEF   *mefo,*mefe;
MOVC    *mcro,*mcre;
MOVBA   *mbao;
EFE     *efe;
CRE     *cre;
ID      idd;
NumX    N0,NV;

	Pasa0aN(&N0);
	switch(d) {
	case 1: cre=SacarApRM();  mcre=SacarApMM();
            mcre->didg=true; MemMove(&(mcre->idg),idc,sizeof(ID));
	        switch(f) {
		    case 1: mcro=inf; MemMove(&idd,&(mcro->idg),sizeof(ID));
			        switch(mcro->tp) {
		              case 1: mcre->tp=3; mcre->ct=0; break;
		              case 3: mcre->tp=1; mcre->ct=0; break;
		            }
		            mcre->v=mcro->v;
		            MemMove(&(mcre->f),&(mcro->f),sizeof(Fecha));
		            SacaTexto(mcre->p,2100,92,sizeof(mcre->p)); 
		            StrCopy(mcre->ds,mefo->dsc);
		            break;
		    case 2: mefo=inf; MemMove(&idd,&(mefo->idg),sizeof(ID));
		            switch(mefo->tp) {
		              case 0: mcre->tp=3; mcre->ct=0; break;
		              case 2: mcre->tp=1; mcre->ct=0; break;
		            }
		            mcre->v=mefo->v;
		            MemMove(&(mcre->f),&(mefo->f),sizeof(Fecha));
		            SacaTexto(mcre->p,2100,83+mcre->tp,sizeof(mcre->p));
		            StrCopy(mcre->ds,mefo->dsc);
		            break;
		    case 7: mbao=inf; MemMove(&idd,&(mbao->idceb),sizeof(ID));
		            switch(mbao->drcc) {
		              case 1: mcre->tp=3; mcre->ct=0; break;
		              case 2: mcre->tp=1; mcre->ct=0; break;
		            }
		            mcre->v=PasaNaF(&mbao->v);
		            MemMove(&(mcre->f),&(mbao->fa),sizeof(Fecha));
		            SacaTexto(mcre->p,2100,83+mcre->tp,sizeof(mcre->p));
		            StrCopy(mcre->ds,mbao->d);
		            break;
	        } 
	        RegMov(1,cre,mcre,&idd);
	        break;
	case 2: efe=SacarApRM(); mefe=SacarApMM();
	        mefe->didg=true; MemMove(&(mefe->idg),idc,sizeof(ID)); 
	        switch(f) {
	        case 1: mcro=inf;
	                switch(mcro->tp) {
		                case 1: mefe->tp=2; mefe->tp1=0; break;
		                case 3: mefe->tp=0; mefe->tp1=0; break;
		            }
		            mefe->v=mcro->v;
		            MemMove(&(mefe->f),&(mcro->f),sizeof(Fecha));
		            StrCopy(mefe->dsc,mcro->ds);
		            break;
	        case 7: mbao=inf;
	                mefe->tp=0;
	                mefe->tp1=mbao->forma;
		            mefe->v=PasaNaF(&mbao->v);
		            MemMove(&(mefe->f),&(mbao->fa),sizeof(Fecha));
		            StrCopy(mefe->dsc,mbao->d);
		            break;
	        } 
	        RegMov(2,efe,mefe,NULL);
	        break;
	case 7: switch(f) {
	            case 1: mcro=inf;
	                    PasaFaN(&mcro->v,&NV);
	                    if(mcro->tp==1)FormaMovBA(1,2,&NV,&mcro->f,2,mcro->ds,idc,&N0);
  	                    if(mcro->tp==3)FormaMovBA(1,1,&NV,&mcro->f,1,mcro->ds,idc,&N0);
		                break;
	        	case 2: mefe=inf;
	        	        PasaFaN(&mefe->v,&NV);
	        	        if(mefe->tp==0) FormaMovBA(1,2,&NV,&mefe->f,mefe->tp1,mefe->dsc,idc,&N0);
   	        	        if(mefe->tp==2) FormaMovBA(1,1,&NV,&mefe->f,mefe->tp1,mefe->dsc,idc,&N0);
   	        	        break;
	        	case 7: mbao=inf; 
	        	        if(mbao->drcc==1)FormaMovBA(1,2,&mbao->v,&mbao->fa,mbao->forma,mbao->d,idc,&N0);        		        		
	                    if(mbao->drcc==2)FormaMovBA(1,1,&mbao->v,&mbao->fa,mbao->forma,mbao->d,idc,&N0);        		
	                    break;
	        }
	        break;
	}
}

void ActualizaCuenta(Char op, void *inf, Char fte, ID *idf, ID *idd, Boolean edt) {
MOVEF   *mefo,*mefe;
MOVC    *mcro,*mcre;
MOVBA   *mbao,*mba;
EFE     *efe;
CRE     *cre;
REGBA   *rb;
Boolean nva;
ID      *idn;
UInt8   dst;

//                     Ponen *idn* el nuevo ID del movimiento
	switch(fte) {
	  case 1: mcre=inf; idn=&(mcre->idg); break;
	  case 2: mefe=inf; idn=&(mefe->idg); break;
	  case 7: mba=inf;  idn=&(mba->idceb);break;
	}
    nva=true; 
//                     Caso de editar/borrar quitar el movimiento original 
	if (edt) {
//                     Sacar si cambio cuenta-movimiento secundario		
    	nva=(MemCmp(idd,idn,sizeof(ID))!=0); 
    	CGB_ID(idd,0); dst=SacarTpApRM();
//                     Procesar cada caso (credito, efectivo, banco)    	
    	switch(dst) {
    	case 1: cre=SacarApRM(); mcro=SacarApMM();
    			switch(cre->tp) {
    			case 0: case 1: case 2: case 3:
    			case 4: switch(mcro->tp) {
		    	        case 1: if (!Futura(&(mcro->f))) {
		    	        			ValCrePag(1,idd,0,mcro->v);
		    	        			cre->sa-=mcro->v; cre->sc-=mcro->v;
		    	        		}
		    	                break;
		    	        case 3: if (RvC(2,&(mcro->f),cre->un.tc.dc)) {
			 						cre->sa+=mcro->v;
									if (RvC(1,&(mcro->f),cre->un.tc.dc)) cre->sc+=mcro->v;
								} break;
    	        		} break;
    	        case 5: case 6:
    	        case 7: break;
    			} break;
    	case 2: efe=SacarApRM(); mefo=SacarApMM();
    	        switch(mefo->tp) {
    	        case 0: if (mefo->rev) efe->sa-=mefo->v; break;
    	        case 2: if (mefo->rev) efe->sa+=mefo->v; break;
    	        } break;
        case 7: rb=SacarApRM();  mbao=SacarApMM();        
                switch (mbao->drcc) {
                case 1: if(mbao->aplicado) NumSRN(&rb->sa,2,&mbao->v); else NumSRN(&rb->sp,2,&mbao->v);
                        break;
                case 2: if(mbao->aplicado) NumSRN(&rb->sa,1,&mbao->v);         
                        break;
                }
                break;   	        
    	}
//                    Actualiza cuenta secundaria y 
//                    borra movimiento secundario     	
    	if (nva || op!=1) CGB_ID(idd,2);
//                    Mismo movimiento, actualiza cuenta-movimiento    	
    	else if (!nva){
    		CopiaValCta(fte,dst,inf,idf); 
    		CGB_ID(idd,1);
    		}
	}
	
//                    Caso de nuevo movimiento secundario
	if (nva) {
		CGB_ID(idn,5); dst=SacarTpApRM();
		CopiaValCta(fte,dst,inf,idf); 
		CGB_ID(idn,3); SacarID(idn);
    	GuardarConID(idf,inf); 
	}
}
// ---------------------------------------------------------------------
// 								    TEXTOS
//  Cargar textos de recusrsos
// ---------------------------------------------------------------------
void SacaTexto(Char *s, UInt16 id, UInt16 i, UInt8 l) {
	SysStringByIndex(id, i, s, l);
}
// ---------------------------------------------------------------------
// 								    SLIDER
//  Mandar llamar slIni y luego agregar slCnt en cliclo de llamada
// ---------------------------------------------------------------------
Boolean slPinta(Dsl *sl, Int16 v, Int8 *col) {
Char  st[50];
Int16 cl;
	PintaB(255,sl->x3+sl->p,sl->y3-2,sl->h3+2,sl->h3+6,9,0,0,0,false,col);
	cl=WinSetForeColor(col[2]); WinDrawLine(sl->x3+sl->p,sl->y3,sl->x3+sl->p+sl->h3+1,sl->y3);
	              if (sl->p==0) WinDrawLine(sl->x3,sl->y3,sl->x3,sl->y3+sl->h3);
	WinSetForeColor(col[1]); WinDrawLine(sl->x3+sl->p,sl->y3+sl->h3,sl->x3+sl->p+sl->h3+1,sl->y3+sl->h3);
    if (sl->p>=sl->w3-sl->h3-2) WinDrawLine(sl->x3+sl->w3,sl->y3,sl->x3+sl->w3,sl->y3+sl->h3);
	     if (sl->v+v<sl->mi) sl->v=sl->mi;
	else if (sl->v+v>sl->ma) sl->v=sl->ma;
	else                     sl->v+=v;
    sl->p=(Int16)((double)((sl->v-sl->mi)/sl->i));
	PintaB(255,sl->x3+sl->p,sl->y3-2,sl->h3+1,sl->h3+5,9,2,0,1,true,col);
	StrIToA(st,sl->v); Texto(st,sl->f,true);
	WinSetForeColor(cl);
	return true;
}
void slIni(Dsl *sl, FieldType *f,
                    Int16 mi, Int16 ma, Int16 v,
                    Int16 x1, Int16 y1, Int16 x2, Int16 y2, Int16 w1, Int16 h1,
                    Int16 x3, Int16 y3, Int16 w3, Int16 h3, Int8 *col) {
Int16 df,w, xi,xf,yi,yf,hi,cl;
    sl->mi=mi; sl->ma=ma; sl->v=v; sl->d4=-1;
    sl->x1=x1; sl->y1=y1; sl->x2=x2; sl->y2=y2; sl->w1=w1; sl->h1=h1;
    sl->x3=x3; sl->y3=y3; sl->w3=w3; sl->h3=h3; sl->f=f;
    df=ma-mi; if (df<0) df*=-1; w=w3-(h3+1);
    sl->i=(double)((double)df/(double)w);
    sl->p=(Int16)((double)((sl->v-sl->mi)/sl->i));
	PintaB(255,sl->x3,sl->y3,sl->w3,sl->h3,9,2,1,9,true,col);
	slPinta(sl,0,col); cl=WinSetForeColor(col[0]);
	xi=sl->x1; xf=sl->x2+w1; yi=sl->y1+(sl->h1/2)-1; yf=sl->y2+(sl->h1/2)-1; hi=1;
	do { WinDrawLine(xi,yi,xi,yi+hi); WinDrawLine(xf,yf,xf,yf+hi); 
		 xi++; xf--;
		 if (hi>=sl->h1) 
		 { WinDrawLine(xi,yi,xi,yi+hi); WinDrawLine(xf,yf,xf,yf+hi); break; }
  		 yi--; yf--; hi+=2;
    } while (1==1);
    WinSetForeColor(cl);
}
Boolean slCnt(Dsl *sl, char tp, Int16 x, Int16 y, Int8 *col) {
	if (tp==1) {
		if (sl->d4!=-1) return false;
		if (x>=sl->x3+sl->p && x<=sl->x3+sl->p+sl->h3+1 &&
		    y>=sl->y3-2 && y<=sl->y3+3+sl->h3) 
		{ sl->d4=x-sl->x3-sl->p; return true; }
		return false;
	}
	if (tp==2) {
	  if (sl->d4!=-1) { sl->d4=-1; return true; }
	  if (x>=sl->x1 && x<=sl->x1+sl->w1 && y>=sl->y1 && y<=sl->y1+sl->h1) 
	  	  return slPinta(sl,-1,col);
	  if (x>=sl->x2 && x<=sl->x2+sl->w1 && y>=sl->y2 && y<=sl->y2+sl->h1) 
	  	  return slPinta(sl,1,col);
	  if (y>=sl->y3-2 && y<=sl->y3+3+sl->h3 && x>=sl->x3 && x<=sl->x3+sl->w3) {
	  	 if (x<sl->x3+sl->p) return slPinta(sl,-10,col);
	  	 if (x>sl->x3+sl->p+sl->h3+1) return slPinta(sl,10,col);
	  	 return false;
	  }
	  return false;
	}
	if (tp==3 && sl->d4!=-1) {
		x-=sl->d4; x-=sl->x3;
		if (x>=0 && x<=sl->w3-sl->h3-1) {
			y=sl->mi+(Int16)((double)((double)x*sl->i));
			return slPinta(sl,y-sl->v,col);
		}
		else return false;
	}
	return false;
}
void slCamp(Dsl *sl, Int8 *col) {
Char  st[100];
Int16 v;
	Texto(st,sl->f,false); 
    v=StrAToI(st); slPinta(sl,v-sl->v,col);
}
// ---------------------------------------------------------------------
// 								    Selección de períodos
// ---------------------------------------------------------------------
// Poner un campo como período (enmarcado punteada)
CPer *ape;
// Inicar periodo
void IniPer(Char tp, Periodo *p) {
	FecHoy(&(p->f));
	p->op=0; 	 	 
	p->tp=2;
	p->v1=p->f.d;
	p->v2=p->f.m;
	p->v3=1; 		 
	p->v4=2; 		 
	p->v=0;
	p->tpv=tp;
	p->da=0;
}
void TextoPeriodo(Char *r, CPer *p) {
Char st[150],s[150];
	switch(p->p->tp) {
	case  0: 
	case  1: SacaTexto(st,1000,35+p->p->tp,sizeof(st)); StrCat(st," ("); 
	         SacaTexto(s,1000,52+p->p->v1,sizeof(s)); StrCat(st,s); StrCat(st,")");
	         break;
	default: if (p->p->tp==7) {
				StrIToA(st,p->p->v3);
				SacaTexto(s,1000,(p->p->v3<2)?43:60,sizeof(s)); 
				StrCat(st," "); StrCat(st,s);
	         } else SacaTexto(st,1000,35+p->p->tp,sizeof(st)); 
	         StrCat(st," ("); SacaTexto(s,1000,59,sizeof(s)); StrCat(st,s);
	         StrCat(st," "); StrIToA(s,p->p->v1); StrCat(st,s); StrCat(st,")");
	         break;
	}
	StrCopy(r,st);
}
// Poner campo tipo periodo
void PonPerCamp(CPer *p, Boolean borrar) {
Char 		   st[120];
RectangleType  r;
Int8           w;
	if (borrar==true) { 
		r.topLeft.x=p->r.topLeft.x-2; r.topLeft.y=p->r.topLeft.y-2;
		r.extent.x=p->r.extent.x+2;   r.extent.y=p->r.extent.y+2;
		WinEraseRectangle(&r,0); p->act=false;
		return; 
	} else p->act=true;
	TextoPeriodo(st,p);
	p->r.extent.y=PonTexto(st,p->r.topLeft.x,p->r.topLeft.y,N,I,0,true,-1,-1,&w);
	p->r.extent.x=w;
}
// Determinar si se está sobre el campo periodo
Boolean EnPeriodo(Int16 x, Int16 y, CPer *p) {
	if (p->act==false) return false;
	return (x>=p->r.topLeft.x && x<=p->r.topLeft.x+p->r.extent.x &&
	        y>=p->r.topLeft.y && y<=p->r.topLeft.y+p->r.extent.y);
}

void ListaAnio(Int16 it, RectangleType *r,char **u, ListType *p) {
Int8  a;
Char  s[50];
Fecha h;
	FecHoy(&h); StrIToA(s,FormaA(h.a1,h.a2)+(it-2));
    PonTexto(s,r->topLeft.x,r->topLeft.y,N,I,0,false,-1,-1,&a);
}

// Seleccionar un periodo
void IniPerQ(FormType *f, Char op, Boolean ini) {
Char  s[50];
CRE   *c;
	if (ini) {
		if (ape->tp==2) { 
			c=(CRE*)(ape->inf); 
			ape->p->v1=ape->p->f.d;
			ape->p->v2=ape->p->f.m;
		}
	}
	if (ape->tp==2) {
		c=(CRE*)ape->inf;
		StrIToA(s,(Int32)(ape->p->v1));
		Texto(s,GetObjPtr(f,300),true);
	}
	if (ape->tp==1) {
		if (op==1) {
	    	SacaTexto(ape->str[1],1000,61+ape->p->v4,sizeof(ape->str[1]));
	   		CtlSetLabel(GetObjPtr(f,125),ape->str[1]);
	   		return;
		}
		if (op==2) {
		   SacaTexto(ape->str[1],1000,65+ape->p->v3,sizeof(ape->str[1]));
	   	   CtlSetLabel(GetObjPtr(f,127),ape->str[1]);
		}
	    if (ape->p->da<0 || ape->p->da>15) ape->p->da=0;
	    Lista(GetObjPtr(f,118),GetObjPtr(f,119),ape->p->da,true,0,NULL);
	   	if (ape->p->v4<0 || ape->p->v4>3) ape->p->v4=2;
	   	SacaTexto(s,1000,61+ape->p->v4,sizeof(s));
		CtlSetLabel(GetObjPtr(f,125),s);
	}
	switch(ape->p->tp) {
	case  0: 
	case  1: FrmHideObject(f,FrmGetObjectIndex(f,110));
	         FrmHideObject(f,FrmGetObjectIndex(f,111));
	         FrmHideObject(f,FrmGetObjectIndex(f,201));
	         FrmHideObject(f,FrmGetObjectIndex(f,114));
	         FrmHideObject(f,FrmGetObjectIndex(f,115));
	         FrmHideObject(f,FrmGetObjectIndex(f,202));
	         FrmHideObject(f,FrmGetObjectIndex(f,203));
	         FrmHideObject(f,FrmGetObjectIndex(f,116));
	         FrmHideObject(f,FrmGetObjectIndex(f,117));
	         FrmHideObject(f,FrmGetObjectIndex(f,120));
	         FrmShowObject(f,FrmGetObjectIndex(f,112));
	         if (ape->p->v1<0 || ape->p->v1>7) ape->p->v1=0;
             Lista(GetObjPtr(f,112),GetObjPtr(f,113),ape->p->v1,true,0,NULL);
	         FrmShowObject(f,FrmGetObjectIndex(f,127));
	         if (ape->p->tp==0) if (ape->p->v3<0 || ape->p->v3>1) ape->p->v3=0;
	         if (ape->p->tp==1) if (ape->p->v3<0 || ape->p->v3>3) ape->p->v3=0;
	   		 SacaTexto(ape->str[1],1000,65+ape->p->v3,sizeof(ape->str[1])); 
	   		 CtlSetLabel(GetObjPtr(f,127),ape->str[1]);
	         break;
	default: if (ape->tp==1) {
	         	FrmHideObject(f,FrmGetObjectIndex(f,127));
	         	FrmHideObject(f,FrmGetObjectIndex(f,112));
			 }
	         if (ape->p->tp!=7) {
		         FrmHideObject(f,FrmGetObjectIndex(f,202));
		         FrmHideObject(f,FrmGetObjectIndex(f,203));
		         FrmHideObject(f,FrmGetObjectIndex(f,116));
		         FrmHideObject(f,FrmGetObjectIndex(f,117));
	         }
	         else {
		         FrmShowObject(f,FrmGetObjectIndex(f,202));
		         FrmShowObject(f,FrmGetObjectIndex(f,203));
		         FrmShowObject(f,FrmGetObjectIndex(f,116));
		         FrmShowObject(f,FrmGetObjectIndex(f,117));
	         	 if (ape->p->v3<1 || ape->p->v3>99) ape->p->v3=1;
             	 Lista(GetObjPtr(f,116),GetObjPtr(f,117),ape->p->v3-1,true,0,NULL);
	         }
	         if (ape->tp==1) {
	         	FrmShowObject(f,FrmGetObjectIndex(f,110));
	         	FrmShowObject(f,FrmGetObjectIndex(f,111));
	         	if (ape->p->v1<1 || ape->p->v1>31) ape->p->v1=1;
             	Lista(GetObjPtr(f,110),GetObjPtr(f,111),ape->p->v1-1,true,0,NULL);
             	FrmShowObject(f,FrmGetObjectIndex(f,125));
	         }
	         FrmShowObject(f,FrmGetObjectIndex(f,120));
	         FrmShowObject(f,FrmGetObjectIndex(f,201));
	         FrmShowObject(f,FrmGetObjectIndex(f,114));
	         FrmShowObject(f,FrmGetObjectIndex(f,115));
	         if (ape->p->v2<1 || ape->p->v2>12) ape->p->v2=1;
             Lista(GetObjPtr(f,114),GetObjPtr(f,115),ape->p->v2-1,true,45,ape->str[0]);
             StrIToA(ape->str[2],FormaA(ape->p->f.a1,ape->p->f.a2)); 
             CtlSetLabel(GetObjPtr(f,120),ape->str[2]);
    		 if (ini) {
    		 	LstSetDrawFunction(GetObjPtr(f,121),(ListDrawDataFuncPtr)ListaAnio);
    		 	LstSetListChoices(GetObjPtr(f,121),NULL,5);
    		 }
	         break;
	}
	if (ape->tp==1) {
		CtlSetValue(GetObjPtr(f,100),((ape->p->tp==0)?1:0));
		CtlSetValue(GetObjPtr(f,101),((ape->p->tp==1)?1:0));
	}
	CtlSetValue(GetObjPtr(f,102),((ape->p->tp==2)?1:0));
	CtlSetValue(GetObjPtr(f,103),((ape->p->tp==3)?1:0));
	CtlSetValue(GetObjPtr(f,104),((ape->p->tp==4)?1:0));
	CtlSetValue(GetObjPtr(f,105),((ape->p->tp==5)?1:0));
	CtlSetValue(GetObjPtr(f,106),((ape->p->tp==6)?1:0));
	CtlSetValue(GetObjPtr(f,107),((ape->p->tp==7)?1:0));
}
void SelecPeriodo(CPer *p, Boolean revc) { 
	ape=p; 
	if (p->tp==2 && revc) FrmPopupForm(FPeriodoC);
	else { p->tp=1; FrmPopupForm(FPeriodo); }
}
Boolean RPeriodo(EventType* pEvent) {
Int16 v;
Fecha h;
	switch (pEvent->eType) {
		case frmUpdateEvent:
		switch(pEvent->data.frmUpdate.updateCode) {
			case 90: ape->ayu=false; return true;
		}
		break;
		case frmOpenEvent:
			FrmDrawForm(FrmGetActiveForm());
			IniPerQ(FrmGetActiveForm(),0,true);
			return true;
		case ctlSelectEvent:
		    switch(pEvent->data.ctlSelect.controlID) {
   	    	case BAyu: *(ape->ayu)=Ayuda(100,1,ape->col,FPeriodo); return true;
		   	case BAce: 
		   	case BCan: FrmUpdateForm(ape->f,98); FrmReturnToForm(0); return true;
		   	case  100: if (ape->p->tp!=0) ape->p->tp=0; IniPerQ(FrmGetActiveForm(),0,false); break;
		   	case  101: if (ape->p->tp!=1) ape->p->tp=1; IniPerQ(FrmGetActiveForm(),0,false); break;
		   	case  102: if (ape->p->tp!=2) ape->p->tp=2; IniPerQ(FrmGetActiveForm(),0,false); break;
		   	case  103: if (ape->p->tp!=3) ape->p->tp=3; IniPerQ(FrmGetActiveForm(),0,false); break;
		   	case  104: if (ape->p->tp!=4) ape->p->tp=4; IniPerQ(FrmGetActiveForm(),0,false); break;
		   	case  105: if (ape->p->tp!=5) ape->p->tp=5; IniPerQ(FrmGetActiveForm(),0,false); break;
		   	case  106: if (ape->p->tp!=6) ape->p->tp=6; IniPerQ(FrmGetActiveForm(),0,false); break;
		   	case  107: if (ape->p->tp!=7) ape->p->tp=7; IniPerQ(FrmGetActiveForm(),0,false); break;
		    }
		    return true;
        case ctlEnterEvent:
            switch(pEvent->data.ctlEnter.controlID) {
       		case 110: ape->p->v1=1+Lista(GetObjPtr(FrmGetActiveForm(),110),GetObjPtr(FrmGetActiveForm(),111),0,false,0,NULL); break;
       		case 112: ape->p->v1=Lista(GetObjPtr(FrmGetActiveForm(),112),GetObjPtr(FrmGetActiveForm(),113),0,false,0,NULL); break;
       		case 114: ape->p->v2=1+Lista(GetObjPtr(FrmGetActiveForm(),114),GetObjPtr(FrmGetActiveForm(),115),0,false,0,NULL); break;
       		case 116: ape->p->v3=1+Lista(GetObjPtr(FrmGetActiveForm(),116),GetObjPtr(FrmGetActiveForm(),117),0,false,0,NULL); break;
       		case 118: ape->p->da=Lista(GetObjPtr(FrmGetActiveForm(),118),GetObjPtr(FrmGetActiveForm(),119),0,false,0,NULL); break;
       		case 120: v=LstPopupList(GetObjPtr(FrmGetActiveForm(),121));
   	   				  if (v==-1) return true;
					  FecHoy(&h); 
					  ape->p->f.a1=(FormaA(h.a1,h.a2)+(v-2))/100;
					  ape->p->f.a2=(FormaA(h.a1,h.a2)+(v-2))%100;
   	   				  IniPerQ(FrmGetActiveForm(),1,false);
       				  return true;
       		case 125: v=LstPopupList(GetObjPtr(FrmGetActiveForm(),126));
   	   				  if (v==-1) return true;
   	   				  ape->p->v4=(Int8)v;
   	   				  IniPerQ(FrmGetActiveForm(),1,false);
       				  return true;
       		case 127: v=LstPopupList(GetObjPtr(FrmGetActiveForm(),((ape->p->tp==0)?128:129)));
   	   				  if (v==-1) return true;
   	   				  ape->p->v3=(Int8)v;
   	   				  IniPerQ(FrmGetActiveForm(),2,false);
       				  return true;
        	}
        	return false;
		default: break;
	}
	return false;
}
// Calcular proxima fecha de pago
// op-> 1=IniciarFecha(Hoy)  2=RestarFestivos 3=CalculaSiguiente 
//      4=CalculaSiguienteRestaFestivos  5=IniciarFecha(Dada)
//      6=RegresarAnterior
void ProxFPPer(Fecha *f, Periodo *p, Char op) {
UInt8  ds,dd;
Int16  dx;
	switch(op) {
	case 1: FecHoy(f);
	case 5:	switch (p->tp) {
				case  0:
	   			case  1: SacarTFec(&ds,&dd,f);
	   	         		 switch(p->v3) {
	   	 		    	 case 2:
	   	            	 case 0: dx=-1*((ds>=p->v1)?ds-p->v1:7-p->v1-ds); 
	   	                    	 if (p->v3==2) dx-=7; break;
	   	            	 case 3:
	   	            	 case 1: dx=((ds<=p->v1)?p->v1-ds:7-ds-p->v1);
	   	                    	 if (p->v3==3) dx+=7; break;
	   	   		 		 }
	   	         		 SumarDias(dx,f);
	   	         		 break;
	   			default: f->d=p->v1; f->m=p->v2; break;
	   		} break;
	case 3:
	case 4: switch (p->tp) {
				case 0: SumarDias(7,f); break;
				case 1: SumarDias(14,f); break;
				case 2: SumarMeses(1,f); break;
				case 3: SumarMeses(2,f); break;
				case 4: SumarMeses(3,f); break;
				case 5: SumarMeses(6,f); break;
				case 6: SumarAxo(1,f); break;
				case 7: SumarMeses(p->v3,f); break;
			}
			if (op==3) break;
	case 2: PasarFDL(p->v4,(Int16)p->da,f); break;
	case 6: switch (p->tp) {
				case 0: SumarDias(-7,f); break;
				case 1: SumarDias(-14,f); break;
				case 2: SumarMeses(-1,f); break;
				case 3: SumarMeses(-2,f); break;
				case 4: SumarMeses(-3,f); break;
				case 5: SumarMeses(-6,f); break;
				case 6: SumarAxo(-1,f); break;
				case 7: SumarMeses(-(p->v3),f); break;
			} break;
	}
}
// Determinar cuantos periodos vencidos tiene una fecha dada y dejar 
// opcionalmente(si s!=NULL) el string adecuado
Int8 PerVenc(Fecha *o, Periodo *p, Char *s) {
Fecha f,g;
Int8  r;
Int16 v;
Char t[150];
	r=0; 
	MemMove(&f,&(p->f),sizeof(Fecha)); 
	do { ProxFPPer(&f,p,6);
		 MemMove(&g,&f,sizeof(Fecha)); ProxFPPer(&g,p,2);
	     if (Comp2Fec(&g,o)!=1) break; r++; 
	} while(1==1);
	if (s!=NULL) {
		if (r==0) SacaTexto(s,2100,101,150);
		else {
			if (p->tp==7) { v=(p->v3*r); SacaTexto(t,1000,75,150); }
			else { v=r; SacaTexto(t,1000,73+p->tp,150); }
			StrIToA(s,v); StrCat(s," "); StrCat(s,t);
		}
	}
	return r;
}
// ---------------------------------------------------------------------
// 								    SISTEMA
// ---------------------------------------------------------------------
// Obtener preferencia 1=ColorGeneral 2=FFecha 3=FNum
Char PrefGen(Char op) {
UInt32 rg;
	switch(op) {
	case 1: // 1, 2, 4, 8, 16
	        FtrGet(sysFtrCreator, sysFtrNumDisplayDepth, &rg); 
    		return((Char)rg);
    case 2: // dma=1 mda=2 amd=3
	case 3: // Separador
			switch((DateFormatType)PrefGetPreference(prefDateFormat)) {
			case dfMDYWithSlashes	: return(((op==2)?2:'/'));
		    case dfDMYWithSlashes	: return(((op==2)?1:'/'));
		    case dfDMYWithDots		: return(((op==2)?1:'.'));
		    case dfDMYWithDashes	: return(((op==2)?1:'-'));
		    case dfYMDWithSlashes	: return(((op==2)?3:'/'));
		    case dfYMDWithDots		: return(((op==2)?3:'.'));
		    case dfYMDWithDashes	: return(((op==2)?3:'-'));
		    case dfMDYLongWithComma	: return(((op==2)?2:','));
		    case dfDMYLong			: return(((op==2)?1:'.'));
		    case dfDMYLongWithDot	: return(((op==2)?1:'.'));
		    case dfDMYLongNoDay		: return(((op==2)?1:' '));
		    case dfDMYLongWithComma	: return(((op==2)?1:','));
		    case dfYMDLongWithDot	: return(((op==2)?3:'.'));
		    case dfYMDLongWithSpace	: return(((op==2)?3:' '));
		    case dfMYMed			: return(((op==2)?1:' '));
		    case dfMYMedNoPost		: return(((op==2)?1:' '));
		    case dfMDYWithDashes	: return(((op==2)?2:'-'));
			} break;
	case 4: // Miles
	case 5: // Decimal
			switch((NumberFormatType)PrefGetPreference(prefNumberFormat)) {
			case nfCommaPeriod		: return(((op==4)?',':'.'));
			case nfPeriodComma		: return(((op==4)?'.':','));
			case nfSpaceComma		: return(((op==4)?' ':','));
			case nfApostrophePeriod	: return(((op==4)?'\'':'.'));
			case nfApostropheComma	: return(((op==4)?'\'':','));
			} break;
	}
	return 0;
}
// ---------------------------------------------------------------------
// 						LISTAS, CAMPOS, ETC
// ---------------------------------------------------------------------
// Poner / sacar texto de un campo
void Texto(Char *d, FieldType *ft, Boolean poner) {
UInt16    m;
Char      *f;
MemHandle mh;
    if (poner) {
     	m=FldGetTextLength(ft); if (m!=0) FldDelete(ft,0,m);
     	m=StrLen(d); if (m>0 && !(m==1 && d[0]==' ')) FldInsert(ft,d,m);
    }
    else {
        m=FldGetTextLength(ft);
        if (m>0) {	
			mh=FldGetTextHandle(ft); f=(Char *)MemHandleLock(mh);
			StrNCopy(d,f,m); d[m]=0; MemHandleUnlock(mh);
        } else d[0]=0;
    }
}
// Obtener el apuntador de un objeto
void *GetObjPtr(FormType *pForm, UInt16 uwObjectID) {
UInt16 uwObjIndex;
	if (pForm == NULL) return NULL;
	uwObjIndex = FrmGetObjectIndex(pForm, uwObjectID);
	return FrmGetObjectPtr(pForm, uwObjIndex);
}
// Determinar si el 'c' de la lista NO está seleccionado
Boolean SelecLst(Int16 c) {
Int16 ic,sc;
	ic=WinSetForeColor(c); WinSetForeColor(ic);
	sc=UIColorGetTableEntryIndex(UIObjectSelectedForeground); 
	return (!(ic==sc));
}
// Eliminar el marco de una lista
void EliminaMarco(FormType *f, UInt16 id, ListDrawDataFuncPtr fn, UInt16 m, 
                  Boolean ini, Int16 s) {
RectangleType 	c,n; 
ListType 	  	*l;
RGBColorType 	rf,rl;
	UIColorGetTableEntryRGB(UIFormFill,&rf);
	UIColorGetTableEntryRGB(UIObjectFill,&rl);
	UIColorSetTableEntry(UIObjectFill,&rf);
    l=GetObjPtr(f,id); FrmHideObject(f,FrmGetObjectIndex(f,id)); 
    if (ini) LstSetDrawFunction(l,(ListDrawDataFuncPtr)fn);
  	LstSetListChoices(l,NULL,m);
   	WinGetClip(&c); FrmGetObjectBounds(f,FrmGetObjectIndex(f,id),&n); 
   	WinSetClip(&n); LstSetSelection(l,((s==-1)?noListSelection:s)); 
    FrmShowObject(f,FrmGetObjectIndex(f,id)); WinSetClip(&c); 
	UIColorSetTableEntry(UIObjectFill,&rl);
} 
// Poner / sacar valor de una lista
Int16 Lista(ControlType *c, ListType *l, Int16 n, Boolean poner,Int16 m, Char *t) {
Char  *s;
Int16 v;
    if (poner) {
	   	LstSetSelection(l,n); LstSetTopItem(l,n); 
	   	s=LstGetSelectionText(l,n);	
	   	if (m>0) { AjustaSTR(t,s,m); CtlSetLabel(c,t); }
	   	else CtlSetLabel(c,s);
    }
    else {
   	   v=LstPopupList(l);
   	   if (v!=-1) { 
   	   	n=v; s=LstGetSelectionText(l,n); 
   	   	if (m>0) { AjustaSTR(t,s,m); CtlSetLabel(c,t); }
   	   	else CtlSetLabel(c,s); 
   	   }
    }
    return n;
}
// ---------------------------------------------------------------------
// 								  PINTAR
// ---------------------------------------------------------------------
// Iniciar los colores a usar
void IniciaColores(UInt8 *cgp) {
RGBColorType r;
    switch(PrefGen(1)) {
	case  1: r.r=r.g=r.b=0;   cgp[ 0]=WinRGBToIndex(&r);
 			 r.r=r.g=r.b=0;   cgp[ 1]=WinRGBToIndex(&r);
 			 r.r=r.g=r.b=255; cgp[ 2]=WinRGBToIndex(&r);
 			 r.r=r.g=r.b=0;   cgp[ 3]=WinRGBToIndex(&r);
 			 r.r=r.g=r.b=255; cgp[ 4]=WinRGBToIndex(&r);
 			 r.r=r.g=r.b=0;   cgp[ 5]=WinRGBToIndex(&r);
 			 r.r=r.g=r.b=255; cgp[ 6]=WinRGBToIndex(&r);
 			 r.r=r.g=r.b=0;   cgp[ 7]=WinRGBToIndex(&r);
 			 r.r=r.g=r.b=255; cgp[ 8]=WinRGBToIndex(&r);
 			 r.r=r.g=r.b=0;   cgp[ 9]=WinRGBToIndex(&r);
 			 r.r=r.g=r.b=0;   cgp[10]=WinRGBToIndex(&r);
 			 break;
	case  2: r.r=r.g=r.b=  0; cgp[ 0]=WinRGBToIndex(&r);
 			 r.r=r.g=r.b=  0; cgp[ 3]=WinRGBToIndex(&r);
 			 r.r=r.g=r.b=192; cgp[ 4]=WinRGBToIndex(&r);
 			 r.r=r.g=r.b=128; cgp[ 5]=WinRGBToIndex(&r);
 			 r.r=r.g=r.b=255; cgp[ 9]=WinRGBToIndex(&r);
 			 r.r=r.g=r.b=128; cgp[10]=WinRGBToIndex(&r);
 			 break;
   	default: r.r=r.g=r.b=0; 	 			cgp[ 0]=WinRGBToIndex(&r);  
	    	 r.r=r.g=r.b=128; 	 			cgp[ 1]=WinRGBToIndex(&r);  
	    	 r.r=r.g=r.b=255; 	 			cgp[ 2]=WinRGBToIndex(&r);  
	    	 r.r=r.g=0; r.b=128; 			cgp[ 3]=WinRGBToIndex(&r);
	    	 r.r=132; r.g=132; r.b=189; 	cgp[ 4]=WinRGBToIndex(&r);
	    	 r.r=150; r.g=r.b=0;        	cgp[ 5]=WinRGBToIndex(&r);  
	    	 r.r=255; r.g=255; r.b=202; 	cgp[ 6]=WinRGBToIndex(&r);
	    	 r.r=157; r.g=255; r.b=206; 	cgp[ 7]=WinRGBToIndex(&r);
	    	 r.r=183; r.g=219; r.b=255; 	cgp[ 8]=WinRGBToIndex(&r);
	    	 r.r=192;   r.g=192; r.b=192; 	cgp[ 9]=WinRGBToIndex(&r);  
 			 r.r=r.g=0; r.b=128; 		  	cgp[10]=WinRGBToIndex(&r);
	    	 break;
    }
}
// Pintar texto en x,y   tp->n=normal b=bold  
//			             tc->i=izq c=cent d=der
//					     si wm>0 truncar
//						 si mc poner marco alrededor
//                       cl,cf color de letas y de fondo (-1 no poner)
//                       w regresa longitud 
Int16 PonTexto(Char *t, Int16 x, Int16 y, Char tp, Char tc, 
               Int16 wm, Boolean mc, Int8 cl, Int8 cf, Int8 *w) {
Int16 		  ccl,ccf,i,wt,hf;
RectangleType r;
RGBColorType  ct;
    switch(tp) {
    	case 'n': FntSetFont(stdFont); break;
    	case 'b': FntSetFont(boldFont); break;
    	case 'l': FntSetFont(largeFont); break;
    	case 'L': FntSetFont(largeBoldFont); break;
    }
	for (i=0,wt=0;i<StrLen(t);i++) wt+=(UInt16)FntCharWidth(t[i]);
	if (wm!=0 && wt>wm) wt=wm;
	switch(tc) {
		case 'c': x-=(wt/2); break;
		case 'd': x-=wt; break;
		case 'i': break;
	}
	if (cl!=-1) ccl=WinSetTextColor(cl); 
	if (cf!=-1) ccf=WinSetBackColor(cf);
	hf=FntCharHeight(); 
	if (mc) {
		r.topLeft.x=x-1; r.topLeft.y=y-1; r.extent.x=wt+2; r.extent.y=hf+2;
		wt+=2; hf+=2; 
		if (cf==-1) {
			UIColorGetTableEntryRGB(UIObjectFill,&ct);
			ccf=WinSetBackColor(WinRGBToIndex(&ct));
		}
		WinEraseRectangle(&r,0);
		WinDrawGrayRectangleFrame(simpleFrame,&r);
	}
	if (wm==0) WinDrawChars(t,StrLen(t),x,y); else WinDrawTruncChars(t,StrLen(t),x,y,wm); 
	if (cl!=-1) WinSetTextColor(ccl); 
	if (cf!=-1) WinSetBackColor(ccf);
	if (tp!='n') FntSetFont(stdFont); 
	*w=wt;	return hf;
}
// Cargar y pintar una imagen
void PintaImagen(Int16 resID, Int16 x, Int16 y) {
MemHandle	resH;
BitmapPtr	resP;
	resH = DmGetResource(bitmapRsc, resID);
	resP = MemHandleLock(resH);
	WinDrawBitmap (resP, x, y);
	MemPtrUnlock(resP);
	DmReleaseResource(resH);
}
// Pintar un botón en x,y de w,h 
//                    cf,c1,c2,c3 colores fondo marco sup, inf, int
// 					  pl si se desean las líneas, sino solo rectángulo
//					  cg apuntador a colores
void PintaB(UInt16 n, UInt16 x, UInt16 y, UInt16 w, UInt16 h, 
             UInt8 cf, UInt8 c1, UInt8 c2, UInt8 c3, Boolean pl,
             UInt8 *cg) {
RectangleType  rc;
Int16          bc,fc;
	rc.topLeft.x=x; rc.topLeft.y=y; rc.extent.x=w; rc.extent.y=h;
	bc=WinSetBackColor(cg[cf]); WinEraseRectangle(&rc,0);
	if (pl) {
		fc=WinSetForeColor(cg[c1]); 
	           WinDrawLine(x,   y,   x+w, y); 
	           WinDrawLine(x,   y,   x,   y+h-1); 
		WinSetForeColor(cg[c2]); 
	           WinDrawLine(x,   y+h, x+w, y+h); 
	           WinDrawLine(x+w, y+h, x+w, y);
		WinSetForeColor(cg[c3]); 
	           WinDrawLine(x+1,   y+h-1, x+w-1, y+h-1); 
	           WinDrawLine(x+w-1, y+h-1, x+w-1, y+1);
	    WinSetForeColor(fc);
	}
	WinSetBackColor(bc);
}
// ---------------------------------------------------------------------
// 								CONVERSIONES
// ---------------------------------------------------------------------
// Ponerle comas al string numérico
void PonComas(Char *s, Char *st) {
Int16  i,j,k,l,ls,dc,sp;	
Char   pt,cm;
	pt=PrefGen(5); cm=PrefGen(4); ls=StrLen(s); dc=0; 
	if (ls<=1) { s[1]='0'; s[2]=0; } 
	for (l=0;l<ls;l++) if (s[l]==pt) { dc=ls-l-1; break; }
	sp=(ls-dc-((s[l]==pt)?1:0)-2)/3; k=((s[l]!=pt)?0:-1);
	j=ls+sp-1; i=ls; st[j+1]=0;
	do { i--; st[j--]=s[i];
		 if (k==-1) { if (s[i]==pt) k=0; } else k++;
		 if (k==3) { if (sp>0) { st[j--]=cm; sp--; } k=0; }
	} while(i>0);
}
// Regresar el valor numérico de un char
UInt8 Cint(Char c) {
	switch(c) {
	    case '0': return(0);   case '1': return(1);
	    case '2': return(2);   case '3': return(3);
	    case '4': return(4);   case '5': return(5);
	    case '6': return(6);   case '7': return(7);
	    case '8': return(8);   case '9': return(9);
     }
     return 0;
}
// regresar el char de un numérico
Char Cstr(UInt8 e) {
	switch(e) {
	    case 0: return('0');   case 1: return('1');
	    case 2: return('2');   case 3: return('3');
	    case 4: return('4');   case 5: return('5');
	    case 6: return('6');   case 7: return('7');
	    case 8: return('8');   case 9: return('9');
     }
     return ' ';
}
// double -> string
void Astr(double v, Char *st, UInt8 *ps) {
UInt32  x,d,r;
    (*ps)=0; if (v<0) { st[(*ps)++]='-'; v*=(double)-1; } else st[(*ps)++]=' ';
	x=(UInt32)(double)(v*100); d=1; while(d<=x) d*=10; d/=10;
	if (d==0) { StrCopy(st,"0.00"); st[1]=PrefGen(5); }
	else
	do { if (d==10) st[(*ps)++]=PrefGen(5);
		 r=(x/d); st[(*ps)++]=Cstr((Int8)r); r*=d; x-=r; d/=10; 
	} while (d>0);
    st[(*ps)]=0;
}
// Igual, pero elimina el signo(si se pide), y pone comas(si se pide)
void AstrX(double v, Char *s, Boolean coma, Boolean signo) {
UInt8 p,i;
    StrCopy(s,"0.00"); s[1]=PrefGen(5);
    if (v==0) return;
    Astr(v,s,&p); if (coma) PonComas(s,s);
 	if (!signo) { for (i=1;i<=StrLen(s);i++) s[i-1]=s[i]; }
}
// string -> double
double Adbl(Char *st) {
Int16   i,ls,dc,l;
double  v,d;
Char    pt;
    pt=PrefGen(5);
	ls=StrLen(st); dc=0;
	for (i=0;i<ls;i++) if (st[i]==pt) { dc=ls-i-1; break; }
	l=ls-dc-((st[i]==pt)?1:0)-2;
	d=(double)1; while(l>0) { d*=(double)10; l--; }
	v=0; i=1; while (i<ls) {
		if (st[i]==pt) i++;
		v+=(double)((double)Cint(st[i])*d); d/=(double)10; i++;
	}
	if (st[0]!=' ') v*=(double)-1;
	return v;
}
// Igual pero agrega el espacio del signo
double AdblX(Char *s) {
double v=0;
Int16  i,l;
	 if (s!=NULL) {
	 	l=StrLen(s); 
	 	if (l>0) { 
	 		while(s[0]==' ') { for (i=0;i<l;i++) s[i]=s[i+1]; l--; }
	 		if (s[0]!='-' && s[0]!='+') {
	 		   for (i=l+1;i>0;i--) s[i]=s[i-1]; s[0]=' '; 
	 		}
	 		else while(s[1]==' ') { for (i=1;i<l;i++) s[i]=s[i+1]; l--; }
	 		v=Adbl(s); 
	 	}
	 }
	 return v;
}
//    Revisa si hay informacion en el campo, si el campo son 
//    todos blanco regresa false

Boolean  HayInf(Char* c, Int16 l) {
	Int16 i;
	for (i=0;i<l;i++) {
		if( c[i] == 0 ) break;
		if( c[i] == ' ' ) continue;
		return true;
    }
    return false;
}
// ---------------------------------------------------------------------
// 								FECHAS
// ---------------------------------------------------------------------
Int16    DxM[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
//       Fecha Hoy
void     FecHoy (Fecha * F) {
DateTimeType  d;
         TimSecondsToDateTime(TimGetSeconds(),&d);
         F->d=d.day;F->m=d.month;F->a1=d.year/100;F->a2=d.year%100;
         return;         	
}
//       Formar año
Int16    FormaA (UInt8 a1,UInt8 a2) {
Int16    a=((Int16)a1)*100+a2;	
	     return a;	
}
//       Sacar dias de febrero con el año
Int16    DFeb (Int16 a) {
         if(a != (a/4*4) ) return 28;
         if(a == 1900 ) return 28;
         return 29;
}
//       Revisar una fecha
Boolean  RevF (Fecha *F) {
Boolean  HayErr = false;
Int16    d,m,a;
Char     DescDia[maxStrIToALen];
Char     DescMes[maxStrIToALen];
Char     DescAno[maxStrIToALen];
         d=F->d;m=F->m;a=FormaA(F->a1,F->a2);
         if(a<1900 || a>2100) HayErr = true;
         DxM[2]=DFeb(a);
         if(m<1 || m>12) HayErr = true;
         if(!HayErr) if( d<1 || d>DxM[m]) HayErr = true;
         if(HayErr) {
                StrIToA(DescDia, d);
                StrIToA(DescMes, m);
                StrIToA(DescAno, a);
         	FrmCustomAlert(9001,DescDia,DescMes,DescAno);
         }
         return HayErr;
}
//       Sacar tipo de dia   DS 0=do 1=lu 2=ma ... 6 sa
//                           IF 0=no 1=festivo 2=Viernes* SS 3=sa 4=do
//       (Solo acepta fechas > 1995  *solo fechas 2006 a 2015)                     
Boolean  SacarTFec (UInt8 *DS, UInt8 *IF, Fecha * FS) {
UInt8    Df[]={1,5,21,1,16,20,25};
UInt8    Mf[]={1,2,3,5,9,11,12};
UInt8    Dv[]={14,06,21,10,02,22,06,29,18,03};
UInt8    Mv[]={04,04,03,04,04,04,04,03,04,04};
Int16    i,a;
Fecha    F;
Int32    dd;
Int16    dm,da;

         if(RevF(FS)) return true;
         F.a1=19;F.a2=96;F.m=1;F.d=1;
         if(Restar2Fec(&dd,&dm,&da,&F,FS)) return true;
         dd++;
         (*DS)=(UInt8)(dd%7);
         (*IF)=0;
         for (i=0;i<sizeof(Df);i++) {
            if(FS->d==Df[i] && FS->m==Mf[i]) {
              (*IF)=1;
              return false;
            }
         }
         a=FormaA(FS->a1,FS->a2);
         if(a >= 2006 && a <= 2005+sizeof(Dv)) {
              i=a-2006;
              if(FS->d==Dv[i] && FS->m==Mv[i]) {
                (*IF)=2;
                return false;
              }
         }
         if((*DS)==6) (*IF)=3;
         if((*DS)==0) (*IF)=4;
         return false;
}
//       Sumar dias a una fecha
Boolean  SumarDias (Int16 Dias, Fecha *FS) {
Int16    di,d,m,a;
Boolean  cont=true;

         if(RevF(FS)) return true;
         d=FS->d;m=FS->m;a=FormaA(FS->a1,FS->a2);
         while (cont) {
             di=d+Dias;
//                                 Incremento positivo
             if(di > DxM[m]) {
                Dias -= DxM[m] - d;
                d=0;m++;
                if(m <= 12 ) continue;
                m=1;a++;
                DxM[2]=DFeb(a);
                continue;
             }
//                                 Incremento negativo
             if(di < 1) {
                Dias+=d;m--;
                if(m == 0) {
                      m = 12;a--;
                      DxM[2]=DFeb(a);
                }
                d=DxM[m];
                continue;
            }
//                                 Resultado
           FS->d=di;FS->m=m;FS->a1=a/100;FS->a2=a%100;
           cont=false;
       }
       return false;
}
//       Sumar meses a una fecha
Boolean  SumarMeses (Int16 Meses, Fecha *FS) {
Int16    dm,d,m,a;
Boolean  cont=true;
Boolean  UltDiaM=false;

         if(RevF(FS)) return true;
         d=FS->d;m=FS->m;a=FormaA(FS->a1,FS->a2);
         if(d == DxM[m]) UltDiaM=true;
         while (cont) {
             dm=m+Meses;
//                                  Incremento positivo
             if(dm > 12) {
                Meses -= 12 - m;
                m=0;a++;
                continue;
             }
//                                  Incremento negativo
             if(dm < 1) {
                Meses+=m;a--;m=12;
                continue;
            }
//                                  Resultado
           DxM[2]=DFeb(a);
           if(d > DxM[dm] || UltDiaM) d =  DxM[dm];
           FS->d=d;FS->m=dm;FS->a1=a/100;FS->a2=a%100;
           cont=false;
       }
       return false;
}
//       Sumar años a una fecha
Boolean  SumarAxo (Int16 Anos, Fecha *FS) {
Int16    a;	
         if(RevF(FS)) return true;
         a=FormaA(FS->a1,FS->a2);
         a+=Anos;
         DxM[2]=DFeb(a);
         if(((Int16)FS->d)>DxM[FS->m]) FS->d=DxM[FS->m];
         FS->a1=a/100;FS->a2=a%100;
         return false;
}
Boolean Restar2Fec (Int32 *Dd, Int16 *Dm, Int16 *Da, Fecha *Fi, Fecha *Ff) {
Int16   DaM[]={0,31,59,90,120,151,181,212,243,273,304,334};
Int16   di,df,mi,mf,ai,af;
Int16   tdi,tdf;
Int16   tmi,tmf;

        if(RevF(Fi)) return true;
        if(RevF(Ff)) return true;
        ai=FormaA(Fi->a1,Fi->a2);mi=Fi->m;di=Fi->d;
        af=FormaA(Ff->a1,Ff->a2);mf=Ff->m;df=Ff->d;
        tdi=DaM[mi-1]+di;
        if(mi>2) if(DFeb(ai)!=28)tdi++;
        tdf=DaM[mf-1]+df;
        if(mf>2) if(DFeb(af)!=28)tdf++;        
        tmi=ai*12+mi;
        tmf=af*12+mf;
//                                Fecha i < Fecha f
        if(tmi>tmf) return true;
        if(tmi==tmf && tdi>tdf) return true;
//                                Calcula meses
        (*Dm)=tmf-tmi;
        if(di>df && df!=DxM[mf]) (*Dm)--;
//                                Calcular años
        (*Da)=(*Dm)/12;
//                                Calcular dias
        (*Dd)=0;
        while (ai!=af) {
          (*Dd)+=365;
          if(DFeb(ai)!=28) (*Dd)++;
          ai++;
        }
        (*Dd)+=tdf-tdi;
        return false;
}
//      Comparar dos fechas
//      0=iguales  -1=tdi<tdf  1=tdi>tdf
Int16   Comp2Fec (Fecha *Fi, Fecha *Ff) {
Int32   tdi,tdf;

        tdi=((Int32)Fi->a1)*(Int32)1000000+((Int32)Fi->a2)*(Int32)10000+
              ((Int32)Fi->m)*(Int32)100+(Int32)Fi->d;
        tdf=((Int32)Ff->a1)*(Int32)1000000+((Int32)Ff->a2)*(Int32)10000+
              ((Int32)Ff->m)*(Int32)100+(Int32)Ff->d;
        if(tdi==tdf) return 0;
        if(tdi<tdf) return -1;
        return 1;
}
//      Pasar fecha a dia laborable N dias laborables antes.
//      OP=0 No en festivo, =1 No en festivo, ni domingo
//        =2 No en festivo, sabado o domingo, =3 cualquiera 
//		  =4 igual 2 pero después
Boolean  PasarFDL (Int16 Op,Int16 Nd, Fecha *F) {
UInt8    td,df;
         if(RevF(F)) return true;
         while (Nd>=0) {
            if(SacarTFec(&td,&df,F)) return true;
            switch (Op) {
            	case  0: if ( df==3 || df==4 ) df=0; break;
            	case  1: if (df==3) df=0; break;
            	case  2: break;
            	case  3: df=0; break;
            	case  4: break;
            	default:return true;
            }
            if(df==0) Nd--;
            if(Nd>=0) if(SumarDias ((Op==4)?1:-1,F)) return true;
         }
         return false;
}
//      Copia fecha
void CopFec(Fecha *d, Fecha *f) { MemMove(d,f,sizeof(Fecha));  }
//      Revisar si una fecha esta en mes actual y menor o igual
//      al dia de hoy.
Boolean  EsteMes (Fecha *F) {
DateTimeType  d;
    
         TimSecondsToDateTime(TimGetSeconds(),&d);
         if(FormaA(F->a1,F->a2)!=d.year) return false;
         if(F->m!=d.month) return false;
         if(F->d<d.day) return false;
         return true;
}  
//      Revisar si una fecha es futura
Boolean  Futura (Fecha *F) {
DateTimeType  d;
         TimSecondsToDateTime(TimGetSeconds(),&d);
         if(FormaA(F->a1,F->a2)>d.year) return true;
         if(FormaA(F->a1,F->a2)<d.year) return false;
         if(F->m>d.month) return true;
         if(F->m<d.month) return false;
         if(F->d<=d.day) return false;
         return true;
}  
//      Revisar si una fecha es pasada
Boolean  Pasada (Fecha *F) {
DateTimeType  d;
         TimSecondsToDateTime(TimGetSeconds(),&d);
         if(FormaA(F->a1,F->a2)<d.year) return true;
         if(FormaA(F->a1,F->a2)>d.year) return false;
         if(F->m<d.month) return true;
         if(F->m>d.month) return false;
         if(F->d>=d.day) return false;
         return true;
}  
Boolean EsteMesX(Fecha *f) {
DateTimeType  d;
         TimSecondsToDateTime(TimGetSeconds(),&d);
         if(FormaA(f->a1,f->a2)!=d.year)  return false;
         if(f->m!=d.month) return false;
         return true;
}
// Formar fecha op: 1=dd/mm       2=dd/MMM       3=dd/mes
//                  4=dd/mm/aaaa  5=dd/MMM/aaaa  6=dd/mes/aaaa
//                  7=dd/mm/aa    8=dd/MMM/aa    9=dd/mes/aa
// Formar fecha op: 1=dd/mm       2=dd/MMM       3=dd/mes
//                  4=dd/mm/aaaa  5=dd/MMM/aaaa  6=dd/mes/aaaa
//                  7=dd/mm/aa    8=dd/MMM/aa    9=dd/mes/aa
void RMes(Char *s, Int8 m, Boolean crt) {
	if (m>=0 && m<=11) SacaTexto(s,1000,((crt)?10+m:23+m),sizeof(s));
	else SacaTexto(s,1000,22,sizeof(s));
}
void RMesA(Char *s, Int8 m, Int16 a, Boolean crt) {
Char t[10];
	RMes(s,m,crt); StrIToA(t,a); StrCat(s," "); StrCat(s,t);
}
void DimFec(Char op, Fecha *f, Int16 *w, Int16 *h) {
Char st[53];
Int16  i;
	ForFec(st,op,f);
	for (i=0,*w=0;i<StrLen(st);i++) *w+=(UInt16)FntCharWidth(st[i]);
	*h=FntCharHeight(); 
}
void ForFec(Char *s, Char op, Fecha *f) {
Char   tp,sp[2],dd[3],mm[21],aa[5],t[5];
UInt16 at;
Int8   d,m;
Int16  a;
	d=f->d; m=f->m; a=FormaA(f->a1,f->a2);
	tp=PrefGen(2); sp[0]=PrefGen(3); sp[1]=0;
	StrIToA(t,d); StrCopy(dd,((d<10)?"0":"")); StrCat(dd,t); 
	if (op==7 || op==8 || op==9) {
		at=a/1000; at*=1000; a-=at; StrIToA(t,a);
		StrCopy(aa,((a<10)?"0":"")); StrCat(aa,t); 
	}
	else StrIToA(aa,a);
	switch(op) {
		case 7:
        case 4:
		case 1: StrIToA(t,m); StrCopy(mm,((m<10)?"0":"")); StrCat(mm,t); break;
		case 8:
		case 5:
		case 2: RMes(mm,m-1,true); break; 
		case 9:
		case 3:
		case 6: RMes(mm,m-1,false); break; 
	}
	switch(tp) {
		case 1: StrCopy(s,dd); StrCat(s,sp); StrCat(s,mm);
		        if (op>3) { StrCat(s,sp); StrCat(s,aa); } break;
		case 2: StrCopy(s,mm); StrCat(s,sp); StrCat(s,dd);
		        if (op>3) { StrCat(s,sp); StrCat(s,aa); } break;
		case 3: StrCopy(s,aa); StrCat(s,sp); StrCat(s,mm);
		                       StrCat(s,sp); StrCat(s,dd); break;
	}
}
// Poner una fecha como campo (enmarcada punteada)
Int16 PonFecCamp(Int16 x, Int16 y, Fecha *f, 
                 Int8 cl, Int8 cf, Boolean marco, Int8 *w) {
Char   st[52];
	ForFec(st,5,f); return PonTexto(st,x,y,N,I,0,marco,cl,-1,w);
}
void BorFecCamp(Int16 x, Int16 y, Int16 w, Int16 h, Int8 cf) {
RectangleType  rc;
Int16          bc;
	rc.topLeft.x=x; rc.topLeft.y=y-2; rc.extent.x=w; rc.extent.y=h+2;
	if (cf!=-1) bc=WinSetBackColor(cf); 
	WinEraseRectangle(&rc,0);
	if (cf!=-1) WinSetBackColor(bc); 
}
// Seleccionar una fecha
Boolean SelFecha(Char *tit, Fecha *f, Boolean ob) {
Int16   dd,mm,aa;
Boolean r;
    if (ob) FecHoy(f);
    dd=f->d; mm=f->m; aa=FormaA(f->a1,f->a2);
    r=SelectDay(selectDayByDay,&mm,&dd,&aa,tit);
    f->d=dd; f->m=mm; f->a1=aa/100; f->a2=aa%100;
	return r;
}
//  Numero Sumar=1 o Restar=2 otro Numero

Boolean NumSRN (NumX *NA,Int16 Op, NumX *NB ) {
	
	Int16   Acar,Pe1,j;
	Int16   SignoA,SignoB;
	Int16   NumA;
	SignoA = NA->Signo;
	SignoB = NB->Signo;	
	
//  Si es restar, cambiar signo a *B*

    if(Op==2) SignoB = 1 - SignoB;	
    
//  Caso de mismo signo, sumar ambos.

    if(SignoA==SignoB) {
    	Acar=0;
    	for(j=5;j>=0;j--) {
    		NA->VNum[j]+=NB->VNum[j]+Acar;
    		Acar=0;
    		if(NA->VNum[j]>99) {
    			NA->VNum[j]-=100;
    			Acar=1;
    		}
    	}
    	if(Acar==0) return true; else return false;
    } else {
    	
//   Caso de signo diferente, restar ambos.    	

    	Pe1=0;
    	for(j=5;j>=0;j--) {
    		NumA=NA->VNum[j];
    		NumA-=NB->VNum[j];
    		NumA-=Pe1;    		
    		Pe1=0;
    		if(NumA<0) {
    			NumA+=100;
    			Pe1=1;
    		}
    		NA->VNum[j]=NumA;
    	}
    	if(Pe1==0) return true;
    	
//   Caso de complementar    	
    	    
    	Pe1=0;
    	for(j=5;j>=0;j--) {
    		NumA=NA->VNum[j];
    		NumA=100-NumA-Pe1;
    		Pe1=1;
    		if(NumA==100) {
    			NumA=0;
    			Pe1=0;
    		}
    		NA->VNum[j]=NumA;
    	}
    	NA->Signo=SignoB;
    	return true;
    }
}

//   Pasar Numero a flotante

double PasaNaF (NumX * NA) {
	double TNumD[]={100000000.0,   // 0		                   		                  
   		             1000000.0,   // 1		                   		                     		                    
   		               10000.0,   // 2		                       		                     		                      
   		                 100.0,   // 3		                   		                  
   		                   1.0,   // 4
   		                   0.01}; // 5
	Int16 j;
	double Suma;  
	
	Suma = 0.0;
	for (j=0;j<6;j++) Suma+=((double)NA->VNum[j])*TNumD[j];
	if(NA->Signo==0) return Suma; else return -Suma;
}

//   Pasar Flotante a Numero

void PasaFaN (double * NF,NumX * NA) {
	double TNumD[]={100000000.0,   // 0		                   		                  
   		             1000000.0,   // 1		                   		                     		                    
   		               10000.0,   // 2		                       		                     		                      
   		                 100.0,   // 3		                   		                  
   		                   1.0,   // 4
   		                   0.01}; // 5
     double s;
     Int16  j;
     s=(*NF);
     if(s>=0.0) NA->Signo=0;
     else { s=-s;NA->Signo=1;}
     for (j=0;j<6;j++) {
     	NA->VNum[j]=(UInt8)(s/TNumD[j]);
     	s-=((double)NA->VNum[j])*TNumD[j];
     }
     return;
}

//   Pasar 0 a Numero

void  Pasa0aN (NumX* NA) {
	Int16  i;
	
	NA->Signo=0;
	for (i=0;i<6;i++) NA->VNum[i]=0;
	return;
}

//   Pasar 1 a Numero

void  Pasa1aN (NumX* NA) {
	Int16  i;
	
	NA->Signo=0;
	for (i=0;i<6;i++) NA->VNum[i]=0;
	NA->VNum[4]=1;
	return;
}

//   Pasar Numero a Numero

void  PasaNaN (NumX* NA, NumX* NB) {
	Int16  i;
	NB->Signo=NA->Signo;
	for (i=0;i<6;i++) NB->VNum[i]=NA->VNum[i];
}

//   Pasar Numero a Numero , cambiar Signo

void  PasaNaNS (NumX* NA, NumX* NB) {
      PasaNaN(NA,NB);
 	  NB->Signo=1-NA->Signo;
}

//   Pasar Numero a Ascii 

void PasaNaA(NumX * NA, Boolean Comas,Boolean Dec, Char *CB) {
	Char   TNumA[10]={'0','1','2','3','4','5','6','7','8','9'};
	Int16 i,j;
	UInt8 pos;
	UInt8 NumX[12];
	
	if(NA->Signo==1) CB[0]='-'; else CB[0]=' ';
	
	for (i=0,j=0;i<6;i++){
		NumX[j++]=NA->VNum[i]/10;
    	NumX[j++]=NA->VNum[i]%10;
	}
	
    pos = 1;
	for (j=0;j<12;j++) {
		if(pos == 1 && j < 9 && NumX[j]==0 ) continue;
		CB[pos++]=TNumA[NumX[j]];
		if(Comas && ( j==0 || j==3 || j==6) ) CB[pos++]=PrefGen(4);
		if(j==9) {if(Dec)CB[pos++]=PrefGen(5);else break;}		
	}
	CB[pos]=0;
	return;
}

//   Pasar Ascii a Numero

Boolean  PasaAaN (Char * CA,Boolean TieneDec,Boolean TieneSig, NumX * NB) {
	Char   TNumA[12]={'0','1','2','3','4','5','6','7','8','9'
			             ,' ',' '};
	Int16   i,j,Lon,Acar,ColPt,ColCo,Tem,Signo;
	NumX     NX;
	
	TNumA[10]=PrefGen(4);                  // Iniciar
	TNumA[11]=PrefGen(5);
	Pasa0aN (&NX);
	Lon=StrLen(CA);
	ColPt=ColCo=Signo=0;
	
	for(i=0;i<Lon;i++) {                  // Quitar blancos
		if(CA[i]=='-' && Signo==0) {Signo=-1;continue;}
		if(CA[i]=='+' && Signo==0) {Signo=1;continue;}		
		if(CA[i] != ' ' ) break;
	}
	if(i==Lon) {Pasa0aN(NB);return true;}
	for(j=Lon-1;j>i;j--)if(CA[j] != ' ' ) break;
	Lon=j+1;
	
	for (;i<Lon;i++) {               // Tomar uno por uno
       for(j=0;j<12;j++) if(CA[i]==TNumA[j]) break;
       if(j==12) {FrmAlert(113);return false;} 
       if(j==10) {                   // Caso de coma
       	 if(ColPt>0) {FrmAlert(114);return false;} 
       	 if(!(ColCo == 0 || ColCo == 4)) {FrmAlert(114);return false;} 
       	 ColCo=1;
       	 continue;
       }
       if(j==11) {                   // Caso de punto
       	 if(ColPt>0) {FrmAlert(114);return false;} 
       	 if(!(ColCo == 0 || ColCo == 4)) {FrmAlert(114);return false;} 
       	 ColPt=1;
       	 continue;
       }
       if(ColPt>0) {                // Procesar decimales
       	if(ColPt == 1) NX.VNum[5]=j*10;
       	if(ColPt == 2) NX.VNum[5]+=j;
       	if(ColPt > 2) {FrmAlert(114);return false;} 
       	ColPt++;
       	continue;
       }
       if(ColCo > 0) ColCo++;         // Acumular numero
       Acar=j;                        
       for(j=4;j>=0;j--) {
       	Tem=NX.VNum[j];
       	Tem=Tem*10+Acar;
       	Acar=Tem/100;
       	NX.VNum[j]=Tem%100;
       }
       if(Acar>0) {FrmAlert(112);return false;} 
	}
    if(ColPt == 0 && !(ColCo == 0 || ColCo == 4)) {FrmAlert(114);return false;}
    if(!TieneDec && ColPt > 0 ) {FrmAlert(110);return false;}
    if(!TieneSig && Signo == -1) {FrmAlert(111);return false;} 
    PasaNaN(&NX,NB);
    if(Signo == -1) NB->Signo=1;
    return true;
}

//   Compara Numero con Numero

Int16    CompNN (NumX * NA, NumX * NB) {
Int16    i;	
NumX     NC;
         PasaNaN (NA,&NC);
         NumSRN (&NC,2,NB);
         for (i=0;i<6;i++) if(NC.VNum[i]!=0) break;
         if(i==6) return 0;
         if(NC.Signo==1) return -1;
         return +1;
}
//   Compara Numero con 0

Int16    CompN0 (NumX * NA) {
Int16    i;	
         for (i=0;i<6;i++) if(NA->VNum[i]!=0) break;
         if(i==6) return 0;
         if(NA->Signo==1) return -1;
         return +1;
}