// UTS 2000 - Fichier 'aig.cpp' Lecture des variables pour la gestion des aiguillages dans le fichier de configuration, et gestion des aiguillages 
// V3.7c - Le 05/10/2016
/*****************************************************************************/
/* AIG                                                                       */
/*****************************************************************************/
//
/* 
Séquences tous les ticks : 
Sans directives lib0 ou lib1 dans config.txt
default_tic:1,1,0,1,1,0                   minimum prepa + go + repos (utilisation du relais6)
out = Aig=13  Sens=0  GO=0 prepa
out = Aig=13  Sens=0  GO=1 go
out = Aig= 0  Sens=0  GO=0 pas de lib mais directive repos
out = Aig= 5  Sens=1  GO=0 prepa
out = Aig= 5  Sens=1  GO=1 go
out = Aig= 0  Sens=0  GO=0 pas de lib mais directive repos

Sans directives lib0 ou lib1 dans config.txt
default_tic:0,1,0,0,1,0                  minimum go + repos (pas d'utilisation séparé du relais6)
out = Aig=13  Sens=0  GO=1 go
out = Aig= 0  Sens=0  GO=0 pas de lib mais directive repos
out = Aig= 5  Sens=1  GO=1 go 
out = Aig= 0  Sens=0  GO=0 pas de lib mais directive repos
out = Aig= 9  Sens=0  GO=1 go
out = Aig= 0  Sens=0  GO=0 pas de lib mais directive repos

Sans directives lib0 ou lib1 dans config.txt
default_tic:1,0,0,1,0,0
out = Aig=13  Sens=0  GO=0 prepa
out = Aig=13  Sens=0  GO=1 go
out = Aig= 0  Sens=0  GO=0 pas de lib mais directive repos
out = Aig= 5  Sens=1  GO=0 prepa
out = Aig= 5  Sens=1  GO=1 go
out = Aig= 0  Sens=0  GO=0 pas de lib mais directive repos

Sans directives lib0 ou lib1 dans config.txt
default_tic:0,1,1,0,1,1
out = Aig=13  Sens=0  GO=1
out = Aig=13  Sens=0  GO=1
out = Aig= 0  Sens=0  GO=0
out = Aig= 5  Sens=1  GO=1
out = Aig= 5  Sens=1  GO=1
out = Aig= 0  Sens=0  GO=0

Si pas de directive default_tic alors default_tic = 2,2,2,2,2,2
*/

#include  <windows.h>
#include  <string.h>
#include  <stdlib.h>
#include  <stdio.h>
#include "Train_UTS.h"
#include  "iti.h"

#define _CRT_SECURE_NO_WARNINGS  // Limite les messages de warning dans Visual C++

// Déclaration des fonctions externes
extern int get_line(FILE*, char [][CHAR_CONFIG_NB], int*);
extern void EasyTextOut(int, int, char*);
extern void EasyLine(int, int, int, int);
extern int pio_var_ch2int(char []);
extern void bmp_SetTextColor(int no_color);

// Déclaration des variables externes
extern int moins_char_normal;   // 1: - est un caractere normal (comme 0)  0: - est un separateur (comme +)
extern HDC   hMemDC;
extern HFONT bmp_fonte;
extern HPEN  bmp_stylo_noir, bmp_stylo_gris128, bmp_stylo_gris192, bmp_stylo_blanc, bmp_stylo_bleu;
extern HBRUSH  bmp_pinceau_blanc, bmp_pinceau_gris192, bmp_pinceau_gris220, bmp_pinceau_vert, bmp_pinceau_bleu, bmp_pinceau_jaune;
extern int x_mouse,y_mouse,touche,touche_char,x_mouse_move,y_mouse_move, screen_mode_retour;
extern int vio_aig_cmd[NB_AIG];
extern int vio_aig_pos0[NB_AIG];
extern int vio_aig_pos1[NB_AIG];
extern int vio_aig_res[NB_AIG];
extern int aig_enable;
extern int aig_cpt;
extern int aig_state;
extern int aig_select;
extern int aig_pos_select;
extern int pio_define_convert(char [],char []);
extern int vio_out[NB_CARTE][NB_OUT];
extern int screen_mode;
extern int timer_prg;
extern int cfg_memoire_pos_aig; // (0 par défaut), =1 => UTS sauvegarde et récupére la position des aiguillages sur le réseau, à la fermeture et ouverture du programme UTS.
extern int cfg_aigauto;

int aig_descr_info[NB_AIG][AIG_DESCR_INFO_IND_NB];
int aig_descr_idle[2*AIG_DESCR_IDLE_NB_OUT];    //40 variables (no + val);
int aig_descr[NB_AIG][AIG_DESCR_IND_PREGOLIB_NB][AIG_DESCR_IND_OUTTIME_NB]; //64 aig, 3 modes: PREP,GO,LIB 2*nbsorties+time


