home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Garbo
/
Garbo.cdr
/
pc
/
source
/
remind23.lzh
/
remind.2
/
calendar.c
next >
Wrap
C/C++ Source or Header
|
1991-02-24
|
13KB
|
482 lines
/***************************************************************/
/* */
/* 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;
}