home *** CD-ROM | disk | FTP | other *** search
- /***************************************************************/
- /* */
- /* CALENDAR.C */
- /* */
- /* Contains routines and data structures for producing a */
- /* calendar from a reminder file. */
- /* */
- /* By David Skoll - 14 November 1990 */
- /* */
- /***************************************************************/
- #include <stdio.h>
- #ifndef NO_MALLOC_H
- #include <malloc.h>
- #endif
- #include <ctype.h>
- #include <string.h>
- #ifndef UNIX
- #include <stdlib.h>
- #endif
- #include "defines.h"
- #include "globals.h"
- #include "protos.h"
- #include "cache.h"
-
- /* Convert (monday-sunday) sequence to (sunday-saturday) */
- #define DayOfWeek(julian) ((((julian) % 7) + 1) % 7)
-
- /* To center an item of length l in a field of length f, how many spaces? */
- #define PreCenter(f, l) (((f)-(l))/2)
-
- /* How many spaces AFTEr the centered item? */
- #define PostCenter(f, l) ((f)-(l)-((f)-(l))/2)
-
- /* Define the structure of a calendar entry */
- typedef struct CalEntry_t {
- int tim;
- char *text, *current;
- struct CalEntry_t *next;
- } CalEntry;
-
- /* Have a main calendar entry for each weekday */
- CalEntry entry[7];
- int used[7]; /* These hold the day of the month for corresponding
- entry - 0 if not used */
-
- /* Static integers for various stuff */
- static int TotalWidth;
-
- /* Make function prototypes local - they're not used anywhere else */
- #ifdef __STDC__
- CalEntry *CreateCalEntry(int type);
- void AddCalEntry(CalEntry *e);
- void EmitOneCalendarLine(void);
- void InitCalendar(int m, int y);
- void FinishCalendar(void);
- void DoEntries(void);
- #else
- CalEntry *CreateCalEntry();
- void AddCalEntry();
- void EmitOneCalendarLine();
- void InitCalendar();
- void FinishCalendar();
- void DoEntries();
- #endif
-
- /***************************************************************/
- /* */
- /* DoCalendar - main loop for the calendar command. */
- /* */
- /***************************************************************/
- #ifndef __STDC__
- void DoCalendar()
- #else
- void DoCalendar(void)
- #endif
- {
- int y, m, d, init;
-
- TotalWidth = 7*CalWidth + 8;
-
- /* Move back until beginning of month */
- FromJulian(JulianToday, &d, &m, &y);
- JulianToday -= (d-1);
-
- init = 0;
- InitCache();
- while (Calendar) {
- FromJulian(JulianToday, &d, &m, &y);
- CurDay = d;
- CurMon = m;
- CurYear = y;
- if (init == 0 || CurDay == 1) { InitCalendar(m, y); init = 1; }
- DoEntries();
- if (d == DaysInMonth(m, y)) Calendar--;
- JulianToday++;
- if (Calendar) ResetCache();
- }
- if (CurDay != DaysInMonth(CurMon, CurYear)) FinishCalendar();
- DestroyCache();
- FreeStackedOmits();
- }
-
- /***************************************************************/
- /* */
- /* PrintChars: Print n of the specified character */
- /* CopyChars: Copy n of the character to the output buffer */
- /* */
- /***************************************************************/
- #ifdef __STDC__
- void PrintChars(int n, int c)
- #else
- void PrintChars(n, c)
- int n, c;
- #endif
- {
- while(n--) putchar(c);
- }
-
- #ifdef __STDC__
- char *CopyChars(int n, int c, char *dst)
- #else
- char *CopyChars(n, c, dst)
- int n, c;
- char *dst;
- #endif
- {
- while(n--) *dst++ = (char) c;
- return dst;
- }
-
- /***************************************************************/
- /* */
- /* InitCalendar */
- /* Print the calendar header */
- /* */
- /***************************************************************/
- #ifdef __STDC__
- void InitCalendar(int m, int y)
- #else
- void InitCalendar(m, y)
- int y, m;
- #endif
- {
- int i;
-
- if (SimpleCalendar) return;
-
- for (i=0; i<7; i++) {
- entry[i].next = NULL;
- used[i] = 0;
- }
-
- /* Emit the calendar title */
- putchar('+');
- PrintChars(TotalWidth-2, '-');
- putchar('+');
- putchar('\n');
- sprintf(TmpBuf, "%s %d", MonthName[m], y);
- putchar('|');
- PrintChars(PreCenter(TotalWidth-2, strlen(TmpBuf)), ' ');
- printf("%s", TmpBuf);
- PrintChars(PostCenter(TotalWidth-2, strlen(TmpBuf)), ' ');
- putchar('|');
- putchar('\n');
- putchar('+');
- for (i=0; i<7; i++) {
- PrintChars(CalWidth, '-');
- putchar('+');
- }
- putchar('\n');
-
- /* Put the weekdays in */
- /* Argh! Do sunday first, then take care of rest */
- i = 6;
- putchar('|');
- PrintChars(PreCenter(CalWidth, strlen(DayName[i])), ' ');
- printf(DayName[i]);
- PrintChars(PostCenter(CalWidth, strlen(DayName[i])), ' ');
-
- for (i=0; i<6; i++) {
- putchar('|');
- PrintChars(PreCenter(CalWidth, strlen(DayName[i])), ' ');
- printf(DayName[i]);
- PrintChars(PostCenter(CalWidth, strlen(DayName[i])), ' ');
- }
- putchar('|');
- putchar('\n');
- putchar('+');
- for (i=0; i<7; i++) {
- PrintChars(CalWidth, '-');
- putchar('+');
- }
- putchar('\n');
- }
-
- /***************************************************************/
- /* */
- /* FinishCalendar */
- /* Just print a form feed. */
- /* */
- /***************************************************************/
- #ifdef __STDC__
- void FinishCalendar(void)
- #else
- void FinishCalendar()
- #endif
- {
- if (SimpleCalendar) return;
- putchar('\f');
- }
-
- /***************************************************************/
- /* */
- /* DoEntries */
- /* Create all the calendar entries for this week */
- /* */
- /***************************************************************/
- #ifdef __STDC__
- void DoEntries(void)
- #else
- void DoEntries()
- #endif
- {
- int i;
- CalEntry *e;
-
- while (1) {
- used[DayOfWeek(JulianToday)] = CurDay;
- if (GetLine()) break;
- i = ProcessLine();
- if (i>0) if (e = CreateCalEntry(i)) AddCalEntry(e);
- }
-
- /* Now figure out if we should print the calendar */
- if ((DayOfWeek(JulianToday) == 6 ) || CurDay == DaysInMonth(CurMon, CurYear))
- EmitOneCalendarLine();
- if (CurDay == DaysInMonth(CurMon, CurYear)) FinishCalendar();
- }
-
- /***************************************************************/
- /* */
- /* AddCalEntry */
- /* Add a calendar entry for the appropriate weekday. */
- /* */
- /***************************************************************/
- #ifdef __STDC__
- void AddCalEntry(CalEntry *e)
- #else
- void AddCalEntry(e)
- CalEntry *e;
- #endif
- {
- CalEntry *curr, *prev;
-
- prev = &entry[DayOfWeek(JulianToday)];
- curr = prev->next;
- while (curr) {
- if (e->tim == -1 || (e->tim >= curr->tim && curr->tim != -1)) {
- prev = curr;
- curr = prev->next;
- } else {
- prev->next = e;
- e->next = curr;
- break;
- }
- }
- if (!curr) {
- prev->next = e;
- e->next = NULL;
- }
- }
-
- #ifdef __STDC__
- void CopyWord(char **src, char **dst, int l)
- #else
- void CopyWord(src, dst, l)
- char **src, **dst;
- int l;
- #endif
- {
- while(**src && !isspace(**src) && l--) *(*dst)++ = *(*src)++;
- }
-
- #ifdef __STDC__
- int WordLen(char *src)
- #else
- int WordLen(src)
- char *src;
- #endif
- {
- int len = 0;
- while (*src && !isspace(*src)) { len++; src++; }
- return len;
- }
- /***************************************************************/
- /* */
- /* CreateCalEntry */
- /* */
- /* Allocates and creates a calendar entry. */
- /* */
- /* Type = 1: MSG type = 2: RUN */
- /* */
- /* */
- /***************************************************************/
- #ifdef __STDC__
- CalEntry *CreateCalEntry(int type)
- #else
- CalEntry *CreateCalEntry(type)
- int type;
- #endif
- {
- CalEntry *e;
- char *s, *t;
- int column, l;
- enum Token_t tok;
-
- if (type == 1) tok = Msg_t; else tok = Run_t;
-
- if (!SimpleCalendar) {
- e = (CalEntry *) malloc(sizeof(CalEntry));
-
- if (e == NULL) {
- fprintf(stderr, "remind: Can't malloc to create calendar entry.\n");
- exit(1);
- }
- e->next = NULL;
- e->tim = CalTime;
- }
-
- DoSubst(WorkBuf, TmpBuf, CurDay, CurMon, CurYear, JulianToday, tok, CalTime, 1);
-
- /* If the buffer contains zero-length string; forget it. */
- if (!*TmpBuf) {
- if (!SimpleCalendar) free(e);
- return (NULL);
- }
-
- /* If we're doing a simple calendar, just spit out the text and end */
- if (SimpleCalendar) {
- printf("%04d/%02d/%02d: ", CurYear, 1+CurMon, CurDay);
- Output(TmpBuf);
- return (NULL);
- }
-
- /* Now copy from TmpBuf to WorkBuf, splitting words as needed */
- s = TmpBuf;
- t = WorkBuf;
- column = 0;
- while (*s) {
- l = WordLen(s);
- if (column == 0 && l >= CalWidth) {
- CopyWord(&s, &t, CalWidth);
- *t++ = '\n';
- while (isspace(*s)) s++;
- }
- else if (column != 0 && column+l > CalWidth) {
- *t++ = '\n';
- column = 0;
- if (l >= CalWidth) {
- CopyWord(&s, &t, CalWidth);
- *t++ = '\n';
- while (isspace(*s)) s++;
- } else {
- CopyWord(&s, &t, l);
- *t++ = ' ';
- while (isspace(*s)) s++;
- column = l+1;
- if (column >= CalWidth) {
- *(t-1) = '\n';
- column = 0;
- }
-
- }
- }
- else {
- column += l+1;
- CopyWord(&s, &t, l);
- while (isspace(*s)) s++;
- *t++ = ' ';
- if (column > CalWidth) {
- *(t-1) = '\n';
- column = 0;
- }
- }
- }
- *t = 0;
- if (*(t-1) == '\n') *(t-1) = 0;
-
- /* Finally, copy the string to the calendar entry */
- e->text = (char *) malloc(strlen(WorkBuf)+1);
-
- if (!e->text) {
- fprintf(stderr, "remind: Can't malloc memory for calendar text!\n");
- exit(1);
- }
- strcpy(e->text, WorkBuf);
- e->current = e->text;
-
- return e;
- }
-
- /***************************************************************/
- /* */
- /* EmitOneCalendarLine */
- /* This is the biggie - we print out one line. */
- /* */
- /***************************************************************/
- #ifdef __STDC__
- void EmitOneCalendarLine(void)
- #else
- void EmitOneCalendarLine()
- #endif
- {
- int i, nlines, emit, j;
- char *s, *dst;
- CalEntry *e;
- char pend[7]; /* Reminders with following blanks pending */
-
- if (SimpleCalendar) return;
-
- nlines = 0;
- for (i=0; i<7; i++) pend[i] = 0;
- putchar('|');
- /* First, emit the days of the month */
- for (i=0; i<7; i++) {
- if (!used[i]) PrintChars(CalWidth, ' ');
- else {
- sprintf(TmpBuf, "%d", used[i]);
- printf(TmpBuf);
- PrintChars(CalWidth-strlen(TmpBuf), ' ');
- }
- putchar('|');
- }
- putchar('\n');
-
- /* Now cycle through all the reminders until there are none left */
- emit = 1;
- while(emit) {
- dst = WorkBuf;
- *dst++ = '|';
- emit = 0;
- for (i=0; i<7; i++) {
- if (pend[i] || !used[i] || !entry[i].next) {
- dst = CopyChars(CalWidth, ' ', dst);
- *dst++ = '|';
- if(pend[i]) {pend[i] = 0; emit = 1;}
- continue;
- }
- s = entry[i].next->current;
- j = 0;
- emit = 1;
- while (*s && *s != '\n') {
- *dst++ = *s++;
- j++;
- }
- dst = CopyChars(CalWidth - j, ' ', dst);
- if (*s == '\n') entry[i].next->current = s+1;
- else {
- e = entry[i].next;
- entry[i].next = e->next;
- free(e->text);
- free(e);
- if (!entry[i].next) used[i] = 0;
- else pend[i] = 1;
- }
- *dst++ = '|';
- }
- *dst = 0;
- if(emit) printf("%s\n", WorkBuf);
- nlines += emit;
- }
- while(nlines++ < 6) printf("%s\n", WorkBuf);
-
- putchar('+');
- for (i=0; i<7; i++) {
- PrintChars(CalWidth, '-');
- putchar('+');
- }
- putchar('\n');
- for (i=0; i<7; i++) used[i] = 0;
- }
-