
// UTS 2000 - fichier 'ss_prg_aff.cpp' - Divers sous-programmes pour la partie graphique
// V3.7c - Le 22/09/2016
#include <windows.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "Train_UTS.h"

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

//	1 / Déclaration des objets de contexte graphique
//	HDC hMemDC;             = HanDle de Contexte = 
//	HDC h_dc_mem_cells;
//	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;
//
// DECLARATION DES POLICES DE CARACTERES la_fonte(pas utilisée ?), bmp_fonte(standard) et cells_font(dans les bloc des TCO)
// CreateFont(
//	15,10,0,0            //hauteur de la police, largeur, angle global du texte 900=90°, angle de chaque lettre 900=90°
//	400,0,0,0            //epaisseur 400=normal, ?,?,?
//	FW_NORMAL,           //type de gras 'FW_BOLD'
//	FALSE, FALSE, FALSE  // italique, souligné, barré 'TRUE'
//	ANSI_CHARSET,        //type des caractères utilisés (ASCII) 
//	OUT_DEFAULT_PRECIS,  //type d’affichage de la police, Windows choisi une police raisonnable
//	CLIP_DEFAULT_PRECIS, //caractères plus ou moins espacés, Windows choisi une police raisonnable
//	DEFAULT_QUALITY, VARIABLE_PITCH, //	espacement régulier ou non entre les caractères Font)
//
//	HFONT la_fonte;
//	      la_fonte=CreateFont  (15,10,0,0,400,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH|FF_MODERN,"Courier");
//	HFONT bmp_fonte;
//          bmp_fonte=CreateFont (15,10,0,0,400,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH|FF_MODERN,"Courier");
//	HFONT cells_font;
//	      cells_font=CreateFont(10,10,0,0,400,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH|FF_MODERN,"Courier New");
//
// RESERVE DE LA PLACE POUR LES OBJETS GRAPHIQUES
//	Couleur = bmp_stylo_gris = CreatePen(PS_SOLID,1,RGB(192,192,192));...
//	HPEN   bmp_stylo_gris192, bmp_stylo_jaune...;
//
//    Pinceaux = bmp_pinceau_gris = CreateSolidBrush(RGB(192,192,192));...
//	HBRUSH bmp_pinceau_gris192, bmp_pinceau_jaune...;
//
//	int bmp_rgb_color[9][3]={ {  0,  0,  0}, {  0,  0,255}, {  0,255,  0}...
//	unsigned long  bmp_rgb[9]={ RGB(  0,  0,  0), RGB(  0,  0,255), RGB(  0,255,  0)...
//
//    SelectObject(h_dc_mem_cells,cells_font);   Applique la fonte 'cells_font' au 'h_dc_mem_cells' de texte.
//    SetBkMode(h_dc_mem_cells,TRANSPARENT);     Permet au texte d'avoir un fond transparent.
//    SetTextColor(h_dc_mem_cells,RGB(0,0,128)); Applique la couleur 'RGB(0,0,128)' de texte au dc 'SetTextColor'.
//    TextOut(h_dc_mem_cells,x,y,szTemp,4);      Affichage du texte (dc, X, Y, chaine, longueur de chaine).


// Déclaration de diverses fonctions externes
extern int get_line(FILE*, char [][CHAR_CONFIG_NB], int*);

// Déclaration de diverses fonctions générales pour le graphisme
extern void bmp_select_pen(int no_color);
extern void bmp_select_brush(int no_color);
extern void bmp_select_pen(HDC h_dc_,int no_color);
extern void bmp_select_brush(HDC h_dc_,int no_color);


// Déclaration des variables externes
extern int moins_char_normal;   // 1: - est un caractere normal (comme 0)  0: - est un separateur (comme +)
extern HDC   hMemDC;
extern HFONT la_fonte;
extern HFONT cells_font;
extern HFONT aide_font;
extern HDC h_dc_mem_cells;
extern HPEN      bmp_stylo_noir, bmp_stylo_bleu, bmp_stylo_vert, bmp_stylo_cyan, bmp_stylo_rouge, bmp_stylo_violet, bmp_stylo_jaune, bmp_stylo_blanc;
extern HPEN      bmp_stylo_gris128, bmp_stylo_gris192, bmp_stylo_orange, bmp_stylo_marron, bmp_stylo_kaki, bmp_stylo_bleuf, bmp_stylo_grisvert, bmp_stylo_vertfonce;

extern int rendu[RENDU_TAILLE];
extern int color_train[NB_TRAIN];

extern int vio_det[NB_CARTE][NB_CANTON];
extern int color_canton[NB_CARTE][NB_CANTON];
extern int copy_res_auto[NB_CARTE][NB_CANTON];
extern int copy_num_train[NB_CARTE][NB_CANTON];
extern int copy_master_selectif[NB_CARTE][NB_CANTON];
extern int copy_update_selectif[NB_CARTE][NB_CANTON];
extern int cfg_relief;

