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

  1. /***************************************************************/
  2. /*                                                             */
  3. /* CALENDAR.C                                                  */
  4. /*                                                             */
  5. /* Contains routines and data structures for producing a       */
  6. /* calendar from a reminder file.                              */
  7. /*                                                             */
  8. /* By David Skoll - 14 November 1990                           */
  9. /*                                                             */
  10. /***************************************************************/
  11. #include <stdio.h>
  12. #ifndef NO_MALLOC_H
  13. #include <malloc.h>
  14. #endif
  15. #include <ctype.h>
  16. #include <string.h>
  17. #ifndef UNIX
  18. #include <stdlib.h>
  19. #endif
  20. #include "defines.h"
  21. #include "globals.h"
  22. #include "protos.h"
  23. #include "cache.h"
  24.  
  25. /* Convert (monday-sunday) sequence to (sunday-saturday) */
  26. #define DayOfWeek(julian) ((((julian) % 7) + 1) % 7)
  27.  
  28. /* To center an item of length l in a field of length f, how many spaces? */
  29. #define PreCenter(f, l) (((f)-(l))/2)
  30.  
  31. /* How many spaces AFTEr the centered item? */
  32. #define PostCenter(f, l) ((f)-(l)-((f)-(l))/2)
  33.  
  34. /* Define the structure of a calendar entry */
  35. typedef struct CalEntry_t {
  36.    int tim;
  37.    char *text, *current;
  38.    struct CalEntry_t *next;
  39. } CalEntry;
  40.  
  41. /* Have a main calendar entry for each weekday */
  42. CalEntry entry[7];
  43. int used[7];  /* These hold the day of the month for corresponding
  44.                  entry - 0 if not used */
  45.  
  46. /* Static integers for various stuff */
  47. static int TotalWidth;
  48.  
  49. /* Make function prototypes local - they're not used anywhere else */
  50. #ifdef __STDC__
  51. CalEntry *CreateCalEntry(int type);
  52. void AddCalEntry(CalEntry *e);
  53. void EmitOneCalendarLine(void);
  54. void InitCalendar(int m, int y);
  55. void FinishCalendar(void);
  56. void DoEntries(void);
  57. #else
  58. CalEntry *CreateCalEntry();
  59. void AddCalEntry();
  60. void EmitOneCalendarLine();
  61. void InitCalendar();
  62. void FinishCalendar();
  63. void DoEntries();
  64. #endif
  65.  
  66. /***************************************************************/
  67. /*                                                             */
  68. /* DoCalendar - main loop for the calendar command.            */
  69. /*                                                             */
  70. /***************************************************************/
  71. #ifndef __STDC__
  72. void DoCalendar()
  73. #else
  74. void DoCalendar(void)
  75. #endif
  76. {
  77.    int y, m, d, init;
  78.  
  79.    TotalWidth = 7*CalWidth + 8;
  80.  
  81.    /* Move back until beginning of month */
  82.    FromJulian(JulianToday, &d, &m, &y);
  83.    JulianToday -= (d-1);
  84.  
  85.    init = 0;
  86.    InitCache();
  87.    while (Calendar) {
  88.       FromJulian(JulianToday, &d, &m, &y);
  89.       CurDay = d;
  90.       CurMon = m;
  91.       CurYear = y;
  92.       if (init == 0 || CurDay == 1) { InitCalendar(m, y); init = 1; }
  93.       DoEntries();
  94.       if (d == DaysInMonth(m, y)) Calendar--;
  95.       JulianToday++;
  96.       if (Calendar) ResetCache();
  97.    }
  98.    if (CurDay != DaysInMonth(CurMon, CurYear)) FinishCalendar();
  99.    DestroyCache();
  100.    FreeStackedOmits();
  101. }
  102.  
  103. /***************************************************************/
  104. /*                                                             */
  105. /* PrintChars:  Print n of the specified character             */
  106. /* CopyChars:  Copy n of the character to the output buffer    */
  107. /*                                                             */
  108. /***************************************************************/
  109. #ifdef __STDC__
  110. void PrintChars(int n, int c)
  111. #else
  112. void PrintChars(n, c)
  113. int n, c;
  114. #endif
  115. {
  116.    while(n--) putchar(c);
  117. }
  118.  
  119. #ifdef __STDC__
  120. char *CopyChars(int n, int c, char *dst)
  121. #else
  122. char *CopyChars(n, c, dst)
  123. int n, c;
  124. char *dst;
  125. #endif
  126. {
  127.    while(n--) *dst++ = (char) c;
  128.    return dst;
  129. }
  130.  
  131. /***************************************************************/
  132. /*                                                             */
  133. /* InitCalendar                                                */
  134. /* Print the calendar header                                   */
  135. /*                                                             */
  136. /***************************************************************/
  137. #ifdef __STDC__
  138. void InitCalendar(int m, int y)
  139. #else
  140. void InitCalendar(m, y)
  141. int y, m;
  142. #endif
  143. {
  144.    int i;
  145.  
  146.    if (SimpleCalendar) return;
  147.  
  148.    for (i=0; i<7; i++) {
  149.       entry[i].next = NULL;
  150.       used[i] = 0;
  151.    }
  152.  
  153.    /* Emit the calendar title */
  154.    putchar('+');
  155.    PrintChars(TotalWidth-2, '-');
  156.    putchar('+');
  157.    putchar('\n');
  158.    sprintf(TmpBuf, "%s %d", MonthName[m], y);
  159.    putchar('|');
  160.    PrintChars(PreCenter(TotalWidth-2, strlen(TmpBuf)), ' ');
  161.    printf("%s", TmpBuf);
  162.    PrintChars(PostCenter(TotalWidth-2, strlen(TmpBuf)), ' ');
  163.    putchar('|');
  164.    putchar('\n');
  165.    putchar('+');
  166.    for (i=0; i<7; i++) {
  167.       PrintChars(CalWidth, '-');
  168.       putchar('+');
  169.    }
  170.    putchar('\n');
  171.  
  172.    /* Put the weekdays in */
  173.    /* Argh! Do sunday first, then take care of rest */
  174.    i = 6;
  175.    putchar('|');
  176.    PrintChars(PreCenter(CalWidth, strlen(DayName[i])), ' ');
  177.    printf(DayName[i]);
  178.    PrintChars(PostCenter(CalWidth, strlen(DayName[i])), ' ');
  179.  
  180.    for (i=0; i<6; i++) {
  181.       putchar('|');
  182.       PrintChars(PreCenter(CalWidth, strlen(DayName[i])), ' ');
  183.       printf(DayName[i]);
  184.       PrintChars(PostCenter(CalWidth, strlen(DayName[i])), ' ');
  185.    }
  186.    putchar('|');
  187.    putchar('\n');
  188.    putchar('+');
  189.    for (i=0; i<7; i++) {
  190.       PrintChars(CalWidth, '-');
  191.       putchar('+');
  192.    }
  193.    putchar('\n');
  194. }
  195.  
  196. /***************************************************************/
  197. /*                                                             */
  198. /* FinishCalendar                                              */
  199. /* Just print a form feed.                                     */
  200. /*                                                             */
  201. /***************************************************************/
  202. #ifdef __STDC__
  203. void FinishCalendar(void)
  204. #else
  205. void FinishCalendar()
  206. #endif
  207. {
  208.    if (SimpleCalendar) return;
  209.    putchar('\f');
  210. }
  211.  
  212. /***************************************************************/
  213. /*                                                             */
  214. /* DoEntries                                                   */
  215. /* Create all the calendar entries for this week               */
  216. /*                                                             */
  217. /***************************************************************/
  218. #ifdef __STDC__
  219. void DoEntries(void)
  220. #else
  221. void DoEntries()
  222. #endif
  223. {
  224.    int i;
  225.    CalEntry *e;
  226.  
  227.    while (1) {
  228.       used[DayOfWeek(JulianToday)] = CurDay;
  229.       if (GetLine()) break;
  230.       i = ProcessLine();
  231.       if (i>0) if (e = CreateCalEntry(i)) AddCalEntry(e);
  232.    }
  233.  
  234.    /* Now figure out if we should print the calendar */
  235.    if ((DayOfWeek(JulianToday) == 6 ) || CurDay == DaysInMonth(CurMon, CurYear))
  236.       EmitOneCalendarLine();
  237.    if (CurDay == DaysInMonth(CurMon, CurYear)) FinishCalendar();
  238. }
  239.  
  240. /***************************************************************/
  241. /*                                                             */
  242. /* AddCalEntry                                                 */
  243. /* Add a calendar entry for the appropriate weekday.           */
  244. /*                                                             */
  245. /***************************************************************/
  246. #ifdef __STDC__
  247. void AddCalEntry(CalEntry *e)
  248. #else
  249. void AddCalEntry(e)
  250. CalEntry *e;
  251. #endif
  252. {
  253.    CalEntry *curr, *prev;
  254.  
  255.    prev = &entry[DayOfWeek(JulianToday)];
  256.    curr = prev->next;
  257.    while (curr) {
  258.       if (e->tim == -1 || (e->tim >= curr->tim && curr->tim != -1)) {
  259.          prev = curr;
  260.          curr = prev->next;
  261.       } else {
  262.          prev->next = e;
  263.      e->next    = curr;
  264.          break;
  265.       }
  266.    }
  267.    if (!curr) {
  268.       prev->next = e;
  269.       e->next = NULL;
  270.    }
  271. }
  272.  
  273. #ifdef __STDC__
  274. void CopyWord(char **src, char **dst, int l)
  275. #else
  276. void CopyWord(src, dst, l)
  277. char **src, **dst;
  278. int l;
  279. #endif
  280. {
  281.    while(**src && !isspace(**src) && l--) *(*dst)++ = *(*src)++;
  282. }
  283.  
  284. #ifdef __STDC__
  285. int WordLen(char *src)
  286. #else
  287. int WordLen(src)
  288. char *src;
  289. #endif
  290. {
  291.    int len = 0;
  292.    while (*src && !isspace(*src)) { len++; src++; }
  293.    return len;
  294. }
  295. /***************************************************************/
  296. /*                                                             */
  297. /* CreateCalEntry                                              */
  298. /*                                                             */
  299. /* Allocates and creates a calendar entry.                     */
  300. /*                                                             */
  301. /* Type = 1: MSG  type = 2: RUN                                */
  302. /*                                                             */
  303. /*                                                             */
  304. /***************************************************************/
  305. #ifdef __STDC__
  306. CalEntry *CreateCalEntry(int type)
  307. #else
  308. CalEntry *CreateCalEntry(type)
  309. int type;
  310. #endif
  311. {
  312.    CalEntry *e;
  313.    char *s, *t;
  314.    int column, l;
  315.    enum Token_t tok;
  316.    
  317.    if (type == 1) tok = Msg_t; else tok = Run_t;
  318.    
  319.    if (!SimpleCalendar) {
  320.       e = (CalEntry *) malloc(sizeof(CalEntry));
  321.  
  322.       if (e == NULL) {
  323.          fprintf(stderr, "remind: Can't malloc to create calendar entry.\n");
  324.          exit(1);
  325.       }
  326.       e->next = NULL;
  327.       e->tim  = CalTime;
  328.    }
  329.  
  330.    DoSubst(WorkBuf, TmpBuf, CurDay, CurMon, CurYear, JulianToday, tok, CalTime, 1);
  331.  
  332.    /* If the buffer contains zero-length string; forget it. */
  333.    if (!*TmpBuf) {
  334.       if (!SimpleCalendar) free(e);
  335.       return (NULL);
  336.    }
  337.  
  338.    /* If we're doing a simple calendar, just spit out the text and end */
  339.    if (SimpleCalendar) {
  340.       printf("%04d/%02d/%02d: ", CurYear, 1+CurMon, CurDay);
  341.       Output(TmpBuf);
  342.       return (NULL);
  343.    }
  344.  
  345.    /* Now copy from TmpBuf to WorkBuf, splitting words as needed */
  346.    s = TmpBuf;
  347.    t = WorkBuf;
  348.    column = 0;
  349.    while (*s) {
  350.       l = WordLen(s);
  351.       if (column == 0 && l >= CalWidth) {
  352.          CopyWord(&s, &t, CalWidth);
  353.          *t++ = '\n';
  354.          while (isspace(*s)) s++;
  355.       }
  356.       else if (column != 0 && column+l > CalWidth) {
  357.          *t++ = '\n';
  358.          column = 0;
  359.          if (l >= CalWidth) {
  360.             CopyWord(&s, &t, CalWidth);
  361.             *t++ = '\n';
  362.             while (isspace(*s)) s++;
  363.          } else {
  364.             CopyWord(&s, &t, l);
  365.             *t++ = ' ';
  366.             while (isspace(*s)) s++;
  367.             column = l+1;
  368.             if (column >= CalWidth) {
  369.               *(t-1) = '\n';
  370.               column = 0;
  371.             }
  372.  
  373.          }
  374.       }
  375.       else {
  376.          column += l+1;
  377.      CopyWord(&s, &t, l);
  378.          while (isspace(*s)) s++;
  379.          *t++ = ' ';
  380.      if (column > CalWidth) {
  381.            *(t-1) = '\n';
  382.            column = 0;
  383.          }
  384.       }
  385.    }
  386.    *t = 0;
  387.    if (*(t-1) == '\n') *(t-1) = 0;
  388.  
  389.    /* Finally, copy the string to the calendar entry */
  390.    e->text = (char *) malloc(strlen(WorkBuf)+1);
  391.  
  392.    if (!e->text) {
  393.       fprintf(stderr, "remind: Can't malloc memory for calendar text!\n");
  394.       exit(1);
  395.    }
  396.    strcpy(e->text, WorkBuf);
  397.    e->current = e->text;
  398.  
  399.    return e;
  400. }
  401.  
  402. /***************************************************************/
  403. /*                                                             */
  404. /* EmitOneCalendarLine                                         */
  405. /* This is the biggie - we print out one line.                 */
  406. /*                                                             */
  407. /***************************************************************/
  408. #ifdef __STDC__
  409. void EmitOneCalendarLine(void)
  410. #else
  411. void EmitOneCalendarLine()
  412. #endif
  413. {
  414.    int i, nlines, emit, j;
  415.    char *s, *dst;
  416.    CalEntry *e;
  417.    char pend[7];  /* Reminders with following blanks pending */
  418.  
  419.    if (SimpleCalendar) return;
  420.  
  421.    nlines = 0;
  422.    for (i=0; i<7; i++) pend[i] = 0;
  423.    putchar('|');
  424.    /* First, emit the days of the month */
  425.    for (i=0; i<7; i++) {
  426.       if (!used[i]) PrintChars(CalWidth, ' ');
  427.       else {
  428.          sprintf(TmpBuf, "%d", used[i]);
  429.          printf(TmpBuf);
  430.          PrintChars(CalWidth-strlen(TmpBuf), ' ');
  431.       }
  432.       putchar('|');
  433.    }
  434.    putchar('\n');
  435.  
  436.    /* Now cycle through all the reminders until there are none left */
  437.    emit = 1;
  438.    while(emit) {
  439.       dst = WorkBuf;
  440.       *dst++ = '|';
  441.       emit = 0;
  442.       for (i=0; i<7; i++) {
  443.          if (pend[i] || !used[i] || !entry[i].next) {
  444.             dst = CopyChars(CalWidth, ' ', dst);
  445.         *dst++ = '|';
  446.         if(pend[i]) {pend[i] = 0; emit = 1;}
  447.             continue;
  448.          }
  449.          s = entry[i].next->current;
  450.      j = 0;
  451.      emit = 1;
  452.      while (*s && *s != '\n') {
  453.         *dst++ = *s++;
  454.         j++;
  455.      }
  456.      dst = CopyChars(CalWidth - j, ' ', dst);
  457.          if (*s == '\n') entry[i].next->current = s+1;
  458.          else {
  459.             e = entry[i].next;
  460.         entry[i].next = e->next;
  461.             free(e->text);
  462.             free(e);
  463.         if (!entry[i].next) used[i] = 0;
  464.         else pend[i] = 1;
  465.          }
  466.          *dst++ = '|';
  467.       }
  468.       *dst = 0;
  469.       if(emit) printf("%s\n", WorkBuf);
  470.       nlines += emit;
  471.    }
  472.    while(nlines++ < 6) printf("%s\n", WorkBuf);
  473.  
  474.    putchar('+');
  475.    for (i=0; i<7; i++) {
  476.       PrintChars(CalWidth, '-');
  477.       putchar('+');
  478.    }
  479.    putchar('\n');
  480.    for (i=0; i<7; i++) used[i] = 0;
  481. }
  482.