home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
net
/
vcal.2
< prev
next >
Wrap
Internet Message Format
|
1987-02-20
|
89KB
From me@pinot Thu Jan 29 20:34:50 1987
Path: beno!seismo!rutgers!sri-spam!ames!lll-lcc!ptsfa!varian!zehntel!me@pinot (Mike Essex)
From: me@pinot (Mike Essex)
Newsgroups: net.sources
Subject: visual calendar and activities programs, part 2
Message-ID: <137@zehntel.UUCP>
Date: 30 Jan 87 01:34:50 GMT
Sender: news@zehntel.UUCP
Organization: Zehntel Inc., Walnut Creek CA
Lines: 2080
echo x - README
sed 's/^X//' >README <<'*-*-END-of-README-*-*'
X VCAL AND FRIENDS 1/29/87
X
Xdef.: a set of calendar and appointment utility programs to replace
X the traditional paper calendar.
X
XVcal and friends allow the user to view a calendar, enter dates and
Xtimes of activities, set times for prompts to the CRT and to produce
Xlists of a month's activities. Multiple data files may be used to
Xallow the user to have one calendar for personal activities, one for
Xbusiness activities, one for project milestones, etc.
X
XThese programs are written in 'C' and run under UNIX. To date they
Xhave been compiled and execute on the following systems:
X
XDEC PDP 11/70 UNIX Version 7
XDEC VAX 11/750 UNIX BSD 4.2 and 4.3
XSun 2/170 UNIX BSD 4.2
XSun 3/160 UNIX BSD 4.2
XSun 3/260 UNIX BSD 4.2
X
XIncluded in this package are six source files, six manual files, a
Xmakefile and this introduction. The makefile is for use with the
Xstandard "make" utility on a VAX 11/750 under BSD 4.3. For use with
Xa PDP 11/70 BSD Version 7 change the makefile library entry from
X"termlib" to "termcap".
X
XAll the "vcal" files have been combined here with the "shar" script.
XSince the combined size of the files are greater than 65,000
Xcharacters they have been broken into two parts for transmission.
XPart 1 contains makefile, appts.c, autocall.c and callme.c along
Xwith the manual pages for these. Part 2 contains eappts.c, lcal.c
Xand vcal.c and their manual pages.
X
XSynopsis of files:
X
Xappts displays the current or specified day's activities
X
Xautocall starts background reminder processes for each of the
X current day's activities
X
Xcallme starts a background reminder process for a specified
X time and activity
X
Xeappts allows activities to be entered into a data file from
X the command line
X
Xlcal produces a tabular listing of the current or specified
X month's activities
X
Xvcal visual calendar displaying the current or specified
X month's activities; allows entries to be added, changed
X or deleted
X
Xmakefile makefile for all of the "vcal" programs
X
Xmanual pages: appts.l autocall.l callme.l eappts.l lcal.l vcal.l
X
XComments and suggestions will be appreciated and considered.
X
XMike Essex (~me)
X
X ....!ucbvax!zehntel!me
X ....!decvax!sytek!zehntel!me
X ...."zehntel!me"@BERKELEY
*-*-END-of-README-*-*
echo x - eappts.c
sed 's/^X//' >eappts.c <<'*-*-END-of-eappts.c-*-*'
X/*
X * Module: eappts.c
X *
X * Purpose: enters data into appointments file
X *
X * Author: Mike Essex
X *
X * Date: Sep. 16, 1986
X *
X * Includes:
X * stdio.h
X * Discussion:
X * Inputs data from standard input and writes it to ~/.appointments
X * file
X *
X *
X * Edit History
X * ==== =======
X *
X * Date Who What
X * ---- --- ----------------------------------------------
X * 12/1/86 me added multifile capability
X * 12/1/86 me changed 'home' from *home[80] to home[80]
X *
X */
X
X#include <stdio.h>
X#define NL '\010'
X
X
X/*
X * Procedure: main
X *
X * Function: inputs data and writes to users .appointments file
X *
X * Discussion:
X * Prompts users for required appointment information, inputs
X * that info and then appends it to ~/.appointments file.
X */
X
Xmain(argc,argv)
X
Xint argc;
Xchar *argv[];
X
X{
X FILE *fptr;
X char tmpbuf[80];
X int i,j;
X char *getenv();
X char home[80];
X char datedata[20];
X char timedata[20];
X char msgdata[40];
X int month,day,year,time;
X int index[5];
X
X if (argc == 2) {
X strcpy(home,argv[1]);
X }
X else {
X strcpy(home,getenv("HOME"));
X strcat(home,"/.appointments");
X }
X
X fptr = fopen(home,"a");
X if (fptr) {
X printf("What is the date of appointment? (mm dd yyyy) ");
X fgets(datedata,20,stdin);
X i = 0;
X j = 0;
X while(i < 20) {
X while ((i < 20) && (datedata[i] == ' ')) i++;
X index[j++] = i;
X while ((i < 20) && (datedata[i] != ' ')) i++;
X }
X month = atoi(&datedata[index[0]]);
X day = atoi(&datedata[index[1]]);
X year = atoi(&datedata[index[2]]);
X if (year < 100) year += 1900;
X
X printf("What time (24 hour time) is the appointment? (tttt) ");
X fgets(timedata,20,stdin);
X time = atoi(timedata);
X printf("What is the message? (32 characters max) ");
X fgets(msgdata,34,stdin);
X msgdata[strlen(msgdata)-1] = NULL;
X fprintf(fptr,"%d,%d,%d,%4d,%s\n",month,day,year,time,msgdata);
X }
X else {
X printf("Error: Cannot open %s file",argv[1]);
X abort();
X }
X fclose(fptr);
X} /* main */
*-*-END-of-eappts.c-*-*
echo x - lcal.c
sed 's/^X//' >lcal.c <<'*-*-END-of-lcal.c-*-*'
X/*
X * Module: lcal.c
X *
X * Purpose: print month's appointments
X *
X * Author: Mike Essex
X *
X * Date: Sep. 16, 1986
X *
X * Includes:
X * time.h, stdio.h, ctype.h, signal.h
X *
X * Discussion:
X * Reads data from ~/.appointments and/or designated file and
X * writes to standard * out any appoinments which fall in
X * the current or optionally specified month.
X *
X *
X * Edit History
X * ==== =======
X *
X * Date Who What
X * ---- --- ----------------------------------------------
X *
X */
X
X#include <stdio.h>
X#include <signal.h>
X#include <ctype.h>
X#include <time.h>
X
X
Xchar *malloc();
X
Xint monthdata[1000]; /* month data */
Xint daydata[1000]; /* month data */
Xint yeardata[1000]; /* month data */
Xchar *msgdata[1000]; /* message pointers */
Xchar msghold[40];
Xint maxentries;
Xint maxmsgs;
Xint cmonth,cday,cyear;
Xint argvindex;
X
X
X
X/*
X * Procedure: main()
X *
X * Function: prints out listing of appointments
X *
X * Discussion:
X * Parses command line for optional month and year, initializes
X * varialbes, calls required funtions.
X */
X
Xmain (argc,argv)
X
X int argc;
X char *argv[];
X{
X
X int month,day,year;
X int i;
X int tempmonth,tempyear;
X int atoi();
X int maxindex;
X extern int abort();
X
X timeset();
X year = cyear;
X month = cmonth;
X day = cday;
X
X if (argc > 2) {
X tempmonth = atoi(argv[1]);
X tempyear = atoi(argv[2]);
X if (tempmonth && tempyear){
X month = tempmonth;
X year = tempyear;
X if (year < 100) year += 1900;
X if (argc > 3) {
X argvindex = 3;
X maxindex = argc;
X }
X else {
X argvindex = 0;
X maxindex = 1;
X }
X }
X else {
X if (tempmonth || tempyear) {
X printf("Syntax error: Incorrect date arguments\n");
X exit(1);
X }
X else {
X argvindex = 1;
X maxindex = argc;
X }
X }
X }
X else {
X if (argc == 1) {
X argvindex = 0;
X maxindex = argc;
X }
X else {
X argvindex = 1;
X maxindex = argc;
X }
X }
X
X
X signal(2,abort);
X signal(3,abort);
X
X day = 1;
X maxentries = 1000;
X maxmsgs = 18;
X msghold[0] = NULL;
X
X printf(" C A L E N D A R L I S T\n");
X while (argvindex < maxindex) {
X loaddata(argv[argvindex]);
X table(month,day,year,argv[argvindex]);
X argvindex++;
X }
X
X printf("------------------------------------------------------------------------------\n");
X} /* main */
X
X
X/*
X * Procedure: abort()
X *
X * Function: error exit routine
X */
X
Xabort()
X
X{
X exit(1);
X} /* abort */
X
X
X/*
X * Procedure: table(month,day,year)
X *
X * Function: outputs appointments in tabular format
X *
X * Parameters:
X * p1 - int - month
X * p2 - int - day
X * p3 - int - year
X * p3 - char * - file name
X *
X * Discussion:
X * Searches data arrays for appointments in the specified
X * month and year and outputs them in tabular form to standard out.
X */
X
Xtable(month,day,year,filename)
X
X int month,day,year;
X char *filename;
X
X{
X int i,j,k,d,dow,monthday,searchcnt,first;
X int getdow();
X
X static char *dayw[]= {
X "Sat ","Sun ","Mon ", "Tue ",
X "Wed ", "Thu ", "Fri "
X };
X
X static char *smon[]= {
X "JANUARY ", "FEBRUARY ", "MARCH ", "APRIL ",
X "MAY ", "JUNE ", "JULY ", "AUGUST ",
X "SEPTEMBER ", "OCTOBER ", "NOVEMBER ", "DECEMBER "
X };
X
X printf("------------------------------------------------------------------------------\n");
X if (argvindex) {
X printf("| %-10.10s%u %30.30s |\n", smon[month-1], year,filename);
X }
X else {
X printf("| %-10.10s%u |\n", smon[month-1], year);
X }
X monthday = 0;
X while (++monthday <= 31) {
X searchcnt = 0;
X first = 1;
X while (searchcnt <= maxentries) {
X if ((yeardata[searchcnt] == year) &&
X (monthdata[searchcnt] == month) &&
X (daydata[searchcnt] == monthday)) {
X if (first) {
X dow = getdow(month,monthday,year);
X first = 0;
X /* printf("|----------------------------------------------------------------------------|\n"); */
X printf("| |\n");
X printf("| %-7.7s%2d %-64.64s|\n",dayw[dow],monthday,msgdata[searchcnt]);
X }
X else {
X printf("| %-64.64s|\n",msgdata[searchcnt]);
X }
X }
X searchcnt++;
X }
X }
X} /* table */
X
X
X/*
X * Procedure: getdow(tmonth,tday,tyear)
X *
X * Function: calculates day of week
X *
X * Parameters:
X * p1 - int - month
X * p2 - int - day
X * p3 - int - year
X *
X * Return Values:
X * interger value of day of week, sat=0, . . ., etc
X *
X * Discussion:
X * calculates number of days from 1,1,1979 and determines dow
X */
X
Xgetdow(tmonth,tday,tyear)
X
X int tmonth,tday,tyear;
X{
X
X static int mdays[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
X int month,day,year,mcnt;
X long days;
X int tdow;
X
X month = 1;
X day = 1;
X year = 79;
X
X if ((tmonth == month) && (tyear == year)) {
X days = abs(day - tday);
X }
X else {
X days = mdays[month] - day;
X if (tyear == year) {
X while (++month < tmonth) {
X days += mdays[month];
X if ((month == 2) && ((year % 4) == 0)) days++;
X }
X }
X else {
X while (++month < 13) {
X days += mdays[month];
X if ((month == 2) && ((year % 4) == 0)) days++;
X }
X while (++year < tyear) {
X days += 365;
X if ((year % 4) == 0 ) days ++;
X }
X
X mcnt = 0;
X while (++mcnt < tmonth) {
X days += mdays[mcnt];
X if ((mcnt == 2) && ((tyear % 4) == 0)) days++;
X }
X }
X days += tday;
X }
X
X tdow = (days%7);
X
X return(tdow);
X} /* get dow */
X
X
X/*
X * Procedure: loaddata()
X *
X * Function: loads appointment data from ~/.appointments file
X *
X * Return Values:
X * various global arrays loaded with appointment data
X *
X */
X
Xloaddata(filename)
X
Xchar *filename;
X
X{
X char basedata[80];
X char tmpbuf[80];
X char *getenv();
X char home[80];
X FILE *fptr;
X int i,j,k,l,field;
X
X i = 0;
X while (i < maxentries) {
X daydata[i] = 0;
X monthdata[i] = 0;
X yeardata[i] = 0;
X msgdata[i] = 0;
X i++;
X }
X
X
X if (argvindex == 0) {
X strcpy(home,getenv("HOME"));
X strcat(home,"/.appointments");
X }
X else {
X strcpy(home,filename);
X }
X if ((fptr = fopen(home,"r")) != NULL) {
X i = 0;
X while((fgets(basedata,80,fptr) != NULL)) {
X
X basedata[strlen(basedata)-1] = NULL;
X
X j = 0;
X k = 0;
X field = 0;
X while (basedata[j] != NULL ) {
X
X if (basedata[j] != ',') {
X
X tmpbuf[k++] = basedata[j];
X }
X else {
X switch (field) {
X
X case 0 : {
X tmpbuf[k] = NULL;
X monthdata[i] = atoi(tmpbuf);
X k = 0;
X break;
X }
X case 1 : {
X tmpbuf[k] = NULL;
X daydata[i] = atoi(tmpbuf);
X k = 0;
X break;
X }
X case 2 : {
X tmpbuf[k] = NULL;
X yeardata[i] = atoi(tmpbuf);
X k = 0;
X break;
X }
X case 3 : {
X tmpbuf[k++] = ' ';
X tmpbuf[k++] = ' ';
X break;
X }
X }
X field++;
X }
X j++;
X }
X tmpbuf[k] = '\0';
X msgdata[i] = malloc(40);
X strcpy(msgdata[i],tmpbuf);
X
X if (i >= maxentries) {
X printf("Warning: Over 1000 entries in %s file. Data truncated.\n",filename);
X break;
X }
X i++;
X }
X fclose(fptr);
X }
X else {
X printf("Error: Cannot open %s file.\n",filename);
X }
X} /* loaddata */
X
X
X/*
X * Procedure: timeset()
X *
X * Function: Gets current time and date
X *
X * Return Values:
X * loads time and date info into global variables
X *
X */
X
Xtimeset()
X
X{
X struct tm *localtime();
X
X struct tm *tp; /* time structure */
X long tloc; /* number of seconds since 1970 */
X
X time(&tloc); /* fills tloc */
X
X tp = localtime(&tloc);
X
X cyear = tp->tm_year;
X cmonth = tp->tm_mon + 1;
X cday = tp->tm_mday;
X
X cyear += 1900;
X
X} /* timeset */
*-*-END-of-lcal.c-*-*
echo x - vcal.c
sed 's/^X//' >vcal.c <<'*-*-END-of-vcal.c-*-*'
X/*
X * Module: vcal.c
X *
X * Purpose: visual appointment calendar
X *
X * Author: Mike Essex
X *
X * Date: Sep. 16, 1986
X *
X * Includes:
X * time.h, stdio.h, ctype.h, signal.h
X *
X * Discussion:
X * displays a calendar to the screen for the current or optionally
X * specified month. User may move the cursor any day of the month
X * and view or enter appointments for that date.
X *
X *
X * Edit History
X * ==== =======
X *
X * Date Who What
X * ---- --- ----------------------------------------------
X *11/25/86 me added multiple data file capability
X *11/25/86 me fixed array "home" from *home[80] to home[80]
X *11/25/86 me fixed "space" and "area" to be global
X *11/26/86 me changed help message routines
X *
X */
X
X#include <stdio.h>
X#include <signal.h>
X#include <ctype.h>
X#include <time.h>
X
X#define CR '\012'
X#define BS '\010'
X#define ESC '\033'
X
Xint mon[] = {
X 0,
X 31, 29, 31, 30,
X 31, 30, 31, 31,
X 30, 31, 30, 31,
X};
X
Xchar space[BUFSIZ]; /* used by area */
Xchar *area = space; /* termcap required variable */
Xchar *CM; /* cursor motion */
Xchar *CL; /* clear screen */
Xchar *TI; /* begin cm */
Xchar *TE; /* end cm */
Xchar *SO; /* standout*/
Xchar *SE; /* end standout*/
Xchar *UP; /* up doda */
Xint SG;
Xchar * tgoto();
Xchar *malloc();
Xchar tcolumns = 0; /* terminal columns */
Xchar tlines = 0; /* terminal lines */
X
Xint xposition[32]; /* calendar x axis position */
Xint yposition[32]; /* calendar y axis position */
Xint active[33]; /* highlight day array */
X
Xint monthdata[1000]; /* month data */
Xint daydata[1000]; /* month data */
Xint yeardata[1000]; /* month data */
Xchar *msgdata[1000]; /* message pointers */
Xchar msghold[40];
Xint dayindex[18]; /* index to day's msgs */
Xint maxentries;
Xint maxmsgs;
Xint tmonth,tday,tyear;
X
Xint maxchars;
Xint notclear;
Xint help1,help2; /* help message flags */
X
Xchar dayw[] = {
X " S M T W T F S "
X};
X
Xchar *smon[]= {
X "JANUARY ", "FEBRUARY ", "MARCH ", "APRIL ",
X "MAY ", "JUNE ", "JULY ", "AUGUST ",
X "SEPTEMBER ", "OCTOBER ", "NOVEMBER ", "DECEMBER ",
X};
X
X
X
X/*
X * Procedure: main(argv[1],argv[2],argv[3])
X *
X * Function: Front end for calendar program
X *
X * Parameters:
X * p1 - character pointer - optional month
X * p2 - character pointer - optional year
X * p3 - character pointer - optional data file name
X *
X * Discussion:
X * This module parses command line, intializes variables and calls
X * init functions. It then drops into a character interpreter
X * loop, taking input from standard in. Each input either changes
X * cursor position or invokes a function.
X */
X
Xmain (argc,argv)
X
X int argc;
X char *argv[];
X{
X
X int month,day,year;
X char key;
X char *datafile;
X extern int abort();
X int i;
X
X datafile = NULL;
X if (argc == 1) {
X timeset();
X month = tmonth;
X day = tday;
X year = tyear;
X }
X else {
X if (argc == 3) {
X month = atoi(argv[1]);
X year = atoi(argv[2]);
X if (year < 100) year += 1900;
X if (!month || !year) {
X printf("Syntax Error: non-numeric argument\n");
X abort(1);
X }
X }
X else {
X if (argc == 2) {
X timeset();
X month = tmonth;
X day = tday;
X year = tyear;
X datafile = argv[1];
X }
X else {
X if ( argc == 4) {
X month = atoi(argv[1]);
X year = atoi(argv[2]);
X if (year < 100) year += 1900;
X if (!month || !year) {
X printf("Syntax Error: non-numeric argument\n");
X abort(1);
X }
X datafile = argv[3];
X }
X else {
X printf("Syntax Error: incorrect number of arguments\n");
X abort(1);
X }
X }
X }
X }
X signal(2,abort);
X signal(3,abort);
X
X system("stty cbreak -echo");
X
X tinit();
X fputs(TI,stdout);
X day = 1;
X maxchars = 38;
X maxentries = 1000;
X maxmsgs = 18;
X msghold[0] = NULL;
X help1 = 0;
X help2 = 0;
X
X loaddata(datafile);
X cal(month,day,year,datafile);
X movcur(day);
X
X key = 'a';
X while (key != CR) {
X
X key = getchar();
X
X switch (key) {
X
X case 'H' :
X
X helpcal();
X
X break;
X
X case 'p' :
X
X if (--month < 1) {
X month = 12;
X year--;
X }
X day = 1;
X notclear = 0;
X cal(month,day,year,datafile);
X
X break;
X
X case 'n' :
X
X if (++month == 13) {
X month = 1;
X year++;
X }
X day = 1;
X notclear = 0;
X cal(month,day,year,datafile);
X
X break;
X
X case 'h' :
X
X if (--day <= 0) {
X day = mon[month];
X }
X if (notclear) {
X clearmsgs();
X }
X
X break;
X
X case 'l' :
X
X if (++day > mon[month]) {
X day = 1;
X }
X if (notclear) {
X clearmsgs();
X }
X
X break;
X
X case 'j' :
X
X if ((day += 7) > mon[month]) {
X day = day % 7;
X if (day == 0) {
X day = 7;
X }
X }
X if (notclear) {
X clearmsgs();
X }
X
X break;
X
X case 'k' :
X
X if ((day -= 7) <= 0) {
X day += 35;
X if (day > mon[month]) {
X day -= 7;
X }
X }
X if (notclear) {
X clearmsgs();
X }
X
X break;
X
X case 'e' :
X
X day = mon[month];
X if (notclear) {
X clearmsgs();
X }
X
X break;
X
X case 'b' :
X
X day = 1;
X if (notclear) {
X clearmsgs();
X }
X
X break;
X
X case 'c' :
X
X clearday(month,day,year);
X
X break;
X
X case ' ' :
X
X notes(month,day,year);
X
X break;
X
X case 'm' :
X
X modnotes(month,day,year);
X
X break;
X
X
X }
X movcur(day);
X }
X closefile(datafile);
X fputs(TE,stdout);
X system("stty -cbreak echo");
X if (help1 || help2) {
X helpclr();
X }
X mov(1,24);
X} /* main */
X
X
X/*
X * Procedure: <routine name>
X *
X * Function: abort()
X *
X * Discussion:
X * Reset tty parameters and exits with an error code.
X */
X
Xabort()
X
X{
X system("stty -cbreak echo");
X if (help1 || help2) {
X helpclr();
X }
X mov(1,24);
X fputs(TE,stdout);
X exit(1);
X} /* abort */
X
X
X
X/*
X * Procedure: cal(month,day,year,datafile)
X *
X * Function: produces the visual calendar to the screen
X *
X * Parameters:
X * p1 - int - month
X * p2 - int - day
X * p3 - int - year
X * p4 - char * - datafile name
X *
X * Discussion:
X * Calculates current months parameters, such as, starting
X * day of week, number of days and days on which there are
X * appointments. This data is then used to draw a calendar
X * to the screen.
X */
X
Xcal(month,day,year,datafile)
X
X int month,day,year;
X char *datafile;
X
X{
X int i,j,k,d;
X
X fputs(CL,stdout);
X printf("V I S U A L C A L E N D A R\t\t%s\n",datafile);
X printf("-------------------------------------------------------------------------------\n");
X printf("\t\t\t\t%s%u\n", smon[month-1], year);
X printf("-------------------------------------------------------------------------------\n\n");
X printf("%s\n\n", dayw);
X
X
X d = jan1(year);
X mon[2] = 29;
X mon[9] = 30;
X
X
X i = 1;
X while (i <= 32) {
X active[i++] = 0;
X }
X
X i = 0;
X while (i < maxentries) {
X if ((yeardata[i] == year) && (monthdata[i] == month) ) {
X active[daydata[i]] = 1;
X }
X i++;
X }
X
X switch((jan1(year+1)+7-d)%7) {
X
X /*
X * non-leap year
X */
X case 1:
X mon[2] = 28;
X break;
X
X /*
X * 1752
X */
X default:
X mon[9] = 19;
X break;
X
X /*
X * leap year
X */
X case 2:
X ;
X }
X
X /* calculate days from beginning of year */
X
X for(i=1; i<month; i++) {
X d += mon[i];
X }
X
X d %= 7;
X i = 0;
X
X /* inset to first day of week position */
X
X while (i++ < (5*d)) {
X printf(" ");
X }
X
X k = 0;
X i = d;
X
X for (j=1;j<=31;j++) {
X xposition[j] = (i*5) + 2;
X yposition[j] = (k*2) + 7;
X if (++i == 7) {
X i = 0;
X k++;
X }
X }
X
X for(i=1; i<=mon[month]; i++) {
X if(i==3 && mon[month]==19) {
X i += 11;
X mon[month] += 11;
X }
X if (active[i]) {
X if(i > 9) {
X printf(" ");
X printf("%s%d%s",SO,i/10,SE);
X }
X else {
X printf(" ");
X printf("%s %s",SO,SE);
X }
X printf("%s%d%s",SO,i%10,SE);
X if (*SO == NULL) {
X printf("* ");
X }
X else {
X printf(" ");
X }
X }
X else {
X if(i > 9) {
X printf(" %d",i/10);
X }
X else {
X printf(" ");
X }
X printf("%d ",i%10);
X }
X
X if(++d == 7) {
X d = 0;
X printf(" \n\n");
X }
X }
X
X helpclr();
X
X mov(42,5);
X printf ("TIME MESSAGE");
X} /* cal */
X
X
X/*
X * Procedure: jan1(year)
X *
X * Function: calculates day of week of Jan 1 on specified year
X *
X * Parameters:
X * p1 - int - year
X *
X * Return Values:
X * integer representation day of the week
X */
X
Xjan1(year)
X
X int year;
X{
X
X register y, d;
X/*
X * normal gregorian calendar
X * one extra day per four years
X */
X
X y = year;
X d = 4+y+(y+3)/4;
X
X/*
X * julian calendar
X * regular gregorian
X * less three days per 400
X */
X
X if(y > 1800) {
X d -= (y-1701)/100;
X d += (y-1601)/400;
X }
X
X/*
X * great calendar changeover instant
X */
X
X if(y > 1752)
X d += 3;
X
X return(d%7);
X} /* jan1 */
X
X
X
X/*
X * Procedure: movcur(day)
X *
X * Function: moves the cursor to the specified day's position
X *
X * Parameters:
X * p1 - int - day
X *
X * Discussion:
X * uses termcap values to move the cursor to a matrix position
X * stored in a global array
X */
X
Xmovcur(day)
X
X int day;
X{
X printf("%s",tgoto(CM,xposition[day],yposition[day]));
X} /* movcur */
X
X
X/*
X * Procedure: setday(day)
X *
X * Function: places day in calendar display with appointment
X * days highlighted
X *
X * Parameters:
X * p1 - int - day
X *
X * Discussion:
X * Uses day arguement, termcap values and calendar position
X * matrices to write a day to the screen with days with appointment
X * days highlighted.
X */
X
Xsetday(day)
X
X int day;
X{
X printf("%s",tgoto(CM,(xposition[day]-1),yposition[day]));
X if (active[day]) {
X if(day > 9) {
X printf("%s%d%s",SO,day/10,SE);
X }
X else {
X printf("%s %s",SO,SE);
X }
X printf("%s%d%s",SO,day%10,SE);
X if (*SO == NULL) {
X printf("*");
X }
X else {
X printf(" ");
X }
X }
X else {
X if(day > 9) {
X printf("%d",day/10);
X }
X else {
X printf(" ");
X }
X printf("%d ",day%10);
X }
X} /* setday */
X
X
X
X/*
X * Procedure: tinit()
X *
X * Function: gets termcap entries
X *
X * Return Values:
X * loads global variables with termcap parameters
X *
X * Discussion:
X * Initial various termcap variables so that they can later
X * be used to move the cursor and highlight certain displays.
X */
X
Xtinit() /* termcap initalization */
X
X{
X char term[BUFSIZ]; /* holds termcap entry */
X char name[16]; /* terminal name */
X char *np; /* termcap name pointer */
X char *NADA = { "\0" }; /* null string */
X char *tgetstr();
X char *getenv();
X
X if( (np = getenv( "TERM" )) != NULL ) {
X strncpy( name, np, 16 );
X }
X else {
X printf("getenv( \"TERM\" ) failed\n");
X abort();
X }
X
X if( tgetent( term, name ) != 1 ) {
X printf("tgetent( %x, %s ) failed\n", term, name);
X abort();
X }
X
X /* if a capability does not exist, point it to a null string not NULL
X */
X tlines = tgetnum( "li" );
X tcolumns = tgetnum( "co" );
X
X if( (CM = tgetstr( "cm", &area )) == NULL) {
X CM = NADA;
X printf("Error: vcal will not work with this terminal type\n");
X abort();
X }
X if( (CL = tgetstr( "cl", &area )) == NULL)
X CL = NADA;
X if( (UP = tgetstr( "up", &area )) == NULL)
X UP = NADA;
X if( (SO = tgetstr( "so", &area )) == NULL)
X SO = NADA;
X if( (SE = tgetstr( "se", &area )) == NULL)
X SE = NADA;
X if( (TI = tgetstr( "ti", &area)) == NULL)
X TI = NADA;
X if( (TE = tgetstr( "te", &area)) == NULL)
X TE = NADA;
X if( (SG = tgetnum( "sg", &area)) > 0) {
X SO = NADA;
X SE = NADA;
X }
X} /* tinit */
X
X
X
X/*
X * Procedure: loaddata(datafile)
X *
X * Function: loads data file
X *
X * Return Values:
X * Various global arrays loaded with appointment data
X *
X * Discussion:
X * Opens user's data file and reads it in, placing
X * the data in appropriate arrays.
X */
X
Xloaddata(datafile)
X
X char *datafile;
X{
X char basedata[80];
X char tmpbuf[80];
X char *getenv();
X char home[80];
X FILE *fptr;
X int i,j,k,l,field;
X
X i = 0;
X while (i < maxentries) {
X daydata[i] = 0;
X monthdata[i] = 0;
X yeardata[i] = 0;
X msgdata[i] = 0;
X i++;
X }
X
X if (datafile == NULL) {
X strcpy(home,getenv("HOME"));
X strcat(home,"/.appointments");
X }
X else {
X strcpy(home,datafile);
X }
X if ((fptr = fopen(home,"r")) != NULL) {
X i = 0;
X while((fgets(basedata,80,fptr) != NULL)) {
X
X basedata[strlen(basedata)-1] = NULL;
X
X j = 0;
X k = 0;
X field = 0;
X while (basedata[j] != NULL ) {
X
X if (basedata[j] != ',') {
X
X tmpbuf[k++] = basedata[j];
X }
X else {
X switch (field) {
X
X case 0 : {
X tmpbuf[k] = NULL;
X monthdata[i] = atoi(tmpbuf);
X k = 0;
X break;
X }
X case 1 : {
X tmpbuf[k] = NULL;
X daydata[i] = atoi(tmpbuf);
X k = 0;
X break;
X }
X case 2 : {
X tmpbuf[k] = NULL;
X yeardata[i] = atoi(tmpbuf);
X k = 0;
X break;
X }
X case 3 : {
X tmpbuf[k++] = ' ';
X tmpbuf[k++] = ' ';
X break;
X }
X }
X field++;
X }
X j++;
X }
X tmpbuf[k] = NULL;
X msgdata[i] = malloc(40);
X strcpy(msgdata[i],tmpbuf);
X
X if (i >= maxentries) {
X printf("Warning: Over 1000 entries in data file. Data truncated.\n");
X break;
X }
X i++;
X }
X fclose(fptr);
X }
X} /* loaddata */
X
X
X/*
X * Procedure: closefile(datafile)
X *
X * Function: writes appointment data to file
X *
X * Discussion:
X * Opens the user's designated data file and writes the current
X * data into it.
X */
X
Xclosefile(datafile)
X
Xchar *datafile;
X{
X FILE *fptr;
X char tmpbuf[80];
X int i;
X char *getenv();
X char home[80];
X
X if (datafile == NULL) {
X strcpy(home,getenv("HOME"));
X strcat(home,"/.appointments");
X }
X else {
X strcpy(home,datafile);
X }
X if ((fptr = fopen(home,"w")) == NULL) {
X printf("Error: Cannot open %s file",datafile);
X abort();
X }
X i = 0;
X while (i < maxentries) {
X if (daydata[i]) {
X strcpy(tmpbuf,msgdata[i]);
X tmpbuf[4] = NULL;
X fprintf(fptr,"%d,%d,%d,%4.4s,%s\n",monthdata[i],daydata[i],yeardata[i],tmpbuf,&tmpbuf[6]);
X }
X i++;
X }
X fclose(fptr);
X} /* closefile */
X
X
X
X
X/*
X * Procedure: notes(month,day,year)
X *
X * Function: displays the current day's appointments
X *
X * Parameters:
X * p1 - int - month
X * p2 - int - day
X * p3 - int - year
X *
X * Discussion:
X * Writes to notes section of screen notes for day to
X * which the cursor was pointing.
X */
X
Xnotes(month,day,year)
X
X int month,day,year;
X{
X int i,j,k;
X
X if (help1) {
X helpclr();
X help1 = 0;
X }
X
X i = 0;
X while (i < 18) {
X dayindex[i++] = 0;
X }
X
X mov(64,5);
X printf("%2d/%2d/%2d",month,day,year);
X
X i = 0;
X j = 0;
X k = 6;
X
X while (i < maxentries) {
X if ((yeardata[i] == year) && (monthdata[i] == month) && (daydata[i] == day)) {
X dayindex[j++] = i;
X notclear++;
X mov(42,k++);
X printf("%s",msgdata[i]);
X }
X if (j > maxmsgs) {
X mov(42,24);
X printf("* too many entries to print *");
X break;
X }
X i++;
X }
X i = 0;
X while (i < maxentries) {
X if (daydata[i] == 0) {
X dayindex[j++] = i;
X if (j >= maxmsgs) {
X break;
X }
X }
X i++;
X }
X} /* notes */
X
X
X
X/*
X * Procedure: modnotes(month,day,year)
X *
X * Function: add, delete and modify appointment list
X *
X * Parameters:
X * p1 - int - month
X * p2 - int - day
X * p3 - int - year
X *
X * Return Values:
X * changes data in global message and date arrays
X *
X * Discussion:
X * Allows the user to add, delete and modify a specified day's
X * appointment list. Routine contains a small character
X * interpreter which moves the cursor through the notes list
X * and selects routines to modify the list.
X */
X
Xmodnotes (month,day,year)
X
X int month,day,year;
X{
X
X char key,c;
X int xcoord,ycoord;
X int i,cnt,total;
X char tmpmsg[39];
X
X notes(month,day,year);
X xcoord = 42;
X ycoord = 6;
X i = 0;
X mov(xcoord,ycoord);
X key = 'a';
X
X while (key != CR) {
X
X key = getchar();
X
X switch (key) {
X
X case 'H' :
X
X helpnotes();
X
X break;
X
X case 'j' :
X i++;
X if (++ycoord > 23) {
X ycoord = 6;
X i = 0;
X }
X break;
X
X case 'k' :
X i--;
X if (--ycoord < 6) {
X ycoord = 23;
X i = 17;
X }
X break;
X
X case 'd' :
X
X fputs(SO,stdout);
X printf(" ");
X fputs(SE,stdout);
X mov (xcoord,ycoord);
X monthdata[dayindex[i]] = 0;
X daydata[dayindex[i]] = 0;
X yeardata[dayindex[i]] = 0;
X strcpy(msghold,msgdata[dayindex[i]]);
X if (msgdata[dayindex[i]]) {
X free(msgdata[dayindex[i]]);
X msgdata[dayindex[i]] = 0;
X }
X break;
X
X case 'y' :
X
X strcpy(msghold,msgdata[dayindex[i]]);
X
X break;
X
X case 'p' :
X
X if (msgdata[dayindex[i]] == 0) {
X msgdata[dayindex[i]] = malloc(40);
X }
X strcpy(msgdata[dayindex[i]],msghold);
X yeardata[dayindex[i]] = year;
X daydata[dayindex[i]] = day;
X monthdata[dayindex[i]] = month;
X printf("%s",msgdata[dayindex[i]]);
X
X break;
X
X case 'i' :
X
X fputs(SO,stdout);
X printf(" ");
X
X mov (xcoord,ycoord);
X
X c = '0';
X cnt = 0;
X while (c != ESC) {
X c = getchar();
X if (c != ESC ) {
X if (c == BS) {
X if (cnt > 0) {
X cnt--;
X if (cnt == 5) {
X cnt = 3;
X mov(46,ycoord);
X }
X printf("%c %c",c,c);
X }
X }
X else {
X if (c != CR) {
X if ( cnt < maxchars) {
X tmpmsg[cnt] = c;
X cnt++;
X printf("%c",c);
X }
X if (cnt == 4) {
X tmpmsg[4] = ' ';
X tmpmsg[5] = ' ';
X cnt = 6;
X mov(48,ycoord);
X }
X }
X else {
X c = ESC;
X }
X }
X }
X }
X fputs(SE,stdout);
X if (cnt) {
X tmpmsg[cnt] = NULL;
X if (msgdata[dayindex[i]] == 0) {
X msgdata[dayindex[i]] = malloc(40);
X }
X strcpy(msgdata[dayindex[i]],tmpmsg);
X monthdata[dayindex[i]] = month;
X daydata[dayindex[i]] = day;
X yeardata[dayindex[i]] = year;
X }
X else {
X monthdata[dayindex[i]] = 0;
X daydata[dayindex[i]] = 0;
X yeardata[dayindex[i]] = 0;
X if (msgdata[dayindex[i]]) {
X free(msgdata[dayindex[i]]);
X msgdata[dayindex[i]] = 0;
X }
X }
X
X break;
X
X default :;
X }
X mov (xcoord,ycoord);
X }
X
X active[day] = 0;
X i = 0;
X while (i < maxentries) {
X if ((yeardata[i] == year) && (monthdata[i] == month)) {
X notclear = 18;
X active[daydata[i]] = 1;
X }
X i++;
X }
X
X notclear = 18;
X clearmsgs();
X if (active[day]) {
X notes(month,day,year);
X }
X setday(day);
X if (help2) {
X helpclr();
X help2 = 0;
X }
X} /* modnotes */
X
X
X/*
X * Procedure: mov(column,row)
X *
X * Function: moves cursor on screen
X *
X * Parameters:
X * p1 - int - crt column
X * p2 - int - crt row
X *
X * Discussion:
X * Moves the cursor to specified column and row on screen using
X * termcap data.
X */
X
Xmov(col, row)
X
Xint col,row;
X
X{
X printf("%s",tgoto(CM,(col - 1),(row - 1)));
X} /* move */
X
X
X/*
X * Procedure: clearday(month,day,year)
X *
X * Function: deletes specified day's appointments
X *
X * Parameters:
X * p1 - int - month
X * p2 - int - day
X * p2 - int - year
X *
X * Return Values:
X * changes various global arrays
X *
X * Discussion:
X * Removes appointment entries for the specified day from
X * message and date tables and from the crt
X */
X
Xclearday (month,day,year)
X
X int month,day,year;
X{
X int i;
X
X i = 0;
X while (i < maxentries) {
X if ((yeardata[i] == year) && (monthdata[i] == month) && (daydata[i] == day)) {
X active[day] = 0;
X monthdata[i] = 0;
X daydata[i] = 0;
X yeardata[i] = 0;
X if (msgdata[i]) {
X free(msgdata[i]);
X msgdata[i] = 0;
X }
X }
X i++;
X }
X clearmsgs();
X setday(day);
X} /* clearday */
X
X
X/*
X * Procedure: clearmsgs()
X *
X * Function: clears the notes section of the crt
X */
X
Xclearmsgs()
X
X{
X int i;
X
X mov(64,5);
X printf(" ");
X
X if (notclear > maxmsgs) notclear = maxmsgs;
X
X i = 6;
X while (i < (notclear+6)) {
X mov(42,i++);
X printf(" ");
X }
X mov(42,24);
X printf(" ");
X notclear = 0;
X} /* clearmsgs */
X
X
X/*
X * Procedure: helpcal()
X *
X * Function: displays calendar help messages to crt
X */
X
Xhelpcal()
X
X{
X mov(1,19);
X printf("j/k/h/l: cursor down/up/left/right \n");
X printf("b: first day e: last day \n");
X printf("space: display notes m: modify notes \n");
X printf("c: clear notes CR: exit program \n");
X printf("p: previous month n: next month \n");
X printf("BRK: exit w/o changes ");
X help1++;
X} /* helpcal */
X
X
X/*
X * Procedure: helpnotes()
X *
X * Function: displays notes help messages to crt
X */
X
Xhelpnotes()
X
X{
X mov(1,19);
X printf("j/k: cursor down/up \n");
X printf("i: enter insert ESC/CR: exit insert\n");
X printf("d: delete entry CR: exit notes \n");
X printf("y/p: yank/put a line \n");
X printf(" \n");
X printf(" ");
X help2++;
X} /* helpnotes */
X
X
X/*
X * Procedure: helpclr()
X *
X * Function: clears notes area of screen
X */
X
Xhelpclr ()
X{
X mov(1,19);
X printf(" \n");
X printf(" \n");
X printf(" \n");
X printf(" \n");
X printf(" Type 'H' for help \n");
X printf(" ");
X} /* helpclr */
X
X
X/*
X * Procedure: timeset()
X *
X * Function: sets current month, day and year variables
X *
X * Return Values:
X * tday, tmonth and tyear variables set to current date
X */
X
Xtimeset()
X
X{
X struct tm *localtime();
X
X struct tm *tp; /* time structure */
X long tloc; /* number of seconds since 1970 */
X
X time(&tloc); /* fills tloc */
X
X tp = localtime(&tloc);
X
X tyear = tp->tm_year;
X tmonth = tp->tm_mon + 1;
X tday = tp->tm_mday;
X
X tyear += 1900;
X
X} /* timeset */
*-*-END-of-vcal.c-*-*
echo x - eappts.l
sed 's/^X//' >eappts.l <<'*-*-END-of-eappts.l-*-*'
X.TH EAPPTS 1
X.SH NAME
Xeappts \- enter appointments
X.SH SYNOPSIS
X.B eappts [ filename ]
X.SH DESCRIPTION
X.I Eappts
Xis a program which is used to enter appointment data into the user's
X~/.appointments file by default or the file specified in the optional
Xfilename argument.
X.PP
XThe user is prompted for a date, time and message.
XThe date is entered as three numeric values separated by spaces.
XA two or four digit year value should be used.
X.PP
XData entered using
X.I eappts
Xmay be used by four companion programs.
XThese are:
X.br
X.sp
X.nf
Xvcal calendar and notes program
Xappts displays current or seleted day's appoinments
Xautocall set appointment reminders for the current day
Xlcal displays the month's appointments in tabular form
X.fi
X.sp
XFor further information on these, reference the appropriate "man"
Xentries.
X.SH AUTHOR
XMike Essex
X.SH FILES
Xeappts
X.br
X~/.appointments
X.br
X.SH "SEE ALSO"
Xvcal(1), appts(1), autocall(1), lcal(1), callme(1)
X.SH BUGS
XThere are year 2000 time bombs.
*-*-END-of-eappts.l-*-*
echo x - lcal.l
sed 's/^X//' >lcal.l <<'*-*-END-of-lcal.l-*-*'
X.TH LCAL 1
X.SH NAME
Xlcal \- display current or selected month's appointments
X.SH SYNOPSIS
X.B lcal
X[ month year ] [ filename(s) ]
X.sp
Xwhere
X.I month
Xis a numeric value between 1 and 12,
X.I year
Xis a numeric four digit value and
X.I filename(s)
Xare the data files to be searched.
X.SH DESCRIPTION
X.I Lcal
Xis a program which uses the data stored by "vcal" or "eappts" to
Xdisplay the user's appointments to standard out.
X.PP
XWhen an argument is present,
X.I lcal
Xwill display appointments for the requested month and year.
XThe default argument values are the current month and year.
XIf no filename is specified ~/.appointments will be searched.
XIf one or more filenames arguments are used those files will
Xbe searched.
X.SH AUTHOR
XMike Essex
X.SH FILES
Xlcal
X.br
X~/.appointments
X.br
X.SH "SEE ALSO"
Xvcal(1), appts(1), eappts(1), autocall(1), callme(1)
X.SH BUGS
XThere are year 2000 time bombs.
*-*-END-of-lcal.l-*-*
echo x - vcal.l
sed 's/^X//' >vcal.l <<'*-*-END-of-vcal.l-*-*'
X.TH VCAL 1
X.SH NAME
Xvcal \- visual calendar and notes program
X.SH SYNOPSIS
X.B vcal
X[ month year ] [ filename ]
X.sp
Xwhere
X.I month
Xis a numeric value between 1 and 12,
X.I year
Xis a numeric four digit value and
X.I filename
Xis the data file to be accessed.
X.SH DESCRIPTION
X.I Vcal
Xis a visual calendar program which allows the user to enter notes
Xand appointments for each day of the month. It can be used to
Xreplace the "paper" desk or wall calendar with an electronic one
Xwhich can be accessed from any terminal or modem connected to the
Xcomputer system.
X.PP
XWhen a date argument is present,
X.I vcal
Xwill display the requested month and year. The default argument values
Xare the current month and year. When a filename argument is used
X.I vcal
Xwill uses that file instead of the default ~/.appointments file.
XIf ~/.appointments is not used the filename of the current file
Xwill appear at the top of the
X.I vcal
Xcalendar.
X.SH OPERATION
X.I Vcal
Xis entered from UNIX by typing the
Xcommand followed by an optional month and year value. A calendar
Xwill be displayed on the screen with the cursor located on the first
Xday of the month. The cursor may be moved to different days
Xin the following manner.
X.br
X.sp
X.nf
Xkey function
X--- --------
Xj move cursor down
Xk move cursor up
Xl move cursor to the next day
Xh move cursor to the previous day
Xb move cursor to the beginning of the month
Xe move cursor to the end of the month
X.sp
X.fi
X.PP
XPrevious and following months may also be accessed.
X.br
X.sp
X.nf
Xkey function
X--- --------
Xp previous month
Xn next month
X.sp
X.fi
X.PP
XUp to eighteen appointments may be entered on each day of the month.
XThese may be displayed, modified or cleared in with the following keys.
XThey will operate on the day selected by the current cursor position.
X.br
X.sp 4
X.nf
Xkey function
X--- --------
Xspace display appointments for the selected day
Xm enter or modify appointments
Xc clear all appointments for the selected day
X.sp
X.fi
X.PP
XWhen the 'm' is pressed
X.I vcal
Xenters notes mode. While in this mode notes may be added, modified,
Xdeleted, yanked or put.
X.br
X.sp
X.nf
Xkey function
X--- --------
Xj move cursor down
Xk move cursor up
Xi begin data insertion
XESC/CR end data insertion (only while in insert)
Xd delete the selected line
Xy hold the current line
Xp insert the held message
XCR exit notes mode and return to the calendar
X.sp
X.fi
XData must begin with the appointment time in 24 hour format
X(no ':' should be used). Entering new data will erase the current
Xmessage on that line. A held line will be available to insert until
Xit is changed or the user exits
X.I vcal.
XA line which is deleted using the 'd' key will be placed in the hold
Xbuffer.
X.PP
XWhen the cursor is on the calendar a carriage return will cause the
Xthe appointment data to be saved and
X.I vcal
Xto exit. Break or delete will cause
X.I vcal
Xto exit without updating the ~/.appointments file.
X.PP
XA 'H' will display help messages. A calendar help message
Xwill be printed when
Xthe cursor is on calendar days. A notes help message
Xis printed when the cursor is in the notes area.
X.PP
XFive companion programs are available to use with the
X.I vcal
Xprogram. These are:
X.br
X.sp
X.nf
Xappts display current or selected days appointments
Xeappts enter appointments from the UNIX command line
Xautocall set appointment reminders for the current day
Xlcal displays month's appointments in tabular form
Xcallme sets appointment reminders
X.fi
X.sp
XFor further information on these, reference the appropriate "man"
Xentries.
X.SH AUTHOR
XMike Essex
X.SH FILES
Xvcal
X.br
X/etc/termcap
X.br
X~/.appointments
X.br
X.SH "SEE ALSO"
Xappts(1), eappts(1), autocall(1), lcal(1), callme(1)
X.SH BUGS
X.I Vcal
Xmay not work with extremely brain damaged terminals. There must be
Xa 'CM' entry in the termcap for
X.I vcal
Xto draw the screen. There are year 2000 time bombs.
X.br
*-*-END-of-vcal.l-*-*
exit
From me@pinot Thu Feb 19 20:21:00 1987
Path: beno!seismo!lll-lcc!ptsfa!varian!zehntel!me@pinot (Mike Essex)
From: me@pinot (Mike Essex)
Newsgroups: net.sources
Subject: vcal and friends Rev 2.0 Part 2
Message-ID: <141@zehntel.UUCP>
Date: 20 Feb 87 01:21:00 GMT
Sender: news@zehntel.UUCP
Organization: Zehntel Inc., Walnut Creek CA
Lines: 2171
echo x - README.new
sed 's/^X//' >README.new <<'*-*-END-of-README.new-*-*'
X VCAL AND FRIENDS 2/19/87
X
X-------------------------------------------------------------------
XThis is the second release of vcal and friends.
XIt has fixed a number of problems and incorporated some suggestions
XI recieved in your responses. For the most part I have received
Xenthusiastic replies and I thank you for the responses. There
Xwere a number of sites who didn't recieve both pieces and some
Xwho had pieces truncated. Hopefully, this release will get through
Xto all.
X
XChanges include:
X
Xvcal - Changed terminal handler routines to take advantage of
X termcap(3) capabilites allow vcal to be used with a greater
X number of terminal types. Changed start up cursor position
X to current date. Fixed several minor bugs.
X
Xautocall - Fixed a loop bug which was causing core dumps in some
X instances. Changed message buffer size.
X
Xcallme - No change.
X
Xappts.c - Changed message size so that long messages from a manually
X edited data file does not cause a core dump.
X
Xeappts - Changed message buffer size.
X
Xlcal - Changed message buffer size.
X-------------------------------------------------------------------
Xdef.: a set of calendar and appointment utility programs to replace
X the traditional paper calendar.
X
XVcal and friends allow the user to view a calendar, enter dates and
Xtimes of activities, set times for prompts to the CRT and to produce
Xlists of a month's activities. Multiple data files may be used to
Xallow the user to have one calendar for personal activities, one for
Xbusiness activities, one for project milestones, etc.
X
XThese programs are written in 'C' and run under UNIX. To date they
Xhave been compiled and execute on the following systems:
X
XDEC PDP 11/70 UNIX Version 7
XDEC VAX 11/750 UNIX BSD 4.2 and 4.3
XSun 2/170 UNIX BSD 4.2
XSun 3/160 UNIX BSD 4.2
XSun 3/260 UNIX BSD 4.2
XDEC MicroVAX ULTRIX
X
XIncluded in this package are six source files, six manual files, a
Xmakefile and this introduction. The makefile is for use with the
Xstandard "make" utility on a VAX 11/750 under BSD 4.3. For use with
Xa PDP 11/70 BSD Version 7 change the makefile library entry from
X"termlib" to "termcap".
X
XAll the "vcal" files have been combined here with the "shar" script.
XSince the combined size of the files are greater than 65,000
Xcharacters they have been broken into two parts for transmission.
XPart 1 contains makefile, appts.c, autocall.c and callme.c along
Xwith the manual pages for these. Part 2 contains eappts.c, lcal.c
Xand vcal.c and their manual pages.
X
XSynopsis of files:
X
Xappts displays the current or specified day's activities
X
Xautocall starts background reminder processes for each of the
X current day's activities
X
Xcallme starts a background reminder process for a specified
X time and activity
X
Xeappts allows activities to be entered into a data file from
X the command line
X
Xlcal produces a tabular listing of the current or specified
X month's activities
X
Xvcal visual calendar displaying the current or specified
X month's activities; allows entries to be added, changed
X or deleted
X
Xmakefile makefile for all of the "vcal" programs
X
Xmanual pages: appts.l autocall.l callme.l eappts.l lcal.l vcal.l
X
XComments and suggestions will be appreciated and considered.
X
XMike Essex (~me)
X
X ....!ucbvax!zehntel!me
X ....!decvax!sytek!zehntel!me
X ...."zehntel!me"@BERKELEY
*-*-END-of-README.new-*-*
echo x - eappts.c
sed 's/^X//' >eappts.c <<'*-*-END-of-eappts.c-*-*'
X/*
X * Module: eappts.c
X *
X * Purpose: enters data into appointments file
X *
X * Author: Mike Essex
X *
X * Date: Sep. 16, 1986
X *
X * Includes:
X * stdio.h
X * Discussion:
X * Inputs data from standard input and writes it to ~/.appointments
X * file
X *
X *
X * Edit History
X * ==== =======
X *
X * Date Who What
X * ---- --- ----------------------------------------------
X * 12/1/86 me added multifile capability
X * 12/1/86 me changed 'home' from *home[80] to home[80]
X *
X */
X
X#include <stdio.h>
X#define NL '\010'
X
X
X/*
X * Procedure: main
X *
X * Function: inputs data and writes to users .appointments file
X *
X * Discussion:
X * Prompts users for required appointment information, inputs
X * that info and then appends it to ~/.appointments file.
X */
X
Xmain(argc,argv)
X
Xint argc;
Xchar *argv[];
X
X{
X FILE *fptr;
X char tmpbuf[80];
X int i,j;
X char *getenv();
X char home[80];
X char datedata[20];
X char timedata[20];
X char msgdata[40];
X int month,day,year,time;
X int index[5];
X
X if (argc == 2) {
X strcpy(home,argv[1]);
X }
X else {
X strcpy(home,getenv("HOME"));
X strcat(home,"/.appointments");
X }
X
X fptr = fopen(home,"a");
X if (fptr) {
X printf("What is the date of appointment? (mm dd yyyy) ");
X fgets(datedata,20,stdin);
X i = 0;
X j = 0;
X while(i < 20) {
X while ((i < 20) && (datedata[i] == ' ')) i++;
X index[j++] = i;
X while ((i < 20) && (datedata[i] != ' ')) i++;
X }
X month = atoi(&datedata[index[0]]);
X day = atoi(&datedata[index[1]]);
X year = atoi(&datedata[index[2]]);
X if (year < 100) year += 1900;
X
X printf("What time (24 hour time) is the appointment? (tttt) ");
X fgets(timedata,20,stdin);
X time = atoi(timedata);
X printf("What is the message? ");
X fgets(msgdata,79,stdin);
X msgdata[strlen(msgdata)-1] = NULL;
X fprintf(fptr,"%d,%d,%d,%4d,%s\n",month,day,year,time,msgdata);
X }
X else {
X printf("Error: Cannot open %s file",argv[1]);
X abort();
X }
X fclose(fptr);
X} /* main */
*-*-END-of-eappts.c-*-*
echo x - eappts.l
sed 's/^X//' >eappts.l <<'*-*-END-of-eappts.l-*-*'
X.TH EAPPTS 1
X.SH NAME
Xeappts \- enter appointments
X.SH SYNOPSIS
X.B eappts [ filename ]
X.SH DESCRIPTION
X.I Eappts
Xis a program which is used to enter appointment data into the user's
X~/.appointments file by default or the file specified in the optional
Xfilename argument.
X.PP
XThe user is prompted for a date, time and message.
XThe date is entered as three numeric values separated by spaces.
XA two or four digit year value should be used.
X.PP
XData entered using
X.I eappts
Xmay be used by four companion programs.
XThese are:
X.br
X.sp
X.nf
Xvcal calendar and notes program
Xappts displays current or seleted day's appoinments
Xautocall set appointment reminders for the current day
Xlcal displays the month's appointments in tabular form
X.fi
X.sp
XFor further information on these, reference the appropriate "man"
Xentries.
X.SH AUTHOR
XMike Essex
X.SH FILES
Xeappts
X.br
X~/.appointments
X.br
X.SH "SEE ALSO"
Xvcal(1), appts(1), autocall(1), lcal(1), callme(1)
X.SH BUGS
XThere are year 2000 time bombs.
*-*-END-of-eappts.l-*-*
echo x - lcal.c
sed 's/^X//' >lcal.c <<'*-*-END-of-lcal.c-*-*'
X/*
X * Module: lcal.c
X *
X * Purpose: print month's appointments
X *
X * Author: Mike Essex
X *
X * Date: Sep. 16, 1986
X *
X * Includes:
X * time.h, stdio.h, ctype.h, signal.h
X *
X * Discussion:
X * Reads data from ~/.appointments and/or designated file and
X * writes to standard * out any appoinments which fall in
X * the current or optionally specified month.
X *
X *
X * Edit History
X * ==== =======
X *
X * Date Who What
X * ---- --- ----------------------------------------------
X *
X */
X
X#include <stdio.h>
X#include <signal.h>
X#include <ctype.h>
X#include <time.h>
X
X
Xchar *malloc();
X
Xint monthdata[1000]; /* month data */
Xint daydata[1000]; /* month data */
Xint yeardata[1000]; /* month data */
Xchar *msgdata[1000]; /* message pointers */
Xchar msghold[40];
Xint maxentries;
Xint maxmsgs;
Xint cmonth,cday,cyear;
Xint argvindex;
X
X
X
X/*
X * Procedure: main()
X *
X * Function: prints out listing of appointments
X *
X * Discussion:
X * Parses command line for optional month and year, initializes
X * varialbes, calls required funtions.
X */
X
Xmain (argc,argv)
X
X int argc;
X char *argv[];
X{
X
X int month,day,year;
X int i;
X int tempmonth,tempyear;
X int atoi();
X int maxindex;
X extern int abort();
X
X timeset();
X year = cyear;
X month = cmonth;
X day = cday;
X
X if (argc > 2) {
X tempmonth = atoi(argv[1]);
X tempyear = atoi(argv[2]);
X if (tempmonth && tempyear){
X month = tempmonth;
X year = tempyear;
X if (year < 100) year += 1900;
X if (argc > 3) {
X argvindex = 3;
X maxindex = argc;
X }
X else {
X argvindex = 0;
X maxindex = 1;
X }
X }
X else {
X if (tempmonth || tempyear) {
X printf("Syntax error: Incorrect date arguments\n");
X exit(1);
X }
X else {
X argvindex = 1;
X maxindex = argc;
X }
X }
X }
X else {
X if (argc == 1) {
X argvindex = 0;
X maxindex = argc;
X }
X else {
X argvindex = 1;
X maxindex = argc;
X }
X }
X
X
X signal(2,abort);
X signal(3,abort);
X
X day = 1;
X maxentries = 1000;
X maxmsgs = 18;
X msghold[0] = NULL;
X
X printf(" C A L E N D A R L I S T\n");
X while (argvindex < maxindex) {
X loaddata(argv[argvindex]);
X table(month,day,year,argv[argvindex]);
X argvindex++;
X }
X
X printf("------------------------------------------------------------------------------\n");
X} /* main */
X
X
X/*
X * Procedure: abort()
X *
X * Function: error exit routine
X */
X
Xabort()
X
X{
X exit(1);
X} /* abort */
X
X
X/*
X * Procedure: table(month,day,year)
X *
X * Function: outputs appointments in tabular format
X *
X * Parameters:
X * p1 - int - month
X * p2 - int - day
X * p3 - int - year
X * p3 - char * - file name
X *
X * Discussion:
X * Searches data arrays for appointments in the specified
X * month and year and outputs them in tabular form to standard out.
X */
X
Xtable(month,day,year,filename)
X
X int month,day,year;
X char *filename;
X
X{
X int i,j,k,d,dow,monthday,searchcnt,first;
X int getdow();
X
X static char *dayw[]= {
X "Sat ","Sun ","Mon ", "Tue ",
X "Wed ", "Thu ", "Fri "
X };
X
X static char *smon[]= {
X "JANUARY ", "FEBRUARY ", "MARCH ", "APRIL ",
X "MAY ", "JUNE ", "JULY ", "AUGUST ",
X "SEPTEMBER ", "OCTOBER ", "NOVEMBER ", "DECEMBER "
X };
X
X printf("------------------------------------------------------------------------------\n");
X if (argvindex) {
X printf("| %-10.10s%u %30.30s |\n", smon[month-1], year,filename);
X }
X else {
X printf("| %-10.10s%u |\n", smon[month-1], year);
X }
X monthday = 0;
X while (++monthday <= 31) {
X searchcnt = 0;
X first = 1;
X while (searchcnt <= maxentries) {
X if ((yeardata[searchcnt] == year) &&
X (monthdata[searchcnt] == month) &&
X (daydata[searchcnt] == monthday)) {
X if (first) {
X dow = getdow(month,monthday,year);
X first = 0;
X /* printf("|----------------------------------------------------------------------------|\n"); */
X printf("| |\n");
X printf("| %-7.7s%2d %-64.64s|\n",dayw[dow],monthday,msgdata[searchcnt]);
X }
X else {
X printf("| %-64.64s|\n",msgdata[searchcnt]);
X }
X }
X searchcnt++;
X }
X }
X} /* table */
X
X
X/*
X * Procedure: getdow(tmonth,tday,tyear)
X *
X * Function: calculates day of week
X *
X * Parameters:
X * p1 - int - month
X * p2 - int - day
X * p3 - int - year
X *
X * Return Values:
X * interger value of day of week, sat=0, . . ., etc
X *
X * Discussion:
X * calculates number of days from 1,1,1979 and determines dow
X */
X
Xgetdow(tmonth,tday,tyear)
X
X int tmonth,tday,tyear;
X{
X
X static int mdays[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
X int month,day,year,mcnt;
X long days;
X int tdow;
X
X month = 1;
X day = 1;
X year = 79;
X
X if ((tmonth == month) && (tyear == year)) {
X days = abs(day - tday);
X }
X else {
X days = mdays[month] - day;
X if (tyear == year) {
X while (++month < tmonth) {
X days += mdays[month];
X if ((month == 2) && ((year % 4) == 0)) days++;
X }
X }
X else {
X while (++month < 13) {
X days += mdays[month];
X if ((month == 2) && ((year % 4) == 0)) days++;
X }
X while (++year < tyear) {
X days += 365;
X if ((year % 4) == 0 ) days ++;
X }
X
X mcnt = 0;
X while (++mcnt < tmonth) {
X days += mdays[mcnt];
X if ((mcnt == 2) && ((tyear % 4) == 0)) days++;
X }
X }
X days += tday;
X }
X
X tdow = (days%7);
X
X return(tdow);
X} /* get dow */
X
X
X/*
X * Procedure: loaddata()
X *
X * Function: loads appointment data from ~/.appointments file
X *
X * Return Values:
X * various global arrays loaded with appointment data
X *
X */
X
Xloaddata(filename)
X
Xchar *filename;
X
X{
X char basedata[80];
X char tmpbuf[80];
X char *getenv();
X char home[80];
X FILE *fptr;
X int i,j,k,l,field;
X
X i = 0;
X while (i < maxentries) {
X daydata[i] = 0;
X monthdata[i] = 0;
X yeardata[i] = 0;
X msgdata[i] = 0;
X i++;
X }
X
X
X if (argvindex == 0) {
X strcpy(home,getenv("HOME"));
X strcat(home,"/.appointments");
X }
X else {
X strcpy(home,filename);
X }
X if ((fptr = fopen(home,"r")) != NULL) {
X i = 0;
X while((fgets(basedata,80,fptr) != NULL)) {
X
X basedata[strlen(basedata)-1] = NULL;
X
X j = 0;
X k = 0;
X field = 0;
X while (basedata[j] != NULL ) {
X
X if (basedata[j] != ',') {
X
X tmpbuf[k++] = basedata[j];
X }
X else {
X switch (field) {
X
X case 0 : {
X tmpbuf[k] = NULL;
X monthdata[i] = atoi(tmpbuf);
X k = 0;
X break;
X }
X case 1 : {
X tmpbuf[k] = NULL;
X daydata[i] = atoi(tmpbuf);
X k = 0;
X break;
X }
X case 2 : {
X tmpbuf[k] = NULL;
X yeardata[i] = atoi(tmpbuf);
X k = 0;
X break;
X }
X case 3 : {
X tmpbuf[k++] = ' ';
X tmpbuf[k++] = ' ';
X break;
X }
X }
X field++;
X }
X j++;
X }
X tmpbuf[k] = '\0';
X msgdata[i] = malloc(80);
X strncpy(msgdata[i],tmpbuf,80);
X msgdata[79] = NULL;
X
X if (i >= maxentries) {
X printf("Warning: Over 1000 entries in %s file. Data truncated.\n",filename);
X break;
X }
X i++;
X }
X fclose(fptr);
X }
X else {
X printf("Error: Cannot open %s file.\n",filename);
X }
X} /* loaddata */
X
X
X/*
X * Procedure: timeset()
X *
X * Function: Gets current time and date
X *
X * Return Values:
X * loads time and date info into global variables
X *
X */
X
Xtimeset()
X
X{
X struct tm *localtime();
X
X struct tm *tp; /* time structure */
X long tloc; /* number of seconds since 1970 */
X
X time(&tloc); /* fills tloc */
X
X tp = localtime(&tloc);
X
X cyear = tp->tm_year;
X cmonth = tp->tm_mon + 1;
X cday = tp->tm_mday;
X
X cyear += 1900;
X
X} /* timeset */
*-*-END-of-lcal.c-*-*
echo x - lcal.l
sed 's/^X//' >lcal.l <<'*-*-END-of-lcal.l-*-*'
X.TH LCAL 1
X.SH NAME
Xlcal \- display current or selected month's appointments
X.SH SYNOPSIS
X.B lcal
X[ month year ] [ filename(s) ]
X.sp
Xwhere
X.I month
Xis a numeric value between 1 and 12,
X.I year
Xis a numeric four digit value and
X.I filename(s)
Xare the data files to be searched.
X.SH DESCRIPTION
X.I Lcal
Xis a program which uses the data stored by "vcal" or "eappts" to
Xdisplay the user's appointments to standard out.
X.PP
XWhen an argument is present,
X.I lcal
Xwill display appointments for the requested month and year.
XThe default argument values are the current month and year.
XIf no filename is specified ~/.appointments will be searched.
XIf one or more filenames arguments are used those files will
Xbe searched.
X.SH AUTHOR
XMike Essex
X.SH FILES
Xlcal
X.br
X~/.appointments
X.br
X.SH "SEE ALSO"
Xvcal(1), appts(1), eappts(1), autocall(1), callme(1)
X.SH BUGS
XThere are year 2000 time bombs.
*-*-END-of-lcal.l-*-*
echo x - vcal.c
sed 's/^X//' >vcal.c <<'*-*-END-of-vcal.c-*-*'
X/*
X * Module: vcal.c
X *
X * Purpose: visual appointment calendar
X *
X * Author: Mike Essex
X *
X * Date: Sep. 16, 1986
X *
X * Includes:
X * time.h, stdio.h, ctype.h, signal.h
X *
X * Discussion:
X * displays a calendar to the screen for the current or optionally
X * specified month. User may move the cursor any day of the month
X * and view or enter appointments for that date.
X *
X *
X * Edit History
X * ==== =======
X *
X * Date Who What
X * ---- --- ----------------------------------------------
X *11/25/86 me added multiple data file capability
X *11/25/86 me fixed array "home" from *home[80] to home[80]
X *11/25/86 me fixed "space" and "area" to be global
X *11/26/86 me changed help message routines
X * 2/06/86 me changed calendar header from printing a default
X * NULL for .appointments file to not printing
X *02/19/86 me reworked terminal handler to make correct use
X * of termcap(3) functions for greater terminal
X * portability. modified so that cursor comes to
X * current day of month on startup. Fixed minor
X * bugs and changed a few messages.
X *
X */
X
X#include <stdio.h>
X#include <signal.h>
X#include <ctype.h>
X#include <time.h>
X#include <sgtty.h>
X
X#define LF '\012'
X#define BS '\010'
X#define ESC '\033'
X
Xint mon[] = {
X 0,
X 31, 29, 31, 30,
X 31, 30, 31, 31,
X 30, 31, 30, 31,
X};
X
Xint tputc(); /* termcap dependent output */
Xchar space[BUFSIZ]; /* used by area */
Xchar *area = space; /* termcap required variable */
Xchar *BC; /* backspace string pointer */
Xchar *backstring = "\b"; /* backspace string */
Xchar PC; /* number pad characters */
Xchar *UP; /* cursor up string */
Xextern short ospeed; /* output speed */
Xchar *CM; /* cursor motion */
Xchar *CL; /* clear screen */
Xchar *TI; /* begin cm */
Xchar *TE; /* end cm */
Xchar *SO; /* standout*/
Xchar *SE; /* end standout*/
Xchar *tgoto();
Xchar *malloc();
Xchar tcolumns = 0; /* terminal columns */
Xchar tlines = 0; /* terminal lines */
X
Xint xposition[32]; /* calendar x axis position */
Xint yposition[32]; /* calendar y axis position */
Xint active[33]; /* highlight day array */
X
Xint monthdata[1000]; /* month data */
Xint daydata[1000]; /* month data */
Xint yeardata[1000]; /* month data */
Xchar *msgdata[1000]; /* message pointers */
Xchar msghold[80];
Xint dayindex[18]; /* index to day's msgs */
Xint maxentries;
Xint maxmsgs;
Xint tmonth,tday,tyear;
X
Xint maxchars;
Xint notclear;
Xint help1,help2; /* help message flags */
X
Xchar dayw[] = {
X " S M T W T F S "
X};
X
Xchar *smon[]= {
X "JANUARY ", "FEBRUARY ", "MARCH ", "APRIL ",
X "MAY ", "JUNE ", "JULY ", "AUGUST ",
X "SEPTEMBER ", "OCTOBER ", "NOVEMBER ", "DECEMBER ",
X};
X
X
X
X/*
X * Procedure: main(argv[1],argv[2],argv[3])
X *
X * Function: Front end for calendar program
X *
X * Parameters:
X * p1 - character pointer - optional month
X * p2 - character pointer - optional year
X * p3 - character pointer - optional data file name
X *
X * Discussion:
X * This module parses command line, intializes variables and calls
X * init functions. It then drops into a character interpreter
X * loop, taking input from standard in. Each input either changes
X * cursor position or invokes a function.
X */
X
Xmain (argc,argv)
X
X int argc;
X char *argv[];
X{
X
X int month,day,year;
X char key;
X char *datafile;
X extern int abort();
X int i;
X
X datafile = NULL;
X day = 1;
X if (argc == 1) {
X timeset();
X month = tmonth;
X day = tday;
X year = tyear;
X }
X else {
X if (argc == 3) {
X month = atoi(argv[1]);
X year = atoi(argv[2]);
X if (year < 100) year += 1900;
X if (!month || !year) {
X printf("Syntax Error: non-numeric argument\n");
X abort(1);
X }
X }
X else {
X if (argc == 2) {
X timeset();
X month = tmonth;
X day = tday;
X year = tyear;
X datafile = argv[1];
X }
X else {
X if ( argc == 4) {
X month = atoi(argv[1]);
X year = atoi(argv[2]);
X if (year < 100) year += 1900;
X if (!month || !year) {
X printf("Syntax Error: non-numeric argument\n");
X abort(1);
X }
X datafile = argv[3];
X }
X else {
X printf("Syntax Error: incorrect number of arguments\n");
X abort(1);
X }
X }
X }
X }
X signal(2,abort);
X signal(3,abort);
X
X system("stty cbreak -echo");
X
X tinit();
X tputs(TI,1,tputc);
X maxchars = 38;
X maxentries = 1000;
X maxmsgs = 18;
X msghold[0] = NULL;
X help1 = 0;
X help2 = 0;
X
X loaddata(datafile);
X cal(month,day,year,datafile);
X movcur(day);
X
X key = 'a';
X while (key != LF) {
X
X key = getchar();
X
X switch (key) {
X
X case 'H' :
X
X helpcal();
X
X break;
X
X case 'p' :
X
X if (--month < 1) {
X month = 12;
X year--;
X }
X day = 1;
X notclear = 0;
X cal(month,day,year,datafile);
X
X break;
X
X case 'n' :
X
X if (++month == 13) {
X month = 1;
X year++;
X }
X day = 1;
X notclear = 0;
X cal(month,day,year,datafile);
X
X break;
X
X case 'h' :
X
X if (--day <= 0) {
X day = mon[month];
X }
X if (notclear) {
X clearmsgs();
X }
X
X break;
X
X case 'l' :
X
X if (++day > mon[month]) {
X day = 1;
X }
X if (notclear) {
X clearmsgs();
X }
X
X break;
X
X case 'j' :
X
X if ((day += 7) > mon[month]) {
X day = day % 7;
X if (day == 0) {
X day = 7;
X }
X }
X if (notclear) {
X clearmsgs();
X }
X
X break;
X
X case 'k' :
X
X if ((day -= 7) <= 0) {
X day += 35;
X if (day > mon[month]) {
X day -= 7;
X }
X }
X if (notclear) {
X clearmsgs();
X }
X
X break;
X
X case 'e' :
X
X day = mon[month];
X if (notclear) {
X clearmsgs();
X }
X
X break;
X
X case 'b' :
X
X day = 1;
X if (notclear) {
X clearmsgs();
X }
X
X break;
X
X case 'c' :
X
X clearday(month,day,year);
X
X break;
X
X case ' ' :
X
X notes(month,day,year);
X
X break;
X
X case 'm' :
X
X modnotes(month,day,year);
X
X break;
X
X
X }
X movcur(day);
X }
X closefile(datafile);
X tputs(TE,1,tputc);
X system("stty -cbreak echo");
X if (help1 || help2) {
X helpclr();
X }
X mov(1,24);
X} /* main */
X
X
X/*
X * Procedure: <routine name>
X *
X * Function: abort()
X *
X * Discussion:
X * Reset tty parameters and exits with an error code.
X */
X
Xabort()
X
X{
X system("stty -cbreak echo");
X tputs(SE,1,tputc);
X if (help1 || help2) {
X helpclr();
X }
X mov(1,24);
X tputs(TE,1,tputc);
X exit(1);
X} /* abort */
X
X
X
X/*
X * Procedure: cal(month,day,year,datafile)
X *
X * Function: produces the visual calendar to the screen
X *
X * Parameters:
X * p1 - int - month
X * p2 - int - day
X * p3 - int - year
X * p4 - char * - datafile name
X *
X * Discussion:
X * Calculates current months parameters, such as, starting
X * day of week, number of days and days on which there are
X * appointments. This data is then used to draw a calendar
X * to the screen.
X */
X
Xcal(month,day,year,datafile)
X
X int month,day,year;
X char *datafile;
X
X{
X int i,j,k,d;
X
X tputs(CL,24,tputc);
X if (datafile == NULL) {
X printf("V I S U A L C A L E N D A R\n");
X }
X else {
X printf("V I S U A L C A L E N D A R\t\t%s\n",datafile);
X }
X printf("-------------------------------------------------------------------------------\n");
X printf("\t\t\t\t%s%u\n", smon[month-1], year);
X printf("-------------------------------------------------------------------------------\n\n");
X printf("%s\n\n", dayw);
X
X
X d = jan1(year);
X mon[2] = 29;
X mon[9] = 30;
X
X
X i = 1;
X while (i <= 32) {
X active[i++] = 0;
X }
X
X i = 0;
X while (i < maxentries) {
X if ((yeardata[i] == year) && (monthdata[i] == month) ) {
X active[daydata[i]] = 1;
X }
X i++;
X }
X
X switch((jan1(year+1)+7-d)%7) {
X
X /*
X * non-leap year
X */
X case 1:
X mon[2] = 28;
X break;
X
X /*
X * 1752
X */
X default:
X mon[9] = 19;
X break;
X
X /*
X * leap year
X */
X case 2:
X ;
X }
X
X /* calculate days from beginning of year */
X
X for(i=1; i<month; i++) {
X d += mon[i];
X }
X
X d %= 7;
X i = 0;
X
X /* inset to first day of week position */
X
X while (i++ < (5*d)) {
X printf(" ");
X }
X
X k = 0;
X i = d;
X
X for (j=1;j<=31;j++) {
X xposition[j] = (i*5) + 2;
X yposition[j] = (k*2) + 7;
X if (++i == 7) {
X i = 0;
X k++;
X }
X }
X
X for(i=1; i<=mon[month]; i++) {
X if(i==3 && mon[month]==19) {
X i += 11;
X mon[month] += 11;
X }
X if (active[i]) {
X if(i > 9) {
X printf(" ");
X tputs(SO,1,tputc);
X printf("%d",i/10);
X tputs(SE,1,tputc);
X }
X else {
X printf(" ");
X tputs(SO,1,tputc);
X printf(" ");
X tputs(SE,1,tputc);
X }
X tputs(SO,1,tputc);
X printf("%d",i%10);
X tputs(SE,1,tputc);
X if (*SO == NULL) {
X printf("* ");
X }
X else {
X printf(" ");
X }
X }
X else {
X if(i > 9) {
X printf(" %d",i/10);
X }
X else {
X printf(" ");
X }
X printf("%d ",i%10);
X }
X
X if(++d == 7) {
X d = 0;
X printf(" \n\n");
X }
X }
X
X helpclr();
X
X mov(42,5);
X printf ("TIME MESSAGE");
X} /* cal */
X
X
X/*
X * Procedure: jan1(year)
X *
X * Function: calculates day of week of Jan 1 on specified year
X *
X * Parameters:
X * p1 - int - year
X *
X * Return Values:
X * integer representation day of the week
X */
X
Xjan1(year)
X
X int year;
X{
X
X register y, d;
X/*
X * normal gregorian calendar
X * one extra day per four years
X */
X
X y = year;
X d = 4+y+(y+3)/4;
X
X/*
X * julian calendar
X * regular gregorian
X * less three days per 400
X */
X
X if(y > 1800) {
X d -= (y-1701)/100;
X d += (y-1601)/400;
X }
X
X/*
X * great calendar changeover instant
X */
X
X if(y > 1752)
X d += 3;
X
X return(d%7);
X} /* jan1 */
X
X
X
X/*
X * Procedure: movcur(day)
X *
X * Function: moves the cursor to the specified day's position
X *
X * Parameters:
X * p1 - int - day
X *
X * Discussion:
X * uses termcap values to move the cursor to a matrix position
X * stored in a global array
X */
X
Xmovcur(day)
X
X int day;
X{
X tputs( tgoto( CM, xposition[day],yposition[day]), 1, tputc );
X} /* movcur */
X
X
X/*
X * Procedure: setday(day)
X *
X * Function: places day in calendar display with appointment
X * days highlighted
X *
X * Parameters:
X * p1 - int - day
X *
X * Discussion:
X * Uses day arguement, termcap values and calendar position
X * matrices to write a day to the screen with days with appointment
X * days highlighted.
X */
X
Xsetday(day)
X
X int day;
X{
X tputs( tgoto( CM, xposition[day]-1,yposition[day]), 1, tputc );
X if (active[day]) {
X if(day > 9) {
X tputs(SO,1,tputc);
X printf("%d",day/10);
X tputs(SE,1,tputc);
X }
X else {
X tputs(SO,1,tputc);
X printf(" ");
X tputs(SE,1,tputc);
X }
X tputs(SO,1,tputc);
X printf("%d",day%10);
X tputs(SE,1,tputc);
X if (*SO == NULL) {
X printf("*");
X }
X else {
X printf(" ");
X }
X }
X else {
X if(day > 9) {
X printf("%d",day/10);
X }
X else {
X printf(" ");
X }
X printf("%d ",day%10);
X }
X} /* setday */
X
X
X
X/*
X * Procedure: tinit()
X *
X * Function: gets termcap entries
X *
X * Return Values:
X * loads global variables with termcap parameters
X *
X * Discussion:
X * Initial various termcap variables so that they can later
X * be used to move the cursor and highlight certain displays.
X */
X
Xtinit() /* termcap initalization */
X
X{
X struct sgttyb speed;
X
X char term[BUFSIZ]; /* holds termcap entry */
X char name[16]; /* terminal name */
X char *np; /* termcap name pointer */
X char *NADA = { "\0" }; /* null string */
X char *tgetstr();
X char *getenv();
X
X if( (np = getenv( "TERM" )) != NULL ) {
X strncpy( name, np, 16 );
X }
X else {
X printf("TERM environment variable does not exist\n");
X abort();
X }
X
X if( tgetent( term, name ) != 1 ) {
X printf("Termcap for %s does not exist\n",name);
X abort();
X }
X
X /* if a capability does not exist, point it to a null
X * string not NULL
X */
X
X gtty(stdout,&speed);
X ospeed = speed.sg_ospeed;
X
X tlines = tgetnum( "li" );
X tcolumns = tgetnum( "co" );
X
X if( (CM = tgetstr( "cm", &area )) == NULL) {
X CM = NADA;
X printf("Error: No termcap 'cm' entry for this terminal type\n");
X abort();
X }
X if( (CL = tgetstr( "cl", &area )) == NULL)
X CL = NADA;
X if( (UP = tgetstr( "up", &area )) == NULL)
X UP = NADA;
X if( (SO = tgetstr( "so", &area )) == NULL)
X SO = NADA;
X if( (SE = tgetstr( "se", &area )) == NULL)
X SE = NADA;
X if( (TI = tgetstr( "ti", &area)) == NULL)
X TI = NADA;
X if( (TE = tgetstr( "te", &area)) == NULL)
X TE = NADA;
X if( tgetnum( "sg", &area) > 0) {
X SO = NADA;
X SE = NADA;
X }
X if ( (BC = tgetstr( "bc", &area)) == NULL) {
X BC = backstring;
X }
X
X} /* tinit */
X
X
X
X/*
X * Procedure: loaddata(datafile)
X *
X * Function: loads data file
X *
X * Return Values:
X * Various global arrays loaded with appointment data
X *
X * Discussion:
X * Opens user's data file and reads it in, placing
X * the data in appropriate arrays.
X */
X
Xloaddata(datafile)
X
X char *datafile;
X{
X char basedata[80];
X char tmpbuf[80];
X char *getenv();
X char home[80];
X FILE *fptr;
X int i,j,k,l,field;
X
X i = 0;
X while (i < maxentries) {
X daydata[i] = 0;
X monthdata[i] = 0;
X yeardata[i] = 0;
X msgdata[i] = 0;
X i++;
X }
X
X if (datafile == NULL) {
X strcpy(home,getenv("HOME"));
X strcat(home,"/.appointments");
X }
X else {
X strcpy(home,datafile);
X }
X if ((fptr = fopen(home,"r")) != NULL) {
X i = 0;
X while((fgets(basedata,80,fptr) != NULL)) {
X
X basedata[strlen(basedata)-1] = NULL;
X
X j = 0;
X k = 0;
X field = 0;
X while (basedata[j] != NULL ) {
X
X if (basedata[j] != ',') {
X
X tmpbuf[k++] = basedata[j];
X }
X else {
X switch (field) {
X
X case 0 : {
X tmpbuf[k] = NULL;
X monthdata[i] = atoi(tmpbuf);
X k = 0;
X break;
X }
X case 1 : {
X tmpbuf[k] = NULL;
X daydata[i] = atoi(tmpbuf);
X k = 0;
X break;
X }
X case 2 : {
X tmpbuf[k] = NULL;
X yeardata[i] = atoi(tmpbuf);
X k = 0;
X break;
X }
X case 3 : {
X tmpbuf[k++] = ' ';
X tmpbuf[k++] = ' ';
X break;
X }
X }
X field++;
X }
X j++;
X }
X tmpbuf[k] = NULL;
X msgdata[i] = malloc(80);
X strncpy(msgdata[i],tmpbuf,80);
X msgdata[79] = NULL;
X
X if (i >= maxentries) {
X printf("Warning: Over 1000 entries in data file. Data truncated.\n");
X break;
X }
X i++;
X }
X fclose(fptr);
X }
X} /* loaddata */
X
X
X/*
X * Procedure: closefile(datafile)
X *
X * Function: writes appointment data to file
X *
X * Discussion:
X * Opens the user's designated data file and writes the current
X * data into it.
X */
X
Xclosefile(datafile)
X
Xchar *datafile;
X{
X FILE *fptr;
X char tmpbuf[80];
X int i;
X char *getenv();
X char home[80];
X
X if (datafile == NULL) {
X strcpy(home,getenv("HOME"));
X strcat(home,"/.appointments");
X }
X else {
X strcpy(home,datafile);
X }
X if ((fptr = fopen(home,"w")) == NULL) {
X printf("Error: Cannot open %s file",datafile);
X abort();
X }
X i = 0;
X while (i < maxentries) {
X if (daydata[i]) {
X strcpy(tmpbuf,msgdata[i]);
X tmpbuf[4] = NULL;
X fprintf(fptr,"%d,%d,%d,%4.4s,%s\n",monthdata[i],daydata[i],yeardata[i],tmpbuf,&tmpbuf[6]);
X }
X i++;
X }
X fclose(fptr);
X} /* closefile */
X
X
X
X
X/*
X * Procedure: notes(month,day,year)
X *
X * Function: displays the current day's appointments
X *
X * Parameters:
X * p1 - int - month
X * p2 - int - day
X * p3 - int - year
X *
X * Discussion:
X * Writes to notes section of screen notes for day to
X * which the cursor was pointing.
X */
X
Xnotes(month,day,year)
X
X int month,day,year;
X{
X int i,j,k;
X
X if (help1) {
X helpclr();
X help1 = 0;
X }
X
X i = 0;
X while (i < 18) {
X dayindex[i++] = 0;
X }
X
X mov(64,5);
X printf("%2d/%2d/%2d",month,day,year);
X
X i = 0;
X j = 0;
X k = 6;
X
X while (i < maxentries) {
X if ((yeardata[i] == year) && (monthdata[i] == month) && (daydata[i] == day)) {
X dayindex[j++] = i;
X notclear++;
X mov(42,k++);
X printf("%-32.32s",msgdata[i]);
X }
X if (j > maxmsgs) {
X mov(42,24);
X printf("* too many entries to print *");
X break;
X }
X i++;
X }
X i = 0;
X while (i < maxentries) {
X if (daydata[i] == 0) {
X dayindex[j++] = i;
X if (j >= maxmsgs) {
X break;
X }
X }
X i++;
X }
X} /* notes */
X
X
X
X/*
X * Procedure: modnotes(month,day,year)
X *
X * Function: add, delete and modify appointment list
X *
X * Parameters:
X * p1 - int - month
X * p2 - int - day
X * p3 - int - year
X *
X * Return Values:
X * changes data in global message and date arrays
X *
X * Discussion:
X * Allows the user to add, delete and modify a specified day's
X * appointment list. Routine contains a small character
X * interpreter which moves the cursor through the notes list
X * and selects routines to modify the list.
X */
X
Xmodnotes (month,day,year)
X
X int month,day,year;
X{
X
X char key,c;
X int xcoord,ycoord;
X int i,cnt,total;
X char tmpmsg[39];
X
X notes(month,day,year);
X xcoord = 42;
X ycoord = 6;
X i = 0;
X mov(xcoord,ycoord);
X key = 'a';
X
X while (key != LF) {
X
X key = getchar();
X
X switch (key) {
X
X case 'H' :
X
X helpnotes();
X
X break;
X
X case 'j' :
X i++;
X if (++ycoord > 23) {
X ycoord = 6;
X i = 0;
X }
X break;
X
X case 'k' :
X i--;
X if (--ycoord < 6) {
X ycoord = 23;
X i = 17;
X }
X break;
X
X case 'd' :
X
X tputs(SO,1,tputc);
X printf(" ");
X tputs(SE,1,tputc);
X mov (xcoord,ycoord);
X monthdata[dayindex[i]] = 0;
X daydata[dayindex[i]] = 0;
X yeardata[dayindex[i]] = 0;
X strcpy(msghold,msgdata[dayindex[i]]);
X if (msgdata[dayindex[i]]) {
X free(msgdata[dayindex[i]]);
X msgdata[dayindex[i]] = 0;
X }
X break;
X
X case 'y' :
X
X strcpy(msghold,msgdata[dayindex[i]]);
X
X break;
X
X case 'p' :
X
X if (msgdata[dayindex[i]] == 0) {
X msgdata[dayindex[i]] = malloc(80);
X }
X strncpy(msgdata[dayindex[i]],msghold,80);
X yeardata[dayindex[i]] = year;
X daydata[dayindex[i]] = day;
X monthdata[dayindex[i]] = month;
X printf("%s",msgdata[dayindex[i]]);
X
X break;
X
X case 'i' :
X
X tputs(SO,1,tputc);
X printf(" ");
X
X mov (xcoord,ycoord);
X
X c = '0';
X cnt = 0;
X while (c != ESC) {
X c = getchar();
X if (c != ESC ) {
X if (c == BS) {
X if (cnt > 0) {
X cnt--;
X if (cnt == 5) {
X cnt = 3;
X mov(46,ycoord);
X }
X printf("%s %s",BC,BC);
X }
X }
X else {
X if (c != LF) {
X if ( cnt < maxchars) {
X tmpmsg[cnt] = c;
X cnt++;
X printf("%c",c);
X }
X if (cnt == 4) {
X tmpmsg[4] = ' ';
X tmpmsg[5] = ' ';
X cnt = 6;
X mov(48,ycoord);
X }
X }
X else {
X c = ESC;
X }
X }
X }
X }
X tputs(SE,1,tputc);
X if (cnt) {
X tmpmsg[cnt] = NULL;
X if (msgdata[dayindex[i]] == 0) {
X msgdata[dayindex[i]] = malloc(80);
X }
X strncpy(msgdata[dayindex[i]],tmpmsg,80);
X monthdata[dayindex[i]] = month;
X daydata[dayindex[i]] = day;
X yeardata[dayindex[i]] = year;
X }
X else {
X monthdata[dayindex[i]] = 0;
X daydata[dayindex[i]] = 0;
X yeardata[dayindex[i]] = 0;
X if (msgdata[dayindex[i]]) {
X free(msgdata[dayindex[i]]);
X msgdata[dayindex[i]] = 0;
X }
X }
X
X break;
X
X default :;
X }
X mov (xcoord,ycoord);
X }
X
X active[day] = 0;
X i = 0;
X while (i < maxentries) {
X if ((yeardata[i] == year) && (monthdata[i] == month)) {
X notclear = 18;
X active[daydata[i]] = 1;
X }
X i++;
X }
X
X notclear = 18;
X clearmsgs();
X if (active[day]) {
X notes(month,day,year);
X }
X setday(day);
X if (help2) {
X helpclr();
X help2 = 0;
X }
X} /* modnotes */
X
X
X/*
X * Procedure: tputc(character)
X *
X * Function: moves cursor on screen
X *
X * Parameters:
X * p1 - int - character
X *
X * Discussion:
X * Outputs a character to crt. Used as an argument to tputs().
X */
X
Xtputc(c)
X int c;
X{
X putchar(c);
X}
X
X
X/*
X * Procedure: mov(column,row)
X *
X * Function: moves cursor on screen
X *
X * Parameters:
X * p1 - int - crt column
X * p2 - int - crt row
X *
X * Discussion:
X * Moves the cursor to specified column and row on screen using
X * termcap data.
X */
X
Xmov(col, row)
X
Xint col,row;
X
X{
X tputs( tgoto( CM, (col - 1),(row - 1)), 1, tputc );
X} /* move */
X
X
X/*
X * Procedure: clearday(month,day,year)
X *
X * Function: deletes specified day's appointments
X *
X * Parameters:
X * p1 - int - month
X * p2 - int - day
X * p2 - int - year
X *
X * Return Values:
X * changes various global arrays
X *
X * Discussion:
X * Removes appointment entries for the specified day from
X * message and date tables and from the crt
X */
X
Xclearday (month,day,year)
X
X int month,day,year;
X{
X int i;
X
X i = 0;
X while (i < maxentries) {
X if ((yeardata[i] == year) && (monthdata[i] == month) && (daydata[i] == day)) {
X active[day] = 0;
X monthdata[i] = 0;
X daydata[i] = 0;
X yeardata[i] = 0;
X if (msgdata[i]) {
X free(msgdata[i]);
X msgdata[i] = 0;
X }
X }
X i++;
X }
X clearmsgs();
X setday(day);
X} /* clearday */
X
X
X/*
X * Procedure: clearmsgs()
X *
X * Function: clears the notes section of the crt
X */
X
Xclearmsgs()
X
X{
X int i;
X
X mov(64,5);
X printf(" ");
X
X if (notclear > maxmsgs) notclear = maxmsgs;
X
X i = 6;
X while (i < (notclear+6)) {
X mov(42,i++);
X printf(" ");
X }
X mov(42,24);
X printf(" ");
X notclear = 0;
X} /* clearmsgs */
X
X
X/*
X * Procedure: helpcal()
X *
X * Function: displays calendar help messages to crt
X */
X
Xhelpcal()
X
X{
X mov(1,19);
X printf("j/k/h/l: cursor down/up/left/right \n");
X printf("b: first day e: last day \n");
X printf("space: display notes m: modify notes \n");
X printf("c: clear notes CR: exit program \n");
X printf("p: previous month n: next month \n");
X printf("BRK: exit w/o changes ");
X help1++;
X} /* helpcal */
X
X
X/*
X * Procedure: helpnotes()
X *
X * Function: displays notes help messages to crt
X */
X
Xhelpnotes()
X
X{
X mov(1,19);
X printf("j/k: cursor down/up \n");
X printf("i: enter insert ESC/CR: exit insert\n");
X printf("d: delete entry CR: exit notes \n");
X printf("y/p: yank/put a line \n");
X printf(" \n");
X printf(" ");
X help2++;
X} /* helpnotes */
X
X
X/*
X * Procedure: helpclr()
X *
X * Function: clears notes area of screen
X */
X
Xhelpclr ()
X{
X mov(1,19);
X printf(" \n");
X printf(" \n");
X printf(" \n");
X printf(" \n");
X printf(" Type 'H' for help \n");
X printf(" ");
X} /* helpclr */
X
X
X/*
X * Procedure: timeset()
X *
X * Function: sets current month, day and year variables
X *
X * Return Values:
X * tday, tmonth and tyear variables set to current date
X */
X
Xtimeset()
X
X{
X struct tm *localtime();
X
X struct tm *tp; /* time structure */
X long tloc; /* number of seconds since 1970 */
X
X time(&tloc); /* fills tloc */
X
X tp = localtime(&tloc);
X
X tyear = tp->tm_year;
X tmonth = tp->tm_mon + 1;
X tday = tp->tm_mday;
X
X tyear += 1900;
X
X} /* timeset */
*-*-END-of-vcal.c-*-*
echo x - vcal.l
sed 's/^X//' >vcal.l <<'*-*-END-of-vcal.l-*-*'
X.TH VCAL 1
X.SH NAME
Xvcal \- visual calendar and notes program
X.SH SYNOPSIS
X.B vcal
X[ month year ] [ filename ]
X.sp
Xwhere
X.I month
Xis a numeric value between 1 and 12,
X.I year
Xis a numeric four digit value and
X.I filename
Xis the data file to be accessed.
X.SH DESCRIPTION
X.I Vcal
Xis a visual calendar program which allows the user to enter notes
Xand appointments for each day of the month. It can be used to
Xreplace the "paper" desk or wall calendar with an electronic one
Xwhich can be accessed from any terminal or modem connected to the
Xcomputer system.
X.PP
XWhen a date argument is present,
X.I vcal
Xwill display the requested month and year. The default argument values
Xare the current month and year. When a filename argument is used
X.I vcal
Xwill uses that file instead of the default ~/.appointments file.
XIf ~/.appointments is not used the filename of the current file
Xwill appear at the top of the
X.I vcal
Xcalendar.
X.SH OPERATION
X.I Vcal
Xis entered from UNIX by typing the
Xcommand followed by an optional month and year value. A calendar
Xwill be displayed on the screen with the cursor located on the first
Xday of the month. The cursor may be moved to different days
Xin the following manner.
X.br
X.sp
X.nf
Xkey function
X--- --------
Xj move cursor down
Xk move cursor up
Xl move cursor to the next day
Xh move cursor to the previous day
Xb move cursor to the beginning of the month
Xe move cursor to the end of the month
X.sp
X.fi
X.PP
XPrevious and following months may also be accessed.
X.br
X.sp
X.nf
Xkey function
X--- --------
Xp previous month
Xn next month
X.sp
X.fi
X.PP
XUp to eighteen appointments may be entered on each day of the month.
XThese may be displayed, modified or cleared in with the following keys.
XThey will operate on the day selected by the current cursor position.
X.br
X.sp 4
X.nf
Xkey function
X--- --------
Xspace display appointments for the selected day
Xm enter or modify appointments
Xc clear all appointments for the selected day
X.sp
X.fi
X.PP
XWhen the 'm' is pressed
X.I vcal
Xenters notes mode. While in this mode notes may be added, modified,
Xdeleted, yanked or put.
X.br
X.sp
X.nf
Xkey function
X--- --------
Xj move cursor down
Xk move cursor up
Xi begin data insertion
XESC/CR end data insertion (only while in insert)
Xd delete the selected line
Xy hold the current line
Xp insert the held message
XCR exit notes mode and return to the calendar
X.sp
X.fi
XData must begin with the appointment time in 24 hour format
X(no ':' should be used). Entering new data will erase the current
Xmessage on that line. A held line will be available to insert until
Xit is changed or the user exits
X.I vcal.
XA line which is deleted using the 'd' key will be placed in the hold
Xbuffer.
X.PP
XWhen the cursor is on the calendar a carriage return will cause the
Xthe appointment data to be saved and
X.I vcal
Xto exit. Break or delete will cause
X.I vcal
Xto exit without updating the ~/.appointments file.
X.PP
XA 'H' will display help messages. A calendar help message
Xwill be printed when
Xthe cursor is on calendar days. A notes help message
Xis printed when the cursor is in the notes area.
X.PP
XFive companion programs are available to use with the
X.I vcal
Xprogram. These are:
X.br
X.sp
X.nf
Xappts display current or selected days appointments
Xeappts enter appointments from the UNIX command line
Xautocall set appointment reminders for the current day
Xlcal displays month's appointments in tabular form
Xcallme sets appointment reminders
X.fi
X.sp
XFor further information on these, reference the appropriate "man"
Xentries.
X.SH AUTHOR
XMike Essex
X.SH FILES
Xvcal
X.br
X/etc/termcap
X.br
X~/.appointments
X.br
X.SH "SEE ALSO"
Xappts(1), eappts(1), autocall(1), lcal(1), callme(1)
X.SH BUGS
X.I Vcal
Xmay not work with extremely brain damaged terminals. There must be
Xa 'CM' entry in the termcap for
X.I vcal
Xto draw the screen. There are year 2000 time bombs.
X.br
*-*-END-of-vcal.l-*-*
exit