// UTS 2000 - fichier 'exe.ccp' Lecture des variables pour lancer des exécutables dans le fichier de configuration, et gestion de ces exécutables - 
// V3.7e - Le 16/11/2018
// Exemple pour activer un son à un moment donné. = Execution d'un ".wav"
#include  <windows.h>
#include  <string.h>
#include  <stdlib.h>
#include  <stdio.h>
#include "Train_UTS.h"
#include  "exe.h"

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

// Déclaration des fonctions externes
extern void bmp_SetTextColor(int no_color);
extern void EasyTextOut(int , int , char* );
extern void EasyLine(int, int, int, int);

// Déclaration des variables externes.
extern HDC     hMemDC;
extern HFONT   bmp_fonte;
extern HPEN    bmp_stylo_noir, bmp_stylo_gris128, bmp_stylo_gris192, bmp_stylo_blanc, bmp_stylo_jaune;
extern HBRUSH  bmp_pinceau_blanc, bmp_pinceau_jaune, bmp_pinceau_gris192,  bmp_pinceau_gris220, bmp_pinceau_vert;
extern int screen_mode;
extern int nb_exe_lus; // Nombre d'élements 'exeXX' lus dans config.txt.
extern int x_mouse,y_mouse,touche,touche_char,x_mouse_move,y_mouse_move, screen_mode_retour;



// Déclaration des variables 
int pio_exe[NB_EXE];
char aszExe[NB_EXE][EXE_TAILLE+1]; // Taille + 1 pour le '/0'. (100 executables de 200 caractères!).

//
//
cExe::cExe(void) { }


// Sous programme pour récupérer les informations des 'Executables' dans le fichier 'config.txt'
//
//
void cExe::init(char filename[])
{
	FILE* pf;
	int no, i, j, k;
	int ligne_verif; //   0 => Erreur,   1 => Rechercher 'exe',   2 => Recherche ':',   3 => Recherche 'Commande',  4 => Stockage des caractères.
	int num_car; // Numéro de caractère en cours de saisie.

	char ch[CHAR_CONFIG_NB];
	char ch_error[250];
	char c;
	char* pt;

	for(i=0;i<NB_EXE;i++) { strcpy(aszExe[i],""); pio_exe[i]=0; }
	nb_exe_lus=0;

	if ((pf=fopen(filename,"rt"))==NULL) {
		MessageBox(NULL,"UTS - Impossible d'ouvrir le fichier de configuration du #exe '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,"#exe")) {
			fscanf(pf," %s",ch); // Passe '['.
			ligne_verif=1; // 1 = Ligne à vérifier.
//
// exe2: "E:\projet\dev_c++\projet\train5\sons\arreter_montagne.wav"
// exe14: "C:\APPLI\VLC_PLAYER.020105\vlc.exe"   "E:\Users\moi\Documents\Départ_TER_01.mp3"   "--play-and-exit"    "--qt-start-minimized"
// 1ere chaîne = Programme ou fichier, chaînes suivantes optionelles = Paramètres passés au programme.
//
			while (ligne_verif!=0) {
				if (fscanf(pf," %s",ch)==EOF) break;
				if (ch[0]=='@') { // Passe tout le texte après un '@' = commentaires, jusqu'à la fin de la ligne.
					while (fscanf(pf,"%c",&c)!=EOF && c!='\n') ;
					continue;
				}

				else if (ch[0]==']') break; // On est arrivé à la fin de la section '#exe'.

				else if (ch[0]=='\n' && ligne_verif!=1) ligne_verif=0; // Ligne vide, on passe à la suivante.

				else if (ligne_verif==1) { // Recherche d'une chaine 'exe'.
					if (ch[0]=='e' && ch[1]=='x' && ch[2]=='e') {
						// On a trouvé une ligne qui commence par "exe".
						no=atoi(&ch[3]); // Numéro de l'executable
						if (no>=0 && no<(NB_EXE) && strlen(ch)>3) { // Recherche d'un caractère ':' ou '"'.
							if (ch[strlen(ch)-1]=='"') c='"';
							if (ch[strlen(ch)-1]==':') c=':';
							else while (fscanf(pf,"%c",&c)!=EOF && c!='\n' && c!=':') ;
							if (c==':' || c=='"') {
								if (c==':') while (fscanf(pf,"%c",&c)!=EOF && c!='\n' && c!='"') ;
								if (c=='"') {
									aszExe[no][0] = c;
									num_car = 1;
									while (fscanf(pf,"%c",&c)!=EOF && c!='\n') {
										if (num_car<EXE_TAILLE-3) { // Erreur,  ligne trop longue.
											aszExe[no][num_car]=c;
											num_car++;
										}
										else ligne_verif=0; // On a lu toute la ligne sans erreur.
									}
									k = 0;
									for (j = 0; j < EXE_TAILLE && aszExe[no][j] != '\0'; j++) {
										if (aszExe[no][j] == '"') k++; // k = Nombre de caractère '"' sur la ligne traitée. 
									}
									if (k>=2 && k%2==0) {  // Chaine de caratère valide, si elle contient des caractère '"' en nombre paire.
										aszExe[no][num_car]='\0';
										nb_exe_lus++;
									}
									else ligne_verif=0;
								}
							}
							else ligne_verif=0;
						}
						else ligne_verif=0;
					}
				} //fin while
			}     //fin #exe
			if (ligne_verif!=1) { // Erreur ou on n'a pas trouvé de signification sur la chaine de caractères analysée. On sort pour ne pas boucler ici.
				strcpy(ch_error,"Fichier 'config.txt',  Section #exe\n\nOn attend une ligne de type =  exeXX:  \"commande\" \n(Ne pas oublier un espace entre 'exeXX:' et \"commande\")\n\n\nErreur de description sur la ligne :\n\n");
				strcat(ch_error,ch);
				MessageBox(NULL,ch_error,"UTS - Erreur",MB_OK|MB_ICONERROR); 	exit(1);
			}
			break;
		}
	}
	//fin fscanf
    fclose(pf);
}

