#include #include #include #include #include #include #include #include #define DEBUG #define EOS ('\0') #define bool char #define In(x,y,z) ((x)<=(y) && (y)<=(z)) #define Min(x,y) ((x)<(y) ? (x) : (y)) #define Max(x,y) ((x)>(y) ? (x) : (y)) #define streq !strcmp enum {weekly,monthly,yearly}; void create_calendar(void); void exit_here(bool opt,const char *format,...); int get_day_of_week(int year,int month,int day); void get_second_field_parameters(char *string); void get_third_field_parameters(char *string); void get_today(void); bool leap_year(int year); int n_rows_in_monthly_calendar(int year,int month,int dw); void preprocess(int argc,char *argv[]); void show_usage(void); int str2num(char *str); void write_calendar_page(int n,FILE *fp_out); int CalendarType; /* weekly=0, monthly=1 or yearly=2 */ int Npages; /* -n */ int MperPage=1; /* m in -n,m. For "monthly" only. */ int StartYear,StartMonth,StartDay; /* [year/month/day] */ /* Above are determined in preprocess(), from the command line. */ int Days_of_month[12]={31,28,31,30,31,30,31,31,30,31,30,31}; char *MonthName[12]={"January","February","March","April", "May","June","July","August", "September","October","November","December"}, *Month_name[12]={"Jan","Feb","Mar","Apr", "May","Jun","Jul","Aug", "Sep","Oct","Nov","Dec"}; char *DayName[7]={"Sunday","Monday","Tuesday","Wednesday", "Thursday","Friday","Saturday"}, *Day_name[7]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}; int ThisYear,ThisMonth,Today; /* Counts from one. */ void main(int argc,char *argv[]) { char *calendartype[3]={"weekly","monthly","yearly"}; if(!In(2,argc,4)) show_usage(); get_today(); preprocess(argc,argv); if(MperPage>=4) exit_here(0,"This option not available yet."); printf("\nWe'll create %d page",Npages); if(Npages>1) printf("s"); printf(" of %s calendar starting from %d", calendartype[CalendarType],StartYear); if(CalendarType==weekly) printf("/%d/%d.\n",StartMonth,StartDay); else if(CalendarType==monthly){ printf("/%d.\nMonth per page = %d.\n",StartMonth,MperPage); } else printf(".\n"); cprintf("\r\nContinue ? (y/n): "); if(getche()!='y') exit_here(0,"\nAborted by user request."); create_calendar(); printf("\nExecute \"latex calendar\".\n"); } /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ void preprocess(int argc,char *argv[]) { char *p; /* first field, CalendarType */ if(argv[1][0]!='-') show_usage(); if(streq((p=&(argv[1][1])),"w") || streq(p,"weekly")) CalendarType = weekly; else if(streq(p,"m") || streq(p,"monthly")) CalendarType = monthly; else if(streq(p,"y") || streq(p,"yearly")) CalendarType = yearly; else show_usage(); /* give default values, tentatively */ Npages = 1; StartYear = ThisYear; StartMonth = ThisMonth; StartDay = Today; /* year day */ if(argv[2][0]=='-'){ get_second_field_parameters(&(argv[2][1])); if(argc==4) get_third_field_parameters(argv[3]); else if(argc!=3) show_usage(); } else if(argc==3) get_third_field_parameters(argv[2]); else if(argc!=2) show_usage(); } /* -------------------------------------- */ void show_usage(void) { printf("\nUsage: nemocal -options [-n[,m]] [year/month/day]\n\n\ where -options = -w[eekly]|-m[onthly]|-y[early]\n\ -n = number of pages\n\ m = number of months in a page (for -monthly only)\n\ year/month/day = start of the calendar\n\n"); exit(0); } /* -------------------------------------- */ void print_rows(int rows,int dw,int dmon,bool center, int width,int height6,int height5, int depth6,int depth5,FILE *fp_out) { /* for monthly calendars only */ int x,row,i; char xstr[21]; x = 0; for(row=0;rowdmon) x = 0; } if(x==0) strcpy(xstr," "); else sprintf(xstr,"%d",x); if(center){ if(i<6) fprintf(fp_out,"\\makebox[%dpt]{%s} &\n",width,xstr); else fprintf(fp_out,"\\makebox[%dpt]{%s} \\\\ \\hline\n", width,xstr); } else{ if(i<6) fprintf(fp_out,"\\makebox[%dpt][r]{%s} &\n",width,xstr); else fprintf(fp_out,"\\makebox[%dpt][r]{%s} \\\\ \\hline\n", width,xstr); } } } } /* -------------------------------------- */ void create_calendar(void) { FILE *fp_out; int n; fp_out = fopen("calendar.tex","wt"); if(fp_out==NULL) exit_here(1,"Can't create calendar.tex."); cprintf("\r\n\nCreating calendar.tex"); fprintf(fp_out,"\\documentstyle{article}\n\n"); fprintf(fp_out,"\\oddsidemargin 0cm\n"); fprintf(fp_out,"\\evensidemargin 0cm\n"); if(CalendarType==weekly) fprintf(fp_out,"\\topmargin -1cm\n"); else fprintf(fp_out,"\\topmargin -1.6cm\n"); fprintf(fp_out,"\\parindent 0cm\n"); if(CalendarType!=monthly || (MperPage!=1 && MperPage!=4)){ /* Portrait mode */ fprintf(fp_out,"\\textheight 11in\n"); fprintf(fp_out,"\\textwidth 16.44cm\n"); } else{ /* Landscape mode */ fprintf(fp_out,"\\textheight 7.0in\n"); fprintf(fp_out,"\\textwidth 9.0in\n"); } fprintf(fp_out,"\\pagestyle{empty}\n\n"); fprintf(fp_out,"\\begin{document}\n\n"); for(n=1;n<=Npages;n++){ write_calendar_page(n,fp_out); cprintf(" [%d]",n); } fprintf(fp_out,"\\end{document}\n\n"); fclose(fp_out); printf(" Done.\n"); if(CalendarType==monthly && (MperPage==1 || MperPage==4)) printf("\nRemember the landscape mode!\n"); } /* -------------------------------------- */ void write_calendar_page(int n,FILE *fp_out) { int startmonth,endmonth,startyear,endyear, d_Sun,dw,i,j,k,days_remaining,day,dmon,rows,month; char month_str[21],year_str[21]; if(n>1) fprintf(fp_out,"\\newpage\n"); if(CalendarType==weekly){ /* for weekly calendars, one page may have two months/years */ dw = get_day_of_week(StartYear,StartMonth,StartDay); if(StartDay>=dw){ d_Sun = StartDay - dw + 1; startyear = endyear = StartYear; startmonth = endmonth = StartMonth; days_remaining = Days_of_month[StartMonth-1] - StartDay; if(StartMonth==2 && leap_year(StartYear)) days_remaining++; if(days_remaining<7-dw){ if(StartMonth<12) endmonth = startmonth+1; else{ endmonth = 1; endyear = StartYear+1; } } } else{ if(StartMonth>1){ startyear = endyear = StartYear; startmonth = StartMonth-1; endmonth = StartMonth; } else{ startyear = StartYear - 1; endyear = StartYear; startmonth = 12; endmonth = 1; } d_Sun = Days_of_month[startmonth-1] - dw + 2; if(startmonth==2 && leap_year(startyear)) d_Sun++; } if(endmonth==startmonth) sprintf(month_str,"%s",Month_name[startmonth-1]); else sprintf(month_str,"%s/%s", Month_name[startmonth-1],Month_name[endmonth-1]); if(endyear==startyear) sprintf(year_str,"%d",startyear); else sprintf(year_str,"%d/%d",startyear,endyear); if(n%2==1) fprintf(fp_out, "{\\large\\sf\n\\hfill %s \\ %s\n}\n\\vspace{1cm}\n\n", month_str,year_str); else fprintf(fp_out,"{\\large\\sf\n %s \\ %s\n}\n\\vspace{1cm}\n\n", month_str,year_str); fprintf(fp_out,"\\begin{tabular}{|c|c|} \\hline\n"); for(i=1;i<=7;i++){ day = d_Sun + i - 1; if(day>(dmon = Days_of_month[startmonth-1] + (startmonth==2 && leap_year(startyear)))) day -= dmon; fprintf(fp_out,"\\rule{0cm}{1.5cm}{\\Huge %d}\ & \\rule{13.68cm}{0cm} \\\\ \n",day); fprintf(fp_out,"\\rule{0cm}{1cm}\\raisebox{.1cm}{\\sf %s}\ & \\\\ \\hline \n",DayName[i-1]); } fprintf(fp_out,"\\end{tabular}\n\n"); StartDay += 7; if(StartDay > (dmon = Days_of_month[StartMonth-1] + (StartMonth==2 && leap_year(StartYear)))){ StartDay -= dmon; StartMonth++; if(StartMonth>12){ StartMonth = 1; StartYear++; } } } else if(CalendarType==monthly){ switch(MperPage){ case 1: dw = get_day_of_week(StartYear,StartMonth,1) - 1; /* Sunday=0,Monday=1 etc. for no good reason */ rows = n_rows_in_monthly_calendar(StartYear,StartMonth,dw); if(rows<6) fprintf(fp_out,"\\rule{0cm}{0.6cm}\n"); fprintf(fp_out,"\\begin{center}\n\n"); fprintf(fp_out,"{\\huge\\sf %s \\rule{1.5em}{0em} %d}\n\n", MonthName[StartMonth-1],StartYear); fprintf(fp_out,"\\rule{0em}{3em}\n\n"); fprintf(fp_out,"{\\Large\\sf\n"); fprintf(fp_out,"\\begin{tabular}{|c|c|c|c|c|c|c|} \\hline\n"); fprintf(fp_out,"\\rule[-3mm]{0mm}{10mm}"); for(i=0;i<7;i++){ fprintf(fp_out,"\\makebox[71pt]{%s}",Day_name[i]); if(i<6) fprintf(fp_out," &\n"); } fprintf(fp_out," \\\\ \\hline\n"); dmon = Days_of_month[StartMonth-1] + (StartMonth==2 && leap_year(StartYear)); print_rows(rows,dw,dmon,0,71,65,71,48,54,fp_out); fprintf(fp_out,"\\end{tabular}\n"); fprintf(fp_out,"}\n\n"); fprintf(fp_out,"\\end{center}\n\n"); StartMonth++; if(StartMonth>12){ StartMonth = 1; StartYear++; } break; case 2: for(j=0;j<2;j++){ if(j==0) fprintf(fp_out,"\\rule{0cm}{0.5cm}\n"); else fprintf(fp_out,"\\rule{0cm}{1.5cm}\n"); dw = get_day_of_week(StartYear,StartMonth,1) - 1; /* Sunday=0,Monday=1 etc. for no good reason */ rows = n_rows_in_monthly_calendar(StartYear,StartMonth,dw); fprintf(fp_out,"\\begin{center}\n\n"); fprintf(fp_out,"{\\Large\\sf %s \\rule{1.5em}{0em} %d}\n\n", MonthName[StartMonth-1],StartYear); fprintf(fp_out,"\\rule{0em}{2em}\n\n"); fprintf(fp_out,"{\\large\\sf\n"); fprintf(fp_out,"\\begin{tabular}{|c|c|c|c|c|c|c|} \\hline\n"); fprintf(fp_out,"\\rule[-7pt]{0pt}{22pt}"); for(i=0;i<7;i++){ fprintf(fp_out,"\\makebox[43pt]{%s}",Day_name[i]); if(i<6) fprintf(fp_out," &\n"); } fprintf(fp_out," \\\\ \\hline\n"); dmon = Days_of_month[StartMonth-1] + (StartMonth==2 && leap_year(StartYear)); print_rows(rows,dw,dmon,0,43,37,43,25,31,fp_out); fprintf(fp_out,"\\end{tabular}\n"); fprintf(fp_out,"}\n\n"); fprintf(fp_out,"\\end{center}\n\n"); StartMonth++; if(StartMonth>12){ StartMonth = 1; StartYear++; } } break; /* case 4 and case 6 not available yet */ } } else{ /* yearly */ fprintf(fp_out,"\\begin{center}\n"); fprintf(fp_out,"{\\huge\\sf %d}\n",StartYear); fprintf(fp_out,"\\end{center}\n\n"); for(j=0;j<4;j++){ /* each j corrsponds to three months */ if(j==0) fprintf(fp_out,"\\rule{0cm}{3.5cm}\n"); else fprintf(fp_out,"\\rule{0cm}{3.0cm}\n"); for(k=0;k<3;k++){ fprintf(fp_out,"\\parbox{4.8cm}{\n"); /* Write a monthly calendar here. */ month = j*3 + k + 1; dw = get_day_of_week(StartYear,month,1) - 1; /* Sunday=0,Monday=1 etc. for no good reason */ rows = n_rows_in_monthly_calendar(StartYear,month,dw); fprintf(fp_out,"\\begin{center}\n\n"); fprintf(fp_out,"{\\sf %s}\n\n",MonthName[month-1]); fprintf(fp_out,"\\rule{0em}{1em}\n\n"); fprintf(fp_out,"{\\sf\n"); fprintf(fp_out,"\\begin{tabular}{|c|c|c|c|c|c|c|} \\hline\n"); fprintf(fp_out,"\\rule[-3pt]{0pt}{11pt}"); for(i=0;i<7;i++){ fprintf(fp_out,"\\makebox[7pt]{\\footnotesize %s}",Day_name[i]); if(i<6) fprintf(fp_out," &\n"); } fprintf(fp_out," \\\\ \\hline\n"); dmon = Days_of_month[month-1] + (month==2 && leap_year(StartYear)); print_rows(rows,dw,dmon,1,7,8,11,-2,0,fp_out); fprintf(fp_out,"\\end{tabular}\n"); fprintf(fp_out,"}\n\n"); fprintf(fp_out,"\\end{center}\n\n"); if(k<2) fprintf(fp_out,"}\\rule{0.9cm}{0cm}\n"); else fprintf(fp_out,"} \\\\ \n"); } } StartYear++; } } /* * * void exit_here(bool opt,const char *format,...) * Prints formatted error messages on stdout and exits. * * int get_day_of_week(int year,int month,int day) * Sun=1,Mon=2 etc. * * void get_second_field_parameters(char *string) * Computes the global variable(s) Npages (and MperPage) from the * input string -n[,m]. * * void get_third_field_parameters(char *string) * Computes the global variables StartYear,StartMonth and StartDay * from the input string year/month/day. The CalendarType strongly * affects the way this routine calculates those values. * * void get_today(void) * * bool leap_year(int year) * * int n_rows_in_monthly_calendar(int year,int month,int dw) * year is to determine leap year. * dw is day of the week counting from zero. * * int str2num(char *str) * */ void exit_here(bool opt,const char *format,...) { /* opt==0 iff doesn't show !*** ERROR ***! */ char buffer[401]; va_list argp; /* write to {\tt buffer[]} */ va_start(argp,format); vsprintf(buffer,format,argp); va_end(argp); /* print the message and exit */ printf("\n"); if(opt) printf("!*** ERROR ***! "); printf("%s\n\n",buffer); exit(1); } /* -------------------------------------- */ int get_day_of_week(int year,int month,int day) { /* 1994/1/1 is Saturday */ int day_1_1, /* day of the week of Jan 1 of the input year */ day_m_1, /* day of the week of year/month/1 */ delta,n; /* get day_1_1 */ delta = 0; if(year>=1994){ for(n=1994;n= 0) Npages = x; else{ if(CalendarType!=monthly) show_usage(); pos = vpos = 0; while((c=string[pos++])!=',' && c!=EOS){ if(vpos>10) show_usage(); str1[vpos++] = c; } if(c!=',') show_usage(); str1[vpos] = EOS; if((Npages=str2num(str1))<0) show_usage(); vpos = 0; while((c=string[pos++])!=EOS){ if(vpos>=10) show_usage(); str2[vpos++] = c; } str2[vpos] = EOS; if((MperPage=str2num(str2))<0) show_usage(); if(MperPage!=1 && MperPage!=2 && MperPage!=4 && MperPage!=6) exit_here(0,"You can have only 1,2,4 or 6 months per page."); } } /* -------------------------------------- */ void get_third_field_parameters(char *string) { int n=0; /* number of subfields separated by / */ char numstring[3][5]; int pos=0,vpos=0,i; char c; while((c=string[pos++])!=EOS){ if(c=='/'){ if(n>=2) show_usage(); numstring[n++][vpos] = EOS; vpos = 0; } else{ if(vpos>=4) show_usage(); numstring[n][vpos++] = c; } } numstring[n++][vpos] = EOS; for(i=0;itm_mday; ThisMonth = tmbuf->tm_mon + 1; ThisYear = tmbuf->tm_year + 1900; } /* -------------------------------------- */ bool leap_year(int year) { if(year%4 == 0){ if(year%100 == 0){ if(year%400 == 0) return 1; else return 0; } else return 1; } else return 0; } /* -------------------------------------- */ int n_rows_in_monthly_calendar(int year,int month,int dw) { int rows=1,i,dmon; dmon = Days_of_month[month-1] + (month==2 && leap_year(year)); for(i=2;i<=dmon;i++){ if((i+dw)%7 == 1) rows++; } return rows; } /* -------------------------------------- */ int str2num(char *str) { /* Returns 0 <= x <= 29999 normally. Returns -1 if input is illegal. */ char c; int n=0,pos=0; while((c=str[pos])!=EOS){ if(!isdigit(c)) return -1; n = n*10 + c - '0'; pos++; } if(pos>5 || (pos==5 && str[0]>'2')) return -1; else return n; }