
// UTS  2000 Fichier Train_'UTS_V01.cpp' Programme principal
// V3.7f - Le 22/09/2019
//
//                      UTS : Ulysse Train System
//
/*
Compilation du programme UTS 2000 (Ulysse Train System)
Compilation sous Windows Visual C++ Express (version gratuite)

Application Console = Application sous interface DOS
Application Windows = APIWIN32 avec interface graphique

Le programme fonctionne en mode Windows APIWIN32 Graphique
Pas de prise en charge de MFC (Microsoft class Library) ni ACTL

Configuration spéciale et obligatoire pour accepter du code C :

   Menu : Projet > Propriétés  
      Propriétés de configuration > Général
           Paramètres par défaut du projet > Jeu de caractères = Non défini

		   Attention pour être aussi compatible avec Windows XP dans Visual Studio Express 2013,
    menu : PROJET > Propriétés de Train_UTS_V3.5 > Propriétés de Configuration > 
	       Générale > Ensemble d'outils de plateforme = "Visual Studio 2013 - Windows XP (v120_xp)".


Par défaut, Visual C++ 2005/2008 linke dynamiquement l'exécutable contre la C Runtime Library 
(la bibliothèque C de Visual Studio). Il en résulte que le programme obtenu a besoins des DLL de Visual Studio pour fonctionner.
Vous pouvez configurer votre projet pour que votre exécutable soit linké statiquement contre la C Runtime Library :
 (Project properties -> Configuration -> C/C++ -> Code generation -> Runtime Library -> sélectionner "Multithread (/MT)" au lien de "Multithread DLL (/MD)").
*/

#include <windows.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "canton.h"
#include "exe.h"
#include "garage.h"
#include "serial_port.h"
#include "tdv.h"
#include "train.h"
#include "selectif.h"
#include "aigauto.h"
#include "balauto.h"
#include "deplacement.h"
#include "iti.h"
#include "Train_UTS.h"

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

HINSTANCE ghinstance;
HWND      hwnd;               /* This is the handle for our window */
HDC       hdc_ori;
HFONT     la_fonte;		//
HFONT     cells_font;		// Font = Police + taille + aspect + orientation + ...
HFONT     aide_font;		//

HDC       hMemDC;
HBITMAP   hMemBmp;
HGDIOBJ   hOldBmp;

// Déclaration des classes externes
extern cCanton      canton;
extern cExe         ThisExe;
extern cGarage      garage;
extern cSerial      serial;
extern cSerialPort  serialPort;
extern cTdv         tdv;
extern cTrain       train;
extern cSelectif    selectif;
extern cAigauto     aigauto;
extern cBalauto     balauto;
extern cDeplacement deplacement;
extern cIti         iti;

// Déclaration des fonctions externes
extern void init_fonte_pen_brush(void);
extern void bmp_select_brush(int no_color);
extern void bmp_select_brush(HDC h_dc_,int no_color);
extern void bmp_select_pen(HDC h_dc_,int no_color);
extern void bmp_select_pen(int no_color);
extern void bmp_SetTextColor(int no_color);
extern void bmp_fond_default(void);
extern void font_pinceau_stylo_init(void);
extern void EasyTextOut(int, int, char*);
extern void EasyLine(int, int, int, int); 
//extern void dessine_picto(int, int, int, int, int, int, int);


extern void config_general_exit_if_no_file(char[]);
extern void config_general_init_file(char[]);

extern void pio_init(void);
extern  int pio_var_ch2int(char []);
extern  int pio_var_ch2int_(char []);
extern  int pio_set_val(int ,int);
extern  int pio_get_val(int);
extern  int pio_get_val_(int);
extern  int pio_var_int2ch(int ,char []);
extern  int pio_define_convert(char [],char []);

extern void vib_init_file(char[]);
extern void vib_maj(void);
extern void vib_debug(int);

extern void horo_init_file(char filename[]);
extern void horo_save_conf(void);
extern void horo_maj(void);
extern void horo_debug_r(int action);
extern void horo_debug_l(int action);

extern void aig_init_file(char filename[]);
extern void aig_save_conf(void);
extern void aig_maj(void);
extern void aig_debug(int action);
extern  int aig_descr_info[NB_AIG][AIG_DESCR_INFO_IND_NB];


extern void serial_debug(int action);
extern void pot_vir_debug(int action);
extern void ir_maj(void);

extern void srv_maj(void);
extern void srv_debug(int action);

extern void special_var_tick(void);
extern void var_debug(int action);

extern  int rendu_need_grostrait(int c);
extern  int rendu_need_fleche(int c);
extern  int rendu_select_brush_for_canton(int c);
extern void rendu_select_pen_for_canton(int c);
extern void rendu_little_rect(int x,int y, int color);
extern void private_cells_draw_one(int type, int subtype, int x, int y, char szTxt[], int cant, int n1, int n2,  int v1, int v2, int v3, int v4, int c1,int c2, int c3, int c4, int opt, int sens);
extern void ecran_init_file(char [], int*, int*, int*);
extern void draw_fleche(char* sz, int x, int y);
extern void canton_maj_profil(void);
extern void iti2_tick(void);
extern int get_line(FILE*, char [][CHAR_CONFIG_NB], int*);
extern void log(char* sz);

// Déclaration des fonctions internes
//void update_copy_canton(void);
//void update_copy_train(void);


// Déclaration des variables.
extern int iti_tab[ITI_TAB_NB][ITI_TAB_IND_TAILLE];	
	// Tableau des itinéraires.
	// iti_tab[<Numéro d'itinéraire>][].
	// iti_tab[][ITI_TAB_IND_EXIST 0] = 0-1, 1 = L'itinéraire existe.
	// iti_tab[][ITI_TAB_IND_TYPE  1] = 
	// iti_tab[][ITI_TAB_IND_START 2] = 0-1, 1 = Demande de lancement de l'itinéraire.
	// iti_tab[][ITI_TAB_IND_STOP  3] = 0-1, 1 = Demande d'arrêt de l'itinéraire.
	// iti_tab[][ITI_TAB_IND_STEP  4] = ITI_CST_STATE_IDLE          0 = 
	//                                  ITI_CST_STATE_WAIT_CANT_DEP 1 = 
	//                                  ITI_CST_STATE_WAIT_RES      2 = 
	//                                  ITI_CST_STATE_WAIT_VER      3 = 
	//                                  ITI_CST_STATE_WAIT_CANT_FIN 4 = 
	//                                  ITI_CST_STATE_WAIT_WAIT     5 = 
	//                                  ITI_CST_STATE_WAIT_STOP     6 = 
	//                                  ITI_CST_STATE_RELEASE       7 = 
	// iti_tab[][ITI_TAB_IND_TEMPO      5] = Temps restant en 'tick' avant la fin de l'itineraire après détection des conditions de fin.
	// iti_tab[][ITI_TAB_IND_WAIT       6] = 0-1, 1 = L'itinéraire est en pause. Attend la libération d'un canton ou d'un aiguillage.
	// iti_tab[][ITI_TAB_IND_OK         7] = 
	// iti_tab[][ITI_TAB_IND_CANT_START 8] = 
	// iti_tab[][ITI_TAB_IND_CANT_STOP  9] = 

extern int serial_error; // Compteur d'erreur RS232, erreur de liaison avec la carte.
extern int serial_tab_cmd[4][5];
extern int serial_tab_adresse[4][5];
extern int serial_tab_data[4][5];
extern int tab_auto_read[4][4];

int x_mouse,y_mouse,touche,touche_char,x_mouse_move,y_mouse_move;
int pulse_tab[NB_PULSE][10]; // on w1 a1 w2 a2 w3 out1 out2 (phase tempo)
int pulse_no;

extern int pio_var[NB_VAR];
extern int special_var[NB_SPECIAL_VAR];
extern int pio_tdv_on_off[NB_TDV];  // Table de vérité en fonction si =1.
extern int pio_tdv_ind[NB_TDV+1];	 // Vadidité d'un table de vérité. -1 = invalide ou indicateur d'offset de cette table dans 'pio_tab[]'.
extern int pio_pulse_cmd[NB_PULSE];

int moins_char_normal=0;   // 1: - est un caractere normal (comme 0)  0: - est un separateur (comme +)
//char* TabSzScreenMode[]= { "tco0", "tco1", "tco2", "tco3", "tco4", "tco5", "tco6", "tco7","horloge", "rs232", "aig", "iti", "selectif", 
//                           "depl", "regu", "cantons", "vib" };
int screen_mode=MD_ECRAN_TCO0;			// Ecran affiché au démarrage d'UTS.
int screen_mode_retour=MD_ECRAN_TCO0;		// Ecran de retour si on tape la touche 'Esc' sur une fenêtre de debug.

int timer_prg=TIMER_PRG;      // Pas d'activation d'UTS en msec. Cadence UTS et le transfert de trame vers la carte.
                              // Durée du timer d'activation du programme = 250 msec en 2.0, 80 msec en V3.3

extern int horo_j,horo_j_dep;    //global    //0-6    //horaire de départ: 7=week 8=weekend
extern int horo_h,horo_h_dep;    //global    //0-23
extern int horo_m,horo_m_dep;    //global    //0-59
extern int horo_tab[HORO_TAB_NB][HORO_TAB_IND_TAILLE];
extern int horo_tic_min; //4s_reel/min  4min_reel/h  48min_reel/j
extern int horo_tic_dec;
extern int horo_tic_on;            //global
extern int horo_blocked;           //global

/* variables  */
int cfg_show_cards_found=0;	// (0 par défaut) si=1 Au démarrage du programme, on affiche une fenêtre avec les numéros des cartes UTS détectées
int cfg_aigauto=1;          // (1 par défaut) si=1 On active la configuration de la section "#aigauto", aiguillages automatiques.
int cfg_relief;             // =0 => UTS normal, =1 => UTS en relief (par défaut).
int cfg_memoire_pos_train=0;  // (0 par défaut), =1 => UTS sauvegarde et récupére la position des trains sur le réseau, à la fermeture et ouverture du preogramme UTS.
int cfg_memoire_pos_aig=0;    // (0 par défaut), =1 => UTS sauvegarde et récupére la position des aiguillages sur le réseau, à la fermeture et ouverture du preogramme UTS.

int vio_can[NB_CARTE][NB_CAN];					// 0-255, valeurs lues sur la carte par le programme pour les entrées analogiques 
int cfg_can_inv[NB_CARTE][NB_CAN]={{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0}};

int vio_in[NB_CARTE][NB_IN];					// 0-1, valeurs lues sur la carte par le programme pour l'état des entrées (0à35(Entrées MUX)  40à79(Entrées directes[2])).

int vio_out[NB_CARTE][NB_OUT];					// 0-1, valeurs calculées par le programme pour activer les sorties.

int vio_det[NB_CARTE][NB_CANTON];				// 0-1, 1 = canton occupé, valeurs acquises.
int det_elabore[NB_CARTE][NB_CANTON];			// 0-1, 1 = canton occupé  (avec temporisation), utilisé pour l'affichage des feux tricolore.
int det_elaborep[NB_CARTE][NB_CANTON];			// 0-1, 1 = canton occupé  (avec temporisation), utilisé pour l'affichage des feux tricolore. Vitesse train > 0.
int det_elaborem[NB_CARTE][NB_CANTON];			// 0-1, 1 = canton occupé  (avec temporisation), utilisé pour l'affichage des feux tricolore. Vitesse train < 0.
int vio_bal_cant_p[NB_CARTE][NB_CANTON];		// 0-1, =1 => Bloc automatique - Canton bloqué dans le sens Plus.
int vio_bal_cant_m[NB_CARTE][NB_CANTON];		// 0-1, =1 => Bloc automatique - Canton bloqué dans le sens Moins.
int color_canton[NB_CARTE][NB_CANTON];
int vio_canton_vit[NB_CARTE][NB_CANTON];		// Valeurs brutes pour être envoyées vers la carte pour alimenter les cantons
int vio_canton_vit_profil[NB_CARTE][NB_CANTON];	// Valeurs envoyées vers la carte pour alimenter les cantons (après calcul du profil d'alimentation de la locomotive).
int copy_res_auto[NB_CARTE][NB_CANTON];
int copy_num_train[NB_CARTE][NB_CANTON];
int canton_pb_capt[NB_CARTE][NB_CANTON];		// 0-1, =1 si le train n'est pas dectecté sur le canton alors qu'il devrait être présent.
int copy_allowed_sens[NB_CARTE][NB_CANTON];
int copy_master_selectif[NB_CARTE][NB_CANTON];
int copy_update_selectif[NB_CARTE][NB_CANTON];

int vio_led[NB_CARTE][NB_LED];					// 0-1, valeurs calculées par le programme pour allumer les leds.
int vio_led_cli[NB_CARTE][NB_LED];				// 0-1, valeurs calculées par le programme pour faire clignoter les leds.
int vio_led_phase[NB_CARTE][NB_LED];			// 0-1, valeurs calculées par le programme pour faire clignoter les leds en opposition de phase.

int cfg_enable_leds[NB_CARTE]={ 1,1,1,1};

#ifndef VERSION_UTS_V3 // Ne pas toucher à cette ligne !!!
int cfg_enable_servos[NB_CARTE][NB_SERVO]={ {0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0} };
#endif
int vio_srv[NB_CARTE][NB_SERVO];				// 0-255, valeurs envoyées vers la carte. Ces variables atteignent lentement les valeurs de consigne.
int vio_srv_res[NB_CARTE][NB_SERVO];			// 0-1, Reservation d'un servo, si =1 le servo est reservé dans le cadre d'un déplacement avec verrouillage.
int vio_srv_cmd[NB_CARTE][NB_SERVO+NB_SERVO_VIT];	// 1ére partie = 0-255, valeurs de consigne fixes calculées, pour les 5 servos-moteur. 
													// 2éme partie = -1023 à +1023 = Pas de déplacement du servo pour régler la vitesse de déplacement.

//autres
int vio_pot_virtual_step[NB_POT_VIR]={0,0,0,0,0}; //UU_NEW
// Potentiomètres virtuels commandés par le clavier. vio_pot_virtual_conf[x][0] = caractère pour accélerer, [x][1] = pour arreter,  [x][2] = pour ralentir.
int vio_pot_virtual_conf[NB_POT_VIR][3]={ {0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0} }; 

int vio_aig_res[NB_AIG];		// Si = 1 => L'aiguillage est reservé, sert aux déplacements, pour réserver tous les aiguillages avant de déplacer le train.
int vio_aig_cmd[NB_AIG];		// 
int vio_aig_pos0[NB_AIG];		// Si = 1 => L'aiguillage 'n' en position '0'.
int vio_aig_pos1[NB_AIG]; 		// Si = 1 => L'aiguillage 'n' en position '1'.


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).
int vio_garage_lock_res[NB_GARAGE];    // 0 ou 1, 1 => Garage réservé.
int vio_garage_lock_status[NB_GARAGE]; // 0 ou 1, 1 => Le garage est isolé du canton (état réel).

int vio_selectif_new_pot=-1;
int vio_selectif_new_reg=-1;

int depl_tab[DEPL_TAB_NB][DEPL_TAB_IND_TAILLE];
int depl_acc_dec[DEPL_TAB_INERTIE_NB]; // Accélération et décélération pour tous les déplacements.

int special_seq_feu;		// Variables globales utilisées dans 'ss_pgr.cpp'. Sert à élaborer les variables spéciales.
int special_seq_2, special_seq_3, special_seq_4, special_seq_5, special_seq_6, special_seq_10;
int special_sens_11a=1, special_sens_12a=1, special_sens_21a=1, special_sens_22a=1;
int special_sens_11b=1, special_sens_12b=1, special_sens_21b=1, special_sens_22b=1;

int vib_on=0;      //dans pio
int vib_state=0;   //dans pio
int vib_var=-1;
int vib_var_inv=0;
int vib_pwm_no=-1;
int vib_pwm_vit=-1;
int vib_time_before=8;
int vib_time_after=8;
int vib_dec_before=0;
int vib_dec_after=0;

int arret_urg_on=0;      //dans pio
int arret_urg_on_old=0; // Pour comparer et voir si la variable a changer.
/* recopie les variables menbres de canton car classe en dessous de TCO*/
int color_train[NB_TRAIN];
int  train_pb_capt[NB_TRAIN]; // 0 ou 1, 1 => Le train n'est pas détecté sur les cantons.
char copy_train_name[NB_TRAIN][10];

int  copy_garage_num_train[NB_GARAGE];
int  copy_garage_ass_canton[NB_GARAGE];
int  rendu[RENDU_TAILLE];
int  cells_tick=0;
int  cells[CELLS_TCO_NB][CELLS_X_NB][CELLS_Y_NB][CELLS_ENR_NB];
char sz_cells[CELLS_TCO_NB][CELLS_X_NB][CELLS_Y_NB][CELLS_SZ_LEN];

HDC h_dc_mem_cells;
//DEBUG
//int selected_card=0;
//int selected_can_and_card=-1;
int debug_tic_nb=0;
//int atoh(char ch[])
extern int infrarouge;
int cells_pouss_en_cours=-1;		// Variable V1 = Pour débuter une action quand le bouton de souris est enfoncé, et l'arrêter quand on le relache.
int cells_pouss_en_cours_srv=-1;	// =1  pour modifier une variable de type -1023à+1023 ou =0 pour des variables numériques.


int aig_enable;
int aig_cpt;
int aig_state;
int aig_select;
int aig_pos_select;
int nb_selectif_lus;	// Pour connaitre le nombre de terme Cx:+- lus dans la partie '#selectif' de 'config.txt' pour ne pas dépasser la limite de 100. (Ajouter +1 pour avoir le nombre).
int nb_aigauto_lus;		// Pour connaitre le nombre de lignes lus dans la partie '#aigauto' de 'config.txt' pour ne pas dépasser la limite de 100. (Ajouter +1 pour avoir le nombre).
int nb_exe_lus;			// Nombre d'élements 'exeXX' lus dans config.txt

int nb_balauto_vitmax_lus;
int nb_balauto_halt_lus;
int balauto_vitmax_train[NB_TRAIN]; // En cas de limitation de vitesse d'un train '#balauto' + 'vitmax:' = 1 => Train en 'vitmax:'.
int balauto_halt_train[NB_TRAIN];   // En cas de halte d'un train sur un canton '#balauto' + 'halt:' = 1 => Train en 'halt:'.
int balauto_cant_train[NB_TRAIN];   // En cas de blocage d'un train sur un canton '#balauto' +'cant:' = 1 => Consigne vitesse du train = 0.
int balauto_cant_train_dec[NB_TRAIN];   // -1 ou 1 à 28 = décélération du train sur 'cant:'.
int balauto_cant_train_ral[NB_TRAIN];   // -64 à 64 = ralenti du train sur 'cant:'.
int cfg_tempo_libe_cant; // 0 à 99 = Temporisation pour libérer un canton. Valeur lue dans 'config.txt'.

int tdv_deb;	// Programme debug.tdv Sur la page débug, numéro de la premiere table de vérité à afficher.
int num_cant_a_lib;	// Numéro de canton à libérer dans debug2 uniquement.

// Variable de débug.
extern int serial_debug_led[NB_CARTE][NB_LED];				//
extern int serial_debug_led_cli[NB_CARTE][NB_LED];			//
extern int serial_debug_led_phase[NB_CARTE][NB_LED];		//
extern int serial_debug_select_led[NB_CARTE][NB_LED];		//


extern int serial_debug_canton_vit[NB_CARTE][NB_CANTON];
extern int serial_debug_select_canton_vit[NB_CARTE][NB_CANTON];
int serial_debug_out[NB_CARTE][NB_OUT];		// 0-1, valeurs manuelles saisies dans l'écran RSR232 pour les sorties
int serial_debug_select_out[NB_CARTE][NB_OUT];	// 0-1, Utilisé dans l'écran RS232,si = 1 les valeurs saisies remplacent les valeurs pour les sorties.
extern int serial_debug_srv[NB_CARTE][NB_SERVO];
int cmd_divers[CMD_DIVERS_TAILLE];   // Tableau pour commander directement les déplacements par clic sur les cases du TCO.

int acc_progressif[NB_PROGRESSIF]; // Tableau pour une accélération progressive.
int dec_progressif[NB_PROGRESSIF]; // Tableau pour une déccélération progressive.
int connecte; // 0 = pas de carte, 1 = au moins une carte




/*****************************************************************************/
/* BMP VOY                                                                   */
/*****************************************************************************/
HDC       bmp_h_dc_mem;
HDC       bmp_h_dc_fond_0;
HDC       bmp_h_dc_fond_1;
HDC       bmp_h_dc_fond_2;
HDC       bmp_h_dc_fond_3;
HFONT     bmp_fonte;

HBRUSH    bmp_pinceau_, bmp_pinceau_noir, bmp_pinceau_bleu, bmp_pinceau_vert, bmp_pinceau_cyan, bmp_pinceau_rouge, bmp_pinceau_violet;
HBRUSH    bmp_pinceau_jaune, bmp_pinceau_blanc, bmp_pinceau_rougef, bmp_pinceau_vertfluo, bmp_pinceau_orange, bmp_pinceau_marron;
HBRUSH    bmp_pinceau_kaki, bmp_pinceau_bleuf, bmp_pinceau_grisvert, bmp_pinceau_vertfonce, bmp_pinceau_gris32, bmp_pinceau_gris64, bmp_pinceau_gris128;
HBRUSH    bmp_pinceau_gris192, bmp_pinceau_griswin, bmp_pinceau_magenta, bmp_pinceau_magentaf, bmp_pinceau_cyanf, bmp_pinceau_vertdeau;
HBRUSH    bmp_pinceau_lilas, bmp_pinceau_bleulagon, bmp_pinceau_verttendre, bmp_pinceau_rosefluo, bmp_pinceau_saumon, bmp_pinceau_rose;
HBRUSH    bmp_pinceau_gris220, bmp_pinceau_gris230, bmp_pinceau_gris240;
HBRUSH    bmp_pinceau_bleuf2, bmp_pinceau_jauneclair,bmp_pinceau_bleuf3;

HPEN      bmp_stylo_, bmp_stylo_noir, bmp_stylo_bleu, bmp_stylo_vert, bmp_stylo_cyan, bmp_stylo_rouge, bmp_stylo_violet;
HPEN      bmp_stylo_jaune, bmp_stylo_blanc, bmp_stylo_rougef, bmp_stylo_vertfluo, bmp_stylo_orange, bmp_stylo_marron;
HPEN      bmp_stylo_kaki, bmp_stylo_bleuf, bmp_stylo_grisvert, bmp_stylo_vertfonce, bmp_stylo_gris32, bmp_stylo_gris64, bmp_stylo_gris128;
HPEN      bmp_stylo_gris192, bmp_stylo_griswin, bmp_stylo_magenta, bmp_stylo_magentaf, bmp_stylo_cyanf, bmp_stylo_vertdeau;
HPEN      bmp_stylo_lilas, bmp_stylo_bleulagon, bmp_stylo_verttendre, bmp_stylo_rosefluo, bmp_stylo_saumon, bmp_stylo_rose;
HPEN      bmp_stylo_gris220, bmp_stylo_gris230, bmp_stylo_gris240;
HPEN      bmp_stylo_bleuf2, bmp_stylo_jauneclair, bmp_stylo_bleuf3;



/* int       bmp_cli=0;
int       bmp_rgb_color[9][3]={ {  0,  0,  0}, {  0,  0,255}, {  0,255,  0},
                                {  0,255,255}, {255,  0,  0}, {255,  0,255},
                                {255,255,  0}, {255,255,255}, {192,192,192} };
unsigned long  bmp_rgb[9]={ RGB(  0,  0,  0), RGB(  0,  0,255), RGB(  0,255,  0),
                            RGB(  0,255,255), RGB(255,  0,  0), RGB(255,  0,255),
                            RGB(255,255,  0), RGB(255,255,255), RGB(192,192,192) };*/


/*****************************************************************************/
/* TCO                                                                       */
/*****************************************************************************/

// Sous programme pour initialiser les tableaux TCO en mémoire à partir du fichier 'config_tco.txt'.
//
//
// Ligne du fichier 'config_tco.txt' :
// x=02 y=10 data:   -1   -1   -1   -1   -1   -1   -1   -1   -1   -1   -1   -1   -1   -1   -1 string= "                    "
//
// Un TCO est constitué de cellule : cells[c][x][y][e]
// = cells [Numéro_du_TCO] [Position_X_du_bloc][Position_Y_du_bloc][Numéro_de_variable_du_bloc]
//            0 à 8           0 à 32               0 à 25                0 à 14
//
// Numéro_de_variable_du_bloc possibles :
//CELLS_TYPE     
//   CELLS_TYPE_RIEN   -1		// Bloc pas encore renseigné.
//   CELLS_TYPE_LINK   0		// Bloc de type 'Voie'
//   CELLS_TYPE_AIG    1		// Bloc de type 'Aiguillage'
//   CELLS_TYPE_CMDVOY 2		// Bloc de type 'Commande ou voyant'
//   CELLS_TYPE_SPE    3		// Bloc de type 'Spécial'
//
// SI CELLS_TYPE==CELLS_TYPE_LINK  :  CELLS_SUBTYPE = 
//    CELLS_SUBTYPE_LINK_H       0	// Différents Eléments de voies 
//    CELLS_SUBTYPE_LINK_V       1, //    CELLS_SUBTYPE_LINK_SONE    2, //    CELLS_SUBTYPE_LINK_NOSE    3, //    CELLS_SUBTYPE_LINK_SE      4
//    CELLS_SUBTYPE_LINK_OS      5, //    CELLS_SUBTYPE_LINK_NE      6, //    CELLS_SUBTYPE_LINK_ON      7, //    CELLS_SUBTYPE_LINK_SOE     8, 
//    CELLS_SUBTYPE_LINK_OSE     9, //    CELLS_SUBTYPE_LINK_NOE    10, //    CELLS_SUBTYPE_LINK_ONE    11, //    CELLS_SUBTYPE_LINK_BALA   12,
//    CELLS_SUBTYPE_LINK_SON    13, //    CELLS_SUBTYPE_LINK_NSE    14, //    CELLS_SUBTYPE_LINK_NOS    15, //    CELLS_SUBTYPE_LINK_SNE    16
//    CELLS_SUBTYPE_LINK_PH     17, //    CELLS_SUBTYPE_LINK_PV     18, 
//
// SI CELLS_TYPE==CELLS_TYPE_AIG  :  CELLS_SUBTYPE = 
//    CELLS_SUBTYPE_AIG_CH     0  // Différents aiguillages
//    CELLS_SUBTYPE_AIG_CB     1, //    CELLS_SUBTYPE_AIG_CHB    2, //    CELLS_SUBTYPE_AIG_HC     3, //    CELLS_SUBTYPE_AIG_BC     4
//    CELLS_SUBTYPE_AIG_HBC    5, //    CELLS_SUBTYPE_AIG_HCV    6, //    CELLS_SUBTYPE_AIG_CHV    7, //    CELLS_SUBTYPE_AIG_CBV    8
//    CELLS_SUBTYPE_AIG_BCV    9
//
// SI CELLS_TYPE==CELLS_TYPE_CMDVOY  :  CELLS_SUBTYPE = 
//    CELLS_SUBTYPE_CMDVOY_POUSS 0	// Voyants carré et/ou boutons poussoirs
//    CELLS_SUBTYPE_CMDVOY_INT   1	// Voyants carré et/ou interrupteurs
//    CELLS_SUBTYPE_CMDVOY_ITI   2	// Voyants rond à bordure active
//    CELLS_SUBTYPE_CMDVOY_VOY4  3	// 4 voyants carrés
//    CELLS_SUBTYPE_CMDVOY_LABEL 4	// Bloc de texte (4 lignes de texte)
//    CELLS_SUBTYPE_CMDVOY_VOY2  5	// 2 voyants ronds
//    CELLS_SUBTYPE_CMDVOY_VOY1  6	// 1 voyant rond
//    CELLS_SUBTYPE_CMDVOY_GO    7	// Bloc pour aller directement à une autre page (horizontal)
//    CELLS_SUBTYPE_CMDVOY_SRV   8	// Bloc pour comander les servo moteurs
//    CELLS_SUBTYPE_CMDVOY_VAL   9	// Bloc pour afficher 3 lignes de texte + 1 valeur numérique
//
// SI CELLS_TYPE==CELLS_TYPE_SPE  :  CELLS_SUBTYPE = 
//    CELLS_SUBTYPE_SPE_VOY     0		// Voie + état d'occupation du canton (horizontal)
//    CELLS_SUBTYPE_SPE_DETEL   1		// Voie + affiche un dételeur (pas utilisé)(horizontal)
//    CELLS_SUBTYPE_SPE_CANT    2		// Voie + affiche les valeurs propre à un canton (horizontal)
//    CELLS_SUBTYPE_SPE_IN      3		// Voie + contact au passage du train (horizontal)
//    CELLS_SUBTYPE_SPE_OUT     4		// Voie + signal envoyé par le programme (pas utilisé)(horizontal)
//    CELLS_SUBTYPE_SPE_SENS    5		// Voie + impose le sens de parcours (horizontal)
//    CELLS_SUBTYPE_SPE_CH      6		// Voie + butoir (horizontal)
//    CELLS_SUBTYPE_SPE_HC      7		// Voie + butoir (horizontal)
//    CELLS_SUBTYPE_SPE_HOR     8		// Bloc d'horloge
//    CELLS_SUBTYPE_SPE_FEU     9		// Voie + feu tricolore (vertical)
//    CELLS_SUBTYPE_SPE_CV     10		// Voie + butoir (vertical)
//    CELLS_SUBTYPE_SPE_VC     11		// Voie + butoir (vertical)
//    CELLS_SUBTYPE_SPE_VOYV   12		// Voie + état d'occupation du canton (vertical)
//    CELLS_SUBTYPE_SPE_CANTV  13		// Voie + affiche les valeurs propre à un canton (vertical)
//    CELLS_SUBTYPE_SPE_INV    14		// Voie + contact au passage du train (vertical)
//    CELLS_SUBTYPE_SPE_OUTV   15		// Voie + signal envoyé par le programme (pas utilisé)(vertical)
//    CELLS_SUBTYPE_SPE_SENSV  16		// Voie + impose le sens de parcours (vertical)
//    CELLS_SUBTYPE_SPE_FEUV   17		// Voie + feu tricolore  (vertical)
//
//
//    CELLS_CANT     2  => Numéro du canton 000 à 315  (-1 = pas renseigné).
//
//    CELLS_N1       3  => Variable temporaire propre à un bloc lors de calcul dans le programme.
//    CELLS_N2       4
//
//    CELLS_V1       5  => Variable V1 = Contenu de cette variable a prendre en compte pour animer le bloc
//    CELLS_V2       6  => Variable V2   ou un action sur ce bloc modifie le contenu de cette variable.
//    CELLS_V3       7  => Variable V3   (-1 = pas renseigné).
//    CELLS_V4       8  => Variable V4   //
//
//    CELLS_C1       9  => Variable C1 = 0-15 => Couleur propre à un élément de ce bloc (-1 = pas renseigné).
//    CELLS_C2      10  => Variable C2   //
//    CELLS_C3      11  => Variable C3   //
//    CELLS_C4      12  => Variable C4   //
//
//    CELLS_OPT     13  => Variable pour une option sur certains bloc (-1 = pas renseigné)
//
//    CELLS_SENS    14  => 0/1 => Défini le sens du bloc pour afficher des flèches sur les élémenst de voie. (-1 = pas renseigné)
//
//


