// UTS 2000 - Fichier 'bal.cpp' Lecture des variables pour simuler un bloc automatique.
//
// V3.7c le 30/09/2016
/*****************************************************************************/
/* Début BALAUTO                                                             */
/*****************************************************************************/
#include  <windows.h>
#include  <string.h>
#include  <stdlib.h>
#include  <stdio.h>
#include "Train_UTS.h"
#include "balauto.h"
#include "canton.h"
#include "selectif.h"
#include "train.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 int pio_var_int2ch(int ,char []);
extern int pio_define_convert(char [],char []);
extern int pio_get_val(int);
extern void bmp_SetTextColor(int no_color);

// Déclaration des variables externes
extern HDC     hMemDC;
extern HFONT   bmp_fonte;
extern HPEN    bmp_stylo_noir, bmp_stylo_gris128, bmp_stylo_gris192, bmp_stylo_blanc, bmp_stylo_jaune;
extern HBRUSH  bmp_pinceau_blanc, bmp_pinceau_jaune, bmp_pinceau_gris192, bmp_pinceau_gris220, bmp_pinceau_vert, bmp_pinceau_rouge, bmp_pinceau_orange;
extern cCanton  canton;
extern cTrain   train;
extern int screen_mode;
extern int moins_char_normal; 
extern int nb_balauto_vitmax_lus;
extern int nb_balauto_halt_lus;
extern int vio_det[NB_CARTE][NB_CANTON];
extern int vio_aig_res[NB_AIG];
extern int vio_aig_cmd[NB_AIG];
extern int vio_aig_pos0[NB_AIG];
extern int vio_aig_pos1[NB_AIG];

extern int cmd_divers[CMD_DIVERS_TAILLE]; // Tableau pour commander directement les déplacements par clic sur les cases du TCO
extern int balauto_vitmax_train[NB_TRAIN]; // Vitesse en cas de limitation de vitesse d'un train '#balauto' + 'vitmax:' != 0 => 'vitmax:'.
extern int balauto_halt_train[NB_TRAIN];   // 1 = En cas de halte d'un train sur un canton '#balauto' + 'halt:' = 1 => Train en 'halt:'.
extern int balauto_cant_train[NB_TRAIN];   // =2 => En cas de blocage d'un train sur un canton '#balauto' +'cant:' = 1 => Consigne vitesse du train = 0. =1 => Ralentissement.
extern int balauto_cant_train_dec[NB_TRAIN];   // -1 ou 1 à 28 = décélération du train sur 'cant:'.
extern int balauto_cant_train_ral[NB_TRAIN];   // -64 à 64 = ralenti du train sur 'cant:'.
extern int cfg_tempo_libe_cant; // 0 à 99 = Temporisation pour libérer un canton. Valeur lue dans 'config.txt'.

extern int vio_bal_cant_p[NB_CARTE][NB_CANTON];				// 0-1, 1 = Bloc automatique - Canton bloqué dans le sens Plus
extern int vio_bal_cant_m[NB_CARTE][NB_CANTON];				// 0-1, 1 = Bloc automatique - Canton bloqué dans le sens Moins
extern int x_mouse,y_mouse, screen_mode_retour;

//
cBalauto balauto;

//
cBalauto::cBalauto(void)
{}

