Bug #21128. Reviewed by John Darrington.
authorBen Pfaff <blp@gnu.org>
Sun, 23 Sep 2007 05:59:01 +0000 (05:59 +0000)
committerBen Pfaff <blp@gnu.org>
Sun, 23 Sep 2007 05:59:01 +0000 (05:59 +0000)
* 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.

22 files changed:
ChangeLog
NEWS
acinclude.m4
config/ChangeLog
config/automake.mk
config/papersize [deleted file]
configure.ac
doc/configuring.texi
src/language/ChangeLog
src/language/command.def
src/language/tests/ChangeLog
src/language/tests/automake.mk
src/language/tests/paper-size.c [new file with mode: 0644]
src/output/ChangeLog
src/output/output.c
src/output/output.h
src/output/postscript.c
src/ui/terminal/ChangeLog
src/ui/terminal/main.c
tests/ChangeLog
tests/automake.mk
tests/output/paper-size.sh [new file with mode: 0755]

index b117867f7f790babbb501a46c26894b62a403869..8fd7bc7dc6e705948f76d90a2fe333495029a390 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+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.
 2007-08-05  Ben Pfaff  <blp@gnu.org>
 
        Bug #16189.  Reviewed by Jason Stover.
diff --git a/NEWS b/NEWS
index 8e65aa793d99f08fd4a44fe1cf7d47f662cb4862..2ba38211abe5130fb51dfa68a26a3acc22975674 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,5 @@
 PSPP NEWS -- history of user-visible changes.
 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.
 
 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.
 
   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
   For developers, the build system now requires Autoconf 2.60 and
   Automake 1.10.
 \f
index 4201e22b58c67012d73ece9280e538e35a8b79bb..61290a1802158861f1fbb736838f2c20a6e4690d 100644 (file)
@@ -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.
 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)])
 
 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
index 93c9e809675aa696b5e1be4c606f82a57cb8957d..27cb2b33268fd8025750993bf763ac2acfd031f1 100644 (file)
@@ -1,3 +1,11 @@
+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
 2007-08-26  Ben Pfaff  <blp@gnu.org>
 
        * devices: Change raw-ascii from screen to listing device (because
index fa493d525498ab2ef9a9a34f0e92ccf71d4afeb7..ba01a397f3809bde328cc03786a8010cf768b37b 100644 (file)
@@ -2,8 +2,7 @@
 
 
 dist_pkgsysconf_DATA = \
 
 
 dist_pkgsysconf_DATA = \
-       config/devices \
-       config/papersize
+       config/devices
 
 psfontsdir = $(pkgsysconfdir)/psfonts
 dist_psfonts_DATA = \
 
 psfontsdir = $(pkgsysconfdir)/psfonts
 dist_psfonts_DATA = \
diff --git a/config/papersize b/config/papersize
deleted file mode 100644 (file)
index f3866ed..0000000
+++ /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:
index cb5b4c58f814f4a3d879f7fc142e4e8bb12694ec..ea4cef37de95ff553251123c8245a2b24572d847 100644 (file)
@@ -30,6 +30,7 @@ AC_SYS_LARGEFILE
 AC_FUNC_FSEEKO
 AC_CHECK_LIB(m, sin)
 PSPP_LIBPLOT
 AC_FUNC_FSEEKO
 AC_CHECK_LIB(m, sin)
 PSPP_LIBPLOT
+PSPP_LC_PAPER
 AM_CONDITIONAL(WITHCHARTS, test x"$with_libplot" != x"no")
 
 
 AM_CONDITIONAL(WITHCHARTS, test x"$with_libplot" != x"no")
 
 
index c299d9c83795b24a4ec0349906d5510d5e4dcffd..18d24cac45a498518895d17945aacb3702780d2c 100644 (file)
@@ -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{}
 * 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
 * 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
 
 @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
 
 @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}
 
 
 @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}
 
 
 @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}.
 
 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
 
 @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
 
 
 @item TMPDIR
 
index d25c2d0379b7210e1d71fcff6453ff465894161f..840278b2b04654734f816b527bc84b5d68e4a76e 100644 (file)
@@ -1,10 +1,15 @@
+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-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
 2007-06-06  Ben Pfaff  <blp@gnu.org>
 
        * command.def: Add DEBUG DATASHEET command.  Remove DEBUG CASEFILE