void cells_config(char sz_filename[])
{
	int i, j, c, x, y, e, num_train;
	FILE* pf;
	char szTemp[100];
	char cTemp;
	char ch_tab[BLOC_CONFIG_NB][CHAR_CONFIG_NB];

	h_dc_mem_cells = CreateCompatibleDC(hMemDC); // je me demande si cette ligne sert vraiment !

	// Mets à '-1' toutes les paramétres numériques des toutes les cellules du TCO actif en mémoire
	for (c = 0; c < CELLS_TCO_NB; c++) for (x = 0; x < CELLS_X_NB; x++) for (y = 0; y < CELLS_Y_NB; y++) for (e = 0; e < CELLS_ENR_NB; e++) {
		cells[c][x][y][e] = -1;
	}
	// Mets à ' ' le paramétre 'chaine alphanumériques' des toutes les cellules du TCO actif en mémoire
	for (c = 0; c < CELLS_TCO_NB; c++) for (x = 0; x < CELLS_X_NB; x++) for (y = 0; y < CELLS_Y_NB; y++) strcpy(sz_cells[c][x][y], "                    ");

	for (i = 0; i < RENDU_TAILLE; i++) rendu[i] = 0;
	for (j = 0; j < NB_CARTE; j++) for (i = 0; i < NB_CANTON; i++) color_canton[j][i] = 0;
	//    for(i=0;i<NB_TRAIN_COULEUR;i++) color_train[i]=-1; // Couleur des trains.
	for (i = NB_TRAIN_COULEUR; i < NB_TRAIN; i++) color_train[i] = BMP_CST_COLOR_MAGENTA; // Couleurs des wagons.

	// Lit le fichier 'config_tco.txt' pour récupérer les paramètres de tous les TCO.
	// et en fin de fichier, les paramètres 'rendu data' pour les couleurs.
	// La couleur de ces rendus sont définis à la fin du fichier 'config_tco.txt'
	// Ils sont modifiables depuis le menu : 'Modifications > Rendu TCO'.
	// Chaque rendu est associé à une couleur.
	// 'c' = numéro de TCO en cours de lecture.
	pf = fopen(sz_filename, "rt");

	// Si pas de fichier 'config_tco.txt', on donne des couleurs et les rendus par défaut.
	if (pf == NULL) { 
		rendu[RENDU_COLOR_RAIL_LIBRE]    = BMP_CST_COLOR_NOIR;
		rendu[RENDU_COLOR_FOND_LIBRE]    = BMP_CST_COLOR_BLANC;
		rendu[RENDU_USE_GROS_LIBRE]      = 0;
		rendu[RENDU_USE_FLECHE_LIBRE]    = 1;

		rendu[RENDU_COLOR_RAIL_OCC]      = BMP_CST_COLOR_NOIR;
		rendu[RENDU_COLOR_FOND_OCC]      = BMP_CST_COLOR_ROUGE;
		rendu[RENDU_USE_GROS_OCC]        = 0;
		rendu[RENDU_USE_FLECHE_OCC]      = 1;

		rendu[RENDU_COLOR_RAIL_SELPREV]  = BMP_CST_COLOR_TRAIN;
		rendu[RENDU_COLOR_FOND_SELPREV]  = BMP_CST_COLOR_GRISWIN;
		rendu[RENDU_USE_GROS_SELPREV]    = 0;
		rendu[RENDU_USE_FLECHE_SELPREV]  = 1; 

		rendu[RENDU_COLOR_RAIL_SELOCC]   = BMP_CST_COLOR_TRAIN;
		rendu[RENDU_COLOR_FOND_SELOCC]   = BMP_CST_COLOR_BLANC;
		rendu[RENDU_USE_GROS_SELOCC]     = 1;
		rendu[RENDU_USE_FLECHE_SELOCC]   = 1; 
	
		rendu[RENDU_COLOR_RAIL_AUTOPREV] = BMP_CST_COLOR_TRAIN;
		rendu[RENDU_COLOR_FOND_AUTOPREV] = BMP_CST_COLOR_JAUNE;
		rendu[RENDU_USE_GROS_AUTOPREV]   = 0;
		rendu[RENDU_USE_FLECHE_AUTOPREV] = 1;
	
		rendu[RENDU_COLOR_RAIL_AUTOOCC]  = BMP_CST_COLOR_TRAIN;
		rendu[RENDU_COLOR_FOND_AUTOOCC]  = BMP_CST_COLOR_JAUNE;
		rendu[RENDU_USE_GROS_AUTOOCC]    = 1;
		rendu[RENDU_USE_FLECHE_AUTOOCC]  = 1;
	
		rendu[RENDU_COLOR_RAIL_GARALOCK] = BMP_CST_COLOR_TRAIN;
		rendu[RENDU_COLOR_FOND_GARALOCK] = BMP_CST_COLOR_GRIS64;
		rendu[RENDU_USE_GROS_GARALOCK]   = 0;
		rendu[RENDU_USE_FLECHE_GARALOCK] = 0; // Pas utilisé.
	
		rendu[RENDU_COLOR_FOND]      =  BMP_CST_COLOR_BLANC;
		rendu[RENDU_COLOR_FOND_RAIL] =  BMP_CST_COLOR_BLANC;
		rendu[RENDU_COLOR_GRILLE]    =  BMP_CST_COLOR_GRISWIN;
		rendu[RENDU_COLOR_TEXT]      =  BMP_CST_COLOR_VIOLET;

		rendu[RENDU_COLOR_DET_ON]    =  BMP_CST_COLOR_ROUGE;
		rendu[RENDU_COLOR_DET_OFF]   =  BMP_CST_COLOR_GRISWIN;   
		rendu[RENDU_COLOR_AIG_ON]    =  BMP_CST_COLOR_JAUNE;   
		rendu[RENDU_COLOR_AIG_OFF]   =  BMP_CST_COLOR_GRISWIN;

		rendu[RENDU_COLOR_VOY_ON]    =  BMP_CST_COLOR_VERT;
		rendu[RENDU_COLOR_VOY_OFF]   =  BMP_CST_COLOR_ORANGE;
		rendu[RENDU_COLOR_INT_ON]    =  BMP_CST_COLOR_VERT;    
		rendu[RENDU_COLOR_INT_OFF]   =  BMP_CST_COLOR_GRIS128;    

		rendu[RENDU_COLOR_IPP_ON]      = BMP_CST_COLOR_CYAN;
		rendu[RENDU_COLOR_IPP_OFF]     = BMP_CST_COLOR_GRISWIN;
		rendu[RENDU_COLOR_IPP_LOCKON]  = BMP_CST_COLOR_ROUGE;
		rendu[RENDU_COLOR_IPP_LOCKOFF] = BMP_CST_COLOR_BLANC;

		for (i = 0;                i < NB_TRAIN_COULEUR;   i++) color_train[i] = i; // Couleurs des trains.
		for (i = NB_TRAIN_COULEUR; i < NB_TRAIN;           i++) color_train[i] = BMP_CST_COLOR_MAGENTA; // Couleurs des wagons.
		for (j = 0; j < NB_CARTE; j++) for (i = 0; i < NB_CANTON; i++) color_canton[j][i]=i+1; // on ne prend pas le noir
	}

	// Si fichier 'config_tco.txt' présent, on lit les couleurs et le rendus.
	else { 
		// Lit les paramètres des bloc des 7 TCO.
		// Attend la ligne d'entête : 
		// [TCO_data]
		while (fscanf(pf, "%s%*[^\n]\n", szTemp) != EOF) {	// " %s" => "%s%*[^\n]\n" = Lit uniquement le premier mot de chaque ligne.
			if (STR_SAME strcmp(szTemp, "[TCO_data]")) break;
		}
		for (c = 0; c < CELLS_TCO_NB; c++)
		{
			// Attend la ligne d'entête : 
			// tco=0     
			// tco=1
			while (fscanf(pf, "%s%*[^\n]\n", szTemp) != EOF) {	// " %s" => "%s%*[^\n]\n" = Lit uniquement le premier mot de chaque ligne.
				if (STR_SAME strncmp(szTemp, "tco=", 4)) break;
			}
			for (x = 0; x < CELLS_X_NB; x++) for (y = 0; y < CELLS_Y_NB; y++)
			{
				fscanf(pf, " %s %s %s", szTemp, szTemp, szTemp);	// supprime 'x=%02d y=%02d data:'
				for (e = 0; e < CELLS_ENR_NB; e++) fscanf(pf, " %d", &cells[c][x][y][e]);
				fscanf(pf, " %s", szTemp);				// supprimer 'string='
				fscanf(pf, " %c", &cTemp);				// supprime  '"'
				for (e = 0; e < 20; e++) fscanf(pf, "%c", &sz_cells[c][x][y][e]); sz_cells[c][x][y][20] = '\0';
				fscanf(pf, " %c", &cTemp);				// supprime  '"'
			}
		}

		// Lit les paramètres de rendu en fin de fichier (couleur, ascpect).
		// Attend les lignes d'entête : 
		// rendu
		// data:
		while (fscanf(pf, "%s%*[^\n]\n", szTemp) != EOF) {	// " %s" => "%s%*[^\n]\n" = Lit uniquement le premier mot de chaque ligne.
			if (STR_SAME strcmp(szTemp, "rendu")) break;
		}
		while (fscanf(pf, "%s%*[^\n]\n", szTemp) != EOF) {	// " %s" => "%s%*[^\n]\n" = Lit uniquement le premier mot de chaque ligne.
			if (STR_SAME strcmp(szTemp, "data:")) break;
		}
		
		for (i = 0; i < RENDU_TAILLE; i++) fscanf(pf, " %d", &rendu[i]);
		for (j = 0; j < NB_CARTE; j++) for (i = 0; i < NB_CANTON; i++) fscanf(pf, " %d", &color_canton[j][i]);
		for (i = 0; i < NB_TRAIN_COULEUR; i++) {
			if (color_train[i] == -1) fscanf(pf, " %d", &color_train[i]);
			else fscanf(pf, " %d", &j);  // On n'efface pas la couleur des trains lue dans le fichier "config.txt". &j = variable qui ne sert pas ici.
		}

		// Initialisation d'autres tableaux
		for (i = 0; i < CMD_DIVERS_TAILLE; i++) cmd_divers[i] = 0;

		// V3.7a Lit la constitution et la position des trains à la fin du fichier "config_tco.txt".
		// Restauration de la position des trains.
		/*
		[SAUVEGARDE_POSITION_DES_TRAINS]
		train00  RAILCHEM  color02  pot  000  ok_auto  pasinv  06 64 13 13 -1  SEL c0
		train01  DB_ROUGE  color04  pot  001  ok_auto  pasinv  01 40 11 07 -1  SEL c9
		...
		train31
		[FIN]
		*/
		moins_char_normal = 1; // 1: '- 'est un caractère normal (comme 0)  0: '-' est un séparateur (comme +)
		if (cfg_memoire_pos_train == 1) { // =1 => UTS remet en place la position des trains pour le réseau, à l'ouverture du preogramme UTS,
			// dans ce cas, on n'a pa lu la configuration des trains dans "config.txt".
			while (fscanf(pf, "%s%*[^\n]\n", szTemp) != EOF) {	// " %s" => "%s%*[^\n]\n" = Lit uniquement le permier mot de chaque ligne.
				if (STR_SAME strcmp(szTemp, "[SAUVEGARDE_POSITION_DES_TRAINS]")) break;
			}
			while (get_line(pf, ch_tab, &c)) {
				if (c == 0) continue;  // Ligne vide, on passe à la ligne suivante.
				if (c == 1 && (STR_SAME strcmp(ch_tab[0], "[FIN]"))) break;
				if (c < 13 || c >= BLOC_CONFIG_NB) continue;  // Il faut une ligne "trainxx ... ..." compléte avec tous les arguments.
				if (STR_SAME strncmp(ch_tab[0], "train", 5)) {
					if (atoi(&ch_tab[0][5]) >= 0 && atoi(&ch_tab[0][5]) < NB_TRAIN) {  // N° du train de 0 à 31
						num_train = atoi(&ch_tab[0][5]);
						if (strlen(ch_tab[1]) == 8) { // Le nom du train doit faire exactement 8 caractères, complété si besoin par des '_'.
							strcpy(train.name[num_train], ch_tab[1]);
							for (j = 0; j < 8; j++) if (train.name[num_train][j] == '_') train.name[num_train][j] = ' ';
						}
						if (STR_SAME strncmp(ch_tab[2], "color", 5)) {
							if (atoi(&ch_tab[2][5]) >= 0 && atoi(&ch_tab[2][5]) < BMP_CST_COLOR_NB) {  // N° de couleur
								color_train[num_train] = atoi(&ch_tab[2][5]);
							}
						}
						// "clav 000" à "cla 004", "pot 000" à "pot 304" ou "sans cmd".
						// (-1 par défaut) = commandes du train, 0,1,2,3,4,10,11.. pour les potentiomètres de la carte, ou 1000,1001,1002,1003,1004 pour la commande par clavier
						if (STR_SAME strncmp(ch_tab[3], "clav", 4)) {
							if (atoi(ch_tab[4]) >= 0 && atoi(ch_tab[4]) < NB_POT_VIR) {
								train.cmd[num_train] = 1000 + atoi(ch_tab[4]);	// cmd[n° du train] = 1000,1001,1002,1003,1004 = commande par le clavier pour conduire le train.
							}
						}
						else if (STR_SAME strncmp(ch_tab[3], "pot", 3)) {
							if (atoi(ch_tab[4]) >= 0 && atoi(ch_tab[4]) < (300 + NB_CAN) && (atoi(ch_tab[4]) % 100) < NB_CAN) {
								train.cmd[num_train] = atoi(ch_tab[4]);
							}
						}
						else if (STR_SAME strncmp(ch_tab[3], "sans", 4)) {
							train.cmd[num_train] = -1;
						}
						if (STR_SAME strncmp(ch_tab[5], "ok_auto", 7)) {
							train.en_auto[num_train] = 1; // (0 par défaut) = 1 si le train peut être aussi conduit en mode automatique.
						}
						if (STR_SAME strncmp(ch_tab[6], "invers", 6)) {
							train.inv[num_train] = 1;     // (0 par défaut) = 1 si l'alimentation du train est inversée.
						}

						if (atoi(ch_tab[7]) >= 0 && atoi(ch_tab[7]) < VITESSE_MINI)         train.vmin[num_train] = atoi(ch_tab[7]);  else train.vmin[num_train] = VITESSE_CANT_MIN;
						if (atoi(ch_tab[8]) >= 1 && atoi(ch_tab[8]) < VITESSE_CANT_MAXI)    train.vmax[num_train] = atoi(ch_tab[8]);  else train.vmax[num_train] = VITESSE_CANT_MAXI;
						if (atoi(ch_tab[8]) <= atoi(ch_tab[7])) train.vmax[num_train] = VITESSE_CANT_MAXI;
						if (atoi(ch_tab[9]) >= 1 && atoi(ch_tab[9]) < VITESSE_INERTIE_MAXI) train.acc[num_train] = atoi(ch_tab[9]);  else train.acc[num_train] = -1;
						if (atoi(ch_tab[10]) >= 1 && atoi(ch_tab[10]) < VITESSE_INERTIE_MAXI) train.dec[num_train] = atoi(ch_tab[10]); else train.dec[num_train] = -1;
						if (atoi(ch_tab[11]) >= 1 && atoi(ch_tab[11]) < VITESSE_INERTIE_MAXI) train.frein[num_train] = atoi(ch_tab[11]); else train.frein[num_train] = -1;

						// On repasse toujours le train en mode "Selectif" et pas en mode "AUTO", car les anciens déplacements sont annulés au lancement d'UTS.
						strcpy(train.mode[num_train], "SEL");
						train.enable[num_train] = 1;

						if (c > 13) { // Au moins un garage ou un canton.
							if (ch_tab[13][0] == 'g') {
								j = atoi(&ch_tab[13][1]);         // Renseigne le numéro du garage depuis le n° sauvegardé.
								if (j >= 0 && j < NB_GARAGE) {
									train.cant_lock[num_train] = j;
									vio_garage_lock_cmd[j] = 1;         // 0 ou 1, 1 => Demande d'isolation du garage (Sera réalisée si il a un train sur le canton).
									vio_garage_lock_status[j] = 1;      // 0 ou 1, 1 => Le garage est isolé du canton (état réel).
									garage.numero_train[j] = num_train; // -1 = Garage relié au canton, ou Numéro de train occupant le garage isolé du canton.
								}
							}
							else {
								for (i = 0; i < 6; i++) { // Pour un train sur 6 cantons maximun.
									if (13 + i < c) {
										if (ch_tab[13 + i][0] == 'c') {
											j = atoi(&ch_tab[13 + i][1]);         // Renseigne le numéro du canton depuis le n° sauvegardé.
											if (j >= 0 && j < (300 + NB_CANTON) && (j % 100) < NB_CANTON) {
												canton.num_train[j / 100][j % 100] = num_train;
												canton.master_selectif[j / 100][j % 100] = 1;
												canton.inv_selectif[j / 100][j % 100] = 0;
												canton.update_selectif[j / 100][j % 100] = 0;
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}

		// V3.7a Lit la constitution et la position des aiguillages à la fin du fichier "config_tco.txt".
		// Restauration de la position des aiguillages.
		/*
		[SAUVEGARDE_POSITION_DES_AIGUILLAGES]
		a00.0  a01.1  a02.1  a03.0  a04.0  a05.1  a06.0  a07.0  a08.0  a09.0
		a10.0  a11.0  a12.0  a13.0  a14.1  a15.0  a16.0  a17.0  a18.0  a19.0
		...
		a60.0  a61.0  a62.0  a63.0
		[FIN]
		*/

		if (cfg_memoire_pos_aig == 1) { // =1 => UTS remet en place la position des aiguillages pour le réseau, à l'ouverture du preogramme UTS.
			while (fscanf(pf, "%s%*[^\n]\n", szTemp) != EOF) {	// " %s" => "%s%*[^\n]\n" = Lit uniquement le permier mot de chaque ligne.
				if (STR_SAME strcmp(szTemp, "[SAUVEGARDE_POSITION_DES_AIGUILLAGES]")) break;
			}
			while (get_line(pf, ch_tab, &c)) {
				if (c == 0) continue;  // Ligne vide, on passe à la ligne suivante.
				if (c == 1 && (STR_SAME strcmp(ch_tab[0], "[FIN]"))) break;
				if (c < 2 || c >= BLOC_CONFIG_NB) continue;  // Il faut une ligne "aigxx.y ... ..." compléte avec tous les arguments.
				if (STR_SAME strncmp(ch_tab[0], "a", 1)) {
					for (i = 0; i < c; i = i + 3) {             // Pour 10 aiguillages maximun par ligne.
						if (ch_tab[i][0] == 'a' && ch_tab[i + 1][0] == '.') {
							j = atoi(&ch_tab[i][1]);         // Renseigne le numéro 'j' de l'aiguillage depuis le n° sauvegardé.
							if (j >= 0 && j < NB_AIG && atoi(ch_tab[i + 2]) == 1) {
								if (aig_descr_info[j][AIG_DESCR_INFO_IND_EXIST] == 1) vio_aig_cmd[j] = 1;
							}
						}
					}
				}
			}
		}
		fclose(pf);
	}
}


// Sous programme pour écrire les tableaux TCO dans le fichier 'config_tco.txt'
// pour conserver les modifications.
//    cells_save("config.txt")
//
//
void cells_save(char sz_filename[])
{
	FILE* pf;
	int i, j, c, x, y, e;

	pf = fopen(sz_filename, "wt");
	if (pf == NULL) return;

	fprintf(pf, "[TCO_data]");
	for (c = 0; c < CELLS_TCO_NB; c++) {
		fprintf(pf, "\n\ntco=%d", c);
		for (x = 0; x < CELLS_X_NB; x++) for (y = 0; y < CELLS_Y_NB; y++) {
			fprintf(pf, "\nx=%02d y=%02d data:", x, y);
			for (e = 0; e < CELLS_ENR_NB; e++) fprintf(pf, " %4d", cells[c][x][y][e]);
			fprintf(pf, " string= \"%20s\"", sz_cells[c][x][y]);
		}
	}
	// Ecrit les paramètres de rendu en fin de fichier (couleur, ascpect).
	fprintf(pf, "\n\nrendu\ndata:");
	for (i = 0; i < RENDU_TAILLE; i++) fprintf(pf, "\n%4d", rendu[i]);
	for (j = 0; j < NB_CARTE; j++) for (i = 0; i < NB_CANTON; i++) fprintf(pf, "\n%4d", color_canton[j][i]);
	for (i = 0; i < NB_TRAIN_COULEUR; i++) fprintf(pf, "\n%4d", color_train[i]);

	// V3.7a Ecrit la constitution et la position des trains à la suite du fichier "config_tco.txt".
	// Sauvegarde les trains et n° des cantons réservés en manuel.
	// Sauvegarde les trains et n° des cantons réservés en automatique, si le train est détecté dessus (ou sinon sur tous les cantons réservés en automatique).

	fprintf(pf, "\n\n[SAUVEGARDE_POSITION_DES_TRAINS]\n"); // Entête de section sauvegardée.
	for (i = 0; i < NB_TRAIN; i++) {
		fprintf(pf, "train%02d", i);
		if (train.enable[i] == 1) {       // Pour tous les trains qui existent.
			for (j = 0; j < 8; j++) if (train.name[i][j] == ' ') train.name[i][j] = '_'; // Pas d'espaces dans les noms des trains.
			fprintf(pf, " %s", train.name[i]);
			fprintf(pf, " color%02d", color_train[i]);
			if (train.cmd[i] == -1) fprintf(pf, " sans cmd");
			else if (train.cmd[i] < 1000) fprintf(pf, " pot  %03d", train.cmd[i]);
			else fprintf(pf, " clav %03d", train.cmd[i] - 1000);
			if (train.en_auto[i]) fprintf(pf, " ok_auto"); else fprintf(pf, " pasauto");
			if (train.inv[i]) fprintf(pf, " invers"); else fprintf(pf, " pasinv");
			fprintf(pf, " %02d %02d %02d %02d %02d", train.vmin[i], train.vmax[i], train.acc[i], train.dec[i], train.frein[i]);
			fprintf(pf, " %s", train.mode[i]);  // "SEL" ou "AUTO".
			if (train.cant_lock[i] != -1) {
				fprintf(pf, " g%02d", train.cant_lock[i]);  // N° du garage
			}
			else { // On recherhe les cantons ou le garage du train.
				if (STR_SAME stricmp(train.mode[i], "SEL")) {
					for (x = 0; x < NB_CARTE; x++) for (y = 0; y < NB_CANTON; y++) {
						if (canton.num_train[x][y] == i) { 
							if (canton.master_selectif[x][y]) fprintf(pf, " c%d", 100 * x + y); // Train en manuel, on enregistre tous les cantons même sans présence du train.
						}
					}
				}
				else {
					j = 0;
					for (x = 0; x < NB_CARTE; x++) for (y = 0; y < NB_CANTON; y++) {
						if (canton.num_train[x][y] == i) { 
							if (canton.res_auto[x][y] && vio_det[x][y]) {                // Train en déplacement automatique, 1ere passe sur les canton avec présence du train.
								fprintf(pf, " c%d", 100 * x + y);         
								j = 1;
							}
						}
					}
					if (j == 0) {
						for (x = 0; x < NB_CARTE; x++) for (y = 0; y < NB_CANTON; y++) {
							if (canton.num_train[x][y] == i) {                               // Train en déplacement automatique, 
								if (canton.res_auto[x][y]) fprintf(pf, " c%d", 100 * x + y); // si l'on n'a pas trouvé de train, 2 eme passe pour prendre tous les cantons.
							}
						}
					}
				}
			}
		}
		fprintf(pf, "\n");
	}
	fprintf(pf, "[FIN]\n");

	// V3.7a Ecrit la position des aiguillages (qui existent ou pas) à la suite du fichier "config_tco.txt".
	
	fprintf(pf, "\n[SAUVEGARDE_POSITION_DES_AIGUILLAGES]\n");
	for (i = 0; i < NB_AIG; i++) {
		fprintf(pf, "a%02d.%1d ", i, vio_aig_cmd[i]);
		if (i % 10 == 9 && i < NB_AIG-1) fprintf(pf, "\n");    // 10 aiguillages par ligne
	}
	fprintf(pf, "\n[FIN]\n");
	fclose(pf);
}


// Données pour définir la position des blocs dans la fenêtre d'écran 'TCO Edition'.
// Les blocs sont affiché en colonnes, lignes
//
int conf_symb[]={
				1,1,CELLS_TYPE_LINK,CELLS_SUBTYPE_LINK_H,
				1,2,CELLS_TYPE_LINK,CELLS_SUBTYPE_LINK_V,
				1,3,CELLS_TYPE_AIG,CELLS_SUBTYPE_AIG_HC,
				1,4,CELLS_TYPE_AIG,CELLS_SUBTYPE_AIG_BC,

				2,1,CELLS_TYPE_LINK,CELLS_SUBTYPE_LINK_NOSE,
				2,2,CELLS_TYPE_LINK,CELLS_SUBTYPE_LINK_SONE,
				2,3,CELLS_TYPE_AIG,CELLS_SUBTYPE_AIG_CH,
				2,4,CELLS_TYPE_AIG,CELLS_SUBTYPE_AIG_CB,

				3,1,CELLS_TYPE_LINK,CELLS_SUBTYPE_LINK_SE,
				3,2,CELLS_TYPE_LINK,CELLS_SUBTYPE_LINK_NE,
				3,3,CELLS_TYPE_AIG,CELLS_SUBTYPE_AIG_HCV,
				3,4,CELLS_TYPE_AIG,CELLS_SUBTYPE_AIG_BCV,

				4,1,CELLS_TYPE_LINK,CELLS_SUBTYPE_LINK_OS,
				4,2,CELLS_TYPE_LINK,CELLS_SUBTYPE_LINK_ON,
				4,3,CELLS_TYPE_AIG,CELLS_SUBTYPE_AIG_CHV,
				4,4,CELLS_TYPE_AIG,CELLS_SUBTYPE_AIG_CBV,

				5,1,CELLS_TYPE_LINK,CELLS_SUBTYPE_LINK_SOE,
				5,2,CELLS_TYPE_LINK,CELLS_SUBTYPE_LINK_NOE,
				5,3,CELLS_TYPE_LINK,CELLS_SUBTYPE_LINK_SNE,
				5,4,CELLS_TYPE_LINK,CELLS_SUBTYPE_LINK_NSE,

				6,1,CELLS_TYPE_LINK,CELLS_SUBTYPE_LINK_OSE,
				6,2,CELLS_TYPE_LINK,CELLS_SUBTYPE_LINK_ONE,
				6,3,CELLS_TYPE_LINK,CELLS_SUBTYPE_LINK_NOS,
				6,4,CELLS_TYPE_LINK,CELLS_SUBTYPE_LINK_SON,

				7,3,CELLS_TYPE_AIG,CELLS_SUBTYPE_AIG_HBC,
				7,4,CELLS_TYPE_SPE,CELLS_SUBTYPE_SPE_CV,
				7,5,CELLS_TYPE_SPE,CELLS_SUBTYPE_SPE_HC,
				7,6,CELLS_TYPE_LINK,CELLS_SUBTYPE_LINK_PH,

				8,3,CELLS_TYPE_AIG,CELLS_SUBTYPE_AIG_CHB,
				8,4,CELLS_TYPE_SPE,CELLS_SUBTYPE_SPE_CH,
				8,5,CELLS_TYPE_SPE,CELLS_SUBTYPE_SPE_VC,
				8,6,CELLS_TYPE_LINK,CELLS_SUBTYPE_LINK_PV,
				8,8,CELLS_TYPE_LINK,CELLS_SUBTYPE_LINK_BALA,

				1,5,CELLS_TYPE_SPE,CELLS_SUBTYPE_SPE_VOY,
				2,5,CELLS_TYPE_SPE,CELLS_SUBTYPE_SPE_CANT,
				3,5,CELLS_TYPE_SPE,CELLS_SUBTYPE_SPE_IN,
				4,5,CELLS_TYPE_SPE,CELLS_SUBTYPE_SPE_OUT,
				5,5,CELLS_TYPE_SPE,CELLS_SUBTYPE_SPE_SENS,
				6,5,CELLS_TYPE_SPE,CELLS_SUBTYPE_SPE_FEU,
				
				1,6,CELLS_TYPE_SPE,CELLS_SUBTYPE_SPE_VOYV,
				2,6,CELLS_TYPE_SPE,CELLS_SUBTYPE_SPE_CANTV,
				3,6,CELLS_TYPE_SPE,CELLS_SUBTYPE_SPE_INV,
				4,6,CELLS_TYPE_SPE,CELLS_SUBTYPE_SPE_OUTV,
				5,6,CELLS_TYPE_SPE,CELLS_SUBTYPE_SPE_SENSV,
				6,6,CELLS_TYPE_SPE,CELLS_SUBTYPE_SPE_FEUV,
				7,8,CELLS_TYPE_CMDVOY,CELLS_SUBTYPE_CMDVOY_DIVERS,

				1,7,CELLS_TYPE_CMDVOY,CELLS_SUBTYPE_CMDVOY_POUSS,
				2,7,CELLS_TYPE_CMDVOY,CELLS_SUBTYPE_CMDVOY_INT,
				3,7,CELLS_TYPE_CMDVOY,CELLS_SUBTYPE_CMDVOY_ITI,
				4,7,CELLS_TYPE_CMDVOY,CELLS_SUBTYPE_CMDVOY_VOY1,
				5,7,CELLS_TYPE_CMDVOY,CELLS_SUBTYPE_CMDVOY_VOY2,
				6,7,CELLS_TYPE_CMDVOY,CELLS_SUBTYPE_CMDVOY_VOY4,
				7,7,CELLS_TYPE_SPE,CELLS_SUBTYPE_SPE_DETEL,
				8,7,CELLS_TYPE_SPE,CELLS_SUBTYPE_SPE_DETELV,
				
				1,8,CELLS_TYPE_RIEN,0,
				2,8,CELLS_TYPE_CMDVOY,CELLS_SUBTYPE_CMDVOY_LABEL,
				3,8,CELLS_TYPE_CMDVOY,CELLS_SUBTYPE_CMDVOY_VAL,
				4,8,CELLS_TYPE_SPE,CELLS_SUBTYPE_SPE_HOR,
				5,8,CELLS_TYPE_CMDVOY,CELLS_SUBTYPE_CMDVOY_GO,
				6,8,CELLS_TYPE_CMDVOY,CELLS_SUBTYPE_CMDVOY_SRV,
				0 };


// Sous programmme pour affiche la fenêtre 'Edition de TCO'
// En fonction de 'c_conf_wnd'= 'A,B,C,D', cette fenêtre est plus ou moins décalée sur la droite.
//
//
char c_conf_wnd=' ';	// Type de fenêtre d'édition affichée (Edition TCO, rendu, aide).
int do_not_redraw=1;	// do_not_redraw==0 => Affichage complet d'une fenêtre ('Edition' ou 'Rendu') toute les 2,4 sec (en V3.3, tic = 80 msec).
int cells_redraw=0;		// cells_redraw==1 => si ouverture d'une fenêtre ('Edition' ou 'Rendu') ou déplacement <--> de cette fenêtre.
int cells_type_sel=-1;
int cells_subtype_sel=0;
int temp_conf_canton=-1;
int temp_conf_sens=-1;
int temp_conf_n1=-1;
int temp_conf_n2=-1;
int temp_conf_v1=-1;
int temp_conf_v2=-1;
int temp_conf_v3=-1;
int temp_conf_v4=-1;
int temp_conf_opt=-1;
int temp_conf_c1=-1;
int temp_conf_c2=-1;
int temp_conf_c3=-1;
int temp_conf_c4=-1;
char sz_temp_conf_txt[]="                     "; // 21 caractères.
int cells_entry_sel=-1;
int yopt=400;
//
void draw_win_conf_V(void)
{
	int i, j;
	int xdep, ydep;				/* int xdep,ydep,xopt; */
	char szTemp[100];
	ydep = 0;
	xdep = 0;
	yopt = 400;
	// 'A' => On affiche la fenêtre à gauche de l'écran, xdep = 000.
	if (c_conf_wnd == 'B') xdep = 200;	// 'B' => On affiche la fenêtre à droite de l'écran, xdep = 200.
	if (c_conf_wnd == 'C') xdep = 400;	// 'C' => On affiche la fenêtre à droite de l'écran, xdep = 400.
	if (c_conf_wnd == 'D') xdep = 760;	// 'D' => On affiche la fenêtre à droite de l'écran, xdep = 800-40 pour rester visible.

	//0. total config window redraw
	// if(do_not_redraw==0 || cells_redraw==1)	// 'cells_redraw==1' => si ouverture d'une fenêtre ('Edition' ou 'Rendu') ou déplacement <--> de cette fenêtre.
	// On supprime ce test et l'on redessine à chaque fois l'image pour le double buffering.

	cells_redraw = 0;
	SelectObject(h_dc_mem_cells, bmp_pinceau_grisvert);
	SelectObject(h_dc_mem_cells, bmp_stylo_grisvert);
	Rectangle(h_dc_mem_cells, xdep, 0, xdep + 400, 680);	// Fenêtre de 400 x 680 pixels.
	SelectObject(h_dc_mem_cells, bmp_stylo_noir);

	SelectObject(hMemDC, bmp_pinceau_gris192); SelectObject(hMemDC, bmp_stylo_gris192); Rectangle(hMemDC, xdep + 368 - 15, 15, xdep + 368 - 2, 2); // [<]
	SelectObject(hMemDC, bmp_stylo_noir);  EasyLine(xdep + 368 - 2, 1, xdep + 368 - 2, 16); EasyLine(xdep + 368 - 16, 15, xdep + 368 - 1, 15); // Trait noir.
	SelectObject(hMemDC, bmp_stylo_gris128); EasyLine(xdep + 368 - 3, 2, xdep + 368 - 3, 15); EasyLine(xdep + 368 - 15, 14, xdep + 368 - 2, 14); // Trait gris foncé.
	SelectObject(hMemDC, bmp_stylo_noir);
	for (i = 0; i < 6; i++) {
		EasyLine(xdep + 364 - 2 * i, 2 + i, xdep + 364 - 2 * i, 14 - i);
		EasyLine(xdep + 363 - 2 * i, 2 + i, xdep + 363 - 2 * i, 14 - i);
	}
	SelectObject(hMemDC, bmp_pinceau_gris192); SelectObject(hMemDC, bmp_stylo_gris192); Rectangle(hMemDC, xdep + 384 - 15, 15, xdep + 384 - 2, 2); // [>]
	SelectObject(hMemDC, bmp_stylo_noir);  EasyLine(xdep + 384 - 2, 1, xdep + 384 - 2, 16); EasyLine(xdep + 384 - 16, 15, xdep + 384 - 1, 15); // Trait noir.
	SelectObject(hMemDC, bmp_stylo_gris128); EasyLine(xdep + 384 - 3, 2, xdep + 384 - 3, 15); EasyLine(xdep + 384 - 15, 14, xdep + 384 - 2, 14); // Trait gris foncé.
	SelectObject(hMemDC, bmp_stylo_noir);
	for (i = 0; i < 6; i++) {
		EasyLine(xdep + 369 + 2 * i, 2 + i, xdep + 369 + 2 * i, 14 - i);
		EasyLine(xdep + 370 + 2 * i, 2 + i, xdep + 370 + 2 * i, 14 - i);
	}
	SelectObject(hMemDC, bmp_pinceau_gris192); SelectObject(hMemDC, bmp_stylo_gris192); Rectangle(hMemDC, xdep + 400 - 15, 15, xdep + 400 - 2, 2); // [X]
	SelectObject(hMemDC, bmp_stylo_noir);  EasyLine(xdep + 400 - 14, 3, xdep + 400 - 3, 14); EasyLine(xdep + 400 - 14, 13, xdep + 400 - 3, 2); // Croix noire.
	SelectObject(hMemDC, bmp_stylo_noir);  EasyLine(xdep + 400 - 2, 1, xdep + 400 - 2, 16); EasyLine(xdep + 400 - 16, 15, xdep + 400 - 1, 15); // Trait noir.
	SelectObject(hMemDC, bmp_stylo_gris128); EasyLine(xdep + 400 - 3, 2, xdep + 400 - 3, 15); EasyLine(xdep + 400 - 15, 14, xdep + 400 - 2, 14); // Trait gris foncé.
	SelectObject(hMemDC, bmp_pinceau_blanc); SelectObject(hMemDC, bmp_stylo_gris192);

	SelectObject(h_dc_mem_cells, cells_font);
	SetTextColor(hMemDC, RGB(0, 0, 0));
	SelectObject(h_dc_mem_cells, bmp_pinceau_blanc); SelectObject(h_dc_mem_cells, bmp_stylo_blanc);
	Rectangle(h_dc_mem_cells, xdep + 40, 4, xdep + 350, 14);
	strcpy(szTemp, "TOUCHE '+' : FENÊTRE SUIVANTE"); TextOut(h_dc_mem_cells, xdep + 70, 5, szTemp, strlen(szTemp));
	strcpy(szTemp, "ESC:QUIT");  TextOut(h_dc_mem_cells, xdep + 320, 17, szTemp, strlen(szTemp));

	//1. partial config window redraw
	//   Affiche le choix de cases possibles pour construire un TCO et les champs pour les variables.
	i = 0;
	while (conf_symb[i]) {
		j = -1;
		if (conf_symb[i + 2] == CELLS_TYPE_SPE && ((conf_symb[i + 3] == CELLS_SUBTYPE_SPE_FEU) || (conf_symb[i + 3] == CELLS_SUBTYPE_SPE_FEUV))) { strcpy(szTemp, "      123      "); j = 1; }
		else strcpy(szTemp, "    text        ");
		if (conf_symb[i + 2] == CELLS_TYPE_CMDVOY && conf_symb[i + 3] == CELLS_SUBTYPE_CMDVOY_DIVERS) j = 1;
		//      private_cells_draw_one(type, subtype, x, y, char szTxt[], cant, n1, n2,  v1, v2, v3, v4, c1,c2, c3, c4, opt, sens)
		private_cells_draw_one(conf_symb[i + 2], conf_symb[i + 3], xdep + 40 * conf_symb[i + 0], ydep + 40 * conf_symb[i + 1], szTemp, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, j, -10); // sens = -10 pour un symbol de démonstration.
		i = i + 4;
	}
	// Affiche la case du bloc sélectionné dans la fenêtre.
	private_cells_draw_one(cells_type_sel, cells_subtype_sel, 320 + xdep, 40, sz_temp_conf_txt, temp_conf_canton, temp_conf_n1, temp_conf_n2, temp_conf_v1, temp_conf_v2, temp_conf_v3, temp_conf_v4, temp_conf_c1, temp_conf_c2, temp_conf_c3, temp_conf_c4, temp_conf_opt, temp_conf_sens);

	// Affiche les textes d'aide à la saisie des paramètres propres à chaque bloc de TCO. Texte noir sur grand rectangle blanc en bas de la fenêtre.
	SelectObject(h_dc_mem_cells, bmp_pinceau_blanc); SelectObject(h_dc_mem_cells, bmp_stylo_blanc);
	SetTextColor(hMemDC, RGB(0, 0, 0)); Rectangle(h_dc_mem_cells, 4 + xdep, yopt + 137, xdep + 396, yopt + 195+80);
	SelectObject(h_dc_mem_cells, bmp_pinceau_noir); SelectObject(h_dc_mem_cells, bmp_stylo_noir);	// Pour les cases C1 à C4 si aucune couleur n'est définie.

	if (cells_type_sel == CELLS_TYPE_LINK){
		sprintf_s(szTemp, "ÉLEMENTS DE VOIES :");							TextOut(h_dc_mem_cells, 10 + xdep, yopt + 138, szTemp, strlen(szTemp));
		sprintf_s(szTemp, "CANT: NUMÉRO DU CANTON: 0-315,(GARAGE+1000)");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 148, szTemp, strlen(szTemp));
		sprintf_s(szTemp, "S+  : ORIENTATION DU BLOC"); 					TextOut(h_dc_mem_cells, 10 + xdep, yopt + 158, szTemp, strlen(szTemp));
		sprintf_s(szTemp, "#1  : 0 A 16 POUR AJOUT VOIE SECONDAIRE"); 		TextOut(h_dc_mem_cells, 10 + xdep, yopt + 168, szTemp, strlen(szTemp));
		sprintf_s(szTemp, "    : +100 A +800 AJOUT D'UN PONT");				TextOut(h_dc_mem_cells, 10 + xdep, yopt + 178, szTemp, strlen(szTemp));
		sprintf_s(szTemp, "#2  : NUMÉRO CANTON DE VOIE SECONDAIRE"); 		TextOut(h_dc_mem_cells, 10 + xdep, yopt + 188, szTemp, strlen(szTemp));
		sprintf_s(szTemp, "OPT : 1 A 3 VOIES EN POINTILLÉE"); 				TextOut(h_dc_mem_cells, 10 + xdep, yopt + 198, szTemp, strlen(szTemp));
		sprintf_s(szTemp, "    : 4 A 29 AJOUT D'UN PICTOGRAMME");			TextOut(h_dc_mem_cells, 10 + xdep, yopt + 208, szTemp, strlen(szTemp));
		sprintf_s(szTemp, "    : UNIQUEMENT POUR RAIL VERTICAL/HORIZON");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 218, szTemp, strlen(szTemp));
		sprintf_s(szTemp, "    : 1 HP, 2 PLAY, 3,4 LAMPADAIRE");			TextOut(h_dc_mem_cells, 10 + xdep, yopt + 228, szTemp, strlen(szTemp));
		sprintf_s(szTemp, "    : 5 A 12 RECANGLE, 13 A 20 TOIT MAISON");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 238, szTemp, strlen(szTemp));
		sprintf_s(szTemp, "    : 21,22 MAISON, 23 A 26 LOCO, RE");			TextOut(h_dc_mem_cells, 10 + xdep, yopt + 248, szTemp, strlen(szTemp));
		sprintf_s(szTemp, "    : 27,28 RECTANGLE COULEUR C1");				TextOut(h_dc_mem_cells, 10 + xdep, yopt + 258, szTemp, strlen(szTemp));
		sprintf_s(szTemp, "    : 29 RECTANGLE + COULEUR C1, C2 ,C3 C4");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 268, szTemp, strlen(szTemp));
}


	if (cells_type_sel == CELLS_TYPE_AIG)	{
		sprintf_s(szTemp, "AIGUILLAGES :");			 							TextOut(h_dc_mem_cells, 10 + xdep, yopt + 138, szTemp, strlen(szTemp));
		sprintf_s(szTemp, "CANT: NUMÉRO DU CANTON: 0-315,(GARAGE+1000)");		TextOut(h_dc_mem_cells, 10 + xdep, yopt + 148, szTemp, strlen(szTemp));
		sprintf_s(szTemp, "S+  : ORIENTATION DU BLOC");							TextOut(h_dc_mem_cells, 10 + xdep, yopt + 158, szTemp, strlen(szTemp));
		sprintf_s(szTemp, "#1  : NUMÉRO DE COMMANDE DU MOTEUR 1: 0-63");		TextOut(h_dc_mem_cells, 10 + xdep, yopt + 168, szTemp, strlen(szTemp));
		sprintf_s(szTemp, "#2  : SI AIG TRIPLE     CMD.MOTEUR 2: 0-63");		TextOut(h_dc_mem_cells, 10 + xdep, yopt + 178, szTemp, strlen(szTemp));
	}

	if (cells_type_sel == CELLS_TYPE_SPE) {
		if (cells_subtype_sel == CELLS_SUBTYPE_SPE_CH || cells_subtype_sel == CELLS_SUBTYPE_SPE_HC 		// Butoirs 
			|| cells_subtype_sel == CELLS_SUBTYPE_SPE_CV || cells_subtype_sel == CELLS_SUBTYPE_SPE_VC) {
			sprintf_s(szTemp, "ÉLEMENTS DE VOIES, BUTOIR + CAPTEUR PASSAGE");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 138, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "CANT: NUMÉRO DU CANTON: 0-315,(GARAGE+1000)");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 148, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "S+  : ORIENTATION DU BLOC"); 					TextOut(h_dc_mem_cells, 10 + xdep, yopt + 158, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "V1:NUMÉRO DE VARIABLE (CAPTEUR) FACULTATIF");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 168, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "SI V1:1 ALLUME UN VOYANT FIN DE COURSE");		TextOut(h_dc_mem_cells, 10 + xdep, yopt + 178, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "VOIR FENÊTRE RENDU (VOY DETECT -[]-)");			TextOut(h_dc_mem_cells, 10 + xdep, yopt + 188, szTemp, strlen(szTemp));
		}

		if (cells_subtype_sel == CELLS_SUBTYPE_SPE_VOY || cells_subtype_sel == CELLS_SUBTYPE_SPE_VOYV){	// Rail avec voyant rectangulaire = '-[]-'
			sprintf_s(szTemp, "AFFICHE L'ÉTAT DE L'OCCUPATION DU CANTON:");		TextOut(h_dc_mem_cells, 10 + xdep, yopt + 138, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "CANT: NUMÉRO DU CANTON: 0-315,(GARAGE+1000)");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 148, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "S+  : ORIENTATION DU BLOC"); 					TextOut(h_dc_mem_cells, 10 + xdep, yopt + 158, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "COULEURS:VOIR FENÊTRE RENDU(VOY DETECT-[]-)");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 168, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "CLIC DESSUS:PERMET DE LANCER UN ITINÉRAIRE ");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 178, szTemp, strlen(szTemp));
		}

		if (cells_subtype_sel == CELLS_SUBTYPE_SPE_SENS || cells_subtype_sel == CELLS_SUBTYPE_SPE_SENSV){	// Rail avec flèches d'imposition de sens de circulation = '-<>-'.
			sprintf_s(szTemp, "IMPOSE LE SENS DE PARCOURS :");					TextOut(h_dc_mem_cells, 10 + xdep, yopt + 138, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "CANT: NUMÉRO DU CANTON: 0-315,(GARAGE+1000)");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 148, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "S+  : ORIENTATION DU BLOC"); 					TextOut(h_dc_mem_cells, 10 + xdep, yopt + 158, szTemp, strlen(szTemp));
		}

		if (cells_subtype_sel == CELLS_SUBTYPE_SPE_CANT || cells_subtype_sel == CELLS_SUBTYPE_SPE_CANTV){	// Rail avec affiche des info du canton
			sprintf_s(szTemp, "AFFICHE LE NUMÉRO DU CANTON, LA VITESSE ET");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 138, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "LE NOM DU TRAIN :");								TextOut(h_dc_mem_cells, 10 + xdep, yopt + 148, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "CANT: NUMÉRO DU CANTON: 0-315,(GARAGE+1000)");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 158, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "S+  : ORIENTATION DU BLOC"); 					TextOut(h_dc_mem_cells, 10 + xdep, yopt + 168, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "SI PB DÉTECTION TRAIN, CLIGNOTE EN ROUGE"); 		TextOut(h_dc_mem_cells, 10 + xdep, yopt + 178, szTemp, strlen(szTemp));
		}

		if (cells_subtype_sel == CELLS_SUBTYPE_SPE_IN || cells_subtype_sel == CELLS_SUBTYPE_SPE_INV){	// Rail avec pédale de détection de passage de train = '-/\-'
			sprintf_s(szTemp, "AFFICHE L'ÉTAT DU CAPTEUR DE PASSAGE :");		TextOut(h_dc_mem_cells, 10 + xdep, yopt + 138, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "CANT: NUMÉRO DU CANTON: 0-315,(GARAGE+1000)");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 148, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "S+  : ORIENTATION DU BLOC"); 					TextOut(h_dc_mem_cells, 10 + xdep, yopt + 158, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "V1  : NUMERO DE VARIABLE (CAPTEUR D'ENTREE)");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 168, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "SI V1:1 ALLUME UN VOYANT RECTANGULAIRE");		TextOut(h_dc_mem_cells, 10 + xdep, yopt + 178, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "VOIR FENÊTRE RENDU (VOY DETECT -[]-)");			TextOut(h_dc_mem_cells, 10 + xdep, yopt + 188, szTemp, strlen(szTemp));
		}

		if (cells_subtype_sel == CELLS_SUBTYPE_SPE_FEU || cells_subtype_sel == CELLS_SUBTYPE_SPE_FEUV){	// Feu tricolore.
			sprintf_s(szTemp, "AFFICHE UN FEU AU BORD DE LA VOIE");				TextOut(h_dc_mem_cells, 10 + xdep, yopt + 138, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "CANT: NUMÉRO DU CANTON: 0-315,(GARAGE+1000)");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 148, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "S+   : ORIENTATION DU BLOC DE VOIE"); 			TextOut(h_dc_mem_cells, 10 + xdep, yopt + 158, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "V1-V4: NUMÉRO VARIABLES DES LAMPES 1-4");		TextOut(h_dc_mem_cells, 10 + xdep, yopt + 168, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "C1-C4: COULEUR DES LAMPES 1-4");					TextOut(h_dc_mem_cells, 10 + xdep, yopt + 178, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "OPT  : 1 A 4 FORME DU PIED");					TextOut(h_dc_mem_cells, 10 + xdep, yopt + 188, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "OPT  : 5 FEUX PASSAGE A NIVEAU");				TextOut(h_dc_mem_cells, 10 + xdep, yopt + 198, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "TEXTE: 123+ESPACE : LAMPES1+2+3");				TextOut(h_dc_mem_cells, 10 + xdep, yopt + 208, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "     : 1 : LAMPE 1, 2 : LAMPE 2, ...");			TextOut(h_dc_mem_cells, 10 + xdep, yopt + 218, szTemp, strlen(szTemp));
		}

		if (cells_subtype_sel == CELLS_SUBTYPE_SPE_HOR) {	// Horloge
			sprintf_s(szTemp, "AFFICHE UNE HORLOGE : CHOISIR LES COULEURS");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 138, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "C1 : COULEUR A L'ÉTAT 'ON'");					TextOut(h_dc_mem_cells, 10 + xdep, yopt + 148, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "C2 : COULEUR A L'ÉTAT 'OFF'");					TextOut(h_dc_mem_cells, 10 + xdep, yopt + 158, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "C3 : COULEUR CLIGNOTANTE A L'ÉTAT 'BLOQUÉE'");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 168, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "MISE EN MARCHE EN CLIQUANT SUR LE BLOC");		TextOut(h_dc_mem_cells, 10 + xdep, yopt + 178, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "EN RELIEF, LES COULEURS SONT IMPOSÉES");			TextOut(h_dc_mem_cells, 10 + xdep, yopt + 188, szTemp, strlen(szTemp));
		}

		if (cells_subtype_sel == CELLS_SUBTYPE_SPE_DETEL || cells_subtype_sel == CELLS_SUBTYPE_SPE_DETELV){	// Dételeur.
			sprintf_s(szTemp, "AFFICHE L'ÉTAT DU RAIL DÉTELEUR");				TextOut(h_dc_mem_cells, 10 + xdep, yopt + 138, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "CANT: NUMÉRO DU CANTON: 0-315,(GARAGE+1000)");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 148, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "S+ : ORIENTATION DU BLOC");						TextOut(h_dc_mem_cells, 10 + xdep, yopt + 158, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "V1 : NUMÉRO VARIABLE D'ÉTAT DU DÉTELEUR");		TextOut(h_dc_mem_cells, 10 + xdep, yopt + 168, szTemp, strlen(szTemp));
		}

		if (cells_subtype_sel == CELLS_SUBTYPE_SPE_OUT || cells_subtype_sel == CELLS_SUBTYPE_SPE_OUTV){	// ?
			sprintf_s(szTemp, "ÉLEMENT PAS ENCORE UTILISABLE");					TextOut(h_dc_mem_cells, 10 + xdep, yopt + 138, szTemp, strlen(szTemp));
		}
	}

	if (cells_type_sel == CELLS_TYPE_CMDVOY){
		if (cells_subtype_sel == CELLS_SUBTYPE_CMDVOY_POUSS) {		// Bouton poussoir rectangulaire
			sprintf_s(szTemp, "BOUTON POUSSOIR, A CHAQUE ACTION CHANGE");		TextOut(h_dc_mem_cells, 10 + xdep, yopt + 138, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "L'ÉTAT DES VARIABLES (DE SORTIES) :");			TextOut(h_dc_mem_cells, 10 + xdep, yopt + 148, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "V1 : MISE A 1 LE TEMPS DU CLIC ENFONCÉ");		TextOut(h_dc_mem_cells, 10 + xdep, yopt + 158, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "V2 : MISE A 1 DE CETTE VARIABLE AU CLIC");		TextOut(h_dc_mem_cells, 10 + xdep, yopt + 168, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "V3 : MISE A 0 DE CETTE VARIABLE AU CLIC");		TextOut(h_dc_mem_cells, 10 + xdep, yopt + 178, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "COULEURS: VOIR FENÊTRE RENDU(VOY.INTER/BP)");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 188, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "TXT : 4 LIGNES DE 4 CARACTÈRES");				TextOut(h_dc_mem_cells, 10 + xdep, yopt + 198, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "OPT : AJOUT D'UN PICTOGRAMME (1 A 29)");			TextOut(h_dc_mem_cells, 10 + xdep, yopt + 208, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "    : 1 HP, 2 PLAY, 3,4 LAMPADAIRE");			TextOut(h_dc_mem_cells, 10 + xdep, yopt + 218, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "    : 5 A 12 RECANGLE, 13 A 20 TOIT MAISON");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 228, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "    : 21,22 MAISON, 23 A 26 LOCO, RE");			TextOut(h_dc_mem_cells, 10 + xdep, yopt + 238, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "    : 27,28 RECTANGLE COULEUR C1");				TextOut(h_dc_mem_cells, 10 + xdep, yopt + 248, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "    : 29 RECTANGLE + COULEUR C1, C2 ,C3 C4");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 258, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "    : +100 AFFICHE LE VOYANT");					TextOut(h_dc_mem_cells, 10 + xdep, yopt + 268, szTemp, strlen(szTemp));
		}

		if (cells_subtype_sel == CELLS_SUBTYPE_CMDVOY_INT) {		// Bouton interrupteur rectangulaire, change d'état à chaque pression.
			sprintf_s(szTemp, "INTERRUPTEUR :");								TextOut(h_dc_mem_cells, 10 + xdep, yopt + 138, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "CHANGE L'ÉTAT DES VARIABLES (DE SORTIES)");		TextOut(h_dc_mem_cells, 10 + xdep, yopt + 148, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "V1 : CHANGE L'ÉTAT DE CETTE VARIABLE (0-1)");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 158, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "     A CHAQUE CLIC");							TextOut(h_dc_mem_cells, 10 + xdep, yopt + 168, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "COULEURS: VOIR FENÊTRE RENDU(VOY.INTER/BP)");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 178, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "TXT : 4 LIGNES DE 4 CARACTÈRES");				TextOut(h_dc_mem_cells, 10 + xdep, yopt + 188, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "OPT : AJOUT D'UN PICTOGRAMME (1 A 29)");			TextOut(h_dc_mem_cells, 10 + xdep, yopt + 198, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "    : 1 HP, 2 PLAY, 3,4 LAMPADAIRE");			TextOut(h_dc_mem_cells, 10 + xdep, yopt + 208, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "    : 5 A 12 RECANGLE, 13 A 20 TOIT MAISON");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 218, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "    : 21,22 MAISON, 23 A 26 LOCO, RE");			TextOut(h_dc_mem_cells, 10 + xdep, yopt + 228, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "    : 27,28 RECTANGLE COULEUR C1");				TextOut(h_dc_mem_cells, 10 + xdep, yopt + 238, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "    : 29 RECTANGLE + COULEUR C1, C2 ,C3 C4");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 248, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "    : +100 AFFICHE LE VOYANT");					TextOut(h_dc_mem_cells, 10 + xdep, yopt + 258, szTemp, strlen(szTemp));
		}

		if (cells_subtype_sel == CELLS_SUBTYPE_CMDVOY_ITI){		// Bouton poussoir rond à Appui/Traction Clic-gauche/Clic-droit.
			sprintf_s(szTemp, "BOUTON A APPUI/TRACTION (ITINÉRAIRES):");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 138, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "V1 : ITI_START, MISE A 1 AU CLIC-GAUCHE");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 148, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "V2 : ITI_STOP,  MISE A 1 AU CLIC-DROIT");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 158, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "V3 : ITI_OK, VOYANT ALLUMÉ SI VAR : 1");		TextOut(h_dc_mem_cells, 10 + xdep, yopt + 168, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "V4 : ITI_WAIT, CLIGNOTE SI VAR : 1");		TextOut(h_dc_mem_cells, 10 + xdep, yopt + 178, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "COULEURS: VOIR FENÊTRE RENDU(B.ITI)");		TextOut(h_dc_mem_cells, 10 + xdep, yopt + 188, szTemp, strlen(szTemp));
		}

		if (cells_subtype_sel == CELLS_SUBTYPE_CMDVOY_VOY1) {		// Un voyant rond ou carré
			sprintf_s(szTemp, "VOYANT POUR AFFICHER L'ÉTAT DES VARIABLES");		TextOut(h_dc_mem_cells, 10 + xdep, yopt + 138, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "V1  : SI VAR: 1, LE VOYANT S'ALLUME(PRIORI)");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 148, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "V2  : SI VAR: 1, LE VOYANT CLIGNOTE");			TextOut(h_dc_mem_cells, 10 + xdep, yopt + 158, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "TXT : 4 LIGNES DE 4 CARACTÈRES");				TextOut(h_dc_mem_cells, 10 + xdep, yopt + 168, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "OPT : FORMES DU VOYANT (-1, 1 A 6)");			TextOut(h_dc_mem_cells, 10 + xdep, yopt + 178, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "    : -1 GROS ROND,");							TextOut(h_dc_mem_cells, 10 + xdep, yopt + 188, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "    : 1 PETIT ROND, 2 PETIT ROND HAUT");			TextOut(h_dc_mem_cells, 10 + xdep, yopt + 198, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "    : 3 CARRÉ, 4 CARRÉ HAUT");		            TextOut(h_dc_mem_cells, 10 + xdep, yopt + 208, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "    : 5 CARRÉ SIMPLE, 6 CARRÉ SIMPLE HAUT");		TextOut(h_dc_mem_cells, 10 + xdep, yopt + 218, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "COULEUR: PAR DÉFAUT OU C1 / C2 SI DÉFINIES");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 228, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "       : VOIR FENÊTRE RENDU(VOYANTS 1,2,4)");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 238, szTemp, strlen(szTemp));
		}

		if (cells_subtype_sel == CELLS_SUBTYPE_CMDVOY_VOY2){		// Deux voyants ronds ou carrés
			sprintf_s(szTemp, "2VOYANTS POUR AFFICHER L'ÉTAT DES VARIABLES"); TextOut(h_dc_mem_cells, 10 + xdep, yopt + 138, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "V1 : SI VAR: 1, LE VOYANT 1 S'ALLUME(PRIO)");  TextOut(h_dc_mem_cells, 10 + xdep, yopt + 148, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "V2 : SI VAR: 1,      //     CLIGNOTE(C1/C2)"); TextOut(h_dc_mem_cells, 10 + xdep, yopt + 158, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "V3 : SI VAR: 1, LE VOYANT 2 S'ALLUME(PRIO)");  TextOut(h_dc_mem_cells, 10 + xdep, yopt + 168, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "V4 : SI VAR: 1,      //     CLIGNOTE(C3/C4)"); TextOut(h_dc_mem_cells, 10 + xdep, yopt + 178, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "TXT : 4 LIGNES DE 4 CARACTÈRES");			  TextOut(h_dc_mem_cells, 10 + xdep, yopt + 188, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "OPT : FORMES DES VOYANTS (-1, 1,2,10,11,12)"); TextOut(h_dc_mem_cells, 10 + xdep, yopt + 198, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "    : -1 ROND, 1 CARRÉ, 2 CARRÉ SIMPLE");	  TextOut(h_dc_mem_cells, 10 + xdep, yopt + 208, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "    : OPT > 10 AFFICHAGE QUE SI VX DÉFINIE");  TextOut(h_dc_mem_cells, 10 + xdep, yopt + 218, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "    : 10 ROND, 11 CARRÉ, 12 CARRÉ SIMPLE");    TextOut(h_dc_mem_cells, 10 + xdep, yopt + 228, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "COULEUR: PAR DÉFAUT OU C1 A C4 SI DÉFINIES");  TextOut(h_dc_mem_cells, 10 + xdep, yopt + 238, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "       : VOIR FENÊTRE RENDU(VOYANTS 1,2,4)");  TextOut(h_dc_mem_cells, 10 + xdep, yopt + 248, szTemp, strlen(szTemp));
		}

		if (cells_subtype_sel == CELLS_SUBTYPE_CMDVOY_VOY4){		// Quatre voyants carrés
			sprintf_s(szTemp, "4VOYANTS POUR AFFICHER L'ÉTAT DES VARIABLES");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 138, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "V1 : SI VAR: 1, LE VOYANT 1 S'ALLUME (C1)");		TextOut(h_dc_mem_cells, 10 + xdep, yopt + 148, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "V2 : SI VAR: 1,      //   2    //    (C2)");		TextOut(h_dc_mem_cells, 10 + xdep, yopt + 158, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "V3 : SI VAR: 1,      //   3    //    (C3)");		TextOut(h_dc_mem_cells, 10 + xdep, yopt + 168, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "V4 : SI VAR: 1,      //   4    //    (C4)");		TextOut(h_dc_mem_cells, 10 + xdep, yopt + 178, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "TXT : 4 LIGNES DE 4 CARACTÈRES");				TextOut(h_dc_mem_cells, 10 + xdep, yopt + 188, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "OPT : FORMES DES VOYANTS (-1, 1,2,10,11,12)");   TextOut(h_dc_mem_cells, 10 + xdep, yopt + 198, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "    : -1 CARRÉ, 1 ROND, 2 CARRÉ SIMPLE");		TextOut(h_dc_mem_cells, 10 + xdep, yopt + 208, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "    : OPT > 10 AFFICHAGE QUE SI VX DÉFINIE");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 218, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "    : 10 CARRÉ, 11 ROND, 12 CARRÉ SIMPLE");		TextOut(h_dc_mem_cells, 10 + xdep, yopt + 228, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "COULEUR: PAR DÉFAUT OU C1 A C4 SI DÉFINIES");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 238, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "       : VOIR FENÊTRE RENDU(VOYANTS 1,2,4)");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 248, szTemp, strlen(szTemp));
		}

		if (cells_subtype_sel == CELLS_SUBTYPE_CMDVOY_LABEL){		// Pour afficher 4 lignes de texte dans un bloc.
			sprintf_s(szTemp, "POUR AFFICHER DU TEXTE:");						TextOut(h_dc_mem_cells, 10 + xdep, yopt + 138, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "TXT : 4 LIGNES DE 4 CARACTÈRES");				TextOut(h_dc_mem_cells, 10 + xdep, yopt + 148, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "COULEUR: PAR DÉFAUT OU C1 SI DÉFINIE");			TextOut(h_dc_mem_cells, 10 + xdep, yopt + 158, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "       : VOIR FENÊTRE RENDU(CoulTEXT)");			TextOut(h_dc_mem_cells, 10 + xdep, yopt + 168, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "OPT : AJOUT D'UN PICTOGRAMME (1 A 29)");			TextOut(h_dc_mem_cells, 10 + xdep, yopt + 178, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "    : 1 HP, 2 PLAY, 3,4 LAMPADAIRE");			TextOut(h_dc_mem_cells, 10 + xdep, yopt + 188, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "    : 5 A 12 RECANGLE, 13 A 20 TOIT MAISON");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 198, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "    : 21,22 MAISON, 23 A 26 LOCO");				TextOut(h_dc_mem_cells, 10 + xdep, yopt + 208, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "    : 27,28 RECTANGLE COULEUR C1");				TextOut(h_dc_mem_cells, 10 + xdep, yopt + 218, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "    : 29 RECTANGLE + COULEUR C1, C2 ,C3 C4");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 228, szTemp, strlen(szTemp));

		}

		if (cells_subtype_sel == CELLS_SUBTYPE_CMDVOY_VAL){		// Pour afficher 3 lignes de texte dans un bloc + une valeur numérique.
			sprintf_s(szTemp, "POUR AFFICHER DU TEXTE + 1 VALEUR NUMÉRIQUE");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 138, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "V1  : AFFICHE LA VALEUR DE V1 SUR 4 DIGITS");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 148, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "POUR BARGRAPHE SERVO UTILISER : SRV_POS_XX");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 158, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "TXT : 3 LIGNES DE 4 CARACTÈRES");				TextOut(h_dc_mem_cells, 10 + xdep, yopt + 168, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "COULEUR: PAR DÉFAUT OU C1 A C3 SI DÉFINIES");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 178, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "       : C1 : COULEUR DU TEXTE");				TextOut(h_dc_mem_cells, 10 + xdep, yopt + 188, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "       : C2 : COULEUR DU TRAIT BARGRAPH");		TextOut(h_dc_mem_cells, 10 + xdep, yopt + 198, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "       : C3 : COULEUR DU NOMBRE");				TextOut(h_dc_mem_cells, 10 + xdep, yopt + 208, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "       : VOIR FENÊTRE RENDU(CoulTEXT)");			TextOut(h_dc_mem_cells, 10 + xdep, yopt + 218, szTemp, strlen(szTemp));
		}

		if (cells_subtype_sel == CELLS_SUBTYPE_CMDVOY_GO)	{		// Pour afficher un autre écran.
			sprintf_s(szTemp, "POUR AFFICHER DIRECTEMENT UN AUTRE ÉCRAN");    TextOut(h_dc_mem_cells, 10 + xdep, yopt + 138, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "TXT : 4 LIGNES DE 4 CARACTÈRES");			  TextOut(h_dc_mem_cells, 10 + xdep, yopt + 148, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "OPT : 0-7:TCO_0a7, 8:TRAIN, 9:TRAIN->CANTON"); TextOut(h_dc_mem_cells, 10 + xdep, yopt + 158, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "10-16:DÉPLACEMENTS, 17:HORO, 18:VIBREUR,");	  TextOut(h_dc_mem_cells, 10 + xdep, yopt + 168, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "19-20:ITI, 21:GARAGES, 22-23:AIG, 24:RS232,"); TextOut(h_dc_mem_cells, 10 + xdep, yopt + 178, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "25-27:VARIABLES, 28-29:CANTONS, 30:SERVOS,");  TextOut(h_dc_mem_cells, 10 + xdep, yopt + 188, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "31:TABLES VÉRITÉ, 32-34:SÉLECTIF, 35-37:AGA"); TextOut(h_dc_mem_cells, 10 + xdep, yopt + 198, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "#1 : FORME DU BLOC (-1, 1, 2, 3, 4)");         TextOut(h_dc_mem_cells, 10 + xdep, yopt + 208, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "COULEUR: PAR DÉFAUT OU C1 SI DÉFINIE");		  TextOut(h_dc_mem_cells, 10 + xdep, yopt + 218, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "       : VOIR FENÊTRE RENDU(CoulTEXT)");		  TextOut(h_dc_mem_cells, 10 + xdep, yopt + 228, szTemp, strlen(szTemp));
		}

		if (cells_subtype_sel == CELLS_SUBTYPE_CMDVOY_SRV) {		// Pour afficher un bouton de commande de servo-moteur.
			sprintf_s(szTemp, "COMMANDE DÉPLACEMENT SERVO");					TextOut(h_dc_mem_cells, 10 + xdep, yopt + 138, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "V1:VAR_SERVO (8000-8305),  TXT:TEXTE LIBRE");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 148, szTemp, strlen(szTemp));
			sprintf_s(szTemp, " |DEPL_BP|INCREME_BP|PLUSIEU_BP| POSIT_BP");		TextOut(h_dc_mem_cells, 10 + xdep, yopt + 158, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "#1|   -1 |PAS 0_1023|        -1|P0  0_1023");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 168, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "#2|   -1 |        -1|BUT 0_1023|P1  0_1023");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 178, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "S+|  +/- |      +/- |(<-SENS DE ROTATION)");		TextOut(h_dc_mem_cells, 10 + xdep, yopt + 188, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "TXT : 4 LIGNES DE 4 CARACTÈRES");				TextOut(h_dc_mem_cells, 10 + xdep, yopt + 198, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "OPT : 0-255 TEMPS ROTATION MAX EN 1/10Sec");		TextOut(h_dc_mem_cells, 10 + xdep, yopt + 208, szTemp, strlen(szTemp));
		}

		if (cells_subtype_sel == CELLS_SUBTYPE_CMDVOY_DIVERS) {		// Bouton poussoir rectangulaire, affiche la liste des déplacements en cours.
			sprintf_s(szTemp, "BLOC A FONCTION MULTIPLES (OPT:1,2,3..) :");		TextOut(h_dc_mem_cells, 10 + xdep, yopt + 138, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "OPT:1 AFFICHE/ANNULE TOUS LES DÉPLACEMENTS");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 148, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "OPT:2 AFFICHE/ANNULE TOUS LES ITINÉRAIRES ");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 158, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "OPT:3 AFFECTE LE TRAIN SUR LE CANTON LIBRE");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 168, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "OPT:4 URGENCE STOP");							TextOut(h_dc_mem_cells, 10 + xdep, yopt + 178, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "OPT:5 BAL-HALTE INHIBITION");					TextOut(h_dc_mem_cells, 10 + xdep, yopt + 188, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "OPT:6 BLOCAGE INHIBITION");						TextOut(h_dc_mem_cells, 10 + xdep, yopt + 198, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "OPT:7 AFFICHAGE DES COMMANDES DES TRAINS");		TextOut(h_dc_mem_cells, 10 + xdep, yopt + 208, szTemp, strlen(szTemp));
			sprintf_s(szTemp, "OPT:8 RAZ TOUS LES BITS INVERSE DES CANTONS");	TextOut(h_dc_mem_cells, 10 + xdep, yopt + 218, szTemp, strlen(szTemp));
		}
	}

	if (cells_type_sel == CELLS_TYPE_RIEN) {
		sprintf_s(szTemp, "CASE VIDE");                                   TextOut(h_dc_mem_cells, 10 + xdep, yopt + 138, szTemp, strlen(szTemp));
		sprintf_s(szTemp, "CLIC-GAUCHE + ESPACE >> RAZ VARIABLE");        TextOut(h_dc_mem_cells, 10 + xdep, yopt + 148, szTemp, strlen(szTemp));
		sprintf_s(szTemp, "CLIC-GAUCHE + NOMBRE + ENTRÉE >> DANS VAR.");  TextOut(h_dc_mem_cells, 10 + xdep, yopt + 158, szTemp, strlen(szTemp));
		sprintf_s(szTemp, "SUR UN BLOC DU TCO :");                        TextOut(h_dc_mem_cells, 10 + xdep, yopt + 168, szTemp, strlen(szTemp));
		sprintf_s(szTemp, " - CLIC-DROIT  = COPIER LE BLOC DEPUIS TCO");  TextOut(h_dc_mem_cells, 10 + xdep, yopt + 178, szTemp, strlen(szTemp));
		sprintf_s(szTemp, " - CLIC-GAUCHE = PLACER LE BLOC");             TextOut(h_dc_mem_cells, 10 + xdep, yopt + 188, szTemp, strlen(szTemp));
		//
		sprintf_s(szTemp, "ON PEUT COPIER/COLLER UNE CASE D'UN TCO");     TextOut(h_dc_mem_cells, 10 + xdep, yopt + 208, szTemp, strlen(szTemp));
		sprintf_s(szTemp, "SUR UN AUTRE TCO, AVEC UN CLIC-DROIT +");      TextOut(h_dc_mem_cells, 10 + xdep, yopt + 218, szTemp, strlen(szTemp));
		sprintf_s(szTemp, "CHANGEMENT DE TCO + CLIC-GAUCHE.");            TextOut(h_dc_mem_cells, 10 + xdep, yopt + 228, szTemp, strlen(szTemp));
	}


	// Dessine les rectangles blancs pour afficher les informations sur les variables V1,V2 V3 et V4.

	SelectObject(h_dc_mem_cells, cells_font); SetBkMode(h_dc_mem_cells, TRANSPARENT); // Défini le mode d'arrière plan. L'arrière-plan n'est pas modifié avant le dessin.
	SetTextColor(h_dc_mem_cells, RGB(0, 0, 0)); //SetTextColor(h_dc_mem_cells,RGB(0,128,128));
	SelectObject(h_dc_mem_cells, bmp_pinceau_blanc);
	SelectObject(h_dc_mem_cells, bmp_stylo_noir);

	Rectangle(h_dc_mem_cells, 100 + xdep, yopt + 20 + 0 - 2, 100 + xdep + 190, yopt + 20 + 10);
	if (temp_conf_v1 != -1) { pio_var_int2ch(temp_conf_v1, szTemp); TextOut(h_dc_mem_cells, 102 + xdep, yopt + 20 + 0, szTemp, strlen(szTemp)); }

	Rectangle(h_dc_mem_cells, 100 + xdep, yopt + 40 + 0 - 2, 100 + xdep + 190, yopt + 40 + 10);
	if (temp_conf_v2 != -1) { pio_var_int2ch(temp_conf_v2, szTemp); TextOut(h_dc_mem_cells, 102 + xdep, yopt + 40 + 0, szTemp, strlen(szTemp)); }

	Rectangle(h_dc_mem_cells, 100 + xdep, yopt + 60 + 0 - 2, 100 + xdep + 190, yopt + 60 + 10);
	if (temp_conf_v3 != -1) { pio_var_int2ch(temp_conf_v3, szTemp); TextOut(h_dc_mem_cells, 102 + xdep, yopt + 60 + 0, szTemp, strlen(szTemp)); }

	Rectangle(h_dc_mem_cells, 100 + xdep, yopt + 80 + 0 - 2, 100 + xdep + 190, yopt + 80 + 10);
	if (temp_conf_v4 != -1) { pio_var_int2ch(temp_conf_v4, szTemp); TextOut(h_dc_mem_cells, 102 + xdep, yopt + 80 + 0, szTemp, strlen(szTemp)); }


	// Dessine les rectangles jaunes et affiche les masques de saisie des paramètres des blocs de TCO.

	SelectObject(h_dc_mem_cells, bmp_pinceau_jaune);
	SelectObject(h_dc_mem_cells, bmp_stylo_noir);

	sprintf_s(szTemp, "CANT"); TextOut(h_dc_mem_cells, 10 + xdep - 6, yopt + 0, szTemp, strlen(szTemp));
	Rectangle(h_dc_mem_cells, 40 + xdep, yopt + 0 - 2, 40 + xdep + 50, yopt + 0 + 10);
	sprintf_s(szTemp, "%d", temp_conf_canton); TextOut(h_dc_mem_cells, 42 + xdep, yopt + 0, szTemp, strlen(szTemp));

	sprintf_s(szTemp, "#1"); TextOut(h_dc_mem_cells, 115 + xdep, yopt, szTemp, strlen(szTemp));
	Rectangle(h_dc_mem_cells, 140 + xdep, yopt - 2, 140 + xdep + 50, yopt + 10);
	sprintf_s(szTemp, "%d", temp_conf_n1); TextOut(h_dc_mem_cells, 142 + xdep, yopt, szTemp, strlen(szTemp));

	sprintf_s(szTemp, "#2"); TextOut(h_dc_mem_cells, 215 + xdep, yopt + 0, szTemp, strlen(szTemp));
	Rectangle(h_dc_mem_cells, 240 + xdep, yopt - 2, 240 + xdep + 50, yopt + 10);
	sprintf_s(szTemp, "%d", temp_conf_n2); TextOut(h_dc_mem_cells, 242 + xdep, yopt, szTemp, strlen(szTemp));

	sprintf_s(szTemp, "V1"); TextOut(h_dc_mem_cells, 10 + xdep, yopt + 20 + 0, szTemp, strlen(szTemp));
	Rectangle(h_dc_mem_cells, 40 + xdep, yopt + 20 - 2, 40 + xdep + 50, yopt + 20 + 10);
	sprintf_s(szTemp, "%d", temp_conf_v1); TextOut(h_dc_mem_cells, 42 + xdep, yopt + 20, szTemp, strlen(szTemp));

	sprintf_s(szTemp, "V2"); TextOut(h_dc_mem_cells, 10 + xdep, yopt + 40 + 0, szTemp, strlen(szTemp));
	Rectangle(h_dc_mem_cells, 40 + xdep, yopt + 40 - 2, 40 + xdep + 50, yopt + 40 + 10);
	sprintf_s(szTemp, "%d", temp_conf_v2); TextOut(h_dc_mem_cells, 42 + xdep, yopt + 40, szTemp, strlen(szTemp));

	sprintf_s(szTemp, "V3"); TextOut(h_dc_mem_cells, 10 + xdep, yopt + 60 + 0, szTemp, strlen(szTemp));
	Rectangle(h_dc_mem_cells, 40 + xdep, yopt + 60 - 2, 40 + xdep + 50, yopt + 60 + 10);
	sprintf_s(szTemp, "%d", temp_conf_v3); TextOut(h_dc_mem_cells, 42 + xdep, yopt + 60, szTemp, strlen(szTemp));

	sprintf_s(szTemp, "V4"); TextOut(h_dc_mem_cells, 10 + xdep, yopt + 80 + 0, szTemp, strlen(szTemp));
	Rectangle(h_dc_mem_cells, 40 + xdep, yopt + 80 - 2, 40 + xdep + 50, yopt + 80 + 10);
	sprintf_s(szTemp, "%d", temp_conf_v4); TextOut(h_dc_mem_cells, 42 + xdep, yopt + 80, szTemp, strlen(szTemp));

	sprintf_s(szTemp, "OPT"); TextOut(h_dc_mem_cells, 10 + xdep, yopt + 100 + 0, szTemp, strlen(szTemp));
	Rectangle(h_dc_mem_cells, 40 + xdep, yopt + 100 - 2, 40 + xdep + 100, yopt + 100 + 10);
	sprintf_s(szTemp, "%d", temp_conf_opt); TextOut(h_dc_mem_cells, 42 + xdep, yopt + 100, szTemp, strlen(szTemp));

	sprintf_s(szTemp, "TXT"); TextOut(h_dc_mem_cells, 10 + xdep, yopt + 120 + 0, szTemp, strlen(szTemp));
	Rectangle(h_dc_mem_cells, 40 + xdep, yopt + 120 - 2, xdep + 221, yopt + 120 + 10);
	MoveToEx(h_dc_mem_cells, 40 + xdep + 200 - 21 - 36, yopt + 115, NULL); LineTo(h_dc_mem_cells, 40 + xdep + 200 - 21 - 36, yopt + 120 - 2); // Affiche des traits verticaux tous les 4 caractères.
	MoveToEx(h_dc_mem_cells, 40 + xdep + 200 - 21 - 2 * 36, yopt + 115, NULL); LineTo(h_dc_mem_cells, 40 + xdep + 200 - 21 - 2 * 36, yopt + 120 - 2); // Affiche des traits verticaux tous les 4 caractères.
	MoveToEx(h_dc_mem_cells, 40 + xdep + 200 - 21 - 3 * 36, yopt + 115, NULL); LineTo(h_dc_mem_cells, 40 + xdep + 200 - 21 - 3 * 36, yopt + 120 - 2); // Affiche des traits verticaux tous les 4 caractères.
	MoveToEx(h_dc_mem_cells, 40 + xdep + 200 - 21 - 4 * 36, yopt + 115, NULL); LineTo(h_dc_mem_cells, 40 + xdep + 200 - 21 - 4 * 36, yopt + 120 - 2); // Affiche des traits verticaux tous les 4 caractères.
	sprintf_s(szTemp, "%s", sz_temp_conf_txt); TextOut(h_dc_mem_cells, 40 + xdep, yopt + 120, szTemp, strlen(szTemp));
	
	// Dessine la case RAZ du texte.
	bmp_select_brush(h_dc_mem_cells, BMP_CST_COLOR_JAUNE);
	//sprintf_s(szTemp, "RAZ"); TextOut(h_dc_mem_cells, 310 + xdep, yopt + 100 + 0, szTemp, strlen(szTemp));
	Rectangle(h_dc_mem_cells, xdep + 236, yopt + 118, xdep + 256, yopt + 130);
	SelectObject(h_dc_mem_cells, bmp_stylo_noir);
	MoveToEx(h_dc_mem_cells, xdep + 240, yopt + 121, NULL); LineTo(h_dc_mem_cells, xdep + 252, yopt + 127);
	MoveToEx(h_dc_mem_cells, xdep + 251, yopt + 121, NULL); LineTo(h_dc_mem_cells, xdep + 239, yopt + 127);
	MoveToEx(h_dc_mem_cells, xdep + 236, yopt + 118, NULL); LineTo(h_dc_mem_cells,xdep + 230, yopt + 124);  LineTo(h_dc_mem_cells,xdep + 236, yopt + 130);

	// Dessine les 4 rectangles de sélection de couleur.
	if (temp_conf_c1 == -1) bmp_select_brush(h_dc_mem_cells, BMP_CST_COLOR_JAUNE);
	else                    bmp_select_brush(h_dc_mem_cells, temp_conf_c1);
	sprintf_s(szTemp, "C1"); TextOut(h_dc_mem_cells, 312 + xdep, yopt + 21, szTemp, strlen(szTemp));
	Rectangle(h_dc_mem_cells, 340 + xdep, yopt + 19, 340 + xdep + 20, yopt + 19 + 10);
	if (temp_conf_c1 == -1) {
		SelectObject(h_dc_mem_cells, bmp_stylo_noir);
		MoveToEx(h_dc_mem_cells, 340 + xdep, yopt + 19, NULL);     LineTo(h_dc_mem_cells, 340 + xdep + 20, yopt + 19 + 10);
		MoveToEx(h_dc_mem_cells, 340 + xdep, yopt + 19 + 9, NULL); LineTo(h_dc_mem_cells, 340 + xdep + 19, yopt + 19);
	}	// Si couleur = -1 => Couleur par défaut = case barrée

	if (temp_conf_c2 == -1) bmp_select_brush(h_dc_mem_cells, BMP_CST_COLOR_JAUNE);
	else                    bmp_select_brush(h_dc_mem_cells, temp_conf_c2);
	sprintf_s(szTemp, "C2"); TextOut(h_dc_mem_cells, 312 + xdep, yopt + 41, szTemp, strlen(szTemp));
	Rectangle(h_dc_mem_cells, 340 + xdep, yopt + 39, 340 + xdep + 20, yopt + 39 + 10);
	if (temp_conf_c2 == -1) {
		SelectObject(h_dc_mem_cells, bmp_stylo_noir);
		MoveToEx(h_dc_mem_cells, 340 + xdep, yopt + 39, NULL);     LineTo(h_dc_mem_cells, 340 + xdep + 20, yopt + 39 + 10);
		MoveToEx(h_dc_mem_cells, 340 + xdep, yopt + 39 + 9, NULL); LineTo(h_dc_mem_cells, 340 + xdep + 19, yopt + 39);
	}	// Si couleur = -1 => Couleur par défaut = case barrée

	if (temp_conf_c3 == -1) bmp_select_brush(h_dc_mem_cells, BMP_CST_COLOR_JAUNE);
	else                    bmp_select_brush(h_dc_mem_cells, temp_conf_c3);
	sprintf_s(szTemp, "C3"); TextOut(h_dc_mem_cells, 312 + xdep, yopt + 61 + 0, szTemp, strlen(szTemp));
	Rectangle(h_dc_mem_cells, 340 + xdep, yopt + 59 + 0, 340 + xdep + 20, yopt + 59 + 10);
	if (temp_conf_c3 == -1) {
		SelectObject(h_dc_mem_cells, bmp_stylo_noir);
		MoveToEx(h_dc_mem_cells, 340 + xdep, yopt + 59 + 0, NULL); LineTo(h_dc_mem_cells, 340 + xdep + 20, yopt + 59 + 10);
		MoveToEx(h_dc_mem_cells, 340 + xdep, yopt + 59 + 9, NULL); LineTo(h_dc_mem_cells, 340 + xdep + 19, yopt + 59 + 0);
	}	// Si couleur = -1 => Couleur par défaut = case barrée

	if (temp_conf_c4 == -1) bmp_select_brush(h_dc_mem_cells, BMP_CST_COLOR_JAUNE);
	else                    bmp_select_brush(h_dc_mem_cells, temp_conf_c4);
	sprintf_s(szTemp, "C4"); TextOut(h_dc_mem_cells, 312 + xdep, yopt + 81 + 0, szTemp, strlen(szTemp));
	Rectangle(h_dc_mem_cells, 340 + xdep, yopt + 79 + 0, 340 + xdep + 20, yopt + 79 + 10);
	if (temp_conf_c4 == -1) {
		SelectObject(h_dc_mem_cells, bmp_stylo_noir);
		MoveToEx(h_dc_mem_cells, 340 + xdep, yopt + 79,     NULL); LineTo(h_dc_mem_cells, 340 + xdep + 20, yopt + 79 + 10);
		MoveToEx(h_dc_mem_cells, 340 + xdep, yopt + 79 + 9, NULL); LineTo(h_dc_mem_cells, 340 + xdep + 19, yopt + 79);
	}	// Si couleur = -1 => Couleur par défaut = case barrée

	// Dessine la case RAZ des couleurs
	bmp_select_brush(h_dc_mem_cells, BMP_CST_COLOR_JAUNE);
	sprintf_s(szTemp, "RAZ"); TextOut(h_dc_mem_cells, 287 + xdep, yopt + 120 + 0, szTemp, strlen(szTemp));
	Rectangle(h_dc_mem_cells, 340 + xdep, yopt + 120 + 0, 340 + xdep + 20, yopt + 120 + 10);
	SelectObject(h_dc_mem_cells, bmp_stylo_noir);
	MoveToEx(h_dc_mem_cells, 340 + xdep+4,  yopt + 120 + 2, NULL); LineTo(h_dc_mem_cells, 340 + xdep + 16, yopt + 120 + 8);
	MoveToEx(h_dc_mem_cells, 340 + xdep+15, yopt + 120 + 2, NULL); LineTo(h_dc_mem_cells, 340 + xdep + 3,  yopt + 120 + 8);
	MoveToEx(h_dc_mem_cells, 340 + xdep, yopt + 121, NULL);    LineTo(h_dc_mem_cells, 349 + xdep, yopt + 112);  LineTo(h_dc_mem_cells, 358  + xdep, yopt + 121);

	sprintf_s(szTemp, "CLIC-DROIT"); TextOut(h_dc_mem_cells, 305 + xdep, yopt + 95, szTemp, strlen(szTemp));
	sprintf_s(szTemp, "ou GAUCHE");  TextOut(h_dc_mem_cells, 310 + xdep, yopt + 103, szTemp, strlen(szTemp));

	sprintf_s(szTemp, "S+"); TextOut(h_dc_mem_cells, 312 + xdep, yopt + 4, szTemp, strlen(szTemp));
	SelectObject(h_dc_mem_cells, bmp_pinceau_gris192);
	SelectObject(h_dc_mem_cells, bmp_stylo_gris192);
	Rectangle(h_dc_mem_cells, 340 + xdep, yopt + 0, 0 + xdep + 360, yopt + 15);
	SelectObject(h_dc_mem_cells, bmp_stylo_noir);

	// Affiche la case 'S+' pour le sens des éléments de voies. Permet d'afficher une fléche dans le sens du parcours du train.
	if (temp_conf_sens == 0) {
		MoveToEx(h_dc_mem_cells, 345 + xdep, yopt + 7, NULL); LineTo(h_dc_mem_cells, xdep + 345, yopt + 0);	// Traits vers le haut et la droite.
		MoveToEx(h_dc_mem_cells, 345 + xdep, yopt + 7, NULL); LineTo(h_dc_mem_cells, xdep + 355, yopt + 0);
		MoveToEx(h_dc_mem_cells, 345 + xdep, yopt + 7, NULL); LineTo(h_dc_mem_cells, xdep + 355, yopt + 7);
		MoveToEx(h_dc_mem_cells, 345 + xdep, yopt + 7, NULL); LineTo(h_dc_mem_cells, xdep + 355, yopt + 15);
	}
	if (temp_conf_sens == 1) {
		MoveToEx(h_dc_mem_cells, 355 + xdep, yopt + 7, NULL); LineTo(h_dc_mem_cells, xdep + 355, yopt + 15);	// Traits vers le bas et la gauche.
		MoveToEx(h_dc_mem_cells, 355 + xdep, yopt + 7, NULL); LineTo(h_dc_mem_cells, xdep + 345, yopt + 0);
		MoveToEx(h_dc_mem_cells, 355 + xdep, yopt + 7, NULL); LineTo(h_dc_mem_cells, xdep + 345, yopt + 7);
		MoveToEx(h_dc_mem_cells, 355 + xdep, yopt + 7, NULL); LineTo(h_dc_mem_cells, xdep + 345, yopt + 15);
	}
	// Affiche la palette à droite de la fenêtre. Non intéractif, uniquement pour aide mémoire pour connaitre les couleurs qui vont défiler.
	for (i = 0; i < BMP_CST_COLOR_NB; i++) {
		rendu_little_rect(xdep + 384, ydep + 205 + 10 * i, i);
	}
	i=BMP_CST_COLOR_TRAIN;
	rendu_little_rect(xdep+384,ydep+205+10*i,BMP_CST_COLOR_JAUNE); // Rectangle barré en croix.
	SelectObject(h_dc_mem_cells,bmp_stylo_noir);
	MoveToEx(h_dc_mem_cells,xdep+384+1,ydep+205+10*i+1,NULL);      LineTo(h_dc_mem_cells,xdep+384+12-1,ydep+205+10*i+8-1);
	MoveToEx(h_dc_mem_cells,xdep+384+12-1-1,ydep+205+10*i+1,NULL); LineTo(h_dc_mem_cells,xdep+384,ydep+205+10*i+8-1);	// Si couleur = -1 => Couleur par défaut = case barrée
}