//
void cBalauto::init(char filename[])
{
	FILE* pf;
	char ch[CHAR_CONFIG_NB],ch_tab[BLOC_CONFIG_NB][CHAR_CONFIG_NB],ch_error[200],ch_syst[100];
	int  i,j,i_param,ch_nb,no_balauto_vitmax,no_balauto_halt,no_balauto_cant,no_cant,i_verif,ligne_verif,balauto_mode;

	for(j=0;j<BALAUTO_VITMAX_NB;j++) {
		for(i=0;i<BALAUTO_VITMAX_TAB_IND_TAILLE;i++) {
			balauto_vitmax_tab[j][i]=-1;
		}
		balauto_vitmax_tab[j][BALAUTO_VITMAX_TAB_IND_CANT_VIT]=0; // Ensuite on place -1 ou +1.
	}
	for(j=0;j<BALAUTO_HALT_NB;j++) {
		for(i=0;i<BALAUTO_HALT_TAB_IND_TAILLE;i++) {
			balauto_halt_tab[j][i]=-1;
		}
		balauto_halt_tab[j][BALAUTO_HALT_TAB_IND_CANT_SENS]=0;
	}
	for(j=0;j<BALAUTO_CANT_NB;j++) {
		for(i=0;i<BALAUTO_CANT_TAB_IND_TAILLE;i++) {
			balauto_cant_tab[j][i]=-1;
		}
		balauto_cant_tab[j][BALAUTO_CANT_TAB_IND_CANT_SENS]=0;
	}

	for(j=0;j<NB_TRAIN;j++) {
		balauto_halt_train[j]=0;
		balauto_cant_train[j]=0;
		balauto_cant_train_dec[j]=-1;
		balauto_cant_train_ral[j]=0;
	}

	if ((pf=fopen(filename,"rt"))==NULL){
		MessageBox(NULL,"Impossible d'ouvrir le fichier de configuration du #balauto","Erreur",MB_OK|MB_ICONERROR);	exit(1);
	}

	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,"#balauto")) {
			fscanf(pf," %s",ch);	// Passe le caractère '['.
			no_balauto_vitmax=-1;
			no_balauto_halt=-1;
			no_balauto_cant=-1;
			moins_char_normal=0; // Si 'moins_char_normal' = 0, le caractère '-' est un caractère séparateur comme ' ' -10:+10 =>  [-][10]  et  [+][10]
			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 '#balauto'","Erreur",MB_OK|MB_ICONERROR);
					MessageBox(NULL,"Section '#balauto' (ligne>75 blocs) commençant par (taper sur Entrée) : ","Erreur",MB_OK|MB_ICONERROR);
					strcpy(ch_error,"Section #balauto 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 #balauto
				for(i=0;i<ch_nb;i++) if(ch_tab[i][0]=='@') ch_nb=i;  // Supprime sur une lignes le texte après un '@' = Commentaires.
				no_cant=-1;
//	vitmax:c12:+10    condi: a2.0 in_2.1
//	halt:c1:+   condi: a4.0 a5.0  in_49.1 garage_lock_status_0.1
//	cant:c1:+   ral:10   dec:11   plusur: c0 c9    blocage: det_2.1 a4.1 | det_13.1 a4.0 a5.1 | a4.0 a5.0 garage_lock_status_0.1
				balauto_mode=0;	// 00=Aucun mode, 
								// 10=Mode définition 'vitmax:' élément 'condi:', 11=Mode définition 'vitmax:' partie 'condi:' élément <variables>
								// 20=Mode définition 'halt:' élément condi:, 21=Mode définition 'halt:' partie 'condi:' élément <variables>
								// 30=Mode définition 'cant:' élément 'plusur:', 31=Mode définition 'cant:' partie 'plusur:' élément <variables> 
				                // 31=Mode définition 'cant:' partie 'blocage:', 32=Mode définition 'cant:' partie 'blocage:' <variables>
				ligne_verif=0;
				i_param=0;
				i=0;
				while(i<ch_nb) {
					i_verif=i;
// 'tempo_libe_cant:' ou 'vitmax:'  ou  'halt:'  ou  'cant:' ?
					if (STR_SAME strcmp(ch_tab[i],"tempo") && ch_tab[i+1][0]=='-' && STR_SAME strcmp(ch_tab[i+2],"libe") && 
						ch_tab[i+3][0]=='-' && STR_SAME strcmp(ch_tab[i+4],"cant") && ch_tab[i+5][0]==':' && ch_nb-i>=6) {
						if (atoi(ch_tab[i+6])>=0 && atoi(ch_tab[i+6])<=99) {
							cfg_tempo_libe_cant=atoi(ch_tab[i+6]);
							i=i+7;
							ligne_verif=1;
						}
					}
					else if (balauto_mode==0 && STR_SAME strcmp(ch_tab[i],"vitmax") && ch_tab[i+1][0]==':' && ch_nb-i>=6) {
						no_balauto_vitmax++; // Nouvel élément.
						ligne_verif=0;
						if(no_balauto_vitmax>=BALAUTO_VITMAX_NB) break;	// Fin de la partie 'vitmax:'
						j=atoi(&ch_tab[i+2][1]); // = Numéro du canton en cours.
						balauto_vitmax_tab[no_balauto_vitmax][BALAUTO_VITMAX_TAB_IND_CANT_NO]=j; // N° du canton encours
						if (j>=0 && j<(300+NB_CANTON) && (j%100)<NB_CANTON) ligne_verif=1; // OK
						if (ch_tab[i+2][0]!='c') ligne_verif=0;
						if (ch_tab[i+3][0]!=':') ligne_verif=0; // Erreur
						j=atoi(&ch_tab[i+5][0]); // = Vitesse maximum sur ce canton.
						if (ch_tab[i+4][0]=='-')      balauto_vitmax_tab[no_balauto_vitmax][BALAUTO_VITMAX_TAB_IND_CANT_VIT]=-j; // Vitesse maxi sur canton en cours.
						else if (ch_tab[i+4][0]=='+') balauto_vitmax_tab[no_balauto_vitmax][BALAUTO_VITMAX_TAB_IND_CANT_VIT]=j;  // Vitesse maxi sur canton en cours.
						if (ch_tab[i+4][0]!='-' && ch_tab[i+4][0]!='+')           ligne_verif=0; // Erreur 
						if (j<1 || j>VITESSE_CANT_MAXI) ligne_verif=0; // 'j' est toujours positif! Erreur, Vitesse minimum = 1.
						if (ligne_verif==1) balauto_mode=10;  // On passe en mode 10=Mode définition 'vitmax:' élément 'condi:'.
						i_param=0; i=i+6;
					}
					else if (balauto_mode==0 && STR_SAME strcmp(ch_tab[i],"halt") && ch_tab[i+1][0]==':' && ch_nb-i>=5+2) { // 5+2 car 'condi:' obligatoire
						no_balauto_halt++; // Nouvel élément.
						ligne_verif=0;
						if(no_balauto_halt>=BALAUTO_HALT_NB) break;	// Fin de la partie 'halt:'
						j=atoi(&ch_tab[i+2][1]); // = Numéro du canton en cours.
						balauto_halt_tab[no_balauto_halt][BALAUTO_HALT_TAB_IND_CANT_NO]=j; // N° du canton encours
						if (j>=0 && j<(300+NB_CANTON) && (j%100)<NB_CANTON) ligne_verif=1; // OK
						if (ch_tab[i+2][0]!='c') ligne_verif=0;
						if (ch_tab[i+3][0]!=':') ligne_verif=0; // Erreur
						if (ch_tab[i+4][0]!='-' && ch_tab[i+4][0]!='+') ligne_verif=0; // Erreur 
						if (ch_tab[i+4][0]=='-')      balauto_halt_tab[no_balauto_halt][BALAUTO_HALT_TAB_IND_CANT_SENS]=-1;
						else if (ch_tab[i+4][0]=='+') balauto_halt_tab[no_balauto_halt][BALAUTO_HALT_TAB_IND_CANT_SENS]=1;
						if (ligne_verif==1) balauto_mode=20;  // On passe en mode 20=Mode définition 'halt:' élément condi:
						i_param=0; i=i+5;
					}
					else if (balauto_mode==0 && STR_SAME strcmp(ch_tab[i],"cant") && ch_tab[i+1][0]==':' && ch_nb-i>=5+2) { // 5+2 car 'plusur:' ou 'blocage:' obligatoire
						no_balauto_cant++; // Nouvel élément.
						ligne_verif=0;
						if(no_balauto_cant>=BALAUTO_CANT_NB) break;	// Fin de la partie 'cant:'
						j=atoi(&ch_tab[i+2][1]); // = Numéro du canton en cours.
						balauto_cant_tab[no_balauto_cant][BALAUTO_CANT_TAB_IND_CANT_NO]=j; // N° du canton encours
						if (j>=0 && j<(300+NB_CANTON) && (j%100)<NB_CANTON) ligne_verif=1; // OK
						if (ch_tab[i+2][0]!='c') ligne_verif=0;
						if (ch_tab[i+3][0]!=':') ligne_verif=0; // Erreur
						if (ch_tab[i+4][0]!='-' && ch_tab[i+4][0]!='+') ligne_verif=0; // Erreur 
						if (ch_tab[i+4][0]=='-')      balauto_cant_tab[no_balauto_cant][BALAUTO_CANT_TAB_IND_CANT_SENS]=-1;
						else if (ch_tab[i+4][0]=='+') balauto_cant_tab[no_balauto_cant][BALAUTO_CANT_TAB_IND_CANT_SENS]=1;
						if (ligne_verif==1) balauto_mode=30;  // On passe en mode 30=Mode définition 'cant:' élément condi:
						i_param=0; i=i+5;
					}
//
// vitmax:c12:+10    condi: a2.0 in_2.1    ('condi:' facultatif)
// 10 = Mode définition 'vitmax:' élément 'condi:'
// 11 = Mode définition 'vitmax:' partie 'condi:' <variables>
					else if (balauto_mode==10 && STR_SAME strcmp(ch_tab[i],"condi") && ch_tab[i+1][0]==':' && ch_nb-i>=2) {
						// 10 = Mode définition 'vitmax:' élément 'ral:' ou 'dec:' ou 'condi:'
						balauto_mode=11;  // On passe en mode définition 'vitmax:' partie 'condi:' <variables>
						i_param=0; i=i+2;
					}
					else if (balauto_mode==11 && ch_nb-i>=3) {
						//  11=Mode définition 'vitmax:' partie 'condi:' élément <variables>
						if (i_param<BALAUTO_VITMAX_NB_MAX_VAR) {
							if (ch_tab[i+1][0]!='.')                        ligne_verif=0; // Erreur.
							if (ch_tab[i+2][0]!='0' && ch_tab[i+2][0]!='1') ligne_verif=0; // Erreur on n'accepte que 0 ou 1 comme valeur.
							if (ligne_verif==1 && ch_tab[i][0]=='a' && ch_tab[i][1]>='0'&& ch_tab[i][1]<='9') {
								// On va faire un effort, on va convertir exceptionnellement "aX.Y" en "posY_aig_X.1".
								if (ch_tab[i+2][0]=='0') strcpy(ch_error,"pos0_aig_");
								else                     strcpy(ch_error,"pos1_aig_");
								strcat(ch_error,&ch_tab[i][1]); // = "posy_aig_x"
								strcpy(ch_tab[i],ch_error);
								if (pio_define_convert(ch_tab[i],ch_syst)==0) strcpy(ch_syst,ch_tab[i]);	// Converti '401' en 'in_1'.
								j=pio_var_ch2int(ch_syst);					 								// Converti 'in_1' en '401'.
								if (j!=-1) {
									balauto_vitmax_tab[no_balauto_vitmax][BALAUTO_VITMAX_TAB_IND_VAR_0+i_param]=j;
								    balauto_vitmax_tab[no_balauto_vitmax][BALAUTO_VITMAX_TAB_IND_VAL_0+i_param]=1; // "pos0_aig_X.1" ou "pos0_aig_X.1"
								}
								else ligne_verif=0; // Erreur sur le n° de variables.
								i_param++; i=i+3;
							}	
							else {
								// Tous les autres cas de variables.
								if (pio_define_convert(ch_tab[i],ch_syst)==0) strcpy(ch_syst,ch_tab[i]);	// Converti '401' en 'in_1'.
								j=pio_var_ch2int(ch_syst);													// Converti 'in_1' en '401'.
								if (j!=-1) {
									balauto_vitmax_tab[no_balauto_vitmax][BALAUTO_VITMAX_TAB_IND_VAR_0+i_param]=j;
								    balauto_vitmax_tab[no_balauto_vitmax][BALAUTO_VITMAX_TAB_IND_VAL_0+i_param]=atoi(&ch_tab[i+2][0]);
								}
								else ligne_verif=0; // Erreur sur le n° de variables.
								i_param++; i=i+3;
							}
						}
						else ligne_verif=0; // On a  dépassé le nb de variable autorisée, on va sortir du programme en fin de boucle.	
					}
//
// halt:c1+   condi: a4.0 a5.0 in_49.1 garage_lock_status_0.1     ('condi:' obligatoire)
// 20=Mode définition 'halt:' élément condi:,
// 21=Mode définition 'halt:' partie 'condi:' élément <variables>
					else if (balauto_mode==20 && STR_SAME strcmp(ch_tab[i],"condi") && ch_tab[i+1][0]==':' && ch_nb-i>=2+3) { // 2+3 car <variable>.x obligatoire
						// 20 = Mode définition 'halt:' élément condi:,
						balauto_mode=21;  // On passe en mode définition 'halt:' partie 'condi:' élément <variables>.
						i_param=0; i=i+2;
					}
					else if (balauto_mode==21 && ch_nb-i>=3) {
						//  21=Mode définition 'halt:' partie 'condi:' élément <variables>
						if (i_param<BALAUTO_HALT_NB_MAX_VAR) {
							if (ch_tab[i+1][0]!='.')                        ligne_verif=0; // Erreur.
							if (ch_tab[i+2][0]!='0' && ch_tab[i+2][0]!='1') ligne_verif=0; // Erreur on n'accepte que 0 ou 1 comme valeur.
							if (ligne_verif==1 && ch_tab[i][0]=='a' && ch_tab[i][1]>='0'&& ch_tab[i][1]<='9') {
								// On va faire un effort, on va convertir exceptionnellement "aX.Y" en "posY_aig_X.1".
								if (ch_tab[i+2][0]=='0') strcpy(ch_error,"pos0_aig_");
								else                     strcpy(ch_error,"pos1_aig_");
								strcat(ch_error,&ch_tab[i][1]); // = "posy_aig_x"
								strcpy(ch_tab[i],ch_error);
								if (pio_define_convert(ch_tab[i],ch_syst)==0) strcpy(ch_syst,ch_tab[i]);	// Converti '401' en 'in_1'.
								j=pio_var_ch2int(ch_syst);					 								// Converti 'in_1' en '401'.
								if (j!=-1) {
									balauto_halt_tab[no_balauto_halt][BALAUTO_HALT_TAB_IND_VAR_0+i_param]=j;
								    balauto_halt_tab[no_balauto_halt][BALAUTO_HALT_TAB_IND_VAL_0+i_param]=1; // "pos0_aig_X.1" ou "pos0_aig_X.1"
								}
								else ligne_verif=0; // Erreur sur le n° de variables.
								i_param++; i=i+3;
							}	
							else {
								// Tous les autres cas de variables.
								if (pio_define_convert(ch_tab[i],ch_syst)==0) strcpy(ch_syst,ch_tab[i]);	// Converti '401' en 'in_1'.
								j=pio_var_ch2int(ch_syst);													// Converti 'in_1' en '401'.
								if (j!=-1) {
									balauto_halt_tab[no_balauto_halt][BALAUTO_HALT_TAB_IND_VAR_0+i_param]=j;
								    balauto_halt_tab[no_balauto_halt][BALAUTO_HALT_TAB_IND_VAL_0+i_param]=atoi(&ch_tab[i+2][0]);
								}
								else ligne_verif=0; // Erreur sur le n° de variables.
								i_param++; i=i+3;
							}
						}
						else ligne_verif=0; // On a  dépassé le nb de variable autorisée, on va sortir du programme en fin de boucle.	
					}

// cant:c1:+   plusur: c0 c9       blocage: det_2.1 a4.1 | det_13.1 a4.0 a5.1 | a4.0 a5.0 garage_lock_status_0.1
// 30=Mode définition 'cant:' élément 'plusur:', 
// 31=Mode définition 'cant:' partie 'plusur:' élément <variables> 
// 31=Mode définition 'cant:' élément 'blocage:', 
// 32=Mode définition 'cant:' partie 'blocage:' <variables>
					else if (balauto_mode==30 && STR_SAME strcmp(ch_tab[i],"plusur") && ch_tab[i+1][0]==':' && ch_nb-i>=2) {
						// 30=Mode définition 'cant:' élément 'plusur:', 
						balauto_mode=31;  // On passe en mode définition 'cant:' partie 'plusur:' élément <variables>
						i_param=0; i=i+2;
					}
					else if ((balauto_mode==30 || balauto_mode==31) && STR_SAME strcmp(ch_tab[i],"blocage") && ch_tab[i+1][0]==':' && ch_nb-i>=2+3) {  // 2+3 car il faut au minimum une condition de blocage.
						balauto_mode=32; // 32=Mode définition 'cant:' partie 'blocage:' <variables>
						i_param=0; i=i+2;
					}
 					else if (balauto_mode==30 && STR_SAME strcmp(ch_tab[i],"dec") && ch_tab[i+1][0]==':' && ch_nb-i>=3) {
						// 30 = Mode définition 'vitmax:' élément 'dec:' = valeur de l'inertie au ralentissement.
						// On reste en mode définition 30 = 'cant:' partie 'plusur:' élément <variables>
						j=atoi(&ch_tab[i+2][0]);
						if (j>=VITESSE_INERTIE_MINI && j<=VITESSE_INERTIE_MAXI) {
							balauto_cant_tab[no_balauto_cant][BALAUTO_CANT_TAB_IND_DEC]=j;
							i_param=0; i=i+3;
						}
					}
 					else if (balauto_mode==30 && STR_SAME strcmp(ch_tab[i],"ral") && ch_tab[i+1][0]==':' && ch_nb-i>=3) {
						// 30 = Mode définition 'vitmax:' élément 'ral:' = valeur de ralenti si le prochain canton est occupé
						// Si un groupe de vaiable 'condi:' impose un blocage mais que l'on n'a pas encore libéré les cantons précédents indiqués dans 'plusur:'
						// on passe en mode ralenti avec cette valeur.
						// On reste en mode définition 30 = 'cant:' partie 'plusur:' élément <variables>
						j=atoi(&ch_tab[i+2][0]);
						if (j>=VITESSE_CANT_MIN && j<=VITESSE_CANT_MAXI) {
							balauto_cant_tab[no_balauto_cant][BALAUTO_CANT_TAB_IND_RAL]=j;
							i_param=0; i=i+3;
						}
					}
//
					else if (balauto_mode==31 && ch_nb-i>=1) { // Recherche des cantons avec CE train = cx
						if (i_param<BALAUTO_CANT_NB_MAX_CANT) {
							if (ch_tab[i][0]!='c') ligne_verif=0;			// Erreur on n'accepte que c. comme descriptif.
							if (atoi(&ch_tab[i][1])<0 || atoi(&ch_tab[i][1])>=(300+NB_CANTON) || (atoi(&ch_tab[i][1])%100)>=NB_CANTON) ligne_verif=0; // Erreur
							if (ligne_verif!=0) {
								balauto_cant_tab[no_balauto_cant][BALAUTO_CANT_TAB_IND_CANT_0_NO+i_param]= atoi(&ch_tab[i][1]);
								i_param++; i=i+1;
							}
						}
						else ligne_verif=0; // On a  dépassé le nb autorisé de cantons, on va sortir du programme en fin de boucle.
					}

					else if (balauto_mode==32) {
						//  32=Mode définition 'cant:' partie 'blocage:' <variables>
						ligne_verif=0;
						if (ch_nb-i>=1+3) { // 1+3 car on attend une condition après un '|'
							if (i_param<BALAUTO_CANT_NB_MAX_VAR) {
								if (ch_tab[i][0]=='|' && ch_tab[i][1]==0 && ch_tab[i+1][0]!='|') { // Pas deux '|' successif.
									balauto_cant_tab[no_balauto_cant][BALAUTO_CANT_TAB_IND_VAR_0+i_param]=EQ_BASE+EQ_O;
								    balauto_cant_tab[no_balauto_cant][BALAUTO_CANT_TAB_IND_VAL_0+i_param]=0;
									if (i_param!=0) {  // Il faut que le '|' ne soit pas le premier élément rencontré après 'blocage:'.
										ligne_verif=1;
										i_param++; i=i+1;
									}
								}
							}
						}
						if (ligne_verif==0 && ch_nb-i>=3) { // On ne traite qu'un élément à la fois, et on sortira en erreur ici si l'on avait trouvé deux '|' successif.
															// On ne passe pas ici si l'on avait trouvé un '|'.
							if (i_param<BALAUTO_CANT_NB_MAX_VAR) {
								if (ch_tab[i][0]=='a' && ch_tab[i][1]>='0'&& ch_tab[i][1]<='9') {
									// On va faire un effort, on va convertir exceptionnellement "aX.Y" en "posY_aig_X.1".
									if (ch_tab[i+2][0]=='0') strcpy(ch_error,"pos0_aig_");
									else                     strcpy(ch_error,"pos1_aig_");
									strcat(ch_error,&ch_tab[i][1]); // = "posy_aig_x"
									strcpy(ch_tab[i],ch_error);
									if (pio_define_convert(ch_tab[i],ch_syst)==0) strcpy(ch_syst,ch_tab[i]);	// Converti '401' en 'in_1'.
									j=pio_var_ch2int(ch_syst);					 								// Converti 'in_1' en '401'.
									if (j!=-1) {
										balauto_cant_tab[no_balauto_cant][BALAUTO_CANT_TAB_IND_VAR_0+i_param]=j;
									    balauto_cant_tab[no_balauto_cant][BALAUTO_CANT_TAB_IND_VAL_0+i_param]=1; // "pos0_aig_X.1" ou "pos0_aig_X.1"
										ligne_verif=1;
										i_param++; i=i+3;
									}
								}	
								else {
									// Tous les autres cas de variables.
									if (pio_define_convert(ch_tab[i],ch_syst)==0) strcpy(ch_syst,ch_tab[i]);	// Converti '401' en 'in_1'.
									j=pio_var_ch2int(ch_syst);													// Converti 'in_1' en '401'.
									if (j!=-1) {
										balauto_cant_tab[no_balauto_cant][BALAUTO_CANT_TAB_IND_VAR_0+i_param]=j;
									    balauto_cant_tab[no_balauto_cant][BALAUTO_CANT_TAB_IND_VAL_0+i_param]=atoi(&ch_tab[i+2][0]);
										ligne_verif=1;
										if (ch_tab[i+1][0]!='.')                        ligne_verif=0; // Erreur.
										if (ch_tab[i+2][0]!='0' && ch_tab[i+2][0]!='1') ligne_verif=0; // Erreur on n'accepte que 0 ou 1 comme valeur.
										i_param++; i=i+3;
									}
								}
							}
						}
					}

					if (ligne_verif==0 || i_verif==i) { // Erreur ou on n'a pas trouvé de signification sur la chaine de caractères analysée. On sort pour ne pas boucler ici.
						strcpy(ch_error,"Fichier 'config.txt',\n\nSection #balauto,\n\nErreur de description sur la 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);
					}

				}
			}	// While (get_line) fin de la ligne de texte.
			break; // Pour sortir de la lecture de la suite du fichier.
		}		// if(==#balauto)   fin description '#balauto'.
	}			// While (scanf)    fin du fichier 'config.txt'.
	moins_char_normal=1;		// '-' est un caractère normal, comme '+'.
	nb_balauto_vitmax_lus=no_balauto_vitmax+1;
	nb_balauto_halt_lus=no_balauto_halt+1;
	fclose(pf);
}