//--------------------------------------------------------------------------------------------------
// Sous-programme pour écrire un texte à l'écran
//    EasyTextOut(position X, position Y, chaine de caractères)
//
void EasyTextOut(int x, int y, char* sz)
{
	TextOut(hMemDC,x,y,sz,strlen(sz));
}


//--------------------------------------------------------------------------------------------------
// Sous-programme pour dessiner une ligne à l'écran
//    EasyLine(position départ X, position départ Y, position arrivée X, position arrivée Y)
//
void EasyLine(int x1, int y1, int x2, int y2)
{ 
	MoveToEx(hMemDC,x1,y1,NULL); LineTo(hMemDC,x2,y2);
}


//--------------------------------------------------------------------------------------------------
// Sous-programme pour initialiser les caractèristiques des fonctions graphiques
//    init_fonte_pen_brush()
//
// Font 'aide_font' pour la fenêtre d'aide sur les variables. Cette police plus grande est plus lisible.
//
void init_fonte_pen_brush(void)
{
	//* CreateFont(nHeight, nWidth, nEscapement, nOrientation, nWeight, bItalic, bUnderline, cStrikeOut, nCharSet, nOutPrecision, nClipPrecision, nQuality, nPitchAndFamily, lpszFacename
	la_fonte=CreateFont(15,10,0,0,400,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH|FF_MODERN,"Courier");
	//cells_font=CreateFont(10,10,0,0,400,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,1,"Terminal");
	cells_font=CreateFont(10,10,0,0,400,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH|FF_MODERN,"Courier New");
	aide_font=CreateFont(15,10,0,0,400,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH|FF_MODERN,"Courier");
}

// Sous-programme pour sélectionner la couleur des rails d'un bloc de TCO en fonction de l'état du canton
// et des paramètres de rendu.
//    rendu_select_pen_for_canton(numéro_du_canton)
//
void rendu_select_pen_for_canton(int c)
{
    int color;

    SelectObject(h_dc_mem_cells,bmp_stylo_noir); // Couleur par défaut.
    if(c!=-1)
    {
        if(     copy_res_auto[c/100][c%100] && vio_det[c/100][c%100]==0) color=rendu[RENDU_COLOR_RAIL_AUTOPREV];
        else if(copy_res_auto[c/100][c%100] && vio_det[c/100][c%100]==1) color=rendu[RENDU_COLOR_RAIL_AUTOOCC];
        else if(copy_master_selectif[c/100][c%100]                     ) color=rendu[RENDU_COLOR_RAIL_SELOCC];
        else if(copy_update_selectif[c/100][c%100]                     ) color=rendu[RENDU_COLOR_RAIL_SELPREV];
        else if(                               vio_det[c/100][c%100]==1) color=rendu[RENDU_COLOR_RAIL_OCC];
        else   /*                              vio_det[c/100][c%100]==0*/color=rendu[RENDU_COLOR_RAIL_LIBRE];
// Si le numéro de rendu = BMP_CST_COLOR_TRAIN on prendre la couleur du train.
//                       = BMP_CST_COLOR_CANTON on prendre la couleur du canton.
        if(color==BMP_CST_COLOR_TRAIN)  if(copy_num_train[c/100][c%100]!=-1) color=color_train[copy_num_train[c/100][c%100]];
        if(color==BMP_CST_COLOR_CANTON) if(c!=1) color=color_canton[c/100][c%100];  // Pourquoi c!=1 ????
        bmp_select_pen(color);
    }
}


// Sous-programme pour sélectionner la couleur de fond d'un bloc de TCO en fonction de l'état du canton
// et des paramètres de rendu.
//    rendu_select_brush_for_canton(numéro_du_canton)
//
int rendu_select_brush_for_canton(int c)
{
    int color;

    bmp_select_brush(rendu[RENDU_COLOR_FOND_RAIL]); // Couleur par défaut.
	color = -1;
    if(c!=-1)
	{
        if(     copy_res_auto[c/100][c%100] && vio_det[c/100][c%100]==0) color=rendu[RENDU_COLOR_FOND_AUTOPREV];
        else if(copy_res_auto[c/100][c%100] && vio_det[c/100][c%100]==1) color=rendu[RENDU_COLOR_FOND_AUTOOCC];
        else if(copy_master_selectif[c/100][c%100]                     ) 
			{if (cfg_relief > 0 )  color=BMP_CST_COLOR_GRISWIN; else color=rendu[RENDU_COLOR_FOND_SELOCC];}
        else if(copy_update_selectif[c/100][c%100]                     ) color=rendu[RENDU_COLOR_FOND_SELPREV];
        else if(                               vio_det[c/100][c%100]==1) color=rendu[RENDU_COLOR_FOND_OCC];
        else                                 /*vio_det[c/100][c%100]==0*/
			{if (cfg_relief > 0 ) color=BMP_CST_COLOR_GRISWIN; else color=rendu[RENDU_COLOR_FOND_LIBRE];}
// Si le numéro de rendu = BMP_CST_COLOR_TRAIN on prendre la couleur du train.
//                       = BMP_CST_COLOR_CANTON on prendre la couleur du canton.
        if(color==BMP_CST_COLOR_TRAIN) if(copy_num_train[c/100][c%100]!=-1) color=color_train[copy_num_train[c/100][c%100]];
        if(color==BMP_CST_COLOR_CANTON) if(c!=1) color=color_canton[c/100][c%100];  // Pourquoi c!=1 ????
        bmp_select_brush(color);
    }
	return color;
}