// Sous-programme pour afficher une fenêtre d'édition horizontale.
// Cette partie n'est pas encore codée ni utilisée. Affiche juste un rectangle gris.
//
void draw_win_conf_H(void)
{
    int ydep;
    ydep=0;
    if(c_conf_wnd=='A') ydep=300; 		// 'A' => On affiche la fenêtre en haut de l'écran, ydep = 0.
										// sinon on l'affiche en bas, xdep = 300.
    SelectObject(h_dc_mem_cells,bmp_pinceau_grisvert);
    SelectObject(h_dc_mem_cells,bmp_stylo_grisvert);
    Rectangle(h_dc_mem_cells,0,ydep,800,ydep+299);
}


// Sous-programme pour afficher les différents mode d'édition des TCO.
// Quand un TCO est affiché, appuyer sur la touche '+' permet de passer d'une
// position d'une fenêtre d'édition à une autre ou de changer de type de fenêtre (Edition/Rendu). 
// Les fenêtres d'édition horizontales ne sont pas encore utilisables.
//
void move_win_conf(void)
{
    switch(c_conf_wnd)	 {					// 'c_conf_wnd' = variable de mode d''affichage en cours.
        case ' ': c_conf_wnd='A'; break;	// 'A'= Affiche la fenêtre 'Edition TCO' à gauche.
        case 'A': c_conf_wnd='B'; break;	// 'B'= Affiche la fenêtre 'Edition TCO' à gauche + 1*décalage à droite
        case 'B': c_conf_wnd='C'; break;	// 'C'= Affiche la fenêtre 'Edition TCO' à gauche + 2*décalages à droite
        case 'C': c_conf_wnd='D'; break;	// 'D'= Affiche la fenêtre 'Edition TCO' à gauche + 3*décalages à droite
        case 'D': c_conf_wnd='H'; break;	// 'H'= Affiche la fenêtre 'Aide sur les variables'.
        case 'H': c_conf_wnd='R'; break;	// 'R'= Affiche la fenêtre 'Rendu des couleurs'.
        case 'R': c_conf_wnd=' '; break;	// ' '= Supprime la fenêtre d'édition.
        default: break;
    }
	cells_redraw=1;
	cells_type_sel=CELLS_TYPE_RIEN;		// Pour afficher l'aide générale en bas de la fenêtre au départ.
}