//
void cBalauto::tick_vitmax(void)
{
//
// Pour la section #balauto,  descriptif 'vitmax:' uniquement
//   vitmax:c7:-10     condi: a9.0 a14.0
//   Directive pour limiter la vitesse, en descente ou en courbe. La limitation dépend du sens du parcours du canton.
//   Dans ce cas la consigne du train = Vitesse limite du canton. Changement de vitesse avec inertie.
//
// La mise à 0 de la vitesse des trains se fait dans le sous programme  : train.maj() = Train::maj(). 
// La mise à 0 de la vitesse des cantons se fait dans le sous programme : train.canton_maj_profil() = Train::canton_maj_profil().
//
// si plusieurs lignes 'vitmax:' pour le même canton, on prend la vitesse la plus faible.

	int i, j, canton_inverse;
	int cant_n, vit_n, train_n, action_n, var_n , val_n;

	for(i=0;i<NB_TRAIN;i++) {
		balauto_vitmax_train[i]=0; // != 0 => Le train ne doit pas être placé en 'vitmax:'. Sert dans Train::maj().
	}
	for(i=0;i<BALAUTO_VITMAX_NB;i++) {
		if (balauto_vitmax_tab[i][BALAUTO_VITMAX_TAB_IND_CANT_NO]==-1) break;	// Après le dernier élément du tableau on sort.
		cant_n=balauto_vitmax_tab[i][BALAUTO_VITMAX_TAB_IND_CANT_NO];			// cant_n = n° du canton 'aigauto' en cours de traitement.
		balauto_vitmax_tab[i][BALAUTO_VITMAX_TAB_IND_ACTION_OK]=0;
		if (canton.master_selectif[cant_n/100][cant_n%100]==1) {
			// Pour le canton en cours de traitement, on a trouvé qu'il est un canton principal en conduite manuelle (<>-1).
			train_n = canton.num_train[cant_n/100][cant_n%100];				// On récupere le n° du train.
			canton_inverse = 1;
			if (canton.inv_selectif[cant_n / 100][cant_n % 100] != 0) canton_inverse = -1; // Prend en compte les cantons inversés (après une boucle de retournement) en V3.7c
			vit_n=balauto_vitmax_tab[i][BALAUTO_VITMAX_TAB_IND_CANT_VIT];		// vit_n = vitesse du canton en cours de traitement.
			if ((vit_n>0 && canton.vit_selectif[cant_n/100][cant_n%100]>=vit_n)         || (vit_n<0 && canton.vit_selectif[cant_n/100][cant_n%100]<=vit_n) || 
			    (vit_n>0 && canton_inverse*train.cons_sans_correction[train_n]>=vit_n)  || (vit_n<0 && canton_inverse*train.cons_sans_correction[train_n]<=vit_n)) {
				// Pour le canton en cours de traitement, on a trouvé qu'il est un canton principal en conduite manuelle (<>-1) et qui est occupé (==1).
				// et que sa vitesse en manuel est > à celle demandée.
				action_n = 1;
				for(j=0;j<BALAUTO_VITMAX_NB_MAX_VAR;j++) {
					if (balauto_vitmax_tab[i][BALAUTO_VITMAX_TAB_IND_VAR_0+j]==-1) break;	// On arrive à la fin du tableau des conditions avec des valeurs.
					var_n=balauto_vitmax_tab[i][BALAUTO_VITMAX_TAB_IND_VAR_0+j];			// var_n = n° de la variable à tester.
					val_n=balauto_vitmax_tab[i][BALAUTO_VITMAX_TAB_IND_VAL_0+j];			// val_n = valeur à vérifier.
					// Ici, 'action_n' vaut toujours '1' en entrée de test => Blocage si l'on ne change pas sa valeur.
					if (var_n>=5100 && var_n<5100+NB_AIG) { // pos0_aig_xxx 
						// Si l'aiguillage est en mouvement, la condition sera toujours valide pour bloquer le train.
						if (pio_get_val(var_n)==1 || pio_get_val(var_n+100)==1) {
							if (pio_get_val(var_n)!=val_n) { action_n=0; break; }	
						}
					}
					else if (var_n>=5200 && var_n<5200+NB_AIG) { // pos1_aig_xxx 
						// Si l'aiguillage est en mouvement, la condition sera toujours valide pour bloquer le train.
						if (pio_get_val(var_n)==1 || pio_get_val(var_n-100)==1) {
							if (pio_get_val(var_n)!=val_n) { action_n=0; break; }	
						}
					}
					else if (pio_get_val(var_n)!=val_n) { action_n=0; break; }			// [var_n] = val_n ?
				}
				if (action_n==1) {
					// On va donner une limitation de vitesse au train.
					balauto_vitmax_tab[i][BALAUTO_VITMAX_TAB_IND_ACTION_OK]=1; // Indicateur canton en 'vitesse max'.
					if (balauto_vitmax_train[train_n]==0) {
						balauto_vitmax_train[train_n]=canton_inverse*vit_n; // !=0 => Le train doit être limité à cette vitesse. Sert dans Train::maj().
					}
					else if (vit_n>0 && balauto_vitmax_train[train_n]>vit_n) { // On garde la vitesse la plus faible
						balauto_vitmax_train[train_n]=canton_inverse*vit_n; // !=0 => Le train doit être limité à cette vitesse. Sert dans Train::maj().
					}
					else if (vit_n<0 && balauto_vitmax_train[train_n]<vit_n) { // On garde la vitesse la plus faible
						balauto_vitmax_train[train_n]=canton_inverse*vit_n; // !=0 => Le train doit être limité à cette vitesse. Sert dans Train::maj().
					}
				}
			}
		}
	}
}


