home *** CD-ROM | disk | FTP | other *** search
/ Meeting Pearls 3 / Meeting_Pearls_III.iso / Pearls / dev / Libraries / Date / src / TextEngine.c < prev    next >
Encoding:
Text File  |  1995-07-31  |  41.5 KB  |  1,433 lines

  1. /* Copyright 1994-95 by Kai Hofmann
  2. ******* TextEngine/--history-- **********************************************
  3. *
  4. *   NAME
  5. *    history -- TextEngine is a module to help with text features
  6. *
  7. *   VERSION
  8. *    $VER: TextEngine 33.071 (28.07.95)
  9. *
  10. *   HISTORY
  11. *    22.02.1994 -    DateString() initiated.
  12. *    23.02.1994 -    Continuation of DateString(), making FormatStr() and
  13. *            copying max from old Datum.mod
  14. *            TimeString() Initiated.
  15. *    24.02.1994 -    Inserting %w command in DateString()
  16. *    04.03.1994 -    Starting translation into C
  17. *    21.01.1995 -    Continuation of translation to C,
  18. *            using new date library functions.
  19. *            Internal procedures: FormatStr(), strdel(),
  20. *            strinspos()
  21. *            TimeString() completly rewritten.
  22. *    04.02.1995 -    TimeString() completly rewritten.
  23. *            Bug fixes in strinspos().
  24. *    05.02.1995 -    DateString() completly rewritten.
  25. *            Eliminating FormatStr(), because there is no need for
  26. *            it, at the moment.
  27. *            TextEngine(), TextEngineJD() initiated.
  28. *    06.02.1995 -    Small changes in the autodocs
  29. *    16.02.1995 -    Fixing bugs found with C++
  30. *            Adding C++ overloading to TextEngine() &
  31. *            TextEngineJD()
  32. *    24.02.1995 -    Rita Reichl corrects my bad English - again.
  33. *    16.03.1995 -    Corrections and changes in the autodocs.
  34. *    22.03.1995 -    Introducing DiffDateString().
  35. *            Changing interface!!!
  36. *    02.04.1995 -    More C++ Support! Adding To-Do list.
  37. *            Adding NOTES to autodocs. Fixing some things.
  38. *            Introducing DiffTimeString(),StringString().
  39. *    07.04.1995 -    Fixing two bugs.
  40. *    17.04.1995 -    Integrating StringString()
  41. *    22.04.1995 -    Rita Reichl corrects my bad English - again.
  42. *    14.05.1995 -    New copyright notice!
  43. *    16.05.1995 -    Fixing two small bugs.
  44. *    19.05.1995 -    Rita corrects my English.
  45. *    24.05.1995 -    Changing interface of TextEngine(), TextEngineJD(),
  46. *            StringString()
  47. *            Rewriting StringString() to support additional insert
  48. *            strings.
  49. *    25.05.1995 -    Writing test program
  50. *    08.06.1995 -    Writing --compiling-- autodoc and some other small
  51. *            fixes in the autodocs.
  52. *    18.06.1995 -    Fixing C++ warnings/errors in textenginetest.c
  53. *    18.07.1995 -    Replacing abs() with labs() to avoid problems!
  54. *            Changing header from *strarr[] to **stararr
  55. *    28.07.1995 -    Shortening the year of the version-string to 95,
  56. *            because the Amiga 'version' command is buggy!
  57. *
  58. *****************************************************************************
  59. *
  60. *
  61. */
  62.  
  63. /*
  64. ******* TextEngine/--todo-- *************************************************
  65. *
  66. *   NAME
  67. *    todo -- This is the 'To-Do' list of the TextEngine module
  68. *
  69. *   TODO
  70. *    Find out about the Borland C++ 4.5 report about lines 140/150 in
  71. *    textenginetest.c 'suspicious pointer conversion' / 'could not match
  72. *    TextEngine()' :
  73. *    void TextEngine(char *const string, double jd, const Languages lang,
  74. *    double jd2, const char *const *const strarr);
  75. *                ----- (That's what the compiler does not like!)
  76. *
  77. *****************************************************************************
  78. *
  79. *
  80. */
  81.  
  82. /*
  83. ******* TextEngine/--compiling-- ********************************************
  84. *
  85. *   NAME
  86. *    compiling -- Specials for compiling the textengine.
  87. *
  88. *   COMPILING
  89. *    - You could compile this code as normal C or as C++
  90. *
  91. *****************************************************************************
  92. *
  93. *
  94. */
  95.  
  96. /*
  97. ******* TextEngine/--background-- *******************************************
  98. *
  99. *   NAME
  100. *    TextEngine -- This module helps you with text features (V33)
  101. *
  102. *   FUNCTION
  103. *    This module handles strings with different % commands
  104. *
  105. *   NOTES
  106. *    None.
  107. *
  108. *   COPYRIGHT
  109. *    This software is copyrighted 1994-95 by Kai Hofmann.
  110. *    All rights reserved!
  111. *
  112. *    - Permission for COMMERCIAL USE is only given by an extra available
  113. *      commercial license that must be validated!
  114. *      Contact me directly for this license, because it will be
  115. *      individually handed out per your needs!
  116. *
  117. *    - Permission is hereby granted, without written agreement and without
  118. *      license, to USE this software and its documentation for any
  119. *      NON-COMMERCIAL purpose, provided that the above copyright notice
  120. *      and the following paragraph appear in all copies of this software
  121. *      (Non-commercial includes Giftware and Shareware!).
  122. *
  123. *      You *must* include the following notice in your product and in your
  124. *      documentation:
  125. *      "This software uses the textengine that is copyrighted 1994-95 by
  126. *       Kai Hofmann"
  127. *
  128. *      You "must" send me a full version of your product at no cost
  129. *      including free updates!
  130. *      Extra money is welcome (For Bank Account see below - but *ONLY*
  131. *      send in DM to this Bank Account!).
  132. *
  133. *    - THERE IS *NO PERMISSION* GIVEN TO MODIFY THIS SOFTWARE!
  134. *
  135. *      If you need only parts of this software, you should not worry,
  136. *      because it's the job of the optimizer from your C compiler to
  137. *      include only the needed parts in your executable!
  138. *
  139. *   DISCLAIMER
  140. *    THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
  141. *    APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
  142. *    HOLDER AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT
  143. *    WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
  144. *    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  145. *    A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
  146. *    PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
  147. *    DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
  148. *    CORRECTION.
  149. *
  150. *    IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
  151. *    WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY REDISTRIBUTE
  152. *    THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
  153. *    INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
  154. *    ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING
  155. *    BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR
  156. *    LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM
  157. *    TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER
  158. *    PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
  159. *
  160. *    THE AUTHOR HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
  161. *    UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  162. *
  163. *   DISTRIBUTION
  164. *    Permission is hereby granted, without written agreement and without
  165. *    license or royalty fees, to copy and distribute this software and its
  166. *    documentation for any purpose, provided that the above copyright
  167. *    notice and the following paragraphs appear in all copies of this
  168. *    software, to:
  169. *    - All who will distribute this software for free!
  170. *    - All free accessible INTERNET servers and PHONE boxes!
  171. *    - All Aminet sites
  172. *    - All SimTel sites
  173. *    - Fred Fish for his great Amiga-Software-Library
  174. *    - The German SAAR AG PD-Library
  175. *    - All others who do NOT take more than $5.- for one disk that
  176. *      includes this software!
  177. *    - ALL others who do NOT take more than $40.- for one CD that includes
  178. *      this software!
  179. *
  180. *   ADDITIONAL INFORMATIONS
  181. *    I have tried to make portable/useful and I hope bugfree software
  182. *    for eternity!
  183. *    So I hope very much that to some extend I will be compensated for my
  184. *    hard work - monetarily or otherwise:-)
  185. *
  186. *    Kindly send US - dollars to a friend of mine in the USA who will
  187. *    forward it to me in a timely manner.  Please send checks or money
  188. *    orders only.
  189. *    Contact me via email for more!
  190. *
  191. *   AUTHOR
  192. *    Kai Hofmann
  193. *    Arberger Heerstraße 92
  194. *    28307 Bremen
  195. *    Germany
  196. *
  197. *    Phone: (+49)-(0)421/480780
  198. *           (Remember that my parents don't speak english!)
  199. *    EMail: i07m@zfn.uni-bremen.de
  200. *           i07m@informatik.uni-bremen.de
  201. *    IRC  : PowerStat@#AmigaGer
  202. *    WWW  : http://www.informatik.uni-bremen.de/~i07m
  203. *
  204. *    Bank account : 1203 7503
  205. *    Account owner: Kai Hofmann
  206. *    Bank code    : 290 501 01
  207. *    Bank name    : Sparkasse in Bremen/Germany
  208. *
  209. *    THANKS
  210. *    Thank you's are going to the following people:
  211. *    Rita Reichl        - For correcting my bad english (very often)
  212. *    Christian Schaefer    - For spending time on this code with his
  213. *                  Borland C++ 4.5 compiler
  214. *    Jacco van Weert &
  215. *    Frans Slothouber    - For the 'Robodoc' utility
  216. *
  217. *****************************************************************************
  218. *
  219. *
  220. */
  221.  
  222.  
  223.  #include "TextEngine.h"
  224.  #include "Date.h"   /* bool, Languages, ... */
  225.  #include <string.h> /* strlen(), strchr() */
  226.  #include <stdio.h>  /* sprintf() */
  227.  #include <stdlib.h> /* abs() */
  228.  #include <math.h>   /* floor() */
  229.  
  230.  /* ------------------------------------------------------------------------- */
  231. /*
  232.  static void FormatStr(char *const string, const unsigned int formatlength, const char orientation, const char leftfill, const char rightfill)
  233.  
  234. / *
  235. *****i* TextEngine/FormatStr ************************************************
  236. *
  237. *   NAME
  238. *    FormatStr -- Formats a string (V33)
  239. *
  240. *   SYNOPSIS
  241. *    FormatStr(string,formatlength,orientation);
  242. *
  243. *    void FormatStr(char *string, unsigned int formatlength,
  244. *        char orientation, const char leftfill, const char rightfill);
  245. *
  246. *   FUNCTION
  247. *    Formats the string to left, right or center.
  248. *
  249. *   INPUTS
  250. *    string       - String to format.
  251. *    formatlength - The length in which the string should be formatted.
  252. *    orientation  - The orientation to format the string:
  253. *                   'l' for left, 'r' for right and 'c' for center
  254. *    leftfill     - Character to use for leftside fill
  255. *    rightfill    - Character to use for rightside fill
  256. *
  257. *   RESULT
  258. *    string - The formatted string.
  259. *
  260. *   EXAMPLE
  261. *    ...
  262. *    string = "test";
  263. *    FormatStr(string,10,'l');
  264. *    ...
  265. *
  266. *   NOTES
  267. *    None.
  268. *
  269. *   BUGS
  270. *    FormatStr will not test if the string is long enough for
  271. *    formatlength - so if this is not true, system crashes could happen!
  272. *
  273. *   SEE ALSO
  274. *
  275. *
  276. *****************************************************************************
  277. *
  278. *
  279. * /
  280.  
  281.   {
  282.    unsigned int strlength;
  283.    bool         leftright;
  284.  
  285.    strlength = strlen(string);
  286.    switch (orientation)
  287.     {
  288.      case 'l' : while (strlength < formatlength)
  289.                  {
  290.                   string[strlength++] = rightfill;
  291.                   string[strlength] = '\x0';
  292.                  }
  293.                 break;
  294.      case 'r' : while (strlength < formatlength)
  295.                  {
  296.                   unsigned int i;
  297.  
  298.                   for(i=strlength+1;i>0;i--)
  299.                     string[i] = string[i-1];
  300.                   string[0] = leftfill;
  301.                   strlength++;
  302.                  }
  303.                 break;
  304.      case 'c' : leftright = false; / * start right * /
  305.             while (strlength < formatlength)
  306.                  {
  307.               if (leftright)
  308.                    {
  309.                     unsigned int i;
  310.  
  311.                     for(i=strlength+1;i>0;i--)
  312.                       string[i] = string[i-1];
  313.                     string[0] = leftfill;
  314.                     strlength++;
  315.                }
  316.                   else
  317.                    {
  318.                     string[strlength++] = rightfill;
  319.                     string[strlength] = '\x0';
  320.                    }
  321.                   leftright = !leftright;
  322.                  }
  323.                 break;
  324.      default  : ;
  325.     }
  326.   }
  327. */
  328.  static void strdel(char *const string, const unsigned int pos, unsigned int count)
  329.  
  330. /*
  331. *****i* TextEngine/strdel ***************************************************
  332. *
  333. *   NAME
  334. *    strdel -- Deletes characters from a string (V33)
  335. *
  336. *   SYNOPSIS
  337. *    strdel(string,pos,count);
  338. *
  339. *    void strdel(char *string, const unsigned int pos,
  340. *        unsigned int count);
  341. *
  342. *   FUNCTION
  343. *    Deletes count characters from position pos in string or until
  344. *    the end of the string.
  345. *
  346. *   INPUTS
  347. *    string - String from which characters should be deleted.
  348. *    pos    - Position from which characters should be deleted.
  349. *    count  - Characters to delete.
  350. *
  351. *   RESULT
  352. *    string - The string without the characters.
  353. *
  354. *   EXAMPLE
  355. *    ...
  356. *    string = "test bla";
  357. *    strdel(string,4,4);
  358. *    ...
  359. *
  360. *   NOTES
  361. *    None.
  362. *
  363. *   BUGS
  364. *    Unknown.
  365. *
  366. *   SEE ALSO
  367. *
  368. *
  369. *****************************************************************************
  370. *
  371. *
  372. */
  373.  
  374.   {
  375.    unsigned short i;
  376.  
  377.    while (count > 0)
  378.     {
  379.      for (i=0;string[pos+i] != '\x0';i++)
  380.       {
  381.        string[pos+i] = string[pos+i+1];
  382.       }
  383.      count--;
  384.     }
  385.   }
  386.  
  387.  static void strinspos(char *const string, const unsigned int pos, const char *const istr)
  388.  
  389. /*
  390. *****i* TextEngine/strinspos ************************************************
  391. *
  392. *   NAME
  393. *    strinspos -- Inserts a string into another at a position (V33)
  394. *
  395. *   SYNOPSIS
  396. *    strinspos(string,pos,istr);
  397. *
  398. *    void strinspos(char *string, const unsigned int pos, char *istr);
  399. *
  400. *   FUNCTION
  401. *    Inserts istr in string at position pos.
  402. *
  403. *   INPUTS
  404. *    string - String into istr should be inserted
  405. *    pos    - Position into istr should be inserted
  406. *    istr   - String to insert into string
  407. *
  408. *   RESULT
  409. *    string - The string including istr
  410. *
  411. *   EXAMPLE
  412. *    ...
  413. *    char string1[16] = "test bla";
  414. *    char string2 = " bluber";
  415. *    strinspos(string1,4,string2);
  416. *    ...
  417. *
  418. *   NOTES
  419. *    None.
  420. *
  421. *   BUGS
  422. *    There is no test if there is enough space for istr in string!
  423. *
  424. *   SEE ALSO
  425. *
  426. *
  427. *****************************************************************************
  428. *
  429. *
  430. */
  431.  
  432.   {
  433.    unsigned int lenistr,lenstr;
  434.    int i;
  435.  
  436.    lenstr = strlen(string);
  437.    lenistr = strlen(istr);
  438.    for (i=(int)(lenstr-1);i>=(int)pos;i--)
  439.      string[i+lenistr] = string[i];
  440.    for (i=0;i<lenistr;i++)
  441.      string[pos+i] = istr[i];
  442.    string[lenstr+lenistr] = '\x0';
  443.   }
  444.  
  445.  /* ------------------------------------------------------------------------- */
  446.  
  447.  #ifndef __cplusplus
  448.    static void DateString(char *const string, const unsigned short day, const unsigned short month, const int year, const Languages lang)
  449.  #else
  450.    static void DateString(char *const string, const unsigned short day, const unsigned short month, const int year = 0, const Languages lang = English)
  451.  #endif
  452.  
  453. /*
  454. *****i* TextEngine/DateString ***********************************************
  455. *
  456. *   NAME
  457. *    DateString -- Fills up %-commands for dates. (V33)
  458. *
  459. *   SYNOPSIS
  460. *    DateString(string,day,month,year,lang);
  461. *
  462. *    void DateString(char *const string, const unsigned short day,
  463. *        const unsigned short month, const int year,
  464. *        const Languages lang);
  465. *
  466. *    void DateString(char *const string, const unsigned short day,
  467. *        const unsigned short month, const int year = 0,
  468. *        const Languages lang = English);
  469. *
  470. *   FUNCTION
  471. *    Finds and replaces % commands with real values.
  472. *
  473. *   INPUTS
  474. *    string - String with % commands
  475. *    day    - The day to fill in for % command
  476. *    month  - The month to fill in for % command
  477. *    year   - The year to fill in for % command, but only if it is != 0.
  478. *    lang   - The language to use for weekday and month texts
  479. *
  480. *   RESULT
  481. *    string - String without % commands, but with real values
  482. *
  483. *   EXAMPLE
  484. *    ...
  485. *    string = "Today is %Dwl the %Ddf.%DMl.%Dyf4";
  486. *    DateString(string,22,2,1994,English);
  487. *    ...
  488. *
  489. *   SYNTAX
  490. *    Syntax of % commands:
  491. *      %D1[2][3]
  492. *      1 : d : day
  493. *          m : month
  494. *          M : month text
  495. *          y : year
  496. *          w : weekday
  497. *          W : week
  498. *          s : scaliger year
  499. *          j : JD
  500. *          J : MJD
  501. *      2 : v : variable length
  502. *          f : fixed length
  503. *          s : short text
  504. *          l : long text
  505. *      3 : 2 : short year
  506. *          4 : full year
  507. *
  508. *      %Ddv  - supported: d[d]
  509. *      %Ddf  - supported: dd
  510. *      %Dmv  - supported: m[m]
  511. *      %Dmf  - supported: mm
  512. *      %DMs  - supported: MMM
  513. *      %DMl  - supported: M..M
  514. *      %Dyv2 - supported: y[y]
  515. *      %Dyv4 - supported: y[y[y[y]]]
  516. *      %Dyf2 - supported: yy
  517. *      %Dyf4 - supported: yyyy
  518. *      %Dws  - supported: ww[w]
  519. *      %Dwl  - supported: w..w
  520. *      %DWv  - supported: W[W]
  521. *      %DWf  - supported: WW
  522. *      %Dsv  - supported: s[s[s[s]]]
  523. *      %Dsf  - supported: ssss
  524. *      %Dj   - supported: j..
  525. *      %DJ   - supported: J..
  526. *
  527. *   NOTES
  528. *    None.
  529. *
  530. *   BUGS
  531. *    Unknown.
  532. *
  533. *   SEE ALSO
  534. *    TimeString()
  535. *
  536. *****************************************************************************
  537. *
  538. *
  539. */
  540.  
  541.   {
  542.    char *pos;
  543.    unsigned short delcounter;
  544.    char insertstr[21];
  545.  
  546.    pos = strchr(string,'%');
  547.    while (pos != NULL)
  548.     {
  549.      delcounter = 0;
  550.      insertstr[0] = '\x0';
  551.      if (pos[1] == 'D')
  552.       {
  553.        delcounter = 4;
  554.        switch (pos[2])
  555.         {
  556.          case 'd' : switch (pos[3])
  557.                      {
  558.                       case 'v' : sprintf(insertstr,"%hu",day);
  559.                                  break;
  560.                       case 'f' : sprintf(insertstr,"%02hu",day);
  561.                                  break;
  562.                       default  : delcounter = 0;
  563.                      }
  564.                     break;
  565.          case 'm' : switch (pos[3])
  566.                      {
  567.                       case 'v' : sprintf(insertstr,"%hu",month);
  568.                                  break;
  569.                       case 'f' : sprintf(insertstr,"%02hu",month);
  570.                                  break;
  571.                       default  : delcounter = 0;
  572.                      }
  573.                     break;
  574.          case 'M' : switch (pos[3])
  575.                      {
  576.                       case 's' : MonthShortText(month,insertstr,lang);
  577.                                  break;
  578.                       case 'l' : MonthText(month,insertstr,lang);
  579.                                  break;
  580.                       default  : delcounter = 0;
  581.                      }
  582.                     break;
  583.          case 'y' : switch (pos[3])
  584.                      {
  585.                       case 'v' : delcounter = 5;
  586.                                  switch (pos[4])
  587.                                   {
  588.                                    case '2' : sprintf(insertstr,"%2d",year-(year/100)*100);
  589.                                               break;
  590.                                    case '4' : sprintf(insertstr,"%4d",year);
  591.                                               break;
  592.                                    default  : delcounter = 0;
  593.                                   }
  594.                                  break;
  595.                       case 'f' : delcounter = 5;
  596.                                  switch (pos[4])
  597.                                   {
  598.                                    case '2' : sprintf(insertstr,"%02d",year-(year/100)*100);
  599.                                               break;
  600.                                    case '4' : sprintf(insertstr,"%04d",year);
  601.                                               break;
  602.                                    default  : delcounter = 0;
  603.                                   }
  604.                                  break;
  605.                       default  : delcounter = 0;
  606.                      }
  607.                     if (year == 0)
  608.                       insertstr[0] = '\x0';
  609.                     break;
  610.          case 'w' : switch (pos[3])
  611.                      {
  612.                       case 's' : WeekdayShortText(HeisWeekday(day,month,year),insertstr,lang);
  613.                                  break;
  614.                       case 'l' : WeekdayText(HeisWeekday(day,month,year),insertstr,lang);
  615.                                  break;
  616.                       default  : delcounter = 0;
  617.                      }
  618.                     break;
  619.          case 'W' : switch (pos[3])
  620.                      {
  621.                       case 'v' : sprintf(insertstr,"%hu",HeisWeek(day,month,year));
  622.                                  break;
  623.                       case 'f' : sprintf(insertstr,"%02hu",HeisWeek(day,month,year));
  624.                                  break;
  625.                       default  : delcounter = 0;
  626.                      }
  627.                     break;
  628.          case 's' : switch (pos[3])
  629.                      {
  630.                       case 'v' : sprintf(insertstr,"%u",HYearToScaliger(year));
  631.                                  break;
  632.                       case 'f' : sprintf(insertstr,"%04u",HYearToScaliger(year));
  633.                                  break;
  634.                       default  : delcounter = 0;
  635.                      }
  636.                     break;
  637.          case 'j' : delcounter = 3;
  638.                     sprintf(insertstr,"%lu",HeisToJD(day,month,year));
  639.                     break;
  640.          case 'J' : delcounter = 3;
  641.                     sprintf(insertstr,"%lu",JDtoMJD(HeisToJD(day,month,year)));
  642.                     break;
  643.          default  : delcounter = 0;
  644.         }
  645.        strdel(pos,0,delcounter);
  646.        strinspos(pos,0,insertstr);
  647.       }
  648.      pos = strchr(pos+(delcounter == 0 ? 2 : strlen(insertstr)),'%');
  649.     }
  650.   }
  651.  
  652.  /* ------------------------------------------------------------------------- */
  653.  
  654.  #ifndef __cplusplus
  655.    static void TimeString(char *const string, const unsigned short hour, const unsigned short min, const unsigned short sec)
  656.  #else
  657.    static void TimeString(char *const string, const unsigned short hour, const unsigned short min = 0, const unsigned short sec = 0)
  658.  #endif
  659.  
  660. /*
  661. *****i* TextEngine/TimeString ***********************************************
  662. *
  663. *   NAME
  664. *    TimeeString -- Fills up %-commands for times. (V33)
  665. *
  666. *   SYNOPSIS
  667. *    TimeString(string,hour,min,sec);
  668. *
  669. *    void TimeString(char *const string, const unsigned short hour,
  670. *        const unsigned short min, const unsigned short sec);
  671. *
  672. *    void TimeString(char *const string, const unsigned short hour,
  673. *        const unsigned short min = 0, const unsigned short sec = 0);
  674. *
  675. *   FUNCTION
  676. *    Finds and replaces % commands with real values.
  677. *
  678. *   INPUTS
  679. *    string - String with % commands
  680. *    hour   - The hour to use
  681. *    min    - The minute to use
  682. *    sec    - The sec to use
  683. *
  684. *   RESULT
  685. *    string - String with real values.
  686. *
  687. *   EXAMPLE
  688. *    ...
  689. *    string = "Time %Thf:%Tmf.%Tsf";
  690. *    TimeString(string,22,23,0);
  691. *    ...
  692. *
  693. *   SYNTAX
  694. *    Syntax of % commands:
  695. *      %T1[2]
  696. *      T : time identifier
  697. *      1 : h : hour 24h format
  698. *          H : hour 12h format without "am/pm" text
  699. *          M : "am/pm" text
  700. *          m : minute
  701. *          s : second
  702. *          j : jd time
  703. *      2 : v : variable length
  704. *          f : fixed length
  705. *
  706. *      %Thv - supported: h[h]
  707. *      %Thf - supported: hh
  708. *      %THv - supported: h[h]
  709. *      %THf - supported: hh
  710. *      %TM  - supported: am|pm
  711. *      %Tmv - supported: m[m]
  712. *      %Tmf - supported: mm
  713. *      %Tsv - supported: s[s]
  714. *      %Tsf - supported: ss
  715. *      %Tj  - supported: j
  716. *
  717. *   NOTES
  718. *    None.
  719. *
  720. *   BUGS
  721. *    No known bugs.
  722. *
  723. *   SEE ALSO
  724. *    DateString()
  725. *
  726. *****************************************************************************
  727. *
  728. *
  729. */
  730.  
  731.   {
  732.    char *pos;
  733.    unsigned short delcounter;
  734.    char insertstr[9];
  735.    unsigned short hour12;
  736.  
  737.    pos = strchr(string,'%');
  738.    while (pos != NULL)
  739.     {
  740.      delcounter = 0;
  741.      insertstr[0] = '\x0';
  742.      if (pos[1] == 'T')
  743.       {
  744.        delcounter = 4;
  745.        switch (pos[2])
  746.         {
  747.          case 'h' : switch (pos[3])
  748.                      {
  749.                       case 'v' : sprintf(insertstr,"%hu",hour);
  750.                                  break;
  751.                       case 'f' : sprintf(insertstr,"%02hu",hour);
  752.                                  break;
  753.                       default  : delcounter = 0;
  754.                      }
  755.                     break;
  756.          case 'H' : hour12 = (unsigned short)(hour > 12 ? hour-12 : hour);
  757.                     switch (pos[3])
  758.                      {
  759.                       case 'v' : sprintf(insertstr,"%hu",hour12);
  760.                                  break;
  761.                       case 'f' : sprintf(insertstr,"%02hu",hour12);
  762.                                  break;
  763.                       default  : delcounter = 0;
  764.                      }
  765.                     break;
  766.          case 'm' : switch (pos[3])
  767.                      {
  768.                       case 'v' : sprintf(insertstr,"%hu",min);
  769.                                  break;
  770.                       case 'f' : sprintf(insertstr,"%02hu",min);
  771.                                  break;
  772.                       default  : delcounter = 0;
  773.                      }
  774.                     break;
  775.          case 's' : switch (pos[3])
  776.                      {
  777.                       case 'v' : sprintf(insertstr,"%hu",sec);
  778.                                  break;
  779.                       case 'f' : sprintf(insertstr,"%02hu",sec);
  780.                                  break;
  781.                       default  : delcounter = 0;
  782.                      }
  783.                     break;
  784.          case 'M' : delcounter = 3;
  785.                     if (hour >= 12)
  786.                      {
  787.                       strcpy(insertstr,"pm");
  788.                      }
  789.                     else
  790.                      {
  791.                       strcpy(insertstr,"am");
  792.                      }
  793.                     break;
  794.          case 'j' : delcounter = 3;
  795.                     sprintf(insertstr,"%#f",TimeToJD(hour,min,sec));
  796.                     break;
  797.          default  : delcounter = 0;
  798.         }
  799.        strdel(pos,0,delcounter);
  800.        strinspos(pos,0,insertstr);
  801.       }
  802.      pos = strchr(pos+(delcounter == 0 ? 2 : strlen(insertstr)),'%');
  803.     }
  804.   }
  805.  
  806.  /* ------------------------------------------------------------------------- */
  807.  
  808.  #ifndef __cplusplus
  809.    static void DiffDateString(char *const string, const unsigned short day1, const unsigned short month1, const int year1, const unsigned short day2, const unsigned short month2, int year2)
  810.  #else
  811.    static void DiffDateString(char *const string, const unsigned short day1, const unsigned short month1, const int year1, const unsigned short day2, const unsigned short month2, int year2 = 0)
  812.  #endif
  813.  
  814. /*
  815. *****i* TextEngine/DiffDateString *******************************************
  816. *
  817. *   NAME
  818. *    DiffDateString -- Fills up %-commands for dates. (V33)
  819. *
  820. *   SYNOPSIS
  821. *    DiffDateString(string,day1,month1,year1,day2,month2,year2);
  822. *
  823. *    void DiffDateString(char *const string, const unsigned short day1,
  824. *        const unsigned short month1, const int year1,
  825. *        const unsigned short day2, const unsigned short month2,
  826. *        int year2);
  827. *
  828. *    void DiffDateString(char *const string, const unsigned short day1,
  829. *        const unsigned short month1, const int year1,
  830. *        const unsigned short day2, const unsigned short month2,
  831. *        int year2 = 0);
  832. *
  833. *   FUNCTION
  834. *    Finds and replaces % commands with real values.
  835. *
  836. *   INPUTS
  837. *    string - String with % commands
  838. *    day1   - The day of the lower date for % command
  839. *    month1 - The month of the lower date for % command
  840. *    year1  - The year of the lower date for % command
  841. *    day2   - The day of the higher date for % command
  842. *    month2 - The month of the higher date for % command
  843. *    year2  - The year of the higher date for % command, if this is 0, it
  844. *         means the same year as year1!
  845. *
  846. *   RESULT
  847. *    string - String without % commands, but with real values
  848. *
  849. *   EXAMPLE
  850. *    ...
  851. *    string = "Kai is %Ay years old.";
  852. *    DiffDateString(string,18,9,1970,22,3,1995);
  853. *    ...
  854. *
  855. *   SYNTAX
  856. *    Syntax of % commands:
  857. *      %AD1
  858. *      1 : d : days
  859. *          y : years
  860. *
  861. *      %ADd - supported: d[d..]
  862. *      %ADy - supported: y[y..]
  863. *
  864. *   NOTES
  865. *    If day2 and month2 are both 0 only year2-year1 will be calculated
  866. *    for %ADy, don't use %ADd in this situation!
  867. *
  868. *   BUGS
  869. *    There is no check if date1 is really < than date2!
  870. *
  871. *   SEE ALSO
  872. *    DiffTimeString()
  873. *
  874. *****************************************************************************
  875. *
  876. *
  877. */
  878.   {
  879.    char *pos;
  880.    unsigned short delcounter;
  881.    char insertstr[11];
  882.    unsigned long age;
  883.  
  884.    if (year2 == 0)
  885.      year2 = year1;
  886.    pos = strchr(string,'%');
  887.    while (pos != NULL)
  888.     {
  889.      delcounter = 0;
  890.      insertstr[0] = '\x0';
  891.      if ((pos[1] == 'A') && (pos[2] == 'D'))
  892.       {
  893.        delcounter = 4;
  894.        switch (pos[3])
  895.         {
  896.          case 'd' : sprintf(insertstr,"%ld",HeisDayDiff(day1,month1,year1,day2,month2,year2));
  897.                     break;
  898.          case 'y' : age = year2-year1;
  899.                     if ((Compare2Dates(day1,month1,0,day2,month2,0) == 1) && (month2 != 0) && (day2 != 0))
  900.                       age--;
  901.                     sprintf(insertstr,"%lu",age);
  902.                     break;
  903.          default  : delcounter = 0;
  904.         }
  905.        strdel(pos,0,delcounter);
  906.        strinspos(pos,0,insertstr);
  907.       }
  908.      pos = strchr(pos+(delcounter == 0 ? 2 : strlen(insertstr)),'%');
  909.     }
  910.   }
  911.  
  912.  /* ------------------------------------------------------------------------- */
  913.  
  914.  #ifndef __cplusplus
  915.    static void DiffTimeString(char *const string, const unsigned short hour1, const unsigned short hour2, const unsigned short min1, const unsigned short min2, const unsigned short sec1, const unsigned short sec2)
  916.  #else
  917.    static void DiffTimeString(char *const string, const unsigned short hour1, const unsigned short hour2, const unsigned short min1 = 0, const unsigned short min2 = 0, const unsigned short sec1 = 0, const unsigned short sec2 = 0)
  918.  #endif
  919.  
  920. /*
  921. *****i* TextEngine/DiffTimeString *******************************************
  922. *
  923. *   NAME
  924. *    DiffTimeString -- Fills up %-commands for dates. (V33)
  925. *
  926. *   SYNOPSIS
  927. *    DiffTimeString(string,hour1,min1,sec1,hour2,min2,sec2);
  928. *
  929. *    void DiffTimeString(char *const string, const unsigned short hour1,
  930. *        const unsigned short hour2, const unsigned short min1,
  931. *        const unsigned short min2, const unsigned short sec1,
  932. *        const unsigned short sec2);
  933. *
  934. *    void DiffTimeString(char *const string, const unsigned short hour1,
  935. *        const unsigned short hour2, const unsigned short min1 = 0,
  936. *        const unsigned short min2 = 0, const unsigned short sec1 = 0,
  937. *        const unsigned short sec2 = 0);
  938. *
  939. *   FUNCTION
  940. *    Finds and replaces % commands with real values.
  941. *
  942. *   INPUTS
  943. *    string - String with % commands
  944. *    hour1  - The hour of the lower time for % command
  945. *    hour2  - The hour of the higher time for % command
  946. *    min1   - The minute of the lower time for % command
  947. *    min2   - The minute of the higher time for % command
  948. *    sec1   - The second of the lower time for % command
  949. *    sec2   - The second of the higher time for % command
  950. *
  951. *   RESULT
  952. *    string - String without % commands, but with real values
  953. *
  954. *   EXAMPLE
  955. *    ...
  956. *    string1 = "%ATh hours & %ATm minutes & %ATs seconds to go!";
  957. *    DiffTimeString(string,18,20,30,15,0,0);
  958. *    string2 = "%ATH hours = %ATM minutes = %ATS seconds to go! ";
  959. *    DiffTimeString(string,18,20,30,15,0,0);
  960. *    ...
  961. *
  962. *   SYNTAX
  963. *    Syntax of % commands:
  964. *      %AT1
  965. *      1 : h : full hours
  966. *          m : full minutes
  967. *          s : full seconds
  968. *          H : all in hours
  969. *          M : all in minutes
  970. *          S : all in seconds
  971. *          j : as JD time difference
  972. *
  973. *      %ATh - supported: h[h..]
  974. *      %ATm - supported: m[m]
  975. *      %ATs - supported: s[s]
  976. *      %ATH - supported: h[h..][.h[h..]]
  977. *      %ATM - supported: m[m..][.m[m..]]
  978. *      %ATS - supported: s[s..]
  979. *      %ATj - supported: j
  980. *
  981. *   NOTES
  982. *    None.
  983. *
  984. *   BUGS
  985. *    There is no check if time1 is really < than time2!
  986. *
  987. *   SEE ALSO
  988. *    DiffDateString()
  989. *
  990. *****************************************************************************
  991. *
  992. *
  993. */
  994.   {
  995.    char *pos;
  996.    unsigned short delcounter,h3,m3,s3;
  997.    char insertstr[21];
  998.    long seconds;
  999.  
  1000.    seconds = (long)(TimeToSec(hour2,min2,sec2)-TimeToSec(hour1,min1,sec1));
  1001.    #ifndef __cplusplus
  1002.      seconds = labs(seconds);
  1003.      SecToTime(seconds,&h3,&m3,&s3);
  1004.    #else
  1005.      if (seconds < 0)
  1006.        seconds = -seconds;
  1007.      SecToTime(seconds,h3,m3,s3);
  1008.    #endif
  1009.    pos = strchr(string,'%');
  1010.    while (pos != NULL)
  1011.     {
  1012.      delcounter = 0;
  1013.      insertstr[0] = '\x0';
  1014.      if ((pos[1] == 'A') && (pos[2] == 'T'))
  1015.       {
  1016.        delcounter = 4;
  1017.        switch (pos[3])
  1018.         {
  1019.          case 'h' : sprintf(insertstr,"%hu",h3);
  1020.                     break;
  1021.          case 'm' : sprintf(insertstr,"%hu",m3);
  1022.                     break;
  1023.          case 's' : sprintf(insertstr,"%hu",s3);
  1024.                     break;
  1025.          case 'H' : sprintf(insertstr,"%#.2f",(float)(seconds/3600.0));
  1026.                     break;
  1027.          case 'M' : sprintf(insertstr,"%#.2f",(float)(seconds/60.0));
  1028.                     break;
  1029.          case 'S' : sprintf(insertstr,"%ld",seconds);
  1030.                     break;
  1031.          case 'j' : sprintf(insertstr,"%#f",TimeToJD(h3,m3,s3));
  1032.                     break;
  1033.          default  : delcounter = 0;
  1034.         }
  1035.        strdel(pos,0,delcounter);
  1036.        strinspos(pos,0,insertstr);
  1037.       }
  1038.      pos = strchr(pos+(delcounter == 0 ? 2 : strlen(insertstr)),'%');
  1039.     }
  1040.   }
  1041.  
  1042.  /* ------------------------------------------------------------------------- */
  1043.  
  1044.  static void StringString(char *const string, const char *const strarr[])
  1045.  
  1046. /*
  1047. *****i* TextEngine/StringString *********************************************
  1048. *
  1049. *   NAME
  1050. *    StringString -- Fills up %-commands for strings. (V33)
  1051. *
  1052. *   SYNOPSIS
  1053. *    StringString(string,string2);
  1054. *
  1055. *    void StringString(char *const string, const char *const strarr[]);
  1056. *
  1057. *   FUNCTION
  1058. *    Finds and replaces % commands with real values.
  1059. *
  1060. *   INPUTS
  1061. *    string  - String with % commands
  1062. *    strarr  - Stringarray with the strings to insert, terminated by NULL
  1063. *
  1064. *   RESULT
  1065. *    string - String with real value.
  1066. *
  1067. *   EXAMPLE
  1068. *    ...
  1069. *    string = "This is a %S0";
  1070. *    StringString(string,{"test",NULL});
  1071. *    ...
  1072. *
  1073. *   SYNTAX
  1074. *    Syntax of % commands:
  1075. *      %S1
  1076. *      1 : Stringarray index
  1077. *
  1078. *      %Sx - supported: s[x]
  1079. *
  1080. *   NOTES
  1081. *    None.
  1082. *
  1083. *   BUGS
  1084. *    It is not possible to write a number directly behind a %S command,
  1085. *    because this will be identified as array index, so another character
  1086. *    as a digit is needed!
  1087. *
  1088. *   SEE ALSO
  1089. *    DateString(), TimeString()
  1090. *
  1091. *****************************************************************************
  1092. *
  1093. *
  1094. */
  1095.  
  1096.   {
  1097.    char *pos;
  1098.    unsigned short delcounter;
  1099.    unsigned int idx,maxidx=0;
  1100.  
  1101.    if (strarr != NULL)
  1102.     {
  1103.      while (strarr[maxidx] != NULL)
  1104.       {
  1105.        maxidx++;
  1106.       }
  1107.      pos = strchr(string,'%');
  1108.      while (pos != NULL)
  1109.       {
  1110.        delcounter = 0;
  1111.        idx = 0;
  1112.        if (pos[1] == 'S')
  1113.         {
  1114.          while ((pos[2+delcounter] >= '0') && (pos[2+delcounter] <= '9'))
  1115.           {
  1116.            idx *= 10;
  1117.            idx += (unsigned int)pos[2+delcounter] - (unsigned int)'0';
  1118.            delcounter++;
  1119.           }
  1120.          if (delcounter != 0)
  1121.           {
  1122.            delcounter += 2;
  1123.            strdel(pos,0,delcounter);
  1124.            if (idx < maxidx)
  1125.             {
  1126.              strinspos(pos,0,strarr[idx]);
  1127.             }
  1128.           }
  1129.         }
  1130.        pos = strchr(pos+(delcounter == 0 ? 2 : strlen(strarr[idx])),'%');
  1131.       }
  1132.     }
  1133.   }
  1134.  
  1135.  /* ------------------------------------------------------------------------- */
  1136.  
  1137.  #ifndef __cplusplus
  1138.    void TextEngine(char *const string, const unsigned short day, const unsigned short month, const int year, const unsigned short hour, const unsigned short min, const unsigned short sec, const Languages lang, const unsigned short day2, const unsigned short month2, const int year2, const unsigned short hour2, const unsigned short min2, const unsigned short sec2, const char *const *const strarr)
  1139.  #else
  1140.    void TextEngine(char *const string, const unsigned short day, const unsigned short month, const int year, const unsigned short hour, const unsigned short min, const unsigned short sec, const Languages lang, const unsigned short day2, const unsigned short month2, const int year2, const unsigned short hour2, const unsigned short min2, const unsigned short sec2, const char *const *const strarr)
  1141.  #endif
  1142.  
  1143. /*
  1144. ******* TextEngine/TextEngine ***********************************************
  1145. *
  1146. *   NAME
  1147. *    TextEngine -- Fills up %-commands (V33)
  1148. *
  1149. *   SYNOPSIS
  1150. *    TextEngine(string,day,month,year,hour,min,sec,lang,day2,month2,
  1151. *        year2,hour2,min2,sec2,strarr);
  1152. *    TextEngine(string,jd,lang,jd2,strarr)
  1153. *
  1154. *    void TextEngine(char *const string, const unsigned short day,
  1155. *        const unsigned short month, const int year = 0,
  1156. *        const unsigned short hour = 0, const unsigned short min = 0,
  1157. *        const unsigned short sec = 0, const Languages lang = English,
  1158. *        const unsigned short day2 = 0, const unsigned short month2 = 0,
  1159. *        const int year2 = 0, const unsigned short hour2 = 0,
  1160. *        const unsigned short min2 = 0, const unsigned short sec2 = 0,
  1161. *        const char *const *const strarr = NULL);
  1162. *
  1163. *    void TextEngine(char *const string, double jd,
  1164. *        const Languages lang = English, double jd2 = 0.0.
  1165. *        const char *const *const strarr = NULL);
  1166. *
  1167. *   FUNCTION
  1168. *    Finds and replaces % commands with real values.
  1169. *
  1170. *   INPUTS
  1171. *    string  - String with % commands
  1172. *    day     - The day to fill in for % command
  1173. *    month   - The month to fill in for % command
  1174. *    year    - The year to fill in for % command, if this is 0 it will not
  1175. *          filled in!
  1176. *    hour    - The hour to use
  1177. *    min     - The minute to use
  1178. *    sec     - The sec to use
  1179. *    lang    - The language to use for texts
  1180. *    day2    - The diff. day
  1181. *    month2  - The diff. month
  1182. *    year2   - The diff. year, if you use 0, this will mean: use the same
  1183. *          as year!
  1184. *    hour2   - The diff. hour
  1185. *    min2    - The diff. minute
  1186. *    sec2    - The diff. second
  1187. *    strarr  - Stringarray with the strings to insert, terminated by NULL
  1188. *
  1189. *   RESULT
  1190. *    string - String without % commands, but with real values
  1191. *
  1192. *   EXAMPLE
  1193. *    ...
  1194. *    string = "Only a test!";
  1195. *    TextEngine(string,18,9,1970,14,44,0,English,22,3,1995,15,14,0,NULL);
  1196. *    ...
  1197. *
  1198. *   SYNTAX
  1199. *    Syntax of % commands:
  1200. *      %%    : %
  1201. *      %+DTj : JD.JD  date+time
  1202. *      %+DTJ : MJD.JD date+time
  1203. *
  1204. *      %D1[2][3]
  1205. *      1 : d : day
  1206. *          m : month
  1207. *          M : month text
  1208. *          y : year
  1209. *          w : weekday
  1210. *          W : week
  1211. *          s : scaliger year
  1212. *          j : JD
  1213. *          J : MJD
  1214. *      2 : v : variable length
  1215. *          f : fixed length
  1216. *          s : short text
  1217. *          l : long text
  1218. *      3 : 2 : short year
  1219. *          4 : full year
  1220. *
  1221. *      %Ddv  - supported: d[d]
  1222. *      %Ddf  - supported: dd
  1223. *      %Dmv  - supported: m[m]
  1224. *      %Dmf  - supported: mm
  1225. *      %DMs  - supported: MMM
  1226. *      %DMl  - supported: M..M
  1227. *      %Dyv2 - supported: y[y]
  1228. *      %Dyv4 - supported: y[y[y[y]]]
  1229. *      %Dyf2 - supported: yy
  1230. *      %Dyf4 - supported: yyyy
  1231. *      %Dws  - supported: ww[w]
  1232. *      %Dwl  - supported: w..w
  1233. *      %DWv  - supported: W[W]
  1234. *      %DWf  - supported: WW
  1235. *      %Dsv  - supported: s[s[s[s]]]
  1236. *      %Dsf  - supported: ssss
  1237. *      %Dj   - supported: j..
  1238. *      %DJ   - supported: J..
  1239. *
  1240. *      %T1[2]
  1241. *      T : time identifier
  1242. *      1 : h : hour 24h format
  1243. *          H : hour 12h format without "am/pm" text
  1244. *          M : "am/pm" text
  1245. *          m : minute
  1246. *          s : second
  1247. *          j : jd time
  1248. *      2 : v : variable length
  1249. *          f : fixed length
  1250. *
  1251. *      %Thv - supported: h[h]
  1252. *      %Thf - supported: hh
  1253. *      %THv - supported: h[h]
  1254. *      %THf - supported: hh
  1255. *      %TM  - supported: am|pm
  1256. *      %Tmv - supported: m[m]
  1257. *      %Tmf - supported: mm
  1258. *      %Tsv - supported: s[s]
  1259. *      %Tsf - supported: ss
  1260. *      %Tj  - supported: j
  1261. *
  1262. *      %AD1
  1263. *      1 : d : Difference from the given date to the actual date in days.
  1264. *          y : Difference from the given date to the actual date in years.
  1265. *
  1266. *      %ADd - supported: d[d..]
  1267. *      %ADy - supported: y[y..]
  1268. *
  1269. *      %AT1
  1270. *      1 : h : full hours
  1271. *          m : full minutes
  1272. *          s : full seconds
  1273. *          H : all in hours
  1274. *          M : all in minutes
  1275. *          S : all in seconds
  1276. *          j : as JD time difference
  1277. *
  1278. *      %ATh - supported: h[h..]
  1279. *      %ATm - supported: m[m]
  1280. *      %ATs - supported: s[s]
  1281. *      %ATH - supported: h[h..][.h[h..]]
  1282. *      %ATM - supported: m[m..][.m[m..]]
  1283. *      %ATS - supported: s[s..]
  1284. *      %ATj - supported: j
  1285. *
  1286. *      %S
  1287. *      S : string identifier
  1288. *
  1289. *      %S - supported: s
  1290. *
  1291. *   NOTES
  1292. *    If day2 and month2 are both 0 only year2-year will be calculated
  1293. *    for %ADy, don't use %ADd in this situation!
  1294. *    Think before using:
  1295. *      TextEngine(str,18,9,1970,0,0,0,English,18,9,1995,0,0,0) or
  1296. *      TextEngine(str,18,9,1995,0,0,0,English,18,9,1970,0,0,0)
  1297. *
  1298. *   BUGS
  1299. *    Keep care that in string is enought space to expand it - if not
  1300. *    unknown effects may occur!
  1301. *
  1302. *   SEE ALSO
  1303. *    DateString(), TimeString()
  1304. *
  1305. *****************************************************************************
  1306. *
  1307. *
  1308. */
  1309.  
  1310.   {
  1311.    char *pos;
  1312.    unsigned short delcounter;
  1313.    char insertstr[21];
  1314.  
  1315.    StringString(string,strarr);
  1316.    DateString(string,day,month,year,lang);
  1317.    TimeString(string,hour,min,sec);
  1318.    if (Compare2Dates(day,month,year,day2,month2,year2) == -1)
  1319.      DiffDateString(string,day,month,year,day2,month2,year2);
  1320.    else
  1321.      DiffDateString(string,day2,month2,year2,day,month,year);
  1322.    DiffTimeString(string,hour,hour2,min,min2,sec,sec2);
  1323.    pos = strchr(string,'%');
  1324.    while (pos != NULL)
  1325.     {
  1326.      delcounter = 0;
  1327.      insertstr[0] = '\x0';
  1328.      if ((pos[1] == '+') && (pos[2] == 'D') && (pos[3] == 'T'))
  1329.       {
  1330.        delcounter = 5;
  1331.        switch (pos[4])
  1332.         {
  1333.          case 'j' : sprintf(insertstr,"%#f",HeisToJD(day,month,year)+TimeToJD(hour,min,sec));
  1334.                     break;
  1335.          case 'J' : sprintf(insertstr,"%#f",JDtoMJD(HeisToJD(day,month,year))+TimeToJD(hour,min,sec));
  1336.                     break;
  1337.          default  : delcounter = 0;
  1338.         }
  1339.        strdel(pos,0,delcounter);
  1340.        strinspos(pos,0,insertstr);
  1341.       }
  1342.      else if (pos[1] == '%')
  1343.       {
  1344.        delcounter = 2;
  1345.        strcpy(insertstr,"%");
  1346.        strdel(pos,0,delcounter);
  1347.        strinspos(pos,0,insertstr);
  1348.       }
  1349.      pos = strchr(pos+(delcounter == 0 ? 2 : strlen(insertstr)),'%');
  1350.     }
  1351.   }
  1352.  
  1353.  
  1354.  #ifndef __cplusplus
  1355.    void TextEngineJD(char *const string, double jd, const Languages lang, double jd2, const char *const *const strarr)
  1356. /*
  1357. ******* TextEngine/TextEngineJD *********************************************
  1358. *
  1359. *   NAME
  1360. *    TextEngineJD -- Fills up %-commands (V33)
  1361. *
  1362. *   SYNOPSIS
  1363. *    TextEngineJD(string,jd,lang,jd2,strarr);
  1364. *
  1365. *    void TextEngineJD(char *const string, double jd,
  1366. *        const Languages lang = English, double jd2 = 0.0,
  1367. *        const char *const *const strarr);
  1368. *
  1369. *   FUNCTION
  1370. *    Finds and replaces % commands with real values.
  1371. *
  1372. *   INPUTS
  1373. *    string  - String with % commands.
  1374. *    jd      - The JD including time information.
  1375. *    lang    - The language to use for texts.
  1376. *    jd2     - The diff. JD.
  1377. *    strarr  - Stringarray with the strings to insert, terminated by NULL
  1378. *
  1379. *   RESULT
  1380. *    string - String without % commands, but with real values.
  1381. *
  1382. *   EXAMPLE
  1383. *    ...
  1384. *    string = "Only a test!";
  1385. *    TextEngineJD(string,2449754.630556,English,2449700,NULL);
  1386. *    ...
  1387. *
  1388. *   SYNTAX
  1389. *    Syntax of % commands:
  1390. *      See TextEngine()
  1391. *
  1392. *   NOTES
  1393. *    See TextEngine().
  1394. *
  1395. *   BUGS
  1396. *    Unknown.
  1397. *
  1398. *   SEE ALSO
  1399. *    TextEngine()
  1400. *
  1401. *****************************************************************************
  1402. *
  1403. *
  1404. */
  1405.  #else
  1406.    void TextEngine(char *const string, double jd, const Languages lang, double jd2, const char *const *const strarr)
  1407.  #endif
  1408.  
  1409.   {
  1410.    unsigned short day,month,hour,min,sec,day2,month2,hour2,min2,sec2;
  1411.    int year,year2;
  1412.  
  1413.    #ifndef __cplusplus
  1414.      JDToHeis((unsigned long)jd,&day,&month,&year);
  1415.      JDToHeis((unsigned long)jd2,&day2,&month2,&year2);
  1416.    #else
  1417.      JDToHeis((unsigned long)jd,day,month,year);
  1418.      JDToHeis((unsigned long)jd2,day2,month2,year2);
  1419.    #endif
  1420.    jd -= floor(jd);
  1421.    jd2 -= floor(jd2);
  1422.    #ifndef __cplusplus
  1423.      JDToTime((float)jd,&hour,&min,&sec);
  1424.      JDToTime((float)jd2,&hour2,&min2,&sec2);
  1425.    #else
  1426.      JDToTime((float)jd,hour,min,sec);
  1427.      JDToTime((float)jd2,hour2,min2,sec2);
  1428.    #endif
  1429.    TextEngine(string,day,month,year,hour,min,sec,lang,day2,month2,year2,hour2,min2,sec2,strarr);
  1430.   }
  1431.  
  1432.  /* ------------------------------------------------------------------------- */
  1433.