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