/* Programma non stupido di agenda elettronica */

/* Il file contenente gli appuntamenti deve avere il seguente formato:	*/
/* Prima devono venire gli appuntamenti periodici, quindi con cadenza	*/
/* fissa, poi in ordine quelli fissati.					*/

/* 23/12/1991 ..... */
/* 24/12/1992 ..... */

/*  Versione 1.1	corretto un problema nel calcolo del giorno	*/
/*			della settimana.				*/

#include <exec/types.h>
#include <stdio.h>
#include <dos.h>
#include <ctype.h>
#include <stdlib.h>
#include <time.h>

typedef unsigned char uchar;
typedef int bool;

struct Data {
  UWORD giorno,mese;
  UWORD anno;
  UWORD ora,minuti,secondi,pad;
};

struct Dati {
  UWORD flags;		/* flags sulle wild cards evento */
  int oggi_delta;	/* distanza di oggi dalla fatidica data in sec. */
  struct Data oggi;	/* data odierna */
  int evento_delta;	/* distanza dell'evento dalla fatidica data in sec. */
  struct Data evento;	/* data dell'evento */
  uchar *p_ora;		/* punatore descrittore ora */
};

const UWORD FWILD_GIORNO = 0x0001;
const UWORD FWILD_MESE = 0x0002;
const UWORD FWILD_ANNO = 0x0004;
const UWORD FWILD_ORA = 0x0008;
/*	const UWORD FWILD_MINUTI = 0x0010;	*/
const UWORD FWILD_SECONDI = 0x0020;

#define MAXLINE		1024
#define NOME_AGENDA	"grasso:etc/appuntamenti"
#define WHITEPEN	printf("\x1b[36m")
#define NORMAL		printf("\x1b[m")

const int GIORNIAVANTI = 10;
const int SECONDIPERGIORNO = 24*3600;
const int SECONDIPERANNO = 365*24*3600;
const int CARATTEREORA = 7;
const int CARATTERESECONDI = 12;
const uchar *giorno[] = {
	"Domenica",
	"Lunedì",
	"Martedì",
	"Mercoledì",
	"Giovedì",
	"Venerdì",
	"Sabato",
};
const uchar *mese[] = {
	"Gennaio",
	"Febbraio",
	"Marzo",
	"Aprile",
	"Maggio",
	"Giugno",
	"Luglio",
	"Agosto",
	"Settembre",
	"Ottobre",
	"Novembre",
	"Dicembre"
};
const int GiorniDaInizioAnno[] = {
	0,	/* gennaio */
	31,	/* febbraio */
	31+28,	/* marzo */
	31+28+31,	/* aprile */
	31+28+31+30,	/* maggio */
	31+28+31+30+31,	/* giugno */
	31+28+31+30+31+30,	/* luglio */
	31+28+31+30+31+30+31,	/* agosto */
	31+28+31+30+31+30+31+31,	/* settembre */
	31+28+31+30+31+30+31+31+30,	/* ottobre */
	31+28+31+30+31+30+31+31+30+31,	/* novembre */
	31+28+31+30+31+30+31+31+30+31+30	/* dicembre */
};
extern int _OSERR;

/* prototipi: */
void scrivi_data( struct Data *data );
void scrivi_ora( struct Data *data, bool secs );
void analizza( uchar *linea, struct Dati *dati );
int date_to_secs( struct Data *data );
int main( int, char ** );

void
scrivi_data( data )
struct Data *data;
{
int gg;		/* giorni trascorsi dall'inizio dell'anno */

  /* Troviamo quanti giorni sono trascorsi dall'anno 0	*/
  /* fino al primo giorno dell'anno richiesto.		*/
  gg = 365*data->anno + (data->anno-1)/4 - (data->anno-1)/100 + (data->anno-1)/400;

  /* Giorni trascorsi dall'inizio dell'anno */
  gg += GiorniDaInizioAnno[ data->mese-1 ] + data->giorno - 1;
  if( (data->mese > 2) && (data->anno % 4)==0 && (data->anno%100) != 0
			 || (data->anno%400) == 0) gg++; 

  WHITEPEN;
  printf("%s %d/%s/%d", giorno[gg % 7], data->giorno, mese[data->mese-1], data->anno );
  NORMAL;
}

void
scrivi_ora( data, secs )
struct Data *data;
bool secs;
{
  if( secs ) printf(" %d:%0.2d:%0.2d", data->ora, data->minuti, data->secondi );
  else printf(" %d:%0.2d", data->ora, data->minuti );
}

