/* ========================================================================== jcal.c - a simple text-based calendar program Copyright (c) 1999 by Jeffrey S. Rosenthal (jeff@math.toronto.edu). Available from http://probability.ca/jeff/comp/ Licensed for general copying, distribution and modification according to the GNU General Public License (http://www.gnu.org/copyleft/gpl.html). Tested on Linux 2.0.3x, LinuxPPC, and Irix 6.x. -------------------------------------------- Compile with "cc jcal.c -lcurses -o jcal". -------------------------------------------- User documentation is available in the companion file jcal.doc, which should normally be stored at /usr/local/doc/jcal.doc to be accessible by pressing '?' from within jcal. (Note: the "defaultdocpath" for accessing jcal.doc can be modified; see the fourth line of the code below.) ========================================================================== */ /* DEFAULT VALUES -- MAY BE MODIFIED. */ #define defaulteditor "vi" /* overwritten by $VISUAL or $EDITOR. */ #define defaultprintcommand "print" /* overwritten by $PRINTCOMMAND. */ #define defaultdirname ".jcal" /* in home directory; overwritten by $JCALDIR. */ #define defaultdocpath "/usr/local/doc/jcal.doc" /* overwritten by $JCALDOCPATH. */ #define defaultpager "more" /* overwritten by $JCALPAGER */ /* overwritten by $JCALDOCPATH. */ #define auxfilename "auxiliary" #include #include #include #include main() { /* INITIAL DECLARATIONS. */ int i,j,k,tmpint; int xpos, ypos; int currentyear, currentmonth, currentday, currentdayofweek; int tmpyear, tmpmonth, tmpday, tmpdayofweek; int year[6][7]; int month[6][7]; int day[6][7]; char tmpstring[82]; char holdstring[82]; char holdinitmonthname[5]; char holdlastmonthname[5]; char directorystring[82]; char *editstring; char *docpoint; char *pagerpoint; char *printstring; char *homestring; char *holdstringpointer; char datalines[7][8][5][12]; char keypress, oldkeypress, keypresshold, c; char commandstring[100]; char printcommand[100]; char editcommand[100]; char docpath[100]; char pager[100]; int OVER, REDRAW, ZSTOPPING, COPYING; /* boolean */ int numrep, oldnumrep; FILE *pfp; /* Check added later: */ int existstmp, existshold; time_t timeholder; struct tm *localtimeholder; char *asctimept; char asctimeholder[80]; /* CONSTANT PRINT LINES. */ char daynameline[82]; char separatorline[82]; char blankcalline[82]; char vertchar; if ( (holdstringpointer = getenv("JCALVERTCHAR")) == NULL) vertchar = '$'; else vertchar = holdstringpointer[0]; sprintf(daynameline, "%c SUNDAY %c MONDAY %c TUESDAY %c WEDNESDAY%c THURSDAY %c FRIDAY %c SATURDAY %c\n", vertchar, vertchar, vertchar, vertchar, vertchar, vertchar, vertchar, vertchar); sprintf(separatorline, "==============================================================================\n"); sprintf(blankcalline, "%c %c %c %c %c %c %c %c\n", vertchar, vertchar, vertchar, vertchar, vertchar, vertchar, vertchar, vertchar); /* DETERMINE "editstring" EDITOR INFO. */ if ( (editstring = getenv("VISUAL")) == NULL) { if ( (editstring = getenv("EDITOR")) == NULL) { strcpy(tmpstring, defaulteditor); editstring = tmpstring; } } sprintf(editcommand, "%s", editstring); /* DETERMINE "printstring" PRINT-COMMAND INFO. */ if ( (printstring = getenv("PRINTCOMMAND")) == NULL) { strcpy(tmpstring, defaultprintcommand); printstring = tmpstring; } sprintf(printcommand, "%s", printstring); /* DETERMINE "docpath" DOCUMENT-PATH INFO. */ if ( (docpoint = getenv("JCALDOCPATH")) == NULL) { strcpy(tmpstring, defaultdocpath); docpoint = tmpstring; } sprintf(docpath, "%s", docpoint); /* DETERMINE "pager" INFO. */ if ( (pagerpoint = getenv("JCALPAGER")) == NULL) { strcpy(tmpstring, defaultpager); pagerpoint = tmpstring; } sprintf(pager, "%s", pagerpoint); /* DETERMINE "directorystring" INFO. */ if ( (holdstringpointer = getenv("JCALDIR")) == NULL) { if ( (homestring = getenv("HOME")) == NULL) { fprintf(stderr, "Oops, please sent your HOME environment variable.\n"); exit(1); } sprintf(directorystring, "%s/%s", homestring, defaultdirname); } else { sprintf(directorystring, "%s", holdstringpointer); } /* Remove any trailing slashes from directorystring. */ i = strlen(directorystring) - 1; while ( (i>0) && (directorystring[i]=='/') ) { directorystring[i] = '\0'; i--; } /* DEAL WITH DIRECTORY. */ sprintf(commandstring, "test -d %s", directorystring); if (!system(commandstring)) { printf("(Reading from directory %s.)\n", directorystring); } else { sprintf(commandstring, "test -f %s", directorystring); if (!system(commandstring)) { fprintf(stderr, "Oops, %s is a regular file!\n", directorystring); exit(1); } else { sprintf(commandstring, "mkdir %s", directorystring); if (!system(commandstring)) { printf("Creating directory %s ...", directorystring); printf(" done.\n"); sleep(1); } else { fprintf(stderr, "Oops, cannot create directory %s\n", directorystring); exit(1); } } } /* GET CURRENT DAY INFO. */ time(&timeholder); localtimeholder = localtime(&timeholder); currentyear = (*localtimeholder).tm_year + 1900; currentmonth = (*localtimeholder).tm_mon + 1; currentday = (*localtimeholder).tm_mday; currentdayofweek = (*localtimeholder).tm_wday; /* INITIALISE SCREEN DAYS INFO & DATA. */ ypos = 0; xpos = currentdayofweek; newinfo(xpos, ypos, currentyear, currentmonth, currentday, year, month, day, datalines, directorystring); /* INITIALISE THE SCREEN. */ if (getenv("JCALNORESIZE") == NULL) fixsize(); initscr(); cbreak(); OVER = 0; REDRAW = 1; ZSTOPPING = 0; numrep = 0; /* while (TRUE) { c = getchar(); printw("%d %d \n\n", c, c); refresh(); } gives output 27 91 68 for left-arrow, 27 91 67 for right-arrow, 27 91 65 for up-arrow, 27 91 66 for down-arrow, on my home Mac. */ /* MAIN LOOP. */ while (OVER == 0) { if (REDRAW == 1) { /* PRINT THE SCREEN. */ clear(); move(0, 0); /* Print top matter. */ printw("%s", daynameline); printw("%s", separatorline); for (k=0; k<3; k++) { /* Print header line. */ printw("%c", vertchar); for (j=0; j<7; j++) { createheader(month[k][j], day[k][j], tmpstring); printw("%s", tmpstring); printw("%c", vertchar); } printw("\n"); /* Print blank calendar line. */ printw("%s", blankcalline); /* Print data lines. */ for (i=0; i<4; i++) { printw("%c", vertchar); for (j=0; j<7; j++) { printw("%s", datalines[k][j][i]); printw("%c", vertchar); } printw("\n"); } /* Print separator line. */ printw("%s", separatorline); } printw(" move: h,j,k,l,J,K; [e]dit; [p]rint; [t]oday; [?]help; [q]uit "); REDRAW = 0; } /* PRINT POSITION MARKER. */ attron(A_REVERSE); createheader(month[ypos][xpos], day[ypos][xpos], tmpstring); move ( 7*ypos+2 , 11*xpos+1 ); printw("%s", tmpstring); move ( 7*ypos+3 , 11*xpos+1 ); printw("***%4d", year[ypos][xpos]); if (year[ypos][xpos] < 1000000) printw("*"); if (year[ypos][xpos] < 100000) printw("*"); if (year[ypos][xpos] < 10000) printw("*"); attroff(A_REVERSE); /* HANDLE CHARACTER INPUT. */ move(23,75); /* Just move cursor. */ refresh(); keypress = getchar(); /* Deal with arrow-keys, specific to certain terminals types (for now). */ if (keypress==27) { keypress = getchar(); if (keypress==91) { keypress = getchar(); if (keypress==68) { /* They've typed left-arrow. */ keypress = 'h'; } if (keypress==67) { /* They've typed right-arrow. */ keypress = 'l'; } if (keypress==65) { /* They've typed up-arrow. */ keypress = 'k'; } if (keypress==66) { /* They've typed down-arrow. */ keypress = 'j'; } } } if (keypress == '.') { keypress = oldkeypress; numrep = oldnumrep; } else { oldnumrep = numrep; oldkeypress = keypress; } if (keypress == 'Z') { if (ZSTOPPING == 1) OVER = 1; else ZSTOPPING = 1; } else { ZSTOPPING = 0; } if (keypress == 12) { /* ctrl-l */ newinfo(xpos, ypos, year[ypos][xpos], month[ypos][xpos], day[ypos][xpos], year, month, day, datalines, directorystring); REDRAW = 1; } if (keypress == 'q') OVER = 1; if (keypress == '?') { sprintf(commandstring, "%s %s", pager, docpath); endwin(); system("stty susp undef"); /* Disable ^Z. */ system(commandstring); system("stty susp ^Z"); /* Re-enable ^Z. */ if (getenv("JCALNOWAIT") == NULL) { raw(); system("echo -n \"Press any key to return to jcal ... \" "); getchar(); noraw(); cbreak(); } } if ( (keypress=='J') || (keypress==4) /* ctrl-d */ || (keypress==6) /* ctrl-f */ ) { numrep = imax(3, 3*numrep); keypress = 10; /* ctrl-j */ } if ( (keypress=='K') || (keypress==21) /* ctrl-u */ || (keypress==2) /* ctrl-b */ ) { numrep = imax(3, 3*numrep); keypress = 11; /* ctrl-k */ } COPYING = 0; if (keypress == 'D') { COPYING = 1; keypress = 'l'; } if (keypress == 'W') { COPYING = 1; keypress = 'j'; } if (keypress == 'V') { COPYING = 2; strcpy(holdstring, auxfilename); } if (keypress == 'C') { COPYING = 3; strcpy(holdstring, auxfilename); } if (keypress == 24) { /* ctrl-x */ createfilename (year[ypos][xpos], month[ypos][xpos], day[ypos][xpos], tmpstring); sprintf(commandstring, "rm %s/%s\n", directorystring, tmpstring); system(commandstring); getdata(year[ypos][xpos], month[ypos][xpos], day[ypos][xpos], datalines[ypos][xpos], directorystring); REDRAW = 1; } /* if (keypress == KEY_LEFT) { keypress = 'h'; } -- doesn't work! */ if ( (keypress == 'h') || (keypress == 'j') || (keypress == 10) || (keypress == 11) /* ctrl-j or -k */ || (keypress == 'V') || (keypress == 'C') || (keypress == 'm') || (keypress == 'M') || (keypress == 'y') || (keypress == 'Y') || (keypress == 'k') || (keypress == 'l') ) { /* Repeatable movement commands -- repeated numrep times. */ numrep = imax(numrep, 1); keypresshold = keypress; while (numrep-- > 0) { keypress = keypresshold; if (COPYING == 1) createfilename (year[ypos][xpos], month[ypos][xpos], day[ypos][xpos], holdstring); /* Erase position marker. */ move ( 7*ypos+3 , 11*xpos+1 ); printw(" ", year[ypos][xpos]); createheader(month[ypos][xpos], day[ypos][xpos], tmpstring); move ( 7*ypos+2 , 11*xpos+1 ); printw("%s", tmpstring); /* Correct special cases. */ if ( (keypress == 'h') && (xpos == 0) ) { xpos = 6; keypress = 'k'; } if ( (keypress == 'l') && (xpos == 6) ) { xpos = 0; keypress = 'j'; } /* Handle movement. */ if (keypress == 'h') xpos--; if (keypress == 'l') xpos++; if ( (keypress == 'j') || (keypress == 10 /* ctrl-j */) ) { if ( (ypos <= 1) && (keypress=='j') ) { ypos++; } else { /* Shift everything down one week! */ for (k=0; k <= 1; k++) { for (j=0; j < 7; j++) { /* copy [k+1][j] to [k][j] */ year[k][j] = year[k+1][j]; month[k][j] = month[k+1][j]; day[k][j] = day[k+1][j]; for (i=0; i<4; i++) { strcpy(datalines[k][j][i], datalines[k+1][j][i]); } } } /* Create new data for new (later) week. */ tmpyear = year[2][6]; tmpmonth = month[2][6]; tmpday = day[2][6]; for (j=0; j<7; j++) { increment(&tmpyear, &tmpmonth, &tmpday, 1); year[2][j] = tmpyear; month[2][j] = tmpmonth; day[2][j] = tmpday; getdata(tmpyear, tmpmonth, tmpday, datalines[2][j], directorystring); } REDRAW = 1; } } if ( (keypress == 'k') || (keypress == 11 /* ctrl-k */) ) { if ( (ypos >= 1) && (keypress=='k') ) { ypos--; } else { /* Shift everything up one week! */ for (k=2; k >= 1; k--) { for (j=0; j < 7; j++) { /* copy [k-1][j] to [k][j] */ year[k][j] = year[k-1][j]; month[k][j] = month[k-1][j]; day[k][j] = day[k-1][j]; for (i=0; i<4; i++) { strcpy(datalines[k][j][i], datalines[k-1][j][i]); } } } /* Create new data for new (earlier) week. */ tmpyear = year[0][0]; tmpmonth = month[0][0]; tmpday = day[0][0]; for (j=6; j>=0; j--) { decrement(&tmpyear, &tmpmonth, &tmpday, 1); year[0][j] = tmpyear; month[0][j] = tmpmonth; day[0][j] = tmpday; getdata(tmpyear, tmpmonth, tmpday, datalines[0][j], directorystring); } REDRAW = 1; } } if (COPYING >= 1) { createfilename (year[ypos][xpos], month[ypos][xpos], day[ypos][xpos], tmpstring); sprintf(commandstring, "test -f %s/%s", directorystring, tmpstring); existstmp = !system(commandstring); sprintf(commandstring, "test -f %s/%s", directorystring, holdstring); existshold = !system(commandstring); if (COPYING==3) sprintf(commandstring, "cat %s/%s > %s/%s\n", directorystring, tmpstring, directorystring, holdstring); else sprintf(commandstring, "cat %s/%s >> %s/%s\n", directorystring, holdstring, directorystring, tmpstring); /* Check added later: */ if ( ((COPYING==3)&&(existstmp)) || (COPYING<3)&&(existshold) ) system(commandstring); /* else fprintf(stderr, " NO!!!! "); */ getdata(year[ypos][xpos], month[ypos][xpos], day[ypos][xpos], datalines[ypos][xpos], directorystring); if (COPYING<3) REDRAW = 1; } if (keypress == 'm') { tmpdayofweek = ( xpos + monthlength (year[ypos][xpos], month[ypos][xpos]) ) % 7; month[ypos][xpos]++; if (month[ypos][xpos] > 12) { month[ypos][xpos] = 1; year[ypos][xpos]++; } if ( (tmpint = day[ypos][xpos] - monthlength(year[ypos][xpos], month[ypos][xpos])) > 0 ) { day[ypos][xpos] = day[ypos][xpos] - tmpint; tmpdayofweek = tmpdayofweek - tmpint; } if (tmpdayofweek<0) tmpdayofweek = tmpdayofweek + 7; newinfo(tmpdayofweek, ypos, year[ypos][xpos], month[ypos][xpos], day[ypos][xpos], year, month, day, datalines, directorystring); xpos = tmpdayofweek; REDRAW = 1; } if (keypress == 'M') { month[ypos][xpos]--; if (month[ypos][xpos] <= 0) { month[ypos][xpos] = 12; year[ypos][xpos]--; } tmpdayofweek = ( xpos - monthlength (year[ypos][xpos], month[ypos][xpos]) ) % 7; if ( (tmpint = day[ypos][xpos] - monthlength(year[ypos][xpos], month[ypos][xpos])) > 0 ) { day[ypos][xpos] = day[ypos][xpos] - tmpint; tmpdayofweek = tmpdayofweek - tmpint; } if (tmpdayofweek<0) tmpdayofweek = tmpdayofweek + 7; if (tmpdayofweek<0) tmpdayofweek = tmpdayofweek + 7; /* Repeat to handle extremes. */ newinfo(tmpdayofweek, ypos, year[ypos][xpos], month[ypos][xpos], day[ypos][xpos], year, month, day, datalines, directorystring); xpos = tmpdayofweek; REDRAW = 1; } if (keypress == 'y') { /* Do usual day-of-week update. */ tmpdayofweek = xpos + 1; /* Handle leap years. */ if ( ( (month[ypos][xpos]<=2) && (monthlength(year[ypos][xpos],2)==29) ) || ( (month[ypos][xpos]>2) && (monthlength(year[ypos][xpos]+1,2)==29) ) ) tmpdayofweek++; /* Handle Feb 29 special case. */ if ( (month[ypos][xpos] == 2) && (day[ypos][xpos] == 29) ) { day[ypos][xpos]--; tmpdayofweek--; } if (tmpdayofweek>6) tmpdayofweek = tmpdayofweek - 7; /* Increment year. */ year[ypos][xpos]++; /* Read new data. */ newinfo(tmpdayofweek, ypos, year[ypos][xpos], month[ypos][xpos], day[ypos][xpos], year, month, day, datalines, directorystring); xpos = tmpdayofweek; REDRAW = 1; } if (keypress == 'Y') { /* Do usual day-of-week update. */ tmpdayofweek = xpos - 1; /* Handle leap years. */ if ( ( (month[ypos][xpos]>2) && (monthlength(year[ypos][xpos],2)==29) ) || ( (month[ypos][xpos]<=2) && (monthlength(year[ypos][xpos]-1,2)==29) ) ) tmpdayofweek--; /* Handle Feb 29 special case. */ if ( (month[ypos][xpos] == 2) && (day[ypos][xpos] == 29) ) { day[ypos][xpos]--; tmpdayofweek--; } if (tmpdayofweek<0) tmpdayofweek = tmpdayofweek + 7; /* Decrement year. */ year[ypos][xpos]--; /* Read new data. */ newinfo(tmpdayofweek, ypos, year[ypos][xpos], month[ypos][xpos], day[ypos][xpos], year, month, day, datalines, directorystring); xpos = tmpdayofweek; REDRAW = 1; } } /* End of repeatable movement commands. */ } if (keypress == 't') { /* Re-get current day info. */ time(&timeholder); localtimeholder = localtime(&timeholder); currentyear = (*localtimeholder).tm_year + 1900; currentmonth = (*localtimeholder).tm_mon + 1; currentday = (*localtimeholder).tm_mday; currentdayofweek = (*localtimeholder).tm_wday; /* Reset to "today". */ ypos = 0; xpos = currentdayofweek; newinfo(xpos, ypos, currentyear, currentmonth, currentday, year, month, day, datalines, directorystring); REDRAW = 1; } if (keypress == 'e') { createfilename (year[ypos][xpos], month[ypos][xpos], day[ypos][xpos], tmpstring); sprintf(commandstring, "%s %s/%s\n", editcommand, directorystring, tmpstring); clear(); refresh(); nocbreak(); endwin(); system(commandstring); cbreak(); system("stty -echo -onlcr"); /* Fix problems from e.g. vi. */ getdata(year[ypos][xpos], month[ypos][xpos], day[ypos][xpos], datalines[ypos][xpos], directorystring); REDRAW = 1; } if (keypress == 'A') { sprintf(commandstring, "%s %s/%s\n", editcommand, directorystring, auxfilename); clear(); refresh(); nocbreak(); endwin(); system(commandstring); cbreak(); system("stty -echo -onlcr"); /* Fix problems from e.g. vi. */ REDRAW = 1; } if (keypress == 'p') { /* Create new data for new (later) weeks. */ tmpyear = year[2][6]; tmpmonth = month[2][6]; tmpday = day[2][6]; for (k=3; k<6; k++) { for (j=0; j<7; j++) { increment(&tmpyear, &tmpmonth, &tmpday, 1); year[k][j] = tmpyear; month[k][j] = tmpmonth; day[k][j] = tmpday; getdata(tmpyear, tmpmonth, tmpday, datalines[k][j], directorystring); } } /* Create file "toprint". */ sprintf(tmpstring, "%s/toprint", directorystring); if ((pfp = fopen(tmpstring, "w")) == NULL) { fprintf(stderr, "Unable to write to file %s.\n", tmpstring); exit(1); } else { /* Obtain current date. */ time(&timeholder); localtimeholder = localtime(&timeholder); asctimept = asctime(localtimeholder); sprintf(asctimeholder, "%s", asctimept); asctimeholder[strlen(asctimeholder)-1] = '\0'; /* Overwrite \n. */ /* Print top matter. */ createmonthname(month[0][0], holdinitmonthname); createmonthname(month[5][6], holdlastmonthname); fprintf(pfp, "\n\n JCAL OUTPUT FOR %s %d, %d TO %s %d, %d.\n\n\n", holdinitmonthname, day[0][0], year[0][0], holdlastmonthname, day[5][6], year[5][6] ); fprintf(pfp, " Directory: %s\n", directorystring); if ( (holdstringpointer = getenv("HOSTNAME")) != NULL) fprintf(pfp, " Host: %s\n", holdstringpointer); fprintf(pfp, " Date: %s\n\n\n", asctimeholder); fprintf(pfp, "%s", daynameline); fprintf(pfp, "%s", separatorline); for (k=0; k<6; k++) { /* Print header line. */ fprintf(pfp, "%c", vertchar); for (j=0; j<7; j++) { createheader(month[k][j], day[k][j], tmpstring); fprintf(pfp, "%s", tmpstring); fprintf(pfp, "%c", vertchar); } fprintf(pfp, "\n"); /* Print blank calendar line. */ fprintf(pfp, "%s", blankcalline); /* Print data lines. */ for (i=0; i<4; i++) { fprintf(pfp, "%c", vertchar); for (j=0; j<7; j++) { fprintf(pfp, "%s", datalines[k][j][i]); fprintf(pfp, "%c", vertchar); } fprintf(pfp, "\n"); } /* Print separator line. */ fprintf(pfp, "%s", separatorline); } fprintf(pfp, "\n"); fclose(pfp); /* Give option to print. */ move(23,0); for (i=0; i<7; i++) printw(" "); /* Clear bottom line. */ move(23,0); printw(" print command (ctrl-a to abort) [%s]: ", printcommand); refresh(); /* fgets(tmpstring, 60, stdin); */ i = 0; c = getchar(); while ( (c!=10) && (c!=13) && (c!=1) /* ctrl-a */ && (i<60) ) { if ( (c=='\b') /* backspace */ || (c==127) /* delete */ ) { if (i>0) { i=i-1; printw("\b"); } } else { tmpstring[i] = c; i++; printw("%c", c); } refresh(); c = getchar(); } tmpstring[i] = '\0'; if (c!=1) /* ctrl-a */ { move(23,0); for (j=0; j<7; j++) printw(" "); /* Clear bottom line. */ move(23,0); printw(" Printing ..."); refresh(); if (strlen(tmpstring)>0) { strcpy(printcommand, tmpstring); } sprintf(commandstring, "%s %s/toprint\n", printcommand, directorystring); system("stty susp undef"); /* Disable ^Z. */ system("stty onlcr"); if (!system(commandstring)) { printw(" done."); } system("stty -onlcr"); system("stty susp ^Z"); /* Re-enable ^Z. */ refresh(); sleep(2); } REDRAW = 1; } /* end if(fopen) statement */ } /* end of 'p' case */ if ( (keypress >= '0') && (keypress <= '9') && (numrep<1000) ) { numrep = 10*numrep + (keypress - '0'); } else { numrep = 0; } refresh(); } /* End of while loop. */ /* WRAP UP. */ if (LINES < 26) { move(23,0); for (i=0; i<7; i++) printw(" "); /* Clear bottom line. */ } refresh(); nocbreak(); endwin(); return(0); } increment(int *pyear, int *pmonth, int *pday, int numdays) { if (numdays <= monthlength(*pyear, *pmonth) - *pday) { *pday = *pday + numdays; } else { *pday = *pday + numdays - monthlength(*pyear, *pmonth); if (*pmonth == 12) { *pyear = *pyear + 1; *pmonth = 1; } else { *pmonth = *pmonth + 1; } } return(0); } decrement(int *pyear, int *pmonth, int *pday, int numdays) { if (numdays < *pday) { *pday = *pday - numdays; } else { if (*pmonth == 1) { *pyear = *pyear - 1; *pmonth = 12; } else { *pmonth = *pmonth - 1; } *pday = *pday - numdays + monthlength(*pyear, *pmonth); } return(0); } monthlength( theyear, themonth) { if (themonth == 2) { if( divisible(theyear,4) && (!divisible(theyear,100) || divisible(theyear,400)) ) { return(29); } else { return(28); } } /* return(daysinmonth[themonth]); */ if ((themonth==9) || (themonth==4) || (themonth==6) || (themonth==11)) { return(30); } return(31); } divisible (int aaa, int bbb) { return ( (bbb*(aaa/bbb) == aaa) ); } createfilename (int theyear, int themonth, int theday, char *thetmpstring) { if (themonth < 10) { if (theday < 10) { sprintf(thetmpstring, "%d-0%d-0%d", theyear, themonth, theday); } else { sprintf(thetmpstring, "%d-0%d-%d", theyear, themonth, theday); } } else { if (theday < 10) { sprintf(thetmpstring, "%d-%d-0%d", theyear, themonth, theday); } else { sprintf(thetmpstring, "%d-%d-%d", theyear, themonth, theday); } } return(0); } createheader (int themonth, int theday, char *thetmpstring) { char monthname[5]; createmonthname(themonth, monthname); if (theday < 10) { sprintf(thetmpstring, " %s %d ", monthname, theday); } else { sprintf(thetmpstring, " %s %d ", monthname, theday); } return(0); } createmonthname (int themonth, char themonthname[5]) { switch (themonth) { case 1: strcpy(themonthname,"JAN"); break; case 2: strcpy(themonthname,"FEB"); break; case 3: strcpy(themonthname,"MAR"); break; case 4: strcpy(themonthname,"APR"); break; case 5: strcpy(themonthname,"MAY"); break; case 6: strcpy(themonthname,"JUN"); break; case 7: strcpy(themonthname,"JUL"); break; case 8: strcpy(themonthname,"AUG"); break; case 9: strcpy(themonthname,"SEP"); break; case 10: strcpy(themonthname,"OCT"); break; case 11: strcpy(themonthname,"NOV"); break; case 12: strcpy(themonthname,"DEC"); break; default: strcpy(themonthname,"???"); break; } return(0); } getdata (int theyear, int themonth, int theday, char thedata[5][12], char *thedirectorystring) { FILE *dp; char thestring[402]; char filename[82]; int ii, t; createfilename(theyear, themonth, theday, thestring); sprintf(filename, "%s/%s", thedirectorystring, thestring); if ((dp = fopen(filename, "r")) == NULL) { for (ii=0; ii<4; ii++) sprintf( thedata[ii], " "); } else if ( (t=fgetc(dp)) == EOF) { for (ii=0; ii<4; ii++) sprintf( thedata[ii], " "); fclose(dp); } else { ungetc(t, dp); ii = 0; t = 5; while ( (t != EOF) && (ii < 4) ) { fgets(thestring, 400, dp); if ( (thestring[0] != '#') && (thestring[0] != '%') ) { if (thestring[strlen(thestring)-1] == '\n') thestring[strlen(thestring)-1] = '\0'; /* remove new-line */ if (getenv("JCALNOCENTER") == NULL) { if (strlen(thestring)<=8) prepend(thestring, " "); if (strlen(thestring)<=7) prepend(thestring, " "); /* center if short */ } strcat(thestring, " "); /* pad with spaces */ thestring[10] = '\0'; /* Truncate at ten characters. */ sprintf( thedata[ii], thestring); ii++; } /* Check for EOF. */ t = getc(dp); if (t != EOF) ungetc(t, dp); } for ( ; ii < 4; ii++) { /* Fill any remaining lines. */ sprintf( thedata[ii], " "); } fclose(dp); } return(0); } imax(int aa, int bb) { if (aa>bb) return(aa); return(bb); } newinfo( int xpos, int ypos, int theyear, int themonth, int theday, int year[6][7], int month[6][7], int day[6][7], char datalines[7][8][5][12], char directorystring[82] ) { int j, k; int tmpyear, tmpmonth, tmpday; year[ypos][xpos] = tmpyear = theyear; month[ypos][xpos] = tmpmonth = themonth; day[ypos][xpos] = tmpday = theday; getdata(tmpyear, tmpmonth, tmpday, datalines[ypos][xpos], directorystring); j = xpos - 1; k = ypos; while (k >= 0) { while (j >= 0) { decrement(&tmpyear, &tmpmonth, &tmpday, 1); year[k][j] = tmpyear; month[k][j] = tmpmonth; day[k][j] = tmpday; getdata(tmpyear, tmpmonth, tmpday, datalines[k][j], directorystring); j--; } j=6; k--; } tmpyear = theyear; tmpmonth = themonth; tmpday = theday; j = xpos + 1; k = ypos; while (k < 3) { while (j < 7) { increment(&tmpyear, &tmpmonth, &tmpday, 1); year[k][j] = tmpyear; month[k][j] = tmpmonth; day[k][j] = tmpday; getdata(tmpyear, tmpmonth, tmpday, datalines[k][j], directorystring); j++; } j = 0; k++; } return(0); } prepend (char *str1, char *str2) { char tmpstring[170]; sprintf(tmpstring, "%s%s", str2, str1); strcpy(str1, tmpstring); return(0); } /* FIXSIZE: Compute number of columns and lines from "resize" output. */ /* Somewhat awkward; there must be a more direct way. */ /* Note that commands like numlines = tigetnum("lines"); numcolumns = tigetnum("cols"); only propogate curses' errors. */ /* Necessary since initscr() sometimes gets number of lines wrong, depending on terminfo entry. */ fixsize() { FILE *sfp; int c; char commandstring[100]; int numcolumns, numlines; if ( (getenv("COLUMNS")==NULL) || (getenv("COLUMNS")==NULL) ) { numcolumns = numlines = 0; if ( (sfp = popen("resize -u", "r")) != NULL ) { c = fgetc(sfp); while (c != EOF) { if (c == 'C') { if ( (fgetc(sfp) == 'O') && (fgetc(sfp) == 'L') && (fgetc(sfp) == 'U') && (fgetc(sfp) == 'M') && (fgetc(sfp) == 'N') && (fgetc(sfp) == 'S') && (fgetc(sfp) == '=') ) { numcolumns = 0; while ( ( (c = fgetc(sfp)) >= '0') && (c <= '9') ) numcolumns = 10*numcolumns + (c - '0'); } } else if (c == 'L') { if ( (fgetc(sfp) == 'I') && (fgetc(sfp) == 'N') && (fgetc(sfp) == 'E') && (fgetc(sfp) == 'S') && (fgetc(sfp) == '=') ) { numlines = 0; while ( ( (c = fgetc(sfp)) >= '0') && (c <= '9') ) numlines = 10*numlines + (c - '0'); } } c = fgetc(sfp); } pclose(sfp); } numcolumns = imax(numcolumns, 80); sprintf(commandstring, "COLUMNS=%d", numcolumns); putenv(commandstring); numlines = imax(numlines, 24); sprintf(commandstring, "LINES=%d", numlines); putenv(commandstring); } return(0); }