// Sous-programme pour dessiner un rectangle de couleur donnée.
// Color = RENDU_COLOR_RAIL_LIBRE ou RENDU_COLOR_FOND_LIBRE ou RENDU_USE_GROS_LIBRE...
// Utilisé dans l'affichage de la fenêtre de 'rendu des couleurs'.

void rendu_rect(int x,int y, int color)
{
   SelectObject(h_dc_mem_cells,bmp_stylo_noir);
   if (color<100) {
       if (color<BMP_CST_COLOR_NB)      bmp_select_brush(color);
       if (color==BMP_CST_COLOR_TRAIN)  bmp_select_brush(BMP_CST_COLOR_JAUNE);
       if (color==BMP_CST_COLOR_CANTON) bmp_select_brush(BMP_CST_COLOR_JAUNE);
       Rectangle(h_dc_mem_cells,x,y-2,x+15,y+15);
       if (color==BMP_CST_COLOR_TRAIN)  TextOut(h_dc_mem_cells,x+3, y+3,"T",1);
       if (color==BMP_CST_COLOR_CANTON) TextOut(h_dc_mem_cells,x+3, y+3,"C",1);
   }
   if (color>=100) {
       if (color==100) bmp_select_brush(BMP_CST_COLOR_GRIS192);
       if (color==101) bmp_select_brush(BMP_CST_COLOR_VERT);
       Rectangle(h_dc_mem_cells,x,y-2,x+15,y+15);
       if (color==100) TextOut(h_dc_mem_cells,x+3, y+3,"N",1);
       if (color==101) TextOut(h_dc_mem_cells,x+3, y+3,"O",1);
   }
   SelectObject(h_dc_mem_cells,bmp_pinceau_gris192); SelectObject(h_dc_mem_cells,bmp_stylo_gris192);
}


// Sous-programme pour dessiner un rectangle d'une couleur donnée et de contour noir.
//    rendu_little_rect (Position X, Position Y, n° de couleur).
//
void rendu_little_rect(int x,int y, int color)
{
   SelectObject(h_dc_mem_cells,bmp_stylo_noir);
   bmp_select_brush(color);
   Rectangle(h_dc_mem_cells,x,y,x+12,y+8);
   SelectObject(h_dc_mem_cells,bmp_pinceau_gris192); SelectObject(h_dc_mem_cells,bmp_stylo_gris192);
}


// Sous-programme pour afficher le fenêtre de 'Sélection du rendu'.
// Permet de choisir les couleurs de rendu.
// Cette configuration est sauvegardée à la fin du fichier 'config_tco.txt'.
//
//
void draw_win_rendu(void)
{
    int i,j,x,y; /*int i,j,x,y,v; */
    char szTemp[100];
    //if(c_conf_wnd=='R')
//0. total config window redraw
	// if(do_not_redraw==0 || cells_redraw==1) {
	// On supprime ce test et l'on redessine à chaque fois l'image pour le double buffering.

	cells_redraw=0;
	SelectObject(h_dc_mem_cells,bmp_pinceau_grisvert);
	SelectObject(h_dc_mem_cells,bmp_stylo_grisvert);
	Rectangle(h_dc_mem_cells,0,0,400,680);
	SelectObject(h_dc_mem_cells,bmp_stylo_noir);
	SelectObject(hMemDC,bmp_pinceau_gris192); SelectObject(hMemDC,bmp_stylo_gris192); Rectangle(hMemDC,400-15,15,400-2,2); // [X]
	SelectObject(hMemDC,bmp_stylo_noir);  EasyLine(400-14,3,400-3,14); EasyLine(400-14,13,400-3,2); // Croix noire.
	SelectObject(hMemDC,bmp_stylo_noir);  EasyLine(400-2,1, 400-2,16); EasyLine(400-16,15,400-1,15); // Trait noir.
	SelectObject(hMemDC,bmp_stylo_gris128); EasyLine(400-3,2, 400-3,15); EasyLine(400-15,14,400-2,14); // Trait gris foncé.
	SelectObject(hMemDC,bmp_pinceau_blanc); SelectObject(hMemDC,bmp_stylo_gris192);

//1. partial config window redraw
    SelectObject(h_dc_mem_cells,cells_font);
    SelectObject(h_dc_mem_cells,bmp_pinceau_blanc); SelectObject(h_dc_mem_cells,bmp_stylo_blanc);
	Rectangle(h_dc_mem_cells,40,4,360,14);
	SetTextColor(hMemDC,RGB(0,0,0));
	strcpy(szTemp,"TOUCHE '+' : FENÊTRE SUIVANTE"); TextOut(h_dc_mem_cells,70,5,szTemp,strlen(szTemp));
	strcpy(szTemp,"ESC:QUIT"); TextOut(h_dc_mem_cells,320,17,szTemp,strlen(szTemp));

    SetBkMode(h_dc_mem_cells,TRANSPARENT);
    SetTextColor(h_dc_mem_cells,RGB(0,0,0)); //SetTextColor(h_dc_mem_cells,RGB(0,128,128));
    SelectObject(h_dc_mem_cells,bmp_pinceau_gris192); SelectObject(h_dc_mem_cells,bmp_stylo_gris192);
	x=80; y=20; Rectangle(h_dc_mem_cells,x, y, x+220, y+10); strcpy(szTemp," CONFIGURATION DU RENDU");   TextOut(h_dc_mem_cells,x+1,y+2,szTemp,strlen(szTemp));
	
// Affiche la partie 'Voies'
    x=10;  y=40;  Rectangle(h_dc_mem_cells,x, y, x+370, y+10); strcpy(szTemp," COULEURS DES VOIES");	TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));
	x=10;  y=54;  strcpy(szTemp,"SI COULEUR : [C]OU[T]");									TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));
	x=10;  y=64;  strcpy(szTemp,"LA COULEUR DÉPEND DE :");									TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));
    x=10;  y=74;  strcpy(szTemp,"[C]DU N°DU CANTON,CXXX");									TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));
    x=10;  y=84;  strcpy(szTemp,"[T]DU N°DU TRAIN,TRAIN");									TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));
    x=296; y=84;  strcpy(szTemp,"[O]ui[N]on");												TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));
    x=220; y=60;  Rectangle(h_dc_mem_cells,x, y, x+38, y+10); strcpy(szTemp,"Coul"              ); TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));
           y=70;  Rectangle(h_dc_mem_cells,x, y, x+38, y+10); strcpy(szTemp,"RAIL"              ); TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));
    x=260; y=60;  Rectangle(h_dc_mem_cells,x, y, x+38, y+10); strcpy(szTemp,"Coul"              ); TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));
           y=70;  Rectangle(h_dc_mem_cells,x, y, x+38, y+10); strcpy(szTemp,"FOND"              ); TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));
    x=300; y=60;  Rectangle(h_dc_mem_cells,x, y, x+38, y+10); strcpy(szTemp,"GROS"              ); TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));
           y=70;  Rectangle(h_dc_mem_cells,x, y, x+38, y+10); strcpy(szTemp,"RAIL"              ); TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));
    x=340; y=60;  Rectangle(h_dc_mem_cells,x, y, x+38, y+10); strcpy(szTemp,"SENS"              ); TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));
           y=70;  Rectangle(h_dc_mem_cells,x, y, x+38, y+10); strcpy(szTemp,"FLEC"              ); TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));
    x=20;  y=100; Rectangle(h_dc_mem_cells,x, y, x+185, y+10); strcpy(szTemp,"CANTON LIBRE"     ); TextOut(h_dc_mem_cells,x+3, y+2,szTemp,strlen(szTemp)); rendu_rect(220,y,rendu[RENDU_COLOR_RAIL_LIBRE]);    rendu_rect(260,y,rendu[RENDU_COLOR_FOND_LIBRE]);    rendu_rect(300,y,rendu[RENDU_USE_GROS_LIBRE]+100);    rendu_rect(340,y,rendu[RENDU_USE_FLECHE_LIBRE]+100);
           y=120; Rectangle(h_dc_mem_cells,x, y, x+185, y+10); strcpy(szTemp,"ERREUR OCCUPATION"); TextOut(h_dc_mem_cells,x+3, y+2,szTemp,strlen(szTemp)); rendu_rect(220,y,rendu[RENDU_COLOR_RAIL_OCC]);      rendu_rect(260,y,rendu[RENDU_COLOR_FOND_OCC]);      rendu_rect(300,y,rendu[RENDU_USE_GROS_OCC]+100);      rendu_rect(340,y,rendu[RENDU_USE_FLECHE_OCC]+100);
           y=140; Rectangle(h_dc_mem_cells,x, y, x+185, y+10); strcpy(szTemp,"CANT MANUEL PROCHAIN"); TextOut(h_dc_mem_cells,x+3, y+2,szTemp,strlen(szTemp)); rendu_rect(220,y,rendu[RENDU_COLOR_RAIL_SELPREV]);  rendu_rect(260,y,rendu[RENDU_COLOR_FOND_SELPREV]);  rendu_rect(300,y,rendu[RENDU_USE_GROS_SELPREV]+100);  rendu_rect(340,y,rendu[RENDU_USE_FLECHE_SELPREV]+100);
           y=160; Rectangle(h_dc_mem_cells,x, y, x+185, y+10); strcpy(szTemp,"CANT MANUEL OCCUPÉ" ); TextOut(h_dc_mem_cells,x+3, y+2,szTemp,strlen(szTemp)); rendu_rect(220,y,rendu[RENDU_COLOR_RAIL_SELOCC]);   rendu_rect(260,y,rendu[RENDU_COLOR_FOND_SELOCC]);   rendu_rect(300,y,rendu[RENDU_USE_GROS_SELOCC]+100);   rendu_rect(340,y,rendu[RENDU_USE_FLECHE_SELOCC]+100);
           y=180; Rectangle(h_dc_mem_cells,x, y, x+185, y+10); strcpy(szTemp,"CANT AUTO PROCHAIN" ); TextOut(h_dc_mem_cells,x+3, y+2,szTemp,strlen(szTemp)); rendu_rect(220,y,rendu[RENDU_COLOR_RAIL_AUTOPREV]); rendu_rect(260,y,rendu[RENDU_COLOR_FOND_AUTOPREV]); rendu_rect(300,y,rendu[RENDU_USE_GROS_AUTOPREV]+100); rendu_rect(340,y,rendu[RENDU_USE_FLECHE_AUTOPREV]+100);
           y=200; Rectangle(h_dc_mem_cells,x, y, x+185, y+10); strcpy(szTemp,"CANT AUTO OCCUPÉ"   ); TextOut(h_dc_mem_cells,x+3, y+2,szTemp,strlen(szTemp)); rendu_rect(220,y,rendu[RENDU_COLOR_RAIL_AUTOOCC]);  rendu_rect(260,y,rendu[RENDU_COLOR_FOND_AUTOOCC]);  rendu_rect(300,y,rendu[RENDU_USE_GROS_AUTOOCC]+100);  rendu_rect(340,y,rendu[RENDU_USE_FLECHE_AUTOOCC]+100);
           y=220; Rectangle(h_dc_mem_cells,x, y, x+185, y+10); strcpy(szTemp,"GARAGE ISOLÉ"       ); TextOut(h_dc_mem_cells,x+3, y+2,szTemp,strlen(szTemp)); rendu_rect(220,y,rendu[RENDU_COLOR_RAIL_GARALOCK]); rendu_rect(260,y,rendu[RENDU_COLOR_FOND_GARALOCK]); rendu_rect(300,y,rendu[RENDU_USE_GROS_GARALOCK]+100);

// Affiche la partie 'Général'
    x=10;  y=245;  Rectangle(h_dc_mem_cells,x, y, x+370, y+10); strcpy(szTemp," COULEURS DES BLOCS DU TCO :"); TextOut(h_dc_mem_cells,x+3, y+2,szTemp,strlen(szTemp));
	x=10;  y=259;  strcpy(szTemp,"BALA: COULEUR DU BLOC");									TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));
	x=10;  y=269;  strcpy(szTemp,"DE VOIE,SI LE CANTON ");									TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));
	x=10;  y=279;  strcpy(szTemp,"N'EST PAS DÉFINI     ");									TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));
    x=220; y=260;  Rectangle(h_dc_mem_cells,x, y,  x+38, y+10); strcpy(szTemp,"Coul"           ); TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));
    x=260; y=260;  Rectangle(h_dc_mem_cells,x, y,  x+38, y+10); strcpy(szTemp,"Coul"           ); TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));
    x=300; y=260;  Rectangle(h_dc_mem_cells,x, y,  x+38, y+10); strcpy(szTemp,"Coul"           ); TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));
    x=340; y=260;  Rectangle(h_dc_mem_cells,x, y,  x+38, y+10); strcpy(szTemp,"Coul"           ); TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));
    x=220; y=270;  Rectangle(h_dc_mem_cells,x, y,  x+38, y+10); strcpy(szTemp,"FOND"           ); TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));
    x=260; y=270;  Rectangle(h_dc_mem_cells,x, y,  x+38, y+10); strcpy(szTemp,"BALA"           ); TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));
    x=300; y=270;  Rectangle(h_dc_mem_cells,x, y,  x+38, y+10); strcpy(szTemp,"GRIL"           ); TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));
    x=340; y=270;  Rectangle(h_dc_mem_cells,x, y,  x+38, y+10); strcpy(szTemp,"TEXT"           ); TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));
    x=20;  y=300;  Rectangle(h_dc_mem_cells,x, y, x+185, y+10); strcpy(szTemp,"BLOC D'ÉCRAN DE TCO"    ); TextOut(h_dc_mem_cells,x+3, y+2,szTemp,strlen(szTemp));  rendu_rect(220,y,rendu[RENDU_COLOR_FOND]); rendu_rect(260,y,rendu[RENDU_COLOR_FOND_RAIL]); rendu_rect(300,y,rendu[RENDU_COLOR_GRILLE]); rendu_rect(340,y,rendu[RENDU_COLOR_TEXT]);

// Affiche la partie 'Voyants'
    x=10;  y=325;  Rectangle(h_dc_mem_cells,x, y, x+370, y+10); strcpy(szTemp," COULEURS DES VOYANTS :"); TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));
    x=220; y=340;  Rectangle(h_dc_mem_cells,x, y,  x+38, y+10); strcpy(szTemp,"Coul"           ); TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));
    x=260; y=340;  Rectangle(h_dc_mem_cells,x, y,  x+38, y+10); strcpy(szTemp,"Coul"           ); TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));
    x=300; y=340;  Rectangle(h_dc_mem_cells,x, y,  x+38, y+10); strcpy(szTemp,"Coul"           ); TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));
    x=340; y=340;  Rectangle(h_dc_mem_cells,x, y,  x+38, y+10); strcpy(szTemp,"Coul"           ); TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));
    x=220; y=350;  Rectangle(h_dc_mem_cells,x, y,  x+38, y+10); strcpy(szTemp,"OFF"            ); TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));
    x=260; y=350;  Rectangle(h_dc_mem_cells,x, y,  x+38, y+10); strcpy(szTemp,"ON"             ); TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));
    x=300; y=350;  Rectangle(h_dc_mem_cells,x, y,  x+38, y+10); strcpy(szTemp,"VOFF"           ); TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));
    x=340; y=350;  Rectangle(h_dc_mem_cells,x, y,  x+38, y+10); strcpy(szTemp,"VON"            ); TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));
    x=20;  y=380;  Rectangle(h_dc_mem_cells,x, y, x+185, y+10); strcpy(szTemp,"VOYANT DETECT:-[]-");	TextOut(h_dc_mem_cells,x+3, y+2,szTemp,strlen(szTemp));  rendu_rect(220,y,rendu[RENDU_COLOR_DET_OFF]); rendu_rect(260,y,rendu[RENDU_COLOR_DET_ON]);
           y=400;  Rectangle(h_dc_mem_cells,x, y, x+185, y+10); strcpy(szTemp,"POSITION AIGUILLAGE");	TextOut(h_dc_mem_cells,x+3, y+2,szTemp,strlen(szTemp));  rendu_rect(220,y,rendu[RENDU_COLOR_AIG_OFF]); rendu_rect(260,y,rendu[RENDU_COLOR_AIG_ON]);
           y=420;  Rectangle(h_dc_mem_cells,x, y, x+185, y+10); strcpy(szTemp,"VOYANTS 1,2,4");			TextOut(h_dc_mem_cells,x+3, y+2,szTemp,strlen(szTemp));  rendu_rect(220,y,rendu[RENDU_COLOR_VOY_OFF]); rendu_rect(260,y,rendu[RENDU_COLOR_VOY_ON]);
           y=440;  Rectangle(h_dc_mem_cells,x, y, x+185, y+10); strcpy(szTemp,"VOYANT INTERRUPT/BP");	TextOut(h_dc_mem_cells,x+3, y+2,szTemp,strlen(szTemp));  rendu_rect(220,y,rendu[RENDU_COLOR_INT_OFF]); rendu_rect(260,y,rendu[RENDU_COLOR_INT_ON]);
           y=460;  Rectangle(h_dc_mem_cells,x, y, x+185, y+10); strcpy(szTemp,"VOYANT B.ITI+BORD BP");	TextOut(h_dc_mem_cells,x+3, y+2,szTemp,strlen(szTemp));  rendu_rect(220,y,rendu[RENDU_COLOR_IPP_OFF]); rendu_rect(260,y,rendu[RENDU_COLOR_IPP_ON]); rendu_rect(300,y,rendu[RENDU_COLOR_IPP_LOCKOFF]); rendu_rect(340,y,rendu[RENDU_COLOR_IPP_LOCKON]);

	 x=285 ; y=390; sprintf_s(szTemp, "COULEURS +/-"); TextOut(h_dc_mem_cells,x+3, y+2,szTemp,strlen(szTemp));
	 x=290 ; y=400; sprintf_s(szTemp, "CLIC-DROIT");   TextOut(h_dc_mem_cells,x+3, y+2,szTemp,strlen(szTemp));
	 x=295 ; y=410; sprintf_s(szTemp, "OU GAUCHE");    TextOut(h_dc_mem_cells,x+3, y+2,szTemp,strlen(szTemp));


// Affiche la partie 'Cantons-Trains'
    x=10;  y=500;  Rectangle(h_dc_mem_cells,x, y, x+370, y+10); strcpy(szTemp," COULEURS DES CANTONS [C] ET TRAINS [T]"); TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));
    x=60;  y=520;  for(j=0;j<NB_CARTE;j++) for(i=0;i<NB_CANTON;i++) rendu_little_rect(x+20*i,y+10*j,color_canton[j][i]);		// Rectangle de 12*8 pixels
    x=60;  y=580;                          for(i=0;i<NB_TRAIN_COULEUR;i++)  rendu_little_rect(x+20*i,y,color_train[i]);
    x=10;  y=520;  for(j=0;j<NB_CARTE;j++) { 
				Rectangle(h_dc_mem_cells,x,y+10*j,x+45,y+10+10*j); 
				sprintf_s(szTemp,"C%dXX",1*j); TextOut(h_dc_mem_cells,x,1+y+10*j,szTemp,strlen(szTemp)); }
    x=10;  y=580;       { Rectangle(h_dc_mem_cells,x,y,x+45,y+10); 
				sprintf_s(szTemp,"TRAIN");     TextOut(h_dc_mem_cells,x,1+y     ,szTemp,strlen(szTemp)); }
    x=60;  y=565;  for(i=0;i<NB_CANTON;i++) { 
				Rectangle(h_dc_mem_cells,x+20*i,y,x+20*i+18,y+10); 
				sprintf_s(szTemp,"%2d",i);      TextOut(h_dc_mem_cells,x+20*i,y,szTemp,strlen(szTemp)); }

	x=10;  y=600;  strcpy(szTemp,"SI 'memorisation_train' : ON, LA"); TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));
	x=10;  y=610;  strcpy(szTemp,"MODIFICATION DES COULEURS EST SAUVEGARDÉE"); TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));

	x=10;  y=630;  strcpy(szTemp,"CLIC-GAUCHE:(+)  COULEURS  (-):CLIC-DROIT"); TextOut(h_dc_mem_cells,x+1, y+2,szTemp,strlen(szTemp));

// Affiche verticalement la palette à droite de la fenêtre.
	x=400-14; y=100;  
	for(i=0;i<BMP_CST_COLOR_NB;i++) rendu_little_rect(x,y+10*i,i);
	rendu_little_rect(x,y+10*(i),  BMP_CST_COLOR_JAUNE); TextOut(h_dc_mem_cells,x+1,y+10*(i),  "T",1);
	rendu_little_rect(x,y+10*(i+1),BMP_CST_COLOR_JAUNE); TextOut(h_dc_mem_cells,x+1,y+10*(i+1),"C",1);
}

// Affiche une page d'aide sur les numéros des variables.
//
//
//
void draw_win_aide(void)
{
    int i;
    int xdep,ydep;				/* int xdep,ydep,xopt; */
    char szTemp[100];

	char* lignes_aide[]= {		// Fini par une chaine vide = "".
"NOM            CARTE(1),  CARTE(2): DESCRIPTION",
"det_xxx          0-  15,  100- 115: ÉTAT DE DÉTECTIONS DES TRAINS PAR CANTONS",
"det2_xxx      4000-4015, 4100-4115: CANTON OCCUPÉ, (Avec temporisation, pour feux)",
"det2p_xxx     4020-4035, 4120-4135: CANTON OCCUPÉ, VITESSE>3 (Avec temporisation, pour feux)",
"det2m_xxx     4040-4055, 4140-4155: CANTON OCCUPÉ, VITESSE<3 (Avec temporisation, pour feux)",
"in_xxx         400- 479,  500- 579: VALEURS DES ENTRÉES NUMÉRIQUES (Matricées et directes)",
"can_xxx        800- 805,  900- 905: VALEURS DES ENTRÉES ANALOGIQUES (0-255)",
"out_xxx       1200-1279, 1300-1379: ACTIVATION DES SORTIES (1=SOUS TENSION)",
"led_xxx       1600-1647, 1700-1747: ALLUMAGE LEDS (1=ALLUMÉE)",
"led_cli_xxx   2000-2047, 2100-2147: MODE CLIGNOTEMENT (1=SI ALLUMÉE CLIGNOTE)",
"led_phase_xxx 2400-2447, 2500-2547: INVERSION DE LA PHASE DU CLIGNOTEMENT (1=PHASE INVERSÉE)",
"bal_cant_p_xx 3200-3215, 3300-3315: BLOC AUTOMATIQUE - 1=CANTON BLOQUÉ DANS LE SENS PLUS",
"bal_cant_m_xx 3600-3615, 3700-3715: BLOC AUTOMATIQUE - 1=CANTON BLOQUÉ DANS LE SENS MOINS",
"srv_pos_xxx   2800-2804, 2900-2904: POSITION RÉELLE DU SERVO (0-1023)",
"srv_cmd_xxx   8000-8005, 8100-8105: CONSIGNE DE POSITION DES SERVO,+10=vitesse  (0-1023)",
"var_xxx       5400-5850:   450 VARIABLES LIBRES POUR L'UTILISATEUR (0-1023) (>450 réservé)",
"special_var_x 9100-9199:   100 VARIABLES SPÉCIALES RENSEIGNÉES PAR UTS",
"exe_xxx       8400-8499:Z: EXÉCUTE UN PROGRAMME, SURTOUT UTILE POUR DES SONS",
"pulse_cmd_xxx 8500-8531:Z: DÉCLENCHEMENT D'UNE IMPULSION (Dételeur...)",
"aig_cmd_xxx   5000-5063:   ACTIVE UN AIGUILLAGE EN POSITION 0 ou 1",
"pos0_aig_xxx  5100-5163:   SI AIGUILLAGE EN POSITION 0   =1  (Lecture uniquement)",
"pos1_aig_xxx  5200-5263:   SI AIGUILLAGE EN POSITION 1   =1  (Lecture uniquement)" ,
"iti_start_xxx 6000-6049:Z: ACTIVATION D'UN ITINÉRAIRE    =1  (Écriture uniquement)",
"iti_stop_xxx  6100-6149:Z: DÉSACTIVATION D'UN ITINÉRAIRE =1  (Écriture uniquement)",
"iti_wait_xxx  6200-6249:   ITINÉRAIRE EN ATTENTE         =1  (Lecture uniquement)",
"iti_ok_xxx    6300-6349:   ITINÉRAIRE ÉTABLIT            =1  (Lecture uniquement)",
"pb_capt_t_xxx 9000_9015:   PROBLÈME DE DÉTECTION DES TRAINS (SUR LES CANTONS) 1=PB",
"pb_capt_c_xxx 8600-8615, 8700-8715: PROBLÈME DE DÉTECTION (DE TRAIN) SUR LES CANTONS",
"depl_start_run_xxx    6500-6699:Z:  DÉMARRE UN DÉPLACEMENT",
"depl_stop_xxx         6700-6899:Z:  ARRÊT PRÉMATURÉ D'UN DÉPLACEMENT ",
"garage_lock_cmd_xxx   6900-6915:    COMMANDES DE VERROUILLAGE (ISOLATION) DES GARAGES",
"garage_lock_status_xx 6950-6965:    ÉTATS DE VERROUILLAGE (ISOLATION) DES GARAGES",
"separe_xxx    9400-9499:Z: SÉPARE UN TRAIN EN LOCO + WAGONS        (Écriture uniquement)",
"regroupe_xxx  9500-9599:Z: REGROUPE UNE LOCO + WAGONS EN UN TRAIN  (Écriture uniquement)",
"vib_on        7000:  MISE EN MARCHE SURVEILLANCE DES FAUX-CONTACTS (ACTIVATION DU VIBREUR)",
"vib_state     7002:  ÉTAT DU VIBREUR (ON/OFF)   || screen_mode     7003: N° DE L'ÉCRAN AFFICHÉ",
"arret_urg_on  7004:  ACTIONNE L'ARRÊT D'URGENCE || arret_urg_state 7005: ÉTAT DE L'ARRÊT D'URGENCE",
" ",
"Z  : AUTOMATIQUEMENT REMIS A ZÉRO APRÈS PRISE EN COMPTE (ou à la fin du déplacement)",
""};

	ydep=0;
	xdep=0;
	yopt=40;

//0. total config window redraw
	// if(do_not_redraw==0 || cells_redraw==1)	{ // 'cells_redraw==1' => si ouverture d'une fenêtre ('Edition' ou 'Rendu') ou déplacement <--> de cette fenêtre.
	// On supprime ce test et l'on redessine à chaque fois l'image pour le double buffering.
	cells_redraw=0;
	SelectObject(h_dc_mem_cells,bmp_pinceau_grisvert);	SelectObject(h_dc_mem_cells,bmp_stylo_grisvert);
	Rectangle(h_dc_mem_cells,xdep,0,xdep+800,600+80);	// Fenêtre de 800 x 600 pixels.
	SelectObject(h_dc_mem_cells,bmp_stylo_noir);
	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);
    
	SelectObject(h_dc_mem_cells,cells_font);
    SelectObject(h_dc_mem_cells,bmp_pinceau_blanc); 
	SelectObject(h_dc_mem_cells,bmp_stylo_blanc);
	SetTextColor(hMemDC,RGB(0,0,0)); 
	Rectangle(h_dc_mem_cells,xdep+40,4,xdep+360,14);

	SetBkMode(hMemDC,TRANSPARENT);
	strcpy(szTemp,"TOUCHE '+' : FENÊTRE SUIVANTE"); TextOut(h_dc_mem_cells,xdep+70,5,szTemp,strlen(szTemp));
	strcpy(szTemp,"ESC:QUIT"); TextOut(h_dc_mem_cells,xdep+720,17,szTemp,strlen(szTemp));

	SetBkMode(h_dc_mem_cells,TRANSPARENT);
    SetTextColor(h_dc_mem_cells,RGB(0,0,0)); //SetTextColor(h_dc_mem_cells,RGB(0,128,128));
    SelectObject(h_dc_mem_cells,bmp_pinceau_gris192); SelectObject(h_dc_mem_cells,bmp_stylo_gris192);
	Rectangle(h_dc_mem_cells, xdep+40, ydep+20, xdep+360, ydep+30); strcpy(szTemp,"LISTE DES VARIABLES DE UTS 2000");
	TextOut(h_dc_mem_cells,xdep+65,ydep+22,szTemp,strlen(szTemp));

// Affiche les textes d'aide à la saisie des paramètres propres à chaque bloc de TCO. Texte noir sur grand rectangle blanc en bas de la fenêtre.
    SelectObject(h_dc_mem_cells,bmp_pinceau_noir); 
	SelectObject(h_dc_mem_cells,bmp_stylo_noir);	// Pour les cases C1 à C4 si aucune couleur n'est définie.
	SelectObject(h_dc_mem_cells,aide_font);
	i=0;
	while (strlen(lignes_aide[i])!=0) {
		//TextOut(h_dc_mem_cells,10+xdep,yopt+16*i,lignes_aide[i],strlen(lignes_aide[i]));
		EasyTextOut(10+xdep,yopt+16*i,lignes_aide[i]);
		i++;
		}
	SelectObject(h_dc_mem_cells,cells_font);
	}


