summaryrefslogtreecommitdiff
path: root/src/pr.c
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>2001-03-17 08:48:23 +0000
committerJim Meyering <jim@meyering.net>2001-03-17 08:48:23 +0000
commitca0659ab9afcd95f27cbb2e8975444bf9a097f31 (patch)
treebcdac878d677111483ba6a25ae2c3b319db81f8c /src/pr.c
parent6fa00f67daa4077d66a4547aad3b96466d8d8883 (diff)
downloadcoreutils-ca0659ab9afcd95f27cbb2e8975444bf9a097f31.tar.xz
Include mbswidth.h.
(standard_header, header, test_suite): Remove. (date_format, date_text, file_text, header_width_available): New vars. (long_options, main, init_header, usage): Add new -D or --date-format option. (CHARS_FOR_DATE_AND_PAGE, T_BUF_FMT, T_BUF_SIZE, NO_DATE): Remove. (init_header): Allow arbitrary width for date format. Change "Page %5d" to "Page %d", since the code no longer assumes fixed width. Do not assume that localtime succeeds. (init_header, print_header, usage): Do not truncate headers. (init_header, print_header): Defer width calculations until page is printed, since "Page 100000" is wider than "Page 1". Count columns, not bytes, in page headers. Custom headers take up only the center, not the whole header. (print_header): Use printf rather than fprintf(stdout).
Diffstat (limited to 'src/pr.c')
-rw-r--r--src/pr.c173
1 files changed, 72 insertions, 101 deletions
diff --git a/src/pr.c b/src/pr.c
index 8681957e9..5c5b96a1b 100644
--- a/src/pr.c
+++ b/src/pr.c
@@ -1,5 +1,5 @@
/* pr -- convert text files for printing.
- Copyright (C) 88, 91, 1995-2000 Free Software Foundation, Inc.
+ Copyright (C) 88, 91, 1995-2001 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -150,6 +150,8 @@
-d, --double-space Double space the output.
+ -D FORMAT, --date-format=FORMAT Use FORMAT for the header date.
+
-e[CHAR[WIDTH]], --expand-tabs[=CHAR[WIDTH]]
Expand tabs to spaces on input. Optional argument CHAR
is the input TAB character. (Default is TAB). Optional
@@ -162,12 +164,7 @@
-h HEADER, --header=HEADER
Replace the filename in the header with the string HEADER.
- Checking and left-hand-side truncation of the length of the
- standard and custom header string. A centered header is used.
- The format of date and time has been shortened
- to yyyy-mm-dd HH:MM to give place to a maximal filename
- information.
- -h "" now prints a blank line header. -h"" shows an error.
+ A centered header is used.
-i[CHAR[WIDTH]], --output-tabs[=CHAR[WIDTH]]
Replace spaces with tabs on output. Optional argument
@@ -320,6 +317,7 @@
#include "system.h"
#include "closeout.h"
#include "error.h"
+#include "mbswidth.h"
#include "xstrtol.h"
/* The official name of this program (e.g., no `g' prefix). */
@@ -506,10 +504,6 @@ static int print_a_FF = FALSE;
to print after it. */
static int print_a_header;
-/* (-h) True means we're using the standard header rather than a
- customized one specified by the -h flag. */
-static int standard_header = TRUE;
-
/* (-f) True means use formfeeds instead of newlines to separate pages. */
static int use_form_feed = FALSE;
@@ -711,8 +705,15 @@ static int pad_vertically;
/* (-h) String of characters used in place of the filename in the header. */
static char *custom_header;
-/* String containing the date, filename or custom header, and "Page ". */
-static char *header;
+/* (-D) Date format for the header. */
+static char const *date_format;
+
+/* Date and file name for the header. */
+static char *date_text;
+static char const *file_text;
+
+/* Output columns available, not counting the date and file name. */
+static int header_width_available;
static int *clump_buff;
@@ -722,10 +723,6 @@ static int *clump_buff;
structure COLUMN. */
static int last_line = FALSE;
-/* If nonzero, print a non-variable date and time with the header
- -h HEADER using pr test-suite */
-static int test_suite;
-
/* For long options that have no equivalent short option, use a
non-character as a pseudo short option, starting with CHAR_MAX + 1. */
enum
@@ -736,12 +733,12 @@ enum
static struct option const long_options[] =
{
- {"test", no_argument, &test_suite, 1},
{"pages", required_argument, NULL, PAGES_OPTION},
{"columns", required_argument, NULL, COLUMNS_OPTION},
{"across", no_argument, NULL, 'a'},
{"show-control-chars", no_argument, NULL, 'c'},
{"double-space", no_argument, NULL, 'd'},
+ {"date-format", required_argument, NULL, 'D'},
{"expand-tabs", optional_argument, NULL, 'e'},
{"form-feed", no_argument, NULL, 'f'},
{"header", required_argument, NULL, 'h'},
@@ -862,7 +859,7 @@ main (int argc, char **argv)
: NULL);
while ((c = getopt_long (argc, argv,
- "-0123456789abcde::fFh:i::Jl:mn::N:o:rs::S::tTvw:W:",
+ "-0123456789abcdD:e::fFh:i::Jl:mn::N:o:rs::S::tTvw:W:",
long_options, NULL))
!= -1)
{
@@ -932,6 +929,9 @@ main (int argc, char **argv)
case 'd':
double_space = TRUE;
break;
+ case 'D':
+ date_format = optarg;
+ break;
case 'e':
if (optarg)
getoptarg (optarg, 'e', &input_tab_char,
@@ -945,7 +945,6 @@ main (int argc, char **argv)
break;
case 'h':
custom_header = optarg;
- standard_header = FALSE;
break;
case 'i':
if (optarg)
@@ -1065,6 +1064,11 @@ main (int argc, char **argv)
}
}
+ if (! date_format)
+ date_format = (getenv ("POSIXLY_CORRECT")
+ ? dcgettext (NULL, "%b %e %H:%M %Y", LC_TIME)
+ : "%Y-%m-%d %H:%M");
+
/* Now we can set a reasonable initial value: */
if (first_page_number == 0)
first_page_number = 1;
@@ -1624,90 +1628,47 @@ print_files (int number_of_files, char **av)
;
}
-/* Estimate the number of characters taken up by a short format date and
- time: "yy-mm-dd HH:MM" and: "Page NNNN". */
-#define CHARS_FOR_DATE_AND_PAGE 25
-
-#define T_BUF_FMT "%Y-%m-%d %H:%M" /* date/time short format */
-
-/* Add `2' because the expansion of %Y occupies 4 bytes, which is two more
- than the length of `%Y'. Each of the other formats expand to two bytes. */
-#define T_BUF_SIZE (2 + sizeof T_BUF_FMT)
-
-/* This string is exactly the same length as the expansion of T_BUF_FMT. */
-#define NO_DATE "-- Date/Time -- "
-
/* Initialize header information.
If DESC is non-negative, it is a file descriptor open to
- FILENAME for reading.
-
- Allocate space for a header string,
- Determine the time, insert file name or user-specified string.
- Make use of a centered header with left-hand-side truncation marked by
- a '*` in front, if necessary. */
+ FILENAME for reading. */
static void
init_header (char *filename, int desc)
{
- char *f = filename;
+ char *buf;
+ char initbuf[MAX (256, INT_STRLEN_BOUND (long) + 1)];
struct stat st;
- size_t header_buf_size;
-
- if (filename == NULL)
- f = "";
-
- if (header != NULL)
- free (header);
-
- /* Allow a space on each side of the the filename-or-header. */
- header_buf_size = MAX (chars_per_line, CHARS_FOR_DATE_AND_PAGE + 2) + 1;
- header = (char *) xmalloc (header_buf_size);
-
- if (!standard_header && *custom_header == '\0')
- *header = '\0'; /* blank line header */
+ struct tm *tm;
+
+ /* If parallel files or standard input, use current date. */
+ if (STREQ (filename, "-"))
+ desc = -1;
+ if (desc < 0 || fstat (desc, &st) != 0)
+ st.st_mtime = time (NULL);
+
+ buf = initbuf;
+ tm = localtime (&st.st_mtime);
+ if (! tm)
+ sprintf (buf, "%ld", (long) st.st_mtime);
else
{
- int chars_per_middle, lhs_blanks, rhs_blanks;
- struct tm *tmptr;
- char t_buf[T_BUF_SIZE];
- char *header_text;
-
- /* If parallel files or standard input, use current time. */
- if (desc < 0 || STREQ (filename, "-") || fstat (desc, &st))
- st.st_mtime = time (NULL);
-
- tmptr = localtime (&st.st_mtime);
- strftime (t_buf, T_BUF_SIZE, T_BUF_FMT, tmptr);
-
- chars_per_middle = header_buf_size - 1 - CHARS_FOR_DATE_AND_PAGE;
- if (chars_per_middle < 3)
- {
- header_text = ""; /* Nothing free for a heading */
- lhs_blanks = 1;
- rhs_blanks = 1;
- }
- else
+ size_t bufsize = sizeof initbuf;
+ for (;;)
{
- int chars_free;
- header_text = standard_header ? f : custom_header;
- chars_free = chars_per_middle - (int) strlen (header_text);
- if (chars_free > 1)
- {
- lhs_blanks = chars_free / 2; /* text not truncated */
- rhs_blanks = chars_free - lhs_blanks;
- }
- else
- { /* lhs truncation */
- header_text = header_text - chars_free + 2;
- *header_text = '*';
- lhs_blanks = 1;
- rhs_blanks = 1;
- }
+ *buf = '\1';
+ if (strftime (buf, bufsize, date_format, tm) || ! *buf)
+ break;
+ buf = alloca (bufsize *= 2);
}
-
- sprintf (header, _("%s%*s%s%*sPage"), (test_suite ? NO_DATE : t_buf),
- lhs_blanks, " ", header_text, rhs_blanks, " ");
}
+
+ if (date_text)
+ free (date_text);
+ date_text = xstrdup (buf);
+ file_text = custom_header ? custom_header : desc < 0 ? "" : filename;
+ header_width_available = (chars_per_line
+ - mbswidth (date_text, 0)
+ - mbswidth (file_text, 0));
}
/* Set things up for printing a page
@@ -2404,20 +2365,29 @@ skip_to_page (int page)
static void
print_header (void)
{
+ char page_text[256 + INT_STRLEN_BOUND (int)];
+ int available_width;
+ int lhs_spaces;
+ int rhs_spaces;
+
if (!use_form_feed)
- fprintf (stdout, "\n\n");
+ printf ("\n\n");
output_position = 0;
pad_across_to (chars_per_margin);
print_white_space ();
- if (!standard_header && *custom_header == '\0')
- {
- fprintf (stdout, "%s\n\n\n", header);
- page_number++;
- }
- else
- fprintf (stdout, "%s%5d\n\n\n", header, page_number++);
+ /* The translator must ensure that formatting the translation of
+ "Page %d" does not generate more than (sizeof page_text - 1)
+ bytes. */
+ sprintf (page_text, _("Page %d"), page_number++);
+ available_width = header_width_available - mbswidth (page_text, 0);
+ available_width = MAX (0, available_width);
+ lhs_spaces = available_width >> 1;
+ rhs_spaces = available_width - lhs_spaces;
+
+ printf ("%s%*s%s%*s%s\n\n\n",
+ date_text, lhs_spaces, " ", file_text, rhs_spaces, " ", page_text);
print_a_header = FALSE;
output_position = 0;
@@ -2791,6 +2761,8 @@ Paginate or columnate FILE(s) for printing.\n\
use hat notation (^G) and octal backslash notation\n\
-d, --double-space\n\
double space the output\n\
+ -D, --date-format=FORMAT\n\
+ use FORMAT for the header date\n\
-e[CHAR[WIDTH]], --expand-tabs[=CHAR[WIDTH]]\n\
expand input CHARs (TABs) to tab WIDTH (8)\n\
-F, -f, --form-feed\n\
@@ -2801,7 +2773,6 @@ Paginate or columnate FILE(s) for printing.\n\
printf (_("\
-h HEADER, --header=HEADER\n\
use a centered HEADER instead of filename in page header,\n\
- with long headers left-hand-side truncation may occur,\n\
-h \"\" prints a blank line, don't use -h\"\"\n\
-i[CHAR[WIDTH]], --output-tabs[=CHAR[WIDTH]]\n\
replace spaces with CHARs (TABs) to tab WIDTH (8)\n\