//
// Pour la section #balauto,  descriptif 'halt:' uniquement
//   halt:c1:+   condi: a4.0 a5.0  in_49.1 garage_lock_status_0.1
//   Directive pour stopper net un train en fin de voie, quand il franchi une barrière infra-rouge placé 5 cm avant un heurtoir.
//   Dans ce cas la vitesse du train = 0. (On ignore la consigne).  Arrêt sans inertie.
//   cons_sans_correction[t] = -64 à +64. =0 si le le bouton frein  est actionné.
//
// La mise à 0 de la vitesse des trains se fait dans le sous programme  : train.maj() = Train::maj(). 
// La mise à 0 de la vitesse des cantons se fait dans le sous programme : train.canton_maj_profil() = Train::canton_maj_profil().

void cBalauto::tick_halt(void)
{
	int i, j, canton_inverse;
	int cant_n, sens_n, train_n, action_n, var_n , val_n;

	for(i=0;i<NB_TRAIN;i++) {
		balauto_halt_train[i]=0; // 0 = Le train ne doit pas être placé en 'halte:'. Sert dans Train::maj().
	}
	for(i=0;i<BALAUTO_HALT_NB;i++) {
		if (balauto_halt_tab[i][BALAUTO_HALT_TAB_IND_CANT_NO]==-1) break;	// Après le dernier élément du tableau on sort.
		cant_n=balauto_halt_tab[i][BALAUTO_HALT_TAB_IND_CANT_NO];			// cant_n = n° du canton 'aigauto' en cours de traitement.
		balauto_halt_tab[i][BALAUTO_HALT_TAB_IND_ACTION_OK]=0;
		if (canton.master_selectif[cant_n/100][cant_n%100]==1) {
			// Pour le canton en cours de traitement, on a trouvé qu'il est un canton principal en conduite manuelle (<>-1).
			sens_n=balauto_halt_tab[i][BALAUTO_HALT_TAB_IND_CANT_SENS];		// vit_n = vitesse du canton en cours de traitement.
			train_n = canton.num_train[cant_n/100][cant_n%100];				// On récupere le n° du train.
			canton_inverse = 1;
			if (canton.inv_selectif[cant_n / 100][cant_n % 100] != 0) canton_inverse = -1; // Prend en compte les cantons inversé (après une boucle de retournement) en V3.7c
			if ((sens_n>0 && canton.vit_selectif[cant_n/100][cant_n%100]>=1)         || (sens_n<0 && canton.vit_selectif[cant_n/100][cant_n%100]<=-1) || 
			    (sens_n>0 && canton_inverse*train.cons_sans_correction[train_n]>=1)  || (sens_n<0 && canton_inverse*train.cons_sans_correction[train_n]<=-1)) {

				// Pour le canton en cours de traitement, on a trouvé qu'il est un canton principal en conduite manuelle (<>-1) 
				// et que son sens de parcours est celui pouvant être bloqué.
				action_n = 1;
				for(j=0;j<BALAUTO_HALT_NB_MAX_VAR;j++) {
					if (balauto_halt_tab[i][BALAUTO_HALT_TAB_IND_VAR_0+j]==-1) break;	// On arrive à la fin du tableau avec des valeurs.
					var_n=balauto_halt_tab[i][BALAUTO_HALT_TAB_IND_VAR_0+j];			// var_n = n° de la variable à tester.
					val_n=balauto_halt_tab[i][BALAUTO_HALT_TAB_IND_VAL_0+j];			// val_n = valeur à vérifier.
					// Ici, 'action_n' vaut toujours '1' en entrée de test => Blocage si l'on ne change pas sa valeur.
					if (var_n>=5100 && var_n<5100+NB_AIG) { // pos0_aig_xxx 
						// Si l'aiguillage est en mouvement, la condition sera toujours valide pour bloquer le train.
						if (pio_get_val(var_n)==1 || pio_get_val(var_n+100)==1) {
							if (pio_get_val(var_n)!=val_n) { action_n=0; break; }
						}
					}
					else if (var_n>=5200 && var_n<5200+NB_AIG) { // pos1_aig_xxx 
						// Si l'aiguillage est en mouvement, la condition sera toujours valide pour bloquer le train.
						if (pio_get_val(var_n)==1 || pio_get_val(var_n-100)==1) {
							if (pio_get_val(var_n)!=val_n){ action_n=0; break; }
						}
					}
					else if (pio_get_val(var_n)!=val_n) { action_n=0; break; } // [var_n] = val_n ?
				}
				if (action_n==1) {
					// On va bloquer le train = Pas d'arrêt progressif.
					balauto_halt_tab[i][BALAUTO_HALT_TAB_IND_ACTION_OK]=1; // Indicateur canton en 'halte'.
					balauto_halt_train[train_n]=1; // 1 = Le train doit être placé en 'halte:'. Sert dans Train::maj()
				}
			}
		}
	}
}

//
// Pour la section #balauto,  descriptif 'cant:' uniquement
// cant:c1:+   plusur: c0 c9       blocage: det_2.1 a4.1 | det_13.1 a4.0 a5.1 | a4.0 a5.0 garage_lock_status_0.1
// Directive pour bloquer un train sur un canton, si le canton suivant est occupé ou si les aiguillages sont fermés.
// Dans ce cas la consigne du train = 0.  Arrêt avec inertie.
//
// La mise à 0 de la vitesse des trains se fait dans le sous programme  : train.maj() = Train::maj(). 
// La mise à 0 de la vitesse des cantons se fait dans le sous programme : train.canton_maj_profil() = Train::canton_maj_profil().

// si plusieurs condition pour le même canton, on prend la vitesse la plus faible.