// Lecture dans le fichier 'config.txt' des paramètres pour la section 'aiguillages'.
//
void aig_init_file(char filename[])
{
	FILE* pf;
	char ch[CHAR_CONFIG_NB],ch_tab[BLOC_CONFIG_NB][CHAR_CONFIG_NB],ch_error[200],ch_syst[100];
	int  ch_nb,i,j,k,ok,aig_no=0,op=0,ind=0,var;

	if((pf=fopen(filename,"rt"))==NULL) {
		MessageBox(NULL,"Impossible d'ouvrir le fichier de configuration des aiguillages 'Config.txt'","Erreur",MB_OK|MB_ICONERROR); exit(1);
	}
	aig_state=SM_IDLE;
	aig_enable=1;
	aig_cpt=0;
	aig_select=-1;    //car pré-incrementation
	aig_pos_select=0;
	for(i=0;i<NB_AIG;i++) {
		for(j=0;j<6;j++) for(k=0;k<(2*AIG_DESCR_NB_OUT+1);k++) aig_descr[i][j][k]=-1;
	}
	for(i=0;i<2*AIG_DESCR_IDLE_NB_OUT;i++) aig_descr_idle[i]=-1;
	for(i=0;i<NB_AIG;i++) {
		for(j=1;j<AIG_DESCR_INFO_IND_NB;j++) aig_descr_info[i][j]=-1;    // For j=1 !!!
		aig_descr_info[i][0]=0;
		vio_aig_res[i]=0;
		vio_aig_pos0[i]=0;
		vio_aig_pos1[i]=0;
		vio_aig_cmd[i]=0;  // Pour obliger à mettre en position '0' au départ.
	}

// aig0:  prep0:      out0=0 out1=0 out2=0 tic=1
//        go0:        out0=0 out1=1 out2=0 tic=2
//        lib0:       out0=0 out1=0 out2=0 tic=1
//        prep1,lib1: out0=1 out1=0 out2=0 tic=1
//        go1:        out0=1 out1=1 out2=0 tic=2
//        verif0:     io_in_25=0
//        verif1:     io_in_25=1
// repos:             out0=0 out1=0 out2=0
// default_tic:1,2,1,1,2,1

	op=-1; //repos
	ind=0;
	while(fscanf(pf,"%s%*[^\n]\n",ch)!=EOF) {	// " %s" => "%s%*[^\n]\n" = Nouvelle formule au 02/03/2012, lit uniquement le permier mot de chaque ligne.
		if(STR_SAME strcmp(ch,"#aig")) {
			fscanf(pf," %s",ch); // Passe le caractère '['
			while(get_line(pf,ch_tab,&ch_nb)) {
	   			if(ch_nb>=BLOC_CONFIG_NB)	{
					MessageBox(NULL,"Le fichier config.txt comporte une ligne trop complexe dans la section '#aig'","Erreur",MB_OK|MB_ICONERROR);
					MessageBox(NULL,"Section '#aig' (ligne>75 blocs) commençant par (taper sur entrée) : ","Erreur",MB_OK|MB_ICONERROR);
					strcpy(ch_error,"Section #aig Erreur ligne :");
					for(i=0;i<ch_nb;i++) { strcat(ch_error,"  "); strcat(ch_error,ch_tab[i]); }
					MessageBox(NULL,ch_error,"UTS - Erreur",MB_OK|MB_ICONERROR); exit(1);
				}
				if(ch_tab[0][0]==']') break;				// Fin de la section #aig
				for(i=0;i<ch_nb;i++) if(ch_tab[i][0]=='@') ch_nb=i;	// Supprime les commentaires
				i=0;
				while(i<ch_nb) {					// ch_nb = nombre de bloc de caractères (nb de mots)
					if (ch_nb-i>=2)
					if (!strncmp(ch_tab[i],"aig",3) && ch_tab[i+1][0]==':') {
						aig_no=atoi(&ch_tab[i][3]);
						if (aig_no<NB_AIG) {		// Sort en erreur si le n° d'aiguillage n'existe pas.
							aig_descr_info[aig_no][AIG_DESCR_INFO_IND_EXIST]=1;
							i=i+2; continue;
						}
					}
					if (ch_nb-i>=2)
					if (ch_tab[i+1][0]==':') {
						ok=1;
						if(     !strcmp(ch_tab[i],"prep0"))    {op=AIG_DESCR_IND_PREP_POS_0; ind=0;}
						else if(!strcmp(ch_tab[i],"prep1"))    {op=AIG_DESCR_IND_PREP_POS_1; ind=0;}
						else if(!strcmp(ch_tab[i],"go0"  ))    {op=AIG_DESCR_IND_GO_POS_0  ; ind=0;}
						else if(!strcmp(ch_tab[i],"go1"  ))    {op=AIG_DESCR_IND_GO_POS_1  ; ind=0;}
						else if(!strcmp(ch_tab[i],"lib0" ))    {op=AIG_DESCR_IND_LIB_POS_0 ; ind=0;}
						else if(!strcmp(ch_tab[i],"lib1" ))    {op=AIG_DESCR_IND_LIB_POS_1 ; ind=0;}
						else if(!strcmp(ch_tab[i],"repos"))    {op=-1                      ; ind=0;}
						else if(!strcmp(ch_tab[i],"preplib0")) {op=-2                      ; ind=0;}
						else if(!strcmp(ch_tab[i],"preplib1")) {op=-3                      ; ind=0;}
						else ok=0;
						if(ok) {i=i+2; continue;}
					}
					if (ch_nb-i>=3)
					if (!strncmp(ch_tab[i],"out",3) && ch_tab[i+1][0]=='=') {
						if (op!=-1 && op!=-2 && op!=-3) {
							aig_descr[aig_no][op][2*ind+AIG_DESCR_IND_OUT_NO_0]=atoi(&ch_tab[i][3]);
							aig_descr[aig_no][op][2*ind+AIG_DESCR_IND_OUT_VAL_0]=atoi(ch_tab[i+2]);
						}
						else if (op==-1) {
							aig_descr_idle[2*ind+AIG_DESCR_IDLE_IND_OUT_NO_0]=atoi(&ch_tab[i][3]);
							aig_descr_idle[2*ind+AIG_DESCR_IDLE_IND_OUT_VAL_0]=atoi(ch_tab[i+2]);
						}
						else if (op==-2) {
							aig_descr[aig_no][AIG_DESCR_IND_PREP_POS_0][2*ind+AIG_DESCR_IND_OUT_NO_0 ]=atoi(&ch_tab[i][3]);
							aig_descr[aig_no][AIG_DESCR_IND_PREP_POS_0][2*ind+AIG_DESCR_IND_OUT_VAL_0]=atoi(ch_tab[i+2]);
							aig_descr[aig_no][AIG_DESCR_IND_LIB_POS_0 ][2*ind+AIG_DESCR_IND_OUT_NO_0 ]=atoi(&ch_tab[i][3]);
							aig_descr[aig_no][AIG_DESCR_IND_LIB_POS_0 ][2*ind+AIG_DESCR_IND_OUT_VAL_0]=atoi(ch_tab[i+2]);
						}
						else if (op==-3) {
							aig_descr[aig_no][AIG_DESCR_IND_PREP_POS_1][2*ind+AIG_DESCR_IND_OUT_NO_0 ]=atoi(&ch_tab[i][3]);
							aig_descr[aig_no][AIG_DESCR_IND_PREP_POS_1][2*ind+AIG_DESCR_IND_OUT_VAL_0]=atoi(ch_tab[i+2]);
							aig_descr[aig_no][AIG_DESCR_IND_LIB_POS_1 ][2*ind+AIG_DESCR_IND_OUT_NO_0 ]=atoi(&ch_tab[i][3]);
							aig_descr[aig_no][AIG_DESCR_IND_LIB_POS_1 ][2*ind+AIG_DESCR_IND_OUT_VAL_0]=atoi(ch_tab[i+2]);
						}
						ind++;
						i=i+3; continue;
					}
					if (ch_nb-i>=3)
					if (!strcmp(ch_tab[i],"tic") && ch_tab[i+1][0]=='=') {
						if (op>=0) aig_descr[aig_no][op][AIG_DESCR_IND_TIME]=atoi(ch_tab[i+2]);
						if (op==-2) {
							aig_descr[aig_no][AIG_DESCR_IND_PREP_POS_0][AIG_DESCR_IND_TIME]=atoi(ch_tab[i+2]);
							aig_descr[aig_no][AIG_DESCR_IND_LIB_POS_0 ][AIG_DESCR_IND_TIME]=atoi(ch_tab[i+2]);
						}
						if (op==-3) {
							aig_descr[aig_no][AIG_DESCR_IND_PREP_POS_1][AIG_DESCR_IND_TIME]=atoi(ch_tab[i+2]);
							aig_descr[aig_no][AIG_DESCR_IND_LIB_POS_1 ][AIG_DESCR_IND_TIME]=atoi(ch_tab[i+2]);
						}
						i=i+3; continue;
					}
					if (ch_nb-i>=5)
					if (!strncmp(ch_tab[i],"verif",5) && ch_tab[i+1][0]==':' && ch_tab[i+3][0]=='=') {
						if (pio_define_convert(ch_tab[i+2],ch_syst)==0) strcpy(ch_syst,ch_tab[i+2]);
						if ((var=pio_var_ch2int(ch_syst))!=-1) {
							if (ch_tab[i][5]=='0') {
								aig_descr_info[aig_no][AIG_DESCR_INFO_IND_VERIF_NUM_POS_0]=var;
								aig_descr_info[aig_no][AIG_DESCR_INFO_IND_VERIF_VAL_POS_0]=atoi(ch_tab[i+4]);
							}
							if (ch_tab[i][5]=='1') {
								aig_descr_info[aig_no][AIG_DESCR_INFO_IND_VERIF_NUM_POS_1]=var;
								aig_descr_info[aig_no][AIG_DESCR_INFO_IND_VERIF_VAL_POS_1]=atoi(ch_tab[i+4]);
							}
							i=i+5; continue;
						}
					}
					if (ch_nb-i>=13)
					if (!strcmp(ch_tab[i],"default_tic") && ch_tab[i+1][0]==':'
					   && ch_tab[i+3 ][0]==','           && ch_tab[i+5][0]==','
					   && ch_tab[i+7 ][0]==','           && ch_tab[i+9][0]==','
					   && ch_tab[i+11][0]==',') {
						for(j=0;j<NB_AIG;j++) {
							if (aig_descr[j][AIG_DESCR_IND_PREP_POS_0][AIG_DESCR_IND_TIME]==-1 ) aig_descr[j][AIG_DESCR_IND_PREP_POS_0][AIG_DESCR_IND_TIME]=atoi(ch_tab[i+2]);
							if (aig_descr[j][AIG_DESCR_IND_GO_POS_0  ][AIG_DESCR_IND_TIME]==-1 ) aig_descr[j][AIG_DESCR_IND_GO_POS_0  ][AIG_DESCR_IND_TIME]=atoi(ch_tab[i+4]);
							if (aig_descr[j][AIG_DESCR_IND_LIB_POS_0 ][AIG_DESCR_IND_TIME]==-1 ) aig_descr[j][AIG_DESCR_IND_LIB_POS_0 ][AIG_DESCR_IND_TIME]=atoi(ch_tab[i+6]);
							if (aig_descr[j][AIG_DESCR_IND_PREP_POS_1][AIG_DESCR_IND_TIME]==-1 ) aig_descr[j][AIG_DESCR_IND_PREP_POS_1][AIG_DESCR_IND_TIME]=atoi(ch_tab[i+8]);
							if (aig_descr[j][AIG_DESCR_IND_GO_POS_1  ][AIG_DESCR_IND_TIME]==-1 ) aig_descr[j][AIG_DESCR_IND_GO_POS_1  ][AIG_DESCR_IND_TIME]=atoi(ch_tab[i+10]);
							if (aig_descr[j][AIG_DESCR_IND_LIB_POS_1 ][AIG_DESCR_IND_TIME]==-1 ) aig_descr[j][AIG_DESCR_IND_LIB_POS_1 ][AIG_DESCR_IND_TIME]=atoi(ch_tab[i+12]);
						}
						i=i+13; continue;
					}
                    
// position_depart:a2.1  a3.1  a4.1  pour les aiguillages qui doivent être en position'1' au lancement d'UTS.
// vio_aig_cmd[i]=0;  // Pour obliger à mettre en position '0' au départ.

					if (ch_nb-i>=5)
					if (!strcmp(ch_tab[i], "position_depart") && ch_tab[i + 1][0] == ':') {
						i = i + 2;
						if (cfg_memoire_pos_aig == 1) break; // On ne récupére par la position des aiguillages ici, mais dans "config_tco.txt".
						while (ch_nb - i >= 3) {
							if (ch_tab[i][0] == 'a' && ch_tab[i + 1][0] == '.') {
								if (atoi(&ch_tab[i][1]) < NB_AIG && atoi(ch_tab[i + 2]) == 1) { vio_aig_cmd[atoi(&ch_tab[i][1])] = 1; i = i + 3; }
							}
						}
					continue;
					}

					strcpy(ch_error,"Fichier 'config.txt',\n\nSection #aig Erreur ligne :");
					for(i=0;i<ch_nb;i++) { strcat(ch_error,"  "); strcat(ch_error,ch_tab[i]); }
					MessageBox(NULL,ch_error,"UTS - Erreur",MB_OK|MB_ICONERROR); exit(1);
				}  //fin groupe de mot
			}	// While (get_line) fin de la ligne de texte.
			break; // Pour sortir de la lecture de la suite du fichier.
		}		// if(==#aig)   fin description '#aig'.
	}			// While (scanf)    fin du fichier 'config.txt'.
	moins_char_normal=1;		// '-' est un caractère normal, comme '+'.
	fclose(pf);
}



