// UTS 2000 - fichier 'iti.cpp' Lecture des variables pour la gestion des itinéraires dans le fichier de configuration, et gestion de ces itinéraires.
// V3.7e - Le 31/08/

/*****************************************************************************/
/* debut ITI                                                                 */
/*****************************************************************************/
#include  <windows.h>
#include  <string.h>
#include  <stdlib.h>
#include  <stdio.h>
#include  "Train_UTS.h"
#include  "iti.h"
#include  "canton.h"
#include  "garage.h"
#include  "train.h"

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

// Déclaration des classes externes
extern cCanton  canton;
extern cGarage  garage;
extern cTrain   train;

// 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);

// Déclaration des variables externes
extern HBRUSH  bmp_pinceau_blanc, bmp_pinceau_gris192, bmp_pinceau_gris220, bmp_pinceau_vert, bmp_pinceau_jaune, bmp_pinceau_cyan;
extern HDC     hMemDC;
extern HFONT   bmp_fonte;
extern HPEN    bmp_stylo_noir, bmp_stylo_gris128, bmp_stylo_gris192, bmp_stylo_blanc, bmp_stylo_rouge;

extern int moins_char_normal;   // 1: - est un caractere normal (comme 0)  0: - est un separateur (comme +)
extern int x_mouse,y_mouse,touche,touche_char,x_mouse_move,y_mouse_move, screen_mode_retour;
extern int screen_mode;

extern int vio_det[NB_CARTE][NB_CANTON];
extern int vio_srv_res[NB_CARTE][NB_SERVO];

extern int vio_srv_cmd[NB_CARTE][NB_SERVO+NB_SERVO_VIT];