// Sous-programme qui retourne '1' si l'on doit afficher les flèches dans les blocs dans les TCO.
//    rendu_need_fleche(numéro_du_canton)
//
int rendu_need_fleche(int c)
{
    int r;
    r=0; 		// Par défaut on n'affiche pas les flèches.
    if(c!=-1) {
        if(     copy_res_auto[c/100][c%100] && vio_det[c/100][c%100]==0) r=rendu[RENDU_USE_FLECHE_AUTOPREV];
        else if(copy_res_auto[c/100][c%100] && vio_det[c/100][c%100]==1) r=rendu[RENDU_USE_FLECHE_AUTOOCC];
        else if(copy_master_selectif[c/100][c%100]                     ) r=rendu[RENDU_USE_FLECHE_SELOCC];
        else if(copy_update_selectif[c/100][c%100]                     ) r=rendu[RENDU_USE_FLECHE_SELPREV];
        else if(                               vio_det[c/100][c%100]==1) r=rendu[RENDU_USE_FLECHE_OCC];
        else                                 /*vio_det[c/100][c%100]==0*/r=rendu[RENDU_USE_FLECHE_LIBRE];
    }
	return r;
}


// Sous-programme qui retourne '1' si l'on doit afficher un trait épais dans les blocs dans les TCO.
//    rendu_need_grostrait(numéro_du_canton)
//
int rendu_need_grostrait(int c)
{
	int r;
	r=0; 		// Par défaut on affiche 'rendu[RENDU_USE_GROS_LIBRE]'.
	if(c!=-1) {
		if(     copy_res_auto[c/100][c%100] && vio_det[c/100][c%100]==0) r=rendu[RENDU_USE_GROS_AUTOPREV];
		else if(copy_res_auto[c/100][c%100] && vio_det[c/100][c%100]==1) r=rendu[RENDU_USE_GROS_AUTOOCC];
		else if(copy_master_selectif[c/100][c%100]                     ) r=rendu[RENDU_USE_GROS_SELOCC];
		else if(copy_update_selectif[c/100][c%100]                     ) r=rendu[RENDU_USE_GROS_SELPREV];
		else if(                               vio_det[c/100][c%100]==1) r=rendu[RENDU_USE_GROS_OCC];
		else                                 /*vio_det[c/100][c%100]==0*/r=rendu[RENDU_USE_GROS_LIBRE];
	}
	return r;
}


// Sous-programme pour afficher une flèches sur les rails dans les blocs dans les TCO (40 * 40 pixels).
// Les directions = ("N","E","O","S","NO","NE","SO","SE")
// Exemple pour "N" :
//        0,0 =.---------+        
//             |    ^    |
//             |         |
//             |         |
//             +---------+        
//    draw_fleche(Direction de la flèche, Position X, PositionY)
//
void draw_fleche(char* sz, int x, int y)
{
    if(STR_SAME stricmp(sz,"N")) { MoveToEx(h_dc_mem_cells,x+17,y+3 ,NULL); LineTo(h_dc_mem_cells,CELLS_N); 
		LineTo(h_dc_mem_cells,x+23,y+3 ); LineTo(h_dc_mem_cells,x+17,y+3 ); }
    if(STR_SAME stricmp(sz,"S")) { MoveToEx(h_dc_mem_cells,x+17,y+37,NULL); LineTo(h_dc_mem_cells,CELLS_S); 
		LineTo(h_dc_mem_cells,x+23,y+37); LineTo(h_dc_mem_cells,x+17,y+37); }
    if(STR_SAME stricmp(sz,"O")) { MoveToEx(h_dc_mem_cells,x+3 ,y+17,NULL); LineTo(h_dc_mem_cells,CELLS_O); 
		LineTo(h_dc_mem_cells,x+3 ,y+23); LineTo(h_dc_mem_cells,x+3 ,y+17); }
    if(STR_SAME stricmp(sz,"E")) { MoveToEx(h_dc_mem_cells,x+37,y+17,NULL); LineTo(h_dc_mem_cells,CELLS_E); 
		LineTo(h_dc_mem_cells,x+37,y+23); LineTo(h_dc_mem_cells,x+37,y+17); }
                                                                                                     
    if(STR_SAME stricmp(sz,"NO")){ MoveToEx(h_dc_mem_cells,x+1 ,y+5 ,NULL); LineTo(h_dc_mem_cells,CELLS_NO); 
		LineTo(h_dc_mem_cells,x+5 ,y+1 ); LineTo(h_dc_mem_cells,x+1 ,y+5 ); }
    if(STR_SAME stricmp(sz,"NE")){ MoveToEx(h_dc_mem_cells,x+39,y+5 ,NULL); LineTo(h_dc_mem_cells,CELLS_NE); 
		LineTo(h_dc_mem_cells,x+34,y+1 ); LineTo(h_dc_mem_cells,x+39,y+5 ); }
    if(STR_SAME stricmp(sz,"SO")){ MoveToEx(h_dc_mem_cells,x+1 ,y+34,NULL); LineTo(h_dc_mem_cells,CELLS_SO); 
		LineTo(h_dc_mem_cells,x+5 ,y+39); LineTo(h_dc_mem_cells,x+1 ,y+34); }
    if(STR_SAME stricmp(sz,"SE")){ MoveToEx(h_dc_mem_cells,x+39,y+34,NULL); LineTo(h_dc_mem_cells,CELLS_SE); 
		LineTo(h_dc_mem_cells,x+34,y+39); LineTo(h_dc_mem_cells,x+39,y+34); }
}


