 /* Data: 24/05/2025 */
 /* Linha para compilar: gcc FileConverter.c -o FileConverter.exe -Wall -pedantic -Wextra -Werror */
 /* Forma de execu‡Æo:
    - Digitar: FileConverter.exe
		1) Programa pedir  para digitar um nome de arquivo;
		2) Gerar  um arquivo de sa¡da denominado "saida_oem.txt" com o conte£do do arquivo de entrada convertido para OEM850.
	- Digitar: FileConverter.exe 1
		1) Programa pedir  para digitar um nome de arquivo;
		2) Gerar  um arquivo de sa¡da, com o conte£do do arquivo de entrada convertido para OEM850, com o mesmo nome de arquivo digitado pelo usu rio.
  */	
 
#include <stdio.h>		/* Fun‡äes: fclose(), fgets(), fopen(), fput(), snprintf(), printf(). Tipo: FILE 	 */
#include <stdlib.h>		/* Fun‡Æo: system() */
#include <string.h>		/* Fun‡Æo: strcspn() */
#include <wchar.h>		/* Tipo: wchar_t */
#include <windows.h>	/* Fun‡äes: MultiByteToWideChar(), WideCharToMultiByte() */

/* Indicar se ‚ para fazer a conversÆo e ter como resultado final, o mesmo nome de arquivo j  convertido */
#define SAIDA_SER_NO_MESMO_ARQUIVO_ORIGINAL 1

int main(int argc, char *argv[])
 {

	/* Declara‡Æo das vari veis locais */
	FILE *entrada, *saida; /* arquivos de entrada e sa¡da */
	char arquivo_entrada[50];
	char buffer_ansi[1024];
	wchar_t buffer_unicode[1024];
    char buffer_oem[1024];
	int num_unicode;
	int num_oem;
	char comando_final[100];
	int codigos_erros = 0;
	enum { ERRO_AO_LER_ENTRADA, ABERTURA_ARQUIVO_ENTRADA, ABERTURA_ARQUIVO_SAIDA, ERRO_CONVERSAO_PARA_UNICODE, ERRO_CONVERSAO_PARA_OEM850 } tipo_erro;
	char *mensagens_de_erro[] = { "Erro ao ler entrada\n",
								  "Erro ao abrir arquivo de entrada\n", 
							      "Erro ao abrir arquivo de sa¡da\n",
								  "Erro na conversÆo ANSI -> Unicode\n",
								  "Erro na conversÆo Unicode -> OEM\n"
								};
	argc = argc;
	argv = argv;
								
    printf("Digite o nome do arquivo de entrada: ");									
	if ( !fgets(arquivo_entrada, sizeof(arquivo_entrada), stdin) )
	{
		tipo_erro = ERRO_AO_LER_ENTRADA;
        printf( "%s", mensagens_de_erro[tipo_erro] );
        codigos_erros = 1;  /* setando o bit 1 */
	}

	/* Eliminando o \n do final do nome do arquivo lido do usu rio e substituindo-o pelo terminador de string \0 */
	arquivo_entrada[strcspn(arquivo_entrada, "\n")] = '\0';

    /* Abrir arquivo de entrada (ANSI / Windows-1252)  somente para leitura em modo texto. Se o arquivo nÆo existir ‚ um erro (retorna NULL). Detalhe: se ler \r\n (final de linha) converter  para \n */
    entrada = fopen(arquivo_entrada, "r");
    if ( !entrada ) 
	{
		tipo_erro = ABERTURA_ARQUIVO_ENTRADA;
        printf( "%s", mensagens_de_erro[tipo_erro] );
        codigos_erros = codigos_erros | 0x2; /* setando o bit 2 */
    }
	
	/* Abrir arquivo de sa¡da (OEM 850) para escrita (cria ou substitui o arquivo), no modo bin rio (sem conversÆo de final de linha)> Detalhe: gravar  \n como 0x0A diretamente e nÆo como \r\n */
	saida = fopen( "saida_oem.txt", "wb" ); 
	if ( !saida ) 
	{
		tipo_erro = ABERTURA_ARQUIVO_SAIDA;
		printf( "%s", mensagens_de_erro[tipo_erro] );
		fclose( entrada );
		codigos_erros = codigos_erros | 0x4; /* setando o bit 3 */
	}

	if ( !codigos_erros ) /* entrar somente se nÆo tiver ocorrido nenhum erro at‚ este momento */
	{
		while ( fgets(buffer_ansi, sizeof(buffer_ansi), entrada) ) 
		{
			/* Converter ANSI (1252)  Unicode */
			num_unicode = MultiByteToWideChar(
												1252, /* P gina de c¢digo de origem (ANSI Latin 1) */
												0,    /* Para converter para UTF-8 */
												buffer_ansi, /* String de entrada a ser convertida */
												-1,   /* ou o tamanho da string de entrada, ou -1 se a string de entrada for terminada em
														 nulo */
												buffer_unicode, /* Buffer que receber  a cadeia convertida */
												1024  /* tamanho do buffer de sa¡da */
											  );
			if (num_unicode == 0) 
			{
				tipo_erro = ERRO_CONVERSAO_PARA_UNICODE;
				printf( "%s", mensagens_de_erro[tipo_erro] );
				codigos_erros = codigos_erros | 0x8; /* setando o bit 4 */
				break;
			}

			/* Converter Unicode  OEM 850 */
			num_oem = WideCharToMultiByte(
											850, /* P gina de c¢digo destino da conversÆo ( OEM850 ) */
											0,	 /* Converter para UTF-8 */ 
											buffer_unicode, /* String de entrada a ser convertida */
											-1, /* indicar que a string de entrada deve ser terminada pelo caracter NULL */
											buffer_oem,	/* Buffer que receber  a cadeia convertida */ 
											1024, /* tamanho do buffer que receber  a cadeia convertida */
											NULL, 
											NULL
										  );
			if (num_oem == 0)
			{
				tipo_erro = ERRO_CONVERSAO_PARA_OEM850;
				printf( "%s", mensagens_de_erro[tipo_erro] );
				codigos_erros = codigos_erros | 0x10; /* setando o bit 5 */
				break;
			}

			/* Escrever no arquivo de sa¡da */
			fputs( buffer_oem, saida );
		}
    }

    fclose( entrada );
    fclose( saida );
	
	
	if ( argc > 1 )
		if ( atoi(argv[1]) == SAIDA_SER_NO_MESMO_ARQUIVO_ORIGINAL )
		{
			/* Criar comando para ser executado pelo SO */
			snprintf( comando_final, sizeof(comando_final), "%s%s", "del ", arquivo_entrada );
			/* Apagar arquivo de entrada original */
			system( comando_final );
			
			/* Renomear arquivo gerado para o nome do arquivo de entrada original */
			snprintf( comando_final, sizeof(comando_final), "%s%s", "ren saida_oem.txt ", arquivo_entrada );
			system( comando_final );
		}

	if ( !codigos_erros )
		 printf("ConversÆo conclu¡da com sucesso!\n");
	
    return codigos_erros;
}