extern int vio_aig_cmd[NB_AIG];
extern int vio_aig_res[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 vio_garage_lock_res[NB_GARAGE]; // 0 ou 1, 1 => Garage réservé.
extern int vio_garage_lock_cmd[NB_GARAGE]; // 0 ou 1, 1 => Demande d'isolation du garage (Sera réalisée si il a un train sur le canton).
extern int vio_garage_lock_status[NB_GARAGE]; // 0 ou 1, 1 => Le garage est isolé du canton (état réel).
extern int copy_garage_num_train[NB_GARAGE];
extern int train_pb_capt[NB_TRAIN];  // 0 ou 1, 1 => Le train n'est pas détecté sur les cantons.

char iti_name[ITI_TAB_NB][ITI_TAB_NAME_TAILLE]; 
int  iti_tab[ITI_TAB_NB][ITI_TAB_IND_TAILLE];

int  separe_tab[SEPARE_TAB_NB][SEPARE_TAB_IND_TAILLE];
int  regroupe_tab[REGROUPE_TAB_NB][REGROUPE_TAB_IND_TAILLE];

cIti iti;

int cIti::get_iti_line(FILE* pf, char ch_tab[][CHAR_CONFIG_NB], int* ch_nb)
{
    int ret;
    moins_char_normal=0;  // - is not a normal character (so it is parsed)
    ret=get_line(pf,ch_tab, ch_nb);
    moins_char_normal=1;
    return ret;
}

cIti::cIti(void) { }

char* iti_step_name[]={
//	"012345678901234567890123"
	"     -  .  -  .  -      ",			// "ITI_CST_STATE_IDLE"
	"EN ATTENTE LOCO SUR CANT",			// "ITI_CST_STATE_WAIT_CANT_DEP"
	" EN ATTENTE RÉSERVE AIG ",			// "ITI_CST_STATE_WAIT_RES"
	"EN ATTENTE POSITION AIG ",			// "ITI_CST_STATE_WAIT_VER"
	"EN ATTENTE LOCO CANT FIN",			// "ITI_CST_STATE_WAIT_CANT_FIN"
	"  EN ATTENTE FIN TEMPO  ",			// "ITI_CST_STATE_WAIT_WAIT"
	"   ITINÉRAIRE  ETABLI   ",			// "ITI_CST_STATE_WAIT_STOP"
	"       LIBÉRATION       " };		// "ITI_CST_STATE_RELEASE"


/* Plan de gestion des itinéraires.
IDLE                       En attente d'événement.
   |                         Si start manuel ou programmé.
WAIT_CANT_DEP              Si un canton de départ est spécifié, on attend qu'un train soit dessus.
  < >                        Si 'start:cx' est défini attend un train sur ce canton. Si pas de train -> WAIT_CANT_DEP
ITI_CST_STATE_WAIT_RES       On attend si un aiguillage est déjà reservé, qu'il se libére.
  < >                        Un aiguillage est déjà réservé -> ITI_CST_STATE_WAIT_RES
   |                         Renseigne le tableau avec la position désirée des aiguillages
ITI_CST_STATE_WAIT_VER       Demande de positionnement d'aiguillages.
  < >                         si il reste un aiguillage à positionner -> ITI_CST_STATE_WAIT_VER
ITI_CST_STATE_WAIT_CANT_FIN  Attend l'arrivé sur le canton d'arrivée 'stop:'
  < >                        Si 'stop:cx' n'est pas défini -> ITI_CST_STATE_WAIT_STOP
   |                         Arme une temporisation.
ITI_CST_STATE_WAIT_WAIT      Attend la fin de temporisation.
  < >                        Décremente la temporisation.  Si !=0 -> ITI_CST_STATE_WAIT_WAIT
ITI_CST_STATE_WAIT_STOP      Stop manuel.
   |                         Stop manuel
ITI_CST_STATE_RELEASE

*/
// Lecture dans le fichier 'config.txt' des paramètres pour la section 'itinéraires'.
//

//
// Lecture dans le fichier 'config.txt' des paramètres pour la section 'itinéraires'.
//
void cIti::init(char filename[])
{
    FILE* pf;
    char ch[CHAR_CONFIG_NB];
    char ch_tab[BLOC_CONFIG_NB][CHAR_CONFIG_NB];
    char ch_error[200];
    int  ch_nb, j, i, iti_verif, separe_verif, regroupe_verif, iti_no, separe_no, regroupe_no, aig_no;
//
    for (j=0; j<ITI_TAB_NB; j++) {
        for (i=0; i<ITI_TAB_IND_CANT_START; i++) iti_tab[j][i]=0;
        for (i=ITI_TAB_IND_CANT_START; i<ITI_TAB_IND_TAILLE; i++) iti_tab[j][i]=-1;
        iti_name[j][0]='\0';
    }
    for (j=0; j<SEPARE_TAB_NB; j++) {
        for (i=0; i<SEPARE_TAB_IND_TAILLE; i++) separe_tab[j][i]=-1;
    }
    for (j=0; j<REGROUPE_TAB_NB; j++) {
        for (i=0; i<REGROUPE_TAB_IND_TAILLE; i++) regroupe_tab[j][i]=-1;
    }

    if ((pf=fopen(filename,"rt"))==NULL) {
        MessageBox(NULL,"Impossible d'ouvrir le fichier de configuration des itinéraires 'Config.txt'","Erreur",MB_OK|MB_ICONERROR); exit(1);
    }

    //   iti19: onoff  a9.0 a1.1 a2.1       start c2 stop c7  @ V3  <--> U
    //   iti0:  direct a9.1 a4.0 a5.1      @ M   <--> U
	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,"#iti")) {
            fscanf(pf," %s",ch);				// Ignore le caractère '['
            while (get_iti_line(pf,ch_tab,&ch_nb)) {
                if (ch_nb>=CHAR_CONFIG_NB)	{
					MessageBox(NULL,"Le fichier config.txt comporte une ligne trop complexe dans la section '#iti","Erreur",MB_OK|MB_ICONERROR);
					MessageBox(NULL,"Section '#iti' (ligne>75 blocs) commençant par (taper sur entrée) : ","Erreur",MB_OK|MB_ICONERROR);
					strcpy(ch_error,"Section #iti 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 #iti
				for (i=0; i<ch_nb; i++) if (ch_tab[i][0]=='@') ch_nb=i;	// Supprime les commentaires
                iti_no=-1;
                i=0;
				iti_verif=0;
				separe_verif=0;
				regroupe_verif=0;
                while(i<ch_nb) {
					if ((ch_nb-i)>=2) {
						if ((iti_verif+separe_verif+regroupe_verif)==0 && (!strncmp(ch_tab[i],"iti",3)) && ch_tab[i+1][0]==':' ) {
	                        iti_no=atoi(&ch_tab[i][3]);
							if (iti_no>=0 && iti_no<ITI_TAB_NB) {	// N° d'itinéraire valide ?
								iti_tab[iti_no][ITI_TAB_IND_EXIST]=1;
								i=i+2;
								aig_no=0;
								iti_verif=1;
								continue;
							}
						}
						if ((iti_verif+separe_verif+regroupe_verif)==0 && (!strncmp(ch_tab[i],"separe",6)) && ch_tab[i+1][0]==':' ) {
	                        separe_no=atoi(&ch_tab[i][6]);
							if (separe_no>=0 && separe_no<SEPARE_TAB_NB) {	// N° valide ?
								separe_tab[separe_no][SEPARE_TAB_IND_EXIST]=0;
								i=i+2;
								separe_verif=1;
								continue;
							}
						}
						if ((iti_verif+separe_verif+regroupe_verif)==0 && (!strncmp(ch_tab[i],"regroupe",8)) && ch_tab[i+1][0]==':' ) {
	                        regroupe_no=atoi(&ch_tab[i][8]);
							if (regroupe_no>=0 && regroupe_no<REGROUPE_TAB_NB) {	// N° valide ?
								regroupe_tab[regroupe_no][REGROUPE_TAB_IND_EXIST]=0;
								i=i+2;
								regroupe_verif=1;
								continue;
							}
						}
                    }
					if (iti_verif==1 && iti_no!=-1) {
						if ((ch_nb-i)>=1) {
							if (!strcmp(ch_tab[i],"direct")) {
								iti_tab[iti_no][ITI_TAB_IND_TYPE]=ITI_CST_DIRECT;
								i++;
								continue;
							}
                        }
						if ((ch_nb-i)>=1) {
							if (!strcmp(ch_tab[i],"onoff")) {
	                            iti_tab[iti_no][ITI_TAB_IND_TYPE]=ITI_CST_ONOFF;
								i++;
								continue;
							}
                        }
						if ((ch_nb-i)>=2) {	
							if ((!strcmp(ch_tab[i],"start")) && ch_tab[i+1][0]=='c') {
								if (atoi(&ch_tab[i+1][1])>=0 && atoi(&ch_tab[i+1][1])<(300+NB_CANTON) && (atoi(&ch_tab[i+1][1])%100)<NB_CANTON) {
		                            iti_tab[iti_no][ITI_TAB_IND_CANT_START]=atoi(&ch_tab[i+1][1]);
			                        i=i+2;
				                    continue;
								}
							}
                        }
						if ((ch_nb-i)>=2) {
							if ((!strcmp(ch_tab[i],"stop")) && ch_tab[i+1][0]=='c') {
								if (atoi(&ch_tab[i+1][1])>=0 && atoi(&ch_tab[i+1][1])<(300+NB_CANTON) && (atoi(&ch_tab[i+1][1])%100)<NB_CANTON) {
		                            iti_tab[iti_no][ITI_TAB_IND_CANT_STOP]=atoi(&ch_tab[i+1][1]);
				                    i=i+2;
			                        continue;
								}
							}
                        }
						if (aig_no<ITI_TAB_AIG_NB && ch_nb-i>=3) {
							if (ch_tab[i][0]=='a' && ch_tab[i+1][0]=='.') {
								if (atoi(&ch_tab[i][1])>=0 && atoi(&ch_tab[i][1])<NB_AIG && (atoi(ch_tab[i+2])==0 || atoi(ch_tab[i+2])==1)) {
									iti_tab[iti_no][ITI_TAB_IND_AIG_NO +2*aig_no]=atoi(&ch_tab[i][1]);		// n° aiguillage
									iti_tab[iti_no][ITI_TAB_IND_AIG_POS+2*aig_no]=atoi(ch_tab[i+2]);		// Position 
									i=i+3;
									aig_no++;
									continue;
								}
							}
						}
						if ((ch_nb-i)>=3) {
							if ((!strcmp(ch_tab[i],"name")) && ch_tab[i+1][0]==':') {
								if (strlen(ch_tab[i+2])<ITI_TAB_NAME_TAILLE) {				// Le nom de l'itinéraire doit être inférieur à 'ITI_TAB_NAME_TAILLE' (=41) caractères.
							        strcpy(iti_name[iti_no],ch_tab[i+2]);
						            i=i+3; // + 3 termes = 'name' + ':' + 'nom'.
					                continue;
								}
							}
                        }
                    } //fin iti_no ok
//	separe0: c303 c304
/*					if (separe_verif==1 && (ch_nb-i)>=2) {
						j=atoi(&ch_tab[i][1]); // = Numéro du premier canton.
						if ((j>=0 && j<(300+NB_CANTON) && (j%100)<NB_CANTON) || (j>=1000 && (j-1000)<NB_GARAGE_REEL)) { // OK
							separe_tab[separe_no][SEPARE_TAB_IND_C1]=j;
							j=atoi(&ch_tab[i+1][1]); // = Numéro du deuxième canton.
							if ((j>=0 && j<(300+NB_CANTON) && (j%100)<NB_CANTON) || (j>=1000 && (j-1000)<NB_GARAGE_REEL)) { // OK
								separe_tab[separe_no][SEPARE_TAB_IND_C2]=j;
								i=i+2;
				                continue;
							}
						}
					}*/


					if (separe_verif == 1 && (ch_nb - i) >= 2) {
						if (ch_tab[i][0] == 'c') {
							j = atoi(&ch_tab[i][1]); // = Numéro du premier canton.
							if (j >= 0 && j < (300 + NB_CANTON) && (j % 100) < NB_CANTON) { // OK
								separe_tab[separe_no][SEPARE_TAB_IND_C1] = j; // N° de canton.
							}
						}
						if (ch_tab[i][0] == 'g') {
							j = atoi(&ch_tab[i][1]); // = Numéro du premier garage.
							if (j >= 0 && j < NB_GARAGE_REEL) { // OK
								separe_tab[separe_no][SEPARE_TAB_IND_C1] = j + 1000; // N° de garage, +1000 pour un garage.
							}
						}
						if (ch_tab[i + 1][0] == 'c') {
							j = atoi(&ch_tab[i + 1][1]); // = Numéro du deuxième canton.
							if (j >= 0 && j < (300 + NB_CANTON) && (j % 100) < NB_CANTON) { // OK
								separe_tab[separe_no][SEPARE_TAB_IND_C2] = j; // N° de canton.
							}
						}
						if (ch_tab[i + 1][0] == 'g') {
							j = atoi(&ch_tab[i + 1][1]); // = Numéro du deuxième garage.
							if (j >= 0 && j < NB_GARAGE_REEL) { // OK
								separe_tab[separe_no][SEPARE_TAB_IND_C2] = j + 1000; // N° de garage, +1000 pour un garage.
							}
						}
						if (separe_tab[separe_no][SEPARE_TAB_IND_C1] != -1 && separe_tab[separe_no][SEPARE_TAB_IND_C2] != -1) {
							i = i + 2;
							continue;
						}
					}


//	regroupe0: c202 c203
/*					if (regroupe_verif==1 && (ch_nb-i)>=2) {
						j=atoi(&ch_tab[i][1]); // = Numéro du premier canton.
						if ((j>=0 && j<(300+NB_CANTON) && (j%100)<NB_CANTON) || (j>=1000 && (j-1000)<NB_GARAGE_REEL)) { // OK
							regroupe_tab[regroupe_no][REGROUPE_TAB_IND_C1]=j;
							j=atoi(&ch_tab[i+1][1]); // = Numéro du deuxième canton.
							if ((j>=0 && j<(300+NB_CANTON) && (j%100)<NB_CANTON) || (j>=1000 && (j-1000)<NB_GARAGE_REEL)) { // OK
								regroupe_tab[regroupe_no][REGROUPE_TAB_IND_C2]=j;
								i=i+2;
				                continue;
							}
						}
					}*/
//	regroupe0: c202 c203 corrigé le 25/07/2019
					if (regroupe_verif==1 && (ch_nb-i)>=2) {
						if( ch_tab[i][0]=='c') {
							j=atoi(&ch_tab[i][1]); // = Numéro du premier canton.
							if (j>=0 && j<(300+NB_CANTON) && (j%100)<NB_CANTON) { // OK
								regroupe_tab[regroupe_no][REGROUPE_TAB_IND_C1]=j; // N° de canton.
							}
						}
						if( ch_tab[i][0]=='g') {
							j=atoi(&ch_tab[i][1]); // = Numéro du premier garage.
							if (j>=0 && j<NB_GARAGE_REEL) { // OK
								regroupe_tab[regroupe_no][REGROUPE_TAB_IND_C1]=j+1000; // N° de garage, +1000 pour un garage.
							}
						}
						if( ch_tab[i+1][0]=='c') {
							j=atoi(&ch_tab[i+1][1]); // = Numéro du deuxième canton.
							if (j>=0 && j<(300+NB_CANTON) && (j%100)<NB_CANTON) { // OK
								regroupe_tab[regroupe_no][REGROUPE_TAB_IND_C2]=j; // N° de canton.
							}
						}
						if( ch_tab[i+1][0]=='g') {
							j=atoi(&ch_tab[i+1][1]); // = Numéro du deuxième garage.
							if (j>=0 && j<NB_GARAGE_REEL) { // OK
								regroupe_tab[regroupe_no][REGROUPE_TAB_IND_C2]=j+1000; // N° de garage, +1000 pour un garage.
							}
						}
						if  (regroupe_tab[regroupe_no][REGROUPE_TAB_IND_C1] != -1 && regroupe_tab[regroupe_no][REGROUPE_TAB_IND_C2]!= -1 ) {
							i=i+2;
							continue;
						}
					}


					// Nombre maximum d'aiguillages pour un itinéraire. = ITI_TAB_AIG_NB = 10 en V3.3.
					strcpy(ch_error,"Fichier 'config.txt',\n\nSection #Itineraire,\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 dans 'config.txt'",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(==#iti)   fin description '#iti'.
	}			// While (scanf)    fin du fichier 'config.txt'.
	moins_char_normal=1;		// '-' est un caractère normal, comme '+'.
	fclose(pf);
}


//
//
void cIti::save_conf(void)
{
    FILE* pf;
    int i,j;
    if((pf=fopen("debug_iti.txt","wt"))==NULL) {
        MessageBox(NULL,"Impossible de créer le fichier 'Debug_iti.txt'","Erreur",MB_OK|MB_ICONERROR); exit(1);
    }
    for(j=0;j<ITI_TAB_NB;j++) {
        fprintf(pf,"\n");
        for(i=0;i<ITI_TAB_IND_TAILLE;i++) fprintf(pf," %2d",iti_tab[j][i]);
    }
   fclose(pf);
}

//
//
void cIti::tick(void)
{
    int i, aig_ind, ok, aig_no, aig_pos, canton;

	for (i=0;i<ITI_TAB_NB;i++) if(iti_tab[i][ITI_TAB_IND_EXIST]) {

		if(iti_tab[i][ITI_TAB_IND_STOP]) { // Si = 1 = demande d'arrêt manuel du déplacement, menu : 'Tables > Itinéraires' + colonne 'stop'.
			iti_tab[i][ITI_TAB_IND_STOP]=0;
			if(iti_tab[i][ITI_TAB_IND_STEP]==ITI_CST_STATE_WAIT_RES) { // On était encore au stade de la réservation. 
				iti_tab[i][ITI_TAB_IND_STEP]=ITI_CST_STATE_IDLE;
				iti_tab[i][ITI_TAB_IND_START]=0;
			}
			else if(iti_tab[i][ITI_TAB_IND_STEP]!=ITI_CST_STATE_IDLE)
				iti_tab[i][ITI_TAB_IND_STEP]=ITI_CST_STATE_RELEASE;
		}

        if(iti_tab[i][ITI_TAB_IND_TYPE]==ITI_CST_DIRECT) {
            if(iti_tab[i][ITI_TAB_IND_START]) {
                iti_tab[i][ITI_TAB_IND_START]=0;
                for(aig_ind=0;aig_ind<ITI_TAB_AIG_NB;aig_ind++) {
                    aig_no =iti_tab[i][ITI_TAB_IND_AIG_NO +2*aig_ind];
                    aig_pos=iti_tab[i][ITI_TAB_IND_AIG_POS+2*aig_ind];
                    if(aig_no!=-1 && vio_aig_res[aig_no]==0) vio_aig_cmd[aig_no]=aig_pos;  // ( ne modifie pas les aiguillages reserves )
                }
            }
            ok=1;
            for(aig_ind=0 ; aig_ind<ITI_TAB_AIG_NB ; aig_ind++) {
                aig_no =iti_tab[i][ITI_TAB_IND_AIG_NO +2*aig_ind];
                aig_pos=iti_tab[i][ITI_TAB_IND_AIG_POS+2*aig_ind];
                if(aig_no!=-1) if(  (aig_pos==1 && vio_aig_pos1[aig_no]!=1) || (aig_pos==0 && vio_aig_pos0[aig_no]!=1) ) ok=0;
            }
            iti_tab[i][ITI_TAB_IND_OK]=ok;
        }
        if(iti_tab[i][ITI_TAB_IND_TYPE]==ITI_CST_ONOFF) {
// IDLE En attente d'événement.
            if(iti_tab[i][ITI_TAB_IND_STEP]==ITI_CST_STATE_IDLE)
            if(iti_tab[i][ITI_TAB_IND_START]==1) {
                iti_tab[i][ITI_TAB_IND_START]=0;
                iti_tab[i][ITI_TAB_IND_STEP]=ITI_CST_STATE_WAIT_CANT_DEP;
            }
// WAIT_CANT_DEP Si un canton de départ est spécifié, on attend qu'un train soit dessus.
//  < >          Si 'start:cx' est défini attend un train sur ce canton. Si pas de train -> WAIT_CANT_DEP
            if(iti_tab[i][ITI_TAB_IND_STEP]==ITI_CST_STATE_WAIT_CANT_DEP) {
                canton=iti_tab[i][ITI_TAB_IND_CANT_START];
                if(canton==-1) iti_tab[i][ITI_TAB_IND_STEP]=ITI_CST_STATE_WAIT_RES;
                else if(vio_det[canton/100][canton%100]) iti_tab[i][ITI_TAB_IND_STEP]=ITI_CST_STATE_WAIT_RES;
            }
// ITI_CST_STATE_WAIT_RES On attend si un aiguillage est déjà reservé, qu'il se libére.
//   < >                  Un aiguillage est déjà réservé -> ITI_CST_STATE_WAIT_RES
//    |                   Renseigne le tableau avec la position désirée des aiguillages
            if(iti_tab[i][ITI_TAB_IND_STEP]==ITI_CST_STATE_WAIT_RES) {
                //mettre la verification et reservation
                ok=1;
				for(aig_ind=0;aig_ind<ITI_TAB_AIG_NB;aig_ind++) {        // verifie si pas reservation
                    aig_no =iti_tab[i][ITI_TAB_IND_AIG_NO +2*aig_ind];
                    aig_pos=iti_tab[i][ITI_TAB_IND_AIG_POS+2*aig_ind];
                    if(aig_no!=-1 && vio_aig_res[aig_no]!=0) ok=0;
                }
				if(ok) for(aig_ind=0;aig_ind<ITI_TAB_AIG_NB;aig_ind++) { // reserve et commande
                    aig_no =iti_tab[i][ITI_TAB_IND_AIG_NO +2*aig_ind];
                    aig_pos=iti_tab[i][ITI_TAB_IND_AIG_POS+2*aig_ind];
                    if(aig_no!=-1) { vio_aig_cmd[aig_no]=aig_pos; vio_aig_res[aig_no]=1; }
                }
                if(ok) iti_tab[i][ITI_TAB_IND_STEP]=ITI_CST_STATE_WAIT_VER;
            }
// ITI_CST_STATE_WAIT_VER Demande de positionnement d'aiguillages.
//   < >                  si il reste un aiguillage à positionner -> ITI_CST_STATE_WAIT_VER
            if(iti_tab[i][ITI_TAB_IND_STEP]==ITI_CST_STATE_WAIT_VER) {
                ok=1;
                for(aig_ind=0;aig_ind<ITI_TAB_AIG_NB;aig_ind++) {
                    aig_no =iti_tab[i][ITI_TAB_IND_AIG_NO +2*aig_ind];
                    aig_pos=iti_tab[i][ITI_TAB_IND_AIG_POS+2*aig_ind];
                    if(aig_no!=-1) if(  (aig_pos==1 && vio_aig_pos1[aig_no]!=1) || (aig_pos==0 && vio_aig_pos0[aig_no]!=1) ) ok=0;
                }
                if(ok) iti_tab[i][ITI_TAB_IND_STEP]=ITI_CST_STATE_WAIT_CANT_FIN;
            }
// ITI_CST_STATE_WAIT_CANT_FIN  Attend l'arrivé sur le canton d'arrivée 'stop:'
//   < >                        Si 'stop:cx' n'est pas défini -> ITI_CST_STATE_WAIT_STOP
//    |                         Arme une temporisation.
			if(iti_tab[i][ITI_TAB_IND_STEP]==ITI_CST_STATE_WAIT_CANT_FIN) {
                canton=iti_tab[i][ITI_TAB_IND_CANT_STOP];
                if(canton==-1) iti_tab[i][ITI_TAB_IND_STEP]=iti_tab[i][ITI_TAB_IND_STEP]=ITI_CST_STATE_WAIT_STOP;
                else if(vio_det[canton/100][canton%100])
                {
                    iti_tab[i][ITI_TAB_IND_STEP]=ITI_CST_STATE_WAIT_WAIT;
                    iti_tab[i][ITI_TAB_IND_TEMPO]=16;		// 4secondes en V2.0,  mais 1,28 seconde en V3.3
                }
            }
// ITI_CST_STATE_WAIT_WAIT Attend la fin de temporisation.
//  < >                    Décremente la temporisation.  Si !=0 -> ITI_CST_STATE_WAIT_WAIT
            if(iti_tab[i][ITI_TAB_IND_STEP]==ITI_CST_STATE_WAIT_WAIT)  // stop automatic par detection canton + 4s
            {
                if(iti_tab[i][ITI_TAB_IND_TEMPO]!=0) iti_tab[i][ITI_TAB_IND_TEMPO]--;
                else  iti_tab[i][ITI_TAB_IND_STEP]=ITI_CST_STATE_RELEASE;
            }
// ITI_CST_STATE_WAIT_STOP  Stop manuel.
            if(iti_tab[i][ITI_TAB_IND_STEP]==ITI_CST_STATE_WAIT_STOP)  // stop manual
            if(iti_tab[i][ITI_TAB_IND_STOP]==1) {
                iti_tab[i][ITI_TAB_IND_STOP]=0;
                iti_tab[i][ITI_TAB_IND_STEP]=ITI_CST_STATE_RELEASE;
            }
// ITI_CST_STATE_RELEASE
            if(iti_tab[i][ITI_TAB_IND_STEP]==ITI_CST_STATE_RELEASE) {
                //dereservation
				for(aig_ind=0;aig_ind<ITI_TAB_AIG_NB;aig_ind++) {        // verifie si pas de réservation.
                    aig_no =iti_tab[i][ITI_TAB_IND_AIG_NO +2*aig_ind];
                    aig_pos=iti_tab[i][ITI_TAB_IND_AIG_POS+2*aig_ind];
                    if(aig_no!=-1) vio_aig_res[aig_no]=0;
                }
                iti_tab[i][ITI_TAB_IND_STEP]=ITI_CST_STATE_IDLE;
            }

            //mise a jour des indicateurs
            if(iti_tab[i][ITI_TAB_IND_STEP]==ITI_CST_STATE_WAIT_STOP ||
               iti_tab[i][ITI_TAB_IND_STEP]==ITI_CST_STATE_WAIT_CANT_FIN ||
               iti_tab[i][ITI_TAB_IND_STEP]==ITI_CST_STATE_WAIT_WAIT)
            iti_tab[i][ITI_TAB_IND_OK]=1; else iti_tab[i][ITI_TAB_IND_OK]=0;

            if(iti_tab[i][ITI_TAB_IND_STEP]==ITI_CST_STATE_WAIT_CANT_DEP ||
               iti_tab[i][ITI_TAB_IND_STEP]==ITI_CST_STATE_WAIT_RES      ||
               iti_tab[i][ITI_TAB_IND_STEP]==ITI_CST_STATE_WAIT_VER)
            iti_tab[i][ITI_TAB_IND_WAIT]=1; else iti_tab[i][ITI_TAB_IND_WAIT]=0;
        } // fin onoff
    } // fin for 
}

//
// Parcourt les tables des variables pour savoir si il faut regrouper ou séparer des locomotives et leurs wagons.
// Variables 'separe_xxx' et 'regroupe_xxx'.
//
void iti2_tick(void)
{
    int i, j, cant1, cant2, train1, train2;

	for (i=0; i<SEPARE_TAB_NB; i++) { // Séparation Loco - Wagons.
			if (separe_tab[i][SEPARE_TAB_IND_EXIST]==1) {
				separe_tab[i][SEPARE_TAB_IND_EXIST]=0;
				cant1=separe_tab[i][SEPARE_TAB_IND_C1];
				cant2=separe_tab[i][SEPARE_TAB_IND_C2];
				// POUR SEPARER LA LOCOMOTIVE DE SES WAGONS.
				// le code est le même que dans 'Train_UTS.cpp' pour la même fonction en deux clic de souris.
				// On ne teste pas 'cant1' et 'cant2' qui ont été testés à la lecture du fichier 'config.txt'.
				if ((cant1>=0 && cant1<(300+NB_CANTON) && (cant1%100)<NB_CANTON && vio_det[cant1/100][cant1%100]==1) || (cant1>=1000 && (cant1-1000)<NB_GARAGE_REEL)) {
					if ((cant2>=0 && cant2<(300+NB_CANTON) && (cant2%100)<NB_CANTON && vio_det[cant2/100][cant2%100]==1) || (cant2>=1000 && (cant2-1000)<NB_GARAGE_REEL)) {
						if ((cant1<1000 || (cant1>=1000 && vio_garage_lock_status[cant1-1000]==1)) && (cant2<1000 || (cant2>=1000 && vio_garage_lock_status[cant2-1000]==1))) {
							if (((cant1<1000 && vio_det[cant1/100][cant1%100]==1 && canton.master_selectif[cant1/100][cant1%100]==1) ||
							(cant1>=1000 && vio_garage_lock_status[cant1-1000]==0 && vio_garage_lock_res[cant1-1000]==0) &&
							(cant2<1000 && vio_det[cant2/100][cant2%100]==1 && canton.master_selectif[cant2/100][cant2%100]==1) ||
							(cant2>=1000 && vio_garage_lock_status[cant2-1000]==0 && vio_garage_lock_res[cant2-1000]==0))) {
								// Les cantons sont occupés par le même train en conduite manuelle ou le garage est RELIE au canton et n'est pas réservé.
								train1=-1;
								train2=-1;
								if (cant1<1000) train1=canton.num_train[cant1/100][cant1%100];
								else if (vio_garage_lock_status[cant1-1000]==0) { // 1 => Le garage est relié au canton.
									if (garage.ass_canton[cant1-1000]!=-1) train1=canton.num_train[garage.ass_canton[cant1-1000]/100][garage.ass_canton[cant1-1000]%100];
								}
								if (cant2<1000) train2=canton.num_train[cant2/100][cant2%100];
								else if (vio_garage_lock_status[cant2-1000]==0) { // 1 => Le garage est relié au canton.
									if (garage.ass_canton[cant2-1000]!=-1) train2=canton.num_train[garage.ass_canton[cant2-1000]/100][garage.ass_canton[cant2-1000]%100];
								}
								if (train1==train2 && train1!=-1 && train1<NB_TRAIN_COULEUR && STR_SAME stricmp(train.mode[train1],"SEL")) {
									// VERIFIER QUE NE SONT PAS DEUX WAGONS[xx]>NB COULEUR
									// On a le même train sur un canton et sur un garage relié à ce canton.
									train2=-1;
									for (i=NB_TRAIN-1; i>=NB_TRAIN_COULEUR && train2==-1; i--) {
										if (train.enable[i]==0) train2=i;
									}
									if (train2!=-1) {
									// On a trouvé un numéro libre de Wagon[xx].
										if (cant1<1000 && cant2<1000) {
											// Cas où la Locomotive et les Wagons sont sur des cantons.
											// On donne aux cantons 2, le n° de Wagons.
											canton.num_train[cant2/100][cant2%100]=train2;
											train.enable[train2]=1;
											sprintf_s(train.name[train2],"WGON[%2d]",train2); // Nom des wagons = 8 caractères.
											train.en_auto[train2]=0; // Par défaut les nouveaux wagons ne peuvent pas être en conduite automatique.
											train_pb_capt[train2]=0; // Le train2 est de nouveau sur un canton, pour éviter un affichage 'PB' intempestif.
											train.capt[train2]=1;    // Le train2 est de nouveau sur un canton, pour éviter un affichage 'PB' intempestif.
										}
										else if (cant1<1000 && cant2>=1000) {
												// 'cant1' = CANTON  et  'cant2' = GARAGE.
											// 'cant1' = Locomotive  et  'cant2' = Wagons[xx], car l'on a relaché le bouton de la souris sur 'cant2'.
											// On va isoler les Wagons[xx] sur le garage.
											train.enable[train2]=1;
											sprintf_s(train.name[train2],"WGON[%2d]",train2); // Nom des wagons = 8 caractères.
											train.en_auto[train2]=0; // Par défaut les nouveaux wagons ne sont pas en conduite automatique.
											train.cant_lock[train2]=cant2-1000;
											vio_garage_lock_cmd[cant2-1000]=1;      // 1 => Demande d'isolation du garage (Sera réalisée si il a un train sur le canton).
											vio_garage_lock_status[cant2-1000]=1;   // 1 => Le garage est isolé du canton (état réel).
											garage.numero_train[cant2-1000]=train2; // Numéro de train occupant le garage isolé du canton.
										}
										else if (cant1>=1000 && cant2<1000) {
												// 'cant1' = GARAGE  et  'cant2' = CANTON.
											// 'cant1' = Wagons[xx]  et  'cant2' = Locomotive, car l'on a relaché le bouton de la souris sur 'cant2'.
											// On va isoler la locomotive sur le garage.
											canton.num_train[cant2/100][cant2%100]=train2;
											train.enable[train2]=1;
											sprintf_s(train.name[train2],"WGON[%2d]",train2); // Nom des wagons = 8 caractères.
											train.en_auto[train2]=0; // Par défaut les nouveaux wagons ne sont pas en conduite automatique.
											train.cant_lock[train1]=cant1-1000;
											vio_garage_lock_cmd[cant1-1000]=1;      // 1 => Demande d'isolation du garage (Sera réalisée si il a un train sur le canton).
											vio_garage_lock_status[cant1-1000]=1;   // 1 => Le garage est isolé du canton (état réel).
											garage.numero_train[cant1-1000]=train1; // Numéro de train occupant le garage isolé du canton.
											for (j=0; j<NB_CARTE; j++) {
												for (i=0; i<NB_CANTON; i++) { 
													if (canton.num_train[j][i]==train1) canton.num_train[j][i]=train2; // Changement de propriétaire des cantons.
												}
											}
											train_pb_capt[train2]=0; // Le train2 est de nouveau sur un canton, pour éviter un affichage 'PB' intempestif.
											train.capt[train2]=1;    // Le train2 est de nouveau sur un canton, pour éviter un affichage 'PB' intempestif.
										}
									} // FIn on a trouvé un numéro de train de wagons libre.
								} // Fin train = SEL.
							} // Fin vérif canton ou garage.
						} // Fin suite si 'cmd_divers[CMD_DIVERS_RESULT]==0' pour séparer les wagons.
					} // Fin 'cant2' = ok.
				}
			}
		}

		for (i=0; i<REGROUPE_TAB_NB; i++) { // Regroupement Loco _ Wagons.
			if (regroupe_tab[i][REGROUPE_TAB_IND_EXIST]==1) {
				regroupe_tab[i][REGROUPE_TAB_IND_EXIST]=0; // Cas traité.
				cant1=regroupe_tab[i][REGROUPE_TAB_IND_C1];
				cant2=regroupe_tab[i][REGROUPE_TAB_IND_C2];
				// le code est le même que dans 'Train_UTS.cpp' pour la même fonction en deux clic de souris.
				// On ne teste pas 'cant1' et 'cant2' qui ont été testés à la lecture du fichier 'config.txt'.
				if ((cant1>=0 && cant1<(300+NB_CANTON) && (cant1%100)<NB_CANTON && vio_det[cant1/100][cant1%100]==1) || (cant1>=1000 && (cant1-1000)<NB_GARAGE_REEL)) {
					if ((cant2>=0 && cant2<(300+NB_CANTON) && (cant2%100)<NB_CANTON && vio_det[cant2/100][cant2%100]==1) || (cant2>=1000 && (cant2-1000)<NB_GARAGE_REEL)) {
						if ((cant1<1000 || (cant1>=1000 && vio_garage_lock_status[cant1-1000]==1)) && (cant2<1000 || (cant2>=1000 && vio_garage_lock_status[cant2-1000]==1))) {
							// On n'a pas laché le bouton de souris sur le même numéro de canton.
							// Les garages sont reliés au canton, indispensable pour séparer un train.
							// 
							// POUR REGROUPER UNE LOCOMOTIVE ET DES WAGONS ou,
							// POUR SEPARER LA LOCOMOTIVE DE SES WAGONS (sur deux cantons!!!).
							if (((cant1<1000 && vio_det[cant1/100][cant1%100]==1 && canton.master_selectif[cant1/100][cant1%100]==1) 
							|| (cant1>=1000 && vio_garage_lock_res[cant1-1000]==0)) &&
							((cant2<1000 && vio_det[cant2/100][cant2%100]==1 && canton.master_selectif[cant2/100][cant2%100]==1) 
							|| (cant2>=1000 && vio_garage_lock_res[cant2-1000]==0))) {
								// Le canton d'arrivé est occupé par un train en conduite manuelle ou le garage est ISOLE et pas réservé (ou l'inverse).
								// On a le canton de la Locomotive et le canton des Wagons en mémoire.
								train1=-1;
								train2=-1;
								if (cant1<1000) {
									train1=canton.num_train[cant1/100][cant1%100];
								}
								else if (vio_garage_lock_status[cant1-1000]) { // 1 => Le garage est isolé du canton.
									train1=copy_garage_num_train[cant1-1000];
								}
								if (cant2<1000) {
									train2=canton.num_train[cant2/100][cant2%100];
								}
								else if (vio_garage_lock_status[cant2-1000]) { // 1 => Le garage est isolé du canton.
									train2=copy_garage_num_train[cant2-1000];
								}
								// On a les numéros de la Locomotive et des Wagons.
								if (train1>=0 && train2>=0 && (train1<NB_TRAIN_COULEUR && train2>=NB_TRAIN_COULEUR) || (train2<NB_TRAIN_COULEUR && train1>=NB_TRAIN_COULEUR)) {
									// On a un n° de Locomotive valide et un n° de Wagon valide,
									// et les trains n'ont pas le même numéro => Séparation.
									if (STR_SAME stricmp(train.mode[train1],"SEL") && STR_SAME stricmp(train.mode[train2],"SEL")) {
										// Les Locomotive et wagons ne sont pas en déplacements automatique.
										if (cant1<1000 && cant2<1000) {
											// Cas où la Locomotive et les Wagons sont sur des cantons.
											// REGROUPAGE => on donne aux cantons du train n°2, le n° du train1.
											if (train1>train2) {
												j=train2;
												train2=train1;
												train1=j;
											}
											// TRAIN1 = Locomotive.
											// TRAIN2 = Wagons.
											// On libére le 'train2'=Wagons[xx]. On affecte le canton du train 2 au 'train1'=Locomotive.
											train.enable[train2]=0; // Libération compléte du 'train2'=Wagons[xx].
											train.cmd[train2]=-1;   // Comme quand l'on supprime un train du tableau des trains.
											train.en_auto[train2]=0;
											train.inv[train2]=0;
											train.vmin[train2]=0; train.vmax[train2]=64;
											train.acc[train2]=-1; train.dec[train2]=-1; train.frein[train2]=-1;
											train.cons[train2]=0; train.vit[train2]=0;
											strcpy(train.mode[train2],"SEL");
											for (j=0; j<NB_CARTE; j++) {
												for (i=0; i<NB_CANTON; i++) { 
													if (canton.num_train[j][i]==train2) canton.num_train[j][i]=train1; // Changement de propriétaire des cantons.
												}
											}
										}
										else if (cant1>=1000 && cant2<1000) {
											// Cas où un train est sur un canton 'cant2' et l'autre train sur un garage isolé 'cant1'.
											// REGROUPAGE => on relie le garage au canton.
											if (garage.ass_canton[cant1-1000]==cant2 && vio_garage_lock_res[cant1-1000]==0) {
												// On a le droit de relier un garage isolé qu'au canton ou il est relié.
												// Le garage ne doit pas être réservé.
												// On a déjà vérifié qu'il y avait un train sur le garage.
												vio_garage_lock_cmd[cant1-1000]=0;    // 0 => Demande pour relier le garage au canton.
												vio_garage_lock_status[cant1-1000]=0; // 0 => Le garage est relié au canton (état réel).
												garage.numero_train[cant1-1000]=-1;   // -1 = Garage relié au canton.
												train.cant_lock[train1]=-1;
												if (train1>train2) {
													j=train2;
													train2=train1;
													train1=j;
												}
												// TRAIN1 = Locomotive.
												// TRAIN2 = Wagons.
												// On libére le 'train2'=wagon[xx].
												train.enable[train2]=0; // Libération compléte du 'train2'=Wagons[xx].
												train.cmd[train2]=-1;   // Comme quand l'on supprime un train du tableau des trains.
												train.en_auto[train2]=0;
												train.inv[train2]=0;
												train.vmin[train2]=0; train.vmax[train2]=64;
												train.acc[train2]=-1; train.dec[train2]=-1; train.frein[train2]=-1;
												train.cons[train2]=0; train.vit[train2]=0;
												strcpy(train.mode[train2],"SEL");
												for (j=0; j<NB_CARTE; j++) {
													for (i=0; i<NB_CANTON; i++) { 
														if (canton.num_train[j][i]==train2) canton.num_train[j][i]=train1; // Changement de propriétaire des cantons.
													}
												}
											}
										}
										else if (cant1<1000 && cant2>=1000) {
											// Cas où un train est sur un canton 'cant2' et l'autre train sur un garage isolé 'cant1'.
											// REGROUPAGE => on relie le garage au canton.
											if (garage.ass_canton[cant2-1000]==cant1 && vio_garage_lock_res[cant2-1000]==0) {
												// On a le droit de relier un garage isolé qu'au canton ou il est relié. Le garage ne doit pas être réservé.
												// Le garage ne doit pas être réservé.
												// On a déjà vérifié qu'il y avait un train sur le garage.
												vio_garage_lock_cmd[cant2-1000]=0;    // 0 => Demande pour relier le garage au canton.
												vio_garage_lock_status[cant2-1000]=0; // 0 => Le garage est relié au canton (état réel).
												garage.numero_train[cant2-1000]=-1;   // -1 = Garage relié au canton.
												train.cant_lock[train2]=-1;
												if (train1>train2) {
													j=train2;
													train2=train1;
													train1=j;
												}
												// TRAIN1 = Locomotive.
												// TRAIN2 = Wagons.
												// On libére le 'train2'=Wagons[xx]. On affecte le canton du train 2 au 'train1'=Locomotive.
												train.enable[train2]=0; // Libération compléte du 'train2'=Wagons[xx].
												train.cmd[train2]=-1;   // Comme quand l'on supprime un train du tableau des trains.
												train.en_auto[train2]=0;
												train.inv[train2]=0;
												train.vmin[train2]=0; train.vmax[train2]=64;
												train.acc[train2]=-1; train.dec[train2]=-1; train.frein[train2]=-1;
												train.cons[train2]=0; train.vit[train2]=0;
												strcpy(train.mode[train2],"SEL");
												for (j=0; j<NB_CARTE; j++) {
													for (i=0; i<NB_CANTON; i++) { 
														if (canton.num_train[j][i]==train2) canton.num_train[j][i]=train1; // Changement de propriétaire des cantons.
													}
												}
											}
										}
									} // Trains pas en manuel on ne fait rien.
								} // Fin "trainX<16 et  trainY>16' => 'locomotive + wagon'.
							}
						}
					} 
				}
			}
		}
	
}


// Affiche le tableau avec des états des ininéraires. Appel cet écran depuis le menu principal.
// Suivant la valeur de 'screen_mode' on affiche les itinéraires de 0 à 29 ou de 30 à 49.
//
void cIti::debug(int action)
{
	int i;
	static int iti_deb=0;
	char ch[200];
	static int dimx=50; // Dimension horizontal d'une cellule, taille pour désignation possible !
	static int dimy=18; // Dimension vertical d'une cellule, taille pour désignation possible !
	static int decaly=18; // Décalage de l'emplacement du tableau
	static int nblignes=25; // Nombre de ligne du tableau (sans le titre)	

	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,dimy+decaly+1);	// Pour dessiner un rectangle pour les titres des colonnes.
		EasyLine(   dimx,decaly,   dimx,dimy+decaly); // Dessine les trais verticaux.
		EasyLine( 2*dimx,decaly, 2*dimx,dimy+decaly);
		EasyLine( 3*dimx,decaly, 3*dimx,dimy+decaly); 
		EasyLine( 4*dimx,decaly, 4*dimx,dimy+decaly); 
		EasyLine( 5*dimx,decaly, 5*dimx,dimy+decaly); 
		EasyLine( 6*dimx,decaly, 6*dimx,dimy+decaly);
		EasyLine(10*dimx,decaly,10*dimx,dimy+decaly);
		EasyLine(2*dimx-10,dimy+decaly,2*dimx,dimy+decaly-10); // Dessine un trait dans l'angle = valeurs modifiables
		EasyLine(3*dimx-10,dimy+decaly,3*dimx,dimy+decaly-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 ITINÉRAIRES (50 maximum)"); EasyTextOut(800-140,2,"(QUITTER = ESC)");
		EasyTextOut(2,decaly+(nblignes+2)*dimy+1,"Section '#iti'");
		SelectObject(hMemDC,bmp_stylo_noir); SelectObject(hMemDC,bmp_pinceau_gris220); // Rectangle gris foncé.
		Rectangle(hMemDC,0, decaly+(nblignes+3)*dimy+1-2, 97, decaly+(nblignes+4)*dimy+1-2);
		SelectObject(hMemDC,bmp_stylo_gris128);
		EasyLine(1,  decaly+(nblignes+4)*dimy+1-2-2, 96, decaly+(nblignes+4)*dimy+1-2-2);  	// Relief rectangle.
		EasyLine(95, decaly+(nblignes+3)*dimy+1-2+1, 95, decaly+(nblignes+4)*dimy+1-2-2);	// Relief rectangle.
		SelectObject(hMemDC,bmp_stylo_noir);
		EasyLine(97-10,  decaly+(nblignes+4)*dimy+1-4, 97, decaly+(nblignes+4)*dimy+1-2-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-24]<->[25-49]");
		EasyTextOut(2,decaly+(nblignes+4)*dimy+1,"CLIQUEZ dans la colonne 'Start' ou 'Stop' pour activer ou annuler un itinéraire.");
		SelectObject(hMemDC,bmp_pinceau_cyan); // Rectangle bleu.
		Rectangle(hMemDC,0, -2+decaly+(nblignes+5)*dimy+1,96,-2+decaly+(nblignes+6)*dimy+1);
		SelectObject(hMemDC,bmp_pinceau_vert); // Rectangle vert.
		Rectangle(hMemDC,0, -2+decaly+(nblignes+6)*dimy+1,96,-2+decaly+(nblignes+7)*dimy+1);
		SelectObject(hMemDC,bmp_pinceau_jaune); // Rectangle jaune.
		Rectangle(hMemDC,0, -2+decaly+(nblignes+7)*dimy+1,96,-2+decaly+(nblignes+8)*dimy+1);
		SelectObject(hMemDC,bmp_pinceau_blanc);
		EasyTextOut(2,decaly+(nblignes+5)*dimy+1,"LIGNE BLEUE = Itinéraire SANS verrouillage d'aiguillage traçé.");
		EasyTextOut(2,decaly+(nblignes+6)*dimy+1,"LIGNE VERTE = Itinéraire AVEC verrouillage d'aiguillage établi.");
		EasyTextOut(2,decaly+(nblignes+7)*dimy+1,"LIGNE JAUNE = Itinéraire AVEC verrouillage d'aiguillage en attente d'aiguillage libéré.");

		SetTextColor(hMemDC,RGB(255,0,0)); // Texte rouge
		EasyTextOut(        2,2+decaly,"  n°");
		EasyTextOut(   dimx+5,2+decaly,"Start");  // Colonne 'Start' marquée '/' = valeurs modifiables
		EasyTextOut( 2*dimx+7,2+decaly,"Stop");  // Colonne 'Stop'  marquée '/' = valeurs modifiables
		EasyTextOut( 3*dimx+7,2+decaly,"Wait");
		EasyTextOut( 4*dimx+7,2+decaly," Ok");
		EasyTextOut( 5*dimx+5,2+decaly,"Tempo");
		EasyTextOut( 6*dimx+7,2+decaly,"Etat");
		EasyTextOut(10*dimx+7,2+decaly,"Noms des itinéraires");
	}	

    if(action==DEBUG_MOUSE) {	// ACTION = CLIC GAUCHE DE LA SOURIS
		if ((x_mouse > 0 && x_mouse < 97) && (y_mouse > decaly+(nblignes+3)*dimy+1-2 && y_mouse < decaly+(nblignes+4)*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-decaly-dimy)/dimy;
			if(y_mouse>=decaly+dimy && i>= 0 && i<nblignes && iti_deb+i<ITI_TAB_NB) {
				if (iti_tab[iti_deb+i][ITI_TAB_IND_EXIST]!=0) {
					if(x_mouse>dimx   && x_mouse<2*dimx && iti_tab[i][ITI_TAB_IND_STEP]==ITI_CST_STATE_IDLE) iti_tab[iti_deb+i][ITI_TAB_IND_START]^=1;		// Lance l'ininéraire.
					if(x_mouse>2*dimx && x_mouse<3*dimx && iti_tab[i][ITI_TAB_IND_STEP]!=ITI_CST_STATE_IDLE) iti_tab[iti_deb+i][ITI_TAB_IND_STOP]^=1; 		// Arrête l'ininéraire.
				}
			}
		}
    }

	if(action==DEBUG_MOUSE_RIGHT) { // ACTION = CLIC DROIT DE LA SOURIS, on change de page
		Rectangle(hMemDC,0,decaly+dimy,800,decaly+(nblignes+1)*dimy+1);	// N'efface que la partie du tableau.
		if (iti_deb!=nblignes)  screen_mode=MD_ECRAN_ITI2;
		else                    screen_mode=MD_ECRAN_ITI1;
		SelectObject(hMemDC,bmp_pinceau_blanc); SelectObject(hMemDC,bmp_stylo_gris192);
	}

	if (screen_mode==MD_ECRAN_ITI1) iti_deb=0;	// Valeur du premier itinéraire à afficher.
	if (screen_mode==MD_ECRAN_ITI2) iti_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((iti_deb+i)>=ITI_TAB_NB) break;
		if(iti_tab[iti_deb+i][ITI_TAB_IND_WAIT]) SelectObject(hMemDC,bmp_pinceau_jaune);
		if(iti_tab[iti_deb+i][ITI_TAB_IND_OK]) {
			if (iti_tab[iti_deb+i][ITI_TAB_IND_TYPE]==ITI_CST_DIRECT) SelectObject(hMemDC,bmp_pinceau_cyan); // Si itinéraire sans vérrouillage d'aiguillage
			else                                                      SelectObject(hMemDC,bmp_pinceau_vert);
		}
		Rectangle(hMemDC,0,dimy*(i+1)+decaly,800,dimy*(i+2)+1+decaly);
		EasyLine(   dimx,dimy*(i+1)+decaly, 1*dimx,dimy*(i+2)+decaly); 
		EasyLine( 2*dimx,dimy*(i+1)+decaly, 2*dimx,dimy*(i+2)+decaly);
		EasyLine( 3*dimx,dimy*(i+1)+decaly, 3*dimx,dimy*(i+2)+decaly); 
		EasyLine( 4*dimx,dimy*(i+1)+decaly, 4*dimx,dimy*(i+2)+decaly);
		EasyLine( 5*dimx,dimy*(i+1)+decaly, 5*dimx,dimy*(i+2)+decaly); 
		EasyLine( 6*dimx,dimy*(i+1)+decaly, 6*dimx,dimy*(i+2)+decaly);
		EasyLine(10*dimx,dimy*(i+1)+decaly,10*dimx,dimy*(i+2)+decaly);

		if(iti_tab[iti_deb+i][ITI_TAB_IND_EXIST]==0) SetTextColor(hMemDC,RGB(192,192,192));  // Texte GRIS 192
		sprintf_s(ch,"%3d",iti_deb+i);                                   
		EasyTextOut(   10,3+dimy*(i+1)+decaly,ch);
		SetTextColor(hMemDC,RGB(0,0,255));  // Texte Bleu

	
		if(iti_tab[iti_deb+i][ITI_TAB_IND_EXIST]==0) continue;	// On sort de la boucle si l'itinéraire n'est pas valide.

		if (iti_tab[iti_deb+i][ITI_TAB_IND_START]!=0) {
			sprintf_s(ch,"%4d",iti_tab[iti_deb+i][ITI_TAB_IND_START]);
			EasyTextOut( dimx+5,3+dimy*(i+1)+decaly,ch);}

		if (iti_tab[iti_deb+i][ITI_TAB_IND_STOP]!=0) {
			sprintf_s(ch,"%4d",iti_tab[iti_deb+i][ITI_TAB_IND_STOP]);     
			EasyTextOut(2*dimx+5,3+dimy*(i+1)+decaly,ch);}

		if (iti_tab[iti_deb+i][ITI_TAB_IND_WAIT]!=0) {
			sprintf_s(ch,"%3d",iti_tab[iti_deb+i][ITI_TAB_IND_WAIT]);     
			EasyTextOut(3*dimx+5,3+dimy*(i+1)+decaly,ch);}

		if (iti_tab[iti_deb+i][ITI_TAB_IND_OK]!=0) {
			sprintf_s(ch,"%3d",iti_tab[iti_deb+i][ITI_TAB_IND_OK]);       
			EasyTextOut(4*dimx+5,3+dimy*(i+1)+decaly,ch);}

   		if (iti_tab[iti_deb+i][ITI_TAB_IND_TEMPO]!=0) {
			sprintf_s(ch,"%4d",iti_tab[iti_deb+i][ITI_TAB_IND_TEMPO]);       
			EasyTextOut(5*dimx+5,3+dimy*(i+1)+decaly,ch);}

		strcpy(ch,iti_step_name[iti_tab[iti_deb+i][ITI_TAB_IND_STEP]]);  
		EasyTextOut( 6*dimx+5,3+dimy*(i+1)+decaly,ch);
		strcpy(ch,iti_name[iti_deb+i]);                                 
		EasyTextOut(10*dimx+5,3+dimy*(i+1)+decaly,ch);
	}
}



// Affiche les tableaux 'SEPARE' et REGROUPEMENT'. Appel cet écran depuis le menu principal.
//
void cIti::debug2(int action)
{
	int i, j, k1, k2;
	char ch[200];
	char c1, c2;
	int dimx=50; // Dimension horizontal d'une cellule, taille pour désignation possible !
	int dimy=18; // Dimension vertical d'une cellule, taille pour désignation possible !
	int decaly=18; // Décalage de l'emplacement du tableau
	int nblignes=25; // Nombre de ligne du tableau (sans le titre)	
	int nbcolonnes=4;

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

	if (action == DEBUG_MOUSE) {	// ACTION = CLIC GAUCHE DE LA SOURIS
		if ((x_mouse > 0 && x_mouse < 97) && (y_mouse > decaly + (nblignes + 3)*dimy + 1 - 2 && y_mouse < decaly + (nblignes + 4)*dimy + 1 - 4 + 2)) { //	Clic dans [CLIC DROIT]
			action = DEBUG_MOUSE_RIGHT; //	Simule le clic-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, on change de page
		if (screen_mode == MD_ECRAN_SEPARE1) screen_mode = MD_ECRAN_SEPARE2;
		else screen_mode = MD_ECRAN_SEPARE1;
		action = DEBUG_TOTAL_PAINT;
	}

	// Comme on affiche la page "SEPARE ou "REGROUPE" de la même façon, on est obligé de tout afficher à chaque fois, (Toute la page = 0,0,700,800).
	// 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);
	SetTextColor(hMemDC, RGB(0, 0, 0)); // Texte noir
	if (screen_mode == MD_ECRAN_SEPARE1) {
		EasyTextOut(2, 2, "AFFICHE LES VALEURS NON NULLES DES PARAMÈTRES DES SEPARATIONS  (100 maximum)"); EasyTextOut(800 - 140, 2, "(QUITTER = ESC)");
		EasyTextOut(2, decaly + (nblignes + 4)*dimy + 1, "SEPARE : Permet de séparer un train pour donner une locomotive + wagons.");
		EasyTextOut(2, decaly + (nblignes + 5)*dimy + 1, "Affiche la description des variables, mais pas leur valeurs qui sont transitoires (raz automatique)");
		EasyTextOut(2, decaly + (nblignes + 6)*dimy + 1, "La mise à 1 de ces variables est équivalent aux gestes fait avec la souris pour une séparation.");
		EasyTextOut(2, decaly + (nblignes + 7)*dimy + 1, "Si 'separe_xx' = 1, provoque la séparation logique du train sur les cantons affichés.");
	}
	else if (screen_mode == MD_ECRAN_SEPARE2) {
		EasyTextOut(2, 2, "AFFICHE LES VALEURS NON NULLES DES PARAMÈTRES DES REGROUPEMENTS  (100 maximum)"); EasyTextOut(800 - 140, 2, "(QUITTER = ESC)");
		EasyTextOut(2, decaly + (nblignes + 4)*dimy + 1, "REGROUPE : Permet de regrouper une locomotive + wagons en un train.");
		EasyTextOut(2, decaly + (nblignes + 5)*dimy + 1, "Affiche la description des variables, mais pas leur valeurs qui sont transitoires (raz automatique)");
		EasyTextOut(2, decaly + (nblignes + 6)*dimy + 1, "La mise à 1 de ces variables est équivalent aux gestes fait avec la souris pour un regroupement.");
		EasyTextOut(2, decaly + (nblignes + 7)*dimy + 1, "Si 'regroupe_xx' = 1, provoque le regroupement logique de loco + wagons sur les cantons affichés.");
	}
	EasyTextOut(2, decaly + (nblignes + 2)*dimy + 1, "Section '#iti'+'separe:' ou 'regroupe:'");
	SelectObject(hMemDC, bmp_stylo_noir); SelectObject(hMemDC, bmp_pinceau_gris220); // Rectangle gris foncé.
	Rectangle(hMemDC, 0, decaly + (nblignes + 3)*dimy + 1 - 2, 97, decaly + (nblignes + 4)*dimy + 1 - 4 + 2);
	SelectObject(hMemDC, bmp_stylo_gris128);
	EasyLine(1, decaly + (nblignes + 4)*dimy + 1 - 4 + 2 - 2, 96, decaly + (nblignes + 4)*dimy + 1 - 4 + 2 - 2);  	// Relief rectangle.
	EasyLine(95, decaly + (nblignes + 3)*dimy + 1 - 2 + 1, 95, decaly + (nblignes + 4)*dimy + 1 - 4 + 2 - 2);	// Relief rectangle.
	SelectObject(hMemDC, bmp_stylo_noir);
	EasyLine(97 - 10, decaly + (nblignes + 4)*dimy + 1 - 4, 97, decaly + (nblignes + 4)*dimy + 1 - 4 - 12 + 2);  // 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 [SEPARATION]<->[REGROUPEMENT].");
	SetTextColor(hMemDC, RGB(255, 0, 0)); // Texte rouge
	for (i = 0; i < nbcolonnes; i++) {
		Rectangle(hMemDC, dimx*(i * 4), decaly, dimx*(1 + (i * 4)) + 1, decaly + dimy + 1);
		Rectangle(hMemDC, dimx*((i * 4) + 1), decaly, dimx*(3 + (i * 4)) + 1, decaly + dimy + 1);
		EasyTextOut(2 + dimx*(i * 4), 2 + decaly, "  n°");
		EasyTextOut(5 + dimx*((i * 4) + 1), 2 + decaly, " Cantons");  // Colonne 'Start' marquée '/' = valeurs modifiables
	}

	if (action==DEBUG_KEY) { }          // ACTION = TOUCHE ENFONCEE = On ne fait rien si une touche est enfoncée.

	SelectObject(hMemDC,bmp_pinceau_blanc); SelectObject(hMemDC,bmp_stylo_blanc);
	SelectObject(hMemDC,bmp_stylo_gris192);
	SetTextColor(hMemDC,RGB(0,0,255));  // Texte Bleu
	for (i=0; i<nbcolonnes; i++) {
		for (j=0; j<nblignes; j++) {
			Rectangle(hMemDC,dimx*(i*4),decaly+dimy*(j+1), dimx*(1+(i*4))+1, decaly+dimy*(j+2)+1);
			sprintf_s(ch,"%2d",j+(i*nblignes));
			if ((screen_mode==MD_ECRAN_SEPARE1) && separe_tab[j+(i*nblignes)][SEPARE_TAB_IND_EXIST]==-1) SetTextColor(hMemDC,RGB(192,192,192));  // Texte gris 192
			if ((screen_mode==MD_ECRAN_SEPARE2) && regroupe_tab[j+(i*nblignes)][REGROUPE_TAB_IND_EXIST]==-1)  SetTextColor(hMemDC,RGB(192,192,192));  // Texte gris 192
			EasyTextOut( 17+dimx*(i*4),3+decaly+dimy*(j+1),ch);			
			SetTextColor(hMemDC,RGB(0,0,255));  // Texte Bleu
			Rectangle(hMemDC,dimx*((i*4)+1),decaly+dimy*(j+1), dimx*(3+(i*4))+1, decaly+dimy*(j+2)+1);
			if (screen_mode==MD_ECRAN_SEPARE1) {
				if (j+(i*nblignes)<SEPARE_TAB_NB && separe_tab[j+(i*nblignes)][SEPARE_TAB_IND_EXIST]!=-1) {
					c1 = 'c'; c2 = 'c';
					k1 = separe_tab[j + (i*nblignes)][SEPARE_TAB_IND_C1];
					k2 = separe_tab[j + (i*nblignes)][SEPARE_TAB_IND_C2];
					if (k1 >= 1000) { c1 = 'g'; k1 = k1 - 1000;	}
					if (k2 >= 1000) { c2 = 'g'; k2 = k2 - 1000;	}
					sprintf_s(ch, "%c%-3d %c%-3d", c1, k1, c2, k2);
					EasyTextOut( 15+dimx*((i*4)+1),3+decaly+dimy*(j+1),ch);			
				}
			}
			else if (screen_mode==MD_ECRAN_SEPARE2) {
				if (j+(i*nblignes)<REGROUPE_TAB_NB && regroupe_tab[j+(i*nblignes)][REGROUPE_TAB_IND_EXIST]!=-1) {
					c1 = 'c'; c2 = 'c';
					k1 = regroupe_tab[j + (i*nblignes)][REGROUPE_TAB_IND_C1];
					k2 = regroupe_tab[j + (i*nblignes)][REGROUPE_TAB_IND_C2];
					if (k1 >= 1000) { c1 = 'g'; k1 = k1 - 1000;	}
					if (k2 >= 1000) { c2 = 'g'; k2 = k2 - 1000;	}
					sprintf_s(ch, "%c%-3d %c%-3d", c1, k1, c2, k2);
					EasyTextOut( 15+dimx*((i*4)+1),3+decaly+dimy*(j+1),ch);			
				}
			}
		}
	}
}
		