// Sous-programme d'affichage d'un écran TCO avec grille sauf sur l'emplacement
// de la fenêtre d'édition ou de rendu.
//
//     (x-1,y-1)    (x,y-1)
//      (x-1,y)      [x,y]   = Emplacement des cases du TCO.
//
void cells_draw(int tco)
{
    int x,y,xdep,xfin,ydep,yfin;

    RECT rect;
    h_dc_mem_cells=hMemDC;
    cells_tick++;
    GetClientRect(hwnd,&rect);   // hwnd =  C'est un nombre entier généré par Windows permettant d'identifier de manière unique une fenêtre.
	                             // GetClientRect renvoie un rectangle dont les champs Top etLeftsont à zéro.
    xdep=0; xfin=(rect.right )/40; if(xfin>(CELLS_X_NB-1)) xfin=CELLS_X_NB-1; if(xfin<0) xfin=0;
    ydep=0; yfin=(rect.bottom)/40; if(yfin>(CELLS_Y_NB-1)) yfin=CELLS_Y_NB-1; if(yfin<0) yfin=0;

    for(x=xdep;x<=xfin;x++) for(y=ydep;y<=yfin;y++) {
        if(c_conf_wnd=='R' && x>= 0 && x<= 9 && y<=14) continue;	// Ne pas dessiner sur la fenêtre 'Rendu des couleurs' à gauche.
        if(c_conf_wnd=='A' && x>= 0 && x<= 9 && y<=14) continue;	// Ne pas dessiner sur la fenêtre 'Edition TCO' à gauche.
        if(c_conf_wnd=='B' && x>= 5 && x<=14 && y<=14) continue;
        if(c_conf_wnd=='C' && x>=10 && x<=19 && y<=14) continue;
        if(c_conf_wnd=='D' && x>=19 && x<=28 && y<=14) continue;
        if(c_conf_wnd=='H' && x>= 0 && x<=19 && y<=14) continue;	// Ne pas dessiner sur la fenêtre 'Aide sur les variables' à gauche.
//      if(c_conf_wnd=='S' && y>=7  && y<=14) continue;			// Ne pas dessiner sur la fenêtre 'Edition TCO' en bas.

// Affiche à l'écran un bloc avec ses valeurs animées.
        private_cells_draw_one(      cells[tco][x][y][CELLS_TYPE],cells[tco][x][y][CELLS_SUBTYPE],CELLS_SIZE*x,CELLS_SIZE*y,sz_cells[tco][x][y],
        cells[tco][x][y][CELLS_CANT],cells[tco][x][y][CELLS_N1],  cells[tco][x][y][CELLS_N2],
        cells[tco][x][y][CELLS_V1],  cells[tco][x][y][CELLS_V2],  cells[tco][x][y][CELLS_V3],cells[tco][x][y][CELLS_V4],
        cells[tco][x][y][CELLS_C1],  cells[tco][x][y][CELLS_C2],  cells[tco][x][y][CELLS_C3],cells[tco][x][y][CELLS_C4],
        cells[tco][x][y][CELLS_OPT], cells[tco][x][y][CELLS_SENS]);

// Pour les parties horizontales, dessine un point noir à gauche sur la voie pour séparer les cantons de numéros différents.
        if(x>=1)
        if(cells[tco][x-1][y][CELLS_CANT]!=-1)
		if(cells[tco][x][y][CELLS_CANT]!=cells[tco][x-1][y][CELLS_CANT] && (cells[tco][x][y][CELLS_CANT]!=cells[tco][x-1][y][CELLS_N2] || cells[tco][x-1][y][CELLS_TYPE]!=CELLS_TYPE_LINK))
        if((cells[tco][x][y][CELLS_TYPE]==CELLS_TYPE_AIG &&			// Aiguillages horizontaux
		    (cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_AIG_HC
		    || cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_AIG_CH 
		    || cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_AIG_CB 
		    || cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_AIG_BC
		    || cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_AIG_CHB
		    || cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_AIG_HBC))
		  ||(cells[tco][x][y][CELLS_TYPE]==CELLS_TYPE_SPE &&		// Butoir à droite
		    (cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_SPE_CH
		    || cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_SPE_VOY
		    || cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_SPE_CANT
		    || cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_SPE_IN
		    || cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_SPE_OUT
		    || cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_SPE_SENS
		    || cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_SPE_FEU
		    || cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_SPE_DETEL))
		  ||(cells[tco][x][y][CELLS_TYPE]==CELLS_TYPE_LINK &&		// Voies horizontales à gauche
		    (cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_LINK_H
		    || cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_LINK_PH
		    || cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_LINK_OSE
		    || cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_LINK_ONE
		    || cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_LINK_ON
		    || cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_LINK_OS))) {
		SelectObject(h_dc_mem_cells,bmp_stylo_noir); SelectObject(h_dc_mem_cells,bmp_pinceau_noir);
		Ellipse(h_dc_mem_cells,CELLS_SIZE*x-3,CELLS_SIZE*y+17,CELLS_SIZE*x+6-3,CELLS_SIZE*y+17+6);
	}
// Pour les parties verticales, dessine un point en haut sur la voie, pour séparer les cantons de numéros différents.
	if(y>=1)
	if(cells[tco][x][y-1][CELLS_CANT]!=-1)
	if(cells[tco][x][y][CELLS_CANT]!=cells[tco][x][y-1][CELLS_CANT] && (cells[tco][x][y][CELLS_CANT]!=cells[tco][x][y-1][CELLS_N2] || cells[tco][x][y-1][CELLS_TYPE]!=CELLS_TYPE_LINK))
	if((cells[tco][x][y][CELLS_TYPE]==CELLS_TYPE_AIG &&			// Aiguillages verticaux
		   (cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_AIG_HCV 
		    || cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_AIG_CHV 
		    || cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_AIG_CBV 
		    || cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_AIG_BCV))
	    ||(cells[tco][x][y][CELLS_TYPE]==CELLS_TYPE_SPE &&		// Butoir en bas
		    (cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_SPE_VC
 		    || cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_SPE_VOYV
		    || cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_SPE_CANTV
		    || cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_SPE_INV
		    || cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_SPE_OUTV
		    || cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_SPE_SENSV
		    || cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_SPE_FEUV
			|| cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_SPE_DETELV))
	    ||(cells[tco][x][y][CELLS_TYPE]==CELLS_TYPE_LINK &&		// Voies verticales à en haut
		    (cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_LINK_V
		    || cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_LINK_PV
		    || cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_LINK_NSE
		    || cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_LINK_SON
		    || cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_LINK_ON
		    || cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_LINK_NE))) {
		SelectObject(h_dc_mem_cells,bmp_stylo_noir); SelectObject(h_dc_mem_cells,bmp_pinceau_noir);
		Ellipse(h_dc_mem_cells,CELLS_SIZE*x+17,CELLS_SIZE*y-3,CELLS_SIZE*x+17+6,CELLS_SIZE*y+6-3);	// V3.3
	}

// Pour les parties en diagonales = '\', dessine un point en haut à gauche sur la voie, pour séparer les cantons de numéros différents.
	if(x>=1 && y>=1)
	if(cells[tco][x-1][y-1][CELLS_CANT]!=-1)
	if(cells[tco][x][y][CELLS_CANT]!=cells[tco][x-1][y-1][CELLS_CANT] && (cells[tco][x][y][CELLS_CANT]!=cells[tco][x-1][y-1][CELLS_N2] || cells[tco][x-1][y-1][CELLS_TYPE]!=CELLS_TYPE_LINK))
	if((cells[tco][x][y][CELLS_TYPE]==CELLS_TYPE_AIG &&			// Aiguillages avec sortie en haut à gauche
		(cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_AIG_HC 
		    || cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_AIG_HCV
		    || cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_AIG_HBC))
	      ||(cells[tco][x][y][CELLS_TYPE]==CELLS_TYPE_LINK &&		// Voies avec sortie en haut à gauche
		    (cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_LINK_NOS
		    || cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_LINK_NOE
		    || cells[tco][x][y][CELLS_SUBTYPE]==CELLS_SUBTYPE_LINK_NOSE))) {
		SelectObject(h_dc_mem_cells,bmp_stylo_noir); SelectObject(h_dc_mem_cells,bmp_pinceau_noir);
		Ellipse(h_dc_mem_cells,CELLS_SIZE*x-3,CELLS_SIZE*y-3,CELLS_SIZE*x+3,CELLS_SIZE*y+3);	// V3.3
	}

// Pour les parties en diagonales = '/', dessine un point en bas à gauche sur la voie, pour séparer les cantons de numéros différents.
// Dessine le bloc du dessus (y-1) pour que le point ne soit pas effacé par l'affichage du bloc suivant en dessous(y+1). 
// Compare (x,y-1) à (x-1,y) puis dessine pour le bloc (x,y-1). 
	if(x>=1 && y>=1)
	if(cells[tco][x-1][y][CELLS_CANT]!=-1)
//	if(cells[tco][x][y-1][CELLS_CANT]!=cells[tco][x-1][y][CELLS_CANT])
	if(cells[tco][x][y-1][CELLS_CANT]!=cells[tco][x-1][y][CELLS_CANT] && (cells[tco][x][y-1][CELLS_CANT]!=cells[tco][x-1][y][CELLS_N2] || cells[tco][x-1][y][CELLS_TYPE]!=CELLS_TYPE_LINK))

	if((cells[tco][x][y-1][CELLS_TYPE]==CELLS_TYPE_AIG &&			// Aiguillages avec sortie en haut à gauche
		(cells[tco][x][y-1][CELLS_SUBTYPE]==CELLS_SUBTYPE_AIG_BC 
		    || cells[tco][x][y-1][CELLS_SUBTYPE]==CELLS_SUBTYPE_AIG_BCV
		    || cells[tco][x][y-1][CELLS_SUBTYPE]==CELLS_SUBTYPE_AIG_HBC))
		    ||(cells[tco][x][y-1][CELLS_TYPE]==CELLS_TYPE_LINK &&		// Voies avec sortie en haut à gauche
		    (cells[tco][x][y-1][CELLS_SUBTYPE]==CELLS_SUBTYPE_LINK_SON
		    || cells[tco][x][y-1][CELLS_SUBTYPE]==CELLS_SUBTYPE_LINK_SONE
		    || cells[tco][x][y-1][CELLS_SUBTYPE]==CELLS_SUBTYPE_LINK_SOE))) {
			SelectObject(h_dc_mem_cells,bmp_stylo_noir); SelectObject(h_dc_mem_cells,bmp_pinceau_noir);
			Ellipse(h_dc_mem_cells,CELLS_SIZE*x-3,CELLS_SIZE*(y-1)+40-3,CELLS_SIZE*x+3,CELLS_SIZE*(y-1)+40+3);	// V3.3
		}
	}
	if(c_conf_wnd=='A' || c_conf_wnd=='B' || c_conf_wnd=='C'|| c_conf_wnd=='D') draw_win_conf_V();	// Affiche une fenêtre d'édition verticale
	if(c_conf_wnd=='H') draw_win_aide();	// Affiche une fenêtre d'aide sur les variables
//  if(c_conf_wnd=='N' || c_conf_wnd=='S') draw_win_conf_H();	// Affiche une fenêtre d'édition horizontale (pas encore codé)
	if(c_conf_wnd=='R') draw_win_rendu();	// Affiche une fenêtre de rendu des couleurs verticale
//BitBlt(hMemDC,0,0,800,680,h_dc_mem_cells,0,0,SRCCOPY); // MERGECOPY not really good
}

// Sous-programme pour savoir si l'on à cliquer sur un rectangle dessiné par la routine 'rendu_rect()'.
// Retourne '1' si l'on a cliqué dans le rectangle passé en paramètre.
//
int mouse_in_rendu_rect(int x, int y)
{
	if(x_mouse>x && x_mouse<(x+15) && y_mouse>y && y_mouse<(y+15)) return 1;
	return 0;
}


