/** =========== CODE PAGES v1.0 - luglio 2016, di Aldo Carpanelli ==============
Il programma permette di "ispezionare" il code page (character set) usato nella
console del C nell'ambito di una certa localizzazione.
Funziona solo in ambiente Windows, non portabile.
=============================================================================**/
/** ===> INCLUSIONI <======================================================= **/
#include "codepages.h"
/** ===> GLOBALI <========================================================== **/
int gColCons; // il numero delle colonne in console
/** ===> DEFINIZIONI DI FUNZIONI <========================================== **/
int main() {
const int kDimBuff = 1088;
const int kDimMaxLoc = 256;
char *buff = (char*)malloc(kDimBuff); // per le tabelle
char *loc = (char*)malloc(kDimMaxLoc); // per le stringhe di localizzazione
int azione; // il comando scelto tramite il menu
if( buff != NULL && loc != NULL ) { // buffers allocati
sprintf( loc, "%s", setlocale(LC_ALL,NULL) ); // localizzazione corrente
if( RicavaNumeroColonneConsole() ) {
ImpostaTitoloFinestra( kStrNomeProgramma ); // irrilevante
ImpostaColoriConsole( COL_DFLT ); // irrilevante
do { // scelta dei comandi
switch( azione = Menu() ) {
case kCmndCambiaLocale:
CambiaLocale( loc, kDimMaxLoc, buff, kDimBuff );
break;
case kCmndCar_0_31:
VisualizzaTabella( loc, buff, 0 );
break;
case kCmndCar_32_127:
VisualizzaTabella( loc, buff, 1 );
break;
case kCmndCar_128_255:
VisualizzaTabella( loc, buff, 2 );
break;
default: ;
}
} while( azione != kCmndEsci );
}
else {
Errore( kStrErrDimConsoleIlleggibili );
}
}
else {
Errore( kStrErrMemoriaInsuff );
}
// deallocazione della memoria dinamica
if( buff != NULL ) free( buff );
if( loc != NULL ) free( loc );
return 0;
}
/*==============================================================================
Si assicura che la console sia larga a sufficienza per poter contenere le
tabelle (almeno 74 colonne).
==============================================================================*/
bool RicavaNumeroColonneConsole( void ) {
HANDLE hConsole = GetStdHandle( STD_OUTPUT_HANDLE );
bool esito = false;
gColCons = 80; // di solito e' cosi', ma...
if( hConsole != NULL && hConsole != INVALID_HANDLE_VALUE ) {
CONSOLE_SCREEN_BUFFER_INFO csbi = {0};
if( GetConsoleScreenBufferInfo(hConsole,&csbi) ) {
if( csbi.dwSize.X < 74 ) csbi.dwSize.X = 74;
if( SetConsoleScreenBufferSize(hConsole,csbi.dwSize) )
{ gColCons = csbi.dwSize.X; esito = true; }
}
}
return esito;
}
/*==============================================================================
Irrilevante. Cambia il titolo della finestra della console.
==============================================================================*/
void ImpostaTitoloFinestra( const char *titolo ) {
SetConsoleTitle( titolo );
}
/*==============================================================================
Irrilevante. Cambia i colori del testo e dello sfondo della console.
==============================================================================*/
void ImpostaColoriConsole( WORD colori ) {
HANDLE hConsole = GetStdHandle( STD_OUTPUT_HANDLE );
SetConsoleTextAttribute( hConsole, colori );
}
/*==============================================================================
Gestisce il menu per la scelta delle operazioni da compiere.
==============================================================================*/
int Menu( void ) {
int i, aux, scelta = -2;
char buffer[16] = {'\0'};
char *fine;
do {
CLS;
if( scelta < 0 ) {
Box( kStrBoxTitolo_1, gColCons-2, -1, true, true );
A_CAPO; A_CAPO;
for( i=1; i<kTotVociMenu; ++i )
printf( " %3d. %s\n", i, kStrVociMenu[i] );
printf( " %3d. %s\n", 0, kStrVociMenu[0] );
if( scelta < -1 ) {
ImpostaColoriConsole( GIALLO );
printf( "\n%s", kStrSceltaComando_1 );
ImpostaColoriConsole( COL_DFLT );
}
else {
ImpostaColoriConsole( ROSSO );
printf( "\n%s", kStrSceltaComando_2 );
ImpostaColoriConsole( COL_DFLT );
}
}
fgets( buffer, 16, stdin );
aux = strtoul( buffer, &fine, 10 );
if( buffer[strlen(buffer)-1]!='\n' )
while( getchar()!='\n' );
if( fine != buffer )
scelta = aux;
else scelta = -1;
if( scelta < 0 || scelta >= kTotVociMenu )
scelta = -1;
} while( scelta < 0 );
return scelta;
}
/*==============================================================================
Gestisce l'input per il cambiamento della localizzazione corrente.
==============================================================================*/
void CambiaLocale( char *loc, int dimMaxLoc, char *buff, int dimBuff ) {
char *pLoc = NULL;
do {
CLS;
sprintf( loc, "%s", setlocale(LC_ALL,NULL) );
Box( kStrBoxTitolo_2, gColCons-2, -1, true, false );
A_CAPO; A_CAPO;
printf( kStrEtichLocale );
printf( "\"%s\"", loc );
A_CAPO; A_CAPO;
ImpostaColoriConsole( GIALLO );
printf( kStrRichiestaLocale );
ImpostaColoriConsole( COL_DFLT );
A_CAPO; A_CAPO; SPAZI(1);
fgets( buff, dimBuff, stdin );
int l = strlen( buff );
if( buff[l-1] == '\n' )
buff[--l] = '\0';
else while(getchar()!='\n');
if( l == 0 )
pLoc = setlocale( LC_ALL, "" ); // default di sistema
else pLoc = setlocale( LC_ALL, buff );
if( pLoc == NULL ) {
Errore( kStrErrStrLocIgnota );
continue;
}
else {
sprintf( loc, "%s", pLoc );
A_CAPO;
printf( kStrEtichLocale );
printf( "\"%s\"", loc );
A_CAPO; A_CAPO; SPAZI(1);
PAUSE;
break;
}
} while( true );
}
/*==============================================================================
"Smista" i comandi di visualizzazione delle tabelle, scegliendo la funzione piu'
opportuna in relazione al parametro "tipo".
==============================================================================*/
void VisualizzaTabella( const char *loc, char *buff, int tipo ) {
const char *titolo[] = { kStrTitTab_1, kStrTitTab_2, kStrTitTab_3 };
int intAux;
CLS;
intAux = sprintf( buff, kStrSottoTitTab );
sprintf( buff+intAux, "\"%s\"", loc ); A_CAPO;
ImpostaColoriConsole( GIALLO );
Centrato( buff, gColCons ); A_CAPO;
Centrato( titolo[tipo], gColCons ); A_CAPO;
ImpostaColoriConsole( COL_DFLT );
if( tipo == 0 )
Box( ListaCaratteri_0_31(buff), 40, -1, true, true );
else if( tipo == 1 )
Box( ListaCaratteri_32_127(buff), 56, -1, true, true );
else Box( ListaCaratteri_128_255(buff), 72, -1, true, true );
A_CAPO; A_CAPO; SPAZI(1);
ImpostaColoriConsole( GIALLO );
PAUSE;
ImpostaColoriConsole( COL_DFLT );
}
/*==============================================================================
Predispone la lista dei caratteri compresi tra 0 e 31 (alcuni caratteri
"problematici" vengono omessi).
==============================================================================*/
char *ListaCaratteri_0_31( char *buff ) {
if( buff != NULL ) {
char *p = buff;
int nc;
for( int pc=0, i=0; i<8; ++pc, ++i ) {
for( int j=0; j<4; ++j ) {
nc = pc+8*j;
switch( nc ) {
case '\0':
case 7:
case 8:
case '\t':
case '\n':
case '\r':
p += sprintf( p, "%4d %c ", nc, ' ' );
break;
default:
p += sprintf( p, "%4d %c ", nc, nc );
}
}
p += sprintf( p, "%s", "\n" );
}
}
buff[strlen(buff)-1] = '\0'; // elimina l'ultimo "a capo"
return buff;
}
/*==============================================================================
Predispone la lista dei caratteri compresi tra 32 e 127.
==============================================================================*/
char *ListaCaratteri_32_127( char *buff ) {
if( buff != NULL ) {
char *p = buff;
for( int pc=32, i=4; i<20; ++pc, ++i ) {
for( int j=0; j<6; ++j )
p += sprintf( p, "%4d %c ", pc+16*j, pc+16*j );
p += sprintf( p, "%s", "\n" );
}
}
buff[strlen(buff)-1] = '\0'; // elimina l'ultimo "a capo"
return buff;
}
/*==============================================================================
Predispone la lista dei caratteri compresi tra 128 e 255.
==============================================================================*/
char *ListaCaratteri_128_255( char *buff ) {
if( buff != NULL ) {
char *p = buff;
for( int pc=128, i=0; i<16; ++pc, ++i ) {
for( int j=0; j<8; ++j )
p += sprintf( p, "%4d %c ", pc+16*j, pc+16*j );
p += sprintf( p, "%s", "\n" );
}
}
buff[strlen(buff)-1] = '\0'; // elimina l'ultimo "a capo"
return buff;
}
/*==============================================================================
Centra una stringa di testo nella console.
==============================================================================*/
void Centrato( const char *s, int largh ) {
int ls = strlen( s );
SPAZI((largh-ls)/2);
printf( s );
}
/*==============================================================================
Presenta un riquadro contenente una stringa di testo.
==============================================================================*/
void Box( const char *s, int largh, int marg, bool txt_centrato, bool X2 ) {
const char *p1=s, *p2=s;
int i, j, ls, nRighe;
if( marg < 0 ) marg = (gColCons-largh)/2;
largh -= 2;
ls = strlen( s );
for( nRighe=1, i=0; i<ls; ++i ) if( s[i] == '\n' ) ++nRighe;
if( X2 )
{ SPAZI(marg); RIGA_2(largh+2); }
else { SPAZI(marg); RIGA(largh+2); }
for( i=0; i<nRighe; ++i ) {
p2 = i<nRighe-1 ? strchr(p1,'\n') : strchr(p1,'\0');
A_CAPO; SPAZI(marg);
ls = p2-p1;
RIGA_VERT;
if( txt_centrato ) SPAZI( (largh-ls)/2 );
for( j=0; j<ls; ++j ) printf( "%c", p1[j] );
if( txt_centrato )
{ SPAZI( (largh-ls)/2+(largh-ls)%2 ); }
else { SPAZI( largh-ls ); }
RIGA_VERT;
p1 = p2+1;
}
if( X2 )
{ A_CAPO; SPAZI(marg); RIGA_2(largh+2); }
else { A_CAPO; SPAZI(marg); RIGA(largh+2); }
}
/*==============================================================================
Visualizza un messaggio di errore.
==============================================================================*/
void Errore( const char *msg ) {
ImpostaColoriConsole( ROSSO );
Box( msg, 60, 10, false, true );
ImpostaColoriConsole( COL_DFLT );
A_CAPO; A_CAPO; SPAZI(1); PAUSE;
}