* 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.
+2007-09-22 Ben Pfaff <blp@gnu.org>
+
+ Bug #21128. Reviewed by John Darrington.
+
+ * acinclude.m4 (PSPP_LC_PAPER): New macro.
+
+ * configure.ac: Use PSPP_LC_PAPER.
+
2007-08-05 Ben Pfaff <blp@gnu.org>
Bug #16189. Reviewed by Jason Stover.
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.
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.
\f
-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.
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 <locale.h>
+#include <langinfo.h>
+],
+ [(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
+2007-09-22 Ben Pfaff <blp@gnu.org>
+
+ Bug #21128. Reviewed by John Darrington.
+
+ * papersize: Removed.
+
+ * automake.mk (dist_pkgsysconf_DATA): Remove papersize.
+
2007-08-26 Ben Pfaff <blp@gnu.org>
* devices: Change raw-ascii from screen to listing device (because
dist_pkgsysconf_DATA = \
- config/devices \
- config/papersize
+ config/devices
psfontsdir = $(pkgsysconfdir)/psfonts
dist_psfonts_DATA = \
+++ /dev/null
-# 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:
AC_FUNC_FSEEKO
AC_CHECK_LIB(m, sin)
PSPP_LIBPLOT
+PSPP_LC_PAPER
AM_CONDITIONAL(WITHCHARTS, test x"$with_libplot" != x"no")
* 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
@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
@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}
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
+2007-09-22 Ben Pfaff <blp@gnu.org>
+
+ Bug #21128. Reviewed by John Darrington.
+
+ * command.def: Add DEBUG PAPER SIZE command.
+
2007-09-05 John Darrington <john@darrington.wattle.id.au>
* 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 <blp@gnu.org>
* command.def: Add DEBUG DATASHEET command. Remove DEBUG CASEFILE
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)
+2007-09-22 Ben Pfaff <blp@gnu.org>
+
+ Bug #21128. Reviewed by John Darrington.
+
+ * automake.mk: Add new file.
+
+ * paper-size.c: New file.
+
2007-06-06 Ben Pfaff <blp@gnu.org>
* automake.mk: Add new file.
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)
--- /dev/null
+/* 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#include <stdio.h>
+
+#include <language/command.h>
+#include <language/lexer/lexer.h>
+#include <libpspp/assertion.h>
+#include <output/output.h>
+
+/* 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);
+}
+2007-09-22 Ben Pfaff <blp@gnu.org>
+
+ 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 <blp@gnu.org>
* ascii.c (struct ascii_driver_ext): New member reported_error.
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
-#include "output.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
+
#include <ctype.h>
-#include <libpspp/alloc.h>
+#include <errno.h>
+#include <langinfo.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+
#include <data/file-name.h>
-#include "htmlP.h"
-#include "intprops.h"
-#include <libpspp/misc.h>
#include <data/settings.h>
+#include <libpspp/alloc.h>
+#include <libpspp/misc.h>
#include <libpspp/str.h>
+#include <output/htmlP.h>
+#include <output/output.h>
+
#include "error.h"
+#include "intprops.h"
#include "gettext.h"
#define _(msgid) gettext (msgid)
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
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 *);
/* 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
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;
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:
+2007-09-22 Ben Pfaff <blp@gnu.org>
+
+ 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 <blp@gnu.org>
Bug #17238. Thanks to John Darrington for review.
#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 */
+2007-09-22 Ben Pfaff <blp@gnu.org>
+
+ Bug #21128. Reviewed by John Darrington.
+
+ * output/paper-size.sh: New test.
+
2007-09-21 Ben Pfaff <blp@gnu.org>
* bugs/unwritable-dir.sh: New test for bug #21117.
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 \
--- /dev/null
+#!/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 <<EOF
+debug paper size ''.
+debug paper size 'a4'.
+debug paper size 'letter'.
+debug paper size '10x14in'.
+debug paper size '210x297mm'.
+EOF
+if [ $? -ne 0 ] ; then no_result ; fi
+
+activity="Run pspp 1"
+PAPERSIZE=letter $SUPERVISOR $PSPP --testing-mode paper-size.pspp > paper-size.out
+if [ $? -ne 0 ] ; then no_result ; fi
+
+activity="compare results"
+diff -b $TEMPDIR/paper-size.out - <<EOF
+"" => 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 <<EOF
+debug paper size ''.
+EOF
+if [ $? -ne 0 ] ; then no_result ; fi
+
+activity="Run pspp 2"
+PAPERSIZE=a4 $SUPERVISOR $PSPP --testing-mode 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 - <<EOF
+"" => 8.3 x 11.7 in, 210 x 297 mm
+EOF
+if [ $? -ne 0 ] ; then fail ; fi
+
+pass;