// Sous-programme de lecture de 'config.txt' pour retrouver la taille de la fenêtre Windows à ouvrir
// dans la section '#general' recherche du texte : 'resolution_ecran x y'.
// La taille maximale utilisable du TCO = 32 * 25 cases :
//	  - dimx=32*40+10; // Dimension horizontale maximum = 32 bloc + bordures.
//	  - dimy=25*40+50; // Dimension verticale maximum = 25 bloc + bordures + barre de menu + titre de la fenêtre.
//
// Ne mofifie pas les paramètres 'dimx' et 'dimy' si la directive 'resolution_ecran' n'est pas trouvée.
// Ne mofifie pas le paramètre 'relief' si la directive 'relief' n'est pas trouvée.
//
void ecran_init_file(char filename[], int *dimx, int *dimy, int *plein_ecran)
{
    FILE* pf;
    char ch[CHAR_CONFIG_NB], ch_tab[BLOC_CONFIG_NB][CHAR_CONFIG_NB],ch_error[200];
    int  ch_nb,i;

	*plein_ecran=0;
    if((pf=fopen(filename,"rt"))==NULL){
        MessageBox(NULL,"Impossible d'ouvrir le fichier de configuration général 'Config.txt'","Erreur",MB_OK|MB_ICONERROR); exit(1);
	}

	while(fscanf(pf,"%s%*[^\n]\n",ch)!=EOF) {	// " %s" => "%s%*[^\n]\n" = Nouvelle formule au 02/03/2012, lit uniquement le permier mot de chaque ligne.
		if(STR_SAME strcmp(ch,"#general")) {
            fscanf(pf," %s",ch); // Passe le '['.
            while(get_line(pf,ch_tab,&ch_nb)) {
				if(ch_nb>=BLOC_CONFIG_NB)	{
					MessageBox(NULL,"Le fichier 'config.txt' comporte une ligne trop complexe dans la section '#general'","Erreur",MB_OK|MB_ICONERROR);
					MessageBox(NULL,"Section '#general' (ligne>75 blocs) commençant par (taper sur Entrée) : ","Erreur",MB_OK|MB_ICONERROR);
					strcpy(ch_error,"Section #general Erreur ligne :");
				    for(i=0;i<ch_nb;i++) { strcat(ch_error,"  "); strcat(ch_error,ch_tab[i]); }
	                MessageBox(NULL,ch_error,"UTS - Erreur",MB_OK|MB_ICONERROR); exit(1); 
				}
				if(ch_tab[0][0]==']') break;			// Fin de la section #general
                for(i=0;i<ch_nb;i++) if(ch_tab[i][0]=='@') ch_nb=i;  //remove comments
				if(ch_nb>=3) {
					if(STR_SAME stricmp(ch_tab[0],"resolution_ecran")) { // resolution_ecran dimension_horizontal dimension_verticale
						if (!strncmp(ch_tab[1],"plein",5) && (!strncmp(ch_tab[2],"ecran",5) || !strncmp(ch_tab[2],"écran",5))) {
							*dimx=800; *dimy=700; *plein_ecran=1; // Affichage plein écran.
						}
						else {
							*dimx = max(800,atoi(ch_tab[1]));	// dimensions minimum 800 * 700.
							*dimy = max(700,atoi(ch_tab[2]));
						}
					}
				}
                if (ch_nb>=2) if (STR_SAME stricmp(ch_tab[0],"relief"))  if (!stricmp(ch_tab[1],"off")) cfg_relief=0;
			}	// While (get_line) fin de la ligne de texte.
			break; // Pour sortir de la lecture de la suite du fichier.
		}		// if(==#general)   fin description '#general'.
	}			// While (scanf)    fin du fichier 'config.txt'.
	moins_char_normal=1;		// '-' est un caractère normal, comme '+'.
	fclose(pf);
}





