Skip to content

Commit

Permalink
Add support for "$DATE(format)" and "$TIME(format)" header/footer str…
Browse files Browse the repository at this point in the history
…ings

(Issue #472)
  • Loading branch information
michaelrsweet committed Mar 28, 2022
1 parent ffb68b6 commit a67e9cc
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 10 deletions.
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Changes in HTMLDOC v1.9.16

- Added support for `$DATE(format)` and `$TIME(format)` header/footer strings
(Issue #472)
- Fixed a potential image overflow bug with JPEG and PNG images (Issue #471)
- Fixed potential heap overflow bugs with pages (Issue #477, Issue #478,
Issue #480, Issue #482, Issue #483)
Expand Down
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
dnl
dnl Con])guration script for HTMLDOC, an HTML document processing program.
dnl Configuration script for HTMLDOC, an HTML document processing program.
dnl
dnl Copyright © 2011-2022 by Michael R Sweet.
dnl Copyright © 1997-2010 by Easy Software Products.
Expand Down
51 changes: 49 additions & 2 deletions doc/4-htmlref.html
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,10 @@ <H3>Header/Footer Strings</H3>

<!-- NEED 1in -->
<DT><CODE>$DATE</CODE>
<DD>Inserts the current date.
<DT><CODE>$DATE(format)</CODE>
<DD>Inserts the current date. See <a href="#DATETIME">Date/Time
Formats</a> for details on the format string. When no format is
supplied, the default date format for the current locale is used.

<!-- NEED 1in -->
<DT><CODE>$HEADING</CODE>
Expand Down Expand Up @@ -348,7 +351,10 @@ <H3>Header/Footer Strings</H3>

<!-- NEED 1in -->
<DT><CODE>$TIME</CODE>
<DD>Inserts the current time.
<DT><CODE>$TIME(format)</CODE>
<DD>Inserts the current time. See <a href="#DATETIME">Date/Time
Formats</a> for details on the format string. When no format is
supplied, the default time format for the current locale is used.

<!-- NEED 1in -->
<DT><CODE>$TITLE</CODE>
Expand All @@ -360,6 +366,47 @@ <H3>Header/Footer Strings</H3>

</DL>

<H3><A NAME="DATETIME">Date/Time Formats</A></H3>

<p>The <CODE>$DATE</CODE> and <CODE>$TIME</CODE> header/footer strings support
an optional format string in parenthesis. Letters represent date/time values
while other characters are inserted verbatim. The following letters are
supported:</p>

<center>
<table border="1" cellpadding="5">
<tr><th>Letter</th><th>Description</th></tr>
<tr><td><code>A</code></td><td>Full weekday name</td></tr>
<tr><td><code>a</code></td><td>Abbreviated weekday name</td></tr>
<tr><td><code>B</code></td><td>Full month name</td></tr>
<tr><td><code>b</code></td><td>Abbreviated month name</td></tr>
<tr><td><code>C</code></td><td>Century (CC)</td></tr>
<tr><td><code>c</code></td><td>Default date and time format</td></tr>
<tr><td><code>d</code></td><td>Day of the month ("01" to "31")</td></tr>
<tr><td><code>e</code></td><td>Day of the month (" 1" to "31")</td></tr>
<tr><td><code>F</code></td><td>YYYY-MM-DD</td></tr>
<tr><td><code>H</code></td><td>Hours for 24-hour clock ("00" to "23")</td></tr>
<tr><td><code>I</code></td><td>Hours for 12-hour clock ("01" to "12")</td></tr>
<tr><td><code>j</code></td><td>Day of the year ("001" to "366")</td></tr>
<tr><td><code>k</code></td><td>Hours for 24-hour clock (" 0" to "23")</td></tr>
<tr><td><code>l</code></td><td>Hours for 12-hour clock (" 1" to "12")</td></tr>
<tr><td><code>M</code></td><td>Minutes ("00" to "59")</td></tr>
<tr><td><code>m</code></td><td>Month number ("01" to "12")</td></tr>
<tr><td><code>p</code></td><td>"am" or "pm"</td></tr>
<tr><td><code>R</code></td><td>Hours and minutes ("HH:MM")</td></tr>
<tr><td><code>r</code></td><td>Hours, minutes, seconds, and am/pm ("HH:MM:SS am/pm")</td></tr>
<tr><td><code>S</code></td><td>Seconds ("00" to "60")</td></tr>
<tr><td><code>T</code></td><td>Hours, minutes, and seconds ("HH:MM:SS")</td></tr>
<tr><td><code>X</code></td><td>Default time format</td></tr>
<tr><td><code>x</code></td><td>Default date format</td></tr>
<tr><td><code>Y</code></td><td>Year with century (CCYY)</td></tr>
<tr><td><code>y</code></td><td>Year without century (YY)</td></tr>
<tr><td><code>Z</code></td><td>Time zone name</td></tr>
<tr><td><code>z</code></td><td>Time zone offset from UTC</td></tr>
</table>
</center>


<!-- NEED 5in -->
<H2><A NAME="FONT">FONT Attributes</A></H2>

Expand Down
96 changes: 89 additions & 7 deletions htmldoc/ps-pdf.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,7 @@ pspdf_export(tree_t *document, /* I - Document to export */
if (!source_date_epoch || (doc_time = (time_t)strtol(source_date_epoch, NULL, 10)) <= 0)
doc_time = time(NULL);

gmtime_r(&doc_time, &doc_date);
localtime_r(&doc_time, &doc_date);

num_headings = 0;
alloc_headings = 0;
Expand Down Expand Up @@ -1706,14 +1706,96 @@ pspdf_prepare_heading(int page, // I - Page number
}
else if (formatlen == 4 && strncasecmp(formatptr, "TIME", 4) == 0)
{
char timefmt[256]; // Time format

formatptr += 4;
strftime(bufptr, sizeof(buffer) - 1 - (size_t)(bufptr - buffer), "%X", &doc_date);
if (*formatptr == '(')
{
// Support "$TIME(format)"
char *timeptr; // Pointer into time format

for (timeptr = timefmt, formatptr ++; *formatptr && *formatptr != ')'; formatptr ++)
{
if (isalpha(*formatptr))
{
if (timeptr < (timefmt + sizeof(timefmt) - 2))
{
*timeptr++ = '%';
*timeptr++ = *formatptr;
}
else
break;
}
else if (timeptr < (timefmt + sizeof(timefmt) - 1))
{
*timeptr++ = *formatptr;
}
else
break;
}

*timeptr = '\0';

while (*formatptr && *formatptr != ')')
formatptr ++;

if (*formatptr)
formatptr ++;
}
else
{
// Use the locale default format...
strlcpy(timefmt, "%X", sizeof(timefmt));
}

strftime(bufptr, sizeof(buffer) - 1 - (size_t)(bufptr - buffer), timefmt, &doc_date);
bufptr += strlen(bufptr);
}
else if (formatlen == 4 && strncasecmp(formatptr, "DATE", 4) == 0)
{
char datefmt[256]; // Date format

formatptr += 4;
strftime(bufptr, sizeof(buffer) - 1 - (size_t)(bufptr - buffer), "%x", &doc_date);
if (*formatptr == '(')
{
// Support "$DATE(format)"
char *dateptr; // Pointer into date format

for (dateptr = datefmt, formatptr ++; *formatptr && *formatptr != ')'; formatptr ++)
{
if (isalpha(*formatptr))
{
if (dateptr < (datefmt + sizeof(datefmt) - 2))
{
*dateptr++ = '%';
*dateptr++ = *formatptr;
}
else
break;
}
else if (dateptr < (datefmt + sizeof(datefmt) - 1))
{
*dateptr++ = *formatptr;
}
else
break;
}

*dateptr = '\0';

while (*formatptr && *formatptr != ')')
formatptr ++;

if (*formatptr)
formatptr ++;
}
else
{
// Use the locale default format...
strlcpy(datefmt, "%x", sizeof(datefmt));
}

strftime(bufptr, sizeof(buffer) - 1 - (size_t)(bufptr - buffer), datefmt, &doc_date);
bufptr += strlen(bufptr);
}
else if (formatlen == 3 && strncasecmp(formatptr, "URL", 3) == 0)
Expand Down Expand Up @@ -11565,9 +11647,9 @@ write_prolog(FILE *out, /* I - Output file */
fprintf(out, "%%%%BoundingBox: 0 0 %d %d\n", PageWidth, PageLength);
fprintf(out,"%%%%LanguageLevel: %d\n", PSLevel);
fputs("%%Creator: " HTMLDOC_PRODUCER "\n", out);
fprintf(out, "%%%%CreationDate: D:%04d%02d%02d%02d%02d%02d+0000\n",
fprintf(out, "%%%%CreationDate: D:%04d%02d%02d%02d%02d%02d%03d00\n",
doc_date.tm_year + 1900, doc_date.tm_mon + 1, doc_date.tm_mday,
doc_date.tm_hour, doc_date.tm_min, doc_date.tm_sec);
doc_date.tm_hour, doc_date.tm_min, doc_date.tm_sec, (int)(doc_date.tm_gmtoff / 3600));
if (doc_title != NULL)
fprintf(out, "%%%%Title: %s\n", doc_title);
if (author != NULL)
Expand Down Expand Up @@ -11949,9 +12031,9 @@ write_prolog(FILE *out, /* I - Output file */
fputs("/Producer", out);
write_string(out, (uchar *)HTMLDOC_PRODUCER, 0);
fputs("/CreationDate", out);
snprintf(temp, sizeof(temp), "D:%04d%02d%02d%02d%02d%02dZ",
snprintf(temp, sizeof(temp), "D:%04d%02d%02d%02d%02d%02d%03d00",
doc_date.tm_year + 1900, doc_date.tm_mon + 1, doc_date.tm_mday,
doc_date.tm_hour, doc_date.tm_min, doc_date.tm_sec);
doc_date.tm_hour, doc_date.tm_min, doc_date.tm_sec, (int)(doc_date.tm_gmtoff / 3600));
write_string(out, (uchar *)temp, 0);

if (doc_title != NULL)
Expand Down
6 changes: 6 additions & 0 deletions testsuite/basic.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@
</HEAD>
<BODY>

<!--
FOOTER LEFT "Date: $DATE(Y-m-d)"
FOOTER CENTER "Time: $TIME(I:M:Sp)"
FOOTER RIGHT "Page: $PAGE of $PAGES"
-->

<H1>Basic HTML Test</H1>

<H1>Heading 1</H1>
Expand Down

0 comments on commit a67e9cc

Please sign in to comment.