// Ecrit dans le fichier 'debug_aig.txt'
void aig_save_conf(void)
{
	FILE* pf;
	int i,j,k;
	if((pf=fopen("debug_aig.txt","wt"))==NULL) {
		MessageBox(NULL,"Impossible de créer le fichier 'Debug_aig.txt'","Erreur",MB_OK|MB_ICONERROR); exit(1);
	}
	fprintf(pf,"\nAIG_DESCR");
	for(k=0;k<NB_AIG;k++) {
		fprintf(pf,"\nAIG%d:",k);
		for(j=0;j<6;j++) {
			fprintf(pf,"\n    %2d: ",j);
			for(i=0;i<(2*AIG_DESCR_NB_OUT+1);i++) fprintf(pf," %4d",aig_descr[k][j][i]);
		}
	}
	fprintf(pf,"\n\nAIG_DESCR_IDLE");
	for(i=0;i<(2*AIG_DESCR_IDLE_NB_OUT);i++) fprintf(pf," %4d",aig_descr_idle[i]);
	fprintf(pf,"\n\nAIG_DESCR_INFO");
	for(j=0;j<NB_AIG;j++) {
		 fprintf(pf,"\n %2d:  ",j);
		 for(i=0;i<AIG_DESCR_INFO_IND_NB;i++) fprintf(pf," %4d",aig_descr_info[j][i]);
	}
	fclose(pf);
}