//
void cBalauto::tick_cant(void)
{
	int i, j, canton_inverse;
	int cant_n, sens_n, train_n, action1_n, action2_n, var_n , val_n;

	for(i=0;i<NB_TRAIN;i++) {
		balauto_cant_train[i]=0; // 0 = Le train ne doit pas être bloqué. Sert dans Train::maj()
	}
		for(i=0;i<BALAUTO_CANT_NB;i++) {
		if (balauto_cant_tab[i][BALAUTO_CANT_TAB_IND_CANT_NO]==-1) break;	// On arrive à la fin du tableau avec des valeurs.
		cant_n=balauto_cant_tab[i][BALAUTO_CANT_TAB_IND_CANT_NO];			// cant_n = n° du canton 'aigauto' en cours de traitement.
		balauto_cant_tab[i][BALAUTO_CANT_TAB_IND_ACTION_OK]=0;
		sens_n=balauto_cant_tab[i][BALAUTO_CANT_TAB_IND_CANT_SENS];		// vit_n = vitesse du canton en cours de traitement.
//		if ((canton.master_selectif[cant_n/100][cant_n%100]==1) && (vio_det[cant_n/100][cant_n%100]==1)) {
		if (canton.master_selectif[cant_n/100][cant_n%100]==1) {
			// Pour le canton en cours de traitement, on a trouvé qu'il est un canton principal en conduite manuelle (<>-1) et qui est occupé (==1).
			train_n = canton.num_train[cant_n/100][cant_n%100];				// On récupere le n° du train.

			canton_inverse = 1;
			if (canton.inv_selectif[cant_n / 100][cant_n % 100] != 0) canton_inverse = -1; // Prend en compte les cantons inversé (après une boucle de retournement) en V3.7c
			
			if (sens_n>0) vio_bal_cant_p[cant_n/100][cant_n%100]=0; // Renseigne les variables de type 'bal_cant_p_xxx'=1 => BAL Canton bloqué dans le sens Plus.
			else          vio_bal_cant_m[cant_n/100][cant_n%100]=0; // Renseigne les variables de type 'bal_cant_m_xxx'=1 => BAL Canton bloqué dans le sens Moins.
			if ((sens_n>0 && canton.vit_selectif[cant_n/100][cant_n%100]>=1) || (sens_n<0 && canton.vit_selectif[cant_n/100][cant_n%100]<=-1) ||
				(sens_n>0 && canton_inverse*train.cons_sans_correction[train_n]>=1)         || (sens_n<0 && canton_inverse*train.cons_sans_correction[train_n]<=-1)) {
				// Pour le canton en cours de traitement, on a trouvé qu'il est un canton principal en conduite manuelle (<>-1) et qui est occupé (==1).
				// et que son sens de parcours est celui pouvant être bloqué.
				// On a testé aussi 'cons_sans_correction[train_n]' car un train peut être arrété sur un canton car '#balauto' +'cant:' lui interdit d'avancer
				// On teste la valeur du potentiomètre ou du clavier, comme cela la situation se débloque.
				action1_n = 1;													// Par défaut action = 1 si rien n'est déclaré dans 'plusur:'
				// Test de la directive 'plusur:'.
				for(j=0;j<BALAUTO_CANT_NB_MAX_CANT;j++) {
					if (balauto_cant_tab[i][BALAUTO_CANT_TAB_IND_CANT_0_NO+j]==-1) break; // On arrive à la fin du tableau avec des valeurs.
					var_n=balauto_cant_tab[i][BALAUTO_CANT_TAB_IND_CANT_0_NO+j];			// var_n = n° du canton à tester si CE n° de train est dessus.
					if (canton.master_selectif[var_n/100][var_n%100]==1 && vio_det[var_n/100][var_n%100]!=0 && train_n==canton.num_train[var_n/100][var_n%100]) {
						// Pour le canton en cours de traitement, on a trouvé les autres cantons vides ou avec ce même train dessus.
						// CE train est encore sur UN des cantons précédents => On ne fait donc pas les actions.
						action1_n=0; break;
					}
				}
				action2_n=1;
				// action_n=1 => La directive 'plusur:' est valide, On passe aux tests 'blocage:' = Blocage du train si un groupe de conditions est vérifié.
				for(j=0;j<BALAUTO_CANT_NB_MAX_VAR;j++) {
					if (balauto_cant_tab[i][BALAUTO_CANT_TAB_IND_VAR_0+j]==-1) break;	// On arrive à la fin du tableau avec des valeurs.
					var_n=balauto_cant_tab[i][BALAUTO_CANT_TAB_IND_VAR_0+j];			// var_n = n° de la variable à tester.
					val_n=balauto_cant_tab[i][BALAUTO_CANT_TAB_IND_VAL_0+j];			// val_n = valeur à vérifier.
					if (var_n==EQ_BASE+EQ_O && action2_n==1) break;  // == '|' => Fin d'un groupe de test et conditions déjà réunies dans ce groupe pour le blocage.
					if (var_n==EQ_BASE+EQ_O) { 
						action2_n=1; // == '|' => On réinitialise la variable temporaire pour vérifier les conditions pour ce nouveau groupe de test.
					}
					else if (action2_n!=0) { // Si action2 = 0, le test ne passe déjà pas, ce n'est pas la peine de tester les autres variables du groupe.
						if (var_n>=0 && var_n<(300+NB_CANTON) && (var_n%100)<NB_CANTON) {
							// Pour 'BALAUTO'+'cant:', dans 'blocage:' on traite une variable de type 'det_xx.1'.
							// il ne faut pas bloquer si c'est le même n° de train déjà dessus.
							if (pio_get_val(var_n)==1) action2_n=1; // Par principe on bloque si le canton suivant est occupé.
							else action2_n=0;
							// Ici action2_n = 0 ou 1 !
							if (train_n==canton.num_train[var_n/100][var_n%100]) {
								action2_n=0; // Finalement, on ne bloque pas car c'est le même train.
							}
							else {
								// Si le prochain canton n'est pas prévu pour ce même train, on vérifie si il est déjà réservé en manuel ou automatique.
								// Test pour savoir si le canton où va le train (det_xx) est Res_Auto , Master_Selectif ou Update_Selectif.
								if (canton.res_auto[var_n/100][var_n%100]==1 || canton.master_selectif[var_n/100][var_n%100]==1 || 
									canton.update_selectif[var_n/100][var_n%100]==1) action2_n=1; // On bloque si le canton est déjà réservé.
								}
							}
						else { // Ici, 'action2_n' vaut toujours '1' en entrée de test => Blocage si l'on ne change pas sa valeur.
							if (var_n>=5100 && var_n<5100+NB_AIG) { // pos0_aig_xxx 
								// Si l'aiguillage est en mouvement, la condition sera toujours valide pour bloquer le train.
								if (pio_get_val(var_n)==1 || pio_get_val(var_n+100)==1) {
									if (pio_get_val(var_n)!=val_n) action2_n=0;
								}
							}
							else if (var_n>=5200 && var_n<5200+NB_AIG) { // pos1_aig_xxx 
								// Si l'aiguillage est en mouvement, la condition sera toujours valide pour bloquer le train.
								if (pio_get_val(var_n)==1 || pio_get_val(var_n-100)==1) {
									if (pio_get_val(var_n)!=val_n) action2_n=0;
								}
							}
							// Pour 'BALAUTO'+'cant:'+'blocage:', on traite les autres cas que 'det_xx.1', 'pos0_aig_xxx' et 'pos1_aig_xxx'.								
							else if (pio_get_val(var_n)!=val_n) action2_n=0;  // On ne sort pas, car il y a peut d'être d'autres groupe de condition à traiter.
						}
					}	
				}	
				// action2_n=1 at action1_n=0 => Ralentissement.
				// action2_n=1 et action1_n=1 => Blocage.
				if (action2_n==1) { 
					if (action1_n==1) { 
						// Les directives 'plusur:' et 'blocage:' sont valides => Consigne du train = 0.
						balauto_cant_tab[i][BALAUTO_CANT_TAB_IND_ACTION_OK]=2; // =2 => Blocage 
						balauto_cant_train[train_n]=2; // =2 => Train bloqué. Sert dans Train::maj()
						balauto_cant_train_dec[train_n]=balauto_cant_tab[i][BALAUTO_CANT_TAB_IND_DEC]; // -1 ou 1 à 28 = Décélération de 'cant:'.
						if (sens_n>0) vio_bal_cant_p[cant_n/100][cant_n%100]=1; // Renseigne les variables de type 'bal_cant_p_xxx'=1 => BAL Canton bloqué dans le sens Plus.
						if (sens_n<0) vio_bal_cant_m[cant_n/100][cant_n%100]=1; // Renseigne les variables de type 'bal_cant_m_xxx'=1 => BAL Canton bloqué dans le sens Moins.
					}
					else {
						// Uniquement la directive 'blocage:' est valide => Consigne du train = ral:xx.
						if (balauto_cant_tab[i][BALAUTO_CANT_TAB_IND_RAL]!=-1) { // Si il existe une consigne de ralentissement 'ral:'
							balauto_cant_tab[i][BALAUTO_CANT_TAB_IND_ACTION_OK]=1; // =1 => ralenti.
							balauto_cant_train[train_n]=1; // =1 => Train ralenti. Sert dans Train::maj()
							balauto_cant_train_dec[train_n]=balauto_cant_tab[i][BALAUTO_CANT_TAB_IND_DEC]; // -1 ou 1 à 28 = Décélération de 'cant:'.
							balauto_cant_train_ral[train_n]=balauto_cant_tab[i][BALAUTO_CANT_TAB_IND_CANT_SENS]*balauto_cant_tab[i][BALAUTO_CANT_TAB_IND_RAL]; // -64 à +64
						}
					}
				}
			}
		}
		else {
			if (sens_n>0) vio_bal_cant_p[cant_n/100][cant_n%100]=0; // Renseigne les variables de type 'bal_cant_p_xxx'=1 => BAL Canton bloqué dans le sens Plus.
			else          vio_bal_cant_m[cant_n/100][cant_n%100]=0; // Renseigne les variables de type 'bal_cant_m_xxx'=1 => BAL Canton bloqué dans le sens Moins.
		}
	}
}