// Sous-programme pour dessiner un cadre rectangulaire.
//    cadre_relief (Position X1, Position Y1, Position X2, Position Y2, Enfonce, Couleur).
//    Le relief dépend de la variable 'relief'. 0 = pas de relief, 1,2,3,... = relief.
// Le bouton est dessiné
//    Si Enfonce =  0  Dépassant, bordure normale = 2 traits.
//    Si Enfonce =  1  Enfoncé,   bordure normale = 2 traits.
//    Si Enfonce = -1  Sans relief. Dans ce cas il faut définir la couler du cadre avant d'appeler cette fonction. Ex : bmp_select_pen(BMP_CST_COLOR_GRIS64);
//    Si Enfonce = 10  Dépassant  bordure fine = 1 trait. gris + gris foncé
//    Si Enfonce = 11  Enfoncé,   bordure fine = 1 trait. gris + gris foncé
//    Si Enfonce = 20  Dépassant  bordure fine = 1 trait. blanc + gris clair
//    Si Enfonce = 21  Enfoncé,   bordure fine = 1 trait. blanc + gris clair
//    Si couleur != -1 le rectangle est colorié de cette couleur, sinon on utilise bmp_select_pen(en cours).
//
//    x1,y1 = position de l'angle en haut à gauche,   x2,y2 = position de l'angle en bas à droite
//
void cadre_relief(int x1,int y1, int x2,int y2, int enfonce1, int couleur1)
{
	if (couleur1 != -1 ) { bmp_select_brush(couleur1); Rectangle(h_dc_mem_cells,x1,y1,x2+1,y2+1); }
	if (cfg_relief > 0 && enfonce1!= -1 ) {
		if (enfonce1 == 1 ) { // Cadre en relief normal, bouton enfoncé (bas).
			bmp_select_pen(BMP_CST_COLOR_BLANC);
			MoveToEx(h_dc_mem_cells,x2,y1,NULL); LineTo(h_dc_mem_cells,x2,y2); LineTo(h_dc_mem_cells,x1-1,y2);
		    bmp_select_pen(BMP_CST_COLOR_GRIS192);
			MoveToEx(h_dc_mem_cells,x2-1,y1+1,NULL); LineTo(h_dc_mem_cells,x2-1,y2-1); LineTo(h_dc_mem_cells,x1,y2-1);
			bmp_select_pen(BMP_CST_COLOR_GRIS64);
			MoveToEx(h_dc_mem_cells,x1,y2-1,NULL); LineTo(h_dc_mem_cells,x1,y1); LineTo(h_dc_mem_cells,x2,y1);
			bmp_select_pen(BMP_CST_COLOR_GRIS128);
			MoveToEx(h_dc_mem_cells,x1+1,y2-2,NULL); LineTo(h_dc_mem_cells,x1+1,y1+1); LineTo(h_dc_mem_cells,x2-1,y1+1);
		}
		else if (enfonce1 == 0 ){ // Cadre en relief normal, bouton relaché (haut).
			bmp_select_pen(BMP_CST_COLOR_GRIS64);
			MoveToEx(h_dc_mem_cells,x2,y1,NULL); LineTo(h_dc_mem_cells,x2,y2); LineTo(h_dc_mem_cells,x1-1,y2);
		    bmp_select_pen(BMP_CST_COLOR_GRIS128);
			MoveToEx(h_dc_mem_cells,x2-1,y1+1,NULL); LineTo(h_dc_mem_cells,x2-1,y2-1); LineTo(h_dc_mem_cells,x1,y2-1);
			bmp_select_pen(BMP_CST_COLOR_BLANC);
			MoveToEx(h_dc_mem_cells,x1,y2-1,NULL); LineTo(h_dc_mem_cells,x1,y1); LineTo(h_dc_mem_cells,x2,y1);
			bmp_select_pen(BMP_CST_COLOR_GRIS192);
			MoveToEx(h_dc_mem_cells,x1+1,y2-2,NULL); LineTo(h_dc_mem_cells,x1+1,y1+1); LineTo(h_dc_mem_cells,x2-1,y1+1);
		}
		else if (enfonce1 == 11 ){ // Cadre en faible relief, bouton enfoncé (bas). gris + gris foncé
			bmp_select_pen(BMP_CST_COLOR_GRIS128);
			MoveToEx(h_dc_mem_cells,x2-1,y1+1,NULL); LineTo(h_dc_mem_cells,x2-1,y2-1); LineTo(h_dc_mem_cells,x1,y2-1);
			bmp_select_pen(BMP_CST_COLOR_GRIS64);
			MoveToEx(h_dc_mem_cells,x1+1,y2-2,NULL); LineTo(h_dc_mem_cells,x1+1,y1+1); LineTo(h_dc_mem_cells,x2-1,y1+1);
		}
		else if (enfonce1 == 10 ){ // Cadre en faible relief, bouton relaché (haut). gris + gris foncé
			bmp_select_pen(BMP_CST_COLOR_GRIS128);
			MoveToEx(h_dc_mem_cells,x1+1,y2-2,NULL); LineTo(h_dc_mem_cells,x1+1,y1+1); LineTo(h_dc_mem_cells,x2-1,y1+1);
			bmp_select_pen(BMP_CST_COLOR_GRIS64);
			MoveToEx(h_dc_mem_cells,x2-1,y1+1,NULL); LineTo(h_dc_mem_cells,x2-1,y2-1); LineTo(h_dc_mem_cells,x1,y2-1);
		}
		else if (enfonce1 == 21 ){ // Cadre en faible relief, bouton enfoncé (bas). blanc + gris clair
			bmp_select_pen(BMP_CST_COLOR_GRIS128);
			MoveToEx(h_dc_mem_cells,x1+1,y2-2,NULL); LineTo(h_dc_mem_cells,x1+1,y1+1); LineTo(h_dc_mem_cells,x2-1,y1+1);
			bmp_select_pen(BMP_CST_COLOR_BLANC);
			MoveToEx(h_dc_mem_cells,x2-1,y1+1,NULL); LineTo(h_dc_mem_cells,x2-1,y2-1); LineTo(h_dc_mem_cells,x1,y2-1);
		}
		else if (enfonce1 == 20 ){ // Cadre en faible relief, bouton relaché (haut). blanc + gris clair
			bmp_select_pen(BMP_CST_COLOR_BLANC);
			MoveToEx(h_dc_mem_cells,x1+1,y2-2,NULL); LineTo(h_dc_mem_cells,x1+1,y1+1); LineTo(h_dc_mem_cells,x2-1,y1+1);
			bmp_select_pen(BMP_CST_COLOR_GRIS128);
			MoveToEx(h_dc_mem_cells,x2-1,y1+1,NULL); LineTo(h_dc_mem_cells,x2-1,y2-1); LineTo(h_dc_mem_cells,x1,y2-1);
		}
	}
	else { // Cadre normal sans relief.
		MoveToEx(h_dc_mem_cells,x1,y1,NULL); LineTo(h_dc_mem_cells,x2,y1); LineTo(h_dc_mem_cells,x2,y2);
		LineTo(h_dc_mem_cells,x1,y2);  LineTo(h_dc_mem_cells,x1,y1);
	}
return;
}


