From 873165af1d9ae450483816b892aa17afd669a7c0 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Sun, 23 Sep 2007 05:59:01 +0000 Subject: [PATCH] Bug #21128. Reviewed by John Darrington. * output/paper-size.sh: New test. * main.c (i18_init): Set up LC_PAPER locale, if available. Don't bother with LC_MONETARY locale, since we don't use it anywhere. * output.c (TWO_CHARS macro): Removed. (outp_evaluate_dimension): Changed interface, rewritten. Updated all callers. (internal_get_paper_size): Removed. (parse_unit): New function. (parse_paper_size): New function. (outp_get_paper_size): Tweaked interface, rewritten. (get_standard_paper_size): New function. (read_paper_conf): New function. (get_default_paper_size): New function. * postscript.c (ps_open_driver): Use system default paper size as default paper, instead of hard-coding US letter. (handle_option): Allow outp_evaluate_dimension to supply error message instead of generating it here. * automake.mk: Add new file. * paper-size.c: New file. * command.def: Add DEBUG PAPER SIZE command. * papersize: Removed. * automake.mk (dist_pkgsysconf_DATA): Remove papersize. * acinclude.m4 (PSPP_LC_PAPER): New macro. * configure.ac: Use PSPP_LC_PAPER. --- ChangeLog | 8 + NEWS | 8 +- acinclude.m4 | 21 +- config/ChangeLog | 8 + config/automake.mk | 3 +- config/papersize | 60 ---- configure.ac | 1 + doc/configuring.texi | 53 +--- src/language/ChangeLog | 7 +- src/language/command.def | 1 + src/language/tests/ChangeLog | 8 + src/language/tests/automake.mk | 1 + src/language/tests/paper-size.c | 45 +++ src/output/ChangeLog | 20 ++ src/output/output.c | 478 ++++++++++++++++---------------- src/output/output.h | 4 +- src/output/postscript.c | 13 +- src/ui/terminal/ChangeLog | 7 + src/ui/terminal/main.c | 4 +- tests/ChangeLog | 6 + tests/automake.mk | 1 + tests/output/paper-size.sh | 96 +++++++ 22 files changed, 497 insertions(+), 356 deletions(-) delete mode 100644 config/papersize create mode 100644 src/language/tests/paper-size.c create mode 100755 tests/output/paper-size.sh diff --git a/ChangeLog b/ChangeLog index b117867f..8fd7bc7d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2007-09-22 Ben Pfaff + + Bug #21128. Reviewed by John Darrington. + + * acinclude.m4 (PSPP_LC_PAPER): New macro. + + * configure.ac: Use PSPP_LC_PAPER. + 2007-08-05 Ben Pfaff Bug #16189. Reviewed by Jason Stover. diff --git a/NEWS b/NEWS index 8e65aa79..2ba38211 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,5 @@ PSPP NEWS -- history of user-visible changes. -Time-stamp: <2007-07-06 23:12:24 blp> +Time-stamp: <2007-09-22 17:48:06 blp> Copyright (C) 1996-9, 2000 Free Software Foundation, Inc. See the end for copying conditions. @@ -20,6 +20,12 @@ Changes since 0.4.3: may replace any usage of it by SELECT IF following TEMPORARY, which has the same effect. + The default paper size for the PostScript driver is now determined + using the PAPERSIZE environment variable, or the LC_PAPER locale + category on systems that support it. If these are not set, the + default is now A4, instead of US letter. To make US letter the + default, set PAPERSIZE to "letter" in your environment. + For developers, the build system now requires Autoconf 2.60 and Automake 1.10. diff --git a/acinclude.m4 b/acinclude.m4 index 4201e22b..61290a18 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -1,4 +1,4 @@ -dnl Copyright (C) 2005, 2006 Free Software Foundation, Inc. +dnl Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. @@ -205,4 +205,21 @@ t} fi AC_SUBST(EXEEXT_FOR_BUILD)]) -dnl aclocal.m4 ends here +dnl Check for LC_PAPER, _NL_PAPER_WIDTH, _NL_PAPER_HEIGHT. +AC_DEFUN([PSPP_LC_PAPER], +[AC_CACHE_CHECK(for LC_PAPER, pspp_cv_lc_paper, [ + pspp_cv_lc_paper=no + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [#include +#include +], + [(void) LC_PAPER; (void) _NL_PAPER_WIDTH; (void) _NL_PAPER_HEIGHT])], + [pspp_cv_lc_paper=yes]) + ]) + if test "$pspp_cv_lc_paper" = yes; then + AC_DEFINE(HAVE_LC_PAPER, 1, [Define if you have LC_PAPER.]) + fi +]) + +dnl acinclude.m4 ends here diff --git a/config/ChangeLog b/config/ChangeLog index 93c9e809..27cb2b33 100644 --- a/config/ChangeLog +++ b/config/ChangeLog @@ -1,3 +1,11 @@ +2007-09-22 Ben Pfaff + + Bug #21128. Reviewed by John Darrington. + + * papersize: Removed. + + * automake.mk (dist_pkgsysconf_DATA): Remove papersize. + 2007-08-26 Ben Pfaff * devices: Change raw-ascii from screen to listing device (because diff --git a/config/automake.mk b/config/automake.mk index fa493d52..ba01a397 100644 --- a/config/automake.mk +++ b/config/automake.mk @@ -2,8 +2,7 @@ dist_pkgsysconf_DATA = \ - config/devices \ - config/papersize + config/devices psfontsdir = $(pkgsysconfdir)/psfonts dist_psfonts_DATA = \ diff --git a/config/papersize b/config/papersize deleted file mode 100644 index f3866ed9..00000000 --- a/config/papersize +++ /dev/null @@ -1,60 +0,0 @@ -# List of standard paper sizes for use with PSPP output drivers. -# -# Valid units include "in"=inches, "cm"=centimeters, "mm"=millimeters. -# Default units are "in" for dimensions less than 50, "mm" otherwise. -# This automagically determines units for all the standard sizes. -# -# Fractional values are allowed: (1) as decimals, or (2) in the form -# "a-b/c", which has the value of a, plus b divided by c. -# -# Also allowed are synonyms: `"B4/JIS"="B4/ISO"'. The left hand size -# is replaced by the right hand size. - -# U.S. -"Letter" 8-1/2 x 11 -"Legal" 8-1/2 x 14 -"Letter Extra" 9-1/2 x 12 -"Legal Extra" 9-1/2 x 15 -"Executive" 7-1/4 x 10-1/2 -"Ledger" 17 x 11 -"Tabloid" 11 x 17 -"Tabloid Extra" 11.69 x 18 -"US Standard Fanfold"="U.S. Standard Fanfold" -"U.S. Standard Fanfold" 14-7/8 x 11 -"Standard Fanfold" 8-1/2 x 12 -"Legal Fanfold" 8-1/2 x 12 - -# Envelopes. -"DL" 8-2/3 x 4-1/3 -"Monarch" 3-7/8 x 7-1/2 -"6 3/4 Envelope"="6-3/4 Envelope" -"6-3/4 Envelope" 3-5/8 x 6-1/2 -"#9" 3-7/8 x 8-7/8 -"#10" 4-1/8 x 9-1/2 -"#11" 4-1/2 x 10-3/8 -"#12" 4-3/4 x 11 -"#14" 5 x 11-1/2 - -# Metric. -"B4"="B4/ISO" -"B5"="B5/ISO" -"A3" 297 x 420 -"A4" 210 x 297 -"B4/ISO" 250 x 353 -"B4/JIS" 257 x 364 -"B5/ISO" 176 x 250 -"B5/JIS" 182 x 257 -"B6" 176 x 125 -"C3" 324 x 458 -"C4" 229 x 324 -"C5" 162 x 229 -"C6" 114 x 162 -"C65" 114 x 229 -"Envelope" 110 x 230 - -# Demonstration of units. -#"Bizarre" 55mm x 10in - -# Local Variables: -# fill-prefix: "# " -# End: diff --git a/configure.ac b/configure.ac index cb5b4c58..ea4cef37 100644 --- a/configure.ac +++ b/configure.ac @@ -30,6 +30,7 @@ AC_SYS_LARGEFILE AC_FUNC_FSEEKO AC_CHECK_LIB(m, sin) PSPP_LIBPLOT +PSPP_LC_PAPER AM_CONDITIONAL(WITHCHARTS, test x"$with_libplot" != x"no") diff --git a/doc/configuring.texi b/doc/configuring.texi index c299d9c8..18d24cac 100644 --- a/doc/configuring.texi +++ b/doc/configuring.texi @@ -208,7 +208,6 @@ The following sections further elaborate the contents of the * Macro definitions:: Environment variables local to @file{devices}. * Device definitions:: Output device descriptions. * Dimensions:: Lengths, widths, sizes, @enddots{} -* papersize:: Letter, legal, A4, envelope, @enddots{} * Distinguishing line types:: Details on @file{devices} parsing. * Tokenizing lines:: Dividing @file{devices} lines into tokens. @end menu @@ -444,36 +443,6 @@ Numbers 50 or greater are assumed to be in millimeters. @end itemize @end itemize -@node papersize -@subsection Paper sizes - -Output drivers usually deal with some sort of hardcopy media. This -media is called @dfn{paper} by the drivers, though in reality it could -be a transparency or film or thinly veiled sarcasm. To make it easier -for you to deal with paper, PSPP allows you to have (of course!) a -configuration file that gives symbolic names, like ``letter'' or -``legal'' or ``a4'', to paper sizes, rather than forcing you to use -cryptic numbers like ``8-1/2 x 11'' or ``210 by 297''. Surprisingly -enough, this configuration file is named @file{papersize}. -@xref{Configuration files}. - -When PSPP tries to connect a symbolic paper name to a paper size, it -reads and parses each non-comment line in the file, in order. The first -field on each line must be a symbolic paper name in double quotes. -Paper names may not contain double quotes. Paper names are not -case-sensitive: @samp{legal} and @samp{Legal} are equivalent. - -If a match is found for the paper name, the rest of the line is parsed. -If it is found to be a pair of dimensions (@pxref{Dimensions}) separated -by either @samp{x} or @samp{by}, then those are taken to be the paper -size, in order of width followed by length. There @emph{must} be at -least one space on each side of @samp{x} or @samp{by}. - -Otherwise the line must be of the form -@samp{"@var{paper-1}"="@var{paper-2}"}. In this case the target of the -search becomes paper name @var{paper-2} and the search through the file -continues. - @node Distinguishing line types @subsection How lines are divided into types @@ -594,9 +563,16 @@ title and subtitle are printed at the top of each page. Default: @item paper-size=@var{paper-size} -Paper size, either as a symbolic name (i.e., @code{letter} or @code{a4}) -or specific measurements (i.e., @code{8-1/2x11} or @code{"210 x 297"}. -@xref{papersize, , Paper sizes}. Default: @code{letter}. +Paper size. You may specify a name (e.g.@: @code{a4}, @code{letter}) +or measurements (e.g.@: @code{210x297}, @code{8.5x11in}). + +The default paper size is taken from the @env{PAPERSIZE} environment +variable or the file indicated by the @env{PAPERCONF} environment +variable, if either variable is set. If not, and your system supports +the @code{LC_PAPER} locale category, then the default paper size is +taken from the locale. Otherwise, if @file{/etc/papersize} exists, +the default paper size is read from it. As a last resort, A4 paper is +assumed. @item orientation=@var{orientation} @@ -898,15 +874,10 @@ support was compiled into PSPP. The basename used to search for the driver definition file. @xref{Output devices}. @xref{File locations}. Default: @code{devices}. -@item STAT_OUTPUT_PAPERSIZE_FILE - -The basename used to search for the papersize file. @xref{papersize}. -@xref{File locations}. Default: @code{papersize}. - @item STAT_OUTPUT_INIT_PATH -The path used to search for the driver definition file and the papersize -file. @xref{File locations}. Default: the standard configuration path. +The path used to search for the driver definition file. +@xref{File locations}. Default: the standard configuration path. @item TMPDIR diff --git a/src/language/ChangeLog b/src/language/ChangeLog index d25c2d03..840278b2 100644 --- a/src/language/ChangeLog +++ b/src/language/ChangeLog @@ -1,10 +1,15 @@ +2007-09-22 Ben Pfaff + + Bug #21128. Reviewed by John Darrington. + + * command.def: Add DEBUG PAPER SIZE command. + 2007-09-05 John Darrington * command.c (do_parse_command): Translate CMD_FAILURE into CMD_CASCADING_FAILURE, if the ERRMODE_STOP is set on the syntax source. - 2007-06-06 Ben Pfaff * command.def: Add DEBUG DATASHEET command. Remove DEBUG CASEFILE diff --git a/src/language/command.def b/src/language/command.def index 7a89ae0a..f77bd692 100644 --- a/src/language/command.def +++ b/src/language/command.def @@ -131,6 +131,7 @@ DEF_CMD (S_INPUT_PROGRAM, 0, "REREAD", cmd_reread) DEF_CMD (S_ANY, F_TESTING, "DEBUG DATASHEET", cmd_debug_datasheet) DEF_CMD (S_ANY, F_TESTING, "DEBUG EVALUATE", cmd_debug_evaluate) DEF_CMD (S_ANY, F_TESTING, "DEBUG MOMENTS", cmd_debug_moments) +DEF_CMD (S_ANY, F_TESTING, "DEBUG PAPER SIZE", cmd_debug_paper_size) DEF_CMD (S_ANY, F_TESTING, "DEBUG POOL", cmd_debug_pool) DEF_CMD (S_ANY, F_TESTING, "DEBUG FLOAT FORMAT", cmd_debug_float_format) DEF_CMD (S_ANY, F_TESTING, "DEBUG XFORM FAIL", cmd_debug_xform_fail) diff --git a/src/language/tests/ChangeLog b/src/language/tests/ChangeLog index 295c5418..56506452 100644 --- a/src/language/tests/ChangeLog +++ b/src/language/tests/ChangeLog @@ -1,3 +1,11 @@ +2007-09-22 Ben Pfaff + + Bug #21128. Reviewed by John Darrington. + + * automake.mk: Add new file. + + * paper-size.c: New file. + 2007-06-06 Ben Pfaff * automake.mk: Add new file. diff --git a/src/language/tests/automake.mk b/src/language/tests/automake.mk index bbcd777b..49c71da1 100644 --- a/src/language/tests/automake.mk +++ b/src/language/tests/automake.mk @@ -8,6 +8,7 @@ language_tests_sources = \ src/language/tests/datasheet-test.c \ src/language/tests/float-format.c \ src/language/tests/moments-test.c \ + src/language/tests/paper-size.c \ src/language/tests/pool-test.c \ $(language_tests_built_sources) diff --git a/src/language/tests/paper-size.c b/src/language/tests/paper-size.c new file mode 100644 index 00000000..d8c49a59 --- /dev/null +++ b/src/language/tests/paper-size.c @@ -0,0 +1,45 @@ +/* PSPP - a program for statistical analysis. + Copyright (C) 2007 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 + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#include + +#include +#include +#include +#include + +/* Executes the DEBUG PAPER SIZE command. */ +int +cmd_debug_paper_size (struct lexer *lexer, struct dataset *ds UNUSED) +{ + int h, v; + + if (!lex_force_string (lexer)) + return CMD_FAILURE; + + printf ("\"%s\" => ", ds_cstr (lex_tokstr (lexer))); + if (outp_get_paper_size (ds_cstr (lex_tokstr (lexer)), &h, &v)) + printf ("%.1f x %.1f in, %.0f x %.0f mm\n", + h / 72000., v / 72000., + h / (72000 / 25.4), v / (72000 / 25.4)); + else + printf ("error\n"); + lex_get (lexer); + + return lex_end_of_command (lexer); +} diff --git a/src/output/ChangeLog b/src/output/ChangeLog index f7ce7b5c..adabbcde 100644 --- a/src/output/ChangeLog +++ b/src/output/ChangeLog @@ -1,3 +1,23 @@ +2007-09-22 Ben Pfaff + + Bug #21128. Reviewed by John Darrington. + + * output.c (TWO_CHARS macro): Removed. + (outp_evaluate_dimension): Changed interface, rewritten. Updated + all callers. + (internal_get_paper_size): Removed. + (parse_unit): New function. + (parse_paper_size): New function. + (outp_get_paper_size): Tweaked interface, rewritten. + (get_standard_paper_size): New function. + (read_paper_conf): New function. + (get_default_paper_size): New function. + + * postscript.c (ps_open_driver): Use system default paper size as + default paper, instead of hard-coding US letter. + (handle_option): Allow outp_evaluate_dimension to supply error + message instead of generating it here. + 2007-09-21 Ben Pfaff * ascii.c (struct ascii_driver_ext): New member reported_error. diff --git a/src/output/output.c b/src/output/output.c index 5a24d895..842e1c15 100644 --- a/src/output/output.c +++ b/src/output/output.c @@ -15,19 +15,24 @@ along with this program. If not, see . */ #include -#include "output.h" -#include -#include -#include + #include -#include +#include +#include +#include +#include +#include + #include -#include "htmlP.h" -#include "intprops.h" -#include #include +#include +#include #include +#include +#include + #include "error.h" +#include "intprops.h" #include "gettext.h" #define _(msgid) gettext (msgid) @@ -803,275 +808,274 @@ outp_match_keyword (const char *s, const struct outp_option *tab, int *subcat) return -1; } -/* Encapsulate two characters in a single int. */ -#define TWO_CHARS(A, B) \ - ((A) + ((B)<<8)) - -/* Determines the size of a dimensional measurement and returns the - size in units of 1/72000". Units if not specified explicitly are - inches for values under 50, millimeters otherwise. Returns 0, - stores NULL to *TAIL on error; otherwise returns dimension, stores - address of next */ -int -outp_evaluate_dimension (char *dimen, char **tail) +/* Parses UNIT as a dimensional unit. Returns the multiplicative + factor needed to change a quantity measured in that unit into + 1/72000" units. If UNIT is empty, it is treated as + millimeters. If the unit is unrecognized, returns 0. */ +static double +parse_unit (const char *unit) { - char *s = dimen; - char *ptail; - double value; - - value = strtod (s, &ptail); - if (ptail == s) - goto lossage; - if (*ptail == '-') - { - double b, c; - s = &ptail[1]; - b = strtod (s, &ptail); - if (b <= 0.0 || ptail == s) - goto lossage; - if (*ptail != '/') - goto lossage; - s = &ptail[1]; - c = strtod (s, &ptail); - if (c <= 0.0 || ptail == s) - goto lossage; - s = ptail; - if (c == 0.0) - goto lossage; - if (value > 0) - value += b / c; - else - value -= b / c; - } - else if (*ptail == '/') - { - double b; - s = &ptail[1]; - b = strtod (s, &ptail); - if (b <= 0.0 || ptail == s) - goto lossage; - s = ptail; - value /= b; - } - else - s = ptail; - if (*s == 0 || isspace ((unsigned char) *s)) - { - if (value < 50.0) - value *= 72000; - else - value *= 72000 / 25.4; - } - else + struct unit { + char name[3]; double factor; + }; - /* Standard TeX units are supported. */ - if (*s == '"') - factor = 72000, s++; - else - switch (TWO_CHARS (s[0], s[1])) - { - case TWO_CHARS ('p', 't'): - factor = 72000 / 72.27; - break; - case TWO_CHARS ('p', 'c'): - factor = 72000 / 72.27 * 12.0; - break; - case TWO_CHARS ('i', 'n'): - factor = 72000; - break; - case TWO_CHARS ('b', 'p'): - factor = 72000 / 72.0; - break; - case TWO_CHARS ('c', 'm'): - factor = 72000 / 2.54; - break; - case TWO_CHARS ('m', 'm'): - factor = 72000 / 25.4; - break; - case TWO_CHARS ('d', 'd'): - factor = 72000 / 72.27 * 1.0700086; - break; - case TWO_CHARS ('c', 'c'): - factor = 72000 / 72.27 * 12.840104; - break; - case TWO_CHARS ('s', 'p'): - factor = 72000 / 72.27 / 65536.0; - break; - default: - error (0, 0, - _("unit \"%s\" is unknown in dimension \"%s\""), s, dimen); - *tail = NULL; - return 0; - } - ptail += 2; - value *= factor; - } - if (value <= 0.0) - goto lossage; - if (tail) - *tail = ptail; - return value + 0.5; - -lossage: - *tail = NULL; - error (0, 0, _("bad dimension \"%s\""), dimen); + static const struct unit units[] = + { + {"pt", 72000 / 72}, + {"pc", 72000 / 72 * 12.0}, + {"in", 72000}, + {"cm", 72000 / 2.54}, + {"mm", 72000 / 25.4}, + {"", 72000 / 25.4}, + }; + + const struct unit *p; + + unit += strspn (unit, CC_SPACES); + for (p = units; p < units + sizeof units / sizeof *units; p++) + if (!strcasecmp (unit, p->name)) + return p->factor; + return 0.0; +} + +/* Determines the size of a dimensional measurement and returns + the size in units of 1/72000". Units are assumed to be + millimeters unless otherwise specified. Returns 0 on + error. */ +int +outp_evaluate_dimension (const char *dimen) +{ + double raw, factor; + char *tail; + + /* Number. */ + raw = strtod (dimen, &tail); + if (raw <= 0.0) + goto syntax_error; + + /* Unit. */ + factor = parse_unit (tail); + if (factor == 0.0) + goto syntax_error; + + return raw * factor; + +syntax_error: + error (0, 0, _("`%s' is not a valid length."), dimen); return 0; } /* Stores the dimensions in 1/72000" units of paper identified by - SIZE, which is of form `HORZ x VERT' or `HORZ by VERT' where each - of HORZ and VERT are dimensions, into *H and *V. Return true on - success. */ + SIZE, which is of form `HORZ x VERT [UNIT]' where HORZ and + VERT are numbers and UNIT is an optional unit of measurement, + into *H and *V. Return true on success. */ static bool -internal_get_paper_size (char *size, int *h, int *v) +parse_paper_size (const char *size, int *h, int *v) { + double raw_h, raw_v, factor; char *tail; - while (isspace ((unsigned char) *size)) - size++; - *h = outp_evaluate_dimension (size, &tail); - if (tail == NULL) + /* Width. */ + raw_h = strtod (size, &tail); + if (raw_h <= 0.0) + return false; + + /* Delimiter. */ + tail += strspn (tail, CC_SPACES "x,"); + + /* Length. */ + raw_v = strtod (tail, &tail); + if (raw_v <= 0.0) + return false; + + /* Unit. */ + factor = parse_unit (tail); + if (factor == 0.0) return false; - while (isspace ((unsigned char) *tail)) - tail++; - if (*tail == 'x') - tail++; - else if (*tail == 'b' && tail[1] == 'y') - tail += 2; - else - { - error (0, 0, _("`x' expected in paper size `%s'"), size); - return false; - } - *v = outp_evaluate_dimension (tail, &tail); - if (tail == NULL) - return 0; - while (isspace ((unsigned char) *tail)) - tail++; - if (*tail) - { - error (0, 0, _("trailing garbage `%s' on paper size `%s'"), tail, size); - return false; - } + *h = raw_h * factor + .5; + *v = raw_v * factor + .5; return true; } -/* Stores the dimensions, in 1/72000" units, of paper identified by - SIZE into *H and *V. SIZE may be a pair of dimensions of form `H x - V', or it may be a case-insensitive paper identifier, which is - looked up in the `papersize' configuration file. Returns true - on success. May modify SIZE. */ -/* Don't read further unless you've got a strong stomach. */ -bool -outp_get_paper_size (char *size, int *h, int *v) +static bool +get_standard_paper_size (struct substring name, int *h, int *v) { - struct paper_size + static const char *sizes[][2] = { - char *name; - int use; - int h, v; + {"a0", "841 x 1189 mm"}, + {"a1", "594 x 841 mm"}, + {"a2", "420 x 594 mm"}, + {"a3", "297 x 420 mm"}, + {"a4", "210 x 297 mm"}, + {"a5", "148 x 210 mm"}, + {"b5", "176 x 250 mm"}, + {"a6", "105 x 148 mm"}, + {"a7", "74 x 105 mm"}, + {"a8", "52 x 74 mm"}, + {"a9", "37 x 52 mm"}, + {"a10", "26 x 37 mm"}, + {"b0", "1000 x 1414 mm"}, + {"b1", "707 x 1000 mm"}, + {"b2", "500 x 707 mm"}, + {"b3", "353 x 500 mm"}, + {"b4", "250 x 353 mm"}, + {"letter", "612 x 792 pt"}, + {"legal", "612 x 1008 pt"}, + {"executive", "522 x 756 pt"}, + {"note", "612 x 792 pt"}, + {"11x17", "792 x 1224 pt"}, + {"tabloid", "792 x 1224 pt"}, + {"statement", "396 x 612 pt"}, + {"halfletter", "396 x 612 pt"}, + {"halfexecutive", "378 x 522 pt"}, + {"folio", "612 x 936 pt"}, + {"quarto", "610 x 780 pt"}, + {"ledger", "1224 x 792 pt"}, + {"archA", "648 x 864 pt"}, + {"archB", "864 x 1296 pt"}, + {"archC", "1296 x 1728 pt"}, + {"archD", "1728 x 2592 pt"}, + {"archE", "2592 x 3456 pt"}, + {"flsa", "612 x 936 pt"}, + {"flse", "612 x 936 pt"}, + {"csheet", "1224 x 1584 pt"}, + {"dsheet", "1584 x 2448 pt"}, + {"esheet", "2448 x 3168 pt"}, }; - FILE *f; - char *pprsz_fn; - - struct string line; - int line_number = 0; - - bool free_it = false; - bool result = false; - char *ep; - - while (isspace ((unsigned char) *size)) - size++; - if (isdigit ((unsigned char) *size)) - return internal_get_paper_size (size, h, v); - ep = size; - while (*ep) - ep++; - while (isspace ((unsigned char) *ep) && ep >= size) - ep--; - if (ep == size) - { - error (0, 0, _("paper size name cannot be empty")); - return 0; - } - - ep++; - if (*ep) - *ep = 0; - - pprsz_fn = fn_search_path (fn_getenv_default ("STAT_OUTPUT_PAPERSIZE_FILE", - "papersize"), - fn_getenv_default ("STAT_OUTPUT_INIT_PATH", - config_path)); + size_t i; - ds_init_empty (&line); + for (i = 0; i < sizeof sizes / sizeof *sizes; i++) + if (ss_equals_case (ss_cstr (sizes[i][0]), name)) + { + bool ok = parse_paper_size (sizes[i][1], h, v); + assert (ok); + return ok; + } + error (0, 0, _("unknown paper type `%.*s'"), + (int) ss_length (name), ss_data (name)); + return false; +} - if (pprsz_fn == NULL) - { - error (0, 0, _("cannot find `papersize' configuration file")); - goto exit; - } +/* Reads file FILE_NAME to find a paper size. Stores the + dimensions, in 1/72000" units, into *H and *V. Returns true + on success, false on failure. */ +static bool +read_paper_conf (const char *file_name, int *h, int *v) +{ + struct string line = DS_EMPTY_INITIALIZER; + int line_number = 0; + FILE *file; - f = fopen (pprsz_fn, "r"); - if (!f) + file = fopen (file_name, "r"); + if (file == NULL) { - error (0, errno, _("error opening \"%s\""), pprsz_fn); - goto exit; + error (0, errno, _("error opening \"%s\""), file_name); + return false; } for (;;) { - struct substring p, name; + struct substring name; - if (!ds_read_config_line (&line, &line_number, f)) + if (!ds_read_config_line (&line, &line_number, file)) { - if (ferror (f)) - error (0, errno, _("error reading \"%s\""), pprsz_fn); + if (ferror (file)) + error (0, errno, _("error reading \"%s\""), file_name); break; } - p = ds_ss (&line); - ss_ltrim (&p, ss_cstr (CC_SPACES)); - if (!ss_match_char (&p, '"') || !ss_get_until (&p, '"', &name)) - goto lex_error; - if (ss_compare (name, ss_cstr (size))) - continue; + name = ds_ss (&line); + ss_trim (&name, ss_cstr (CC_SPACES)); + if (!ss_is_empty (name)) + { + bool ok = get_standard_paper_size (name, h, v); + fclose (file); + ds_destroy (&line); + return ok; + } + } - ss_ltrim (&p, ss_cstr (CC_SPACES)); - if (ss_match_char (&p, '=')) - { - if (free_it) - free (size); - ss_trim (&p, ss_cstr (CC_SPACES)); - size = ss_xstrdup (p); - free_it = true; - continue; - } - size = ss_data (p); - break; + fclose (file); + ds_destroy (&line); + error (0, 0, _("paper size file \"%s\" does not state a paper size"), + file_name); + return false; +} - lex_error: - error_at_line (0, 0, pprsz_fn, line_number, - _("syntax error in paper size definition")); - } +/* The user didn't specify a paper size, so let's choose a + default based on his environment. Stores the + dimensions, in 1/72000" units, into *H and *V. Returns true + on success, false on failure. */ +static bool +get_default_paper_size (int *h, int *v) +{ + /* libpaper in Debian (and other distributions?) allows the + paper size to be specified in $PAPERSIZE or in a file + specified in $PAPERCONF. */ + if (getenv ("PAPERSIZE") != NULL) + return get_standard_paper_size (ss_cstr (getenv ("PAPERSIZE")), h, v); + if (getenv ("PAPERCONF") != NULL) + return read_paper_conf (getenv ("PAPERCONF"), h, v); + +#if HAVE_LC_PAPER + /* LC_PAPER is a non-standard glibc extension. */ + *h = (int) nl_langinfo(_NL_PAPER_WIDTH) * (72000 / 25.4); + *v = (int) nl_langinfo(_NL_PAPER_HEIGHT) * (72000 / 25.4); + if (*h > 0 && *v > 0) + return true; +#endif + + /* libpaper defaults to /etc/papersize. */ + if (fn_exists ("/etc/papersize")) + return read_paper_conf ("/etc/papersize", h, v); + + /* Can't find a default. */ + return false; +} - /* We found the one we want! */ - result = internal_get_paper_size (size, h, v); +/* Stores the dimensions, in 1/72000" units, of paper identified + by SIZE into *H and *V. SIZE can be the name of a kind of + paper ("a4", "letter", ...) or a pair of dimensions + ("210x297", "8.5x11in", ...). Returns true on success, false + on failure. On failure, *H and *V are set for A4 paper. */ +bool +outp_get_paper_size (const char *size, int *h, int *v) +{ + struct substring s; + bool ok; -exit: - ds_destroy (&line); - if (free_it) - free (size); + s = ss_cstr (size); + ss_trim (&s, ss_cstr (CC_SPACES)); - if (!result) - error (0, 0, _("error reading paper size definition file")); + if (ss_is_empty (s)) + { + /* Treat empty string as default paper size. */ + ok = get_default_paper_size (h, v); + } + else if (isdigit (ss_first (s))) + { + /* Treat string that starts with digit as explicit size. */ + ok = parse_paper_size (size, h, v); + if (!ok) + error (0, 0, _("syntax error in paper size `%s'"), size); + } + else + { + /* Check against standard paper sizes. */ + ok = get_standard_paper_size (s, h, v); + } - return result; + /* Default to A4 on error. */ + if (!ok) + { + *h = 210 * (72000 / 25.4); + *v = 297 * (72000 / 25.4); + } + return ok; } /* If D is NULL, returns the first enabled driver if any, NULL if diff --git a/src/output/output.h b/src/output/output.h index 2338a0d8..2585aa8c 100644 --- a/src/output/output.h +++ b/src/output/output.h @@ -152,8 +152,8 @@ bool outp_parse_options (struct substring options, struct outp_driver *); int outp_match_keyword (const char *, const struct outp_option *, int *); -int outp_evaluate_dimension (char *, char **); -bool outp_get_paper_size (char *, int *h, int *v); +int outp_evaluate_dimension (const char *); +bool outp_get_paper_size (const char *, int *h, int *v); void outp_open_page (struct outp_driver *); void outp_close_page (struct outp_driver *); diff --git a/src/output/postscript.c b/src/output/postscript.c index 27d0404f..9a338070 100644 --- a/src/output/postscript.c +++ b/src/output/postscript.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2006, 2007 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 @@ -138,8 +138,7 @@ ps_open_driver (struct outp_driver *this, struct substring options) x->draw_headers = true; x->page_number = 0; x->portrait = true; - x->paper_width = PSUS * 17 / 2; - x->paper_length = PSUS * 11; + outp_get_paper_size ("", &x->paper_width, &x->paper_length); x->left_margin = PSUS / 2; x->right_margin = PSUS / 2; x->top_margin = PSUS / 2; @@ -380,14 +379,10 @@ handle_option (struct outp_driver *this, const char *key, break; case dimension_arg: { - int dimension = outp_evaluate_dimension (value, NULL); + int dimension = outp_evaluate_dimension (value); if (dimension <= 0) - { - error (0, 0, _("value for `%s' must be a dimension of positive " - "length (i.e., `1in')"), key); - break; - } + break; switch (subcat) { case 0: diff --git a/src/ui/terminal/ChangeLog b/src/ui/terminal/ChangeLog index 374bc52b..0e6e014d 100644 --- a/src/ui/terminal/ChangeLog +++ b/src/ui/terminal/ChangeLog @@ -1,3 +1,10 @@ +2007-09-22 Ben Pfaff + + Bug #21128. Reviewed by John Darrington. + + * main.c (i18_init): Set up LC_PAPER locale, if available. Don't + bother with LC_MONETARY locale, since we don't use it anywhere. + 2007-08-26 Ben Pfaff Bug #17238. Thanks to John Darrington for review. diff --git a/src/ui/terminal/main.c b/src/ui/terminal/main.c index 66fedf04..46ded354 100644 --- a/src/ui/terminal/main.c +++ b/src/ui/terminal/main.c @@ -150,7 +150,9 @@ i18n_init (void) #if HAVE_LC_MESSAGES setlocale (LC_MESSAGES, ""); #endif - setlocale (LC_MONETARY, ""); +#if HAVE_LC_PAPER + setlocale (LC_PAPER, ""); +#endif bindtextdomain (PACKAGE, locale_dir); textdomain (PACKAGE); #endif /* ENABLE_NLS */ diff --git a/tests/ChangeLog b/tests/ChangeLog index d5f95608..e91645ce 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,9 @@ +2007-09-22 Ben Pfaff + + Bug #21128. Reviewed by John Darrington. + + * output/paper-size.sh: New test. + 2007-09-21 Ben Pfaff * bugs/unwritable-dir.sh: New test for bug #21117. diff --git a/tests/automake.mk b/tests/automake.mk index 1b7a38ac..3ee837da 100644 --- a/tests/automake.mk +++ b/tests/automake.mk @@ -121,6 +121,7 @@ dist_TESTS = \ tests/bugs/temp-freq.sh \ tests/bugs/print-crash.sh \ tests/bugs/keep-all.sh \ + tests/output/paper-size.sh \ tests/xforms/recode.sh \ tests/stats/descript-basic.sh \ tests/stats/descript-missing.sh \ diff --git a/tests/output/paper-size.sh b/tests/output/paper-size.sh new file mode 100755 index 00000000..54739376 --- /dev/null +++ b/tests/output/paper-size.sh @@ -0,0 +1,96 @@ +#!/bin/sh + +# This program tests paper size support. + +TEMPDIR=/tmp/pspp-tst-$$ + +# ensure that top_builddir are absolute +if [ -z "$top_builddir" ] ; then top_builddir=. ; fi +if [ -z "$top_srcdir" ] ; then top_srcdir=. ; fi +top_builddir=`cd $top_builddir; pwd` +PSPP=$top_builddir/src/ui/terminal/pspp + +# ensure that top_srcdir is absolute +top_srcdir=`cd $top_srcdir; pwd` + +STAT_CONFIG_PATH=$top_srcdir/config +export STAT_CONFIG_PATH + +LANG=C +export LANG + +cleanup() +{ + cd / + rm -rf $TEMPDIR +} + + +fail() +{ + echo $activity + echo FAILED + cleanup; + exit 1; +} + + +no_result() +{ + echo $activity + echo NO RESULT; + cleanup; + exit 2; +} + +pass() +{ + cleanup; + exit 0; +} + +mkdir -p $TEMPDIR + +cd $TEMPDIR + +activity="Create File 1" +cat > paper-size.pspp < paper-size.out +if [ $? -ne 0 ] ; then no_result ; fi + +activity="compare results" +diff -b $TEMPDIR/paper-size.out - < 8.5 x 11.0 in, 216 x 279 mm +"a4" => 8.3 x 11.7 in, 210 x 297 mm +"letter" => 8.5 x 11.0 in, 216 x 279 mm +"10x14in" => 10.0 x 14.0 in, 254 x 356 mm +"210x297mm" => 8.3 x 11.7 in, 210 x 297 mm +EOF +if [ $? -ne 0 ] ; then fail ; fi + +activity="Create File 2" +cat > paper-size-2.pspp < paper-size-2.out +if [ $? -ne 0 ] ; then no_result ; fi + +activity="compare results 2" +diff -b $TEMPDIR/paper-size-2.out - < 8.3 x 11.7 in, 210 x 297 mm +EOF +if [ $? -ne 0 ] ; then fail ; fi + +pass; -- 2.30.2