//
//
void cExe::save_conf(void)
{
    FILE* pf;
    int i;
    if((pf=fopen("debug_exe.txt","wt"))==NULL) {
        MessageBox(NULL,"UTS - Impossible de créer le fichier 'debug_exe.txt'","Erreur",MB_OK|MB_ICONERROR); exit(1);
    }
    for(i=0;i<NB_EXE;i++) fprintf(pf,"%3d: \"%s\"",i,aszExe[i]);
    fclose(pf);
}

// Sous programme pour lancer un exécutable, un '.wav' ou  un '.mp3'
// Il faut que le texte de commande ne soit pas vide.
// Chaines = "E:\projet\dev_c++\projet\train5\sons\arreter_montagne.wav"
//           "C:\APPLI\VLC_PLAYER.020105\vlc.exe"   "E:\Users\moi\Documents\Départ_TER_01.mp3"   "--play-and-exit"    "--qt-start-minimized"
//            1ere chaîne = Programme ou fichier, chaînes suivantes optionelles = Paramètres passés au programme.
//
// On récupère le texte entre le 1er et deuxième '"' => Executable.
// On récupère le texte entre le troisième et dernier '"' => Paramètres.
//
void cExe::tick(void)
{
    int i,j,k,l;
	char ch1[CHAR_CONFIG_NB];
	char ch2[CHAR_CONFIG_NB];
	for (i=0; i<NB_EXE; i++) {
		if (pio_exe[i]==1) {
			k = 0;
			for (j = 0; j < EXE_TAILLE && aszExe[i][j] != '\0'; j++) {
				if (aszExe[i][j] == '"') k++;  // k = Nombre de caractère '"'. 
			}
			if (k == 2) { //Commande simple, pas de paramètre.
				if (aszExe[i][0] != '\0') ShellExecute(NULL, "open", aszExe[i], NULL, NULL, SW_SHOWNA);
			}
			if (k > 2 && k%2==0) { // Commande avec paramètres.
				k = 0;
				for (j = 0; j < EXE_TAILLE && aszExe[i][j] != '\0' && k<2; j++) {
					if (aszExe[i][j] == '"') k++;  // k = Nombre de caractère '"'. 
					ch1[j] = aszExe[i][j];
				}
				ch1[j] = '\0';  // ch1 = Chaine de commande.
				// On continue à lire la deuxième chaine de caractère à partir du caractère j+1.
				l = j;
				for (j = 0; j+l < EXE_TAILLE && aszExe[i][j+l] != '\0'; j++) {
					ch2[j] = aszExe[i][j+l];
				}
				ch2[j] = '\0';  // ch2 = Chaine de paramètres.
				if (aszExe[i][0] != '\0') ShellExecute(NULL, "open", ch1, ch2, NULL, SW_SHOWNA);
			}
			pio_exe[i] = 0;
		}
	}
}