//
// Affiche les tableaux '#balauto' = 'vitmax:'
//
void cBalauto::debug_vitmax(int action)
{
	int i, j;
	char ch[200], ch2[25], ch3[25];	// ch[25] pour contenir 'garage_lock_status_0'+ '/0'
	static int balauto_vm_deb=0;
	static int dimnx=44;    // Dimension horizontal d'une cellule 'Numéro'
	static int dimcx=68;    // Dimension horizontal d'une cellule 'Cantons'
	static int dimli=350;   // Dimension horizontal d'une cellule 'Libé' min=229
	static int dimy=16;     // Dimension vertical d'une cellule
	static int nblignes=32; // Nombre de ligne du tableau (sans le titre)	
	static int decaly=16;   // Decalage de la premiére ligne vers le bas.
  
	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);
		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);
		Rectangle(hMemDC, 0, decaly,  800, decaly+dimy+1);
		EasyLine(dimnx,                 decaly, dimnx,                 decaly+dimy);
		EasyLine(dimnx+dimcx,           decaly, dimnx+dimcx,           decaly+dimy);
		bmp_SetTextColor(BMP_CST_COLOR_NOIR);			// Texte en noir.
		EasyTextOut(2,2,"AFFICHE LES VALEURS DU TABLEAU INTERNE  '#balauto'+'vitmax:'  (60 maximum)"); EasyTextOut(800-140,2,"(QUITTER = ESC)");
		EasyTextOut(2,decaly+(nblignes+2)*dimy+1,"Section '#balauto'+'vitmax:'");
		SelectObject(hMemDC,bmp_stylo_noir); SelectObject(hMemDC,bmp_pinceau_gris220); // Rectangle gris foncé.
		Rectangle(hMemDC,0,decaly+(nblignes+3)*dimy-1, 97, decaly+(nblignes+4)*dimy+1);
		SelectObject(hMemDC,bmp_stylo_gris128);
		EasyLine(1,  decaly+(nblignes+4)*dimy+1-2, 96, decaly+(nblignes+4)*dimy+1-2);  	// Relief rectangle.
		EasyLine(95, decaly+(nblignes+3)*dimy-1+1, 95, decaly+(nblignes+4)*dimy+1-2);	// Relief rectangle.
		SelectObject(hMemDC,bmp_stylo_noir);
		EasyLine(97-10, decaly+(nblignes+4)*dimy-1, 97, decaly+(nblignes+4)*dimy+1-12);  // Dessine un trait dans l'angle = valeurs modifiables.
		SelectObject(hMemDC,bmp_pinceau_blanc); SelectObject(hMemDC,bmp_stylo_gris192);
		EasyTextOut(2,decaly+(nblignes+3)*dimy+1," CLIC-DROIT :AFFICHE LES PAGES 1<->2, [00-32]<->[32-59]");
		EasyTextOut(2,decaly+(nblignes+4)*dimy,"Permet de limiter la vitesse manuelle des trains par canton.  (Vi=Vitesse maxi)");
		EasyTextOut(2,decaly+(nblignes+5)*dimy,"Limitation en fonction du sens de parcours et des conditions.");

		SelectObject(hMemDC,bmp_pinceau_jaune); // Rectangle jaune.
		Rectangle(hMemDC, 0, -2+decaly+(nblignes+6)*dimy,96,-1+decaly+(nblignes+7)*dimy);
		SelectObject(hMemDC,bmp_pinceau_blanc);
		EasyTextOut(2,decaly+(nblignes+6)*dimy,"LIGNE JAUNE = Canton (Train) limité en vitesse.");
		
		bmp_SetTextColor(BMP_CST_COLOR_ROUGE);			// Texte en rouge.
		EasyTextOut(2,                     2+decaly,"  n°");		// Indice 'i' du tableau : descr[i][].
		EasyTextOut(2+dimnx,               2+decaly,"Cant+-Vi");	//
		EasyTextOut(2+dimnx+dimcx+0*dimli, 2+decaly,"Conditions à vérifier");			// 
	}

	if(action==DEBUG_MOUSE) {	// ACTION = CLIC GAUCHE DE LA SOURIS
		if ((x_mouse > 0 && x_mouse < 97) && (y_mouse > decaly+(nblignes+3)*dimy-1 && y_mouse < decaly+(nblignes+4)*dimy+1)) { //	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.
			}
		}
	}

	if(action==DEBUG_MOUSE_RIGHT) {   // ACTION = CLIC DROIT DE LA SOURIS, 
		switch(balauto_vm_deb/nblignes) {
			case 0 : { screen_mode= MD_ECRAN_VITMAX2; break;}
			case 1 : { screen_mode= MD_ECRAN_VITMAX1; break;}
			default: break;
		}
	}

	if (screen_mode==MD_ECRAN_VITMAX1) balauto_vm_deb= 0;	// Valeur de la premiere ligne à afficher.
	if (screen_mode==MD_ECRAN_VITMAX2) balauto_vm_deb=   nblignes;
	
	if(action==DEBUG_KEY) { }   // ACTION = TOUCHE ENFONCEE, rien

	SelectObject(hMemDC,bmp_pinceau_blanc); SelectObject(hMemDC,bmp_stylo_blanc);
	Rectangle(hMemDC,1, dimy+decaly, 799, (nblignes+1)*dimy+decaly+1);
	SelectObject(hMemDC,bmp_pinceau_blanc); SelectObject(hMemDC,bmp_stylo_gris192);

	bmp_SetTextColor(BMP_CST_COLOR_BLEUF);			// Texte en bleu foncé.
	for(i=0;i<nblignes;i++) {
		if(balauto_vm_deb+i<BALAUTO_VITMAX_NB) {
			sprintf_s(ch,"%3d",balauto_vm_deb+i);
			if (balauto_vitmax_tab[balauto_vm_deb+i][BALAUTO_VITMAX_TAB_IND_ACTION_OK]==1) SelectObject(hMemDC,bmp_pinceau_jaune); // Ligne jaune si action activée.
			else SelectObject(hMemDC,bmp_pinceau_blanc);
			Rectangle(hMemDC, 0, dimy*(i+2), 800, dimy*(i+3)+1);
			EasyLine(dimnx,                 dimy*(i+2), dimnx,                 dimy*(i+3)+1);
			EasyLine(dimnx+dimcx,           dimy*(i+2), dimnx+dimcx,           dimy*(i+3)+1);
			if(balauto_vitmax_tab[balauto_vm_deb+i][BALAUTO_VITMAX_TAB_IND_CANT_NO]==-1) bmp_SetTextColor(BMP_CST_COLOR_GRIS192); // Texte en gris 192.
			EasyTextOut(10,2+dimy*(i+2),ch);			// N° d'indice du tableau
			bmp_SetTextColor(BMP_CST_COLOR_BLEUF);			// Texte en bleu foncé.
			if(balauto_vitmax_tab[balauto_vm_deb+i][BALAUTO_VITMAX_TAB_IND_CANT_NO]!=-1) {  // Elément valide ?
				// Affiche c10 +30 = n° Canton +-Vitesse
				sprintf_s(ch,"c%-2d %3d",balauto_vitmax_tab[balauto_vm_deb+i][BALAUTO_VITMAX_TAB_IND_CANT_NO],balauto_vitmax_tab[balauto_vm_deb+i][BALAUTO_VITMAX_TAB_IND_CANT_VIT]);
				EasyTextOut(2+dimnx+3,2+dimy*(i+2),ch);
				// Affiche var_1=1 det_13=0 = Liste des conditions devant être réalisées.
				sprintf_s(ch,"");
				for (j=0;j<BALAUTO_VITMAX_NB_MAX_VAR;j++) {
					if (balauto_vitmax_tab[balauto_vm_deb+i][BALAUTO_VITMAX_TAB_IND_VAR_0+j]==-1) break ;
					pio_var_int2ch(balauto_vitmax_tab[balauto_vm_deb+i][BALAUTO_VITMAX_TAB_IND_VAR_0+j],ch2);
					// On va réduire la taille de la ligne, on va convertir "posY_aig_X = 1" en "aX = Y".
					if (STR_SAME strncmp(ch2,"pos0_aig_",8)) {
						sprintf_s(ch3,"a%s=0  ",&ch2[9]); strcpy(ch2,ch3); strcat(ch,ch2);
					}
					else if (STR_SAME strncmp(ch2,"pos1_aig_",8)) {
						sprintf_s(ch3,"a%s=1  ",&ch2[9]); strcpy(ch2,ch3); strcat(ch,ch2);
					}
					else {
						strcat(ch,ch2);
						if (balauto_vitmax_tab[balauto_vm_deb+i][BALAUTO_VITMAX_TAB_IND_VAL_0+j]==0) strcat(ch,"=0  ");
						if (balauto_vitmax_tab[balauto_vm_deb+i][BALAUTO_VITMAX_TAB_IND_VAL_0+j]==1) strcat(ch,"=1  ");
					}
				}
				EasyTextOut(2+dimnx+dimcx+3,2+dimy*(i+2),ch);				//
			}
		} 
		else {
			Rectangle(hMemDC, 0, dimy*(i+2), 800, dimy*(i+3)+1);
			EasyLine(dimnx,                 dimy*(i+2), dimnx,                 dimy*(i+3)+1);
			EasyLine(dimnx+dimcx,           dimy*(i+2), dimnx+dimcx,           dimy*(i+3)+1);
		}
	}
}

