home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Divers / remind-03.00.19.tgz / remind-03.00.19.tar / remind-03.00.19 / src / dosubst.c < prev    next >
C/C++ Source or Header  |  1998-03-04  |  14KB  |  693 lines

  1. /***************************************************************/
  2. /*                                                             */
  3. /*  DOSUBST.C                                                  */
  4. /*                                                             */
  5. /*  This performs all the "%" substitution functions when      */
  6. /*  reminders are triggered.                                   */
  7. /*                                                             */
  8. /*  This file is part of REMIND.                               */
  9. /*  Copyright (C) 1992-1998 by David F. Skoll                  */
  10. /*                                                             */
  11. /***************************************************************/
  12.  
  13. #include "config.h"
  14. static char const RCSID[] = "$Id: dosubst.c,v 1.8 1998/03/04 18:13:26 dfs Exp $";
  15.  
  16. #define L_IN_DOSUBST
  17. #include <stdio.h>
  18. #include <string.h>
  19. #include <ctype.h>
  20.  
  21. #ifdef HAVE_STDLIB_H
  22. #include <stdlib.h>
  23. #endif
  24.  
  25. #ifdef HAVE_MALLOC_H
  26. #include <malloc.h>
  27. #endif
  28.  
  29. #include "globals.h"
  30. #include "err.h"
  31. #include "types.h"
  32. #include "protos.h"
  33.  
  34. #define UPPER(c) (islower(c) ? toupper(c) : c)
  35. #define ABS(x) ( (x) < 0 ? -(x) : (x) )
  36. #ifndef NL
  37. #define NL "\n"
  38. #endif
  39.  
  40. static char TODAY[] = L_TODAY;
  41. static char TOMORROW[] = L_TOMORROW;
  42.  
  43. #define SHIP_OUT(s) if(DBufPuts(dbuf, s) != OK) return E_NO_MEM
  44.  
  45. /***************************************************************/
  46. /*                                                             */
  47. /*  DoSubst                                                    */
  48. /*                                                             */
  49. /*  Process the % escapes in the reminder.  If                 */
  50. /*  mode==NORMAL_MODE, ignore the %" sequence.  If             */
  51. /*  mode==CAL_MODE, process the %" sequence.                   */
  52. /*                                                             */
  53. /***************************************************************/
  54. #ifdef HAVE_PROTOS
  55. PUBLIC int DoSubst(ParsePtr p, DynamicBuffer *dbuf, Trigger *t, TimeTrig *tt, int jul, int mode)
  56. #else
  57. int DoSubst(p, dbuf, t, tt, jul, mode)
  58. ParsePtr p;
  59. DynamicBuffer *dbuf;
  60. Trigger *t;
  61. TimeTrig *tt;
  62. int jul, mode;
  63. #endif
  64. {
  65.     int diff = jul - JulianToday;
  66.     int curtime = SystemTime(0) / 60;
  67.     int err, done;
  68.     int c;
  69.     int d, m, y;
  70.     int tim = tt->ttime;
  71.     int h, min, hh, ch, cmin, chh;
  72.     char *pm, *cpm;
  73.     int tdiff, adiff, mdiff, hdiff;
  74.     char *mplu, *hplu, *when, *plu;
  75.     int has_quote = 0;
  76.     char *ss, *os;
  77.     char s[256];
  78.     int origLen = DBufLen(dbuf);
  79.  
  80.     FromJulian(jul, &y, &m, &d);
  81.  
  82.     if (tim == NO_TIME) tim = curtime;
  83.     tdiff = tim - curtime;
  84.     adiff = ABS(tdiff);
  85.     mdiff = adiff % 60;
  86.     hdiff = adiff / 60;
  87.  
  88. #ifdef    L_MPLU_OVER
  89.     L_MPLU_OVER
  90. #else /* L_MPLU_OVER */
  91.     mplu = (mdiff == 1 ? "" : L_MPLU);
  92. #endif /* L_MPLU_OVER */
  93.  
  94. #ifdef L_HPLU_OVER 
  95.     L_HPLU_OVER
  96. #else /* L_HPLU_OVER */
  97.     hplu = (hdiff == 1 ? "" : L_HPLU);
  98. #endif /* L_HPLU_OVER */
  99.  
  100.     when = (tdiff < 0 ? L_AGO : L_FROMNOW);
  101.    
  102.     h = tim / 60;
  103.     min = tim % 60;
  104.  
  105. #ifdef L_AMPM_OVERRIDE
  106.     L_AMPM_OVERRIDE (pm, h)
  107. #else
  108.     pm = (h < 12) ? L_AM : L_PM;
  109. #endif
  110.     hh = (h == 12) ? 12 : h % 12;
  111.    
  112.     ch = curtime / 60;
  113.     cmin = curtime % 60;
  114.  
  115. #ifdef L_AMPM_OVERRIDE
  116.     L_AMPM_OVERRIDE (cpm, ch)
  117. #else
  118.     cpm = (ch < 12) ? L_AM : L_PM;
  119. #endif
  120.     chh = (ch == 12) ? 12 : ch % 12;
  121.  
  122. #ifdef L_ORDINAL_OVERRIDE
  123.     L_ORDINAL_OVERRIDE
  124. #else
  125.     switch(d) {
  126.     case 1:
  127.     case 21:
  128.     case 31: plu = "st"; break;
  129.     
  130.     case 2:
  131.     case 22: plu = "nd"; break;
  132.       
  133.     case 3:
  134.     case 23: plu = "rd"; break;
  135.       
  136.     default: plu = "th"; break;
  137.     }
  138. #endif      
  139.    
  140.     while(1) {
  141.     c = ParseChar(p, &err, 0);
  142.     if (err) {
  143.         DBufFree(dbuf);
  144.         return err;
  145.     }
  146.     if (c == '\n') continue;
  147.     if (!c) {
  148.         if (mode != CAL_MODE && t->typ != RUN_TYPE && !MsgCommand) {
  149.         if (DBufPutc(dbuf, '\n') != OK) return E_NO_MEM;
  150.         }
  151.         break;
  152.     }
  153.     if (c != '%') {
  154.         if (DBufPutc(dbuf, c) != OK) return E_NO_MEM;
  155.         continue;
  156.     }
  157.     s[0] = 0;
  158.     c = ParseChar(p, &err, 0);
  159.     if (err) {
  160.         DBufFree(dbuf);
  161.         return err;
  162.     }
  163.     if (!c) {
  164.         break;
  165.     }
  166.     done = 0;
  167.     if (diff <= 1) {
  168.         switch(UPPER(c)) {
  169. #ifndef L_NOTOMORROW_A
  170.             case 'A':
  171. #endif
  172. #ifndef L_NOTOMORROW_B
  173.             case 'B':
  174. #endif
  175. #ifndef L_NOTOMORROW_C
  176.         case 'C':
  177. #endif
  178. #ifndef L_NOTOMORROW_E
  179.         case 'E':
  180. #endif
  181. #ifndef L_NOTOMORROW_F
  182.         case 'F':
  183. #endif
  184. #ifndef L_NOTOMORROW_G
  185.         case 'G':
  186. #endif
  187. #ifndef L_NOTOMORROW_H
  188.         case 'H':
  189. #endif
  190. #ifndef L_NOTOMORROW_I
  191.         case 'I':
  192. #endif
  193. #ifndef L_NOTOMORROW_J
  194.         case 'J':
  195. #endif
  196. #ifndef L_NOTOMORROW_K
  197.         case 'K':
  198. #endif
  199. #ifndef L_NOTOMORROW_L
  200.         case 'L':
  201. #endif
  202. #ifndef L_NOTOMORROW_U
  203.         case 'U':
  204. #endif
  205. #ifndef L_NOTOMORROW_V
  206.         case 'V':
  207. #endif
  208.         sprintf(s, "%s", (diff ? TOMORROW : TODAY));
  209.         SHIP_OUT(s);
  210.         done = 1;
  211.         break;
  212.              
  213.             default: done = 0;
  214.         }
  215.     }
  216.      
  217.     if (!done) switch(UPPER(c)) {
  218.     case 'A':
  219. #ifdef L_A_OVER
  220.         L_A_OVER
  221. #else     
  222.         sprintf(s, "%s %s, %d %s, %d", L_ON, DayName[jul%7], d,
  223.             MonthName[m], y);
  224. #endif
  225.             SHIP_OUT(s);
  226.         break;
  227.            
  228.     case 'B':
  229. #ifdef L_B_OVER
  230.         L_B_OVER
  231. #else     
  232.         sprintf(s, L_INXDAYS, diff);
  233. #endif
  234.         SHIP_OUT(s);
  235.             break;
  236.            
  237.     case 'C':
  238. #ifdef L_C_OVER
  239.         L_C_OVER
  240. #else     
  241.         sprintf(s, "%s %s", L_ON, DayName[jul%7]);
  242. #endif
  243.         SHIP_OUT(s);
  244.         break;
  245.  
  246.     case 'D':
  247. #ifdef L_D_OVER
  248.         L_D_OVER
  249. #else     
  250.         sprintf(s, "%d", d);
  251. #endif
  252.         SHIP_OUT(s);
  253.         break;
  254.  
  255.     case 'E':
  256. #ifdef L_E_OVER
  257.         L_E_OVER
  258. #else     
  259.         sprintf(s, "%s %02d%c%02d%c%04d", L_ON, d, DATESEP,
  260.             m+1, DATESEP, y);
  261. #endif
  262.         SHIP_OUT(s);
  263.         break;
  264.  
  265.     case 'F':
  266. #ifdef L_F_OVER
  267.         L_F_OVER
  268. #else     
  269.         sprintf(s, "%s %02d%c%02d%c%04d", L_ON, m+1, DATESEP, d, DATESEP, y);
  270. #endif
  271.         SHIP_OUT(s);
  272.         break;
  273.  
  274.     case 'G':
  275. #ifdef L_G_OVER
  276.         L_G_OVER
  277. #else     
  278.         sprintf(s, "%s %s, %d %s", L_ON, DayName[jul%7], d, MonthName[m]);
  279. #endif
  280.         SHIP_OUT(s);
  281.         break;
  282.  
  283.     case 'H':
  284. #ifdef L_H_OVER
  285.         L_H_OVER
  286. #else     
  287.         sprintf(s, "%s %02d%c%02d", L_ON, d, DATESEP, m+1);
  288. #endif
  289.         SHIP_OUT(s);
  290.         break;
  291.  
  292.     case 'I':
  293. #ifdef L_I_OVER
  294.         L_I_OVER
  295. #else     
  296.         sprintf(s, "%s %02d%c%02d", L_ON, m+1, DATESEP, d);
  297. #endif
  298.         SHIP_OUT(s);
  299.         break;
  300.  
  301.     case 'J':
  302. #ifdef L_J_OVER
  303.         L_J_OVER
  304. #else
  305.         sprintf(s, "%s %s, %s %d%s, %d", L_ON, DayName[jul%7],
  306.             MonthName[m], d, plu, y);
  307. #endif
  308.         SHIP_OUT(s);
  309.         break;
  310.  
  311.     case 'K':
  312. #ifdef L_K_OVER
  313.         L_K_OVER
  314. #else
  315.         sprintf(s, "%s %s, %s %d%s", L_ON, DayName[jul%7],
  316.             MonthName[m], d, plu);
  317. #endif
  318.         SHIP_OUT(s);
  319.         break;
  320.  
  321.     case 'L':
  322. #ifdef L_L_OVER
  323.         L_L_OVER
  324. #else
  325.         sprintf(s, "%s %04d%c%02d%c%02d", L_ON, y, DATESEP, m+1, DATESEP, d);
  326. #endif
  327.         SHIP_OUT(s);
  328.         break;
  329.  
  330.     case 'M':
  331. #ifdef L_M_OVER
  332.         L_M_OVER
  333. #else
  334.         sprintf(s, "%s", MonthName[m]);
  335. #endif
  336.         SHIP_OUT(s);
  337.         break;
  338.  
  339.     case 'N':
  340. #ifdef L_N_OVER
  341.         L_N_OVER
  342. #else
  343.         sprintf(s, "%d", m+1);
  344. #endif
  345.         SHIP_OUT(s);
  346.         break;
  347.  
  348.     case 'O':
  349. #ifdef L_O_OVER
  350.         L_O_OVER
  351. #else
  352.         if (RealToday == JulianToday) sprintf(s, " (%s)", L_TODAY);
  353.         else *s = 0;
  354. #endif
  355.         SHIP_OUT(s);
  356.         break;
  357.  
  358.     case 'P':
  359. #ifdef L_P_OVER
  360.         L_P_OVER
  361. #else
  362.         sprintf(s, "%s", (diff == 1 ? "" : L_PLURAL));
  363. #endif
  364.         SHIP_OUT(s);
  365.         break;
  366.  
  367.     case 'Q':
  368. #ifdef L_Q_OVER
  369.         L_Q_OVER
  370. #else
  371.         sprintf(s, "%s", (diff == 1 ? "'s" : "s'"));
  372. #endif
  373.         SHIP_OUT(s);
  374.         break;
  375.  
  376.     case 'R':
  377. #ifdef L_R_OVER
  378.         L_R_OVER
  379. #else
  380.         sprintf(s, "%02d", d);
  381. #endif
  382.         SHIP_OUT(s);
  383.         break;
  384.  
  385.     case 'S':
  386. #ifdef L_S_OVER
  387.         L_S_OVER
  388. #else
  389.         sprintf(s, "%s", plu);
  390. #endif
  391.         SHIP_OUT(s);
  392.         break;
  393.  
  394.     case 'T':
  395. #ifdef L_T_OVER
  396.         L_T_OVER
  397. #else
  398.         sprintf(s, "%02d", m+1);
  399. #endif
  400.         SHIP_OUT(s);
  401.         break;
  402.  
  403.     case 'U':
  404. #ifdef L_U_OVER
  405.         L_U_OVER
  406. #else
  407.         sprintf(s, "%s %s, %d%s %s, %d", L_ON, DayName[jul%7], d,
  408.             plu, MonthName[m], y);
  409. #endif
  410.         SHIP_OUT(s);
  411.         break;
  412.  
  413.     case 'V':
  414. #ifdef L_V_OVER
  415.         L_V_OVER
  416. #else
  417.         sprintf(s, "%s %s, %d%s %s", L_ON, DayName[jul%7], d, plu,
  418.             MonthName[m]);
  419. #endif
  420.         SHIP_OUT(s);
  421.         break;
  422.  
  423.     case 'W':
  424. #ifdef L_W_OVER
  425.         L_W_OVER
  426. #else
  427.         sprintf(s, "%s", DayName[jul%7]);
  428. #endif
  429.         SHIP_OUT(s);
  430.         break;
  431.  
  432.     case 'X':
  433. #ifdef L_X_OVER
  434.         L_X_OVER
  435. #else
  436.         sprintf(s, "%d", diff);
  437. #endif
  438.         SHIP_OUT(s);
  439.         break;
  440.  
  441.     case 'Y':
  442. #ifdef L_Y_OVER
  443.         L_Y_OVER
  444. #else
  445.         sprintf(s, "%d", y);
  446. #endif
  447.         SHIP_OUT(s);
  448.         break;
  449.  
  450.     case 'Z':
  451. #ifdef L_Z_OVER
  452.         L_Z_OVER
  453. #else
  454.         sprintf(s, "%d", y % 100);
  455. #endif
  456.         SHIP_OUT(s);
  457.         break;
  458.  
  459.     case '1':
  460. #ifdef L_1_OVER
  461.         L_1_OVER
  462. #else
  463.         if (tdiff == 0) 
  464.         sprintf(s, "%s", L_NOW);
  465.         else if (hdiff == 0) 
  466.         sprintf(s, "%d %s%s %s", mdiff, L_MINUTE, mplu, when);
  467.         else if (mdiff == 0)
  468.         sprintf(s, "%d %s%s %s", hdiff, L_HOUR, hplu, when);
  469.         else
  470.         sprintf(s, "%d %s%s %s %d %s%s %s", hdiff, L_HOUR, hplu,
  471.             L_AND, mdiff, L_MINUTE, mplu, when);
  472. #endif
  473.         SHIP_OUT(s);
  474.         break;
  475.  
  476.     case '2':
  477. #ifdef L_2_OVER
  478.         L_2_OVER
  479. #else
  480.         sprintf(s, "%s %d%c%02d%s", L_AT, hh, TIMESEP, min, pm);
  481. #endif
  482.         SHIP_OUT(s);
  483.         break;
  484.  
  485.     case '3':
  486. #ifdef L_3_OVER
  487.         L_3_OVER
  488. #else
  489.  
  490.         sprintf(s, "%s %02d%c%02d", L_AT, h, TIMESEP, min);
  491. #endif
  492.         SHIP_OUT(s);
  493.         break;
  494.  
  495.     case '4':
  496. #ifdef L_4_OVER
  497.         L_4_OVER
  498. #else
  499.         sprintf(s, "%d", tdiff);
  500. #endif
  501.         SHIP_OUT(s);
  502.         break;
  503.  
  504.     case '5':
  505. #ifdef L_5_OVER
  506.         L_5_OVER
  507. #else
  508.         sprintf(s, "%d", adiff);
  509. #endif
  510.         SHIP_OUT(s);
  511.         break;
  512.  
  513.     case '6':
  514. #ifdef L_6_OVER
  515.         L_6_OVER
  516. #else
  517.         sprintf(s, "%s", when);
  518. #endif
  519.         SHIP_OUT(s);
  520.         break;
  521.  
  522.     case '7':
  523. #ifdef L_7_OVER
  524.         L_7_OVER
  525. #else
  526.         sprintf(s, "%d", hdiff);
  527. #endif
  528.         SHIP_OUT(s);
  529.         break;
  530.  
  531.     case '8':
  532. #ifdef L_8_OVER
  533.         L_8_OVER
  534. #else
  535.         sprintf(s, "%d", mdiff);
  536. #endif
  537.         SHIP_OUT(s);
  538.         break;
  539.  
  540.     case '9':
  541. #ifdef L_9_OVER
  542.         L_9_OVER
  543. #else
  544.         sprintf(s, "%s", mplu);
  545. #endif
  546.         SHIP_OUT(s);
  547.         break;
  548.  
  549.     case '0':
  550. #ifdef L_0_OVER
  551.         L_0_OVER
  552. #else
  553.         sprintf(s, "%s", hplu);
  554. #endif
  555.         SHIP_OUT(s);
  556.         break;
  557.  
  558.     case '!':
  559. #ifdef L_BANG_OVER
  560.         L_BANG_OVER
  561. #else
  562.         sprintf(s, "%s", (tdiff >= 0 ? L_IS : L_WAS));
  563. #endif
  564.         SHIP_OUT(s);
  565.         break;
  566.  
  567.     case '@':
  568. #ifdef L_AT_OVER
  569.         L_AT_OVER
  570. #else
  571.         sprintf(s, "%d%c%02d%s", chh, TIMESEP, cmin, cpm);
  572. #endif
  573.         SHIP_OUT(s);
  574.         break;
  575.  
  576.     case '#':
  577. #ifdef L_HASH_OVER
  578.         L_HASH_OVER
  579. #else
  580.         sprintf(s, "%02d%c%02d", ch, TIMESEP, cmin);
  581. #endif
  582.         SHIP_OUT(s);
  583.         break;
  584.  
  585.     case '_': 
  586.             if (mode != CAL_MODE && !MsgCommand)
  587.         sprintf(s, "%s", NL);
  588.             else
  589.         sprintf(s, " ");
  590.         SHIP_OUT(s);
  591.         break;
  592.  
  593.     case QUOTE_MARKER:
  594.         /* Swallow any QUOTE_MARKERs which may somehow creep in... */
  595.         break;
  596.  
  597.     case '"':
  598.         if (DBufPutc(dbuf, QUOTE_MARKER) != OK) return E_NO_MEM;
  599.         has_quote = 1;
  600.         break;
  601.  
  602.     default:
  603.         if (DBufPutc(dbuf, c) != OK) return E_NO_MEM;
  604.     }
  605.     if (isupper(c)) {
  606.         os = DBufValue(dbuf) - strlen(s);
  607.         *os = UPPER(*os);
  608.     }
  609.     }
  610.  
  611. /* We're outside the big while loop.  The only way to get here is for c to
  612.    be null.  Now we go through and delete %" sequences, if it's the
  613.    NORMAL_MODE, or retain only things within a %" sequence if it's the
  614.    CAL_MODE. */
  615.  
  616. /* If there are NO quotes, then:  If CAL_MODE && RUN_TYPE, we don't want the
  617.    reminder in the calendar.  Zero the output buffer and quit. */
  618.     if (!has_quote) {
  619.     if (mode == CAL_MODE && t->typ == RUN_TYPE) {
  620.         *DBufValue(dbuf) = 0;
  621.         dbuf->len = 0;
  622.     }
  623.     return OK;
  624.     }
  625.  
  626. /* There ARE quotes.  If in CAL_MODE, delete everything before first quote
  627.    and after second quote.  If in NORMAL_MODE, delete the %" sequences. */
  628.  
  629.     ss = DBufValue(dbuf) + origLen;
  630.     os = ss;
  631.     if (mode == NORMAL_MODE) {
  632.     while (*ss) {
  633.         if (*ss != QUOTE_MARKER) *os++ = *ss;
  634.         ss++;
  635.     }
  636.     *os = 0;
  637.     } else {
  638. /* Skip past the quote marker */
  639.     while (*ss && (*ss != QUOTE_MARKER)) ss++;
  640.  
  641. /* Security check... actually, *s must == QUOTE_MARKER at this point, but
  642.    it doesn't hurt to make it a bit robust. */
  643.     if (*ss) ss++;
  644.  
  645. /* Copy the output until the next QUOTE_MARKER */
  646.     while (*ss && (*ss != QUOTE_MARKER)) *os++ = *ss++;
  647.     *os = 0;
  648.     }
  649.  
  650.     /* Violating encapsulation here!!!! */
  651.     dbuf->len = strlen(dbuf->buffer);
  652.  
  653.     return OK;
  654. }
  655.    
  656.  
  657. /***************************************************************/
  658. /*                                                             */
  659. /*  DoSubstFromString                                          */
  660. /*                                                             */
  661. /*  DoSubst consumes input from a parser.  This function       */
  662. /*  consumes characters from a string.  It also provides       */
  663. /*  default triggers and a mode of NORMAL_MODE.                */
  664. /*                                                             */
  665. /***************************************************************/
  666. #ifdef HAVE_PROTOS
  667. PUBLIC int DoSubstFromString(char *source, DynamicBuffer *dbuf,
  668.                  int jul, int tim)
  669. #else
  670. int DoSubstFromString(source, dbuf, jul, tim)
  671. char *source;
  672. DynamicBuffer *dbuf;
  673. int jul;
  674. int tim;
  675. #endif
  676. {
  677.     Trigger tempTrig;
  678.     TimeTrig tempTime;
  679.     Parser tempP;
  680.     int r;
  681.  
  682.     if (jul == NO_DATE) jul=JulianToday;
  683.     if (tim == NO_TIME) tim=SystemTime(0)/60;
  684.     CreateParser(source, &tempP);
  685.     tempP.allownested = 0;
  686.     tempTrig.typ = MSG_TYPE;
  687.     tempTime.ttime = tim;
  688.    
  689.     r = DoSubst(&tempP, dbuf, &tempTrig, &tempTime, jul, NORMAL_MODE);
  690.     DestroyParser(&tempP);
  691.     return r;
  692. }
  693.