// Sous programme 'aig_in_pos(numéro_d'aiguillage)'
//  Vérifie si l'aiguillage est dans la position demandée.
//  Renvoi '1' si il est dans la position demandée, sinon renvoi '0'.
//  Compare vio_aig_cmd[] à vio_aig_posX[].
//
int aig_in_pos(int aig_select)
{
	if(vio_aig_cmd[aig_select]==0 && vio_aig_pos0[aig_select]==1) return 1;
	if(vio_aig_cmd[aig_select]==1 && vio_aig_pos1[aig_select]==1) return 1;
	return 0;
}

//
void aig_maj(void)
{
	int i,ok,var,val,time;
// 0. Toujours mettre les indicateurs de position à 0 si l'aiguillage n'est pas dans la position souhaité (commande != position_actuelle).
	for(i=0;i<NB_AIG;i++) if(!aig_in_pos(i)) {vio_aig_pos0[i]=0; vio_aig_pos1[i]=0;}
//-------------
// 1. ETAT IDLE
	if(aig_state==SM_IDLE)	{
		if(aig_enable==0) return;
// 1.1. Etat IDLE sorties au repos telle que définit
		for(i=0;i<AIG_DESCR_IDLE_NB_OUT;i++) {
			var=aig_descr_idle[2*i+AIG_DESCR_IDLE_IND_OUT_NO_0];
			val=aig_descr_idle[2*i+AIG_DESCR_IDLE_IND_OUT_VAL_0];
			if(var==-1) break; else vio_out[var/100][var%100]=val;
		}
// 1.2. recherche de changement d'etat
		ok=0;
		for(i=0;i<NB_AIG;i++) {
			aig_select++; if(aig_select>=NB_AIG) aig_select=0;  // C'est bien >= NB_AIG
			if(aig_descr_info[aig_select][AIG_DESCR_INFO_IND_EXIST]==0) continue;
			// On peut changer la postion d'un aiguillage vérouillé, mais uniquement depuis le menu : Tables > Aiguillages.
			if(aig_in_pos(aig_select)==0 /*|| vio_aig_ver[aig_select]==0*/) {ok=1;break;} // Cet aiguillage n'est pas en bonne position, on doit le bouger.
		}
// 1.3. changement d'etat
		if(ok==1) {
			//MessageBox(NULL,"Ok==1","Debug",MB_OK|MB_ICONERROR); exit(1);   
			aig_state=SM_PREP;
			aig_pos_select=vio_aig_cmd[aig_select];
			time=aig_descr[aig_select][AIG_DESCR_IND_PREP_POS_0+3*aig_pos_select][AIG_DESCR_IND_TIME];
			if(time==-1) aig_cpt=2; else aig_cpt=max(time,0); // Pour éviter des valeurs négatives
		}
	}
//-------------
// 2. ETAT PREP
	if(aig_state==SM_PREP) {
// 2.1. actions de l'etat PREP sorties PREP
		//vio_aig_ver[aig_select]=0;
		for(i=0;i<AIG_DESCR_NB_OUT;i++) {
			var=aig_descr[aig_select][AIG_DESCR_IND_PREP_POS_0+3*aig_pos_select][2*i+AIG_DESCR_IND_OUT_NO_0 ];
			val=aig_descr[aig_select][AIG_DESCR_IND_PREP_POS_0+3*aig_pos_select][2*i+AIG_DESCR_IND_OUT_VAL_0];
			if(var==-1) break; else vio_out[var/100][var%100]=val;
		}
// 2.2. recherche de changement d'etat
		ok=0;
		if(aig_cpt==0) ok=1;
		else aig_cpt--;
// 2.3. changement d'etat
		if(ok==1) {
			aig_state=SM_GO;
			time=aig_descr[aig_select][AIG_DESCR_IND_GO_POS_0+3*aig_pos_select][AIG_DESCR_IND_TIME];
			if(time==-1) aig_cpt=2; else aig_cpt=max(time,1); // Pour éviter des valeurs négatives et inférieures à 1.
		}
	}
//-------------
// 3. ETAT GO
	if(aig_state==SM_GO) {
// 3.1. actions de l'etat GO sorties PREP
//vio_aig_ver[aig_select]=0;
		for(i=0;i<AIG_DESCR_NB_OUT;i++) {
			var=aig_descr[aig_select][AIG_DESCR_IND_GO_POS_0+3*aig_pos_select][2*i+AIG_DESCR_IND_OUT_NO_0 ];
			val=aig_descr[aig_select][AIG_DESCR_IND_GO_POS_0+3*aig_pos_select][2*i+AIG_DESCR_IND_OUT_VAL_0];
			if(var==-1) break; else vio_out[var/100][var%100]=val;
		}
// 3.2. recherche de changement d'etat
		ok=0;
		if(aig_cpt==0) ok=1;
		else aig_cpt--;
// 3.3. changement d'etat
		if(ok==1) {
			aig_state=SM_LIB;
			time=aig_descr[aig_select][AIG_DESCR_IND_LIB_POS_0+3*aig_pos_select][AIG_DESCR_IND_TIME];
			if(time==-1) aig_cpt=2; else aig_cpt=max(time,0); // Pour éviter des valeurs négatives
		}
	}
//-------------
// 4. ETAT LIB
	if(aig_state==SM_LIB) {
// 4.1. actions de l'etat LIB sorties PREP
//vio_aig_ver[aig_select]=0;
		for(i=0;i<AIG_DESCR_NB_OUT;i++) {
			var=aig_descr[aig_select][AIG_DESCR_IND_LIB_POS_0+3*aig_pos_select][2*i+AIG_DESCR_IND_OUT_NO_0 ];
			val=aig_descr[aig_select][AIG_DESCR_IND_LIB_POS_0+3*aig_pos_select][2*i+AIG_DESCR_IND_OUT_VAL_0];
			if(var==-1) break; else vio_out[var/100][var%100]=val;
		}
// 2.2. recherche de changement d'etat
		ok=0;
		if(aig_cpt==0) ok=1;
		else aig_cpt--;
// 2.3. changement d'etat
		if(ok==1) {
			aig_state=SM_IDLE;
			if(aig_pos_select) { vio_aig_pos0[aig_select]=0; vio_aig_pos1[aig_select]=1;} else { vio_aig_pos0[aig_select]=1; vio_aig_pos1[aig_select]=0;}
			var=aig_descr_info[aig_select][AIG_DESCR_INFO_IND_VERIF_NUM_POS_0+2*aig_pos_select];
			val=aig_descr_info[aig_select][AIG_DESCR_INFO_IND_VERIF_VAL_POS_0+2*aig_pos_select];
			//if(     var==-1              ) vio_aig_ver[aig_select]=1;
			//else if(pio_get_val(var)==val) vio_aig_ver[aig_select]=1;
			//else                           vio_aig_ver[aig_select]=0;
			// 1.1. actions de l'etat IDLE sorties IDLE
			for(i=0;i<AIG_DESCR_IDLE_NB_OUT;i++) {
				var=aig_descr_idle[2*i+AIG_DESCR_IDLE_IND_OUT_NO_0];
				val=aig_descr_idle[2*i+AIG_DESCR_IDLE_IND_OUT_VAL_0];
				if(var==-1) break; else vio_out[var/100][var%100]=val;
			}
		}
	}
	//sprintf_s(gszErr,"\nstate=%d aig_sel=%d pos_sel=%d",aig_state,aig_select,aig_pos_select); log(gszErr);
}