// Sous-programme pour dessiner un cadre circulaire.
//    cadre_cercle_relief (Position X1, Position Y1, Rayon, Enfonce, Couleur1_intérieure, Couleur2_extérieur).
//    Le relief dépend de la variable 'relief'. 0 = pas de relief, 1,2,3,... = relief.
// Le bouton est dessiné
//    Si Enfonce =  0 Dépassant, bordure normale = 2 traits.
//    Si Enfonce =  1 Enfoncé,   bordure normale = 2 traits.
//    Si Enfonce = -1 Sans relief.
//    Si Enfonce = 10 Dépassant, bordure fine = 1 trait. gris + gris foncé
//    Si Enfonce = 11 Enfoncé,   bordure fine = 1 trait. gris + gris foncé
//    Si Enfonce = 20 Dépassant, bordure fine = 1 trait. blanc + gris clair
//    Si Enfonce = 21 Enfoncé,   bordure fine = 1 trait. blanc + gris clair
//    Si Couleur1 = -2, ne dessine que le bord du cercle.
// Les couleurs
//    Si Couleur1 = couleur intérieur du cercle
//    Si Couleur2 = couleur du bord du cercle
//    Si Couleur1 (ou Couleur2) = -1, la couleur utilisée est celle en cours.
//
//    x1,y1 = milieu du cercle,   r1 = rayon