void
analizza( linea, dati )
uchar *linea;
struct Dati *dati;
{
  sscanf( linea, "%2hd%2hd%2hd %2hd:%2hd:%2hd",	&dati->evento.giorno,
						&dati->evento.mese,
						&dati->evento.anno,
						&dati->evento.ora,
						&dati->evento.minuti,
						&dati->evento.secondi
  );
  dati->flags = 0;
  dati->evento.anno += 1900;
  if( linea[1] == '*' ) {
    dati->evento.giorno = dati->oggi.giorno;		/* oggi */
    dati->flags |= FWILD_GIORNO;
  }
  if( linea[3] == '*' ){
    dati->evento.mese = dati->oggi.mese;	/* questo mese */
    dati->flags |= FWILD_MESE;
  }
  if( linea[5] == '*' ){
    dati->evento.anno = dati->oggi.anno;	/* quest'anno */
    dati->flags |= FWILD_ANNO;
  }
  if( !isdigit( linea[CARATTEREORA] ) ){
    dati->evento.ora = 23;
    dati->evento.minuti = 59;
    dati->evento.secondi = 59;
    dati->flags |= FWILD_ORA | FWILD_SECONDI;
    dati->p_ora = &linea[ CARATTEREORA ];
  }
  else if( linea[ CARATTERESECONDI ] != ':' ){
    dati->evento.secondi = 59;
    dati->flags |= FWILD_SECONDI;
    dati->p_ora = &linea[ CARATTERESECONDI+1 ];
  }
  else dati->p_ora = &linea[CARATTERESECONDI+4 ];
}

int
date_to_secs( data )
struct Data *data;
{
int secondi;

  /* dobbiamo convertire la data in secondi dal 1970...	*/

  secondi = 3600*data->ora + 60 * data->minuti + data->secondi +
    SECONDIPERGIORNO*( GiorniDaInizioAnno[ data->mese-1 ] + data->giorno-1 +
      (data->anno-1968)/4 ) + SECONDIPERANNO*(data->anno-1970) + 6*3600;
  return( secondi );
}

/* Per il momento niente argomenti, un domani si vedrà */

int
main( argc, argv )
int argc;
char *argv[];
{
FILE *agenda;
uchar linea[ MAXLINE ];
struct Dati dati;
uchar clock[8];
int delta;	/* differenza tra l'evento e l'istante attuale */

  if( argc != 1 ){
    printf("           Agenda v1.1\n");
    printf("    --------------------------\n");
    printf("    © 1991 Pagani Massimiliano\n");
    printf("read 'agenda.doc' or 'agenda.e.doc'\n");
    printf("   to see how Agenda 1.1 works.\n");
    exit( 0L );
  }
  /* Leggiamo la data corrente */
  /* Apriamo il file e leggiamo riga per riga */
  agenda = fopen( NOME_AGENDA, "r" );
  if( !agenda ){
    fprintf( stderr, "problemi nell'apertura del file %s (errore = %ld)\n",
			NOME_AGENDA, _OSERR );
    exit( 15 );
  }
  getclk( clock );
  dati.oggi.giorno = clock[3];
  dati.oggi.mese = clock[2];
  dati.oggi.anno = clock[1]+1980;
  dati.oggi.ora = clock[4];
  dati.oggi.minuti = clock[5];
  dati.oggi.secondi = clock[6];
  dati.oggi_delta = date_to_secs( &dati.oggi );
  while( !feof( agenda ) ){
    fgets( linea, MAXLINE, agenda );
    if( _OSERR ) {
      fprintf( stderr, "problemi nella lettura del file %s (errore = %ld)\n",
			NOME_AGENDA, _OSERR );
      exit( 20 );
    }
    if( !(isdigit( *linea ) || (*linea == '*')) ) continue;
    /* decodifica della data */
    analizza( linea, &dati );
    dati.evento_delta = date_to_secs( &dati.evento );
    delta = dati.evento_delta - dati.oggi_delta;

  /* Se la data dell'evento è più di 10 gg nel futuro fine. */
    if( (delta > SECONDIPERGIORNO*GIORNIAVANTI) ){
      if( !(dati.flags & (FWILD_GIORNO|FWILD_MESE|FWILD_ANNO)) ) {
/*	scrivi_data( &dati.evento );		*/
/*	scrivi_ora( &dati.evento, TRUE );	*/
/*	printf( " %s", dati.p_ora );		*/
	break;
      }
    }
    else if( delta >= 0 ){
      /* Visualizza la linea */
      scrivi_data( &dati.evento );
      if( !(dati.flags & FWILD_ORA) ){
	scrivi_ora( &dati.evento, (bool)(!(dati.flags & FWILD_SECONDI)) );
      }
      printf( " %s", dati.p_ora );
    }
  }
  /* chiudi le parentesi */
  if( agenda ) fclose( agenda );
  return( 0L );
}