/***************************************************************************** calend.c calender program v1.0 copywrite: Harold Z. Bencowitz Beaumont, Texas 10-mar-87 ****************************************************************************** description: calender is a program written in whitesmith's C to display the calender for the selected month. it will accept and year from 1983 - 32000. the program has been tested only on a PDP-11/73 system under TSX+ v6.16. it requires a vt100 or vt200 series terminal. operating instructions: run calend month,year or run calend month year or calend > month must be a number 1 - 12. if the year is < 100, 1900 is added ie one can enter 1987 or 87. if no month or year is given, the current date is used. once the initial calender is displayed, the arrow keys are active. up and down will increase and decrease the year whereas right and left will increase and decrease the month. the program can be terminated by control-c or . it will not run unless the terminal is a vt1** or vt2**. revision history: v1.0 completed march 10, 1987 installation/building: the distribution kit consists of calend.c (source code), vt.(c, obj) (video terminal library), hclib (c, obj) (my c library), and calend.sav. to compile the Whitesmith's C compiler (and library) is needed. ttt *****************************************************************************/ #include #include #define MODE 8 #define ROW 1 #define COL 51 #define ERROR -1 #define DELETE 22 int main(ac, av) int ac; char **av; { int process(), istsx(), call_emt(), enter(), ttflush(), vtttid(); int vtesc(), btoi(), instr(), lenstr(), date(); int d[3], i, k, l; unsigned int ijob; extern int nmonth, year; /* * parse command line arguments to month and year */ i = instr(av[1], "="); l = lenstr(av[1]) - i - 1; k = l - i - 1; if(av[1][i] != '\0') { btoi(av[1], i, &year, 10); btoi(&av[1][i+1], k, &nmonth, 10); } else if(av[1][(i = instr(av[1], ","))] != '\0') { btoi(av[1], i, &nmonth, 10); btoi(&av[1][i+1], k, &year, 10); } else { date(d); nmonth = d[0]; year = d[2]; } /* * get day of week of first day of month and number of days */ if(year < 100) year += 1900; /* * set TSX singlechar mode, find terminal type */ if(istsx()) /* if running TSX+ */ i = call_emt(0152, 0, 'S'); /* set singlechar mode */ if(i < 0) { putstr(STDERR,"\ncalender - unable to set singlechar mode\n",NULL); exit(); } i = vtttid(); /* get terminal type */ if(i != 200) { putstr(STDERR,"\ncalender - illegal terminal type, not vt200\n",NULL); exit(); } /* * set terminal special mode, arrows to application mode */ ijob = JSW; JSW = ijob | 010000; vtesc("[?1h"); /* arrow key application mode */ ttflush(); /* * await keyboard input */ while(enter(&process)) /* respond to keyboard input */ ; /* * reset terminal and JSW */ JSW = ijob; /* reset JSW */ vtesc("[?1l"); /* arrow key movement mode */ } /****************************************************************************/ int cal_display() { static char d_month[]={31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30,31}; char ns[18], ds[31]; char *cpystr(), *month(); register int i, j, k; static int rowlast = 0; int day_1, row, dthismonth; int d_of_week(), lenstr(), center_text(), itob(), is_leap(); extern int year, nmonth; if(nmonth < 1) { nmonth = 12; --year; } if(nmonth > 12) { nmonth = 1; ++year; } if((day_1 = d_of_week(1, nmonth, year)) < 0) { putstr(STDERR,"\ncalender - month or year out of range\n",NULL); exit(); } if(is_leap(year)) d_month[1] = 29; else d_month[1] = 28; dthismonth = d_month[nmonth-1]; ds[30] = '\0'; cpystr(ns, month(nmonth), " ", NULL); i = lenstr(ns); i += itob(&ns[i], year, 10); ns[i] = '\0'; center_text(ds, ns, 30, ' '); row = ROW; vtmode(MODE); vttxt(row++, COL, " "); vttxt(row++, COL, ds); vttxt(row++, COL, " "); vttxt(row++, COL, " Sun Mon Tue Wed Thr Fri Sat "); vttxt(row++, COL, " "); for(k = 0; k < 30; k++) ds[k] = ' '; for(j = 3, i = 1; i <= dthismonth; i++) { if(i == 10) j--; itob(&ds[day_1 * 4 + j], i, 10); if(++day_1 > 6 || i >= dthismonth) { day_1 = 0; vttxt(row++, COL, ds); for(k = 0; k < 30; k++) ds[k] = ' '; } } vttxt(row, COL," "); vtmode(0); for(i = 1; i <= rowlast - row; i++) vttxt(row+i, COL," "); rowlast = row; vtmova(23, 0); } /****************************************************************************/ int is_leap(year) /* given the year, returns YES if it was a leapyear */ int year; { if((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) return(YES); else return(NO); } /****************************************************************************/ int d_of_week(day, nmonth, year) /* determines the day of the week given the date. the day of the week is returned as an integer 0 - 6 for Sunday through Saturday. inappropriate arguments result in a return of < 0. years must be no earlier than 1583. internally months are 0 - 11, days and years are the true value. */ int day, nmonth, year; { static char d_month[]={31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30,31}; register int i, dweek, d_this_year; int leap_years(), is_leap(); if(year < 1583 || year > 32000) return(-1); nmonth--; if(nmonth < 0 || nmonth > 11) return(-2); if(is_leap(year)) d_month[1] = 29; else d_month[1] = 28; if(day < 1 || day > d_month[nmonth]) return(-3); /* * */ for(d_this_year = 0, i = 0; i < nmonth; i++) d_this_year += d_month[i - 0]; d_this_year += day; /* * days this year is the number of days since jan 1 of the * current year. the day of the week is increased one day for every * year except +2 in leap years (thus (year-1583)+nleap) where nleap is * the number of leap years since 1583. jan 1, 1583 was a saturday * (ie day 6). */ dweek = d_this_year + (year - 1583) + leap_years(year) + 5; dweek %= 7; return(dweek); } /****************************************************************************/ int leap_years(year) /* given the year, returns the number of leap years since 1583. */ register int year; { register int nleap = 0, centuries; int is_leap(); if(year <= 1583) return(0); centuries = (year - 1600) / 100; nleap = centuries * 24 + (year / 400 - 3); /* 24 per century */ /* plus one every 400 years */ if(year >= 1600) /* number in current century */ nleap += ((year % 100) / 4) + 4; /* 1600 added above */ else nleap += (year - 1584) / 4 + 1; if(is_leap(year)) nleap--; return(nleap); } /****************************************************************************/ int vtesc(s) /* output string s to STDERR preceded by . */ char *s; { int putstr(); putstr(STDERR, "", s, NULL); } /****************************************************************************/ int key() /* get input from one keyboard key. returns code value. */ { char c, cc[2], cget(); int code; /* * */ if((c = cget()) != ESCAPE) switch (c) { case '\177': code = DELETE; break; default: return(ERROR); } else if((c = cget()) == 'O') { /* SS3 introducer */ c = cget(); switch (c) { case 'A': /* arrows */ code = UP; break; case 'B': code = DOWN; break; case 'C': code = RIGHT; break; case 'D': code = LEFT; break; default: return(ERROR); } } return(code); } /****************************************************************************/ int process() /* process the responses to keystrokes */ { int code; int key(), leave(), cal_display(); extern nmonth, year; cal_display(); FOREVER { code = key(); if(code == DELETE) leave(NO); else if(code == UP) { ++year; cal_display(); } else if(code == DOWN) { --year; cal_display(); } else if(code == RIGHT) { ++nmonth; cal_display(); } else if(code == LEFT) { --nmonth; cal_display(); } else errfmt(""); } } /****************************************************************************/ int nmonth = 0, year = 0;