void cadre_cercle_relief(int x1,int y1, int r1, int enfonce1, int couleur_int1, int couleur_ext2)
{
	float angle1= 45;
	float angle2=135;  // =90+angle1.
	if ( r1 < 1 ) return;
	if ( cfg_relief > 0 ) bmp_select_pen(BMP_CST_COLOR_GRIS128); // Pour éviter d'avoir des points noirs (noirs->gris moins voyants) sur les cotés en cas de relief.
	if ( couleur_int1 != -1 ) bmp_select_brush(couleur_int1);
	if ( couleur_ext2 != -1 ) bmp_select_pen(couleur_ext2);
	if ( couleur_int1 != -2 ) Ellipse(h_dc_mem_cells, x1-r1, y1-r1, x1+r1+1, y1+r1+1);  // x2y2+1 pour avoir un cercle parfait.
	if ( cfg_relief > 0 && enfonce1 != -1 ) {
		if (enfonce1 == 1 ) { // Cadre en relief normal, bouton enfoncé (bas).
			bmp_select_pen(BMP_CST_COLOR_GRIS128);
			MoveToEx(h_dc_mem_cells,x1-r1,y1,NULL); AngleArc(h_dc_mem_cells,x1,y1,r1,180,-angle2);
			MoveToEx(h_dc_mem_cells,x1-r1,y1,NULL); AngleArc(h_dc_mem_cells,x1,y1,r1,180,+angle1);
			bmp_select_pen(BMP_CST_COLOR_GRIS192);
			MoveToEx(h_dc_mem_cells,x1+r1,y1,NULL); AngleArc(h_dc_mem_cells,x1,y1,r1,  0,+angle1);
			MoveToEx(h_dc_mem_cells,x1+r1,y1,NULL); AngleArc(h_dc_mem_cells,x1,y1,r1,  0,-angle2);
			r1++;
			bmp_select_pen(BMP_CST_COLOR_GRIS64);
			MoveToEx(h_dc_mem_cells,x1-r1,y1,NULL); AngleArc(h_dc_mem_cells,x1,y1,r1,180,-angle2);
			MoveToEx(h_dc_mem_cells,x1-r1,y1,NULL); AngleArc(h_dc_mem_cells,x1,y1,r1,180,+angle1);
			bmp_select_pen(BMP_CST_COLOR_BLANC);
			MoveToEx(h_dc_mem_cells,x1+r1,y1,NULL); AngleArc(h_dc_mem_cells,x1,y1,r1,  0,+angle1);
			MoveToEx(h_dc_mem_cells,x1+r1,y1,NULL); AngleArc(h_dc_mem_cells,x1,y1,r1,  0,-angle2);
		}
		else if (enfonce1 == 0 ){ // Cadre en relief normal, bouton relaché (haut).
			bmp_select_pen(BMP_CST_COLOR_GRIS192);
			MoveToEx(h_dc_mem_cells,x1-r1,y1,NULL); AngleArc(h_dc_mem_cells,x1,y1,r1,180,-angle2);
			MoveToEx(h_dc_mem_cells,x1-r1,y1,NULL); AngleArc(h_dc_mem_cells,x1,y1,r1,180,+angle1);
			bmp_select_pen(BMP_CST_COLOR_GRIS128);
			MoveToEx(h_dc_mem_cells,x1+r1,y1,NULL); AngleArc(h_dc_mem_cells,x1,y1,r1,  0,+angle1);
			MoveToEx(h_dc_mem_cells,x1+r1,y1,NULL); AngleArc(h_dc_mem_cells,x1,y1,r1,  0,-angle2);
			r1++;
			bmp_select_pen(BMP_CST_COLOR_BLANC);
			MoveToEx(h_dc_mem_cells,x1-r1,y1,NULL); AngleArc(h_dc_mem_cells,x1,y1,r1,180,-angle2);
			MoveToEx(h_dc_mem_cells,x1-r1,y1,NULL); AngleArc(h_dc_mem_cells,x1,y1,r1,180,+angle1);
			bmp_select_pen(BMP_CST_COLOR_GRIS64);
			MoveToEx(h_dc_mem_cells,x1+r1,y1,NULL); AngleArc(h_dc_mem_cells,x1,y1,r1,  0,+angle1);
			MoveToEx(h_dc_mem_cells,x1+r1,y1,NULL); AngleArc(h_dc_mem_cells,x1,y1,r1,  0,-angle2);
		}
		else if (enfonce1 == 11 ){ // Cadre en faible relief, bouton enfoncé (bas). gris + gris foncé
			bmp_select_pen(BMP_CST_COLOR_GRIS64);
			MoveToEx(h_dc_mem_cells,x1-r1,y1,NULL); AngleArc(h_dc_mem_cells,x1,y1,r1,180,-angle2);
			MoveToEx(h_dc_mem_cells,x1-r1,y1,NULL); AngleArc(h_dc_mem_cells,x1,y1,r1,180,+angle1);
			bmp_select_pen(BMP_CST_COLOR_GRIS128);
			MoveToEx(h_dc_mem_cells,x1+r1,y1,NULL); AngleArc(h_dc_mem_cells,x1,y1,r1,  0,+angle1);
			MoveToEx(h_dc_mem_cells,x1+r1,y1,NULL); AngleArc(h_dc_mem_cells,x1,y1,r1,  0,-angle2);
		}
		else if (enfonce1 == 10 ){ // Cadre en faible relief, bouton relaché (haut). gris + gris foncé
			bmp_select_pen(BMP_CST_COLOR_GRIS128);
			MoveToEx(h_dc_mem_cells,x1-r1,y1,NULL); AngleArc(h_dc_mem_cells,x1,y1,r1,180,-angle2);
			MoveToEx(h_dc_mem_cells,x1-r1,y1,NULL); AngleArc(h_dc_mem_cells,x1,y1,r1,180,+angle1);
			bmp_select_pen(BMP_CST_COLOR_GRIS64);
			MoveToEx(h_dc_mem_cells,x1+r1,y1,NULL); AngleArc(h_dc_mem_cells,x1,y1,r1,  0,+angle1);
			MoveToEx(h_dc_mem_cells,x1+r1,y1,NULL); AngleArc(h_dc_mem_cells,x1,y1,r1,  0,-angle2);
		}
		else if (enfonce1 == 21 ){ // Cadre en faible relief, bouton enfoncé (bas). blanc + gris clair
			bmp_select_pen(BMP_CST_COLOR_GRIS128);
			MoveToEx(h_dc_mem_cells,x1-r1,y1,NULL); AngleArc(h_dc_mem_cells,x1,y1,r1,180,-angle2);
			MoveToEx(h_dc_mem_cells,x1-r1,y1,NULL); AngleArc(h_dc_mem_cells,x1,y1,r1,180,+angle1);
			bmp_select_pen(BMP_CST_COLOR_BLANC);
			MoveToEx(h_dc_mem_cells,x1+r1,y1,NULL); AngleArc(h_dc_mem_cells,x1,y1,r1,  0,+angle1);
			MoveToEx(h_dc_mem_cells,x1+r1,y1,NULL); AngleArc(h_dc_mem_cells,x1,y1,r1,  0,-angle2);
		}
		else if (enfonce1 == 20 ){ // Cadre en faible relief, bouton relaché (haut). blanc + gris clair
			bmp_select_pen(BMP_CST_COLOR_BLANC);
			MoveToEx(h_dc_mem_cells,x1-r1,y1,NULL); AngleArc(h_dc_mem_cells,x1,y1,r1,180,-angle2);
			MoveToEx(h_dc_mem_cells,x1-r1,y1,NULL); AngleArc(h_dc_mem_cells,x1,y1,r1,180,+angle1);
			bmp_select_pen(BMP_CST_COLOR_GRIS128);
			MoveToEx(h_dc_mem_cells,x1+r1,y1,NULL); AngleArc(h_dc_mem_cells,x1,y1,r1,  0,+angle1);
			MoveToEx(h_dc_mem_cells,x1+r1,y1,NULL); AngleArc(h_dc_mem_cells,x1,y1,r1,  0,-angle2);
		}
	}	
return;
}