cExe ThisExe;


//
// Affiche les tableaux '#exe'
//
void cExe::debug(int action)
{
	int i, j;
	char ch[EXE_TAILLE+1];
	static int exe_h_deb=0;
	static int dimnx=44;    // Dimension horizontal d'une cellule 'Numéro'
	static int dimcx=68;    // Dimension horizontal d'une cellule 'Cantons'
	static int dimli=350;   // Dimension horizontal d'une cellule 'Libé' min=229
	static int dimy=16;     // Dimension vertical d'une cellule
	static int nblignes=32; // Nombre de ligne du tableau (sans le titre)	
	static int decaly=16;   // Decalage de la premiére ligne vers le bas.
  
	SelectObject(hMemDC,bmp_fonte); SetBkMode(hMemDC,TRANSPARENT);
	SelectObject(hMemDC,bmp_pinceau_blanc); SelectObject(hMemDC,bmp_stylo_gris192);

	if (action==DEBUG_TOTAL_PAINT) { // ACTION = REDESSINE TOUTE LA FENETRE.
		Rectangle(hMemDC, 0 ,0, 1100, 700);
		SelectObject(hMemDC,bmp_pinceau_gris192); SelectObject(hMemDC,bmp_stylo_gris192); Rectangle(hMemDC,1100-15,15,1100-2,2); // Rectangle gris pour fermer la fenêtre.
		SelectObject(hMemDC,bmp_stylo_noir); EasyLine(1100-14,3,1100-3,14 ); EasyLine(1100-14,13,1100-3,2); // Croix noire.
		SelectObject(hMemDC,bmp_stylo_noir);  EasyLine(1100-2,1,1100-2,16); EasyLine(1100-16,15,1100-1,15); // Trait noir.
		SelectObject(hMemDC,bmp_stylo_gris128); EasyLine(1100-3,2,1100-3,15); EasyLine(1100-15,14,1100-2,14); // Trait gris foncé.
		SelectObject(hMemDC,bmp_pinceau_blanc); SelectObject(hMemDC,bmp_stylo_gris192);
		Rectangle(hMemDC, 0, decaly, 1100, decaly+dimy+1);
		EasyLine(dimnx, decaly, dimnx, decaly+dimy);
		EasyLine(dimnx-10, decaly+dimy, dimnx, decaly+dimy-10); // Dessine un trait dans l'angle = valeurs modifiables
		bmp_SetTextColor(BMP_CST_COLOR_NOIR); // Texte en noir.
		EasyTextOut(2,2,"AFFICHE LES VALEURS DU TABLEAU INTERNE  '#exe:'    (100 éléments maximum)"); EasyTextOut(1100-140,2,"(QUITTER = ESC)");
		EasyTextOut(2,decaly+(nblignes+2)*dimy,"Section '#exe'");
		SelectObject(hMemDC,bmp_stylo_noir); SelectObject(hMemDC,bmp_pinceau_gris220); // Rectangle gris foncé.
		Rectangle(hMemDC,0,decaly+(nblignes+3)*dimy-2, 97, decaly+(nblignes+4)*dimy);
		SelectObject(hMemDC,bmp_stylo_gris128);
		EasyLine(1,  decaly+(nblignes+4)*dimy-2,   96, decaly+(nblignes+4)*dimy-2);  	// Relief rectangle.
		EasyLine(95, decaly+(nblignes+3)*dimy-2+1, 95, decaly+(nblignes+4)*dimy-2);	// Relief rectangle.
		SelectObject(hMemDC,bmp_stylo_noir);
		EasyLine(97-10, decaly+(nblignes+4)*dimy-2, 97, decaly+(nblignes+4)*dimy-12);  // Dessine un trait dans l'angle = valeurs modifiables.
		SelectObject(hMemDC,bmp_pinceau_blanc); SelectObject(hMemDC,bmp_stylo_gris192);
		EasyTextOut(2,decaly+(nblignes+3)*dimy," CLIC-DROIT :AFFICHE LES PAGES 1->2->3, [00-31]->[32-63]->[64-95]");
		EasyTextOut(2,decaly+(nblignes+4)*dimy,"CLIQUEZ sur une ligne pour lancer l'action");
		EasyTextOut(2,decaly+(nblignes+5)*dimy,"Permet de lancer une action externe à UTS (Exemple : émettre un son)");
		EasyTextOut(2,decaly+(nblignes+6)*dimy,"Tronque à 130 car. les lignes trop larges à l'affichage (mais 200 car. max en mémoire)");
		bmp_SetTextColor(BMP_CST_COLOR_ROUGE); // Texte en rouge.
		EasyTextOut(2,                     2+decaly,"  n°"); // Indice 'i' du tableau : descr[i][].
		EasyTextOut(2+dimnx,               2+decaly,"Texte de l'action à exécuter");
		bmp_SetTextColor(BMP_CST_COLOR_NOIR); // Texte en noir.
	}

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

	if (action==DEBUG_MOUSE_RIGHT) { // ACTION = CLIC DROIT DE LA SOURIS, 
		switch (exe_h_deb/nblignes) {
			case 0 : { screen_mode= MD_ECRAN_EXE2; break;}
			case 1 : { screen_mode= MD_ECRAN_EXE3; break;}
			case 2 : { screen_mode= MD_ECRAN_EXE1; break;}
			default: break;
		}
	}

	if (screen_mode==MD_ECRAN_EXE1) exe_h_deb=0;	// Valeur de la premiere ligne à afficher.
	else if (screen_mode==MD_ECRAN_EXE2) exe_h_deb=nblignes;
	else if (screen_mode==MD_ECRAN_EXE3) exe_h_deb=2*nblignes;

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

	bmp_SetTextColor(BMP_CST_COLOR_BLEUF); // Texte en bleu foncé.
	for (i=0; i<nblignes; i++) {
		if (exe_h_deb+i<NB_EXE) {
			sprintf_s(ch,"%3d",exe_h_deb+i);
			Rectangle(hMemDC, 0, dimy*(i+2), 1100, dimy*(i+3)+1);
			EasyLine(dimnx, dimy*(i+2), dimnx, dimy*(i+3)+1);
			if (aszExe[exe_h_deb+i][0]=='\0') bmp_SetTextColor(BMP_CST_COLOR_GRIS192); // Texte en gris 192
			EasyTextOut(10,2+dimy*(i+2),ch); // N° d'indice du tableau
			bmp_SetTextColor(BMP_CST_COLOR_BLEUF); // Texte en bleu foncé.
			if (aszExe[exe_h_deb+i][0]!='\0') { // Elément valide 1
				if (strlen(aszExe[exe_h_deb+i])<130) {
					EasyTextOut(2+dimnx,2+dimy*(i+2),aszExe[exe_h_deb+i]); //
				}
				else {
					sprintf_s(ch,"");
					strcat(ch,aszExe[exe_h_deb+i]);
					ch[128]='.'; ch[129]='.'; ch[130]='.'; ch[131]='\0'; // On coupe la ligne pour ne pas déborder du tableau.
					EasyTextOut(2+dimnx,2+dimy*(i+2),ch); //
				}
			}
		} 
	}
}