// Affiche le tableau des états des aiguillages. Appel cet écran depuis le menu principal.
// Suivant la valeur de 'screen_mode' on affiche les aiguillages de 0 à 31 ou de 32 à 65.
//
void aig_debug(int action)
{
	int i;
	static int aig_deb=0;
	static int dimnx=44; // Dimension horizontal de la colonne 'Numéro'.
	static int dimcx=75; // Dimension horizontal des autres colonnes.
	static int dimy=18;		// Dimension verticale d'un cellule
	static int nblignes=30;		// Nombre de lignes dans le tableau (sans le titre)
	char ch[200];
	char ch2[50];

	SelectObject(hMemDC,bmp_fonte); SetBkMode(hMemDC,TRANSPARENT);
	SelectObject(hMemDC,bmp_pinceau_blanc); SelectObject(hMemDC,bmp_stylo_gris192);

	if(action==DEBUG_TOTAL_PAINT) {     // ACTION = REDESSINE TOUTE LA FENETRE.
		Rectangle(hMemDC,0,0,800,700);
		//Rectangle(hMemDC,0,0,800,dimy);	// Pour dessiner un rectangle pour les titres des colonnes.
		SelectObject(hMemDC,bmp_pinceau_gris192); SelectObject(hMemDC,bmp_stylo_gris192); Rectangle(hMemDC,800-15,15,800-2,2); // Rectangle gris pour fermer la fenêtre.
		SelectObject(hMemDC,bmp_stylo_noir); EasyLine(800-14,3,800-3,14 ); EasyLine(800-14,13,800-3,2); // Croix noire.
		SelectObject(hMemDC,bmp_stylo_noir);  EasyLine(800-2,1,800-2,16); EasyLine(800-16,15,800-1,15); // Trait noir.
		SelectObject(hMemDC,bmp_stylo_gris128); EasyLine(800-3,2,800-3,15); EasyLine(800-15,14,800-2,14); // Trait gris foncé.
		SelectObject(hMemDC,bmp_pinceau_blanc); SelectObject(hMemDC,bmp_stylo_gris192);
		EasyLine(0,dimy,4*dimcx+dimnx,dimy);
		EasyLine(        dimnx,dimy,        dimnx,2*dimy); // Dessine les trais verticaux des titres.
		EasyLine(1*dimcx+dimnx,dimy,1*dimcx+dimnx,2*dimy);
		EasyLine(2*dimcx+dimnx,dimy,2*dimcx+dimnx,2*dimy);
		EasyLine(3*dimcx+dimnx,dimy,3*dimcx+dimnx,2*dimy);
		EasyLine(4*dimcx+dimnx,dimy,4*dimcx+dimnx,2*dimy);
		EasyLine(1*dimcx+dimnx-10,2*dimy,1*dimcx+dimnx,2*dimy-10);  // Dessine un trait dans l'angle = valeurs modifiables.
		EasyLine(4*dimcx+dimnx-10,2*dimy,4*dimcx+dimnx,2*dimy-10);  // Dessine un trait dans l'angle = valeurs modifiables.
		SetTextColor(hMemDC,RGB(0,0,0)); // Texte noir
		EasyTextOut(2,2,"AFFICHE LES VALEURS NON NULLES DES PARAMÈTRES DES AIGUILLAGES   (64 maximum)"); EasyTextOut(800-140,2,"(QUITTER = ESC)");
		EasyTextOut(2,(nblignes+3)*dimy+1,"Section '#aig'");
		SelectObject(hMemDC,bmp_stylo_noir); SelectObject(hMemDC,bmp_pinceau_gris220); // Rectangle gris foncé au dessus de [CLIC DROIT]. 
		Rectangle(hMemDC,0,(nblignes+4)*dimy+1-2, 97, (nblignes+5)*dimy+1-2);
		SelectObject(hMemDC,bmp_stylo_gris128);
		EasyLine(1,  (nblignes+5)*dimy+1-2-2, 96, (nblignes+5)*dimy+1-2-2);  	// Relief rectangle.
		EasyLine(95, (nblignes+4)*dimy+1-2+1, 95, (nblignes+5)*dimy+1-2-2);	// Relief rectangle.
		SelectObject(hMemDC,bmp_stylo_noir);
		EasyLine(97 - 10, (nblignes + 5)*dimy + 1 - 4, 97, (nblignes + 5)*dimy + 1 - 2 - 12);  // Dessine un trait dans l'angle = valeurs modifiables.
		SelectObject(hMemDC,bmp_pinceau_blanc); SelectObject(hMemDC,bmp_stylo_gris192);
		EasyTextOut(2,(nblignes+4)*dimy+1," CLIC-DROIT :AFFICHE LES PAGES 1<->2, [00-29]<->[30-59]");
		EasyTextOut(2,(nblignes+5)*dimy+1,"CLIQUEZ sur 'Cmd' pour changer la position d'un aiguillage.");
		EasyTextOut(2,(nblignes+6)*dimy+1,"CLIQUEZ sur 'Réservé' pour changer l'état de réservation d'un aiguillage.");

		SelectObject(hMemDC,bmp_pinceau_jaune); // Rectangle jaune au dessus de [LIGNE JAUNE].
		Rectangle(hMemDC,0, -2+(nblignes+7)*dimy+1,96,-2+(nblignes+8)*dimy+1);
		SelectObject(hMemDC,bmp_pinceau_blanc);
		EasyTextOut(2,(nblignes+7)*dimy+1,"LIGNE JAUNE = Aiguillage en mouvement.");

		SetTextColor(hMemDC,RGB(255,0,0)); // Texte rouge
		EasyTextOut(              14,2+dimy," n°"  );
		EasyTextOut(        dimnx+22,2+dimy,"Cmd" ); // Valeurs de la colonne "Cmd" modifiables.
		EasyTextOut(1*dimcx+dimnx+20,2+dimy,"Pos0"); 
		EasyTextOut(2*dimcx+dimnx+20,2+dimy,"Pos1");
		EasyTextOut(3*dimcx+dimnx+10,2+dimy,"Réservé" ); // Valeurs de la colonne "Res" modifiables.

		SetTextColor(hMemDC,RGB(0,0,0)); // Texte noir	
		EasyTextOut(4*dimcx+dimnx+15,2+3*dimy,"Section '#aig'."); //default_tic:préparation0, go0, libération0 ,préparation1, go1, libération1.
		EasyTextOut(4*dimcx+dimnx+15,2+4*dimy,"Valeur de 'default_tic:' :"); //default_tic:préparation0, go0, libération0 ,préparation1, go1, libération1.
		EasyTextOut(4 * dimcx + dimnx + 15, 2 + 5 * dimy, "    default_tic : ");     // Affiche les valeurs de l'aiguillage n° 'NB_AIG-1' = n° 63.
		sprintf_s(ch,"%d,%d,%d,%d,%d,%d",                           // Affiche les valeurs de l'aiguillage n° 'NB_AIG-1' = n° 63.
		aig_descr[NB_AIG-1][AIG_DESCR_IND_PREP_POS_0][AIG_DESCR_IND_TIME], aig_descr[NB_AIG-1][AIG_DESCR_IND_GO_POS_0  ][AIG_DESCR_IND_TIME],
		aig_descr[NB_AIG-1][AIG_DESCR_IND_LIB_POS_0 ][AIG_DESCR_IND_TIME], aig_descr[NB_AIG-1][AIG_DESCR_IND_PREP_POS_1][AIG_DESCR_IND_TIME], 
		aig_descr[NB_AIG-1][AIG_DESCR_IND_GO_POS_1  ][AIG_DESCR_IND_TIME], aig_descr[NB_AIG-1][AIG_DESCR_IND_LIB_POS_1 ][AIG_DESCR_IND_TIME]);	
		bmp_SetTextColor(BMP_CST_COLOR_BLEUF);			// Texte en bleu.
		EasyTextOut(4*dimcx+dimnx+15+145,2+5*dimy,ch);

		bmp_SetTextColor(BMP_CST_COLOR_NOIR);			// Texte en noir.
		EasyTextOut(4*dimcx+dimnx+15,2+7*dimy, "Ce qui correspond aux temporisations :");
		EasyTextOut(4*dimcx+dimnx+15,2+8*dimy, "Durée de la commande de préparation prep0 = ");
		EasyTextOut(4*dimcx+dimnx+15,2+9*dimy, "Durée de la commande d'action       go0   = ");
		EasyTextOut(4*dimcx+dimnx+15,2+10*dimy,"Durée de la commande de libération  libe0 = ");
		EasyTextOut(4*dimcx+dimnx+15,2+12*dimy,"Durée de la commande de préparation prep1 = ");
		EasyTextOut(4*dimcx+dimnx+15,2+13*dimy,"Durée de la commande d'action       go1   = ");
		EasyTextOut(4*dimcx+dimnx+15,2+14*dimy,"Durée de la commande de libération  libe1 = ");

		bmp_SetTextColor(BMP_CST_COLOR_BLEUF);			// Texte en bleu.
		if (aig_descr[NB_AIG-1][AIG_DESCR_IND_PREP_POS_0][AIG_DESCR_IND_TIME] == -1 ) {sprintf_s(ch,"%3d ms",2*(timer_prg+15));} // Par défaut  timer = 2 dans le code.
		else {sprintf_s(ch,"%3d ms",(aig_descr[NB_AIG-1][AIG_DESCR_IND_PREP_POS_0][AIG_DESCR_IND_TIME])*(timer_prg+15));}
		EasyTextOut(4*dimcx+dimnx+370,2+8*dimy,ch); //

		if (aig_descr[NB_AIG-1][AIG_DESCR_IND_GO_POS_0][AIG_DESCR_IND_TIME] == -1 ) {sprintf_s(ch,"%3d ms",2*(timer_prg+15));} // Par défaut  timer = 2 dans le code.
		else {sprintf_s(ch,"%3d ms",(max(1,aig_descr[NB_AIG-1][AIG_DESCR_IND_GO_POS_0][AIG_DESCR_IND_TIME]))*(timer_prg+15));}
		EasyTextOut(4*dimcx+dimnx+370,2+9*dimy,ch); //
		
		if (aig_descr[NB_AIG-1][AIG_DESCR_IND_LIB_POS_0][AIG_DESCR_IND_TIME] == -1 ) {sprintf_s(ch,"%3d ms",2*(timer_prg+15));} // Par défaut  timer = 2 dans le code.
		else {sprintf_s(ch,"%3d ms",(aig_descr[NB_AIG-1][AIG_DESCR_IND_LIB_POS_0][AIG_DESCR_IND_TIME])*(timer_prg+15));}
		EasyTextOut(4*dimcx+dimnx+370,2+10*dimy,ch); //
	
		if (aig_descr[NB_AIG-1][AIG_DESCR_IND_PREP_POS_1][AIG_DESCR_IND_TIME] == -1 ) {sprintf_s(ch,"%3d ms",2*(timer_prg+15));} // Par défaut  timer = 2 dans le code.
		else {sprintf_s(ch,"%3d ms",(aig_descr[NB_AIG-1][AIG_DESCR_IND_PREP_POS_1][AIG_DESCR_IND_TIME])*(timer_prg+15));}
		EasyTextOut(4*dimcx+dimnx+370,2+12*dimy,ch); //
	
		if (aig_descr[NB_AIG-1][AIG_DESCR_IND_GO_POS_1][AIG_DESCR_IND_TIME] == -1 ) {sprintf_s(ch,"%3d ms",2*(timer_prg+15));} // Par défaut  timer = 2 dans le code.
		else {sprintf_s(ch,"%3d ms",(max(1,aig_descr[NB_AIG-1][AIG_DESCR_IND_GO_POS_1][AIG_DESCR_IND_TIME]))*(timer_prg+15));}
		EasyTextOut(4*dimcx+dimnx+370,2+13*dimy,ch); //
	
		if (aig_descr[NB_AIG-1][AIG_DESCR_IND_LIB_POS_1][AIG_DESCR_IND_TIME] == -1 ) {sprintf_s(ch,"%3d ms",2*(timer_prg+15));} // Par défaut  timer = 2 dans le code.
		else {sprintf_s(ch,"%3d ms",(aig_descr[NB_AIG-1][AIG_DESCR_IND_LIB_POS_1][AIG_DESCR_IND_TIME])*(timer_prg+15));}
		EasyTextOut(4*dimcx+dimnx+370,2+14*dimy,ch); //

		bmp_SetTextColor(BMP_CST_COLOR_NOIR);			// Texte en noir.
		sprintf_s(ch,"AIGAUTO est :"); 
		EasyTextOut(4*dimcx+dimnx+15,2+16*dimy,ch); //
		sprintf_s(ch,"Mémorisation position aiguillages est :");
		EasyTextOut(4*dimcx+dimnx+15,2+17*dimy,ch); //


		if (cfg_aigauto==1) {	sprintf_s(ch,"ACTIF"); } else { sprintf_s(ch,"PAS ACTIF"); }
		bmp_SetTextColor(BMP_CST_COLOR_BLEUF);			// Texte en bleu.
		EasyTextOut(4*dimcx+dimnx+15+113,2+16*dimy,ch); //
		if (cfg_memoire_pos_aig==1) {	sprintf_s(ch,"ACTIF"); } else { sprintf_s(ch, "PAS ACTIF"); }
		EasyTextOut(4*dimcx+dimnx+15+320,2+17*dimy,ch); //
	}

    if (action==DEBUG_MOUSE) {	// ACTION = CLIC GAUCHE DE LA SOURIS
		if ((x_mouse > 0 && x_mouse < 97) && (y_mouse > (nblignes+4)*dimy+1-2 && y_mouse < (nblignes+5)*dimy+1-2)) { //	Clique dans [CLIC DROIT]
			action=DEBUG_MOUSE_RIGHT; //	Simule le clique-droit traité plus loin.
		}
		else {
			if ((x_mouse > 800-15 && x_mouse < 800-2) && (y_mouse > 2 && y_mouse < 15)) {
				screen_mode= screen_mode_retour; 
				return;	// On ferme la fenêtre.
			}
		    i=(y_mouse-2*dimy)/dimy;
			if (y_mouse>=2*dimy && i>=0 && i<nblignes && aig_deb+i<NB_AIG) { //visible: 30 max, aig: 64 max
				if(x_mouse>dimnx && x_mouse<1*dimcx+dimnx)         vio_aig_cmd[aig_deb+i]^=1;	// Change la position de l'aiguillage
				if(x_mouse>3*dimcx+dimnx && x_mouse<4*dimcx+dimnx) vio_aig_res[aig_deb+i]^=1;	// Change l'état 'Reservé' de l'aiguillage.
			}
		}
	}

	if (action==DEBUG_MOUSE_RIGHT) { // ACTION = CLIC DROIT DE LA SOURIS, on change de page
	    // N'efface que la partie du tableau. Pas nécessaire ici, car le tableau est complétement refait.
		//	Rectangle(hMemDC,0,dimy*2,4*dimcx+dimnx,dimy*(nblignes+2));	
		if (aig_deb!=nblignes) screen_mode=MD_ECRAN_AIG2;
		else                   screen_mode=MD_ECRAN_AIG1;
		}

	if (screen_mode==MD_ECRAN_AIG1) aig_deb=0;	      // N° du premier aiguillage à afficher
	if (screen_mode==MD_ECRAN_AIG2) aig_deb=nblignes;

	if (action==DEBUG_KEY) { }          // ACTION = TOUCHE ENFONCEE

	SetTextColor(hMemDC,RGB(0,0,255));    // Texte bleu
	for(i=0;i<nblignes;i++) {
		SelectObject(hMemDC,bmp_pinceau_blanc);
		if (aig_deb+i>NB_AIG) {
			SelectObject(hMemDC,bmp_stylo_blanc);
			Rectangle(hMemDC,0,dimy*(i+1),4*dimcx+dimnx,dimy*(i+2));
			continue;
		}
		SelectObject(hMemDC,bmp_stylo_gris192);
		if (aig_in_pos(aig_deb+i)==0) SelectObject(hMemDC,bmp_pinceau_jaune); // Cet aiguillage n'est pas encore dans la position demandé -> en jaune.
		if (aig_descr_info[aig_deb+i][AIG_DESCR_INFO_IND_EXIST]==0) SelectObject(hMemDC,bmp_pinceau_blanc); // Cet aiguillage n'est pas décrit dans 'config.txt'.

		Rectangle(hMemDC,       0,dimy*(i+2),   4*dimcx+45,dimy*(i+3)+1);
		EasyLine(        dimnx,dimy*(i+2),        dimnx,dimy*(i+3));  	// Dessine les traits verticaux du tableau.
		EasyLine(1*dimcx+dimnx,dimy*(i+2),1*dimcx+dimnx,dimy*(i+3));
		EasyLine(2*dimcx+dimnx,dimy*(i+2),2*dimcx+dimnx,dimy*(i+3)); 
		EasyLine(3*dimcx+dimnx,dimy*(i+2),3*dimcx+dimnx,dimy*(i+3));
		EasyLine(4*dimcx+dimnx,dimy*(i+2),4*dimcx+dimnx,dimy*(i+3));

		if(aig_descr_info[aig_deb+i][AIG_DESCR_INFO_IND_EXIST]==0) SetTextColor(hMemDC,RGB(192,192,192));    // Texte gris 192
		sprintf_s(ch,"%3d",aig_deb+i); EasyTextOut(10,3+dimy*(i+2),ch);
		SetTextColor(hMemDC,RGB(0,0,255));    // Texte bleu

		if(aig_descr_info[aig_deb+i][AIG_DESCR_INFO_IND_EXIST]==0) continue;
		sprintf_s(ch,"%4d",vio_aig_cmd[aig_deb+i]); EasyTextOut(54,3+dimy*(i+2),ch);
		if (vio_aig_pos0[aig_deb+i]!=0) {sprintf_s(ch,"%4d",vio_aig_pos0[aig_deb+i]); EasyTextOut(1*dimcx+54,3+dimy*(i+2),ch);}
		if (vio_aig_pos1[aig_deb+i]!=0) {sprintf_s(ch,"%4d",vio_aig_pos1[aig_deb+i]); EasyTextOut(2*dimcx+54,3+dimy*(i+2),ch);}
		if (vio_aig_res[aig_deb+i]!=0)  {sprintf_s(ch,"%4d",vio_aig_res[aig_deb+i]);  EasyTextOut(3*dimcx+54,3+dimy*(i+2),ch);}
	}
}
