home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume33 / remind / part02 < prev    next >
Encoding:
Text File  |  1992-11-10  |  39.0 KB  |  1,390 lines

  1. Newsgroups: comp.sources.misc
  2. From: dfs@doe.carleton.ca (David F. Skoll)
  3. Subject:  v33i059:  remind - A replacement for calendar, Part02/12
  4. Message-ID: <1992Nov10.041822.771@sparky.imd.sterling.com>
  5. X-Md4-Signature: 7ddd6efa3b103bcd631ef0008cc9a0eb
  6. Date: Tue, 10 Nov 1992 04:18:22 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: dfs@doe.carleton.ca (David F. Skoll)
  10. Posting-number: Volume 33, Issue 59
  11. Archive-name: remind/part02
  12. Environment: UNIX, MS-DOS
  13. Supersedes: remind: Volume 17, Issue 3-6
  14.  
  15. #!/bin/sh
  16. # This is part 02 of Remind 03.00.00
  17. if touch 2>&1 | fgrep 'amc' > /dev/null
  18.  then TOUCH=touch
  19.  else TOUCH=true
  20. fi
  21. # ============= calendar.c ==============
  22. if test X"$1" != X"-c" -a -f 'calendar.c'; then
  23.     echo "File already exists: skipping 'calendar.c'"
  24. else
  25. echo "x - extracting calendar.c (Text)"
  26. sed 's/^X//' << 'SHAR_EOF' > calendar.c &&
  27. X/***************************************************************/
  28. X/*                                                             */
  29. X/*  CALENDAR.C                                                 */
  30. X/*                                                             */
  31. X/*  The code for generating a calendar.                        */
  32. X/*                                                             */
  33. X/*  This file is part of REMIND.                               */
  34. X/*  Copyright (C) 1992 by David F. Skoll.                      */
  35. X/*                                                             */
  36. X/***************************************************************/
  37. X#include "config.h"
  38. X#include <stdio.h>
  39. X#ifdef HAVE_STDLIB_H
  40. X#include <stdlib.h>
  41. X#endif
  42. X#ifdef HAVE_MALLOC_H
  43. X#include <malloc.h>
  44. X#endif
  45. X#include <ctype.h>
  46. X#include "types.h"
  47. X#include "protos.h"
  48. X#include "expr.h"
  49. X#include "globals.h"
  50. X#include "err.h"
  51. X
  52. X/* Data structures used by the calendar */
  53. Xtypedef struct _cal_entry {
  54. X   struct _cal_entry *next;
  55. X   char *text;
  56. X   char *pos;
  57. X   int time;
  58. X} CalEntry;
  59. X
  60. X/* Global variables */
  61. Xstatic CalEntry *CalColumn[7];
  62. X
  63. Xstatic int ColSpaces;
  64. X
  65. XPRIVATE void SortColByTime ARGS((int col));
  66. XPRIVATE void DoCalendarOneWeek ARGS ((void));
  67. XPRIVATE void DoCalendarOneMonth ARGS ((void));
  68. XPRIVATE int WriteCalendarRow ARGS ((void));
  69. XPRIVATE void PrintLeft ARGS ((char *s, int width, char pad));
  70. XPRIVATE void PrintCentered ARGS ((char *s, int width, char pad));
  71. XPRIVATE int WriteOneCalLine ARGS ((void));
  72. XPRIVATE int WriteOneColLine ARGS ((int col));
  73. XPRIVATE void GenerateCalEntries ARGS ((int col));
  74. XPRIVATE void WriteCalHeader ARGS ((void));
  75. XPRIVATE void WriteCalTrailer ARGS ((void));
  76. XPRIVATE int DoCalRem ARGS ((ParsePtr p, int col));
  77. XPRIVATE void WriteSimpleEntries ARGS ((int col, int jul));
  78. XPRIVATE void WriteSolidCalLine ARGS ((void));
  79. XPRIVATE void WriteIntermediateCalLine ARGS ((void));
  80. XPRIVATE void WriteCalDays ARGS ((void));
  81. X
  82. X/***************************************************************/
  83. X/*                                                             */
  84. X/*  ProduceCalendar                                            */
  85. X/*                                                             */
  86. X/*  Main loop for generating a calendar.                       */
  87. X/*                                                             */
  88. X/***************************************************************/
  89. X#ifdef HAVE_PROTOS
  90. XPUBLIC void ProduceCalendar(void)
  91. X#else
  92. Xvoid ProduceCalendar()
  93. X#endif
  94. X{
  95. X   int y, m, d;
  96. X
  97. X   ShouldCache = 1;
  98. X
  99. X   ColSpaces = (CalWidth - 9) / 7;
  100. X   CalWidth = 7*ColSpaces + 8;
  101. X
  102. X   if (CalMonths) {
  103. X      FromJulian(JulianToday, &y, &m, &d);
  104. X      JulianToday = Julian(y, m, 1);   
  105. X      while (CalMonths--)
  106. X         DoCalendarOneMonth();
  107. X      return;
  108. X   } else {
  109. X      JulianToday -= ((JulianToday+1)%7);
  110. X
  111. X      WriteIntermediateCalLine();
  112. X      WriteCalDays();
  113. X      WriteIntermediateCalLine();
  114. X
  115. X      while (CalWeeks--)
  116. X         DoCalendarOneWeek();
  117. X      return;
  118. X   }
  119. X}
  120. X
  121. X/***************************************************************/
  122. X/*                                                             */
  123. X/*  DoCalendarOneWeek                                          */
  124. X/*                                                             */
  125. X/*  Write a calendar for a single week                         */
  126. X/*                                                             */
  127. X/***************************************************************/
  128. X#ifdef HAVE_PROTOS
  129. XPRIVATE void DoCalendarOneWeek(void)
  130. X#else
  131. Xstatic void DoCalendarOneWeek()
  132. X#endif
  133. X{
  134. X   int y, m, d, done, i;
  135. X   char buf[81];
  136. X   int LinesWritten = 0;
  137. X   int OrigJul = JulianToday;
  138. X
  139. X/* Fill in the column entries */
  140. X   for (i=0; i<7; i++) {
  141. X      GenerateCalEntries(i);
  142. X      JulianToday++;
  143. X   }
  144. X
  145. X/* Output the entries */
  146. X
  147. X/* Here come the first two lines... */
  148. X   putchar('|');
  149. X   for (i=0; i<7; i++) {
  150. X      FromJulian(OrigJul+i, &y, &m, &d);
  151. X      sprintf(buf, "%d %c%c%c ", d, MonthName[m][0], MonthName[m][1], 
  152. X                                   MonthName[m][2]);
  153. X      if (OrigJul+i == RealToday)                  
  154. X         PrintLeft(buf, ColSpaces, '*');
  155. X      else
  156. X         PrintLeft(buf, ColSpaces, ' ');
  157. X      putchar('|');
  158. X   }
  159. X   putchar('\n');
  160. X/*** Take out blank line in weekly calendar display - takes up room
  161. X   putchar('|');
  162. X   for (i=0; i<7; i++) {
  163. X      PrintLeft("", ColSpaces, ' ');
  164. X      putchar('|');
  165. X   }
  166. X   putchar('\n');
  167. X***/
  168. X/* Write the body lines */
  169. X   done = 0;
  170. X   while (!done) {
  171. X      done = WriteOneCalLine();
  172. X      LinesWritten++;
  173. X   }
  174. X
  175. X/* Write any blank lines required */
  176. X   while (LinesWritten++ < CAL_LINES) {
  177. X      putchar('|');
  178. X      for (i=0; i<7; i++) {
  179. X         PrintLeft("", ColSpaces, ' ');
  180. X         putchar('|');
  181. X      }
  182. X      putchar('\n');
  183. X   }
  184. X
  185. X/* Write the final line */   
  186. X   WriteIntermediateCalLine();
  187. X}
  188. X
  189. X/***************************************************************/
  190. X/*                                                             */
  191. X/*  DoCalendarOneMonth                                         */
  192. X/*                                                             */
  193. X/*  Produce a calendar for the current month.                  */
  194. X/*                                                             */
  195. X/***************************************************************/
  196. X#ifdef HAVE_PROTOS
  197. XPRIVATE void DoCalendarOneMonth(void)
  198. X#else
  199. Xstatic void DoCalendarOneMonth()
  200. X#endif
  201. X{
  202. X   if (!DoSimpleCalendar) WriteCalHeader();
  203. X
  204. X   while (WriteCalendarRow()) continue;
  205. X
  206. X   if (!DoSimpleCalendar) WriteCalTrailer();
  207. X}   
  208. X
  209. X/***************************************************************/
  210. X/*                                                             */
  211. X/*  WriteCalendarRow                                           */
  212. X/*                                                             */
  213. X/*  Write one row of the calendar                              */
  214. X/*                                                             */
  215. X/***************************************************************/
  216. X#ifdef HAVE_PROTOS
  217. XPRIVATE int WriteCalendarRow(void)
  218. X#else
  219. Xstatic int WriteCalendarRow()
  220. X#endif
  221. X{
  222. X   int y, m, d, wd, i;
  223. X   int done;
  224. X   char buf[81];
  225. X   int OrigJul = JulianToday;
  226. X   int LinesWritten = 0;
  227. X
  228. X/* Get the date of the first day */
  229. X   FromJulian(JulianToday, &y, &m, &d);
  230. X   wd = (JulianToday + 1) % 7;
  231. X
  232. X/* Fill in the column entries */
  233. X   for (i=wd; i<7; i++) {
  234. X      if (d+i-wd > DaysInMonth(m, y)) break;
  235. X      GenerateCalEntries(i);
  236. X      JulianToday++;
  237. X   }
  238. X
  239. X/* Output the entries */
  240. X
  241. X/* If it's "Simple Calendar" format, do it simply... */
  242. X   if (DoSimpleCalendar) {
  243. X      for (i=wd; i<7 && d+i-wd<=DaysInMonth(m, y); i++) {
  244. X         WriteSimpleEntries(i, OrigJul+i-wd);
  245. X      }
  246. X      return (d+7-wd <= DaysInMonth(m, y));
  247. X   }
  248. X
  249. X/* Here come the first two lines... */
  250. X   putchar('|');
  251. X   for (i=0; i<7; i++) {
  252. X      if (i < wd || d+i-wd>DaysInMonth(m, y))
  253. X         PrintLeft("", ColSpaces, ' ');
  254. X      else {
  255. X         sprintf(buf, "%d", d+i-wd);
  256. X     PrintLeft(buf, ColSpaces, ' ');
  257. X      }
  258. X      putchar('|');
  259. X   }
  260. X   putchar('\n');
  261. X   putchar('|');
  262. X   for (i=0; i<7; i++) {
  263. X      PrintLeft("", ColSpaces, ' ');
  264. X      putchar('|');
  265. X   }
  266. X   putchar('\n');
  267. X
  268. X/* Write the body lines */
  269. X   done = 0;
  270. X   while (!done) {
  271. X      done = WriteOneCalLine();
  272. X      LinesWritten++;
  273. X   }
  274. X
  275. X/* Write any blank lines required */
  276. X   while (LinesWritten++ < CAL_LINES) {
  277. X      putchar('|');
  278. X      for (i=0; i<7; i++) {
  279. X         PrintLeft("", ColSpaces, ' ');
  280. X         putchar('|');
  281. X      }
  282. X      putchar('\n');
  283. X   }
  284. X
  285. X   WriteIntermediateCalLine();
  286. X
  287. X/* Return non-zero if we have not yet finished */
  288. X   return (d+7-wd <= DaysInMonth(m, y));
  289. X}
  290. X
  291. X/***************************************************************/
  292. X/*                                                             */
  293. X/*  PrintLeft                                                  */
  294. X/*                                                             */
  295. X/*  Left-justify a piece of text.                              */
  296. X/*                                                             */
  297. X/***************************************************************/
  298. X#ifdef HAVE_PROTOS
  299. XPRIVATE void PrintLeft(char *s, int width, char pad)
  300. X#else
  301. Xstatic void PrintLeft(s, width, pad)
  302. Xchar *s;
  303. Xint width;
  304. Xchar pad;
  305. X#endif
  306. X{
  307. X   int len = strlen(s);
  308. X   printf("%s", s);
  309. X   while (len++ < width) putchar(pad);
  310. X}
  311. X
  312. X/***************************************************************/
  313. X/*                                                             */
  314. X/*  PrintCentered                                              */
  315. X/*                                                             */
  316. X/*  Center a piec of text                                      */
  317. X/*                                                             */
  318. X/***************************************************************/
  319. X#ifdef HAVE_PROTOS
  320. XPRIVATE void PrintCentered(char *s, int width, char pad)
  321. X#else
  322. Xstatic void PrintCentered(s, width, pad)
  323. Xchar *s;
  324. Xint width;
  325. Xchar pad;
  326. X#endif
  327. X{
  328. X   int len = strlen(s);
  329. X   int d = (width - len) / 2;
  330. X   int i;
  331. X
  332. X   for (i=0; i<d; i++) putchar(pad);
  333. X   printf("%s", s);
  334. X   for (i=d+len; i<width; i++) putchar(pad);
  335. X}
  336. X
  337. X/***************************************************************/
  338. X/*                                                             */
  339. X/*  WriteOneCalLine                                            */
  340. X/*                                                             */
  341. X/*  Write a single line.                                       */
  342. X/*                                                             */
  343. X/***************************************************************/
  344. X#ifdef HAVE_PROTOS
  345. XPRIVATE int WriteOneCalLine(void)
  346. X#else
  347. Xstatic int WriteOneCalLine()
  348. X#endif
  349. X{
  350. X   int done = 1, i;
  351. X
  352. X   putchar('|');
  353. X   for (i=0; i<7; i++) {
  354. X      if (CalColumn[i]) {
  355. X         if (WriteOneColLine(i)) done = 0;
  356. X      } else {
  357. X         PrintCentered("", ColSpaces, ' ');
  358. X      }
  359. X      putchar('|');
  360. X   }
  361. X   putchar('\n');
  362. X
  363. X   return done;
  364. X}
  365. X
  366. X     
  367. X/***************************************************************/
  368. X/*                                                             */
  369. X/*  WriteOneColLine                                            */
  370. X/*                                                             */
  371. X/*  Write a single line for a specified column.  Return 1 if   */
  372. X/*  the column still has entries; 0 otherwise.                 */
  373. X/*                                                             */
  374. X/***************************************************************/
  375. X#ifdef HAVE_PROTOS
  376. XPRIVATE int WriteOneColLine(int col)
  377. X#else
  378. Xstatic int WriteOneColLine(col)
  379. Xint col;
  380. X#endif
  381. X{
  382. X   CalEntry *e = CalColumn[col];
  383. X   char *s;
  384. X   char *space;
  385. X   int numwritten = 0;
  386. X
  387. X/* Print as many characters as possible within the column */
  388. X   space = NULL;
  389. X   s = e->pos;
  390. X
  391. X/* If we're at the end, and there's another entry, do a blank line and move
  392. X   to next entry. */
  393. X   if (!*s && e->next) {
  394. X      PrintLeft("", ColSpaces, ' ');
  395. X      CalColumn[col] = e->next;
  396. X      free(e->text);
  397. X      free(e);
  398. X      return 1;
  399. X   }
  400. X
  401. X/* Find the last space char within the column. */
  402. X   while (s - e->pos <= ColSpaces) {
  403. X      if (!*s) {space = s; break;}
  404. X      if (*s == ' ') space = s;
  405. X      s++;
  406. X   }
  407. X
  408. X/* If we couldn't find a space char, print what we have. */
  409. X   if (!space) {
  410. X      for (s = e->pos; s - e->pos < ColSpaces; s++) {
  411. X         if (!*s) break;
  412. X     numwritten++;
  413. X         putchar(*s);
  414. X      }
  415. X      e->pos = s;
  416. X   } else {
  417. X
  418. X/* We found a space - print everything before it. */
  419. X      for (s = e->pos; s<space; s++) {
  420. X         if (!*s) break;
  421. X     numwritten++;
  422. X     putchar(*s);
  423. X      }
  424. X   }
  425. X
  426. X/* Flesh out the rest of the column */
  427. X   while(numwritten++ < ColSpaces) putchar(' ');
  428. X
  429. X/* Skip any spaces before next word */
  430. X   while (*s == ' ') s++;
  431. X
  432. X/* If done, free memory if no next entry. */
  433. X   if (!*s && !e->next) {
  434. X      CalColumn[col] = e->next;
  435. X      free(e->text);
  436. X      free(e);
  437. X   } else {
  438. X      e->pos = s;
  439. X   }
  440. X   if (CalColumn[col]) return 1; else return 0;
  441. X}
  442. X
  443. X/***************************************************************/
  444. X/*                                                             */
  445. X/*  GenerateCalEntries                                         */
  446. X/*                                                             */
  447. X/*  Generate the calendar entries for the ith column           */
  448. X/*                                                             */
  449. X/***************************************************************/
  450. X#ifdef HAVE_PROTOS
  451. XPRIVATE void GenerateCalEntries(int col)
  452. X#else
  453. Xstatic void GenerateCalEntries(col)
  454. Xint col;
  455. X#endif
  456. X{
  457. X   int r;
  458. X   Token tok;
  459. X   char *s;
  460. X   Parser p;
  461. X
  462. X/* Do some initialization first... */
  463. X   ClearGlobalOmits();
  464. X   DestroyOmitContexts();
  465. X   DestroyVars();
  466. X
  467. X   r=OpenFile(InitialFile);
  468. X   if (r) {
  469. X      fprintf(ErrFp, "Can't read %s: %s\n", InitialFile, ErrMsg[r]);
  470. X      exit(1);
  471. X   }
  472. X
  473. X   while(1) {
  474. X      r = ReadLine();
  475. X      if (r == E_EOF) return;
  476. X      if (r) {
  477. X     Eprint("Error reading file: %s", ErrMsg[r]);
  478. X     exit(1);
  479. X      }
  480. X      s = FindInitialToken(&tok, CurLine);
  481. X
  482. X      /* Should we ignore it? */
  483. X      if (NumIfs &&
  484. X          tok.type != T_If &&
  485. X          tok.type != T_Else &&
  486. X          tok.type != T_EndIf &&
  487. X          tok.type != T_IfTrig &&
  488. X          ShouldIgnoreLine())
  489. X      {
  490. X      /* DO NOTHING */
  491. X      }
  492. X      else {
  493. X         /* Create a parser to parse the line */
  494. X         CreateParser(s, &p);
  495. X
  496. X         switch(tok.type) {
  497. X
  498. X            case T_Empty:
  499. X        case T_Comment:
  500. X           break;
  501. X
  502. X        case T_ErrMsg:  r=DoErrMsg(&p);  break;
  503. X        case T_Rem:     r=DoCalRem(&p, col); break;
  504. X        case T_If:      r=DoIf(&p);      break;
  505. X        case T_IfTrig:  r=DoIfTrig(&p);  break;
  506. X        case T_Else:    r=DoElse(&p);    break;
  507. X        case T_EndIf:   r=DoEndif(&p);   break;
  508. X        case T_Include: r=DoInclude(&p); break;
  509. X        case T_Exit:    exit(99);
  510. X        case T_Set:     r=DoSet(&p);     break;
  511. X        case T_Fset:    r=DoFset(&p);    break;
  512. X        case T_UnSet:   r=DoUnset(&p);   break;
  513. X        case T_Clr:     r=DoClear(&p);   break;
  514. X            case T_Debug:   break;  /* IGNORE DEBUG CMD */
  515. X        case T_Dumpvars: break; /* IGNORE DUMPVARS CMD */
  516. X        case T_Banner:  break;  /* IGNORE BANNER CMD */
  517. X        case T_Omit:    r=DoOmit(&p);
  518. X                       if (r == E_PARSE_AS_REM) {
  519. X                   DestroyParser(&p);
  520. X                   CreateParser(s, &p);
  521. X                   r=DoCalRem(&p, col);
  522. X                }
  523. X                            break;
  524. X        case T_Pop:     r=PopOmitContext(&p);     break;
  525. X        case T_Push:    r=PushOmitContext(&p);    break;
  526. X            case T_Preserve: r=DoPreserve(&p);        break;
  527. X        case T_RemType: if (tok.val == RUN_TYPE) {
  528. X                               r=DoRun(&p);
  529. X                               break;
  530. X                 } else {
  531. X                    CreateParser(CurLine, &p);
  532. X                r=DoCalRem(&p, col);
  533. X                break;
  534. X                 }
  535. X
  536. X     /* If we don't recognize the command, do a REM by default */
  537. X     /* Note:  Since the parser hasn't been used yet, we don't */
  538. X     /* need to destroy it here. */
  539. X
  540. X        default:        CreateParser(CurLine, &p);
  541. X                r=DoCalRem(&p, col);
  542. X                break;
  543. X         }
  544. X         if (r && (!Hush || r != E_RUN_DISABLED)) Eprint("%s", ErrMsg[r]);
  545. X
  546. X         /* Destroy the parser - free up resources it may be tying up */
  547. X         DestroyParser(&p);
  548. X      }
  549. X   }
  550. X}
  551. X
  552. X
  553. X/***************************************************************/
  554. X/*                                                             */
  555. X/*  WriteCalHeader                                             */
  556. X/*                                                             */
  557. X/***************************************************************/
  558. X#ifdef HAVE_PROTOS
  559. XPRIVATE void WriteCalHeader(void)
  560. X#else
  561. Xstatic void WriteCalHeader()
  562. X#endif
  563. X{
  564. X   char buf[80];
  565. X   int y, m, d;
  566. X
  567. X   FromJulian(JulianToday, &y, &m, &d);
  568. X   sprintf(buf, "%s %d", MonthName[m], y);
  569. X
  570. X   WriteSolidCalLine();
  571. X
  572. X   putchar('|');
  573. X   PrintCentered(buf, CalWidth-2, ' ');
  574. X   putchar('|');
  575. X   putchar('\n');
  576. X
  577. X   WriteIntermediateCalLine();
  578. X   WriteCalDays();
  579. X   WriteIntermediateCalLine();
  580. X}
  581. X
  582. X/***************************************************************/
  583. X/*                                                             */
  584. X/*  WriteCalTrailer                                            */
  585. X/*                                                             */
  586. X/***************************************************************/
  587. X#ifdef HAVE_PROTOS
  588. XPRIVATE void WriteCalTrailer(void)
  589. X#else
  590. Xstatic void WriteCalTrailer()
  591. X#endif
  592. X{
  593. X   putchar('\f');
  594. X}
  595. X
  596. X/***************************************************************/
  597. X/*                                                             */
  598. X/*  DoCalRem                                                   */
  599. X/*                                                             */
  600. X/*  Do the REM command in the context of a calendar.           */
  601. X/*                                                             */
  602. X/***************************************************************/
  603. X#ifdef HAVE_PROTOS
  604. XPRIVATE int DoCalRem(ParsePtr p, int col)
  605. X#else
  606. Xstatic int DoCalRem(p, col)
  607. XParsePtr p;
  608. Xint col;
  609. X#endif
  610. X{
  611. X
  612. X   Trigger trig;
  613. X   TimeTrig tim;
  614. X   int r;
  615. X   int jul;
  616. X   CalEntry *CurCol = CalColumn[col];
  617. X   CalEntry *e;
  618. X   char *s;
  619. X
  620. X   /* Parse the trigger date and time */
  621. X   if (r=ParseRem(p, &trig, &tim)) return r;
  622. X
  623. X   if (trig.typ == NO_TYPE) return E_EOLN;
  624. X   if (trig.typ == SAT_TYPE) return DoSatRemind(&trig, &tim, p);
  625. X   /* Calculate the trigger date */
  626. X   jul = ComputeTrigger(JulianToday, &trig, &r);
  627. X   if (r) return r;
  628. X
  629. X   /* If trigger date == today, add it to the current entry */   
  630. X   if (jul == JulianToday) {
  631. X      s = SubstBuffer;
  632. X      if (DoSimpleCalendar || tim.ttime != NO_TIME)
  633. X         s += strlen(SimpleTime(tim.ttime, s));
  634. X      if (r=DoSubst(p, s, &trig, &tim, jul, CAL_MODE)) return r;
  635. X      if (!*s) return OK;
  636. X      s = SubstBuffer;
  637. X      if (!DoSimpleCalendar) while (isspace(*s)) s++;
  638. X      e = NEW(CalEntry);
  639. X      if (!e) return E_NO_MEM;
  640. X      e->text = StrDup(s);
  641. X      if (!e->text) {
  642. X         free(e);
  643. X     return E_NO_MEM;
  644. X      }
  645. X      e->pos = e->text;
  646. X      e->time = tim.ttime;
  647. X      e->next = CurCol;
  648. X      CalColumn[col] = e;
  649. X      SortColByTime(col);
  650. X   }
  651. X   return OK;
  652. X}
  653. X
  654. X/***************************************************************/
  655. X/*                                                             */
  656. X/*  WriteSimpleEntries                                         */
  657. X/*                                                             */
  658. X/*  Write entries in 'simple calendar' format.                 */
  659. X/*                                                             */
  660. X/***************************************************************/
  661. X#ifdef HAVE_PROTOS
  662. XPRIVATE void WriteSimpleEntries(int col, int jul)
  663. X#else
  664. Xstatic void WriteSimpleEntries(col, jul)
  665. Xint col, jul;
  666. X#endif
  667. X{
  668. X   CalEntry *e = CalColumn[col];
  669. X   CalEntry *n;
  670. X   int y, m, d;
  671. X
  672. X   FromJulian(jul, &y, &m, &d);
  673. X   while(e) {
  674. X      printf("%04d/%02d/%02d ", y, m+1, d);
  675. X      printf("%s\n", e->text);
  676. X      free(e->text);
  677. X      n = e->next;
  678. X      free(e);
  679. X      e = n;
  680. X   }
  681. X   CalColumn[col] = NULL;
  682. X}
  683. X
  684. X/***************************************************************/
  685. X/*                                                             */
  686. X/*  Various functions for writing different types of lines.    */
  687. X/*                                                             */
  688. X/***************************************************************/
  689. X#ifdef HAVE_PROTOS
  690. XPRIVATE void WriteSolidCalLine(void)
  691. X#else
  692. Xstatic void WriteSolidCalLine()
  693. X#endif
  694. X{
  695. X   putchar('+');
  696. X   PrintCentered("", CalWidth-2, '-');
  697. X   putchar('+');
  698. X   putchar('\n');
  699. X}
  700. X
  701. X#ifdef HAVE_PROTOS
  702. XPRIVATE void WriteIntermediateCalLine(void)
  703. X#else
  704. Xstatic void WriteIntermediateCalLine()
  705. X#endif
  706. X{
  707. X   int i;
  708. X
  709. X   putchar('+');
  710. X   for (i=0; i<7; i++) {
  711. X      PrintCentered("", ColSpaces, '-');
  712. X      putchar('+');
  713. X   }
  714. X   putchar('\n');
  715. X}
  716. X
  717. X#ifdef HAVE_PROTOS
  718. XPRIVATE void WriteCalDays(void)
  719. X#else
  720. Xstatic void WriteCalDays()
  721. X#endif
  722. X{
  723. X   int i;
  724. X   putchar('|');
  725. X   for (i=0; i<7; i++) {
  726. X      PrintCentered(DayName[(i+6)%7], ColSpaces, ' ');
  727. X      putchar('|');
  728. X   }
  729. X   putchar('\n');
  730. X}
  731. X
  732. X/***************************************************************/
  733. X/*                                                             */
  734. X/*  SimpleTime                                                 */
  735. X/*                                                             */
  736. X/*  Format the time according to simple time format.           */
  737. X/*  If out is NULL, result placed in internal static buffer.   */
  738. X/*  A trailing space is always added.                          */
  739. X/*                                                             */
  740. X/***************************************************************/
  741. X#ifdef HAVE_PROTOS
  742. XPUBLIC char *SimpleTime(int tim, char *out)
  743. X#else
  744. Xchar *SimpleTime(tim, out)
  745. Xint tim;
  746. Xchar *out;
  747. X#endif
  748. X{
  749. X   static buf[9];
  750. X   int h, min, hh;
  751. X   
  752. X   if (!out) out = (char *) buf;
  753. X
  754. X   *out = 0;
  755. X   
  756. X   switch(ScFormat) {
  757. X
  758. X      case SC_AMPM:
  759. X     if (tim == NO_TIME) sprintf(out, "        ");
  760. X     else {
  761. X        h = tim / 60;
  762. X        min = tim % 60;
  763. X        if (h == 0) hh=12;
  764. X        else if (h > 12) hh=h-12;
  765. X        else hh=h;
  766. X        sprintf(out, "%2d:%02d%s ", hh, min, (h>=12) ? "pm" : "am");
  767. X         }
  768. X     break;
  769. X
  770. X      case SC_MIL:
  771. X     if (tim == NO_TIME) sprintf(out, "      ");
  772. X     else {
  773. X        h = tim / 60;
  774. X        min = tim % 60;
  775. X        sprintf(out, "%02d:%02d ", h, min);
  776. X         }
  777. X     break;
  778. X   }
  779. X   return out;
  780. X}
  781. X
  782. X/***************************************************************/
  783. X/*                                                             */
  784. X/*  SortColByTime                                              */
  785. X/*                                                             */
  786. X/*  Sort the calendar entries in a column by time.             */
  787. X/*                                                             */
  788. X/***************************************************************/
  789. X#ifdef HAVE_PROTOS
  790. XPRIVATE void SortColByTime(int col)
  791. X#else
  792. Xstatic void SortColByTime(col)
  793. Xint col;
  794. X#endif
  795. X{
  796. X   CalEntry *cur, *prev, *next;
  797. X
  798. X   cur = CalColumn[col];
  799. X   prev = NULL;
  800. X
  801. X/* Note that we use >= comparison rather than > comparison to preserve the
  802. X   file order of reminders which have the same time! */
  803. X
  804. X   while (cur->next && cur->time >= cur->next->time) {
  805. X      next = cur->next;
  806. X   /* Swap cur and next */
  807. X      if (!prev) {
  808. X         CalColumn[col] = next;
  809. X     cur->next = next->next;
  810. X     next->next = cur;
  811. X     prev = next;
  812. X      } else {
  813. X         prev->next = next;
  814. X     cur->next = next->next;
  815. X     next->next = cur;
  816. X     prev = next;
  817. X      }
  818. X   }
  819. X}
  820. X
  821. SHAR_EOF
  822. $TOUCH -am 1109141292 calendar.c &&
  823. chmod 0600 calendar.c ||
  824. echo "restore of calendar.c failed"
  825. set `wc -c calendar.c`;Wc_c=$1
  826. if test "$Wc_c" != "22448"; then
  827.     echo original size 22448, current size $Wc_c
  828. fi
  829. fi
  830. # ============= dorem.c ==============
  831. if test X"$1" != X"-c" -a -f 'dorem.c'; then
  832.     echo "File already exists: skipping 'dorem.c'"
  833. else
  834. echo "x - extracting dorem.c (Text)"
  835. sed 's/^X//' << 'SHAR_EOF' > dorem.c &&
  836. X/***************************************************************/
  837. X/*                                                             */
  838. X/*  DOREM.C                                                    */
  839. X/*                                                             */
  840. X/*  Contains routines for parsing reminders and evaluating     */
  841. X/*  triggers.  Also contains routines for parsing OMIT         */
  842. X/*  commands.                                                  */
  843. X/*                                                             */
  844. X/*  This file is part of REMIND.                               */
  845. X/*  Copyright (C) 1992 by David F. Skoll.                      */
  846. X/*                                                             */
  847. X/***************************************************************/
  848. X#include <stdio.h>
  849. X#include "config.h"
  850. X#ifdef HAVE_STDLIB_H
  851. X#include <stdlib.h>
  852. X#endif
  853. X#ifdef HAVE_MALLOC_H
  854. X#include <malloc.h>
  855. X#endif
  856. X#include "globals.h"
  857. X#include "err.h"
  858. X#include "types.h"
  859. X#include "protos.h"
  860. X#include "expr.h"
  861. X
  862. XPRIVATE int ParseTimeTrig ARGS ((ParsePtr s, TimeTrig *tim));
  863. XPRIVATE int ParseLocalOmit ARGS ((ParsePtr s, Trigger *t));
  864. XPRIVATE int ParseUntil ARGS ((ParsePtr s, Trigger *t));
  865. X
  866. X/***************************************************************/
  867. X/*                                                             */
  868. X/*  DoRem                                                      */
  869. X/*                                                             */
  870. X/*  Do the REM command.                                        */
  871. X/*                                                             */
  872. X/***************************************************************/
  873. X#ifdef HAVE_PROTOS
  874. XPUBLIC int DoRem(ParsePtr p)
  875. X#else
  876. Xint DoRem(p)
  877. XParsePtr p;
  878. X#endif
  879. X{
  880. X
  881. X   Trigger trig;
  882. X   TimeTrig tim;
  883. X   int r;
  884. X   int jul;
  885. X
  886. X   /* Parse the trigger date and time */
  887. X   if (r=ParseRem(p, &trig, &tim)) return r;
  888. X
  889. X   if (trig.typ == NO_TYPE) return E_EOLN;
  890. X   if (trig.typ == SAT_TYPE) return DoSatRemind(&trig, &tim, p);
  891. X   /* Calculate the trigger date */
  892. X   jul = ComputeTrigger(JulianToday, &trig, &r);
  893. X   if (r) return r;
  894. X   
  895. X/* Queue the reminder, if necessary */
  896. X#ifdef HAVE_QUEUED
  897. X   if (jul == JulianToday &&
  898. X       !(!IgnoreOnce &&
  899. X      trig.once != NO_ONCE &&
  900. X      FileAccessDate == JulianToday))
  901. X      QueueReminder(p, trig.typ, &tim);
  902. X/* If we're in daemon mode, do nothing over here */
  903. X   if (Daemon) return OK;
  904. X#endif
  905. X
  906. X
  907. X   if (ShouldTriggerReminder(&trig, &tim, jul)) {
  908. X      if (r=TriggerReminder(p, &trig, &tim, jul)) return r;
  909. X   }
  910. X
  911. X   return OK;
  912. X}   
  913. X
  914. X/***************************************************************/
  915. X/*                                                             */
  916. X/*  ParseRem                                                   */
  917. X/*                                                             */
  918. X/*  Given a parse pointer, parse line and fill in a            */
  919. X/*  trigger structure.                                         */
  920. X/*                                                             */
  921. X/***************************************************************/
  922. X#ifdef HAVE_PROTOS
  923. XPUBLIC int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
  924. X#else
  925. Xint ParseRem(s, trig, tim)
  926. XParsePtr s;
  927. XTrigger *trig;
  928. XTimeTrig *tim;
  929. X#endif
  930. X{
  931. X   register int r;
  932. X   Token tok;
  933. X
  934. X   trig->y = NO_YR;
  935. X   trig->m = NO_MON;
  936. X   trig->d = NO_DAY;
  937. X   trig->wd = NO_WD;
  938. X   trig->back = NO_BACK;
  939. X   trig->delta = NO_DELTA;
  940. X   trig->until = NO_UNTIL;
  941. X   trig->rep  = NO_REP;
  942. X   trig->localomit = NO_WD;
  943. X   trig->skip = NO_SKIP;
  944. X   trig->once = NO_ONCE;
  945. X   trig->typ = NO_TYPE;
  946. X   tim->ttime = NO_TIME;
  947. X   tim->delta = NO_DELTA;
  948. X   tim->rep   = NO_REP;
  949. X
  950. X   while(1) {
  951. X      /* Read space-delimited string */
  952. X      r = ParseToken(s, TokBuffer);
  953. X      if (r) return r;
  954. X
  955. X      /* Figure out what we've got */
  956. X      FindToken(TokBuffer, &tok);
  957. X      switch(tok.type) {
  958. X     case T_WkDay:
  959. X        if (trig->wd & (1 << tok.val)) {
  960. X           Eprint("Weekday specified twice");
  961. X           return E_PARSE_ERR;
  962. X        }
  963. X        trig->wd |= (1 << tok.val);
  964. X        break;
  965. X
  966. X     case T_Month:
  967. X        if (trig->m != NO_MON) {
  968. X           Eprint("Month specified twice");
  969. X           return E_PARSE_ERR;
  970. X        }
  971. X        trig->m = tok.val;
  972. X        break;
  973. X
  974. X     case T_Skip:
  975. X        if (trig->skip != NO_SKIP) {
  976. X           Eprint("Only use one of BEFORE, AFTER or SKIP");
  977. X           return E_PARSE_ERR;
  978. X        }
  979. X        trig->skip = tok.val;
  980. X        break;
  981. X
  982. X     case T_At:
  983. X        r=ParseTimeTrig(s, tim);
  984. X        if (r) return r;
  985. X        break;
  986. X
  987. X     case T_RemType:
  988. X        trig->typ = tok.val;
  989. X        if (s->isnested) {
  990. X           Eprint("Can't nest '%s' in expression", TokBuffer);
  991. X           return E_PARSE_ERR;
  992. X            }
  993. X        return OK;
  994. X
  995. X     case T_Until:
  996. X        r=ParseUntil(s, trig);
  997. X        if (r) return r;
  998. X        break;
  999. X
  1000. X     case T_Year:
  1001. X        if (trig->y != NO_YR) {
  1002. X           Eprint("Year specified twice");
  1003. X           return E_PARSE_ERR;
  1004. X        }
  1005. X        trig->y = tok.val;
  1006. X        break;
  1007. X
  1008. X     case T_Day:
  1009. X        if (trig->d != NO_DAY) {
  1010. X           Eprint("Day of month specified twice");
  1011. X           return E_PARSE_ERR;
  1012. X        }
  1013. X        trig->d = tok.val;
  1014. X        break;
  1015. X
  1016. X     case T_Rep:
  1017. X        if (trig->rep != NO_REP) {
  1018. X           Eprint("Repeat value specified twice");
  1019. X           return E_PARSE_ERR;
  1020. X        }
  1021. X        trig->rep = tok.val;
  1022. X        break;
  1023. X
  1024. X     case T_Delta:
  1025. X        if (trig->delta != NO_DELTA) {
  1026. X           Eprint("Delta value specified twice");
  1027. X           return E_PARSE_ERR;
  1028. X        }
  1029. X        trig->delta = tok.val;
  1030. X        break;
  1031. X
  1032. X     case T_Back:
  1033. X        if (trig->back != NO_BACK) {
  1034. X           Eprint("Back value specified twice");
  1035. X           return E_PARSE_ERR;
  1036. X        }
  1037. X        trig->back = tok.val;
  1038. X        break;
  1039. X
  1040. X     case T_Once:
  1041. X        if (trig->once != NO_ONCE) {
  1042. X           Eprint("ONCE specified twice.  (Hah.)");
  1043. X           return E_PARSE_ERR;
  1044. X        }
  1045. X        trig->once = ONCE_ONCE;
  1046. X        break;
  1047. X
  1048. X     case T_Omit:
  1049. X        r = ParseLocalOmit(s, trig);
  1050. X        if (r) return r;
  1051. X        break;
  1052. X
  1053. X     case T_Empty:
  1054. X        return OK;
  1055. X
  1056. X     default:
  1057. X        Eprint("Unknown token in REM command: %s", TokBuffer);
  1058. X        return E_PARSE_ERR;
  1059. X      }
  1060. X   }
  1061. X}
  1062. X
  1063. X/***************************************************************/
  1064. X/*                                                             */
  1065. X/*  ParseTimeTrig - parse the AT part of a timed reminder      */
  1066. X/*                                                             */
  1067. X/***************************************************************/
  1068. X#ifdef HAVE_PROTOS
  1069. XPRIVATE int ParseTimeTrig(ParsePtr s, TimeTrig *tim)
  1070. X#else
  1071. Xstatic int ParseTimeTrig(s, tim)
  1072. XParsePtr s;
  1073. XTimeTrig *tim;
  1074. X#endif
  1075. X{
  1076. X   Token tok;
  1077. X   int r;
  1078. X
  1079. X   while(1) {
  1080. X      r = ParseToken(s, TokBuffer);
  1081. X      if (r) return r;
  1082. X      FindToken(TokBuffer, &tok);
  1083. X      switch(tok.type) {
  1084. X     case T_Time:
  1085. X        tim->ttime = tok.val;
  1086. X            break;
  1087. X
  1088. X     case T_Delta:
  1089. X        tim->delta = (tok.val > 0) ? tok.val : -tok.val;
  1090. X        break;
  1091. X
  1092. X     case T_Rep:
  1093. X        tim->rep = tok.val;
  1094. X        break;
  1095. X
  1096. X         default:
  1097. X            if (tim->ttime == NO_TIME) {
  1098. X               Eprint("Expecting time after AT.");
  1099. X               return E_PARSE_ERR;
  1100. X        }
  1101. X/* Save in global variable */
  1102. X        LastTriggerTime = tim->ttime;
  1103. X        PushToken(TokBuffer);
  1104. X            return OK;
  1105. X      }
  1106. X   }
  1107. X}
  1108. X
  1109. X/***************************************************************/
  1110. X/*                                                             */
  1111. X/*  ParseLocalOmit - parse the local OMIT portion of a         */
  1112. X/*  reminder.                                                  */
  1113. X/*                                                             */
  1114. X/***************************************************************/
  1115. X#ifdef HAVE_PROTOS
  1116. XPRIVATE int ParseLocalOmit(ParsePtr s, Trigger *t)
  1117. X#else
  1118. Xstatic int ParseLocalOmit(s, t)
  1119. XParsePtr s;
  1120. XTrigger *t;
  1121. X#endif
  1122. X{
  1123. X   Token tok;
  1124. X   int r;
  1125. X
  1126. X   while(1) {
  1127. X      r = ParseToken(s, TokBuffer);
  1128. X      if (r) return r;
  1129. X      FindToken(TokBuffer, &tok);
  1130. X      switch(tok.type) {
  1131. X     case T_WkDay:
  1132. X        t->localomit |= (1 << tok.val);
  1133. X        break;
  1134. X
  1135. X     default:
  1136. X        PushToken(TokBuffer);
  1137. X        return OK;
  1138. X      }
  1139. X   }
  1140. X}
  1141. X
  1142. X/***************************************************************/
  1143. X/*                                                             */
  1144. X/*  ParseUntil - parse the UNTIL portion of a reminder         */
  1145. X/*                                                             */
  1146. X/***************************************************************/
  1147. X#ifdef HAVE_PROTOS
  1148. XPRIVATE int ParseUntil(ParsePtr s, Trigger *t)
  1149. X#else
  1150. Xstatic int ParseUntil(s, t)
  1151. XParsePtr s;
  1152. XTrigger *t;
  1153. X#endif
  1154. X{
  1155. X   int y = NO_YR,
  1156. X       m = NO_MON,
  1157. X       d = NO_DAY;
  1158. X
  1159. X   Token tok;
  1160. X   int r;
  1161. X
  1162. X   if (t->until != NO_UNTIL) {
  1163. X      Eprint("Cannot specify UNTIL twice");
  1164. X      return E_PARSE_ERR;
  1165. X   }
  1166. X
  1167. X   while(1) {
  1168. X      r = ParseToken(s, TokBuffer);
  1169. X      if (r) return r;
  1170. X      FindToken(TokBuffer, &tok);
  1171. X      switch(tok.type) {
  1172. X     case T_Year:
  1173. X        if (y != NO_YR) {
  1174. X           Eprint("Year specified twice in UNTIL");
  1175. X           return E_PARSE_ERR;
  1176. X        }
  1177. X        y = tok.val;
  1178. X        break;
  1179. X
  1180. X     case T_Month:
  1181. X        if (m != NO_MON) {
  1182. X           Eprint("Month specified twice in UNTIL");
  1183. X           return E_PARSE_ERR;
  1184. X        }
  1185. X        m = tok.val;
  1186. X        break;
  1187. X
  1188. X     case T_Day:
  1189. X        if (d != NO_DAY) {
  1190. X           Eprint("Day specified twice in UNTIL");
  1191. X           return E_PARSE_ERR;
  1192. X        }
  1193. X        d = tok.val;
  1194. X        break;
  1195. X
  1196. X     default:
  1197. X        if (y == NO_YR || m == NO_MON || d == NO_DAY) {
  1198. X           Eprint("Incompletely specified UNTIL");
  1199. X           return E_PARSE_ERR;
  1200. X        }
  1201. X        t->until = Julian(y, m, d);
  1202. X        PushToken(TokBuffer);
  1203. X        return OK;
  1204. X      }
  1205. X   }
  1206. X}
  1207. X
  1208. X/***************************************************************/
  1209. X/*                                                             */
  1210. X/*  TriggerReminder                                            */
  1211. X/*                                                             */
  1212. X/*  Trigger the reminder if it's a RUN or MSG type.            */
  1213. X/*                                                             */
  1214. X/***************************************************************/
  1215. X#ifdef HAVE_PROTOS
  1216. XPUBLIC int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
  1217. X#else
  1218. Xint TriggerReminder(p, t, tim, jul)
  1219. XParsePtr p;
  1220. XTrigger *t;
  1221. XTimeTrig *tim;
  1222. Xint jul;
  1223. X#endif
  1224. X{
  1225. X   int r, y, m, d;
  1226. X   Trigger tempTrig;
  1227. X   TimeTrig tempTime;
  1228. X   Parser tempP;
  1229. X
  1230. X   if (t->typ == RUN_TYPE && RunDisabled) return E_RUN_DISABLED;
  1231. X   if (t->typ == CAL_TYPE) return OK;
  1232. X
  1233. X/* If we're in Daemon mode, do nothing over here... */
  1234. X
  1235. X/* If it's a MSG-type reminder, issue the banner. */
  1236. X   if (t->typ == MSG_TYPE && !NumTriggered && !NextMode) {
  1237. X      CreateParser(Banner, &tempP);
  1238. X      tempP.allownested = 0;
  1239. X      tempTrig.typ = MSG_TYPE;
  1240. X      tempTime.ttime = SystemTime()/60;
  1241. X      if (!(r=DoSubst(&tempP, SubstBuffer, &tempTrig,
  1242. X           &tempTime, JulianToday, NORMAL_MODE)))
  1243. X         if (*SubstBuffer) printf("%s\n", SubstBuffer);
  1244. X      DestroyParser(&tempP);
  1245. X   }
  1246. X
  1247. X/* If it's NextMode, process as a CAL-type entry, and issue simple-calendar
  1248. X   format. */
  1249. X   if (NextMode) {
  1250. X      if (r=DoSubst(p, SubstBuffer, t, tim, jul, CAL_MODE)) return r;
  1251. X      if (!*SubstBuffer) return OK;
  1252. X      FromJulian(jul, &y, &m, &d);
  1253. X      printf("%04d/%02d/%02d %s%s\n", y, m+1, d,
  1254. X                                      SimpleTime(tim->ttime, NULL),
  1255. X                                      SubstBuffer);
  1256. X      return OK;
  1257. X   }
  1258. X
  1259. X/* Put the substituted string into the SubstBuffer */
  1260. X   if (r=DoSubst(p, SubstBuffer, t, tim, jul, NORMAL_MODE)) return r;
  1261. X
  1262. X/* Go for it... */
  1263. X   if (t->typ == MSG_TYPE) printf("%s\n", SubstBuffer);
  1264. X   else system(SubstBuffer);
  1265. X
  1266. X   NumTriggered++;
  1267. X   return OK;
  1268. X}
  1269. X
  1270. X/***************************************************************/
  1271. X/*                                                             */
  1272. X/*  ShouldTriggerReminder                                      */
  1273. X/*                                                             */
  1274. X/*  Return 1 if we should trigger a reminder, based on today's */
  1275. X/*  date and the trigger.  Return 0 if reminder should not be  */
  1276. X/*  triggered.                                                 */
  1277. X/*                                                             */
  1278. X/***************************************************************/
  1279. X#ifdef __TURBOC__
  1280. X#pragma argsused
  1281. X#endif
  1282. X#ifdef HAVE_PROTOS
  1283. XPUBLIC int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul)
  1284. X#else
  1285. Xint ShouldTriggerReminder(t, tim, jul)
  1286. XTrigger *t;
  1287. XTimeTrig *tim;
  1288. Xint jul;
  1289. X#endif
  1290. X{
  1291. X   int r;
  1292. X
  1293. X   /* Handle the ONCE modifier in the reminder. */
  1294. X   if (!IgnoreOnce && t->once !=NO_ONCE && FileAccessDate == JulianToday)
  1295. X      return 0;
  1296. X   
  1297. X   if (jul < JulianToday) return 0;
  1298. X
  1299. X   /* Don't trigger timed reminders if DontIssueAts is true, and if the
  1300. X      reminder is for today */
  1301. X
  1302. X#ifdef HAVE_QUEUED
  1303. X   if (jul == JulianToday && DontIssueAts && tim->ttime != NO_TIME) return 0;
  1304. X#endif
  1305. X
  1306. X   /* Don't trigger "old" timed reminders */
  1307. X/*** REMOVED...
  1308. X      if (jul == JulianToday &&
  1309. X       tim->ttime != NO_TIME &&
  1310. X       tim->ttime < SystemTime() / 60) return 0;
  1311. X *** ...UNTIL HERE */
  1312. X
  1313. X   /* If "infinite delta" option is chosen, always trigger future reminders */
  1314. X   if (InfiniteDelta || NextMode) return 1;
  1315. X
  1316. X   /* Move back by delta days, if any */
  1317. X   if (t->delta != NO_DELTA) {
  1318. X      if (t->delta < 0)
  1319. X     jul = jul + t->delta;
  1320. X      else {
  1321. X     r = t->delta;
  1322. X     while(r && jul > JulianToday) {
  1323. X        jul--;
  1324. X        if (!IsOmitted(jul, t->localomit)) r--;
  1325. X     }
  1326. X      }
  1327. X   }
  1328. X
  1329. X   /* Should we trigger the reminder? */
  1330. X   return (jul <= JulianToday);
  1331. X}
  1332. X
  1333. X/***************************************************************/
  1334. X/*                                                             */
  1335. X/*  DoSatRemind                                                */
  1336. X/*                                                             */
  1337. X/*  Do the "satisfying..." remind calculation.                 */
  1338. X/*                                                             */
  1339. X/***************************************************************/
  1340. X#ifdef __TURBOC__
  1341. X#pragma argsused
  1342. X#endif
  1343. X#ifdef HAVE_PROTOS
  1344. XPUBLIC int DoSatRemind(Trigger *trig, TimeTrig *tim, ParsePtr p)
  1345. X#else
  1346. Xint DoSatRemind(trig, tim, p)
  1347. XTrigger *trig;
  1348. XTimeTrig *tim;
  1349. XParsePtr p;
  1350. X#endif
  1351. X{
  1352. X   int iter, jul, r;
  1353. X   Value v;
  1354. X   char *s;
  1355. X
  1356. X   iter = 0;
  1357. X   jul = JulianToday;
  1358. X   while (iter++ < MaxSatIter) {
  1359. X      jul = ComputeTrigger(jul, trig, &r);
  1360. X      if (r) {
  1361. X         if (r == E_CANT_TRIG) return OK; else return r;
  1362. X      }
  1363. X      s = p->pos;
  1364. X      r = EvaluateExpr(p, &v);
  1365. X      p->pos = s;
  1366. X      if (r) return r;
  1367. X      if (v.type != INT_TYPE && v.type != STR_TYPE) return E_BAD_TYPE;
  1368. X      if (v.type == INT_TYPE && v.v.val) return OK;
  1369. X      if (v.type == STR_TYPE && *v.v.str) return OK;
  1370. X      jul++;
  1371. X   }
  1372. X   LastTrigValid = 0;
  1373. X   return OK;
  1374. X}
  1375. X
  1376. SHAR_EOF
  1377. $TOUCH -am 1109141292 dorem.c &&
  1378. chmod 0600 dorem.c ||
  1379. echo "restore of dorem.c failed"
  1380. set `wc -c dorem.c`;Wc_c=$1
  1381. if test "$Wc_c" != "14531"; then
  1382.     echo original size 14531, current size $Wc_c
  1383. fi
  1384. fi
  1385. echo "End of part 2, continue with part 3"
  1386. exit 0
  1387.  
  1388. exit 0 # Just in case...
  1389.