// Sous-programme appelé en cas d'appui sur un des boutons de la souris ou la frappe d'un caractère.
// Un TCO est affiché.
//
//
void cells_debug(int tco, int action)
{
	int xdep, i, j, x_sel, y_sel, x, y, v, v1, v2, v3, n1, n2, cant, sens, g;
	int k, l, t;
	int opt, train1, train2, cant1, cant2;
	xdep = 0;

	if (action == DEBUG_KEY) {
		if (touche_char == '+') move_win_conf();	// Dans un TCO permet d'afficher successivement les fenêtres d'édition des TCO
		if (cells_entry_sel != -1) {
			switch (cells_entry_sel) {
			case 1: if (touche_char >= '0' && touche_char <= '9') { if (temp_conf_canton == -1) temp_conf_canton = 0; temp_conf_canton = temp_conf_canton * 10 + touche_char - '0'; }
					if (temp_conf_canton > 100000 || touche_char == ' ') temp_conf_canton = -1; break;
			case 2: if (touche_char >= '0' && touche_char <= '9') { if (temp_conf_n1 == -1) temp_conf_n1 = 0; temp_conf_n1 = temp_conf_n1 * 10 + touche_char - '0'; }
					if (temp_conf_n1 > 100000 || touche_char == ' ') temp_conf_n1 = -1; break;
			case 3: if (touche_char >= '0' && touche_char <= '9') { if (temp_conf_n2 == -1) temp_conf_n2 = 0; temp_conf_n2 = temp_conf_n2 * 10 + touche_char - '0'; }
					if (temp_conf_n2 > 100000 || touche_char == ' ') temp_conf_n2 = -1; break;
			case 4: if (touche_char >= '0' && touche_char <= '9') { if (temp_conf_v1 == -1) temp_conf_v1 = 0; temp_conf_v1 = temp_conf_v1 * 10 + touche_char - '0'; }
					if (temp_conf_v1 > 100000 || touche_char == ' ') temp_conf_v1 = -1; break;
			case 5: if (touche_char >= '0' && touche_char <= '9') { if (temp_conf_v2 == -1) temp_conf_v2 = 0; temp_conf_v2 = temp_conf_v2 * 10 + touche_char - '0'; }
					if (temp_conf_v2 > 100000 || touche_char == ' ') temp_conf_v2 = -1; break;
			case 6: if (touche_char >= '0' && touche_char <= '9') { if (temp_conf_v3 == -1) temp_conf_v3 = 0; temp_conf_v3 = temp_conf_v3 * 10 + touche_char - '0'; }
					if (temp_conf_v3 > 100000 || touche_char == ' ') temp_conf_v3 = -1; break;
			case 7: if (touche_char >= '0' && touche_char <= '9') { if (temp_conf_v4 == -1) temp_conf_v4 = 0; temp_conf_v4 = temp_conf_v4 * 10 + touche_char - '0'; }
					if (temp_conf_v4 > 100000 || touche_char == ' ') temp_conf_v4 = -1; break;
			case 8: if (touche_char >= '0' && touche_char <= '9') { if (temp_conf_opt == -1) temp_conf_opt = 0; temp_conf_opt = temp_conf_opt * 10 + touche_char - '0'; }
					if (temp_conf_opt > 100000 || touche_char == ' ') temp_conf_opt = -1; break;
			case 9: if ((touche_char >= '0' && touche_char <= '9') || (touche_char >= 'a' && touche_char <= 'z') || (touche_char >= 'A' && touche_char <= 'Z') || touche_char == ' ' 
				       || touche_char == '_' || touche_char == '-' || touche_char == '*'|| touche_char == '(' || touche_char == ')' || touche_char == '<' || touche_char == '>' || touche_char == '[' || touche_char == ']') {
						for (i = 0; i < 19; i++) sz_temp_conf_txt[i] = sz_temp_conf_txt[i + 1];
						sz_temp_conf_txt[19] = touche_char; // Conversion de 'int' en 'char'.
						sz_temp_conf_txt[20] = '\0';
			}
					break;
			default: break;
			}
		}
	}

	if (action == DEBUG_MOUSE) {   // ACTION = CLIC (gauche) DE LA SOURIS
		x_sel = (x_mouse) / 40;
		y_sel = (y_mouse) / 40;
		if (c_conf_wnd == ' ') // La fenêtre d'édition est fermée (Pas de grille à afficher).
		if (x_sel >= 0 && x_sel < CELLS_X_NB && y_sel >= 0 && y_sel < CELLS_Y_NB) {
			if (cells[tco][x_sel][y_sel][CELLS_TYPE] == CELLS_TYPE_CMDVOY && cells[tco][x_sel][y_sel][CELLS_SUBTYPE] == CELLS_SUBTYPE_CMDVOY_INT) {
				v1 = cells[tco][x_sel][y_sel][CELLS_V1];
				v = -1;
				if (v1 != -1) v = pio_get_val(v1);
				if (v != -1) {
					if (v)    pio_set_val(v1, 0);
					if (v == 0) pio_set_val(v1, 1);
				}
			}

			if (cells[tco][x_sel][y_sel][CELLS_TYPE] == CELLS_TYPE_CMDVOY && cells[tco][x_sel][y_sel][CELLS_SUBTYPE] == CELLS_SUBTYPE_CMDVOY_SRV) {
				// Début partie animation des servo moteurs.
				v1 = cells[tco][x_sel][y_sel][CELLS_V1];
				v2 = cells[tco][x_sel][y_sel][CELLS_V2];
				n1 = cells[tco][x_sel][y_sel][CELLS_N1];
				n2 = cells[tco][x_sel][y_sel][CELLS_N2];
				sens = cells[tco][x_sel][y_sel][CELLS_SENS];
				opt = cells[tco][x_sel][y_sel][CELLS_OPT];
				if (v1 != -1) {
					v = pio_get_val(v1);
					if (opt != 0) opt = 1 + 972 / opt; // Si pas de valeur=0, alors par défaut = la vitesse la plus rapide
					else opt = 1023;
					opt = max(1, opt);
					opt = min(opt, 1023);      // opt entre 1 et 1023 = vitesse de déplacement.
					if (n1 == -1 && n2 == -1) { // Déplacement continu dans un sens ou l'autre.
						if (sens == 0) pio_set_val(v1, 1023);  // valeur de consigne V1 = 8xxx
						if (sens == 1) pio_set_val(v1, 0);     // valeur de consigne
						pio_set_val(v1 + NB_SERVO_VIT, opt);   // 972 = 1024 * (0.08-.015) * 10 = max servo * timer prg * tempo en 1/10 secondes
						cells_pouss_en_cours_srv = 1;
						cells_pouss_en_cours = v1;
					}
					if (n1 == -1 && n2 >= 0 && n2 <= 1023) { // Pour une position 'n2' par bouton poussoir .
						pio_set_val(v1, n2);
						pio_set_val(v1 + NB_SERVO_VIT, opt); // 972 = 1024 * (0.08-.015) * 10 = max servo * timer prg * tempo en 1/10 secondes
					}
					if (n1 != -1 && n2 == -1) { // Déplacement ponctuel dans un sens ou l'autre d'un pas ='n1'.
						if (sens == 0) v = v + n1;
						if (sens == 1) v = v - n1;
						v = max(0, v);
						v = min(v, 1023);
						pio_set_val(v1, v);                // Consigne
						pio_set_val(v1 + NB_SERVO_VIT, opt); // Vitesse
					}
					if (n1 != -1 && n2 != -1 && v2 == -1) { // Deux positions par bouton poussoir.
						if (v != n1) v = n1;
						else v = n2;
						v = max(0, v);
						v = min(v, 1023);
						pio_set_val(v1, v);                // Consigne
						pio_set_val(v1 + NB_SERVO_VIT, opt); // Vitesse
					}
				}
			}
			// Pour deux positions commandées par une variable ou une entrée numérique, exemple : une barrière de passage à niveau, configurer une équation dans 'config.txt' :
			//    #tdv
			//    [
			//    equ: l  var_5 =val srv_cmd_000 111        -> si var_5 = 1 le servo est en position 111 (de 0 à 1023)
			//    equ: l  var_5 =val srv_cmd_010 10            srv_cmd_010 = vitesse du servo n°0 (de 1 lent à 1023 rapide)
			//    equ: ln var_5 =val srv_cmd_000 222        -> si var_5 = 0 le servo est en position 222 (de 0 à 1023)
			//    equ: ln var_5 =val srv_cmd_010 10            srv_cmd_010 = vitesse du servo n°0 (de 1 lent à 1023 rapide)
			//    ]
			// Si on remplace 'var_5' par 'in_1', on commande les postion d'un servo à partir de l'entrée n°1 (0/1).
			//fin nouveau partie servo

			if (cells[tco][x_sel][y_sel][CELLS_TYPE] == CELLS_TYPE_CMDVOY && cells[tco][x_sel][y_sel][CELLS_SUBTYPE] == CELLS_SUBTYPE_CMDVOY_POUSS) {
				v1 = cells[tco][x_sel][y_sel][CELLS_V1]; if (v1 != -1) { pio_set_val(v1, 1); cells_pouss_en_cours = v1; cells_pouss_en_cours_srv = 0; }
				v2 = cells[tco][x_sel][y_sel][CELLS_V2]; if (v2 != -1) pio_set_val(v2, 1);
				v3 = cells[tco][x_sel][y_sel][CELLS_V3]; if (v3 != -1) pio_set_val(v3, 0);
			}

			if (cells[tco][x_sel][y_sel][CELLS_TYPE] == CELLS_TYPE_CMDVOY && cells[tco][x_sel][y_sel][CELLS_SUBTYPE] == CELLS_SUBTYPE_CMDVOY_DIVERS) {
				if (cells[tco][x_sel][y_sel][CELLS_OPT] == 1){  // Si option = 1 dans le bloc divers.
					// Actions diverses suivant la valeur de 'OPT'=1  => RAZ DEPLACEMENTS
					cmd_divers[CMD_DIVERS_VAR_BOUTON1] = 1;
					for (i = 0; i < DEPL_TAB_NB; i++) {
						if (depl_tab[i][DEPL_TAB_IND_CANT_START] != -1 && depl_tab[i][DEPL_TAB_IND_STEP] != DEPL_CST_STATE_IDLE) {
							depl_tab[i][DEPL_TAB_IND_STOP] = 1; // Pour tous les déplacements valides.
						}
					}
				}
				else if (cells[tco][x_sel][y_sel][CELLS_OPT] == 2) { // Si option = 2 dans le bloc divers.
					// Actions diverses suivant la valeur de 'OPT'=2  => RAZ ITINERAIRES
					cmd_divers[CMD_DIVERS_VAR_BOUTON2] = 1;
					for (i = 0; i < ITI_TAB_NB; i++) {
						if (iti_tab[i][ITI_TAB_IND_EXIST] == 1 && iti_tab[i][ITI_TAB_IND_STEP] != ITI_CST_STATE_IDLE){
							iti_tab[i][ITI_TAB_IND_STOP] = 1;  // Pour tous les itinéraires.
						}
					}
				}
				else if (cells[tco][x_sel][y_sel][CELLS_OPT] == 3) {  // Si option = 3 dans le bloc divers.
					// Actions diverses suivant la valeur de 'OPT'=3  => AFFECTATION AUTOMATIQUE : train en erreur => canton en erreur.
					cmd_divers[CMD_DIVERS_VAR_BOUTON3] = 1;
					if (cmd_divers[CMD_DIVERS_OPT3_OK] == 1) {
						for (l = 0; l < NB_CARTE; l++) {
							for (k = 0; k < NB_CANTON; k++) {             // libération de l'ancien canton ou le train était attendu (et donc selectif)
								if (canton.num_train[l][k] == cmd_divers[CMD_DIVERS_OPT3_TRAIN]) { // après avoir choisi un garage ou un canton.
									canton.master_selectif[l][k] = 0;
									canton.inv_selectif[l][k] = 0;
									canton.update_selectif[l][k] = 0;
								}
							}
						}
						g = train.cant_lock[cmd_divers[CMD_DIVERS_OPT3_TRAIN]];  // Libération garage.
						if (g >= 0 && g < NB_GARAGE_REEL) {
							vio_garage_lock_cmd[g] = 0;    // 0 ou 1, 1 => Demande d'isolation du garage (Sera réalisée si il a un train sur le canton).
							vio_garage_lock_status[g] = 0; // 0 ou 1, 1 => Le garage est isolé du canton (état réel).
							vio_garage_lock_res[g] = 0;    // 0 ou 1, 1 => Garage réservé.
							garage.numero_train[g] = -1;   // -1 = Garage relié au canton, ou Numéro de train occupant le garage isolé du canton.
							train.cant_lock[cmd_divers[CMD_DIVERS_OPT3_TRAIN]] = -1;
						}
						canton.num_train[cmd_divers[CMD_DIVERS_OPT3_CARTE]][cmd_divers[CMD_DIVERS_OPT3_CANTON]] = cmd_divers[CMD_DIVERS_OPT3_TRAIN];
						canton.master_selectif[cmd_divers[CMD_DIVERS_OPT3_CARTE]][cmd_divers[CMD_DIVERS_OPT3_CANTON]] = 1;
						canton.inv_selectif[cmd_divers[CMD_DIVERS_OPT3_CARTE]][cmd_divers[CMD_DIVERS_OPT3_CANTON]] = 0;
						canton.update_selectif[cmd_divers[CMD_DIVERS_OPT3_CARTE]][cmd_divers[CMD_DIVERS_OPT3_CANTON]] = 0;
					}
				}
				else if (cells[tco][x_sel][y_sel][CELLS_OPT] == 4) {  // Si option = 4 dans le bloc divers.
					// Actions diverses suivant la valeur de 'OPT'=4  ARRET DES TRAINS
					cmd_divers[CMD_DIVERS_VAR_BOUTON4] = 1;
					cmd_divers[CMD_DIVERS_OPT4_ARRET] ^= 1;
				}
				else if (cells[tco][x_sel][y_sel][CELLS_OPT] == 5) {  // Si option = 5 dans le bloc divers.
					// Actions diverses suivant la valeur de 'OPT'=5 'HLT'. Cantons en 'halt:'
					cmd_divers[CMD_DIVERS_VAR_BOUTON5] = 1;
					cmd_divers[CMD_DIVERS_OPT5_HALTE] ^= 1;
				}
				else if (cells[tco][x_sel][y_sel][CELLS_OPT] == 6) {  // Si option = 6 dans le bloc divers.
					// Actions diverses suivant la valeur de 'OPT'=6 'BLC'. Cantons en blocage 'cant:'.
					cmd_divers[CMD_DIVERS_VAR_BOUTON6] = 1;
					cmd_divers[CMD_DIVERS_OPT6_BLOCAG] ^= 1;
				}
				else if (cells[tco][x_sel][y_sel][CELLS_OPT] == 56) {  // Si option = 56 dans le bloc divers.
					// Actions diverses suivant la valeur de 'OPT'=56 'B&H'. Cantons en blocage 'cant:'. + 'halt:'
					cmd_divers[CMD_DIVERS_VAR_BOUTON5] = 1;
					cmd_divers[CMD_DIVERS_OPT5_HALTE] ^= 1;
					cmd_divers[CMD_DIVERS_VAR_BOUTON6] = 1;
					cmd_divers[CMD_DIVERS_OPT6_BLOCAG] ^= 1;
				}
				else if (cells[tco][x_sel][y_sel][CELLS_OPT] == 7) {  // Si option = 6 dans le bloc divers.
					// Actions diverses suivant la valeur de 'OPT'=6 'BLC'.
					cmd_divers[CMD_DIVERS_VAR_BOUTON7] = 1;
				}

				if (cells[tco][x_sel][y_sel][CELLS_OPT] == 8) {  // Si option = 8 dans le bloc divers.
					// Actions diverses suivant la valeur de 'OPT'=8  => RAZ bit INVS de tous les cantons dont la vitesse est == 0.
					cmd_divers[CMD_DIVERS_VAR_BOUTON8] = 1;
					for (i = 0; i < NB_CARTE; i++) {
						for (j = 0; j < NB_CANTON; j++) {
							if ((canton.master_selectif[i][j] != 0 || canton.update_selectif[i][j] != 0) && (canton.vit_selectif[i][j] == 0)) {
								t = canton.num_train[i][j];	// On récupere le n° du train.
								if (t != -1) {
									if (balauto_halt_train[t] == 0 && balauto_cant_train[t] == 0 && balauto_cant_train[t] == 0) {
										canton.inv_selectif[i][j] = 0; // Raz bit 'inverse', si le canton a une vitesse nulle, mais n'est pas bloqué ou en 'halte'.
									}
								}
							}
						}
					}
				}
			}

			if (cells[tco][x_sel][y_sel][CELLS_TYPE] == CELLS_TYPE_CMDVOY && cells[tco][x_sel][y_sel][CELLS_SUBTYPE] == CELLS_SUBTYPE_CMDVOY_ITI) {
				if ((x_mouse % 40)<8 || (x_mouse % 40)>40 - 8) cells[tco][x_sel][y_sel][CELLS_OPT] = (cells[tco][x_sel][y_sel][CELLS_OPT]++) & 1;
				if ((x_mouse % 40) >= 8 && (x_mouse % 40) <= 40 - 8) {
					if (cells[tco][x_sel][y_sel][CELLS_OPT] != 1) {
						// On a cliqué (gauche) sur le bord du bouton rond 'Itinéraire'. On vérrouille le bouton et le bord circulaire change de couleur.
						// On peut cliquer à droite ou à gauche du bouton.
						v1 = cells[tco][x_sel][y_sel][CELLS_V1];
						if (v1 != -1) pio_set_val(v1, 1); // Met la variable 'iti_start_xxx' = 1.
					}
				}
			}

			if (cells[tco][x_sel][y_sel][CELLS_TYPE] == CELLS_TYPE_SPE && cells[tco][x_sel][y_sel][CELLS_SUBTYPE] == CELLS_SUBTYPE_SPE_HOR) {
				horo_tic_on = (horo_tic_on ^ 1) & 1;
			}

			n1 = cells[tco][x_sel][y_sel][CELLS_N1];
			if (cells[tco][x_sel][y_sel][CELLS_TYPE] == CELLS_TYPE_AIG) {
				if (cells[tco][x_sel][y_sel][CELLS_SUBTYPE] == CELLS_SUBTYPE_AIG_CH
					|| cells[tco][x_sel][y_sel][CELLS_SUBTYPE] == CELLS_SUBTYPE_AIG_CB || cells[tco][x_sel][y_sel][CELLS_SUBTYPE] == CELLS_SUBTYPE_AIG_HC
					|| cells[tco][x_sel][y_sel][CELLS_SUBTYPE] == CELLS_SUBTYPE_AIG_BC || cells[tco][x_sel][y_sel][CELLS_SUBTYPE] == CELLS_SUBTYPE_AIG_CHV
					|| cells[tco][x_sel][y_sel][CELLS_SUBTYPE] == CELLS_SUBTYPE_AIG_CBV || cells[tco][x_sel][y_sel][CELLS_SUBTYPE] == CELLS_SUBTYPE_AIG_HCV
					|| cells[tco][x_sel][y_sel][CELLS_SUBTYPE] == CELLS_SUBTYPE_AIG_BCV) {
					if (n1 >= 0 && n1 < NB_AIG) {
						if (vio_aig_res[n1] == 0) vio_aig_cmd[n1] ^= 1;
					}
				}
			}
			n1 = cells[tco][x_sel][y_sel][CELLS_N1];
			n2 = cells[tco][x_sel][y_sel][CELLS_N2];
			if (cells[tco][x_sel][y_sel][CELLS_TYPE] == CELLS_TYPE_AIG) {
				if (cells[tco][x_sel][y_sel][CELLS_SUBTYPE] == CELLS_SUBTYPE_AIG_CHB || cells[tco][x_sel][y_sel][CELLS_SUBTYPE] == CELLS_SUBTYPE_AIG_HBC) {
					if (n1 >= 0 && n1 < NB_AIG && n2 >= 0 && n2 < NB_AIG) {
						if (vio_aig_res[n1] == 0 && vio_aig_res[n2] == 0) {
							if (vio_aig_cmd[n1] == 0 && vio_aig_cmd[n2] == 0) { vio_aig_cmd[n1] = 1; vio_aig_cmd[n2] = 0; }
							else if (vio_aig_cmd[n1] == 1 && vio_aig_cmd[n2] == 0) { vio_aig_cmd[n1] = 0; vio_aig_cmd[n2] = 1; }
							else                                              { vio_aig_cmd[n1] = 0; vio_aig_cmd[n2] = 0; }
						}
					}
				}
			}

			if (cells[tco][x_sel][y_sel][CELLS_TYPE] == CELLS_TYPE_CMDVOY && cells[tco][x_sel][y_sel][CELLS_SUBTYPE] == CELLS_SUBTYPE_CMDVOY_GO) {
				// Clic sur le bloc d'accès direct au TCO.
				// Si on appel un autre écran à partir d'un bloc de TCO, on efface tout, si cet écran n'est pas un TCO.
				if (cells[tco][x_sel][y_sel][CELLS_OPT] >= MD_ECRAN_TCO0 && cells[tco][x_sel][y_sel][CELLS_OPT] < MD_ECRAN_END) bmp_fond_default();
				screen_mode_retour = screen_mode; // Pour revenir à l'écran précédant avec la touche 'Esc'.
				switch (cells[tco][x_sel][y_sel][CELLS_OPT]) {
				case  0: screen_mode = MD_ECRAN_TCO0;      screen_mode_retour = screen_mode; break;
				case  1: screen_mode = MD_ECRAN_TCO1;      screen_mode_retour = screen_mode; break;
				case  2: screen_mode = MD_ECRAN_TCO2;      screen_mode_retour = screen_mode; break;
				case  3: screen_mode = MD_ECRAN_TCO3;      screen_mode_retour = screen_mode; break;
				case  4: screen_mode = MD_ECRAN_TCO4;      screen_mode_retour = screen_mode; break;
				case  5: screen_mode = MD_ECRAN_TCO5;      screen_mode_retour = screen_mode; break;
				case  6: screen_mode = MD_ECRAN_TCO6;      screen_mode_retour = screen_mode; break;
				case  7: screen_mode = MD_ECRAN_TCO7;      screen_mode_retour = screen_mode; break;
				case  8: screen_mode = MD_ECRAN_TRAIN1;    break;
				case  9: screen_mode = MD_ECRAN_POSLOC1;   break;
				case 10: screen_mode = MD_ECRAN_DEPL1;     break;
				case 11: screen_mode = MD_ECRAN_DEPL2;     break;
				case 12: screen_mode = MD_ECRAN_DEPL3;     break;
				case 13: screen_mode = MD_ECRAN_DEPL4;     break;
				case 14: screen_mode = MD_ECRAN_DEPL5;     break;
				case 15: screen_mode = MD_ECRAN_DEPL6;     break;
				case 16: screen_mode = MD_ECRAN_DEPL7;     break;
				case 17: screen_mode = MD_ECRAN_HORO_R;    break;
				case 18: screen_mode = MD_ECRAN_VIB;       break;
				case 19: screen_mode = MD_ECRAN_ITI1;      break;
				case 20: screen_mode = MD_ECRAN_ITI2;      break;
				case 21: screen_mode = MD_ECRAN_GARAGE;    break;
				case 22: screen_mode = MD_ECRAN_AIG1;      break;
				case 23: screen_mode = MD_ECRAN_AIG2;      break;
				case 24: screen_mode = MD_ECRAN_SERIAL;    break;
				case 25: screen_mode = MD_ECRAN_VAR1;      break;
				case 26: screen_mode = MD_ECRAN_VAR2;      break;
				case 27: screen_mode = MD_ECRAN_VAR3;      break;
				case 28: screen_mode = MD_ECRAN_CANTON1;   break;
				case 29: screen_mode = MD_ECRAN_CANTON2;   break;
				case 30: screen_mode = MD_ECRAN_SERVO;     break;
				case 31: screen_mode = MD_ECRAN_TDV1;      break;
				case 32: screen_mode = MD_ECRAN_SELECT1;   break;
				case 33: screen_mode = MD_ECRAN_SELECT2;   break;
				case 34: screen_mode = MD_ECRAN_SELECT3;   break;
				case 35: screen_mode = MD_ECRAN_AIGAUTO1;  break;
				case 36: screen_mode = MD_ECRAN_AIGAUTO2;  break;
				case 37: screen_mode = MD_ECRAN_AIGAUTO3;  break;
				case 38: screen_mode = MD_ECRAN_VITMAX1;   break;
				case 39: screen_mode = MD_ECRAN_VITMAX2;   break;
				case 40: screen_mode = MD_ECRAN_HALTE1;    break;
				case 41: screen_mode = MD_ECRAN_HALTE2;    break;
				case 42: screen_mode = MD_ECRAN_BALAUTO1;  break;
				case 43: screen_mode = MD_ECRAN_BALAUTO2;  break;
				case 44: screen_mode = MD_ECRAN_BALAUTO3;  break;
				case 45: screen_mode = MD_ECRAN_EXE1;      break;
				case 46: screen_mode = MD_ECRAN_EXE2;      break;
				case 47: screen_mode = MD_ECRAN_EXE3;      break;
				case 48: screen_mode = MD_ECRAN_TDV2;      break;
				case 49: screen_mode = MD_ECRAN_HORO_L1;   break;
				case 50: screen_mode = MD_ECRAN_HORO_L2;   break;
				case 51: screen_mode = MD_ECRAN_HORO_L3;   break;
				case 52: screen_mode = MD_ECRAN_HORO_L4;   break;
				case 53: screen_mode = MD_ECRAN_HORO_L5;   break;
				case 54: screen_mode = MD_ECRAN_HORO_L6;   break;
				case 55: screen_mode = MD_ECRAN_HORO_L7;   break;
				case 56: screen_mode = MD_ECRAN_TRAIN2;    break;
				}
				PostMessage(hwnd, WM_PAINT, 0, 0); // Pour provoquer un réaffichage de la fenêtre appelée (Impose "action" = DEBUG_TOTAL_PAINT).
			}

			cant = cells[tco][x_sel][y_sel][CELLS_CANT];
			sens = cells[tco][x_sel][y_sel][CELLS_SENS];
			if (cells[tco][x_sel][y_sel][CELLS_TYPE] == CELLS_TYPE_SPE) {
				if (cells[tco][x_sel][y_sel][CELLS_SUBTYPE] == CELLS_SUBTYPE_SPE_SENS) { // Pour changer le sens de parcours sur un rail horizontal.
					if (cant != -1) if (sens != -1) {
						if ((x_mouse % 40) >= 20) {
							if (sens == 0) copy_allowed_sens[cant / 100][cant % 100] ^= 1;
							if (sens == 1) copy_allowed_sens[cant / 100][cant % 100] ^= 2;
						}
						if ((x_mouse % 40) < 20) {
							if (sens == 0) copy_allowed_sens[cant / 100][cant % 100] ^= 2;
							if (sens == 1) copy_allowed_sens[cant / 100][cant % 100] ^= 1;
						}
					}
				}
				if (cells[tco][x_sel][y_sel][CELLS_SUBTYPE] == CELLS_SUBTYPE_SPE_SENSV)  {// Pour changer le sens de parcours sur un rail vertical .
					if (cant != -1) if (sens != -1) {
						if ((y_mouse % 40) < 20) {
							if (sens == 0) copy_allowed_sens[cant / 100][cant % 100] ^= 1;
							if (sens == 1) copy_allowed_sens[cant / 100][cant % 100] ^= 2;
						}
						if ((y_mouse % 40) >= 20) {
							if (sens == 0) copy_allowed_sens[cant / 100][cant % 100] ^= 2;
							if (sens == 1) copy_allowed_sens[cant / 100][cant % 100] ^= 1;
						}
					}
				}
			}

			if (cells[tco][x_sel][y_sel][CELLS_TYPE] == CELLS_TYPE_SPE) {
				if ((cells[tco][x_sel][y_sel][CELLS_SUBTYPE] == CELLS_SUBTYPE_SPE_CANT) || (cells[tco][x_sel][y_sel][CELLS_SUBTYPE] == CELLS_SUBTYPE_SPE_CANTV)) {
					if (cant >= 1000) {
						g = cant - 1000;
						if (g >= 0 && g < NB_GARAGE_REEL) vio_garage_lock_cmd[g] ^= 1; // 0 ou 1, 1 => Demande d'isolation du garage (Sera réalisée si il a un train sur le canton).
					}
				}
			}
		}
		cant = cells[tco][x_sel][y_sel][CELLS_CANT];
		// On teste si l'on n'a pas cliqué dans la fenêtre de configuration
		if ((c_conf_wnd == ' ' && cant != -1 && cells[tco][x_sel][y_sel][CELLS_TYPE] == CELLS_TYPE_SPE) && (cells[tco][x_sel][y_sel][CELLS_SUBTYPE] == CELLS_SUBTYPE_SPE_VOY || cells[tco][x_sel][y_sel][CELLS_SUBTYPE] == CELLS_SUBTYPE_SPE_VOYV)) {
			// Déplacements automatique commandés par un clic de souris sur le voyant d'occupation de canton de départ, puis sur celui d'arrivée.
			// Le déplacement est activé si un déplacement entre ces cantons est défini dans la section '#depl'!
			// Quand on clique sur le premier canton, les cantons potentiellement destinataires clignotent en jaune.
			cmd_divers[CMD_DIVERS_RELACHE] = 0; // 0 = > On enfonce le bouton de souris, donc il a déjà été relaché.
			if (cmd_divers[CMD_DIVERS_TEMPO] > 0) {
				// Tempo>0 => 2 éme clic de souris. On a déjà sélectionné le canton de départ.
				cant1 = cmd_divers[CMD_DIVERS_C_DEPART];
				cant2 = cant;
				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 && vio_garage_lock_status[cant1 - 1000] == 1)) {
					if ((cant2 >= 0 && cant2 < (300 + NB_CANTON) && (cant2 % 100) < NB_CANTON && vio_det[cant2 / 100][cant2 % 100] == 0) || (cant2 >= 1000 && (cant2 - 1000) < NB_GARAGE_REEL) && vio_garage_lock_status[cant2 - 1000] == 0) {
						cmd_divers[CMD_DIVERS_TEMPO] = 0; // Raz tempo pour arrêter la séquence de designation et les clignotements en jaune.
						cmd_divers[CMD_DIVERS_TEMPO_RESULT] = CMD_DIVERS_TEMPO_VAL_R;
						cmd_divers[CMD_DIVERS_RESULT] = 0;
						cmd_divers[CMD_DIVERS_C_ARRIVEE] = cant2;
						// On a le canton de départ et le canton d'arrivé en mémoire.
						// On cherche un déplacement ayant les conditions = canton_départ=ok et (canton_stop=ok ou condition_de_fin=ok).
						// Pour que cela marche, même si la condition de fin est une barrière infra-rouge, il faut alors une directive 'stop:cxx'.
						for (i = 0; i < DEPL_TAB_NB; i++) {
							if (depl_tab[i][DEPL_TAB_IND_CANT_START] == cant1 && (depl_tab[i][DEPL_TAB_IND_CANT_STOP] == cant2 || depl_tab[i][DEPL_TAB_IND_FIN_F_VAR] == cant2)) {
								// // Test avec le canton de 'stop:cxx' et test avec le canton de fin 'fin:det_xx'.
								depl_tab[i][DEPL_TAB_IND_START_RUN] = 1;
								cmd_divers[CMD_DIVERS_RESULT] = 1;
								break;
							}
						}
					}
					else {
						// 'cant2 en erreur' => Pour clignoter rouge si les blocs d'arrivée et de départ ne sont pas conformes.
						cmd_divers[CMD_DIVERS_TEMPO] = 0; // Raz tempo pour arrêter la séquence de designation et les clignotements en jaune.
						cmd_divers[CMD_DIVERS_TEMPO_RESULT] = CMD_DIVERS_TEMPO_VAL_R;
						cmd_divers[CMD_DIVERS_RESULT] = 0;        // Erreur, on va afficher un cadre rouge clignotant.
						cmd_divers[CMD_DIVERS_C_ARRIVEE] = cant2; // 'cant2' est connu.
					}
				}
				else {
					// 'cant1' en erreur => Pour clignoter rouge si les blocs d'arrivée et de départ ne sont pas conformes.
					cmd_divers[CMD_DIVERS_TEMPO] = 0; // Raz tempo pour arrêter la séquence de designation et les clignotements en jaune.
					cmd_divers[CMD_DIVERS_TEMPO_RESULT] = CMD_DIVERS_TEMPO_VAL_R;
					cmd_divers[CMD_DIVERS_RESULT] = 0;        // Erreur, on va afficher un cadre rouge clignotant.
					cmd_divers[CMD_DIVERS_C_ARRIVEE] = cant2; // 'cant2' est connu.
				}
			}
			else {
				// Tempo =0 = > On n'a pas encore sélectionné le canton de départ.
				// 1er clic de souris, le canton de départ doit être occupé ou le garage de départ isolé avec un train dessus.
				// Cela peut être aussi le premier clic de souris pour séparer ou associer une locomotive et ses wagons.
				if ((cant >= 0 && cant < (300 + NB_CANTON) && (cant % 100) < NB_CANTON && vio_det[cant / 100][cant % 100] == 1) || (cant >= 1000 && (cant - 1000) < NB_GARAGE_REEL)) {
					// Si c'est un garage, il peut être isolé quand on veut le grouper avec un canton, ou relié si l'on veut séparer des wagons dessus,
					// donc pas de test sur l'occupation du garage.
					if (cant < 1000 || (cant >= 1000 && garage.ass_canton[cant - 1000] != -1 &&
						(vio_garage_lock_status[cant - 1000] == 1 || vio_det[garage.ass_canton[cant - 1000] / 100][garage.ass_canton[cant - 1000] % 100] == 1))) {
						// Le garage doit être isolé ou relié au canton avec un train de présent sur ce canton.	
						cmd_divers[CMD_DIVERS_TEMPO] = CMD_DIVERS_TEMPO_VAL; // Tempo pour laisser quelques secondes le temps de désigner le canton d'arrivée.
						cmd_divers[CMD_DIVERS_TEMPO_RESULT] = 0; // Pas de tempo d'affichage de résultat.
						cmd_divers[CMD_DIVERS_C_DEPART] = cant;
						cmd_divers[CMD_DIVERS_C_ARRIVEE] = -1;
						cmd_divers[CMD_DIVERS_RELACHE] = 1; // On vient d'enfoncer le bouton de la souris sur une case avec un rectange rouge.
						// Indicateur pour savoir quand l'on va relacher ce bouton.
					}
					else {
						// Pour clignoter rouge si le bloc de départ n'est pas bien configuré = Le garage n'est pas occupé.
						cmd_divers[CMD_DIVERS_TEMPO] = 0; // Raz tempo pour arrêter la séquence de designation et les clignotements en jaune.
						cmd_divers[CMD_DIVERS_TEMPO_RESULT] = CMD_DIVERS_TEMPO_VAL_R; // Tempo d'affichage de résultat en erreur.
						cmd_divers[CMD_DIVERS_RESULT] = 0; // Erreur, on va afficher un cadre rouge clignotant.
						cmd_divers[CMD_DIVERS_C_DEPART] = cant;
						cmd_divers[CMD_DIVERS_C_ARRIVEE] = cant; // Pour ne faire clignoter que le bloc d'occupation du canton de départ.
					}
				}
				else {
					// Pour clignoter rouge si le bloc de départ n'est pas bien configuré = n° canton invalide.
					cmd_divers[CMD_DIVERS_TEMPO] = 0; // Raz tempo pour arrêter la séquence de designation et les clignotements en jaune.
					cmd_divers[CMD_DIVERS_TEMPO_RESULT] = CMD_DIVERS_TEMPO_VAL_R; // Tempo d'affichage de résultat en erreur.
					cmd_divers[CMD_DIVERS_RESULT] = 0; // Erreur, on va afficher un cadre rouge clignotant.
					cmd_divers[CMD_DIVERS_C_DEPART] = cant;
					cmd_divers[CMD_DIVERS_C_ARRIVEE] = cant; // Pour ne faire clignoter que le bloc d'occupation du canton de départ.
				}
			}
		}

			if (c_conf_wnd == 'R') { // La fenêtre de rendu des couleurs est ouverte
			x = 385; y = 0; if (y_mouse > y && y_mouse<(y + 15) && x_mouse>x && x_mouse < (x + 15)) c_conf_wnd = ' '; //[X] = Quitter la fenêtre de rendu.
			y = 100;
			if (mouse_in_rendu_rect(220, y)) rendu[RENDU_COLOR_RAIL_LIBRE] = (rendu[RENDU_COLOR_RAIL_LIBRE] + 1) % BMP_CST_COLOR_NB_AVEC_CT;
			if (mouse_in_rendu_rect(260, y)) rendu[RENDU_COLOR_FOND_LIBRE] = (rendu[RENDU_COLOR_FOND_LIBRE] + 1) % BMP_CST_COLOR_NB_AVEC_CT;
			if (mouse_in_rendu_rect(300, y)) rendu[RENDU_USE_GROS_LIBRE] = (rendu[RENDU_USE_GROS_LIBRE] + 1) % 2;
			if (mouse_in_rendu_rect(340, y)) rendu[RENDU_USE_FLECHE_LIBRE] = (rendu[RENDU_USE_FLECHE_LIBRE] + 1) % 2;
			y = 120;
			if (mouse_in_rendu_rect(220, y)) rendu[RENDU_COLOR_RAIL_OCC] = (rendu[RENDU_COLOR_RAIL_OCC] + 1) % BMP_CST_COLOR_NB_AVEC_CT;
			if (mouse_in_rendu_rect(260, y)) rendu[RENDU_COLOR_FOND_OCC] = (rendu[RENDU_COLOR_FOND_OCC] + 1) % BMP_CST_COLOR_NB_AVEC_CT;
			if (mouse_in_rendu_rect(300, y)) rendu[RENDU_USE_GROS_OCC] = (rendu[RENDU_USE_GROS_OCC] + 1) % 2;
			if (mouse_in_rendu_rect(340, y)) rendu[RENDU_USE_FLECHE_OCC] = (rendu[RENDU_USE_FLECHE_OCC] + 1) % 2;
			y = 140;
			if (mouse_in_rendu_rect(220, y)) rendu[RENDU_COLOR_RAIL_SELPREV] = (rendu[RENDU_COLOR_RAIL_SELPREV] + 1) % BMP_CST_COLOR_NB_AVEC_CT;
			if (mouse_in_rendu_rect(260, y)) rendu[RENDU_COLOR_FOND_SELPREV] = (rendu[RENDU_COLOR_FOND_SELPREV] + 1) % BMP_CST_COLOR_NB_AVEC_CT;
			if (mouse_in_rendu_rect(300, y)) rendu[RENDU_USE_GROS_SELPREV] = (rendu[RENDU_USE_GROS_SELPREV] + 1) % 2;
			if (mouse_in_rendu_rect(340, y)) rendu[RENDU_USE_FLECHE_SELPREV] = (rendu[RENDU_USE_FLECHE_SELPREV] + 1) % 2;
			y = 160;
			if (mouse_in_rendu_rect(220, y)) rendu[RENDU_COLOR_RAIL_SELOCC] = (rendu[RENDU_COLOR_RAIL_SELOCC] + 1) % BMP_CST_COLOR_NB_AVEC_CT;
			if (mouse_in_rendu_rect(260, y)) rendu[RENDU_COLOR_FOND_SELOCC] = (rendu[RENDU_COLOR_FOND_SELOCC] + 1) % BMP_CST_COLOR_NB_AVEC_CT;
			if (mouse_in_rendu_rect(300, y)) rendu[RENDU_USE_GROS_SELOCC] = (rendu[RENDU_USE_GROS_SELOCC] + 1) % 2;
			if (mouse_in_rendu_rect(340, y)) rendu[RENDU_USE_FLECHE_SELOCC] = (rendu[RENDU_USE_FLECHE_SELOCC] + 1) % 2;
			y = 180;
			if (mouse_in_rendu_rect(220, y)) rendu[RENDU_COLOR_RAIL_AUTOPREV] = (rendu[RENDU_COLOR_RAIL_AUTOPREV] + 1) % BMP_CST_COLOR_NB_AVEC_CT;
			if (mouse_in_rendu_rect(260, y)) rendu[RENDU_COLOR_FOND_AUTOPREV] = (rendu[RENDU_COLOR_FOND_AUTOPREV] + 1) % BMP_CST_COLOR_NB_AVEC_CT;
			if (mouse_in_rendu_rect(300, y)) rendu[RENDU_USE_GROS_AUTOPREV] = (rendu[RENDU_USE_GROS_AUTOPREV] + 1) % 2;
			if (mouse_in_rendu_rect(340, y)) rendu[RENDU_USE_FLECHE_AUTOPREV] = (rendu[RENDU_USE_FLECHE_AUTOPREV] + 1) % 2;
			y = 200;
			if (mouse_in_rendu_rect(220, y)) rendu[RENDU_COLOR_RAIL_AUTOOCC] = (rendu[RENDU_COLOR_RAIL_AUTOOCC] + 1) % BMP_CST_COLOR_NB_AVEC_CT;
			if (mouse_in_rendu_rect(260, y)) rendu[RENDU_COLOR_FOND_AUTOOCC] = (rendu[RENDU_COLOR_FOND_AUTOOCC] + 1) % BMP_CST_COLOR_NB_AVEC_CT;
			if (mouse_in_rendu_rect(300, y)) rendu[RENDU_USE_GROS_AUTOOCC] = (rendu[RENDU_USE_GROS_AUTOOCC] + 1) % 2;
			if (mouse_in_rendu_rect(340, y)) rendu[RENDU_USE_FLECHE_AUTOOCC] = (rendu[RENDU_USE_FLECHE_AUTOOCC] + 1) % 2;
			y = 220;
			if (mouse_in_rendu_rect(220, y)) rendu[RENDU_COLOR_RAIL_GARALOCK] = (rendu[RENDU_COLOR_RAIL_GARALOCK] + 1) % BMP_CST_COLOR_NB_AVEC_CT;
			if (mouse_in_rendu_rect(260, y)) rendu[RENDU_COLOR_FOND_GARALOCK] = (rendu[RENDU_COLOR_FOND_GARALOCK] + 1) % BMP_CST_COLOR_NB_AVEC_CT;
			if (mouse_in_rendu_rect(300, y)) rendu[RENDU_USE_GROS_GARALOCK] = (rendu[RENDU_USE_GROS_GARALOCK] + 1) % 2;
			y = 300;
			if (mouse_in_rendu_rect(220, y)) rendu[RENDU_COLOR_FOND] = (rendu[RENDU_COLOR_FOND] + 1) % BMP_CST_COLOR_NB;
			if (mouse_in_rendu_rect(260, y)) rendu[RENDU_COLOR_FOND_RAIL] = (rendu[RENDU_COLOR_FOND_RAIL] + 1) % BMP_CST_COLOR_NB;
			if (mouse_in_rendu_rect(300, y)) rendu[RENDU_COLOR_GRILLE] = (rendu[RENDU_COLOR_GRILLE] + 1) % BMP_CST_COLOR_NB;
			if (mouse_in_rendu_rect(340, y)) rendu[RENDU_COLOR_TEXT] = (rendu[RENDU_COLOR_TEXT] + 1) % BMP_CST_COLOR_NB;
			y = 380;
			if (mouse_in_rendu_rect(220, y)) rendu[RENDU_COLOR_DET_OFF] = (rendu[RENDU_COLOR_DET_OFF] + 1) % BMP_CST_COLOR_NB;
			if (mouse_in_rendu_rect(260, y)) rendu[RENDU_COLOR_DET_ON] = (rendu[RENDU_COLOR_DET_ON] + 1) % BMP_CST_COLOR_NB;
			y = 400;
			if (mouse_in_rendu_rect(220, y)) rendu[RENDU_COLOR_AIG_OFF] = (rendu[RENDU_COLOR_AIG_OFF] + 1) % BMP_CST_COLOR_NB;
			if (mouse_in_rendu_rect(260, y)) rendu[RENDU_COLOR_AIG_ON] = (rendu[RENDU_COLOR_AIG_ON] + 1) % BMP_CST_COLOR_NB;
			y = 420;
			if (mouse_in_rendu_rect(220, y)) rendu[RENDU_COLOR_VOY_OFF] = (rendu[RENDU_COLOR_VOY_OFF] + 1) % BMP_CST_COLOR_NB;
			if (mouse_in_rendu_rect(260, y)) rendu[RENDU_COLOR_VOY_ON] = (rendu[RENDU_COLOR_VOY_ON] + 1) % BMP_CST_COLOR_NB;
			y = 440;
			if (mouse_in_rendu_rect(220, y)) rendu[RENDU_COLOR_INT_OFF] = (rendu[RENDU_COLOR_INT_OFF] + 1) % BMP_CST_COLOR_NB;
			if (mouse_in_rendu_rect(260, y)) rendu[RENDU_COLOR_INT_ON] = (rendu[RENDU_COLOR_INT_ON] + 1) % BMP_CST_COLOR_NB;
			y = 460;
			if (mouse_in_rendu_rect(220, y)) rendu[RENDU_COLOR_IPP_OFF] = (rendu[RENDU_COLOR_IPP_OFF] + 1) % BMP_CST_COLOR_NB;
			if (mouse_in_rendu_rect(260, y)) rendu[RENDU_COLOR_IPP_ON] = (rendu[RENDU_COLOR_IPP_ON] + 1) % BMP_CST_COLOR_NB;
			if (mouse_in_rendu_rect(300, y)) rendu[RENDU_COLOR_IPP_LOCKOFF] = (rendu[RENDU_COLOR_IPP_LOCKOFF] + 1) % BMP_CST_COLOR_NB;
			if (mouse_in_rendu_rect(340, y)) rendu[RENDU_COLOR_IPP_LOCKON] = (rendu[RENDU_COLOR_IPP_LOCKON] + 1) % BMP_CST_COLOR_NB;
			j = (y_mouse - 520 - 1) / 10; i = (x_mouse - 60 - 1) / 20;
			if (j >= 0 && j <= 3 && i >= 0 && i < NB_CANTON) {
				color_canton[j][i] = (color_canton[j][i] + 1) % BMP_CST_COLOR_NB;
			}
			if (j == 6 && i >= 0 && i < NB_TRAIN_COULEUR) {
				color_train[i] = (color_train[i] + 1) % BMP_CST_COLOR_NB;
			}
			//sprintf_s(gszErr,"i=%d j=%d x=%d y=%d ",i,j,x_mouse,y_mouse); MessageBox(NULL,gszErr,"debug",MB_OK);
		}

		else if (c_conf_wnd == 'A' || c_conf_wnd == 'B' || c_conf_wnd == 'C' || c_conf_wnd == 'D') { // La fenêtre d'édition est ouverte
			if ((c_conf_wnd == 'A' && x_mouse < 400 && y_mouse<680) || (c_conf_wnd == 'B' && x_mouse>200 && x_mouse < 600 && y_mouse<680)
				|| (c_conf_wnd == 'C' && x_mouse>400 && x_mouse < 800 && y_mouse<680) || (c_conf_wnd == 'D' && x_mouse>760 && x_mouse < 1160 && y_mouse<680)) { // La fenêtre fait 400 de large.
				xdep = 0; // 'A' => La fenêtre est déjà affiché à gauche de l'écran, xdep = 0.
				if (c_conf_wnd == 'B') xdep = 200; // 'B' => xdep = 200. La fenêtre est décalée sur la droite.
				if (c_conf_wnd == 'C') xdep = 400; // 'C' => xdep = 480.
				if (c_conf_wnd == 'D') xdep = 760; // 'D' => xdep = 760.
				x_sel = (x_mouse - xdep) / 40;
				y_sel = (y_mouse) / 40;

				if (y_mouse>0 && y_mouse<15)	{ // Le clic de la souris est dans le bandeau du haut.
					if ((x_mouse - xdep)>352 && (x_mouse - xdep)<367) { // Clic sur la case '<'.
						if (c_conf_wnd == 'B') c_conf_wnd = 'A';      // Décalage de la fenêtre plus à droite.
						else if (c_conf_wnd == 'C') c_conf_wnd = 'B';
						else if (c_conf_wnd == 'D') c_conf_wnd = 'C';
						cells_redraw = 1;
					}
					if ((x_mouse - xdep)>368 && (x_mouse - xdep)<383) { // Clic sur la case '>'.
						if (c_conf_wnd == 'A') c_conf_wnd = 'B';      // Décalage de la fenêtre plus à gauche.
						else if (c_conf_wnd == 'B') c_conf_wnd = 'C';
						else if (c_conf_wnd == 'C') c_conf_wnd = 'D';
						cells_redraw = 1;
					}
					if ((x_mouse - xdep)>384 && (x_mouse - xdep) < 399) c_conf_wnd = ' '; // Clic sur la case 'X'. On ferme la fenêtre.
				}

				// Si on a cliqué sur un des bloc dans la fenêtre d'édition, on récupére ses caractéristiques dans 
				// 'cells_type_sel' et 'cells_subtype_sel' pour l'afficher en haut à droite de cette fenêtre.
				i = 0;
				while (conf_symb[i]) {
					if (x_sel == conf_symb[i + 0] && y_sel == conf_symb[i + 1]) {
						cells_type_sel = conf_symb[i + 2];
						cells_subtype_sel = conf_symb[i + 3];
					}
					i = i + 4;
				}
				// yopt = Décalage pour afficher les paramètres = 400.
				// Clic dans la case 'S+' pour définir le sens des flèche affiché dans le bloc.
				if ((x_mouse - xdep) > 340 && (x_mouse - xdep)<360 && (y_mouse - yopt)> 0 && (y_mouse - yopt)<(0 + 15)) temp_conf_sens = (temp_conf_sens ^ 1) & 1;
				// Clic dans la case 'C1,C2,C3 ou C4' pour incrémenter ces variables.
				if ((x_mouse - xdep)>340 && (x_mouse - xdep)<360 && (y_mouse - yopt)>19 && (y_mouse - yopt)<(19 + 10)) temp_conf_c1++;
				if ((x_mouse - xdep)>340 && (x_mouse - xdep)<360 && (y_mouse - yopt)>39 && (y_mouse - yopt)<(39 + 10)) temp_conf_c2++;
				if ((x_mouse - xdep)>340 && (x_mouse - xdep)<360 && (y_mouse - yopt)>59 && (y_mouse - yopt)<(59 + 10)) temp_conf_c3++;
				if ((x_mouse - xdep)>340 && (x_mouse - xdep)<360 && (y_mouse - yopt)>79 && (y_mouse - yopt)<(79 + 10)) temp_conf_c4++;
				if (temp_conf_c1 == BMP_CST_COLOR_NB) temp_conf_c1 = -1;
				if (temp_conf_c2 == BMP_CST_COLOR_NB) temp_conf_c2 = -1;
				if (temp_conf_c3 == BMP_CST_COLOR_NB) temp_conf_c3 = -1;
				if (temp_conf_c4 == BMP_CST_COLOR_NB) temp_conf_c4 = -1;  // 14/12/2009
				// Clic dans la case 'RAZ' pour remettre C1,C2,C3 ou C4' à -1.
				if ((x_mouse - xdep)>340 && (x_mouse - xdep)<360 && (y_mouse - yopt)>120 && (y_mouse - yopt)<130) {
					temp_conf_c1 = -1; temp_conf_c2 = -1; temp_conf_c3 = -1; temp_conf_c4 = -1;
				}
				// Clic dans la case 'RAZ' pour vider la ligne de texte 
				if ((x_mouse - xdep)>236 && (x_mouse - xdep)<256 && (y_mouse - yopt)>118 && (y_mouse - yopt)<130) {
					for (i = 0; i <= 19; i++) sz_temp_conf_txt[i] = ' ';
					sz_temp_conf_txt[20] = '\0';
					cells_entry_sel = 9; // Si l'on clic sur "RAZ TEXTE", on sélectionne le bloc de texte en saisie.
				}
				else {
					cells_entry_sel = -1;
				}
				// Clic dans la case 'CANT' pour définir le numéro de canton du bloc.
				if ((x_mouse - xdep)> 40 && (x_mouse - xdep)< 90 && (y_mouse - yopt)>  0 && (y_mouse - yopt)< 10) cells_entry_sel = 1;

				// Clic dans les cases '#1, #2'.
				if ((x_mouse - xdep)>140 && (x_mouse - xdep)<190 && (y_mouse - yopt)>  0 && (y_mouse - yopt)< 10) cells_entry_sel = 2;
				if ((x_mouse - xdep)>240 && (x_mouse - xdep)<290 && (y_mouse - yopt)>  0 && (y_mouse - yopt)< 10) cells_entry_sel = 3;

				// Clic dans les cases 'V1, V2, V3 V4'.
				if ((x_mouse - xdep)> 40 && (x_mouse - xdep)<290 && (y_mouse - yopt)> 20 && (y_mouse - yopt)< 30) cells_entry_sel = 4;
				if ((x_mouse - xdep)> 40 && (x_mouse - xdep)<290 && (y_mouse - yopt)> 40 && (y_mouse - yopt)< 50) cells_entry_sel = 5;
				if ((x_mouse - xdep)> 40 && (x_mouse - xdep)<290 && (y_mouse - yopt)> 60 && (y_mouse - yopt)< 70) cells_entry_sel = 6;
				if ((x_mouse - xdep)> 40 && (x_mouse - xdep)<290 && (y_mouse - yopt)> 80 && (y_mouse - yopt)< 90) cells_entry_sel = 7;

				// Clic dans les cases 'OPT, TXT'.
				if ((x_mouse - xdep)> 40 && (x_mouse - xdep)<140 && (y_mouse - yopt)>100 && (y_mouse - yopt)<110) cells_entry_sel = 8;
				if ((x_mouse - xdep)> 40 && (x_mouse - xdep)<240 && (y_mouse - yopt)>120 && (y_mouse - yopt)<130) cells_entry_sel = 9;
			}
			else { // Clic sur un des bloc disponible dans la fenêtre d'édition.
				x_sel = (x_mouse) / 40; y_sel = (y_mouse) / 40; // Coordonné du bloc sélectionné.

				cells[tco][x_sel][y_sel][CELLS_TYPE] = cells_type_sel;
				cells[tco][x_sel][y_sel][CELLS_SUBTYPE] = cells_subtype_sel;
				cells[tco][x_sel][y_sel][CELLS_CANT] = temp_conf_canton;
				cells[tco][x_sel][y_sel][CELLS_N1] = temp_conf_n1;
				cells[tco][x_sel][y_sel][CELLS_N2] = temp_conf_n2;
				cells[tco][x_sel][y_sel][CELLS_V1] = temp_conf_v1;
				cells[tco][x_sel][y_sel][CELLS_V2] = temp_conf_v2;
				cells[tco][x_sel][y_sel][CELLS_V3] = temp_conf_v3;
				cells[tco][x_sel][y_sel][CELLS_V4] = temp_conf_v4;
				cells[tco][x_sel][y_sel][CELLS_C1] = temp_conf_c1;
				cells[tco][x_sel][y_sel][CELLS_C2] = temp_conf_c2;
				cells[tco][x_sel][y_sel][CELLS_C3] = temp_conf_c3;
				cells[tco][x_sel][y_sel][CELLS_C4] = temp_conf_c4;
				cells[tco][x_sel][y_sel][CELLS_OPT] = temp_conf_opt;
				cells[tco][x_sel][y_sel][CELLS_SENS] = temp_conf_sens;
				strcpy(sz_cells[tco][x_sel][y_sel], sz_temp_conf_txt);
			}
		}

		else if (c_conf_wnd == 'H') {
			// La fenêtre de d'aide sur les variables est ouverte, on a cliqué sur [X], on éfface cette fenêtre.
			x = 800;
			y = 0;
			if (y_mouse > y && y_mouse<(y + 15) && x_mouse>(x - 15) && x_mouse < x) c_conf_wnd = ' ';
		}
	} // FIN ACTION = CLIC (gauche) DE LA SOURIS

	if (action == DEBUG_MOUSE_UP) { // ACTION = RELACHEMENT DU BOUTON GAUCHE DE LA SOURIS.
		x_sel = (x_mouse) / 40;
		y_sel = (y_mouse) / 40;
		cant = cells[tco][x_sel][y_sel][CELLS_CANT];
		cant2 = cant;
		cmd_divers[CMD_DIVERS_VAR_BOUTON1] = 0;  cmd_divers[CMD_DIVERS_VAR_BOUTON2] = 0; cmd_divers[CMD_DIVERS_VAR_BOUTON3] = 0;
		cmd_divers[CMD_DIVERS_VAR_BOUTON4] = 0;  cmd_divers[CMD_DIVERS_VAR_BOUTON5] = 0; cmd_divers[CMD_DIVERS_VAR_BOUTON6] = 0;
		cmd_divers[CMD_DIVERS_VAR_BOUTON56] = 0; cmd_divers[CMD_DIVERS_VAR_BOUTON7] = 0; cmd_divers[CMD_DIVERS_VAR_BOUTON8] = 0;
		if (cells_pouss_en_cours != -1 && cells_pouss_en_cours_srv == 0) { // Dans le cas ou la variable est du type : 0 / 1.
			pio_set_val(cells_pouss_en_cours, 0);
			cells_pouss_en_cours = -1;
		}
		else if (cells_pouss_en_cours != -1 && cells_pouss_en_cours_srv == 1) { // Pour les servo moteur.
			pio_set_val(cells_pouss_en_cours, pio_get_val(cells_pouss_en_cours + 2800 - 8000)); // V1 = variable de consigne, V1+2800-8000 = valeur actuelle.
			cells_pouss_en_cours = -1; // Le reste se passe dans maj_srv().
		}
		else if ((cant2 != -1 && cells[tco][x_sel][y_sel][CELLS_TYPE] == CELLS_TYPE_SPE) && (cells[tco][x_sel][y_sel][CELLS_SUBTYPE] == CELLS_SUBTYPE_SPE_VOY || cells[tco][x_sel][y_sel][CELLS_SUBTYPE] == CELLS_SUBTYPE_SPE_VOYV)) {
			// La case avec le numéro du canton est != -1.
			// Pour séparer ou regrouper une locomotive et ses wagons.
			// On apppuye sur le bouton de la souris sur la case d'une locomotive et l'on relache le bouton sur la case d'un wagons (ou l'inverse).
			// On regroupe sous un seul numéro de train, la locomotive et les wagons.
			//  cmd_divers[CMD_DIVERS_RELACHE]=1 => Au relachement du clic de souris, le canton d'arrivée doit être occupé ou le garage isolé avec un train stocké dessus.
			cant1 = cmd_divers[CMD_DIVERS_C_DEPART];
			if (cmd_divers[CMD_DIVERS_RELACHE] == 1 && cmd_divers[CMD_DIVERS_TEMPO] > 0 && cant1 != cant2 && (cant1 < 1000 || cant2 < 1000)) {
				// Il ne faut pas désigner deux garages.
				cmd_divers[CMD_DIVERS_RESULT] = 0; // Indicateur pour ne pas repasser dans tous les tests. ; // Jonction pas encore faite, on va afficher un cadre rouge clignotant.
				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).
								cmd_divers[CMD_DIVERS_TEMPO] = 0; // Raz tempo pour arrêter la séquence de désignation et les clignotements.
								cmd_divers[CMD_DIVERS_TEMPO_RESULT] = CMD_DIVERS_TEMPO_VAL_R;
								cmd_divers[CMD_DIVERS_RESULT] = 0; // Jonction pas encore faite, on va afficher un cadre rouge clignotant.
								cmd_divers[CMD_DIVERS_C_ARRIVEE] = cant2;
								// 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.
											cmd_divers[CMD_DIVERS_RESULT] = 2; // Jonction faite, on va afficher un cadre magenta fixe.
											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.
												cmd_divers[CMD_DIVERS_RESULT] = 2;      // Jonction faite, on va afficher un cadre magenta fixe.
												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.
												cmd_divers[CMD_DIVERS_RESULT] = 2;      // Jonction faite, on va afficher un cadre magenta fixe.
												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'.
								else if (train1 == train2 && train1 >= 0 && train1 < NB_TRAIN_COULEUR) {
									// SEPARATION LOCOMOTIVE DE SES WAGONS.
									// Les trains ont le même numéro => Séparation.
									// On a le même train sur deux cantons ou sur un canton et un garage relié à ce canton.
									if (STR_SAME stricmp(train.mode[train1], "SEL")) {
										train2 = -1;
										for (i = NB_TRAIN - 1; i >= NB_TRAIN_COULEUR && train2 == -1; i--) { // Recheche d'un Wagon[xx] libre.
											if (train.enable[i] == 0) train2 = i;
										}
										if (train2 != -1) {
											// On a trouvé un numéro de Wagon[xx] libre.
											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.
												cmd_divers[CMD_DIVERS_RESULT] = 2; // Séparation faite, on va afficher un cadre magenta fixe.
												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.
											}
										}
									}
								}
							}
						} // Fin cas ou les garages sont obligatoirement reliés aux cantons.
						// POUR SEPARER LA LOCOMOTIVE DE SES WAGONS dans le cas (Remarque : Le cas ou l'on est sur deux cantons est déjà traité au-dessus).
						if (cmd_divers[CMD_DIVERS_RESULT] == 0) {
							// Si l'on déjà réalisé une opération au dessus, on ne passe pas ici.
							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é.
								cmd_divers[CMD_DIVERS_TEMPO] = 0; // Raz tempo pour arrêter la séquence de désignation et les clignotements.
								cmd_divers[CMD_DIVERS_TEMPO_RESULT] = CMD_DIVERS_TEMPO_VAL_R;
								cmd_divers[CMD_DIVERS_RESULT] = 0; // Séparation pas encore faite, on va afficher un cadre rouge clignotant.
								cmd_divers[CMD_DIVERS_C_ARRIVEE] = cant2;
								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) {
											// '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.
											cmd_divers[CMD_DIVERS_RESULT] = 2; // Séparation faite, on va afficher un cadre magenta fixe.
											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.
											cmd_divers[CMD_DIVERS_RESULT] = 2; // Séparation faite, on va afficher un cadre magenta fixe.
											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.
					else {
						// 'cant2' en erreur => Pour clignoter rouge si les blocs d'arrivée et de départ ne sont pas conformes.
						cmd_divers[CMD_DIVERS_TEMPO] = 0; // Raz tempo pour arrêter la séquence de designation et les clignotements en jaune.
						cmd_divers[CMD_DIVERS_TEMPO_RESULT] = CMD_DIVERS_TEMPO_VAL_R;
						cmd_divers[CMD_DIVERS_RESULT] = 0;        // Erreur, on va afficher un cadre rouge clignotant.
						cmd_divers[CMD_DIVERS_C_ARRIVEE] = cant1; // 'cant2' est inconnu.
					}
				}
				else {
					// 'cant1' en erreur => Pour clignoter rouge si le bloc de départ n'est pas conforme.
					// Normalement on de doit jamais passer ici, car on à déjà testé 'cant1' lors du premier clic.
					cmd_divers[CMD_DIVERS_TEMPO] = 0; // Raz tempo pour arrêter la séquence de designation et les clignotements en jaune.
					cmd_divers[CMD_DIVERS_TEMPO_RESULT] = CMD_DIVERS_TEMPO_VAL_R;
					cmd_divers[CMD_DIVERS_RESULT] = 0;        // Erreur, on va afficher un cadre rouge clignotant.
					cmd_divers[CMD_DIVERS_C_ARRIVEE] = cant1; // 'cant2' est inconnu.
				}
			}
			// cmd_divers[CMD_DIVERS_TEMPO]==0 ou cmd_divers[CMD_DIVERS_RELACHE]==0 ou cant1==cant2=> il n'y a rien à faire, sauf....
			else if (cant1 == cant2 && cant1 >= 1000 && (cant1 - 1000)<NB_GARAGE_REEL && vio_garage_lock_status[cant1 - 1000] == 0) {
				// On a cliqué sur un garage relié au canton, mais l'on vient de relacher la souris, alors que la seule possibilité est de relacher la souris
				// sur un canton.
				cmd_divers[CMD_DIVERS_TEMPO] = 0; // Raz tempo pour arrêter la séquence de designation et les clignotements en jaune.
				cmd_divers[CMD_DIVERS_TEMPO_RESULT] = CMD_DIVERS_TEMPO_VAL_R;
				cmd_divers[CMD_DIVERS_RESULT] = 0; // Erreur, on va afficher un cadre rouge clignotant.
				cmd_divers[CMD_DIVERS_C_DEPART] = cant1;
				cmd_divers[CMD_DIVERS_C_ARRIVEE] = cant1; // Pour ne faire clignoter que le canton de départ.
			}
		} // Fin Nouveau V3.5
		else if (cmd_divers[CMD_DIVERS_TEMPO]>0 && cmd_divers[CMD_DIVERS_RELACHE] == 1) {
			// On vient de relacher le bouton de la souris sur une case autre qu'un rectangle rouge d'occupation.
			cant1 = cmd_divers[CMD_DIVERS_C_DEPART];
			if (cant1 >= 1000 && (cant1 - 1000) < NB_GARAGE_REEL && vio_garage_lock_status[cant1 - 1000] == 0) { // Pour un déplacement le garage ne peut être qu'isolé du canton.
				// Le premier clic était sur un garage relié au canton, et l'on vient de relacher la souris => Erreur.
				// On fait une raz de la tempo si le garage est relié au canton.
				cmd_divers[CMD_DIVERS_TEMPO] = 0; // Raz tempo pour arrêter la séquence de designation et les clignotements en jaune.
				cmd_divers[CMD_DIVERS_TEMPO_RESULT] = CMD_DIVERS_TEMPO_VAL_R;
				cmd_divers[CMD_DIVERS_RESULT] = 0;        // Erreur, on va afficher un cadre rouge clignotant.
				cmd_divers[CMD_DIVERS_C_ARRIVEE] = cant1; // 'cant2' est inconnu.
			}
		}
		cmd_divers[CMD_DIVERS_RELACHE] = 0; // Dans tous les cas, on vient de relacher le bouton de la souris.
	} // FIN ACTION = RELACHEMENT DU BOUTON (gauche) DE LA SOURIS


	if (action == DEBUG_MOUSE_RIGHT) { // ACTION = CLIC DROIT DE LA SOURIS
		if (c_conf_wnd == 'R') { // La fenêtre de rendu des couleurs est ouverte
			x = 385; y = 0; if (y_mouse > y && y_mouse<(y + 15) && x_mouse>x && x_mouse < (x + 15)) c_conf_wnd = ' '; //[X] = Quitter la fenêtre de rendu.
			y = 100;
			if (mouse_in_rendu_rect(220, y)) rendu[RENDU_COLOR_RAIL_LIBRE] = (rendu[RENDU_COLOR_RAIL_LIBRE] + BMP_CST_COLOR_NB_AVEC_CT - 1 ) % BMP_CST_COLOR_NB_AVEC_CT;
			if (mouse_in_rendu_rect(260, y)) rendu[RENDU_COLOR_FOND_LIBRE] = (rendu[RENDU_COLOR_FOND_LIBRE] + BMP_CST_COLOR_NB_AVEC_CT - 1 ) % BMP_CST_COLOR_NB_AVEC_CT;
			if (mouse_in_rendu_rect(300, y)) rendu[RENDU_USE_GROS_LIBRE] = (rendu[RENDU_USE_GROS_LIBRE] + 1) % 2;
			if (mouse_in_rendu_rect(340, y)) rendu[RENDU_USE_FLECHE_LIBRE] = (rendu[RENDU_USE_FLECHE_LIBRE] + 1) % 2;
			y = 120;
			if (mouse_in_rendu_rect(220, y)) rendu[RENDU_COLOR_RAIL_OCC] = (rendu[RENDU_COLOR_RAIL_OCC] + BMP_CST_COLOR_NB_AVEC_CT - 1 ) % BMP_CST_COLOR_NB_AVEC_CT;
			if (mouse_in_rendu_rect(260, y)) rendu[RENDU_COLOR_FOND_OCC] = (rendu[RENDU_COLOR_FOND_OCC] + BMP_CST_COLOR_NB_AVEC_CT - 1 ) % BMP_CST_COLOR_NB_AVEC_CT;
			if (mouse_in_rendu_rect(300, y)) rendu[RENDU_USE_GROS_OCC] = (rendu[RENDU_USE_GROS_OCC] + 1) % 2;
			if (mouse_in_rendu_rect(340, y)) rendu[RENDU_USE_FLECHE_OCC] = (rendu[RENDU_USE_FLECHE_OCC] + 1) % 2;
			y = 140;
			if (mouse_in_rendu_rect(220, y)) rendu[RENDU_COLOR_RAIL_SELPREV] = (rendu[RENDU_COLOR_RAIL_SELPREV] + BMP_CST_COLOR_NB_AVEC_CT - 1 ) % BMP_CST_COLOR_NB_AVEC_CT;
			if (mouse_in_rendu_rect(260, y)) rendu[RENDU_COLOR_FOND_SELPREV] = (rendu[RENDU_COLOR_FOND_SELPREV] + BMP_CST_COLOR_NB_AVEC_CT - 1 ) % BMP_CST_COLOR_NB_AVEC_CT;
			if (mouse_in_rendu_rect(300, y)) rendu[RENDU_USE_GROS_SELPREV] = (rendu[RENDU_USE_GROS_SELPREV] + 1) % 2;
			if (mouse_in_rendu_rect(340, y)) rendu[RENDU_USE_FLECHE_SELPREV] = (rendu[RENDU_USE_FLECHE_SELPREV] + 1) % 2;
			y = 160;
			if (mouse_in_rendu_rect(220, y)) rendu[RENDU_COLOR_RAIL_SELOCC] = (rendu[RENDU_COLOR_RAIL_SELOCC] + BMP_CST_COLOR_NB_AVEC_CT - 1 ) % BMP_CST_COLOR_NB_AVEC_CT;
			if (mouse_in_rendu_rect(260, y)) rendu[RENDU_COLOR_FOND_SELOCC] = (rendu[RENDU_COLOR_FOND_SELOCC] + BMP_CST_COLOR_NB_AVEC_CT - 1 ) % BMP_CST_COLOR_NB_AVEC_CT;
			if (mouse_in_rendu_rect(300, y)) rendu[RENDU_USE_GROS_SELOCC] = (rendu[RENDU_USE_GROS_SELOCC] + 1) % 2;
			if (mouse_in_rendu_rect(340, y)) rendu[RENDU_USE_FLECHE_SELOCC] = (rendu[RENDU_USE_FLECHE_SELOCC] + 1) % 2;
			y = 180;
			if (mouse_in_rendu_rect(220, y)) rendu[RENDU_COLOR_RAIL_AUTOPREV] = (rendu[RENDU_COLOR_RAIL_AUTOPREV] + BMP_CST_COLOR_NB_AVEC_CT - 1 ) % BMP_CST_COLOR_NB_AVEC_CT;
			if (mouse_in_rendu_rect(260, y)) rendu[RENDU_COLOR_FOND_AUTOPREV] = (rendu[RENDU_COLOR_FOND_AUTOPREV] + BMP_CST_COLOR_NB_AVEC_CT - 1 ) % BMP_CST_COLOR_NB_AVEC_CT;
			if (mouse_in_rendu_rect(300, y)) rendu[RENDU_USE_GROS_AUTOPREV] = (rendu[RENDU_USE_GROS_AUTOPREV] + 1) % 2;
			if (mouse_in_rendu_rect(340, y)) rendu[RENDU_USE_FLECHE_AUTOPREV] = (rendu[RENDU_USE_FLECHE_AUTOPREV] + 1) % 2;
			y = 200;
			if (mouse_in_rendu_rect(220, y)) rendu[RENDU_COLOR_RAIL_AUTOOCC] = (rendu[RENDU_COLOR_RAIL_AUTOOCC] + BMP_CST_COLOR_NB_AVEC_CT - 1 ) % BMP_CST_COLOR_NB_AVEC_CT;
			if (mouse_in_rendu_rect(260, y)) rendu[RENDU_COLOR_FOND_AUTOOCC] = (rendu[RENDU_COLOR_FOND_AUTOOCC] + BMP_CST_COLOR_NB_AVEC_CT - 1 ) % BMP_CST_COLOR_NB_AVEC_CT;
			if (mouse_in_rendu_rect(300, y)) rendu[RENDU_USE_GROS_AUTOOCC] = (rendu[RENDU_USE_GROS_AUTOOCC] + 1) % 2;
			if (mouse_in_rendu_rect(340, y)) rendu[RENDU_USE_FLECHE_AUTOOCC] = (rendu[RENDU_USE_FLECHE_AUTOOCC] + 1) % 2;
			y = 220;
			if (mouse_in_rendu_rect(220, y)) rendu[RENDU_COLOR_RAIL_GARALOCK] = (rendu[RENDU_COLOR_RAIL_GARALOCK] + BMP_CST_COLOR_NB_AVEC_CT - 1 ) % BMP_CST_COLOR_NB_AVEC_CT;
			if (mouse_in_rendu_rect(260, y)) rendu[RENDU_COLOR_FOND_GARALOCK] = (rendu[RENDU_COLOR_FOND_GARALOCK] + BMP_CST_COLOR_NB_AVEC_CT - 1 ) % BMP_CST_COLOR_NB_AVEC_CT;
			if (mouse_in_rendu_rect(300, y)) rendu[RENDU_USE_GROS_GARALOCK] = (rendu[RENDU_USE_GROS_GARALOCK] + 1) % 2;
			y = 300;
			if (mouse_in_rendu_rect(220, y)) rendu[RENDU_COLOR_FOND] = (rendu[RENDU_COLOR_FOND] + BMP_CST_COLOR_NB - 1) % BMP_CST_COLOR_NB;
			if (mouse_in_rendu_rect(260, y)) rendu[RENDU_COLOR_FOND_RAIL] = (rendu[RENDU_COLOR_FOND_RAIL] + BMP_CST_COLOR_NB - 1) % BMP_CST_COLOR_NB;
			if (mouse_in_rendu_rect(300, y)) rendu[RENDU_COLOR_GRILLE] = (rendu[RENDU_COLOR_GRILLE] + BMP_CST_COLOR_NB - 1) % BMP_CST_COLOR_NB;
			if (mouse_in_rendu_rect(340, y)) rendu[RENDU_COLOR_TEXT] = (rendu[RENDU_COLOR_TEXT] + BMP_CST_COLOR_NB - 1) % BMP_CST_COLOR_NB;
			y = 380;
			if (mouse_in_rendu_rect(220, y)) rendu[RENDU_COLOR_DET_OFF] = (rendu[RENDU_COLOR_DET_OFF] + BMP_CST_COLOR_NB - 1) % BMP_CST_COLOR_NB;
			if (mouse_in_rendu_rect(260, y)) rendu[RENDU_COLOR_DET_ON] = (rendu[RENDU_COLOR_DET_ON] + BMP_CST_COLOR_NB - 1) % BMP_CST_COLOR_NB;
			y = 400;
			if (mouse_in_rendu_rect(220, y)) rendu[RENDU_COLOR_AIG_OFF] = (rendu[RENDU_COLOR_AIG_OFF] + BMP_CST_COLOR_NB - 1) % BMP_CST_COLOR_NB;
			if (mouse_in_rendu_rect(260, y)) rendu[RENDU_COLOR_AIG_ON] = (rendu[RENDU_COLOR_AIG_ON] + BMP_CST_COLOR_NB - 1) % BMP_CST_COLOR_NB;
			y = 420;
			if (mouse_in_rendu_rect(220, y)) rendu[RENDU_COLOR_VOY_OFF] = (rendu[RENDU_COLOR_VOY_OFF] + BMP_CST_COLOR_NB - 1) % BMP_CST_COLOR_NB;
			if (mouse_in_rendu_rect(260, y)) rendu[RENDU_COLOR_VOY_ON] = (rendu[RENDU_COLOR_VOY_ON] + BMP_CST_COLOR_NB - 1) % BMP_CST_COLOR_NB;
			y = 440;
			if (mouse_in_rendu_rect(220, y)) rendu[RENDU_COLOR_INT_OFF] = (rendu[RENDU_COLOR_INT_OFF] + BMP_CST_COLOR_NB - 1) % BMP_CST_COLOR_NB;
			if (mouse_in_rendu_rect(260, y)) rendu[RENDU_COLOR_INT_ON] = (rendu[RENDU_COLOR_INT_ON] + BMP_CST_COLOR_NB - 1) % BMP_CST_COLOR_NB;
			y = 460;
			if (mouse_in_rendu_rect(220, y)) rendu[RENDU_COLOR_IPP_OFF] = (rendu[RENDU_COLOR_IPP_OFF] + BMP_CST_COLOR_NB - 1) % BMP_CST_COLOR_NB;
			if (mouse_in_rendu_rect(260, y)) rendu[RENDU_COLOR_IPP_ON] = (rendu[RENDU_COLOR_IPP_ON] + BMP_CST_COLOR_NB - 1) % BMP_CST_COLOR_NB;
			if (mouse_in_rendu_rect(300, y)) rendu[RENDU_COLOR_IPP_LOCKOFF] = (rendu[RENDU_COLOR_IPP_LOCKOFF] + BMP_CST_COLOR_NB - 1) % BMP_CST_COLOR_NB;
			if (mouse_in_rendu_rect(340, y)) rendu[RENDU_COLOR_IPP_LOCKON] = (rendu[RENDU_COLOR_IPP_LOCKON] + BMP_CST_COLOR_NB - 1) % BMP_CST_COLOR_NB;
			j = (y_mouse - 520 - 1) / 10; i = (x_mouse - 60 - 1) / 20;
			if (j >= 0 && j <= 3 && i >= 0 && i < NB_CANTON) {
				color_canton[j][i] = (color_canton[j][i] + BMP_CST_COLOR_NB - 1) % BMP_CST_COLOR_NB;
			}
			if (j == 6 && i >= 0 && i < NB_TRAIN_COULEUR) {
				color_train[i] = (color_train[i] + BMP_CST_COLOR_NB - 1) % BMP_CST_COLOR_NB;
			}
			//sprintf_s(gszErr,"i=%d j=%d x=%d y=%d ",i,j,x_mouse,y_mouse); MessageBox(NULL,gszErr,"debug",MB_OK);
		}


		if (c_conf_wnd == 'A' || c_conf_wnd == 'B' || c_conf_wnd == 'C' || c_conf_wnd == 'D') {
			// La fenêtre d'édition est ouverte.
			if ((c_conf_wnd == 'A' && x_mouse < 400 && y_mouse<680) || (c_conf_wnd == 'B' && x_mouse>200 && x_mouse < 600 && y_mouse<680)
				|| (c_conf_wnd == 'C' && x_mouse>400 && x_mouse < 800 && y_mouse<680) || (c_conf_wnd == 'D' && x_mouse>760 && x_mouse < 1160 && y_mouse < 680)) { // La fenêtre fait 400 de large.
				// Clic-droit dans les cases de couleur = décrementation de l'indice de couleur.
				xdep=0; // 'A' => La fenêtre est déjà affiché à gauche de l'écran, xdep = 0.
				if(c_conf_wnd=='B') xdep=200; // 'B' => xdep = 200. La fenêtre est décalée sur la droite.
				if(c_conf_wnd=='C') xdep=400; // 'C' => xdep = 480.
				if(c_conf_wnd=='D') xdep=760; // 'D' => xdep = 760.
				x_sel=(x_mouse-xdep)/40;
				y_sel=(y_mouse)/40;
				// yopt = Décalage pour afficher les paramètres = 400.
				// Clic dans la case 'S+' pour définir le sens des flèche affiché dans le bloc.
				if ((x_mouse-xdep)>340 && (x_mouse-xdep)<360 && (y_mouse-yopt)> 0 && (y_mouse-yopt)<( 0+15)) temp_conf_sens=(temp_conf_sens^1)&1;
				// Clic dans la case 'C1,C2,C3 ou C4' pour incrémenter ces variables.
				if ((x_mouse-xdep)>340 && (x_mouse-xdep)<360 && (y_mouse-yopt)>20 && (y_mouse-yopt)<(20+10)) temp_conf_c1--;
				if ((x_mouse-xdep)>340 && (x_mouse-xdep)<360 && (y_mouse-yopt)>40 && (y_mouse-yopt)<(40+10)) temp_conf_c2--;
				if ((x_mouse-xdep)>340 && (x_mouse-xdep)<360 && (y_mouse-yopt)>60 && (y_mouse-yopt)<(60+10)) temp_conf_c3--;
				if ((x_mouse-xdep)>340 && (x_mouse-xdep)<360 && (y_mouse-yopt)>80 && (y_mouse-yopt)<(80+10)) temp_conf_c4--;
				if (temp_conf_c1<=-2) temp_conf_c1=BMP_CST_COLOR_NB-1;
				if (temp_conf_c2<=-2) temp_conf_c2=BMP_CST_COLOR_NB-1;
				if (temp_conf_c3<=-2) temp_conf_c3=BMP_CST_COLOR_NB-1;
				if (temp_conf_c4<=-2) temp_conf_c4=BMP_CST_COLOR_NB-1;
			}
			else {
				// Le clic de souris est dans la grille du TCO
				x_sel = (x_mouse) / 40;
				y_sel = (y_mouse) / 40;
				cells_type_sel = cells[tco][x_sel][y_sel][CELLS_TYPE];
				cells_subtype_sel = cells[tco][x_sel][y_sel][CELLS_SUBTYPE];
				temp_conf_canton = cells[tco][x_sel][y_sel][CELLS_CANT];
				temp_conf_n1 = cells[tco][x_sel][y_sel][CELLS_N1];
				temp_conf_n2 = cells[tco][x_sel][y_sel][CELLS_N2];
				temp_conf_v1 = cells[tco][x_sel][y_sel][CELLS_V1];
				temp_conf_v2 = cells[tco][x_sel][y_sel][CELLS_V2];
				temp_conf_v3 = cells[tco][x_sel][y_sel][CELLS_V3];
				temp_conf_v4 = cells[tco][x_sel][y_sel][CELLS_V4];
				temp_conf_c1 = cells[tco][x_sel][y_sel][CELLS_C1];
				temp_conf_c2 = cells[tco][x_sel][y_sel][CELLS_C2];
				temp_conf_c3 = cells[tco][x_sel][y_sel][CELLS_C3];
				temp_conf_c4 = cells[tco][x_sel][y_sel][CELLS_C4];
				temp_conf_opt = cells[tco][x_sel][y_sel][CELLS_OPT];
				temp_conf_sens = cells[tco][x_sel][y_sel][CELLS_SENS];
				strcpy(sz_temp_conf_txt, sz_cells[tco][x_sel][y_sel]);
			}
		}
		else if (c_conf_wnd == ' ') {
			// La fenêtre d'édition est fermée (Le clic est donc dans la grille d'un TCO).
			x_sel = (x_mouse) / 40;
			y_sel = (y_mouse) / 40;
			if (x_sel >= 0 && x_sel < CELLS_X_NB && y_sel >= 0 && y_sel < CELLS_Y_NB)
			if (c_conf_wnd == ' ') {
				// Clic dans la grille
				if (cells[tco][x_sel][y_sel][CELLS_TYPE] == CELLS_TYPE_CMDVOY)
				if (cells[tco][x_sel][y_sel][CELLS_SUBTYPE] == CELLS_SUBTYPE_CMDVOY_ITI)
				if (cells[tco][x_sel][y_sel][CELLS_OPT] != 1) {
					v1 = cells[tco][x_sel][y_sel][CELLS_V1];
					v2 = cells[tco][x_sel][y_sel][CELLS_V2];
					if (v2 != -1) pio_set_val(v2, 1);           // Met la variable 'iti_stop_xxx' = 1
					if (v1 != -1 && v2 == -1) pio_set_val(v1, 0); // Met la variable 'iti_start_xxx' = 0 si 'iti_stop_xxx' n'est pas définie.
				}
			}
		}
	} // FIN ACTION = CLIC DROIT DE LA SOURIS
}