index 7a89ae0a1631cab8384a82c7911b772ea6b74143..f77bd6920acd7d9a717b2596f2472344a14ce09e 100644 (file)
@@ -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 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)
 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)
index 295c5418392699daf026e5ebb60f0fd26e263570..565064522ff9e7967451a3ccf913e65543378f7f 100644 (file)
@@ -1,3 +1,11 @@
+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.
 2007-06-06  Ben Pfaff  <blp@gnu.org>
 
        * automake.mk: Add new file.
index bbcd777b3ebeec54c6b0cece014015a6100b3388..49c71da1bc89f1fa5b9babed06e50448421209dd 100644 (file)
@@ -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/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)
 
        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 (file)
index 0000000..d8c49a5
--- /dev/null
@@ -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 <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);
+}
index f7ce7b5c841eb622ee3ebe8b33fd9d5e9c2f21cb..adabbcde32e077796e704b26296eb68ac8332ff1 100644 (file)
@@ -1,3 +1,23 @@
+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.
 2007-09-21  Ben Pfaff  <blp@gnu.org>
 
        * ascii.c (struct ascii_driver_ext): New member reported_error.
index 5a24d89547a8ea054eb5dd3b5721a7dca761fe0b..842e1c15c63bc383219c4a5de027883b2c086aff 100644 (file)
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
 #include <config.h>
    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 <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 <data/file-name.h>
-#include "htmlP.h"
-#include "intprops.h"
-#include <libpspp/misc.h>
 #include <data/settings.h>
 #include <data/settings.h>
+#include <libpspp/alloc.h>
+#include <libpspp/misc.h>
 #include <libpspp/str.h>
 #include <libpspp/str.h>
+#include <output/htmlP.h>
+#include <output/output.h>
+
 #include "error.h"
 #include "error.h"
+#include "intprops.h"
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
 
 #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;
 }
 
   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;
       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
   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
 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;
 
   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;
     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;
 }
 
   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 (;;)
     {
     }
 
   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;
        }
 
          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
 }
 
 /* If D is NULL, returns the first enabled driver if any, NULL if
index 2338a0d87bf64e761023a49772f99a3d89ac7fd9..2585aa8cbf346783d02557d596db5757e8d4339a 100644 (file)
@@ -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 *);
 
                          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 *);
 
 void outp_open_page (struct outp_driver *);
 void outp_close_page (struct outp_driver *);
index 27d0404f8166fb8996677882a9743e6b7e0d86de..9a33807096bcd092c03380683384443f005ad133 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
 /* 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
 
    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->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;
   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:
       {
       break;
     case dimension_arg:
       {
-       int dimension = outp_evaluate_dimension (value, NULL);
+       int dimension = outp_evaluate_dimension (value);
 
        if (dimension <= 0)
 
        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:
        switch (subcat)
          {
          case 0:
index 374bc52bf5cd59945539d5e6cfaa9dbe807f9491..0e6e014d9b49b9c6f5c186ec442a67813e0a9d78 100644 (file)
@@ -1,3 +1,10 @@
+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.
 2007-08-26  Ben Pfaff  <blp@gnu.org>
 
        Bug #17238.  Thanks to John Darrington for review.
index 66fedf04fd900d9c97427f023b7583ab334b1035..46ded354f7e392903c61d93712d0ad8baff38610 100644 (file)
@@ -150,7 +150,9 @@ i18n_init (void)
 #if HAVE_LC_MESSAGES
   setlocale (LC_MESSAGES, "");
 #endif
 #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 */
   bindtextdomain (PACKAGE, locale_dir);
   textdomain (PACKAGE);
 #endif /* ENABLE_NLS */
index d5f95608c5dd861bc45b9a3163ba35d08e5e3324..e91645ce4c14434d050932a4eb6023362d9603c4 100644 (file)
@@ -1,3 +1,9 @@
+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.
 2007-09-21  Ben Pfaff  <blp@gnu.org>
 
        * bugs/unwritable-dir.sh: New test for bug #21117.
index 1b7a38ac8fbed0cd0ff5d8fae26878f75cdb19b7..3ee837dab621d7bbaceb50db9267c657a146f0e6 100644 (file)
@@ -121,6 +121,7 @@ dist_TESTS = \
        tests/bugs/temp-freq.sh \
        tests/bugs/print-crash.sh \
        tests/bugs/keep-all.sh \
        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 \
        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 (executable)
index 0000000..5473937
--- /dev/null
@@ -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 <<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;