summaryrefslogtreecommitdiff
path: root/support/nemocal/nemocal.c
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/nemocal/nemocal.c
Initial commit
Diffstat (limited to 'support/nemocal/nemocal.c')
-rw-r--r--support/nemocal/nemocal.c615
1 files changed, 615 insertions, 0 deletions
diff --git a/support/nemocal/nemocal.c b/support/nemocal/nemocal.c
new file mode 100644
index 0000000000..b0613bd419
--- /dev/null
+++ b/support/nemocal/nemocal.c
@@ -0,0 +1,615 @@
+#include <conio.h>
+#include <ctype.h>
+#include <malloc.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#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;row<rows;row++){
+ for(i=0;i<7;i++){
+ if(i==0){
+ if(rows<6)
+ fprintf(fp_out,"\\rule[-%dpt]{0pt}{%dpt} ",depth5,height5);
+ else fprintf(fp_out,"\\rule[-%dpt]{0pt}{%dpt} ",depth6,height6);
+ }
+ else fprintf(fp_out," ");
+ if(row==0){
+ if(i<dw) x = 0;
+ else x++;
+ }
+ else{
+ if(x!=0) x++;
+ if(x>dmon) 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<year;n++){
+ delta++;
+ if(leap_year(n)) delta++;
+ }
+ }
+ else{
+ for(n=year;n<1994;n++){
+ delta++;
+ if(leap_year(n)) delta++;
+ }
+ delta = -delta;
+ }
+ day_1_1 = (delta + 6)%7 + 1;
+
+ /* get day_m_1 */
+ delta = 0;
+ for(n=0;n<month-1;n++){
+ delta += Days_of_month[n];
+ if(n==1 && leap_year(year)) delta++;
+ }
+ day_m_1 = (delta+day_1_1-1)%7 + 1;
+ return (day_m_1 + day - 2)%7 + 1;
+}
+
+ /* -------------------------------------- */
+
+void get_second_field_parameters(char *string)
+{
+ int x,pos,vpos;
+ char c,str1[11],str2[11];
+
+ if((x=str2num(string)) >= 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;i<n;i++){
+ if(str2num(numstring[i])<=0) show_usage();
+ }
+
+ switch(CalendarType){ /* StartXxxx */
+
+ case weekly:
+ if(n==1) StartDay = str2num(numstring[0]);
+ else if(n==2){
+ StartMonth = str2num(numstring[0]);
+ StartDay = str2num(numstring[1]);
+ }
+ else if(n==3){
+ StartYear = str2num(numstring[0]);
+ StartMonth = str2num(numstring[1]);
+ StartDay = str2num(numstring[2]);
+ }
+ break;
+
+ case monthly:
+ if(n==1) StartMonth = str2num(numstring[0]);
+ else if(n==2){
+ StartYear = str2num(numstring[0]);
+ StartMonth = str2num(numstring[1]);
+ }
+ else exit_here(0,"No need to specify the day.");
+ break;
+
+ case yearly:
+ if(n!=1) exit_here(0,"No need to specify the month or day.");
+ StartYear = str2num(numstring[0]);
+ break;
+
+ }
+}
+
+ /* -------------------------------------- */
+
+void get_today(void)
+{
+ time_t time_of_day;
+ auto struct tm *tmbuf;
+
+ time_of_day = time(NULL);
+ tmbuf = localtime(&time_of_day);
+ Today = tmbuf->tm_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;
+}
+