// Sous-programme appelé par le menu Windows : 'Menu principal > Edition TCO'.
// Affiche la fenêtre d'édition des TCO à gauche.
//
void cells_open_edit(void)
{
	c_conf_wnd='A';	
	cells_redraw=1;
	cells_type_sel=CELLS_TYPE_RIEN;
}


// Sous-programme appelé par le menu Windows : 'Menu principal > Rendu des couleurs'.
// Affiche la fenêtre de rendu des couleurs à gauche.
//
void cells_open_render(void)
{
	c_conf_wnd='R';
	cells_redraw=1;
	cells_type_sel=CELLS_TYPE_RIEN;
}

// Sous-programme appelé par le menu Windows : 'Menu principal > Aide sur les variables'.
// Affiche la fenêtre 
//
void cells_open_aide(void)
{
	c_conf_wnd='H';	
	cells_redraw=1;
	cells_type_sel=CELLS_TYPE_RIEN;
}


/*****************************************************************************/
/* FIN TCO                                                                   */
/*****************************************************************************/


// Sous-programme 
//
//
void update_copy_canton(void)
{
	int i,j;
	for (j=0; j<NB_CARTE; j++) {
		for (i=0; i<NB_CANTON; i++) {
			copy_res_auto[j][i]=canton.res_auto[j][i];
			copy_master_selectif[j][i]=canton.master_selectif[j][i];
			copy_update_selectif[j][i]=canton.update_selectif[j][i];
			copy_num_train[j][i]=canton.num_train[j][i];
			//copy_allowed_sens[j][i]=canton.allowed_sens[j][i];
			canton.allowed_sens[j][i]=copy_allowed_sens[j][i];
		}
    }
}

void update_copy_train(void)
{
	int i,j,t;
	for (t=0; t<NB_TRAIN; t++) {
		strcpy(copy_train_name[t],train.name[t]);
		train_pb_capt[t]=0;  // 0 ou 1, 1 => Le train n'est pas détecté sur les cantons.
		for (j=0; j<NB_CARTE; j++) {
			for (i=0; i<NB_CANTON; i++) {
				if (canton.num_train[j][i]==t) {
					if (train.capt[t]==0) train_pb_capt[t]=1;
				}
			}
		}
	}

	for (j=0; j<NB_CARTE; j++) {
		for (i=0; i<NB_CANTON; i++){
			canton_pb_capt[j][i]=0;
			for (t=0; t<NB_TRAIN; t++) {
				if (canton.num_train[j][i]==t) {
					if (train.capt[t]==0) canton_pb_capt[j][i]=1;
				}
			}
		}
	}

	for (i=0; i<NB_GARAGE_REEL; i++) { // Nombre de garage limité à 16 pour le moment.
		copy_garage_num_train[i]=garage.numero_train[i]; // -1 = Garage relié au canton, ou Numéro de train occupant le garage isolé du canton.
		copy_garage_ass_canton[i]=garage.ass_canton[i];
	}
}

//
// Réalise le traitement de la demande de Raccordement/Isolation du garage en fonction des conditions.
// Traitement cyclique pour les garages.
//
void garage_lock_and_unlock(void)
{
	int i,j,k,c,t;
	for (i=0; i<NB_GARAGE; i++) { // Pour chaque garage.
		if (garage.ass_canton[i]==-1) continue;  // -1 => Garage non déclaré, on passe au suivant.
		if (vio_garage_lock_res[i]==1) continue; //  1 => Garage réservé, on passe au suivant.
		if (vio_garage_lock_status[i]==0 && vio_garage_lock_cmd[i]==1) { // 1 => Demande d'isolation du garage du canton.
			vio_garage_lock_cmd[i]=0;
			// Vérifier train sur canton principal
			c=garage.ass_canton[i];             if(c==-1) continue; if(canton.master_selectif[c/100][c%100]==0) continue;
			t=canton.num_train[c/100][c%100];   if(t==-1) continue;
			// Libérer le canton principal
			for (j=0; j<NB_CARTE; j++) {
				for(k=0;k<NB_CANTON;k++) {
					if(canton.num_train[j][k]==t) {
						canton.num_train[j][k]=-1;
						canton.master_selectif[j][k]=0;
						canton.update_selectif[j][k]=0;
					}
				}
			}
			// Isoler (Verouiller) le garage avec un train dessus.
			train.cant_lock[t]=i;
			garage.numero_train[i]=t;    // -1 = Garage relié au canton, ou Numéro de train occupant le garage isolé du canton.
			vio_garage_lock_cmd[i]=1;    // 1 => Demande d'isolation du garage (1=demande pour isoler le garage).
			vio_garage_lock_status[i]=1; // 1 => Le garage est isolé du canton (état réel).
		}
		else if(vio_garage_lock_status[i]==1 && vio_garage_lock_cmd[i]==0) {  // 0 => Demande pour relier le garage au canton.
			vio_garage_lock_cmd[i]=1;
			// Vérifier canton principal libre
			c=garage.ass_canton[i]; if(c==-1) continue;
			if(canton.res_auto[c/100][c%100]==1) continue;
			if(canton.master_selectif[c/100][c%100]==1) continue;
			t=garage.numero_train[i]; // -1 = Garage relié au canton, ou Numéro de train occupant le garage isolé du canton.
			// updater le canton principal
			canton.num_train[c/100][c%100]=t;
			canton.master_selectif[c/100][c%100]=1;
			// Relier le garage.
			train.cant_lock[t]=-1;
			garage.numero_train[i]=-1;   // -1 = Garage relié au canton, ou Numéro de train occupant le garage isolé du canton.
			vio_garage_lock_cmd[i]=0;    // 0 => Demande d'isolation du garage (0=demande pour relier le garage).
			vio_garage_lock_status[i]=0; // 0 => Le garage est relié au canton (état réel).
		}
	}
}

//MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
//MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
//MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
/*****************************************************************************/
/* WINDOWS                                                                   */
/*****************************************************************************/
cSerial   serial_card0;
cSerial   serial_card1;
cSerial   serial_card2;
cSerial   serial_card3;


char szDeconnectee[100]="";
/* Declare Windows procedure */
LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM);
//


/*
cbSize	Defines the size of the structure. Use size WNDCLASSEX
style	Describes the behaviour of the window. See API "Class Styles" (CS_xxx)
lpfnWndProc	Pointer to the window procedure
cbClsExtra	Needed if the class shall be extended. Can be left 0.
cbWndExtra	The same for a window. For all classes except dialogues, this can be left 0.
hInstance	Marks our program. Is retrieved using GetModuleHandle.
hIcon	Icon for the window. Use 0 for a standard icon, otherwise the handle of a resource.
hCursor	Like icon, 0 = standard cursor.
hbrBackground	Background colour. If 0, the window won't get coloured automatically.
lpszMenuName	Name of the menu resource (0 = no menu).
lpszClassName	Name which identifies the class. You can call it as you want.
hIconSm	Small icon. See normal icon.
*/
int WINAPI WinMain(HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nFunsterStil)
//                 >numéro unique attribué par le système d'exploitation qui lui permet de l'identifier.
//                                          >NULL pour les applications Win32.
//                                                                   >pointeur sur la ligne de commande.
//                                                                                       >identificateur fenêtre (normal, caché, minimisé.
{
	int dimx, dimy, plein_ecran; // Dimension de la fenêtre Windows.
	MSG messages;			/* Here messages to the application are saved */
	WNDCLASSEX wincl;		/* Data structure for the windowclass */
	ghinstance=hThisInstance;
	/* The Window structure */
	wincl.hInstance   = hThisInstance;
	wincl.lpfnWndProc = WindowProcedure;			// This function is called by windows ou '(WNDPROC) WndProc'
	wincl.style = CS_DBLCLKS;						// Catch double-clicks ou 'CS_HREDRAW | CS_VREDRAW'
	wincl.cbSize = sizeof(WNDCLASSEX);
	/* Use default icon and mouse-pointer */
	wincl.hIcon =   LoadIcon(NULL, IDI_APPLICATION); // Ou '0'.
	wincl.hIconSm = LoadIcon(NULL, IDI_APPLICATION); // Ou '0'.
	wincl.hCursor = LoadCursor(NULL, IDC_ARROW);	 // Curseur = Fléche
	wincl.lpszClassName = "UTS_Train_Class";		 // Nom de cette classe
	wincl.lpszMenuName  = "MAINMENU";				 // Nom du menu de la fenêtre ou '0'
	wincl.cbClsExtra = 0;							 // No extra bytes after the window class = 0 
	wincl.cbWndExtra = 0;							  // structure or the window instance = 0 
	wincl.hbrBackground = (HBRUSH) GetStockObject(LTGRAY_BRUSH); // Couleur du fond de la fenêtre

	if(!RegisterClassEx(&wincl)) return 0;

	dimx=800; dimy=700;  // 800 x 700 = Valeurs par défaut si pas de dimension dans 'config.txt'. 
	cfg_relief=1;            // Relief par defaut.
	config_general_exit_if_no_file("config.txt");
	ecran_init_file("config.txt", &dimx, &dimy, &plein_ecran); // dimxy et dimy ne sont modifiés que si une directive 'resolution_ecran' est trouvé dans 'config.txt'.
                                                               // relief n'est modifié que si une directive 'relief' est trouvé dans 'config.txt'.

	hwnd = CreateWindowEx(   // hwnd = C'est un nombre entier généré par Windows permettant d'identifier de manière unique une fenêtre.
		0,		             // Extended possibilites for variation
		"UTS_Train_Class",   // Classname
		TITRE,		         // Titre de la fenêtre défini dans 'Train_UTS.h'.
		WS_OVERLAPPEDWINDOW, // default window
		CW_USEDEFAULT,       // Windows decides the position
		CW_USEDEFAULT,       // where the window ends up on the screen
		dimx /*800*/,        // Dimension de la fenêtre en pixels
		dimy /*700*/,        //
		HWND_DESKTOP,        // Handle de la fenêtre parent ou du titulaire de la fenêtre en cours de création.
		NULL,		     // No menu
		hThisInstance,       // Handle de l'instance du module d'être associés à la fenêtre
		NULL		      // No Window Creation data
	);

	ShowWindow(hwnd, nFunsterStil); // Dire à Windows d'afficher la fenêtre et la mettre à jour
	if (plein_ecran==1) ShowWindow(hwnd, SW_SHOWMAXIMIZED); 

// Le message en boucle : Windows envoie des messages directement à votre fonction, mais d'autres sont placés dans une file d'attente. 
// Celles-ci viennet du clavier ou d'autres messages d'entrée qui ont besoin de traduction. 
// Nous entrons dans une boucle qui vérifie la file d'attente des messages. Si l'un est trouvé, il est traduit et envoyé à nos fenêtres de procédure.	
	while(GetMessage(&messages, NULL, 0, 0)) {
		TranslateMessage(&messages);
		DispatchMessage(&messages);
	}
	return (int) messages.wParam;   // Si return (0) = Fin du programme.   (int) rajouté le 16/06/2009.
}