//
// Affiche les tableaux '#balauto' + 'halt:'
//
void cBalauto::debug_halt(int action)
{
	int i, j;
	char ch[200], ch2[25], ch3[25];	// ch[25] pour contenir 'garage_lock_status_0'+ '/0'
	static int balauto_h_deb=0;
	static int dimnx=44;    // Dimension horizontal d'une cellule 'Numéro'
	static int dimcx=68;    // Dimension horizontal d'une cellule 'Cantons'
	static int dimli=350;   // Dimension horizontal d'une cellule 'Libé' min=229
	static int dimy=16;     // Dimension vertical d'une cellule
	static int nblignes=32; // Nombre de ligne du tableau (sans le titre)	
	static int decaly=16;   // Decalage de la premiére ligne vers le bas.
  
	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);
		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);
		Rectangle(hMemDC, 0, decaly, 800, decaly+dimy+1);
		EasyLine(dimnx,                 decaly, dimnx,                 decaly+dimy);
		EasyLine(dimnx+dimcx,           decaly, dimnx+dimcx,           decaly+dimy);
		bmp_SetTextColor(BMP_CST_COLOR_NOIR);			// Texte en noir.
		EasyTextOut(2,2,"AFFICHE LES VALEURS DU TABLEAU INTERNE  '#balauto'+'halt:'  (60 éléments maximum)"); EasyTextOut(800-140,2,"(QUITTER = ESC)");
		EasyTextOut(2,decaly+(nblignes+2)*dimy+1,"Section '#balauto'+'halt:'");
		SelectObject(hMemDC,bmp_stylo_noir); SelectObject(hMemDC,bmp_pinceau_gris220); // Rectangle gris foncé.
		Rectangle(hMemDC,0,decaly+(nblignes+3)*dimy-1, 97, decaly+(nblignes+4)*dimy+1);
		SelectObject(hMemDC,bmp_stylo_gris128);
		EasyLine(1,  decaly+(nblignes+4)*dimy+1-2, 96, decaly+(nblignes+4)*dimy+1-2);  	// Relief rectangle.
		EasyLine(95, decaly+(nblignes+3)*dimy-1+1, 95, decaly+(nblignes+4)*dimy+1-2);	// Relief rectangle.
		SelectObject(hMemDC,bmp_stylo_noir);
		EasyLine(97-10, decaly+(nblignes+4)*dimy-1, 97, decaly+(nblignes+4)*dimy+1-12);  // Dessine un trait dans l'angle = valeurs modifiables.
		SelectObject(hMemDC,bmp_pinceau_blanc); SelectObject(hMemDC,bmp_stylo_gris192);
		EasyTextOut(2,decaly+(nblignes+3)*dimy+1," CLIC-DROIT :AFFICHE LES PAGES 1<->2, [00-32]<->[32-59]");
		EasyTextOut(2,decaly+(nblignes+4)*dimy,"Permet de stopper un train pour éviter qu'il sorte du canton ou arrive en fin de voie.");
		EasyTextOut(2,decaly+(nblignes+5)*dimy,"Arrêt immédiat en fonction du sens de parcours et des conditions  (Vi =sens).");

		SelectObject(hMemDC,bmp_pinceau_orange); // Rectangle orange.
		Rectangle(hMemDC, 0, -2+decaly+(nblignes+6)*dimy,103,-1+decaly+(nblignes+7)*dimy);
		SelectObject(hMemDC,bmp_pinceau_blanc);
		EasyTextOut(2,decaly+(nblignes+6)*dimy,"LIGNE ORANGE = Canton (Train) en halte.");

		bmp_SetTextColor(BMP_CST_COLOR_ROUGE);			// Texte en rouge.
		if (cmd_divers[CMD_DIVERS_OPT5_HALTE]==1) EasyTextOut(2,decaly+(nblignes+7)*dimy,"La fonction 'HALTE:' est INHIBE depuis le bloc 'HLT' du TCO.");
		EasyTextOut(2,                     2+decaly,"  n°");		// Indice 'i' du tableau : descr[i][].
		EasyTextOut(2+dimnx,               2+decaly,"Cant+-Vi");	//
		EasyTextOut(2+dimnx+dimcx+0*dimli, 2+decaly,"Conditions à vérifier");			// 
	}

	if (action==DEBUG_MOUSE) {	// ACTION = CLIC GAUCHE DE LA SOURIS
		if ((x_mouse > 0 && x_mouse < 97) && (y_mouse > decaly+(nblignes+3)*dimy-1 && y_mouse < decaly+(nblignes+4)*dimy+1)) { //	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.
			}
		}
	}


	if(action==DEBUG_MOUSE_RIGHT) {   // ACTION = CLIC DROIT DE LA SOURIS, 
		switch(balauto_h_deb/nblignes) {
			case 0 : { screen_mode= MD_ECRAN_HALTE2; break;}
			case 1 : { screen_mode= MD_ECRAN_HALTE1; break;}
			default: break;
		}
	}

	if (screen_mode==MD_ECRAN_HALTE1) balauto_h_deb= 0;	// Valeur de la premiere ligne à afficher.
	if (screen_mode==MD_ECRAN_HALTE2) balauto_h_deb=   nblignes;

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

	SelectObject(hMemDC,bmp_pinceau_blanc); SelectObject(hMemDC,bmp_stylo_blanc);
	Rectangle(hMemDC,1, dimy+decaly, 799, (nblignes+1)*dimy+decaly+1);
	SelectObject(hMemDC,bmp_stylo_gris192);

	bmp_SetTextColor(BMP_CST_COLOR_BLEUF);			// Texte en bleu foncé.
	for(i=0;i<nblignes;i++) {
		if(balauto_h_deb+i<BALAUTO_HALT_NB) {
			sprintf_s(ch,"%3d",balauto_h_deb+i);
			if (balauto_halt_tab[balauto_h_deb+i][BALAUTO_HALT_TAB_IND_ACTION_OK]==1) SelectObject(hMemDC,bmp_pinceau_orange); // Ligne orange si action activée.
			else SelectObject(hMemDC,bmp_pinceau_blanc);
			Rectangle(hMemDC, 0, dimy*(i+2), 800, dimy*(i+3)+1);
			EasyLine(dimnx,       dimy*(i+2), dimnx,       dimy*(i+3)+1);
			EasyLine(dimnx+dimcx, dimy*(i+2), dimnx+dimcx, dimy*(i+3)+1);
			if(balauto_halt_tab[balauto_h_deb+i][BALAUTO_HALT_TAB_IND_CANT_NO]==-1) bmp_SetTextColor(BMP_CST_COLOR_GRIS192);			// Texte en gris 192
			EasyTextOut(10,2+dimy*(i+2),ch);			// N° d'indice du tableau
			bmp_SetTextColor(BMP_CST_COLOR_BLEUF);			// Texte en bleu foncé.
			if(balauto_halt_tab[balauto_h_deb+i][BALAUTO_HALT_TAB_IND_CANT_NO]!=-1) {  // Elément valide ?
				// Affiche c10 + = n° Canton +-Sens
				sprintf_s(ch,"c%-2d ",balauto_halt_tab[balauto_h_deb+i][BALAUTO_HALT_TAB_IND_CANT_NO]);
				if (balauto_halt_tab[balauto_h_deb+i][BALAUTO_HALT_TAB_IND_CANT_SENS]==1) strcat(ch," +");
				else  strcat(ch," -");
				EasyTextOut(2+dimnx+3,2+dimy*(i+2),ch);
				// Affiche var_1=1 det_13=0 = Liste des conditions devant être réalisées.
				sprintf_s(ch,"");
				for (j=0;j<BALAUTO_HALT_NB_MAX_VAR;j++) {
					if (balauto_halt_tab[balauto_h_deb+i][BALAUTO_HALT_TAB_IND_VAR_0+j]==-1) break ;
					pio_var_int2ch(balauto_halt_tab[balauto_h_deb+i][BALAUTO_HALT_TAB_IND_VAR_0+j],ch2);
					// On va réduire la taille de la ligne, on va convertir "posY_aig_X = 1" en "aX = Y".
					if (STR_SAME strncmp(ch2,"pos0_aig_",8)) {
						sprintf_s(ch3,"a%s=0  ",&ch2[9]); strcpy(ch2,ch3); strcat(ch,ch2);
					}
					else if (STR_SAME strncmp(ch2,"pos1_aig_",8)) {
						sprintf_s(ch3,"a%s=1  ",&ch2[9]); strcpy(ch2,ch3); strcat(ch,ch2);
					}
					else {
						strcat(ch,ch2);
						if (balauto_halt_tab[balauto_h_deb+i][BALAUTO_HALT_TAB_IND_VAL_0+j]==0) strcat(ch,"=0  ");
						if (balauto_halt_tab[balauto_h_deb+i][BALAUTO_HALT_TAB_IND_VAL_0+j]==1) strcat(ch,"=1  ");
					}
				}
				EasyTextOut(2+dimnx+dimcx+3,2+dimy*(i+2),ch);				//
			}
		} 
		else {
			Rectangle(hMemDC, 0, dimy*(i+2), 800, dimy*(i+3)+1);
			EasyLine(dimnx,       dimy*(i+2), dimnx,       dimy*(i+3)+1);
			EasyLine(dimnx+dimcx, dimy*(i+2), dimnx+dimcx, dimy*(i+3)+1);
		}
	}
}

