home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #26 / NN_1992_26.iso / spool / comp / sources / misc / 4064 < prev    next >
Encoding:
Text File  |  1992-11-09  |  39.2 KB  |  1,396 lines

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