/* This function is called by the Windows function DispatchMessage( ) */
LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
//                               En général, vous venez de créer une fenêtre de votre fenêtre de la classe.      
//                                          Tel est le message de votre fenêtre a reçue.  
{
	static int en_cours=0;
	static int cx, cy;
	int ret, ok, i, j;
	hdc_ori=GetDC(hwnd);       // hwnd = C'est un nombre entier généré par Windows permettant d'identifier de manière unique une fenêtre.
	char chtemp[100];	


	switch (message) {                      // handle the messages 
		case WM_CREATE :                    // Windows active cette entrée une seule fois au lancement du programme.
			pio_init();                     // pio_define_list();
			config_general_init_file("config.txt");
			font_pinceau_stylo_init();
			tdv.init("config.txt");         // Récupére la configuration des tables de vérité et des équations.
			// tdv.save_conf();             // Appel uniquement en cas de debug pour créer le fichier "Debug_prog.txt" avec le contenu des tdv.
			ThisExe.init("config.txt");     // ThisExe.save_conf();
			vib_init_file("config.txt");    // Récupére la configuration du vibreur.
			iti.init("config.txt");         // Récupére la configuration des ininéraires.
			horo_init_file("config.txt");   horo_tic_on=0;   //horo_save_conf();
			garage.init("config.txt");      // Récupére la configuration des garages.
			deplacement.init("config.txt"); // Récupére la configuration des deplacements.
			aig_init_file("config.txt");    // Récupére la configuration des aiguillages.
			ret=serialPort.init();
			if (ret) { sprintf_s(szDeconnectee, "COM%d", ret); connecte = 1; }
			else { strcpy(szDeconnectee, "Mode Deconnécté"); connecte = 0; }
			serial_card0.init(0,serialPort.card0_ok);
			serial_card1.init(1,serialPort.card1_ok);
			serial_card2.init(2,serialPort.card2_ok);
			serial_card3.init(3,serialPort.card3_ok);
			canton.init();                // Initialise la configuration des cantons.
			train.init("config.txt");     // Récupére la configuration des trains.
			// train.save_conf();         // Appel uniquement en cas de debug pour créer le fichier "debug_train.txt" avec le contenu des trains.
			selectif.init("config.txt");  //selectif::init()
			aigauto.init("config.txt");   //aigauto::init() V3.3
			balauto.init("config.txt");   //balauto::init() V3.4
			init_fonte_pen_brush();
			SetTimer(hwnd,1,timer_prg,NULL); // Durée du timer d'activation du programme = 250 msec en 2.0, 80 msec en V3.3
			screen_mode=MD_ECRAN_TCO0;       // Démarre sur l'écran 'TCO-0'.
			cells_config("config_tco.txt");
			break;

		case WM_SIZE:
			cx=min(CELLS_X_NB*CELLS_SIZE,LOWORD(lParam))+1;  // Pour la fonction CreateCompatible HDC et "BitBlt(hdc_ori, 0, 0, cx, cy, hMemDC, 0, 0, SRCCOPY)".
			cy=min(CELLS_Y_NB*CELLS_SIZE,HIWORD(lParam))+1;  // Cela ne sert à rien de prendre un rectangle plus quand que la surface UTS
			break;                                         // Permet de garder la surface non couverte par UTS en gris, quand on agrandie la fenêtre.

		case WM_TIMER:	// Windows active cette entrée cycliquement en fonction du timer ( 80 msec en V3.3).
			if(wParam!=1) break;
			if(en_cours==1) break;
			en_cours=1;
			ir_maj();
			update_copy_canton(); // canton.xxx[][] => copy_xxx[][]
			update_copy_train();  // train.xxx[] => copy_xxx[]
			debug_tic_nb++;
			if (cmd_divers[CMD_DIVERS_TEMPO]>0)        cmd_divers[CMD_DIVERS_TEMPO]--;
			if (cmd_divers[CMD_DIVERS_TEMPO_RESULT]>0) cmd_divers[CMD_DIVERS_TEMPO_RESULT]--;

			//  Réaffichage complet d'une fenêtre (si 'do_not_redraw'=0) toute les 4 sec suivant la valeur du timer (en V2.0 timer=250 msec, en V3.3 timer=80 msec).
			#ifdef VERSION_UTS_V3
			do_not_redraw=debug_tic_nb%50;
			#else
			do_not_redraw=debug_tic_nb%16;
			#endif

			special_var_tick(); // Mise à jour des variables internes à UTS mais lisibles pour l'utilisateur.
			tdv.tick();			
			srv_maj();          // Mise à jour des servo moteurs avant 
			serial_card0.maj();
			serial_card1.maj();
			serial_card2.maj();
			serial_card3.maj();

			// On peut placer ici des assignations provisoire pour par exemple forcer à '1' la détection sur un canton pour test.
			// Si var_499=1, On passe en mode débug pour test. On force les indicateurs de détection de train sur les cantons.
			// Les variables var_440 à var_431 donnent la valeur de forçage. Ceci permet de tester les tables de vérité.
			// Ces variables sont positionnées depuis des boutons poussoirs du TCO.
			if (pio_var[499]==1 ){
				// int vio_det[NB_CARTE][NB_CANTON] 1 = canton occupé, valeurs acquises.
				vio_det[0][0]=pio_var[450];  vio_det[0][1]=pio_var[451];  vio_det[0][2]=pio_var[452];  vio_det[0][3]=pio_var[453];  vio_det[0][4]=pio_var[454];
				vio_det[0][5]=pio_var[455];  vio_det[0][6]=pio_var[456];  vio_det[0][7]=pio_var[457];  vio_det[0][8]=pio_var[458];  vio_det[0][9]=pio_var[459];
				vio_det[0][10]=pio_var[460]; vio_det[0][11]=pio_var[461]; vio_det[0][12]=pio_var[462]; vio_det[0][13]=pio_var[463]; vio_det[0][14]=pio_var[464];
				vio_det[0][15]=pio_var[465];

				vio_det[1][0]=pio_var[466];  vio_det[1][1]=pio_var[467];  vio_det[1][2]=pio_var[468];  vio_det[1][3]=pio_var[469]; vio_det[1][4]=pio_var[470];  
				vio_det[1][5]=pio_var[471];  vio_det[1][6]=pio_var[472];  vio_det[1][7]=pio_var[473];  vio_det[1][8]=pio_var[474]; vio_det[1][9]=pio_var[475];
				vio_det[1][10]=pio_var[476]; vio_det[1][11]=pio_var[477]; vio_det[1][12]=pio_var[478]; vio_det[1][13]=pio_var[479]; vio_det[1][14]=pio_var[480];
				vio_det[1][15]=pio_var[481];

				// int vio_det[NB_CARTE][NB_CANTON] 1 = canton occupé, valeurs acquises.
				vio_in[0][0] = pio_var[500];  vio_in[0][1] = pio_var[501];  vio_in[0][2] = pio_var[502];  vio_in[0][3] = pio_var[503];  vio_in[0][4] = pio_var[504];
				vio_in[0][5] = pio_var[505];  vio_in[0][6] = pio_var[506];  vio_in[0][7] = pio_var[507];  vio_in[0][8] = pio_var[508];  vio_in[0][9] = pio_var[509];

				vio_in[0][10] = pio_var[510];  vio_in[0][11] = pio_var[511];  vio_in[0][12] = pio_var[512];  vio_in[0][13] = pio_var[513];  vio_in[0][14] = pio_var[514];
				vio_in[0][15] = pio_var[515];  vio_in[0][16] = pio_var[516];  vio_in[0][17] = pio_var[517];  vio_in[0][18] = pio_var[518];  vio_in[0][19] = pio_var[519];

				vio_in[0][20] = pio_var[520];  vio_in[0][21] = pio_var[521];  vio_in[0][22] = pio_var[522];  vio_in[0][23] = pio_var[523];  vio_in[0][24] = pio_var[524];
				vio_in[0][25] = pio_var[525];  vio_in[0][26] = pio_var[526];  vio_in[0][27] = pio_var[527];  vio_in[0][28] = pio_var[528];  vio_in[0][29] = pio_var[529];

				vio_in[0][30] = pio_var[530];  vio_in[0][31] = pio_var[531];  vio_in[0][32] = pio_var[532];  vio_in[0][33] = pio_var[533];  vio_in[0][34] = pio_var[534];
				vio_in[0][35] = pio_var[535];  vio_in[0][36] = pio_var[536];  vio_in[0][37] = pio_var[537];  vio_in[0][38] = pio_var[538];  vio_in[0][39] = pio_var[539];

				vio_in[0][40] = pio_var[540];  vio_in[0][41] = pio_var[541];  vio_in[0][42] = pio_var[542];  vio_in[0][43] = pio_var[543];  vio_in[0][44] = pio_var[544];
				vio_in[0][45] = pio_var[545];  vio_in[0][46] = pio_var[546];  vio_in[0][47] = pio_var[547];  vio_in[0][48] = pio_var[548];  vio_in[0][49] = pio_var[549];

				vio_in[0][50] = pio_var[550];  vio_in[0][51] = pio_var[551];  vio_in[0][52] = pio_var[552];  vio_in[0][53] = pio_var[553];  vio_in[0][54] = pio_var[554];
				vio_in[0][55] = pio_var[555];  vio_in[0][56] = pio_var[556];  vio_in[0][57] = pio_var[557];  vio_in[0][58] = pio_var[558];  vio_in[0][59] = pio_var[559];

				vio_in[0][60] = pio_var[560];  vio_in[0][61] = pio_var[561];  vio_in[0][62] = pio_var[562];  vio_in[0][63] = pio_var[563];  vio_in[0][64] = pio_var[564];
				vio_in[0][65] = pio_var[565];  vio_in[0][66] = pio_var[566];  vio_in[0][67] = pio_var[567];  vio_in[0][68] = pio_var[568];  vio_in[0][69] = pio_var[569];

				vio_in[0][70] = pio_var[570];  vio_in[0][71] = pio_var[571];  vio_in[0][72] = pio_var[572];  vio_in[0][73] = pio_var[573];  vio_in[0][74] = pio_var[574];
				vio_in[0][75] = pio_var[575];  vio_in[0][76] = pio_var[576];  vio_in[0][77] = pio_var[577];  vio_in[0][78] = pio_var[578];  vio_in[0][79] = pio_var[579];
			}

			// Pour débug vitesse du train sur canton 0, pour étudier les paramètres d'inertie dans le tableur Libre Office.
			/*if (vio_canton_vit[0][0]!=0)       {
				sprintf_s(chtemp, "%6d\n", vio_canton_vit[0][0]);
				log(chtemp);
			}*/

			if (arret_urg_on==1 && arret_urg_on_old==0) {  // Pour comparer et voir si la variable d'arrêt d'urgence a changé.
				// On vient d'enfoncer le bouton poussoir d'arrêt d'urgence. On a une équation pour associer une entrée à cette variable dans #tdv.
				cmd_divers[CMD_DIVERS_OPT4_ARRET] ^= 1;    // On change l'état de l'arrêt d'urgence.
			}
			arret_urg_on_old = arret_urg_on;

			// Si le timer < 150 msec, on affiche une image sur deux en V3.3 pour éviter un scintillement.
			if (FREQ_RAFRAICHISSEMENT==0 && screen_mode>=MD_ECRAN_TCO0 && screen_mode<=MD_ECRAN_TCO7) {
				hMemDC  = CreateCompatibleDC(hdc_ori);               // Pour obtenir un Handle de Contexte = "HDC".
				hMemBmp = CreateCompatibleBitmap(hdc_ori, cx, cy);   // Créer un Bitmap compatible avec le périphérique.
				hOldBmp = SelectObject(hMemDC, hMemBmp);             // Pour restaurer l'état à la fin. Reçoit le handle du contexte de périphérique sur lequel 
														             // on veut utiliser l'objet (pinceau, crayon...)et le handle de l'objet comme second paramètre.
				cells_draw(screen_mode);
				BitBlt(hdc_ori, 0, 0, cx, cy, hMemDC, 0, 0, SRCCOPY);
				SelectObject(hMemDC, hOldBmp); DeleteObject(hMemBmp); DeleteDC(hMemDC);
			}
			train.maj(); // cons[train]=x, vit[train]=y. Dans train.maj() : aigauto.tick(), balauto.tick_vitmax(), balauto.tick_halt(), balauto.tick_cant()
			selectif.tick();	// Mise à jour des canton.xxx[][].
			deplacement.tick();
			canton.maj();		// vio_canton_vit[j][i]=x  +  Traitement des variables "det2_xx" en V3.5b
			horo_maj();
			iti.tick();
			iti2_tick();
			aig_maj();
			vib_maj();
			garage.maj();		// vio_out[][]=x.
			ThisExe.tick();
			train.canton_maj_profil(); // Mise à jour de la vitesse des canton en fonction du profil des train (Vmin,Vmax).
			// Si le timer < 150 msec, on affiche une image sur deux depuis la V3.4 pour éviter un scintillement.
			// On recopie avec la fonction "BitBlt' la partie d'écran qui a changé vers le buffer graphique principal (double buffering)
			if (screen_mode>MD_ECRAN_TCO7 && FREQ_RAFRAICHISSEMENT==0) {
				hMemDC  = CreateCompatibleDC(hdc_ori);               // Pour obtenir un Handle de Contexte = "HDC".
				hMemBmp = CreateCompatibleBitmap(hdc_ori, cx, cy);   // Créer un Bitmap compatible avec le périphérique.
				hOldBmp = SelectObject(hMemDC, hMemBmp);             // Pour restaurer l'état à la fin. Reçoit le handle du contexte de périphérique sur lequel 
						                                             // on veut utiliser l'objet (pinceau, crayon...)et le handle de l'objet comme second paramètre.
				                                                     // BitBlt(hdc_ori, Xpos, Ypos, Width, Height).
				if      (screen_mode==MD_ECRAN_GARAGE)  { garage.debug(DEBUG_PAINT);  BitBlt(hdc_ori,   0,   2*18,  800,   18*16, hMemDC,   0,   2*18, SRCCOPY); }
				else if (screen_mode==MD_ECRAN_SERVO)   { srv_debug(DEBUG_PAINT);     BitBlt(hdc_ori,  75, 2*16, 6*75,   20*16, hMemDC,  75, 2*16, SRCCOPY); }
				else if (screen_mode==MD_ECRAN_TDV1)    { tdv.debug(DEBUG_PAINT);     BitBlt(hdc_ori,   0,   70,  800, 20*25-1, hMemDC,   0,   70, SRCCOPY); }
				else if (screen_mode==MD_ECRAN_TDV2)    { tdv.debug2(DEBUG_PAINT);    BitBlt(hdc_ori,   0,  2*16,  800,   32*16, hMemDC,   0,  2*16, SRCCOPY); }
				else if (screen_mode==MD_ECRAN_HORO_R)  { horo_debug_r(DEBUG_PAINT);  BitBlt(hdc_ori, 180,  140,  360,     101, hMemDC, 180,  140, SRCCOPY);
				                                                                      BitBlt(hdc_ori,   1,  321,  720,      16, hMemDC,   1,  321, SRCCOPY);
				                                                                      BitBlt(hdc_ori,  20,  440,  760,      21, hMemDC,  20,  440, SRCCOPY); }
				else if (screen_mode==MD_ECRAN_VIB)     { vib_debug(DEBUG_PAINT);     BitBlt(hdc_ori,  40,  160,  720,     161, hMemDC,  40,  160, SRCCOPY); 
				                                                                      BitBlt(hdc_ori, 600,  340,  130,      21, hMemDC, 600,  340, SRCCOPY); 
				                                                                      BitBlt(hdc_ori, 600,  380,  130,      21, hMemDC, 600,  380, SRCCOPY); 
				                                                                      BitBlt(hdc_ori, 180,  460,  395,      95, hMemDC, 180,  460, SRCCOPY); 
																					  BitBlt(hdc_ori, 180,  580,  395,      45, hMemDC, 180,  580, SRCCOPY); }
				else if (screen_mode==MD_ECRAN_SERIAL)  { serial_debug(DEBUG_PAINT);  BitBlt(hdc_ori,   0,    0,  800,     700, hMemDC,   0,    0, SRCCOPY); }
				else if (screen_mode==MD_ECRAN_TRAIN1  || screen_mode==MD_ECRAN_TRAIN2)    { train.debug(DEBUG_PAINT);
				                                                                             BitBlt(hdc_ori,   1,  100,  798,     600, hMemDC,   1,  100, SRCCOPY);   // Tableau du haut, trains de 1 à 15 jusqu'en bas de la fenêtre
				                                                                             BitBlt(hdc_ori, 600,   30,  200,      40, hMemDC, 600,   30, SRCCOPY); } // Bouton [Trains] ou [Wagons]
				else if (screen_mode==MD_ECRAN_CANTON1 || screen_mode==MD_ECRAN_CANTON2)   { canton.debug(DEBUG_PAINT);
				                                                                             BitBlt(hdc_ori,   1,   32,  798,   32*16, hMemDC,   1,   32, SRCCOPY); }
				else if (screen_mode==MD_ECRAN_VITMAX1 || screen_mode==MD_ECRAN_VITMAX2)   { balauto.debug_vitmax(DEBUG_PAINT);
				                                                                             BitBlt(hdc_ori,   1,   32,  798,   32*16, hMemDC,   1,   32, SRCCOPY); }
				else if (screen_mode==MD_ECRAN_HALTE1  || screen_mode==MD_ECRAN_HALTE2)    { balauto.debug_halt(DEBUG_PAINT);
				                                                                             BitBlt(hdc_ori,   1,   32,  798,   32*16, hMemDC,   1,   32, SRCCOPY); }
				else if (screen_mode==MD_ECRAN_POSLOC1 || screen_mode==MD_ECRAN_POSLOC2)   { train.debug2(DEBUG_PAINT);    
				                                                                             BitBlt(hdc_ori,   1,  100,  798,     560, hMemDC,   1,  100, SRCCOPY);
				                                                                             BitBlt(hdc_ori, 600,   30,  200,      40, hMemDC, 600,   30, SRCCOPY);
																						     BitBlt(hdc_ori, 147,   60,  303,      16, hMemDC, 147,   60, SRCCOPY); }
				else if (screen_mode==MD_ECRAN_ITI1    || screen_mode==MD_ECRAN_ITI2)      { iti.debug(DEBUG_PAINT);
								                                                             BitBlt(hdc_ori,   1, 2*18,  798,   25*18, hMemDC,   1, 2*18, SRCCOPY); }
				else if (screen_mode==MD_ECRAN_AIG1    || screen_mode==MD_ECRAN_AIG2)      { aig_debug(DEBUG_PAINT);
								                                                             BitBlt(hdc_ori,   1, 2*18,  44+(4*75)-1,   30*18, hMemDC,   1, 2*18, SRCCOPY); }
				
				else if (screen_mode==MD_ECRAN_SEPARE1 || screen_mode==MD_ECRAN_SEPARE2)   { iti.debug2(DEBUG_PAINT);
								                                                             BitBlt(hdc_ori,   0,    0,  800,     700, hMemDC,   0,    0, SRCCOPY); }
								
				else if (screen_mode>=MD_ECRAN_SELECT1  && screen_mode<=MD_ECRAN_SELECT3)  { selectif.debug(DEBUG_PAINT);
				                                                                             BitBlt(hdc_ori,   1,   32,  798,   32*16, hMemDC,   1,   32, SRCCOPY); }
				else if (screen_mode>=MD_ECRAN_AIGAUTO1 && screen_mode<=MD_ECRAN_AIGAUTO3) { aigauto.debug(DEBUG_PAINT);
				                                                                             BitBlt(hdc_ori,   1,   32, 1098,   32*16, hMemDC,   1,   32, SRCCOPY); }
				else if (screen_mode>=MD_ECRAN_BALAUTO1 && screen_mode<=MD_ECRAN_BALAUTO3) { balauto.debug_cant(DEBUG_PAINT);
				                                                                             BitBlt(hdc_ori,   1,   32, 1098,   32*16, hMemDC,   1,   32, SRCCOPY); }
				else if (screen_mode>=MD_ECRAN_VAR1     && screen_mode<=MD_ECRAN_VAR3)     { var_debug(DEBUG_PAINT);
								                                                             BitBlt(hdc_ori,   1,   2*16,8*(44+55)-1,   30*16, hMemDC,   1,   2*16, SRCCOPY);
												                                             BitBlt(hdc_ori,   1,35*16+8,        798,  2*16+2, hMemDC,   1,35*16+8, SRCCOPY); }
				else if (screen_mode>=MD_ECRAN_EXE1     && screen_mode<=MD_ECRAN_EXE3)     { ThisExe.debug(DEBUG_PAINT);
				                                                                             BitBlt(hdc_ori,   1,   2*16,1098,   32*16, hMemDC,   1, 2*16, SRCCOPY); }
				else if (screen_mode>=MD_ECRAN_DEPL1    && screen_mode<=MD_ECRAN_DEPL7)    { deplacement.debug(DEBUG_PAINT);
				                                                                             BitBlt(hdc_ori,   1,20+18,  798,  30*18-1, hMemDC,   1,20+18, SRCCOPY); }
				else if (screen_mode >= MD_ECRAN_HORO_L1  && screen_mode <= MD_ECRAN_HORO_L7)  { horo_debug_l(DEBUG_PAINT);
				                                                                                 BitBlt(hdc_ori, 0, 2 * 16, 1100, 32 * 16, hMemDC, 0, 2 * 16, SRCCOPY);
				                                                                                 BitBlt(hdc_ori, 940, 610,  70, 15, hMemDC, 940, 610, SRCCOPY); // Heure en bas à droite
				                                                                                 BitBlt(hdc_ori, 470, 559, 570, 21, hMemDC, 470, 559, SRCCOPY); // Boutons
				}
				SelectObject(hMemDC, hOldBmp); DeleteObject(hMemBmp); DeleteDC(hMemDC);
			}
			serial_debug(DEBUG_TICK);  // every time to manage direct can to debug canton loop
			en_cours=0;
			//if (FREQ_RAFRAICHISSEMENT==0 && screen_mode>MD_ECRAN_TCO7) BitBlt(hdc_ori, 0, 0, 800, 700, hMemDC, 0, 0, SRCCOPY);
			break;


		case WM_PAINT:	// Windows a décidé que la fenêtre entiére doit être re-dessinée. Exemple : cas où UTS était entiérement caché par une autre fenêtre.
			            // Ou si l'on doit afficher une nouvelle fenêtre ou un nouveau tableau.
			hMemDC  = CreateCompatibleDC(hdc_ori);               // Pour obtenir un Handle de Contexte = "HDC".
			hMemBmp = CreateCompatibleBitmap(hdc_ori, cx, cy);   // Créer un Bitmap compatible avec le périphérique.
			hOldBmp = SelectObject(hMemDC, hMemBmp);             // Pour restaurer l'état à la fin. Reçoit le handle du contexte de périphérique sur lequel 
			                                                 // on veut utiliser l'objet (pinceau, crayon...)et le handle de l'objet comme second paramètre.
			if (screen_mode>MD_ECRAN_TCO7) { // Si l'on affiche un tableau, on met du gris sur tout le fond de l'image. 
				SelectObject(hMemDC,bmp_pinceau_gris192); SelectObject(hMemDC,bmp_stylo_gris192); Rectangle(hMemDC,0,0,cx,cy);
			}
			if (screen_mode==MD_ECRAN_GARAGE)       garage.debug(DEBUG_TOTAL_PAINT);
			else if (screen_mode==MD_ECRAN_SERIAL)  serial_debug(DEBUG_TOTAL_PAINT);
			else if (screen_mode==MD_ECRAN_TDV1)    tdv.debug(DEBUG_TOTAL_PAINT);
			else if (screen_mode==MD_ECRAN_TDV2)    tdv.debug2(DEBUG_TOTAL_PAINT);
			else if (screen_mode==MD_ECRAN_SERVO)   srv_debug(DEBUG_TOTAL_PAINT);
			else if (screen_mode==MD_ECRAN_HORO_R)  horo_debug_r(DEBUG_TOTAL_PAINT);
			else if (screen_mode==MD_ECRAN_VIB)     vib_debug(DEBUG_TOTAL_PAINT);
			else if (screen_mode==MD_ECRAN_TRAIN1   || screen_mode==MD_ECRAN_TRAIN2)   train.debug( DEBUG_TOTAL_PAINT);
			else if (screen_mode==MD_ECRAN_CANTON1  || screen_mode==MD_ECRAN_CANTON2)  canton.debug(DEBUG_TOTAL_PAINT);
			else if (screen_mode==MD_ECRAN_VITMAX1  || screen_mode==MD_ECRAN_VITMAX2)  balauto.debug_vitmax(DEBUG_TOTAL_PAINT);
			else if (screen_mode==MD_ECRAN_HALTE1   || screen_mode==MD_ECRAN_HALTE2)   balauto.debug_halt(DEBUG_TOTAL_PAINT);
			else if (screen_mode==MD_ECRAN_POSLOC1  || screen_mode==MD_ECRAN_POSLOC2)  train.debug2(DEBUG_TOTAL_PAINT);
			else if (screen_mode==MD_ECRAN_ITI1     || screen_mode==MD_ECRAN_ITI2)     iti.debug(DEBUG_TOTAL_PAINT);
			else if (screen_mode==MD_ECRAN_AIG1     || screen_mode==MD_ECRAN_AIG2)     aig_debug(DEBUG_TOTAL_PAINT);
			else if (screen_mode==MD_ECRAN_SEPARE1  || screen_mode==MD_ECRAN_SEPARE2)  iti.debug2(DEBUG_TOTAL_PAINT);
			else if (screen_mode>=MD_ECRAN_SELECT1  && screen_mode<=MD_ECRAN_SELECT3)  selectif.debug(DEBUG_TOTAL_PAINT);
			else if (screen_mode>=MD_ECRAN_AIGAUTO1 && screen_mode<=MD_ECRAN_AIGAUTO3) aigauto.debug(DEBUG_TOTAL_PAINT);
			else if (screen_mode>=MD_ECRAN_BALAUTO1 && screen_mode<=MD_ECRAN_BALAUTO3) balauto.debug_cant(DEBUG_TOTAL_PAINT);
			else if (screen_mode>=MD_ECRAN_EXE1     && screen_mode<=MD_ECRAN_EXE3)     ThisExe.debug(DEBUG_TOTAL_PAINT);
			else if (screen_mode>=MD_ECRAN_VAR1     && screen_mode<=MD_ECRAN_VAR3)     var_debug(DEBUG_TOTAL_PAINT);
			else if (screen_mode>=MD_ECRAN_DEPL1    && screen_mode<=MD_ECRAN_DEPL7)    deplacement.debug(DEBUG_TOTAL_PAINT);
			else if (screen_mode>=MD_ECRAN_HORO_L1  && screen_mode<=MD_ECRAN_HORO_L7)  horo_debug_l(DEBUG_TOTAL_PAINT);
			// Si c'est un écran du TCO, ne pas faire de "BitBlt(hdc_ori, 0, 0, cx, cy, hMemDC, 0, 0, SRCCOPY)" car on a rien dessiné dans le buffer ;
			if (screen_mode>MD_ECRAN_TCO7) BitBlt(hdc_ori, 0, 0, cx, cy, hMemDC, 0, 0, SRCCOPY); // cx,cy pour tout en gris.
			SelectObject(hMemDC, hOldBmp); DeleteObject(hMemBmp); DeleteDC(hMemDC);
			break;

		case WM_RBUTTONUP:		// Bouton droit de la souris relaché.
			hMemDC  = CreateCompatibleDC(hdc_ori); hMemBmp = CreateCompatibleBitmap(hdc_ori, cx, cy); hOldBmp = SelectObject(hMemDC, hMemBmp);
			x_mouse=LOWORD(lParam); y_mouse=HIWORD(lParam);
			if (screen_mode>=MD_ECRAN_TCO0 && screen_mode<=MD_ECRAN_TCO7) cells_debug(screen_mode,DEBUG_MOUSE_RIGHT_UP);
			SelectObject(hMemDC, hOldBmp); DeleteObject(hMemBmp); DeleteDC(hMemDC);
			break;

		case WM_RBUTTONDOWN:	// Bouton droit de la souris enfoncé.
			hMemDC  = CreateCompatibleDC(hdc_ori); hMemBmp = CreateCompatibleBitmap(hdc_ori, cx, cy); hOldBmp = SelectObject(hMemDC, hMemBmp);
			x_mouse=LOWORD(lParam); y_mouse=HIWORD(lParam);
			if (screen_mode>=MD_ECRAN_TCO0 && screen_mode<=MD_ECRAN_TCO7) cells_debug(screen_mode,DEBUG_MOUSE_RIGHT);
			else if (screen_mode==MD_ECRAN_GARAGE) garage.debug(DEBUG_MOUSE_RIGHT);
			else if (screen_mode==MD_ECRAN_SERIAL) serial_debug(DEBUG_MOUSE_RIGHT);
			else if (screen_mode==MD_ECRAN_TDV1)   tdv.debug(DEBUG_MOUSE_RIGHT);
			else if (screen_mode==MD_ECRAN_TDV2)   tdv.debug2(DEBUG_MOUSE_RIGHT);
			else if (screen_mode==MD_ECRAN_CANTON1 || screen_mode==MD_ECRAN_CANTON2) canton.debug(DEBUG_MOUSE_RIGHT);
			else if (screen_mode==MD_ECRAN_VITMAX1 || screen_mode==MD_ECRAN_VITMAX2) balauto.debug_vitmax(DEBUG_MOUSE_RIGHT);
			else if (screen_mode==MD_ECRAN_HALTE1  || screen_mode==MD_ECRAN_HALTE2)  balauto.debug_halt(DEBUG_MOUSE_RIGHT);
			else if (screen_mode==MD_ECRAN_ITI1    || screen_mode==MD_ECRAN_ITI2)    iti.debug(DEBUG_MOUSE_RIGHT);
			else if (screen_mode==MD_ECRAN_AIG1    || screen_mode==MD_ECRAN_AIG2)    aig_debug(DEBUG_MOUSE_RIGHT);
			else if (screen_mode==MD_ECRAN_SEPARE1 || screen_mode==MD_ECRAN_SEPARE2) iti.debug2(DEBUG_MOUSE_RIGHT);
			else if (screen_mode>=MD_ECRAN_SELECT1  && screen_mode<=MD_ECRAN_SELECT3)  selectif.debug(DEBUG_MOUSE_RIGHT);
			else if (screen_mode>=MD_ECRAN_BALAUTO1 && screen_mode<=MD_ECRAN_BALAUTO3) balauto.debug_cant(DEBUG_MOUSE_RIGHT);
			else if (screen_mode>=MD_ECRAN_AIGAUTO1 && screen_mode<=MD_ECRAN_AIGAUTO3) aigauto.debug(DEBUG_MOUSE_RIGHT);
			else if (screen_mode>=MD_ECRAN_VAR1     && screen_mode<=MD_ECRAN_VAR3)     var_debug(DEBUG_MOUSE_RIGHT);
			else if (screen_mode>=MD_ECRAN_EXE1     && screen_mode<=MD_ECRAN_EXE3)     ThisExe.debug(DEBUG_MOUSE_RIGHT);
			else if (screen_mode>=MD_ECRAN_DEPL1    && screen_mode<=MD_ECRAN_DEPL7)    deplacement.debug(DEBUG_MOUSE_RIGHT);
			else if (screen_mode>=MD_ECRAN_HORO_L1  && screen_mode<=MD_ECRAN_HORO_L7)  horo_debug_l(DEBUG_MOUSE_RIGHT);
			SelectObject(hMemDC, hOldBmp); DeleteObject(hMemBmp); DeleteDC(hMemDC);
			break;

		case WM_LBUTTONUP:	// Bouton de la souris relaché.
			hMemDC  = CreateCompatibleDC(hdc_ori); hMemBmp = CreateCompatibleBitmap(hdc_ori, cx, cy); hOldBmp = SelectObject(hMemDC, hMemBmp);
			x_mouse=LOWORD(lParam); y_mouse=HIWORD(lParam);
			if(screen_mode>=MD_ECRAN_TCO0 && screen_mode<=MD_ECRAN_TCO7) cells_debug(screen_mode,DEBUG_MOUSE_UP);
			SelectObject(hMemDC, hOldBmp); DeleteObject(hMemBmp); DeleteDC(hMemDC);
			break;

		case WM_LBUTTONDOWN:	// Bouton de la souris enfoncé.
			hMemDC  = CreateCompatibleDC(hdc_ori); hMemBmp = CreateCompatibleBitmap(hdc_ori, cx, cy); hOldBmp = SelectObject(hMemDC, hMemBmp);
			x_mouse=LOWORD(lParam); y_mouse=HIWORD(lParam);
			if (screen_mode>=MD_ECRAN_TCO0 && screen_mode<=MD_ECRAN_TCO7) cells_debug(screen_mode,DEBUG_MOUSE);
			else if (screen_mode==MD_ECRAN_HORO_R)  horo_debug_r(DEBUG_MOUSE);
			else if (screen_mode==MD_ECRAN_VIB)     vib_debug(DEBUG_MOUSE);
			else if (screen_mode==MD_ECRAN_GARAGE)  garage.debug(DEBUG_MOUSE);
			else if (screen_mode==MD_ECRAN_SERVO)   srv_debug(DEBUG_MOUSE);
			else if (screen_mode==MD_ECRAN_SERIAL)  serial_debug(DEBUG_MOUSE);
			else if (screen_mode==MD_ECRAN_TDV1)    tdv.debug(DEBUG_MOUSE);
			else if (screen_mode==MD_ECRAN_TDV2)    tdv.debug2(DEBUG_MOUSE);
			else if (screen_mode==MD_ECRAN_CANTON1  || screen_mode==MD_ECRAN_CANTON2)  canton.debug(DEBUG_MOUSE);
			else if (screen_mode==MD_ECRAN_VITMAX1  || screen_mode==MD_ECRAN_VITMAX2)  balauto.debug_vitmax(DEBUG_MOUSE);
			else if (screen_mode==MD_ECRAN_HALTE1   || screen_mode==MD_ECRAN_HALTE2)   balauto.debug_halt(DEBUG_MOUSE);
			else if (screen_mode==MD_ECRAN_TRAIN1   || screen_mode==MD_ECRAN_TRAIN2)   train.debug(DEBUG_MOUSE);
			else if (screen_mode==MD_ECRAN_POSLOC1  || screen_mode==MD_ECRAN_POSLOC2)  train.debug2(DEBUG_MOUSE);
			else if (screen_mode==MD_ECRAN_ITI1     || screen_mode==MD_ECRAN_ITI2)     iti.debug(DEBUG_MOUSE);
			else if (screen_mode==MD_ECRAN_AIG1     || screen_mode==MD_ECRAN_AIG2)     aig_debug(DEBUG_MOUSE);
			else if (screen_mode==MD_ECRAN_SEPARE1  || screen_mode==MD_ECRAN_SEPARE2)  iti.debug2(DEBUG_MOUSE);
			else if (screen_mode>=MD_ECRAN_SELECT1  && screen_mode<=MD_ECRAN_SELECT3)  selectif.debug(DEBUG_MOUSE);
			else if (screen_mode>=MD_ECRAN_BALAUTO1 && screen_mode<=MD_ECRAN_BALAUTO3) balauto.debug_cant(DEBUG_MOUSE);
			else if (screen_mode>=MD_ECRAN_AIGAUTO1 && screen_mode<=MD_ECRAN_AIGAUTO3) aigauto.debug(DEBUG_MOUSE);
			else if (screen_mode>=MD_ECRAN_VAR1     && screen_mode<=MD_ECRAN_VAR3)     var_debug(DEBUG_MOUSE);
			else if (screen_mode>=MD_ECRAN_EXE1     && screen_mode<=MD_ECRAN_EXE3)     ThisExe.debug(DEBUG_MOUSE);
			else if (screen_mode>=MD_ECRAN_DEPL1    && screen_mode<=MD_ECRAN_DEPL7)    deplacement.debug(DEBUG_MOUSE);
			else if (screen_mode>=MD_ECRAN_HORO_L1  && screen_mode<=MD_ECRAN_HORO_L7)  horo_debug_l(DEBUG_MOUSE);
			SelectObject(hMemDC, hOldBmp); DeleteObject(hMemBmp); DeleteDC(hMemDC);
			break;

		case WM_MOUSEMOVE:	// La souris c'est déplacée
		x_mouse_move=LOWORD(lParam); y_mouse_move=HIWORD(lParam);
		break;

// si la fenetre d'édition est ouverte pour la fermer faire  : c_conf_wnd=' '
//
//
		case WM_CHAR:	// On a tapé un caractère. Il doit être traité si un TCO, l'écran RS232 ou la fenêtre de 'debug train' est affiché.
			// La touche 'Esc' permet de revenir à l'affichage des TCO.  (screen_mode_retour = Numéro de l'avant dernier écran TCO affiché).
			touche_char=LOWORD(wParam);
			if (touche_char=='\x1b') {	// '\x1b' = Caractère Echappement = Escape.
				if (c_conf_wnd!=' ') { c_conf_wnd=' '; break; } // On ferme la fenêtre d'édition en cours.
				screen_mode= screen_mode_retour; 
				break;
			}
			hMemDC = CreateCompatibleDC(hdc_ori); hMemBmp = CreateCompatibleBitmap(hdc_ori, cx, cy); hOldBmp = SelectObject(hMemDC, hMemBmp); // Ligne déplacée en V6.a
			if (screen_mode == MD_ECRAN_TRAIN1 || screen_mode == MD_ECRAN_TRAIN2) train.debug(DEBUG_KEY);
			else if (screen_mode==MD_ECRAN_SERIAL) serial_debug(DEBUG_KEY);
			else if (screen_mode>=MD_ECRAN_TCO0 && screen_mode<=MD_ECRAN_TCO7) cells_debug(screen_mode,DEBUG_KEY);
			ok=1;
			if (screen_mode==MD_ECRAN_SERIAL) ok=0;
			else if (screen_mode>=MD_ECRAN_TCO0 && screen_mode<=MD_ECRAN_TCO7 && c_conf_wnd!=' ') ok=0;
			else if ((screen_mode==MD_ECRAN_TRAIN1 || screen_mode==MD_ECRAN_TRAIN2) && train.entry!=-1) ok=0;
			if (ok) { // Un TCO est affiché, sans autre fenêtre ?
				pot_vir_debug(DEBUG_KEY);	// Oui. Commande la vitesse des trains au clavier.
				// Touches pour un accès direct vers un écran.
				if (touche_char - '0' >= 0 && touche_char - '0' <= 7)  { screen_mode = MD_ECRAN_TCO0 + touche_char - '0'; screen_mode_retour = screen_mode; }
				if ((touche_char == 224) || (touche_char == 178)) { screen_mode = MD_ECRAN_TCO0; screen_mode_retour = screen_mode; }  // = à ou ²
				if (touche_char == 38)  { screen_mode = MD_ECRAN_TCO1; screen_mode_retour = screen_mode; }  // = &
				if (touche_char == 233) { screen_mode = MD_ECRAN_TCO2; screen_mode_retour = screen_mode; }  // = é
				if (touche_char == 34)  { screen_mode = MD_ECRAN_TCO3; screen_mode_retour = screen_mode; }  // = "
				if (touche_char == 39)  { screen_mode = MD_ECRAN_TCO4; screen_mode_retour = screen_mode; }  // = '
				if (touche_char == 40)  { screen_mode = MD_ECRAN_TCO5; screen_mode_retour = screen_mode; }  // = (
				if (touche_char == 45)  { screen_mode = MD_ECRAN_TCO6; screen_mode_retour = screen_mode; }  // = -
				if (touche_char == 232) { screen_mode = MD_ECRAN_TCO7; screen_mode_retour = screen_mode; }  // = è

				if (touche_char == 95 || touche_char == '8')  {
					screen_mode = MD_ECRAN_TRAIN1;   // = _
					PostMessage(hwnd, WM_PAINT, 0, 0); // Pour provoquer un réaffichage de la fenêtre appelée (Impose "action" = DEBUG_TOTAL_PAINT).
				}
				if (touche_char == 231 || touche_char == '9') {
					screen_mode = MD_ECRAN_HORO_L1;  // = ç
					PostMessage(hwnd, WM_PAINT, 0, 0); // Pour provoquer un réaffichage de la fenêtre appelée (Impose "action" = DEBUG_TOTAL_PAINT).
				}				
				if (touche_char == 41) {
					screen_mode = MD_ECRAN_DEPL1;  // = )
					PostMessage(hwnd, WM_PAINT, 0, 0); // Pour provoquer un réaffichage de la fenêtre appelée (Impose "action" = DEBUG_TOTAL_PAINT).
				}				
				if (touche_char == 61) {
					screen_mode = MD_ECRAN_ITI1;  //  =
					PostMessage(hwnd, WM_PAINT, 0, 0); // Pour provoquer un réaffichage de la fenêtre appelée (Impose "action" = DEBUG_TOTAL_PAINT).
				}				
			}
			SelectObject(hMemDC, hOldBmp); DeleteObject(hMemBmp); DeleteDC(hMemDC);
			break;

		case WM_DESTROY:	// Windows a demandé à UTS de s'arréter.
			cells_save("config_tco.txt");
			for(j=0;j<NB_CARTE;j++) { // V3.5c : On arrête les locos et on éteint les sorties avant de fermer UTS.
				for(i=0;i<NB_CANTON;i++) vio_canton_vit_profil[j][i]=0;
				for(i=0;i<NB_OUT;i++)    vio_out[j][i]=0;
				for(i=0;i<NB_LED;i++)  { vio_led[j][i]=0; vio_led_cli[j][i]=0; vio_led_phase[j][i]=0; }
			}
			serial_card0.maj(); 
			serial_card1.maj();
			serial_card2.maj();
			serial_card3.maj();
			PostQuitMessage(0);
			break;

		case WM_COMMAND:	// On a cliqué sur un élément du menu d'UTS.
			if(LOWORD(wParam)>=CM_ECRAN_TCO0 && LOWORD(wParam)<CM_ECRAN_END) bmp_fond_default();
			if(screen_mode>=MD_ECRAN_TCO0 && screen_mode<=MD_ECRAN_TCO7) screen_mode_retour= screen_mode; // Pour revenir à l'écran précédant avec la touche 'Esc'.
			switch(LOWORD(wParam)) {
				case 999                 : infrarouge=LOWORD(lParam);     break;
				case CM_EXIT             : cells_save("config_tco.txt");  PostQuitMessage(0);  break;
				case CM_ECRAN_TCO0       : screen_mode=MD_ECRAN_TCO0;     screen_mode_retour= screen_mode; break;
				case CM_ECRAN_TCO1       : screen_mode=MD_ECRAN_TCO1;     screen_mode_retour= screen_mode; break;
				case CM_ECRAN_TCO2       : screen_mode=MD_ECRAN_TCO2;     screen_mode_retour= screen_mode; break;
				case CM_ECRAN_TCO3       : screen_mode=MD_ECRAN_TCO3;     screen_mode_retour= screen_mode; break;
				case CM_ECRAN_TCO4       : screen_mode=MD_ECRAN_TCO4;     screen_mode_retour= screen_mode; break;
				case CM_ECRAN_TCO5       : screen_mode=MD_ECRAN_TCO5;     screen_mode_retour= screen_mode; break;
				case CM_ECRAN_TCO6       : screen_mode=MD_ECRAN_TCO6;     screen_mode_retour= screen_mode; break;
				case CM_ECRAN_TCO7       : screen_mode=MD_ECRAN_TCO7;     screen_mode_retour= screen_mode; break;
				case CM_ECRAN_TRAIN1     : screen_mode=MD_ECRAN_TRAIN1;   break;
				case CM_ECRAN_TRAIN2     : screen_mode=MD_ECRAN_TRAIN2;   break;
				case CM_ECRAN_POSLOC1    : screen_mode=MD_ECRAN_POSLOC1;  break;
				case CM_ECRAN_POSLOC2    : screen_mode=MD_ECRAN_POSLOC2;  break;
				case CM_ECRAN_DEPL1      : screen_mode=MD_ECRAN_DEPL1;    break;
				case CM_ECRAN_DEPL2      : screen_mode=MD_ECRAN_DEPL2;    break;
				case CM_ECRAN_DEPL3      : screen_mode=MD_ECRAN_DEPL3;    break;
				case CM_ECRAN_DEPL4      : screen_mode=MD_ECRAN_DEPL4;    break;
				case CM_ECRAN_DEPL5      : screen_mode=MD_ECRAN_DEPL5;    break;
				case CM_ECRAN_DEPL6      : screen_mode=MD_ECRAN_DEPL6;    break;
				case CM_ECRAN_DEPL7      : screen_mode=MD_ECRAN_DEPL7;    break;
				case CM_ECRAN_HORO_R     : screen_mode=MD_ECRAN_HORO_R;   break;
				case CM_ECRAN_HORO_L1    : screen_mode=MD_ECRAN_HORO_L1;  break;
				case CM_ECRAN_HORO_L2    : screen_mode=MD_ECRAN_HORO_L2;  break;
				case CM_ECRAN_HORO_L3    : screen_mode=MD_ECRAN_HORO_L3;  break;
				case CM_ECRAN_HORO_L4    : screen_mode=MD_ECRAN_HORO_L4;  break;
				case CM_ECRAN_HORO_L5    : screen_mode=MD_ECRAN_HORO_L5;  break;
				case CM_ECRAN_HORO_L6    : screen_mode=MD_ECRAN_HORO_L6;  break;
				case CM_ECRAN_HORO_L7    : screen_mode=MD_ECRAN_HORO_L7;  break;
				case CM_ECRAN_VIBRATOR   : screen_mode=MD_ECRAN_VIB;      break;
				case CM_ECRAN_ITI1       : screen_mode=MD_ECRAN_ITI1;     break;
				case CM_ECRAN_ITI2       : screen_mode=MD_ECRAN_ITI2;     break;
				case CM_ECRAN_GARAGE     : screen_mode=MD_ECRAN_GARAGE;   break;
				case CM_ECRAN_AIG1       : screen_mode=MD_ECRAN_AIG1;     break;
				case CM_ECRAN_AIG2       : screen_mode=MD_ECRAN_AIG2;     break;
				case CM_ECRAN_SERIAL     : screen_mode=MD_ECRAN_SERIAL;   break;
				case CM_ECRAN_VAR1       : screen_mode=MD_ECRAN_VAR1;     break;
				case CM_ECRAN_VAR2       : screen_mode=MD_ECRAN_VAR2;     break;
				case CM_ECRAN_VAR3       : screen_mode=MD_ECRAN_VAR3;     break;
				case CM_ECRAN_CANTON1    : screen_mode=MD_ECRAN_CANTON1;  break;
				case CM_ECRAN_CANTON2    : screen_mode=MD_ECRAN_CANTON2;  break;
				case CM_ECRAN_SERVO      : screen_mode=MD_ECRAN_SERVO;    break;
				case CM_ECRAN_TDV1       : screen_mode=MD_ECRAN_TDV1;     break;
				case CM_ECRAN_TDV2       : screen_mode=MD_ECRAN_TDV2;     break;
				case CM_ECRAN_SELECT1    : screen_mode=MD_ECRAN_SELECT1;  break;
				case CM_ECRAN_SELECT2    : screen_mode=MD_ECRAN_SELECT2;  break;
				case CM_ECRAN_SELECT3    : screen_mode=MD_ECRAN_SELECT3;  break;
				case CM_ECRAN_AIGAUTO1   : screen_mode=MD_ECRAN_AIGAUTO1; break;
				case CM_ECRAN_AIGAUTO2   : screen_mode=MD_ECRAN_AIGAUTO2; break;
				case CM_ECRAN_AIGAUTO3   : screen_mode=MD_ECRAN_AIGAUTO3; break;
				case CM_ECRAN_VITMAX1    : screen_mode=MD_ECRAN_VITMAX1;  break;
				case CM_ECRAN_VITMAX2    : screen_mode=MD_ECRAN_VITMAX2;  break;
				case CM_ECRAN_HALTE1     : screen_mode=MD_ECRAN_HALTE1;   break;
				case CM_ECRAN_HALTE2     : screen_mode=MD_ECRAN_HALTE2;   break;
				case CM_ECRAN_BALAUTO1   : screen_mode=MD_ECRAN_BALAUTO1; break;
				case CM_ECRAN_BALAUTO2   : screen_mode=MD_ECRAN_BALAUTO2; break;
				case CM_ECRAN_BALAUTO3   : screen_mode=MD_ECRAN_BALAUTO3; break;
				case CM_ECRAN_EXE1       : screen_mode=MD_ECRAN_EXE1;     break;
				case CM_ECRAN_EXE2       : screen_mode=MD_ECRAN_EXE2;     break;
				case CM_ECRAN_EXE3       : screen_mode=MD_ECRAN_EXE3;     break;
				case CM_ECRAN_SEPARE1    : screen_mode=MD_ECRAN_SEPARE1;  break;
				case CM_ECRAN_SEPARE2    : screen_mode=MD_ECRAN_SEPARE2;  break;
				case CM_A_PROPOS         : MessageBox(NULL,SZ_A_PROPOS,"UTS - A propos",MB_OK|MB_ICONINFORMATION);break;
				case CM_AIDE             : MessageBox(NULL,STR_AIDE,"UTS - Aide",MB_OK|MB_ICONINFORMATION);break;
				case CM_CONNEXION        : {
					ret=serialPort.init();
					if(ret) sprintf_s(szDeconnectee,"COM%d",ret);
					else strcpy(szDeconnectee,"Mode Déconnecté");
					serial_card0.init(0,serialPort.card0_ok);
					serial_card1.init(1,serialPort.card1_ok);
					serial_card2.init(2,serialPort.card2_ok);
					serial_card3.init(3,serialPort.card3_ok);
					break;
					}
				case CM_ECRAN_TCOEDIT    : cells_open_edit();              break;
				case CM_ECRAN_TCORENDER  : cells_open_render();            break;
				case CM_ECRAN_AIDE1      : cells_open_aide();              break;
				case CM_ECRAN_TCOSAVE    : cells_save("config_tco.txt");   break;
				case CM_CONFIG_EDIT      : MessageBox(NULL,STR_INFO_OPEN_CONFIG,"UTS - Info",MB_OK|MB_ICONWARNING);
					ShellExecute(NULL,"open","config.txt", NULL, NULL, SW_SHOWNORMAL);
					break;
				case CM_CONFIG_RELOAD    : MessageBox(NULL,STR_INFO_RELOAD_CONFIG,"UTS - Info",MB_OK|MB_ICONWARNING);
					tdv.init("config.txt");         //tdv.save_conf();
					ThisExe.init("config.txt");     //ThisExe.save_conf();
					vib_init_file("config.txt");
					iti.init("config.txt");         //iti.save_conf();
					horo_init_file("config.txt");   horo_tic_on=0; //horo_save_conf();
					deplacement.init("config.txt"); 
					break;
  				case CM_VARIABLES        : MessageBox(NULL,STR_VARIABLES,"UTS - Liste des variables",MB_OK|MB_ICONINFORMATION);break;
				default                  : break;
		}

		PostMessage(hwnd,WM_PAINT,0,0);		// Pour provoquer un Affichage de la fenêtre appelée (Impose "action" = DEBUG_TOTAL_PAINT).
		break;
		default:         break;
	}
//	ReleaseDC(hwnd,hdc_ori); SelectObject(hMemDC, hOldBmp); DeleteObject(hMemBmp); DeleteDC(hMemDC);
	ReleaseDC(hwnd,hdc_ori);
	return DefWindowProc(hwnd, message, wParam, lParam);
}