//
// Affiche les tableaux '#balauto'+'cant:'.
// Liste des cantons bloqués.
//
void cBalauto::debug_cant(int action)
{
	int i, j;
	char ch[200], ch2[25], ch3[25];	// ch[25] pour contenir 'garage_lock_status_0'+ '/0'
	static int balauto_bal_deb=0;
	static int dimnx=44;    // Dimension horizontal d'une cellule 'Numéro'
	static int dimcx=68;    // Dimension horizontal d'une cellule 'Cantons'
	static int demidimcx=34;// Dimension horizontal d'une demi cellule 'Cantons'
	static int dimli=350;   // Dimension horizontal d'une cellule 'Libé' min=229
	static int dimy=16;     // Dimension vertical d'une cellule
	static int nblignes=32; // Nombre de ligne du tableau (sans le titre)	
	static int decaly=16;   //Decalage de la premiére ligne vers les bas.

	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,1100,700);
		SelectObject(hMemDC,bmp_pinceau_gris192); SelectObject(hMemDC,bmp_stylo_gris192); Rectangle(hMemDC,1100-15,15,1100-2,2); // Rectangle gris pour fermer la fenêtre.
		SelectObject(hMemDC,bmp_stylo_noir); EasyLine(1100-14,3,1100-3,14 ); EasyLine(1100-14,13,1100-3,2); // Croix noire.
		SelectObject(hMemDC,bmp_stylo_noir);  EasyLine(1100-2,1,1100-2,16); EasyLine(1100-16,15,1100-1,15); // Trait noir.
		SelectObject(hMemDC,bmp_stylo_gris128); EasyLine(1100-3,2,1100-3,15); EasyLine(1100-15,14,1100-2,14); // Trait gris foncé.
		SelectObject(hMemDC,bmp_pinceau_blanc); SelectObject(hMemDC,bmp_stylo_gris192);
		Rectangle(hMemDC, 0, decaly, 1100, decaly+dimy+1);
		EasyLine(dimnx,                 decaly, dimnx,                 decaly+dimy);
		EasyLine(dimnx+dimcx,           decaly, dimnx+dimcx,           decaly+dimy);
		EasyLine(dimnx+dimcx+demidimcx, decaly, dimnx+dimcx+demidimcx, decaly+dimy);
		EasyLine(dimnx+2*dimcx,         decaly, dimnx+2*dimcx,         decaly+dimy);
		EasyLine(dimnx+dimcx+demidimcx+dimli-99, decaly, dimnx+dimcx+demidimcx+dimli-99, decaly+dimy);
		bmp_SetTextColor(BMP_CST_COLOR_NOIR);			// Texte en noir.
		EasyTextOut(2,2,"AFFICHE LES VALEURS DU TABLEAU INTERNE '#balauto'+'cant:'      (100 lignes maximum)"); EasyTextOut(1100-140,2,"(QUITTER = ESC)");
		EasyTextOut(2,decaly+(nblignes+1)*dimy,"Section '#balauto'+'cant:'");
		SelectObject(hMemDC,bmp_stylo_noir); SelectObject(hMemDC,bmp_pinceau_gris220); // Rectangle gris foncé.
		Rectangle(hMemDC,0,decaly+(nblignes+2)*dimy-2, 97, decaly+(nblignes+3)*dimy);
		SelectObject(hMemDC,bmp_stylo_gris128);
		EasyLine(1,  decaly+(nblignes+3)*dimy-2, 96, decaly+(nblignes+3)*dimy-2);  	// Relief rectangle
		EasyLine(95, decaly+(nblignes+2)*dimy-2+1, 95, decaly+(nblignes+3)*dimy-2);	// Relief rectangle.
		SelectObject(hMemDC,bmp_stylo_noir);
		EasyLine(97-10, decaly+(nblignes+3)*dimy-2, 97, decaly+(nblignes+3)*dimy-12);  // Dessine un trait dans l'angle = valeurs modifiables.
		SelectObject(hMemDC,bmp_pinceau_blanc); SelectObject(hMemDC,bmp_stylo_gris192);
		EasyTextOut(2,decaly+(nblignes+2)*dimy," CLIC-DROIT :AFFICHE LES PAGES 1->2->3, [00-31]->[32-63]->[64-95]");
		EasyTextOut(2,decaly+(nblignes+3)*dimy,"Simulation d'un bloc automatique pour les trains en conduite manuelle.");
		EasyTextOut(2,decaly+(nblignes+4)*dimy,"Arrête un train sur un canton si les conditions de sortie du canton = nok. (Vi =sens)");
		EasyTextOut(2,decaly+(nblignes+5)*dimy,"Colone 'Ral:' Vitesse de ralenti si les conditions de blocage = OK, mais le train encore sur les cantons précédents.");
		EasyTextOut(2,decaly+(nblignes+6)*dimy,"Colone 'Dec:' Décélération = Inertie pour ralentir le train, à moins que celle du train soit plus faible.");
		EasyTextOut(2,decaly+(nblignes+7)*dimy,"Colone 'CE train plus sur..' Ce train ne doit plus être sur ces cantons, pour enfin bloquer ce train.");
		EasyTextOut(2,decaly+(nblignes+8)*dimy,"Colonne des variables qui doivent être à l'état indiqué, pour bloquer le train ('|' = ou) (L'affichage est ici limité à 85 car.).");

		SelectObject(hMemDC,bmp_pinceau_orange); // Rectangle orange.
		Rectangle(hMemDC,  0, -2+decaly+(nblignes+9)*dimy,103,-1+decaly+(nblignes+10)*dimy);
		SelectObject(hMemDC,bmp_pinceau_jaune); // Rectangle jaune.
		Rectangle(hMemDC,230, -2+decaly+(nblignes+9)*dimy,327,-1+decaly+(nblignes+10)*dimy);
		SelectObject(hMemDC,bmp_pinceau_blanc);
		EasyTextOut(2,decaly+(nblignes+9)*dimy,"LIGNE ORANGE = Train bloqué, LIGNE JAUNE = Train ralenti. ");

		EasyTextOut(400, decaly + (nblignes + 1)*dimy, "Temporisation '#balauto'+'tempo_libe_cant:'");
		bmp_SetTextColor(BMP_CST_COLOR_BLEUF);			// Texte en bleu.
		sprintf_s(ch,"= %d => %d sec",cfg_tempo_libe_cant,cfg_tempo_libe_cant/10); 
		EasyTextOut(400+350,decaly+(nblignes+1)*dimy,ch);

		bmp_SetTextColor(BMP_CST_COLOR_ROUGE);			// Texte des titres de colonnes en rouge.
		EasyTextOut(2,                       2+decaly,"  n°");		// Indice 'i' du tableau : descr[i][].
		EasyTextOut(2+dimnx,                 2+decaly,"Cant+-Vi");	//
		EasyTextOut(2+dimnx+dimcx,           2+decaly,"Ral:");	// 
		EasyTextOut(2+dimnx+dimcx+demidimcx, 2+decaly,"Dec:");	// 
		EasyTextOut(2+dimnx+2*dimcx,         2+decaly,"CE train plus sur cantons");	// 
		EasyTextOut(2+dimnx+3*dimcx+dimli-99,2+decaly,"Conditions à vérifier");			// 
	}

	if (action==DEBUG_MOUSE) {	// ACTION = CLIC GAUCHE DE LA SOURIS
		if ((x_mouse > 0 && x_mouse < 97) && (y_mouse > decaly+(nblignes+2)*dimy-2 && y_mouse < decaly+(nblignes+3)*dimy)) { //	Clique dans [CLIC DROIT]
			action=DEBUG_MOUSE_RIGHT; //	Simule le clique-droit traité plus loin.
		}
		else {
			if ((x_mouse > 1100-15 && x_mouse < 1100-2) && (y_mouse > 2 && y_mouse < 15)) {
				screen_mode= screen_mode_retour; 
				return;	// On ferme la fenêtre.
			}
		}
	}


	if (action==DEBUG_MOUSE_RIGHT) {    // ACTION = CLIC DROIT DE LA SOURIS, on passe à la page suivante.
		switch(balauto_bal_deb/nblignes) {
			case 0 : { screen_mode= MD_ECRAN_BALAUTO2; break;}
			case 1 : { screen_mode= MD_ECRAN_BALAUTO3; break;}
			case 2 : { screen_mode= MD_ECRAN_BALAUTO1; break;}
			default: break;
		}
	}

	if (screen_mode==MD_ECRAN_BALAUTO1) balauto_bal_deb= 0;	// Valeur de la premiere ligne à afficher.
	if (screen_mode==MD_ECRAN_BALAUTO2) balauto_bal_deb=   nblignes;
	if (screen_mode==MD_ECRAN_BALAUTO3) balauto_bal_deb= 2*nblignes;

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

	bmp_SetTextColor(BMP_CST_COLOR_BLEUF);			// Texte en bleu foncé.
	for(i=0;i<nblignes;i++) {
		if (balauto_bal_deb+i<BALAUTO_CANT_NB) {
			sprintf_s(ch,"%3d",balauto_bal_deb+i);
			if (balauto_cant_tab[balauto_bal_deb+i][BALAUTO_CANT_TAB_IND_ACTION_OK]==1) SelectObject(hMemDC,bmp_pinceau_jaune); // =2 => Ligne jaune si ralenti activée.
			else if (balauto_cant_tab[balauto_bal_deb+i][BALAUTO_CANT_TAB_IND_ACTION_OK]==2) SelectObject(hMemDC,bmp_pinceau_orange); // =2 => Ligne orange si blocage activée.
			else SelectObject(hMemDC,bmp_pinceau_blanc);
			Rectangle(hMemDC, 0, dimy*(i+2), 1100, dimy*(i+3)+1);
			EasyLine(dimnx,                 dimy*(i+2), dimnx,                 dimy*(i+3)+1);
			EasyLine(dimnx+dimcx,           dimy*(i+2), dimnx+dimcx,           dimy*(i+3)+1);
			EasyLine(dimnx+dimcx+demidimcx, dimy*(i+2), dimnx+dimcx+demidimcx, dimy*(i+3)+1);
			EasyLine(dimnx+2*dimcx,         dimy*(i+2), dimnx+2*dimcx,         dimy*(i+3)+1);
			EasyLine(dimnx+dimcx+demidimcx+dimli-99, dimy*(i+2), dimnx+dimcx+demidimcx+dimli-99, dimy*(i+3)+1);
			if(balauto_cant_tab[balauto_bal_deb+i][BALAUTO_CANT_TAB_IND_CANT_NO]==-1) bmp_SetTextColor(BMP_CST_COLOR_GRIS192); // Texte en gris 192
			EasyTextOut(10,2+dimy*(i+2),ch);			// N° d'indice du tableau
			bmp_SetTextColor(BMP_CST_COLOR_BLEUF);			// Texte en bleu foncé.
			if(balauto_cant_tab[balauto_bal_deb+i][BALAUTO_CANT_TAB_IND_CANT_NO]!=-1) {  // Elément valide ?
				// Affiche c10 + = n° Canton +- Sens
				sprintf_s(ch,"c%-2d ",balauto_cant_tab[balauto_bal_deb+i][BALAUTO_CANT_TAB_IND_CANT_NO]);
				if (balauto_cant_tab[balauto_bal_deb+i][BALAUTO_CANT_TAB_IND_CANT_SENS]==1) strcat(ch," +");
				else  strcat(ch," -");
				EasyTextOut(2+dimnx+6,2+dimy*(i+2),ch);
				if (balauto_cant_tab[balauto_bal_deb+i][BALAUTO_CANT_TAB_IND_RAL]!=-1) { // Colonne 'ral:' Vitesse de ralenti 1 à 64.
					sprintf_s(ch,"%2d",balauto_cant_tab[balauto_bal_deb+i][BALAUTO_CANT_TAB_IND_RAL]);
					EasyTextOut(2+dimnx+dimcx+6,2+dimy*(i+2),ch);
				}
				if (balauto_cant_tab[balauto_bal_deb+i][BALAUTO_CANT_TAB_IND_DEC]!=-1) { // Colonne 'dec:' Inertie = 1 à 28. 
					sprintf_s(ch,"%2d",balauto_cant_tab[balauto_bal_deb+i][BALAUTO_CANT_TAB_IND_DEC]);
					EasyTextOut(2+dimnx+dimcx+demidimcx+6,2+dimy*(i+2),ch);
				}
				// Affiche c15.0 c12.1 c15.1 = Cantons devant être libérés par CE train + Le canton doit être .1 = occupé, .0 = libre.
				sprintf_s(ch,"");
				for (j=0;j<BALAUTO_CANT_NB_MAX_CANT;j++) {   
					if (balauto_cant_tab[balauto_bal_deb+i][BALAUTO_CANT_TAB_IND_CANT_0_NO+j]==-1) break;
					sprintf_s(ch2,"c%d  ",balauto_cant_tab[balauto_bal_deb+i][BALAUTO_CANT_TAB_IND_CANT_0_NO+j]);
					strcat(ch,ch2);
				}
				EasyTextOut(2+dimnx+2*dimcx+3,2+dimy*(i+2),ch);	// affiche le texte sur les conditions
				// Affiche var_1=1 det_13=0 = Liste des conditions devant être réalisées.
				sprintf_s(ch,"");
				for (j=0;j<BALAUTO_CANT_NB_MAX_VAR;j++) {
					if (balauto_cant_tab[balauto_bal_deb+i][BALAUTO_CANT_TAB_IND_VAR_0+j]==-1) break;
					if (balauto_cant_tab[balauto_bal_deb+i][BALAUTO_CANT_TAB_IND_VAR_0+j]==EQ_BASE+EQ_O) {
						strcat(ch,"| ");
					}
					else {
						pio_var_int2ch(balauto_cant_tab[balauto_bal_deb+i][BALAUTO_CANT_TAB_IND_VAR_0+j],ch2);
						// On va réduire la taille de la ligne, on va convertir "posY_aig_X = 1" en "aX = Y".
						if (STR_SAME strncmp(ch2,"pos0_aig_",9)) {
							sprintf_s(ch3,"a%s=0 ",&ch2[9]); strcpy(ch2,ch3); strcat(ch,ch2);
						}
						else if (STR_SAME strncmp(ch2,"pos1_aig_",9)) {
							sprintf_s(ch3,"a%s=1 ",&ch2[9]); strcpy(ch2,ch3); strcat(ch,ch2);
						}
						else {
							strcat(ch,ch2);
							if (balauto_cant_tab[balauto_bal_deb+i][BALAUTO_CANT_TAB_IND_VAL_0+j]==0) strcat(ch,"=0 ");
							if (balauto_cant_tab[balauto_bal_deb+i][BALAUTO_CANT_TAB_IND_VAL_0+j]==1) strcat(ch,"=1 ");
						}
					}
				}
				ch[84]='.'; ch[85]='.'; ch[86]='.'; ch[87]='\0'; // On coupe la ligne pour ne pas déborder du tableau.
				EasyTextOut(2+dimnx+dimcx+demidimcx+dimli-99+3,2+dimy*(i+2),ch);				// affiche le texte sur les conditions
			}
		} 
	}
}
/*****************************************************************************/
/* Fin BALAUTO                                                               */
/*****************************************************************************/