// Sous-programme pour dessiner un cadenas avec ou sans relief.
//    cadenas_relief (Position X1, Position Y1).
//    Le relief dépend de la variable globale 'relief'.
//
void cadenas_relief(int x1,int y1)
{
	if (cfg_relief > 0 ) {  // Avec relief.
		bmp_select_pen(BMP_CST_COLOR_NOIR);
		bmp_select_brush(BMP_CST_COLOR_ROUGE);
		Rectangle(h_dc_mem_cells,x1+0,y1+2,x1+6,y1+8);	// Partie du corps en rouge
		Rectangle(h_dc_mem_cells,x1+1,y1+0,x1+5,y1+2);	// Petite partie haute en noir
		bmp_select_pen(BMP_CST_COLOR_BLANC);
		MoveToEx(h_dc_mem_cells,x1-1,y1+8,NULL);  LineTo(h_dc_mem_cells,x1-1,y1-1); LineTo(h_dc_mem_cells,x1+6,y1-1);
		MoveToEx(h_dc_mem_cells,x1+0,y1+0,NULL);  LineTo(h_dc_mem_cells,x1+0,y1+2);
		MoveToEx(h_dc_mem_cells,x1+2,y1+1,NULL);  LineTo(h_dc_mem_cells,x1+4,y1+1);
		bmp_select_pen(BMP_CST_COLOR_GRIS128);
		MoveToEx(h_dc_mem_cells,x1+0,y1+8,NULL);  LineTo(h_dc_mem_cells,x1+6,y1+8); LineTo(h_dc_mem_cells,x1+6,y1-2);
		MoveToEx(h_dc_mem_cells,x1+5,y1+0,NULL);  LineTo(h_dc_mem_cells,x1+5,y1+2);
	}
	else {  // Sans relief.
		bmp_select_pen(BMP_CST_COLOR_NOIR);
		bmp_select_brush(BMP_CST_COLOR_ROUGE);
		Rectangle(h_dc_mem_cells,x1+0,y1+2,x1+6,y1+8);	// Partie du corps en rouge
		Rectangle(h_dc_mem_cells,x1+1,y1+0,x1+5,y1+2);	// Petite partie haute en noir.
	}
}
