/// === CLASSE MENU ============================================================
/// Versione 3.1.0 - Aldo Carpanelli, ottobre 2014/ottobre 2016
/// ============================================================================
#include "menu.h"
#define CLS system("CLS")
#define DIM_BUFFER 6
// quando viene creato un menu senza indicare la
// quantita' massima delle voci, la classe usa...
const int MENU::kMaxVoci = 32;
// la quantita' massima dei caratteri per riga della console
const int MENU::kMaxWConsole = 80;
// quando viene creato un menu senza indicarne
// esplicitamente il nome, la classe usa...
const char *MENU::kStrVuota = "";
const char *MENU::kStrTitoloDflt = "";
const char *MENU::kStrUscitaDflt = "Esci dal menu";
const char *MENU::kStrRichiesta1Dflt = "Indica il numero d'una voce:";
const char *MENU::kStrRichiesta2Dflt = "Scelta non valida. Riprova:";
MENU::MENU() {
Inizializza(
kStrTitoloDflt,
kStrUscitaDflt,
kStrRichiesta1Dflt,
kStrRichiesta2Dflt,
0, 0 );
}
MENU::MENU( MENU_STR strTitolo ) {
Inizializza(
strTitolo,
kStrUscitaDflt,
kStrRichiesta1Dflt,
kStrRichiesta2Dflt,
0, 0 );
}
MENU::MENU( MENU_STR *dati ) {
Inizializza(
kStrTitoloDflt,
kStrUscitaDflt,
kStrRichiesta1Dflt,
kStrRichiesta2Dflt,
0, 0 );
imposta( dati );
}
MENU::~MENU() {
// niente da distruggere
}
void MENU::imposta( MENU_STR *dati ) {
Inizializza( dati[0], usc, ric[0], ric[1], cls, rpt );
for( short i=1; dati[i] && *dati[i]; i++ )
aggiungi_voce( dati[i] );
}
void MENU::titolo( MENU_STR strTitolo ) {
if( strTitolo )
tit = strTitolo;
else tit = kStrTitoloDflt;
}
void MENU::uscita( MENU_STR strUscita ) {
if( strUscita )
usc = strUscita;
else usc = kStrUscitaDflt;
}
bool MENU::aggiungi_voce( MENU_STR strVoce ) {
if( totVoci == kMaxVoci ) return false;
if( strVoce )
voc[totVoci] = strVoce;
else voc[totVoci] = kStrVuota;
totVoci++; // c'e' una voce in piu'
return true;
}
bool MENU::inserisci_voce( short posVoce, MENU_STR strVoce ) {
if( totVoci == kMaxVoci ) return false;
if( posVoce < 1 ) posVoce = 1;
if( posVoce<=totVoci ) {
short i;
posVoce--;
for( i=totVoci; i>posVoce; i-- )
voc[i] = voc[i-1];
if( strVoce )
voc[i] = strVoce;
else voc[i] = kStrVuota;
totVoci++; // c'e' una voce in piu'
}
else {
// se la posizione e' troppo "avanti",
// aggiungiamo la voce in coda al menu
aggiungi_voce( strVoce );
}
return true;
}
bool MENU::cambia_voce( short posVoce, MENU_STR strVoce ) {
if( posVoce<1 || posVoce>kMaxVoci ) return false;
posVoce--;
if( strVoce )
voc[posVoce] = strVoce;
else voc[posVoce] = kStrVuota;
return true;
}
bool MENU::elimina_voce( short posVoce ) {
if( totVoci<1 || posVoce>totVoci ) return false;
posVoce--;
while( posVoce < totVoci ) {
voc[posVoce] = voc[posVoce+1];
posVoce++;
}
voc[totVoci] = NULL;
totVoci--; // c'e' una voce in meno
return true;
}
void MENU::richiesta1( MENU_STR strRichiesta ) {
if( strRichiesta )
ric[0] = strRichiesta;
else ric[0] = kStrRichiesta1Dflt;
}
void MENU::richiesta2( MENU_STR strRichiesta ) {
if( strRichiesta )
ric[1] = strRichiesta;
else ric[1] = kStrRichiesta2Dflt;
}
short MENU::chiedi( void ) {
MENU_STR aCapo[] = { kStrVuota, "\n" };
short i, scelta = -2;
char buffer[DIM_BUFFER];
MENU_STR p;
if( cls ) CLS; // se e' il caso, svuota la console
do {
if( cls && rpt ) CLS; // se e' il caso, svuota la console
if( scelta == -2 || rpt ) {
// stampa il titolo del menu
if( *tit ) printf( "\n%s\n", tit );
// sottolinea il titolo del menu
for( p=tit; *p && (p-tit)<kMaxWConsole; p++ )
printf( "=" );
// stampa la voce per l'uscita dal menu
printf( "\n\n %2d. %s\n", 0, usc );
// stampa tutte le altre voci del menu
for( i=0; i<totVoci; i++ )
printf( " %2d. %s\n", i+1, voc[i] );
}
// legge l'input dell'utente
if( scelta == -2 )
printf( "\n%s ", ric[0] );
else printf( "%s%s ", aCapo[rpt], ric[1] );
fgets( buffer, DIM_BUFFER, stdin );
svuota_input( buffer );
taglia_non_cifre( buffer );
if( *buffer != '\0' )
scelta = atoi( buffer );
else scelta = -1;
if( scelta > totVoci || scelta < 0 )
scelta = -1;
} while( scelta < 0 );
return scelta;
}
MENU_STR MENU::voce( short posVoce ) const {
if( posVoce>0 && posVoce<=totVoci )
return voc[--posVoce];
else if( posVoce == 0 )
return usc;
else return kStrVuota;
}
/// === FUNZIONI PRIVATE =======================================================
void MENU::Inizializza(
MENU_STR strTitolo,
MENU_STR strUscita,
MENU_STR strRichiesta1,
MENU_STR strRichiesta2,
bool cancella,
bool ripeti ) {
titolo( strTitolo );
uscita( strUscita );
richiesta1( strRichiesta1 );
richiesta2( strRichiesta2 );
totVoci = 0;
cls = cancella;
rpt = ripeti;
for( int i=0; i<kMaxVoci; i++ )
voc[i] = NULL;
}
void MENU::taglia_non_cifre( char *s ) {
char *p = s;
// elimina i caratteri spuri a inizio stringa
while( (*p<'0' || *p>'9') && *p!='\0' ) p++;
// mantiene i primi caratteri cifra (se ce ne sono)
while( (*p>='0' && *p<='9') && *p!='\0' ) {
*s = *p;
s++; p++;
}
*s = '\0'; // termina la stringa
}
void MENU::svuota_input( char *s ) {
size_t l = strlen( s );
if( l>0 )
if( s[--l] != '\n' )
while( getchar() != '\n' );
}